diff --git a/README.md b/README.md index 46341139d..64ec4090a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![logo](https://raw.githubusercontent.com/648540858/wvp-GB28181-pro/wvp-28181-2.0/web_src/static/logo.png) +![logo](doc/_media/logo.png) # 开箱即用的28181协议视频平台 [![Build Status](https://travis-ci.org/xia-chu/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xia-chu/ZLMediaKit) @@ -17,7 +17,7 @@ WEB VIDEO PLATFORM是一个基于GB28181-2016标准实现的开箱即用的网 # 应用场景: 支持浏览器无插件播放摄像头视频。 支持摄像机、平台、NVR等设备接入。 -支持国标级联。 +支持国标级联。多平台级联。跨网视频预览。 支持rtsp/rtmp等视频流转发到国标平台。 支持rtsp/rtmp等推流转发到国标平台。 @@ -31,62 +31,49 @@ WEB VIDEO PLATFORM是一个基于GB28181-2016标准实现的开箱即用的网 https://gitee.com/pan648540858/wvp-GB28181-pro.git # 截图 -![build_1.png](https://images.gitee.com/uploads/images/2022/0304/101513_79632720_1018729.png "2022-03-04_09-51.png") -![build_1.png](https://images.gitee.com/uploads/images/2022/0304/103025_5df016f9_1018729.png "2022-03-04_10-27.png") -![build_1.png](https://images.gitee.com/uploads/images/2022/0304/101706_088fbafa_1018729.png "2022-03-04_09-52_1.png") -![build_1.png](https://images.gitee.com/uploads/images/2022/0304/101756_3d662828_1018729.png "2022-03-04_10-00_1.png") -![build_1.png](https://images.gitee.com/uploads/images/2022/0304/101823_19050c66_1018729.png "2022-03-04_10-12_1.png") -![build_1.png](https://images.gitee.com/uploads/images/2022/0304/101848_e5a39557_1018729.png "2022-03-04_10-12_2.png") -![build_1.png](https://images.gitee.com/uploads/images/2022/0304/101919_ee5b8c79_1018729.png "2022-03-04_10-13.png") +![index](doc/_media/index.png "index.png") +![2](doc/_media/2.png "2.png") +![3](doc/_media/3.png "3.png") +![3-1](doc/_media/3-1.png "3-1.png") +![3-2](doc/_media/3-2.png "3-2.png") +![3-3](doc/_media/3-3.png "3-3.png") +![build_1](https://images.gitee.com/uploads/images/2022/0304/101919_ee5b8c79_1018729.png "2022-03-04_10-13.png") -# 1.0 基础特性 -1. 视频预览; -2. 云台控制(方向、缩放控制); -3. 视频设备信息同步; -4. 离在线监控; -5. 录像查询与回放(基于NVR\DVR,暂不支持快进、seek操作); -6. 无人观看自动断流; -7. 支持UDP和TCP两种国标信令传输模式; -8. 集成web界面, 不需要单独部署前端服务, 直接利用wvp内置文件服务部署, 随wvp一起部署; -9. 支持平台接入, 针对大平台大量设备的情况进行优化; -10. 支持检索,通道筛选; -11. 支持自动配置ZLM媒体服务, 减少因配置问题所出现的问题; -12. 支持启用udp多端口模式, 提高udp模式下媒体传输性能; -13. 支持通道是否含有音频的设置; -14. 支持通道子目录查询; -15. 支持udp/tcp国标流传输模式; -16. 支持直接输出RTSP、RTMP、HTTP-FLV、Websocket-FLV、HLS多种协议流地址 -17. 支持国标网络校时 -18. 支持公网部署, 支持wvp与zlm分开部署 -19. 支持播放h265, g.711格式的流(需要将closeWaitRTPInfo设为false) -20. 报警信息处理,支持向前端推送报警信息 - -# 1.0 新支持特性 -1. 集成web界面, 不需要单独部署前端服务, 直接利用wvp内置文件服务部署, 随wvp一起部署; -2. 支持平台接入, 针对大平台大量设备的情况进行优化; -3. 支持检索,通道筛选; -4. 支持自动配置ZLM媒体服务, 减少因配置问题所出现的问题; -5. 支持启用udp多端口模式, 提高udp模式下媒体传输性能; -6. 支持通道是否含有音频的设置; -7. 支持通道子目录查询; -8. 支持udp/tcp国标流传输模式; -9. 支持直接输出RTSP、RTMP、HTTP-FLV、Websocket-FLV、HLS多种协议流地址 -10. 支持国标网络校时 -11. 支持公网部署, 支持wvp与zlm分开部署 -12. 支持播放h265, g.711格式的流 -13. 支持固定流地址和自动点播,同时支持未点播时直接播放流地址,代码自动发起点播. ( [查看WIKI](https://github.com/648540858/wvp-GB28181-pro/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E5%9B%BA%E5%AE%9A%E6%92%AD%E6%94%BE%E5%9C%B0%E5%9D%80%E4%B8%8E%E8%87%AA%E5%8A%A8%E7%82%B9%E6%92%AD)) -14. 报警信息处理,支持向前端推送报警信息 -15. 支持订阅与通知方法 - - [X] 移动位置订阅 - - [X] 移动位置通知处理 - - [X] 报警事件订阅 - - [X] 报警事件通知处理 - - [X] 设备目录订阅 - - [X] 设备目录通知处理 -16. 移动位置查询和显示,可通过配置文件设置移动位置历史是否存储 - -# 2.0 支持特性 -- [X] 国标通道向上级联 +# 功能特性 +- [X] 集成web界面 +- [X] 兼容性良好 +- [X] 支持电子地图,支持接入WGS84和GCJ02两种坐标系,并且自动转化为合适的坐标系进行展示和分发 +- [X] 接入设备 + - [X] 视频预览 + - [X] 无限制接入路数,能接入多少设备只取决于你的服务器性能 + - [X] 云台控制,控制设备转向,拉近,拉远 + - [X] 预置位查询,使用与设置 + - [X] 查询NVR/IPC上的录像与播放,支持指定时间播放与下载 + - [X] 无人观看自动断流,节省流量 + - [X] 视频设备信息同步 + - [X] 离在线监控 + - [X] 支持直接输出RTSP、RTMP、HTTP-FLV、Websocket-FLV、HLS多种协议流地址 + - [X] 支持通过一个流地址直接观看摄像头,无需登录以及调用任何接口 + - [X] 支持UDP和TCP两种国标信令传输模式 + - [X] 支持UDP和TCP两种国标流传输模式 + - [X] 支持检索,通道筛选 + - [X] 支持通道子目录查询 + - [X] 支持过滤音频,防止杂音影响观看 + - [X] 支持国标网络校时 + - [X] 支持播放H264和H265 + - [X] 报警信息处理,支持向前端推送报警信息 + - [X] 支持订阅与通知方法 + - [X] 移动位置订阅 + - [X] 移动位置通知处理 + - [X] 报警事件订阅 + - [X] 报警事件通知处理 + - [X] 设备目录订阅 + - [X] 设备目录通知处理 + - [X] 移动位置查询和显示 + - [X] 支持手动添加设备和给设备设置单独的密码 +- [X] 支持平台对接接入 +- [X] 支持国标级联 + - [X] 国标通道向上级联 - [X] WEB添加上级平台 - [X] 注册 - [X] 心跳保活 @@ -101,61 +88,33 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git - [X] 目录订阅与通知 - [X] 录像查看与播放 - [X] GPS订阅与通知(直播推流) -- [X] 支持手动添加设备和给设备设置单独的密码 -- [X] 添加RTSP视频 -- [X] 添加接口鉴权 -- [X] 添加RTMP视频 -- [X] 云端录像(需要部署单独服务配合使用) +- [X] 支持自动配置ZLM媒体服务, 减少因配置问题所出现的问题; - [X] 多流媒体节点,自动选择负载最低的节点使用。 -- [X] WEB端支持播放H264与H265,音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。 -- [X] 支持电子地图。 -- [X] 支持接入WGS84和GCJ02两种坐标系。 +- [X] 支持启用udp多端口模式, 提高udp模式下媒体传输性能; +- [X] 支持公网部署; +- [X] 支持wvp与zlm分开部署,提升平台并发能力 +- [X] 支持拉流RTSP/RTMP,分发为各种流格式,或者推送到其他国标平台 +- [X] 支持推流RTSP/RTMP,分发为各种流格式,或者推送到其他国标平台 +- [X] 支持推流鉴权 +- [X] 支持接口鉴权 +- [X] 云端录像,推流/代理/国标视频均可以录制在云端服务器,支持预览和下载 + -[//]: # (# docker快速体验) - -[//]: # (目前作者的docker-compose因为时间有限维护不及时,这里提供第三方提供的供大家使用,维护不易,大家记得给这位小伙伴点个star。 ) - -[//]: # (https://github.com/SaltFish001/wvp_pro_compose) - -[//]: # ([https://github.com/SaltFish001/wvp_pro_compose](https://github.com/SaltFish001/wvp_pro_compose)) - -[//]: # (这是作者维护的一个镜像,可能存在不及时的问题。) - -[//]: # (```shell) - -[//]: # (docker pull 648540858/wvp_pro) - -[//]: # () -[//]: # (docker run --env WVP_IP="你的IP" -it -p 18080:18080 -p 30000-30500:30000-30500/udp -p 30000-30500:30000-30500/tcp -p 80:80 -p 5060:5060 -p 5060:5060/udp 648540858/wvp_pro) - -[//]: # (```) - -[//]: # (docker使用详情查看:[https://hub.docker.com/r/648540858/wvp_pro](https://hub.docker.com/r/648540858/wvp_pro)) - -# gitee同步仓库 -https://gitee.com/pan648540858/wvp-GB28181-pro.git - -# 遇到问题 +# 遇到问题如何解决 国标最麻烦的地方在于设备的兼容性,所以需要大量的设备来测试,目前作者手里的设备有限,再加上作者水平有限,所以遇到问题在所难免; 1. 查看wiki,仔细的阅读可以帮你避免几乎所有的问题 2. 搜索issues,这里有大部分的答案 -3. 加QQ群,这里有大量热心的小伙伴,但是前提新希望你已经仔细阅读了wiki和搜索了issues。 +3. 加QQ群(901799015),这里有大量热心的小伙伴,但是前提新希望你已经仔细阅读了wiki和搜索了issues。 4. 你可以请作者为你解答,但是我不是免费的。 5. 你可以把遇到问题的设备寄给我,可以更容易的复现问题。 - -# 合作 -目前很多打着合作的幌子来私聊的,其实大家大可不必,目前作者没有精力,你有问题可以付费找我解答,也可以提PR -,如果对代码有建议可以提ISSUE;也可以加群一起聊聊。我们欢迎所有有兴趣参与到项目中来的人。 - - - # 使用帮助 QQ群: 901799015, ZLM使用文档[https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit) QQ私信一般不回, 精力有限.欢迎大家在群里讨论.觉得项目对你有帮助,欢迎star和提交pr。 # 授权协议 本项目自有代码使用宽松的MIT协议,在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。 但是本项目也零碎的使用了一些其他的开源代码,在商用的情况下请自行替代或剔除; 由于使用本项目而产生的商业纠纷或侵权行为一概与本项目及开发者无关,请自行承担法律风险。 在使用本项目代码时,也应该在授权协议中同时表明本项目依赖的第三方库的协议 + # 致谢 感谢作者[夏楚](https://github.com/xia-chu) 提供这么棒的开源流媒体服务框架,并在开发过程中给予支持与帮助。 感谢作者[dexter langhuihui](https://github.com/langhuihui) 开源这么好用的WEB播放器。 diff --git a/doc/_media/2.png b/doc/_media/2.png new file mode 100644 index 000000000..dd982e1e5 Binary files /dev/null and b/doc/_media/2.png differ diff --git a/doc/_media/3-1.png b/doc/_media/3-1.png new file mode 100644 index 000000000..a52620f2f Binary files /dev/null and b/doc/_media/3-1.png differ diff --git a/doc/_media/3-2.png b/doc/_media/3-2.png new file mode 100644 index 000000000..bef780eb2 Binary files /dev/null and b/doc/_media/3-2.png differ diff --git a/doc/_media/3-3.png b/doc/_media/3-3.png new file mode 100644 index 000000000..3943a5277 Binary files /dev/null and b/doc/_media/3-3.png differ diff --git a/doc/_media/3.png b/doc/_media/3.png new file mode 100644 index 000000000..913d29490 Binary files /dev/null and b/doc/_media/3.png differ diff --git a/doc/_media/index.png b/doc/_media/index.png new file mode 100644 index 000000000..15200e69b Binary files /dev/null and b/doc/_media/index.png differ diff --git a/pom.xml b/pom.xml index 7ed030440..efc311a19 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ com.genersoft wvp-pro - 2.6.6 + 2.6.7 web video platform 国标28181视频平台 diff --git a/sql/mysql.sql b/sql/mysql.sql index 27c6da103..d9010e2d0 100644 --- a/sql/mysql.sql +++ b/sql/mysql.sql @@ -54,7 +54,7 @@ CREATE TABLE `device` ( `localIp` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `device_deviceId_uindex` (`deviceId`) -) ENGINE=InnoDB AUTO_INCREMENT=57 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -86,7 +86,7 @@ CREATE TABLE `device_alarm` ( `alarmType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -146,7 +146,7 @@ CREATE TABLE `device_channel` ( PRIMARY KEY (`id`), UNIQUE KEY `device_channel_id_uindex` (`id`), UNIQUE KEY `device_channel_pk` (`channelId`,`deviceId`) -) ENGINE=InnoDB AUTO_INCREMENT=74416 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -183,7 +183,7 @@ CREATE TABLE `device_mobile_position` ( `latitudeWgs84` double DEFAULT NULL, `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=55589 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -216,7 +216,7 @@ CREATE TABLE `gb_stream` ( PRIMARY KEY (`gbStreamId`) USING BTREE, UNIQUE KEY `app` (`app`,`stream`) USING BTREE, UNIQUE KEY `gbId` (`gbId`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=331060 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -246,7 +246,7 @@ CREATE TABLE `log` ( `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=760908 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -338,7 +338,7 @@ CREATE TABLE `parent_platform` ( PRIMARY KEY (`id`), UNIQUE KEY `parent_platform_id_uindex` (`id`), UNIQUE KEY `parent_platform_pk` (`serverGBId`) -) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -390,7 +390,7 @@ CREATE TABLE `platform_gb_channel` ( `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `deviceChannelId` int NOT NULL, PRIMARY KEY (`id`) -) ENGINE=InnoDB AUTO_INCREMENT=3146 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -410,13 +410,13 @@ DROP TABLE IF EXISTS `platform_gb_stream`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!50503 SET character_set_client = utf8mb4 */; CREATE TABLE `platform_gb_stream` ( + `id` int NOT NULL AUTO_INCREMENT, `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `gbStreamId` int NOT NULL, - `id` int NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`), UNIQUE KEY `platform_gb_stream_pk` (`platformId`,`catalogId`,`gbStreamId`) -) ENGINE=InnoDB AUTO_INCREMENT=391772 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -458,7 +458,7 @@ CREATE TABLE `stream_proxy` ( `enable_disable_none_reader` bit(1) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `stream_proxy_pk` (`app`,`stream`) -) ENGINE=InnoDB AUTO_INCREMENT=568 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -495,7 +495,7 @@ CREATE TABLE `stream_push` ( `self` int DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `stream_push_pk` (`app`,`stream`) -) ENGINE=InnoDB AUTO_INCREMENT=361492 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -524,7 +524,7 @@ CREATE TABLE `user` ( `pushKey` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, UNIQUE KEY `user_username_uindex` (`username`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -533,7 +533,7 @@ CREATE TABLE `user` ( LOCK TABLES `user` WRITE; /*!40000 ALTER TABLE `user` DISABLE KEYS */; -INSERT INTO `user` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021 - 04 - 13 14:14:57','2021 - 04 - 13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3'); +INSERT INTO `user` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3'); /*!40000 ALTER TABLE `user` ENABLE KEYS */; UNLOCK TABLES; @@ -551,7 +551,7 @@ CREATE TABLE `user_role` ( `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; /*!40101 SET character_set_client = @saved_cs_client */; -- diff --git a/sql/update.sql b/sql/update.sql index 877e24779..2e5d5691b 100644 --- a/sql/update.sql +++ b/sql/update.sql @@ -1,43 +1,3 @@ -alter table media_server - drop column streamNoneReaderDelayMS; - -alter table media_server - drop column sendRtpPortRange; - -alter table stream_proxy - add enable_disable_none_reader bit(1) default null; - +-- 2.6.6->2.6.7 alter table device - add mediaServerId varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'auto'; - -alter table device - add custom_name varchar(255) default null; - -alter table device - add sdpIp varchar(50) default null; - -alter table device - add localIp varchar(50) default null; - -alter table device - add password varchar(255) default null; - -alter table device - modify ip varchar(50) null; - -alter table device - modify port int null; - -alter table device - modify expires int null; - -alter table device - modify subscribeCycleForCatalog int null; - -alter table device - modify hostAddress varchar(50) null; - -alter table stream_proxy - change enable_hls enable_audio bit null; - - + add keepaliveIntervalTime int default null; \ No newline at end of file diff --git a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java index 3db903bba..45cd57be9 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java +++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java @@ -71,6 +71,8 @@ public class VideoManagerConstants { public static final String SYSTEM_INFO_DISK_PREFIX = "VMP_SYSTEM_INFO_DISK_"; public static final String BROADCAST_WAITE_INVITE = "task_broadcast_waite_invite_"; + public static final String REGISTER_EXPIRE_TASK_KEY_PREFIX = "VMP_device_register_expire_"; + diff --git a/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java b/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java index 5f4ac22e8..d1e61c0a3 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java @@ -10,6 +10,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; +import org.springframework.util.ObjectUtils; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.*; @@ -51,6 +52,9 @@ public class ApiAccessFilter extends OncePerRequestFilter { LogDto logDto = new LogDto(); logDto.setName(uriName); + if (ObjectUtils.isEmpty(username)) { + username = ""; + } logDto.setUsername(username); logDto.setAddress(servletRequest.getRemoteAddr()); logDto.setResult(HttpStatus.valueOf(servletResponse.getStatus()).toString()); diff --git a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java index 57f324518..83eace595 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java @@ -35,6 +35,8 @@ public class UserSetting { private Boolean useSourceIpAsStreamIp = Boolean.FALSE; + private Boolean sipUseSourceIpAsRemoteAddress = Boolean.FALSE; + private Boolean streamOnDemand = Boolean.TRUE; private Boolean pushAuthority = Boolean.TRUE; @@ -45,6 +47,8 @@ public class UserSetting { private Boolean pushStreamAfterAck = Boolean.FALSE; + private Boolean sipLog = Boolean.FALSE; + private String serverId = "000000"; private String thirdPartyGBIdReg = "[\\s\\S]*"; @@ -206,4 +210,20 @@ public class UserSetting { public void setPushStreamAfterAck(Boolean pushStreamAfterAck) { this.pushStreamAfterAck = pushStreamAfterAck; } + + public Boolean getSipUseSourceIpAsRemoteAddress() { + return sipUseSourceIpAsRemoteAddress; + } + + public void setSipUseSourceIpAsRemoteAddress(Boolean sipUseSourceIpAsRemoteAddress) { + this.sipUseSourceIpAsRemoteAddress = sipUseSourceIpAsRemoteAddress; + } + + public Boolean getSipLog() { + return sipLog; + } + + public void setSipLog(Boolean sipLog) { + this.sipLog = sipLog; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java index 24b88e55a..605e7cf57 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.gb28181; import com.genersoft.iot.vmp.conf.SipConfig; +import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties; import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver; import gov.nist.javax.sip.SipProviderImpl; @@ -29,6 +30,9 @@ public class SipLayer implements CommandLineRunner { @Autowired private ISIPProcessorObserver sipProcessorObserver; + @Autowired + private UserSetting userSetting; + private final Map tcpSipProviderMap = new ConcurrentHashMap<>(); private final Map udpSipProviderMap = new ConcurrentHashMap<>(); @@ -61,7 +65,7 @@ public class SipLayer implements CommandLineRunner { private void addListeningPoint(String monitorIp, int port){ SipStackImpl sipStack; try { - sipStack = (SipStackImpl)sipFactory.createSipStack(DefaultProperties.getProperties(monitorIp, false)); + sipStack = (SipStackImpl)sipFactory.createSipStack(DefaultProperties.getProperties(monitorIp, false, userSetting.getSipLog())); } catch (PeerUnavailableException e) { logger.error("[Sip Server] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp); return; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java index 280d35acd..99b46a108 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java @@ -94,6 +94,13 @@ public class Device { @Schema(description = "心跳时间") private String keepaliveTime; + + /** + * 心跳间隔 + */ + @Schema(description = "心跳间隔") + private int keepaliveIntervalTime; + /** * 通道个数 */ @@ -414,4 +421,12 @@ public class Device { public void setLocalIp(String localIp) { this.localIp = localIp; } + + public int getKeepaliveIntervalTime() { + return keepaliveIntervalTime; + } + + public void setKeepaliveIntervalTime(int keepaliveIntervalTime) { + this.keepaliveIntervalTime = keepaliveIntervalTime; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RemoteAddressInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RemoteAddressInfo.java new file mode 100644 index 000000000..4107593fe --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RemoteAddressInfo.java @@ -0,0 +1,27 @@ +package com.genersoft.iot.vmp.gb28181.bean; + +public class RemoteAddressInfo { + private String ip; + private int port; + + public RemoteAddressInfo(String ip, int port) { + this.ip = ip; + this.port = port; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java index e0691e5da..3cdf48dc7 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java @@ -1,5 +1,9 @@ package com.genersoft.iot.vmp.gb28181.conf; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd.AlarmNotifyMessageHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.Properties; /** @@ -8,10 +12,11 @@ import java.util.Properties; */ public class DefaultProperties { - public static Properties getProperties(String ip, boolean isDebug) { + public static Properties getProperties(String ip, boolean isDebug, boolean sipLog) { Properties properties = new Properties(); properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); properties.setProperty("javax.sip.IP_ADDRESS", ip); + // 关闭自动会话 properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); /** * 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码 @@ -26,7 +31,7 @@ public class DefaultProperties { // 接收所有notify请求,即使没有订阅 properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true"); properties.setProperty("gov.nist.javax.sip.AUTOMATIC_DIALOG_ERROR_HANDLING", "false"); - properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "false"); + properties.setProperty("gov.nist.javax.sip.CANCEL_CLIENT_TRANSACTION_CHECKED", "true"); // 为_NULL _对话框传递_终止的_事件 properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true"); // 会话清理策略 @@ -35,11 +40,38 @@ public class DefaultProperties { properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60"); // 获取实际内容长度,不使用header中的长度信息 properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true"); + // 线程可重入 + properties.setProperty("gov.nist.javax.sip.REENTRANT_LISTENER", "true"); + // 定义应用程序打算多久审计一次 SIP 堆栈,了解其内部线程的健康状况(该属性指定连续审计之间的时间(以毫秒为单位)) + properties.setProperty("gov.nist.javax.sip.THREAD_AUDIT_INTERVAL_IN_MILLISECS", "30000"); /** * sip_server_log.log 和 sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE */ - properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR"); + Logger logger = LoggerFactory.getLogger(AlarmNotifyMessageHandler.class); + if (sipLog) { + if (logger.isDebugEnabled()) { + System.out.println("DEBUG"); + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "DEBUG"); + }else if (logger.isInfoEnabled()) { + System.out.println("INFO1"); + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "INFO"); + }else if (logger.isWarnEnabled()) { + System.out.println("WARNING"); + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "WARNING"); + }else if (logger.isErrorEnabled()) { + System.out.println("ERROR"); + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "ERROR"); + }else { + System.out.println("INFO2"); + properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "INFO"); + } + logger.info("[SIP日志]级别为: {}", properties.getProperty("gov.nist.javax.sip.TRACE_LEVEL")); + }else { + logger.info("[SIP日志]已关闭"); + } + + return properties; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/SipLoggerPass.java b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/SipLoggerPass.java deleted file mode 100644 index 18dd1519a..000000000 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/SipLoggerPass.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.genersoft.iot.vmp.gb28181.conf; - -import gov.nist.core.StackLogger; - -import java.util.Properties; - -/** - * sip日志格式化 - * 暂不使用 - */ -public class SipLoggerPass implements StackLogger { - - @Override - public void logStackTrace() { - - } - - @Override - public void logStackTrace(int traceLevel) { - - } - - @Override - public int getLineCount() { - return 0; - } - - @Override - public void logException(Throwable ex) { - - } - - @Override - public void logDebug(String message) { - - } - - @Override - public void logDebug(String message, Exception ex) { - - } - - @Override - public void logTrace(String message) { - - } - - @Override - public void logFatalError(String message) { - - } - - @Override - public void logError(String message) { - - } - - @Override - public boolean isLoggingEnabled() { - return false; - } - - @Override - public boolean isLoggingEnabled(int logLevel) { - return false; - } - - @Override - public void logError(String message, Exception ex) { - - } - - @Override - public void logWarning(String string) { - - } - - @Override - public void logInfo(String string) { - - } - - @Override - public void disableLogging() { - - } - - @Override - public void enableLogging() { - - } - - @Override - public void setBuildTimeStamp(String buildTimeStamp) { - - } - - @Override - public void setStackProperties(Properties stackProperties) { - - } - - @Override - public String getLoggerName() { - return null; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java index e2cd84fc5..ea2760d55 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java @@ -13,7 +13,7 @@ import org.springframework.util.ObjectUtils; import java.util.ArrayList; import java.util.List; -/** +/** * @description:视频流session管理器,管理视频预览、预览回放的通信句柄 * @author: swwheihei * @date: 2020年5月13日 下午4:03:02 @@ -51,6 +51,7 @@ public class VideoStreamSessionManager { ssrcTransaction.setSsrc(ssrc); ssrcTransaction.setMediaServerId(mediaServerId); ssrcTransaction.setType(type); + RedisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java index 13a36d7b0..0d6da6453 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java @@ -64,7 +64,7 @@ public interface ISIPCommanderForPlatform { * @param fromTag * @return */ - void deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException; + void deviceStatusResponse(ParentPlatform parentPlatform,String channelId, String sn, String fromTag,int status) throws SipException, InvalidArgumentException, ParseException; /** * 向上级回复移动位置订阅消息 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java index 3181ee21d..729f9b871 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java @@ -574,10 +574,11 @@ public class SIPCommander implements ISIPCommander { if (inviteStreamCallback != null) { inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream())); } + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent -> { ResponseEvent responseEvent = (ResponseEvent) okEvent.event; SIPResponse response = (SIPResponse) responseEvent.getResponse(); - streamSession.put(device.getDeviceId(), channelId,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download); + streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download); }); } @@ -774,7 +775,7 @@ public class SIPCommander implements ISIPCommander { cmdXml.append("" + guardCmdStr + "\r\n"); cmdXml.append("\r\n"); - + Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java index 08cc3c3f7..5a3faac64 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java @@ -287,19 +287,20 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { * @return */ @Override - public void deviceStatusResponse(ParentPlatform parentPlatform, String sn, String fromTag) throws SipException, InvalidArgumentException, ParseException { + public void deviceStatusResponse(ParentPlatform parentPlatform,String channelId, String sn, String fromTag,int status) throws SipException, InvalidArgumentException, ParseException { if (parentPlatform == null) { return ; } + String statusStr = (status==1)?"ONLINE":"OFFLINE"; String characterSet = parentPlatform.getCharacterSet(); StringBuffer deviceStatusXml = new StringBuffer(600); deviceStatusXml.append("\r\n"); deviceStatusXml.append("\r\n"); deviceStatusXml.append("DeviceStatus\r\n"); deviceStatusXml.append("" +sn + "\r\n"); - deviceStatusXml.append("" + parentPlatform.getDeviceGBId() + "\r\n"); + deviceStatusXml.append("" + channelId + "\r\n"); deviceStatusXml.append("OK\r\n"); - deviceStatusXml.append("ONLINE\r\n"); + deviceStatusXml.append(""+statusStr+"\r\n"); deviceStatusXml.append("OK\r\n"); deviceStatusXml.append("\r\n"); @@ -307,7 +308,6 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); sipSender.transmitRequest(parentPlatform.getDeviceIp(), request); - } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java index b4f5d8f26..3ed223e01 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java @@ -1,13 +1,16 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; import com.genersoft.iot.vmp.conf.SipConfig; +import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.auth.DigestServerAuthenticationHelper; import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo; import com.genersoft.iot.vmp.gb28181.bean.WvpSipDate; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; 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.utils.SipUtils; import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.utils.DateUtil; import gov.nist.javax.sip.RequestEventExt; @@ -59,6 +62,9 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @Autowired private SIPSender sipSender; + @Autowired + private UserSetting userSetting; + @Override public void afterPropertiesSet() throws Exception { // 添加消息处理的订阅 @@ -128,15 +134,9 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen // 添加Expires头 response.addHeader(request.getExpires()); - // 获取到通信地址等信息 - ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); - String received = viaHeader.getReceived(); - int rPort = viaHeader.getRPort(); - // 解析本地地址替代 - if (ObjectUtils.isEmpty(received) || rPort == -1) { - received = viaHeader.getHost(); - rPort = viaHeader.getPort(); - } + RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, + userSetting.getSipUseSourceIpAsRemoteAddress()); + if (device == null) { device = new Device(); device.setStreamMode("UDP"); @@ -146,9 +146,9 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen device.setDeviceId(deviceId); device.setOnline(0); } - device.setIp(received); - device.setPort(rPort); - device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); + device.setIp(remoteAddressInfo.getIp()); + device.setPort(remoteAddressInfo.getPort()); + device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort()))); device.setLocalIp(request.getLocalAddress().getHostAddress()); if (request.getExpires().getExpires() == 0) { // 注销成功 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java index 1f4513eb4..527b5d098 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java @@ -67,6 +67,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement @Override public void process(RequestEvent evt) { SIPRequest sipRequest = (SIPRequest)evt.getRequest(); + logger.info("接收到消息:" + evt.getRequest()); logger.debug("接收到消息:" + evt.getRequest()); String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); CallIdHeader callIdHeader = sipRequest.getCallIdHeader(); @@ -94,7 +95,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement if (device == null && parentPlatform == null) { // 不存在则回复404 responseAck(request, Response.NOT_FOUND, "device "+ deviceId +" not found"); - logger.warn("[设备未找到 ]: {}", deviceId); + logger.warn("[设备未找到 ]deviceId: {}, callId: {}", deviceId, callIdHeader.getCallId()); if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){ DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog()); deviceNotFoundEvent.setCallId(callIdHeader.getCallId()); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java index 28469034e..98c1a96f2 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java @@ -1,14 +1,16 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; +import com.genersoft.iot.vmp.common.VideoManagerConstants; +import com.genersoft.iot.vmp.conf.DynamicTask; +import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; +import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import com.genersoft.iot.vmp.service.IDeviceService; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.utils.DateUtil; import gov.nist.javax.sip.message.SIPRequest; import org.dom4j.Element; @@ -17,13 +19,10 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; import javax.sip.SipException; -import javax.sip.header.ViaHeader; import javax.sip.message.Response; import java.text.ParseException; @@ -33,6 +32,7 @@ import java.text.ParseException; @Component public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { + private Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class); private final static String cmdType = "Keepalive"; @@ -42,6 +42,12 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp @Autowired private IDeviceService deviceService; + @Autowired + private UserSetting userSetting; + + @Autowired + private DynamicTask dynamicTask; + @Override public void afterPropertiesSet() throws Exception { notifyMessageHandler.addHandler(cmdType, this); @@ -53,26 +59,27 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp // 未注册的设备不做处理 return; } + SIPRequest request = (SIPRequest) evt.getRequest(); // 回复200 OK try { - responseAck((SIPRequest) evt.getRequest(), Response.OK); + responseAck(request, Response.OK); } catch (SipException | InvalidArgumentException | ParseException e) { - logger.error("[命令发送失败] 国标级联 心跳回复: {}", e.getMessage()); + logger.error("[命令发送失败] 心跳回复: {}", e.getMessage()); } - // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息 - // 获取到通信地址等信息 - ViaHeader viaHeader = (ViaHeader) evt.getRequest().getHeader(ViaHeader.NAME); - String received = viaHeader.getReceived(); - int rPort = viaHeader.getRPort(); - // 解析本地地址替代 - if (ObjectUtils.isEmpty(received) || rPort == -1) { - received = viaHeader.getHost(); - rPort = viaHeader.getPort(); + + RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress()); + if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) { + device.setPort(remoteAddressInfo.getPort()); + device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort()))); + device.setIp(remoteAddressInfo.getIp()); } - if (device.getPort() != rPort) { - device.setPort(rPort); - device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); + if (device.getKeepaliveTime() == null) { + device.setKeepaliveIntervalTime(60); + }else { + long lastTime = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(device.getKeepaliveTime()); + device.setKeepaliveIntervalTime(new Long(System.currentTimeMillis()/1000-lastTime).intValue()); } + device.setKeepaliveTime(DateUtil.getNow()); if (device.getOnline() == 1) { @@ -80,9 +87,15 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp }else { // 对于已经离线的设备判断他的注册是否已经过期 if (!deviceService.expire(device)){ + device.setOnline(0); deviceService.online(device); } } + // 刷新过期任务 + String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); + // 如果三次心跳失败,则设置设备离线 + dynamicTask.startDelay(registerExpireTaskKey, ()-> deviceService.offline(device.getDeviceId()), device.getKeepaliveIntervalTime()*1000*3); + } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java index 7f0e6af08..e9d44d577 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query. import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; @@ -24,6 +25,8 @@ import javax.sip.header.FromHeader; import javax.sip.message.Response; import java.text.ParseException; +import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; + @Component public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { @@ -62,13 +65,19 @@ public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent i FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); // 回复200 OK try { - responseAck((SIPRequest) evt.getRequest(), Response.OK); + responseAck((SIPRequest) evt.getRequest(), Response.OK); } catch (SipException | InvalidArgumentException | ParseException e) { logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复200OK: {}", e.getMessage()); } String sn = rootElement.element("SN").getText(); + String channelId = getText(rootElement, "DeviceID"); + DeviceChannel deviceChannel = storager.queryChannelInParentPlatform(parentPlatform.getServerGBId(), channelId); + if (deviceChannel ==null){ + logger.error("[平台没有该通道的使用权限]:platformId"+parentPlatform.getServerGBId()+" deviceID:"+channelId); + return; + } try { - cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag()); + cmderFroPlatform.deviceStatusResponse(parentPlatform,channelId, sn, fromHeader.getTag(),deviceChannel.getStatus()); } catch (SipException | InvalidArgumentException | ParseException e) { logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复: {}", e.getMessage()); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java index bbce08781..45c5a90a0 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java @@ -1,9 +1,11 @@ package com.genersoft.iot.vmp.gb28181.utils; +import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo; import com.genersoft.iot.vmp.utils.GitUtil; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.header.Subject; +import gov.nist.javax.sip.message.SIPRequest; import org.springframework.util.ObjectUtils; import javax.sip.PeerUnavailableException; @@ -139,4 +141,31 @@ public class SipUtils { int typeCodeFromGbCode = getTypeCodeFromGbCode(deviceId); return typeCodeFromGbCode > 130 && typeCodeFromGbCode < 199; } + /** + * 从请求中获取设备ip地址和端口号 + * @param request 请求 + * @param sipUseSourceIpAsRemoteAddress false 从via中获取地址, true 直接获取远程地址 + * @return 地址信息 + */ + public static RemoteAddressInfo getRemoteAddressFromRequest(SIPRequest request, boolean sipUseSourceIpAsRemoteAddress) { + + String remoteAddress; + int remotePort; + if (sipUseSourceIpAsRemoteAddress) { + remoteAddress = request.getRemoteAddress().getHostAddress(); + remotePort = request.getRemotePort(); + }else { + // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息 + // 获取到通信地址等信息 + remoteAddress = request.getTopmostViaHeader().getReceived(); + remotePort = request.getTopmostViaHeader().getRPort(); + // 解析本地地址替代 + if (ObjectUtils.isEmpty(remoteAddress) || remotePort == -1) { + remoteAddress = request.getTopmostViaHeader().getHost(); + remotePort = request.getTopmostViaHeader().getPort(); + } + } + + return new RemoteAddressInfo(remoteAddress, remotePort); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java index 20946eaa7..ba95972b2 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -19,6 +19,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.hook.*; import com.genersoft.iot.vmp.service.*; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import com.genersoft.iot.vmp.vmanager.bean.StreamContent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -445,7 +446,7 @@ public class ZLMHttpHookListener { } StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, param.getApp(), param.getStream(), param.getTracks(), callId); - param.setStreamInfo(streamInfoByAppAndStream); + param.setStreamInfo(new StreamContent(streamInfoByAppAndStream)); redisCatchStorage.addStream(mediaServerItem, type, param.getApp(), param.getStream(), param); if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal() || param.getOriginType() == OriginType.RTMP_PUSH.ordinal() @@ -463,7 +464,7 @@ public class ZLMHttpHookListener { } GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream()); if (gbStream != null) { -// eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF); +// eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF); } zlmMediaListManager.removeMedia(param.getApp(), param.getStream()); } @@ -534,7 +535,7 @@ public class ZLMHttpHookListener { logger.info("[ZLM HOOK]流无人观看:{]->{}->{}/{}" + param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); JSONObject ret = new JSONObject(); ret.put("code", 0); - // 录像下载 + // 国标类型的流 if ("rtp".equals(param.getApp())){ ret.put("close", userSetting.getStreamOnDemand()); // 国标流, 点播/录像回放/录像下载 @@ -641,7 +642,7 @@ public class ZLMHttpHookListener { @ResponseBody @PostMapping(value = "/on_stream_not_found", produces = "application/json;charset=UTF-8") public JSONObject onStreamNotFound(@RequestBody OnStreamNotFoundHookParam param){ - logger.info("[ZLM HOOK] 流未找到:{}->{}->{}/{}" + param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); + logger.info("[ZLM HOOK] 流未找到:{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); taskExecutor.execute(()->{ MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); if (userSetting.isAutoApplyPlay() && mediaInfo != null) { @@ -709,7 +710,7 @@ public class ZLMHttpHookListener { @PostMapping(value = "/on_send_rtp_stopped", produces = "application/json;charset=UTF-8") public JSONObject onSendRtpStopped(HttpServletRequest request, @RequestBody OnSendRtpStoppedHookParam param){ - logger.info("[ZLM HOOK] 发送rtp被动关闭:{}->{}/{}", param.getMediaServerId(), param.getApp(), param.getStream()); + logger.info("[ZLM HOOK] rtp发送关闭:{}->{}/{}", param.getMediaServerId(), param.getApp(), param.getStream()); JSONObject ret = new JSONObject(); ret.put("code", 0); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamChangedHookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamChangedHookParam.java index 29f91c8ba..07c09e69f 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamChangedHookParam.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamChangedHookParam.java @@ -1,6 +1,6 @@ package com.genersoft.iot.vmp.media.zlm.dto.hook; -import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.vmanager.bean.StreamContent; import java.util.List; @@ -291,7 +291,7 @@ public class OnStreamChangedHookParam extends HookParam{ } } - private StreamInfo streamInfo; + private StreamContent streamInfo; public String getApp() { return app; @@ -407,11 +407,11 @@ public class OnStreamChangedHookParam extends HookParam{ this.docker = docker; } - public StreamInfo getStreamInfo() { + public StreamContent getStreamInfo() { return streamInfo; } - public void setStreamInfo(StreamInfo streamInfo) { + public void setStreamInfo(StreamContent streamInfo) { this.streamInfo = streamInfo; } diff --git a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java index 21375e0a9..1233455f2 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java @@ -37,7 +37,7 @@ public interface IMediaServerService { */ void zlmServerOffline(String mediaServerId); - MediaServerItem getMediaServerForMinimumLoad(); + MediaServerItem getMediaServerForMinimumLoad(Boolean hasAssist); void setZLMConfig(MediaServerItem mediaServerItem, boolean restart); diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java index 39c5ffad6..ffdaef3ef 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java @@ -40,15 +40,20 @@ public interface IPlayService { MediaServerItem getNewMediaServerItem(Device device); + /** + * 获取包含assist服务的节点 + */ + MediaServerItem getNewMediaServerItemHasAssist(Device device); + void onPublishHandlerForDownload(InviteStreamInfo inviteStreamInfo, String deviceId, String channelId, String toString); - DeferredResult> playBack(String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); - DeferredResult> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); + void playBack(String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback); + void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); void zlmServerOffline(String mediaServerId); - DeferredResult> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); - DeferredResult> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); + void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback); + void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream); diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackCallback.java b/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackCallback.java index 5ed6cf344..33a09bd40 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackCallback.java +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackCallback.java @@ -1,10 +1,7 @@ package com.genersoft.iot.vmp.service.bean; -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; +public interface PlayBackCallback { -public interface PlayBackCallback { - - void call(PlayBackResult msg); + void call(PlayBackResult msg); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java index 9db2d6830..880b69711 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java @@ -99,7 +99,7 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { HashMap channelsInStore = new HashMap<>(); Device device = deviceMapper.getDeviceByDeviceId(deviceId); if (channels != null && channels.size() > 0) { - List channelList = channelMapper.queryChannels(deviceId, null, null, null, null); + List channelList = channelMapper.queryChannels(deviceId, null, null, null, null,null); if (channelList.size() == 0) { for (DeviceChannel channel : channels) { channel.setDeviceId(deviceId); diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java index eb208d32a..1c57d0b2b 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.service.impl; +import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.*; @@ -46,8 +47,6 @@ public class DeviceServiceImpl implements IDeviceService { private final static Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class); - private final String registerExpireTaskKeyPrefix = "device-register-expire-"; - @Autowired private DynamicTask dynamicTask; @@ -108,7 +107,10 @@ public class DeviceServiceImpl implements IDeviceService { redisCatchStorage.clearCatchByDeviceId(device.getDeviceId()); } device.setUpdateTime(now); - + if (device.getKeepaliveIntervalTime() == 0) { + // 默认心跳间隔60 + device.setKeepaliveIntervalTime(60); + } // 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询 if (device.getCreateTime() == null) { device.setOnline(1); @@ -123,7 +125,6 @@ public class DeviceServiceImpl implements IDeviceService { } sync(device); }else { - if(device.getOnline() == 0){ device.setOnline(1); device.setCreateTime(now); @@ -160,18 +161,19 @@ public class DeviceServiceImpl implements IDeviceService { addMobilePositionSubscribe(device); } // 刷新过期任务 - String registerExpireTaskKey = registerExpireTaskKeyPrefix + device.getDeviceId(); - dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getExpires() * 1000); + String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); + // 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线 + dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getKeepaliveIntervalTime() * 1000 * 3); } @Override public void offline(String deviceId) { - logger.info("[设备离线], device:{}", deviceId); + logger.error("[设备离线], device:{}", deviceId); Device device = deviceMapper.getDeviceByDeviceId(deviceId); if (device == null) { return; } - String registerExpireTaskKey = registerExpireTaskKeyPrefix + deviceId; + String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + deviceId; dynamicTask.stop(registerExpireTaskKey); device.setOnline(0); redisCatchStorage.updateDevice(device); @@ -356,7 +358,6 @@ public class DeviceServiceImpl implements IDeviceService { device.setUpdateTime(DateUtil.getNow()); if (deviceMapper.update(device) > 0) { redisCatchStorage.updateDevice(device); - } } @@ -432,7 +433,7 @@ public class DeviceServiceImpl implements IDeviceService { if (parentId.length() < 14 ) { return null; } - List deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null); + List deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null,null); List> trees = transportChannelsToTree(deviceChannels, parentId); return trees; } @@ -477,7 +478,7 @@ public class DeviceServiceImpl implements IDeviceService { if (parentId.length() < 14 ) { return null; } - List deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null); + List deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null,null); return deviceChannels; } @@ -541,7 +542,7 @@ public class DeviceServiceImpl implements IDeviceService { } }else { if (haveChannel) { - List deviceChannels = deviceChannelMapper.queryChannels(deviceId, null, null, null, null); + List deviceChannels = deviceChannelMapper.queryChannels(deviceId, null, null, null, null,null); if (deviceChannels != null && deviceChannels.size() > 0) { result.addAll(deviceChannels); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java index ccb556427..28b540562 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java @@ -501,7 +501,7 @@ public class MediaServerServiceImpl implements IMediaServerService { * @return MediaServerItem */ @Override - public MediaServerItem getMediaServerForMinimumLoad() { + public MediaServerItem getMediaServerForMinimumLoad(Boolean hasAssist) { String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(); if (RedisUtil.zSize(key) == null || RedisUtil.zSize(key) == 0) { @@ -514,9 +514,31 @@ public class MediaServerServiceImpl implements IMediaServerService { // 获取分数最低的,及并发最低的 Set objects = RedisUtil.zRange(key, 0, -1); ArrayList mediaServerObjectS = new ArrayList<>(objects); + MediaServerItem mediaServerItem = null; + if (hasAssist == null) { + String mediaServerId = (String)mediaServerObjectS.get(0); + mediaServerItem = getOne(mediaServerId); + }else if (hasAssist) { + for (Object mediaServerObject : mediaServerObjectS) { + String mediaServerId = (String)mediaServerObject; + MediaServerItem serverItem = getOne(mediaServerId); + if (serverItem.getRecordAssistPort() > 0) { + mediaServerItem = serverItem; + break; + } + } + }else if (!hasAssist) { + for (Object mediaServerObject : mediaServerObjectS) { + String mediaServerId = (String)mediaServerObject; + MediaServerItem serverItem = getOne(mediaServerId); + if (serverItem.getRecordAssistPort() == 0) { + mediaServerItem = serverItem; + break; + } + } + } - String mediaServerId = (String)mediaServerObjectS.get(0); - return getOne(mediaServerId); + return mediaServerItem; } /** diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java index fbc507a63..136689ca2 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java @@ -135,14 +135,7 @@ public class PlatformServiceImpl implements IPlatformService { dynamicTask.startCron(registerTaskKey, // 注册失败(注册成功时由程序直接调用了online方法) ()-> { - try { - logger.info("[国标级联] 平台:{}注册即将到期,重新注册", parentPlatform.getServerGBId()); - commanderForPlatform.register(parentPlatform, eventResult -> { - offline(parentPlatform, false); - },null); - } catch (InvalidArgumentException | ParseException | SipException e) { - logger.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage()); - } + registerTask(parentPlatform); }, (parentPlatform.getExpires() - 10) *1000); } @@ -194,6 +187,28 @@ public class PlatformServiceImpl implements IPlatformService { } } + private void registerTask(ParentPlatform parentPlatform){ + try { + // 设置超时重发, 后续从底层支持消息重发 + String key = KEEPALIVE_KEY_PREFIX + parentPlatform.getServerGBId() + "_timeout"; + if (dynamicTask.isAlive(key)) { + return; + } + dynamicTask.startDelay(key, ()->{ + registerTask(parentPlatform); + }, 1000); + logger.info("[国标级联] 平台:{}注册即将到期,重新注册", parentPlatform.getServerGBId()); + commanderForPlatform.register(parentPlatform, eventResult -> { + dynamicTask.stop(key); + offline(parentPlatform, false); + },eventResult -> { + dynamicTask.stop(key); + }); + } catch (InvalidArgumentException | ParseException | SipException e) { + logger.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage()); + } + } + @Override public void offline(ParentPlatform parentPlatform, boolean stopRegister) { logger.info("[平台离线]:{}", parentPlatform.getServerGBId()); diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java index 616aaadf2..d198882e4 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -45,11 +45,8 @@ import gov.nist.javax.sip.message.SIPResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; -import org.springframework.web.context.request.async.DeferredResult; import javax.sip.InvalidArgumentException; import javax.sip.ResponseEvent; @@ -454,6 +451,9 @@ public class PlayServiceImpl implements IPlayService { mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); + // 取消订阅消息监听 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); + subscribe.removeSubscribe(hookSubscribe); } } }, userSetting.getPlayTimeout()); @@ -463,7 +463,6 @@ public class PlayServiceImpl implements IPlayService { dynamicTask.stop(timeOutTaskKey); // 释放ssrc mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); RequestMessage msg = new RequestMessage(); @@ -481,7 +480,7 @@ public class PlayServiceImpl implements IPlayService { onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId); hookEvent.response(mediaServerItemInuse, response); logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); - String streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", ssrcInfo.getStream()); + String streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.flv", mediaServerItemInuse.getHttpPort(), "rtp", ssrcInfo.getStream()); String path = "snap"; String fileName = device.getDeviceId() + "_" + channelId + ".jpg"; // 请求截图 @@ -589,14 +588,10 @@ public class PlayServiceImpl implements IPlayService { } } - private void onPublishHandlerForPlayback(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String uuid) { - RequestMessage msg = new RequestMessage(); - msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId); - if (!ObjectUtils.isEmpty(uuid)) { - msg.setId(uuid); - } - StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); + private void onPublishHandlerForPlayback(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, PlayBackCallback playBackCallback) { + StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); + PlayBackResult playBackResult = new PlayBackResult<>(); if (streamInfo != null) { DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); if (deviceChannel != null) { @@ -605,17 +600,16 @@ public class PlayServiceImpl implements IPlayService { } redisCatchStorage.startPlay(streamInfo); - WVPResult wvpResult = new WVPResult(); - wvpResult.setCode(ErrorCode.SUCCESS.getCode()); - wvpResult.setMsg(ErrorCode.SUCCESS.getMsg()); - wvpResult.setData(streamInfo); - msg.setData(wvpResult); - resultHolder.invokeAllResult(msg); + playBackResult.setCode(ErrorCode.SUCCESS.getCode()); + playBackResult.setMsg(ErrorCode.SUCCESS.getMsg()); + playBackResult.setData(streamInfo); + playBackCallback.call(playBackResult); } else { logger.warn("录像回放调用失败!"); - msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "录像回放调用失败!")); - resultHolder.invokeAllResult(msg); + playBackResult.setCode(ErrorCode.ERROR100.getCode()); + playBackResult.setMsg("录像回放调用失败!"); + playBackCallback.call(playBackResult); } } @@ -626,7 +620,7 @@ public class PlayServiceImpl implements IPlayService { } MediaServerItem mediaServerItem; if (ObjectUtils.isEmpty(device.getMediaServerId()) || "auto".equals(device.getMediaServerId())) { - mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(); + mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null); } else { mediaServerItem = mediaServerService.getOne(device.getMediaServerId()); } @@ -637,45 +631,56 @@ public class PlayServiceImpl implements IPlayService { } @Override - public DeferredResult> playBack(String deviceId, String channelId, String startTime, + public MediaServerItem getNewMediaServerItemHasAssist(Device device) { + if (device == null) { + return null; + } + MediaServerItem mediaServerItem; + if (ObjectUtils.isEmpty(device.getMediaServerId()) || "auto".equals(device.getMediaServerId())) { + mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(true); + } else { + mediaServerItem = mediaServerService.getOne(device.getMediaServerId()); + } + if (mediaServerItem == null) { + logger.warn("[获取可用的ZLM节点]未找到可使用的ZLM..."); + } + return mediaServerItem; + } + + @Override + public void playBack(String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback inviteStreamCallback, PlayBackCallback callback) { Device device = storager.queryVideoDevice(deviceId); if (device == null) { - return null; + return; } MediaServerItem newMediaServerItem = getNewMediaServerItem(device); SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, device.isSsrcCheck(), true); - return playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, inviteStreamCallback, callback); + playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, inviteStreamCallback, callback); } @Override - public DeferredResult> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, + public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback) { if (mediaServerItem == null || ssrcInfo == null) { - return null; + return; } - String uuid = UUID.randomUUID().toString(); - String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId; + Device device = storager.queryVideoDevice(deviceId); if (device == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备: " + deviceId + "不存在"); } - DeferredResult> result = new DeferredResult<>(30000L); - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid, result); - RequestMessage requestMessage = new RequestMessage(); - requestMessage.setId(uuid); - requestMessage.setKey(key); - PlayBackResult playBackResult = new PlayBackResult<>(); + + PlayBackResult playBackResult = new PlayBackResult<>(); String playBackTimeOutTaskKey = UUID.randomUUID().toString(); dynamicTask.startDelay(playBackTimeOutTaskKey, () -> { logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId)); playBackResult.setCode(ErrorCode.ERROR100.getCode()); playBackResult.setMsg("回放超时"); - playBackResult.setData(requestMessage); try { cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); @@ -687,19 +692,14 @@ public class PlayServiceImpl implements IPlayService { mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); } - // 回复之前所有的点播请求 playBackCallback.call(playBackResult); - result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "回放超时")); - resultHolder.exist(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid); }, userSetting.getPlayTimeout()); SipSubscribe.Event errorEvent = event -> { dynamicTask.stop(playBackTimeOutTaskKey); - requestMessage.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg))); playBackResult.setCode(ErrorCode.ERROR100.getCode()); playBackResult.setMsg(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)); - playBackResult.setData(requestMessage); playBackResult.setEvent(event); playBackCallback.call(playBackResult); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); @@ -717,11 +717,9 @@ public class PlayServiceImpl implements IPlayService { return; } redisCatchStorage.startPlayback(streamInfo, inviteStreamInfo.getCallId()); - WVPResult success = WVPResult.success(streamInfo); - requestMessage.setData(success); playBackResult.setCode(ErrorCode.SUCCESS.getCode()); playBackResult.setMsg(ErrorCode.SUCCESS.getMsg()); - playBackResult.setData(requestMessage); + playBackResult.setData(streamInfo); playBackResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); playBackResult.setResponse(inviteStreamInfo.getResponse()); playBackCallback.call(playBackResult); @@ -768,7 +766,7 @@ public class PlayServiceImpl implements IPlayService { logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString()); dynamicTask.stop(playBackTimeOutTaskKey); // hook响应 - onPublishHandlerForPlayback(mediaServerItemInUse, response, device.getDeviceId(), channelId, uuid); + onPublishHandlerForPlayback(mediaServerItemInUse, response, device.getDeviceId(), channelId, playBackCallback); hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream())); }); } @@ -788,50 +786,45 @@ public class PlayServiceImpl implements IPlayService { eventResult.msg = "命令发送失败"; errorEvent.response(eventResult); } - return result; } @Override - public DeferredResult> download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) { + public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback) { Device device = storager.queryVideoDevice(deviceId); if (device == null) { - return null; + return; + } + MediaServerItem newMediaServerItem = getNewMediaServerItemHasAssist(device); + if (newMediaServerItem == null) { + PlayBackResult downloadResult = new PlayBackResult<>(); + downloadResult.setCode(ErrorCode.ERROR100.getCode()); + downloadResult.setMsg("未找到assist服务"); + playBackCallback.call(downloadResult); + return; } - MediaServerItem newMediaServerItem = getNewMediaServerItem(device); SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, device.isSsrcCheck(), true); - return download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, infoCallBack, hookCallBack); + download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, infoCallBack, playBackCallback); } + @Override - public DeferredResult> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) { + public void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) { if (mediaServerItem == null || ssrcInfo == null) { - return null; + return; } - String uuid = UUID.randomUUID().toString(); - String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId; - DeferredResult> result = new DeferredResult<>(30000L); + Device device = storager.queryVideoDevice(deviceId); if (device == null) { throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + "不存在"); } - - resultHolder.put(key, uuid, result); - RequestMessage requestMessage = new RequestMessage(); - requestMessage.setId(uuid); - requestMessage.setKey(key); - WVPResult wvpResult = new WVPResult<>(); - requestMessage.setData(wvpResult); - PlayBackResult downloadResult = new PlayBackResult<>(); - downloadResult.setData(requestMessage); + PlayBackResult downloadResult = new PlayBackResult<>(); String downLoadTimeOutTaskKey = UUID.randomUUID().toString(); dynamicTask.startDelay(downLoadTimeOutTaskKey, () -> { logger.warn(String.format("录像下载请求超时,deviceId:%s ,channelId:%s", deviceId, channelId)); - wvpResult.setCode(ErrorCode.ERROR100.getCode()); - wvpResult.setMsg("录像下载请求超时"); downloadResult.setCode(ErrorCode.ERROR100.getCode()); downloadResult.setMsg("录像下载请求超时"); hookCallBack.call(downloadResult); @@ -846,16 +839,12 @@ public class PlayServiceImpl implements IPlayService { mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); } - // 回复之前所有的点播请求 - hookCallBack.call(downloadResult); }, userSetting.getPlayTimeout()); SipSubscribe.Event errorEvent = event -> { dynamicTask.stop(downLoadTimeOutTaskKey); downloadResult.setCode(ErrorCode.ERROR100.getCode()); downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg)); - wvpResult.setCode(ErrorCode.ERROR100.getCode()); - wvpResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg)); downloadResult.setEvent(event); hookCallBack.call(downloadResult); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); @@ -870,11 +859,9 @@ public class PlayServiceImpl implements IPlayService { streamInfo.setStartTime(startTime); streamInfo.setEndTime(endTime); redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId()); - wvpResult.setCode(ErrorCode.SUCCESS.getCode()); - wvpResult.setMsg(ErrorCode.SUCCESS.getMsg()); - wvpResult.setData(streamInfo); downloadResult.setCode(ErrorCode.SUCCESS.getCode()); downloadResult.setMsg(ErrorCode.SUCCESS.getMsg()); + downloadResult.setData(streamInfo); downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); downloadResult.setResponse(inviteStreamInfo.getResponse()); hookCallBack.call(downloadResult); @@ -886,7 +873,6 @@ public class PlayServiceImpl implements IPlayService { eventResult.msg = "命令发送失败"; errorEvent.response(eventResult); } - return result; } @Override @@ -906,7 +892,10 @@ public class PlayServiceImpl implements IPlayService { } if (mediaServerItem.getRecordAssistPort() > 0) { JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, streamInfo.getApp(), streamInfo.getStream(), null); - if (jsonObject != null && jsonObject.getInteger("code") == 0) { + if (jsonObject == null) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), "连接Assist服务失败"); + } + if (jsonObject.getInteger("code") == 0) { long duration = jsonObject.getLong("data"); if (duration == 0) { diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java index b9693a045..ad37a618e 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java @@ -90,7 +90,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { public StreamInfo save(StreamProxyItem param) { MediaServerItem mediaInfo; if (ObjectUtils.isEmpty(param.getMediaServerId()) || "auto".equals(param.getMediaServerId())){ - mediaInfo = mediaServerService.getMediaServerForMinimumLoad(); + mediaInfo = mediaServerService.getMediaServerForMinimumLoad(null); }else { mediaInfo = mediaServerService.getOne(param.getMediaServerId()); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java index 42cbec5c9..35ed99e45 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java @@ -117,7 +117,7 @@ public class RedisGbPlayMsgListener implements MessageListener { Message msg = taskQueue.poll(); try { JSONObject msgJSON = JSON.parseObject(msg.getBody(), JSONObject.class); - WvpRedisMsg wvpRedisMsg = JSON.toJavaObject(msgJSON, WvpRedisMsg.class); + WvpRedisMsg wvpRedisMsg = JSON.to(WvpRedisMsg.class, msgJSON); if (!userSetting.getServerId().equals(wvpRedisMsg.getToId())) { continue; } @@ -126,11 +126,11 @@ public class RedisGbPlayMsgListener implements MessageListener { switch (wvpRedisMsg.getCmd()){ case WvpRedisMsgCmd.GET_SEND_ITEM: - RequestSendItemMsg content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestSendItemMsg.class); + RequestSendItemMsg content = JSON.to(RequestSendItemMsg.class, wvpRedisMsg.getContent()); requestSendItemMsgHand(content, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); break; case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: - RequestPushStreamMsg param = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestPushStreamMsg.class);; + RequestPushStreamMsg param = JSON.to(RequestPushStreamMsg.class, wvpRedisMsg.getContent()); requestPushStreamMsgHand(param, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); break; default: @@ -142,12 +142,12 @@ public class RedisGbPlayMsgListener implements MessageListener { switch (wvpRedisMsg.getCmd()){ case WvpRedisMsgCmd.GET_SEND_ITEM: - WVPResult content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class); + WVPResult content = JSON.to(WVPResult.class, wvpRedisMsg.getContent()); String key = wvpRedisMsg.getSerial(); switch (content.getCode()) { case 0: - ResponseSendItemMsg responseSendItemMsg =JSON.toJavaObject((JSONObject)content.getData(), ResponseSendItemMsg.class); + ResponseSendItemMsg responseSendItemMsg =JSON.to(ResponseSendItemMsg.class, content.getData()); PlayMsgCallback playMsgCallback = callbacks.get(key); if (playMsgCallback != null) { callbacksForError.remove(key); @@ -172,7 +172,7 @@ public class RedisGbPlayMsgListener implements MessageListener { } break; case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: - WVPResult wvpResult = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class); + WVPResult wvpResult = JSON.to(WVPResult.class, wvpRedisMsg.getContent()); String serial = wvpRedisMsg.getSerial(); switch (wvpResult.getCode()) { case 0: @@ -199,6 +199,7 @@ public class RedisGbPlayMsgListener implements MessageListener { default: break; } + } }catch (Exception e) { logger.warn("[RedisGbPlayMsg] 发现未处理的异常, {}",e.getMessage()); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java index ab4374675..b4644bfb4 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java @@ -59,7 +59,7 @@ public interface IVideoManagerStorage { */ public PageInfo queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, Boolean catalogUnderDevice, int page, int count); - public List queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit); + public List queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit,List channelIds); /** @@ -68,7 +68,7 @@ public interface IVideoManagerStorage { * @param deviceId 设备ID * @return */ - public List queryChannelsByDeviceId(String deviceId); + public List queryChannelsByDeviceId(String deviceId,Boolean online,List channelIds); public List queryOnlineChannelsByDeviceId(String deviceId); /** @@ -91,14 +91,14 @@ public interface IVideoManagerStorage { * @param count 每页数量 * @return List 设备对象数组 */ - public PageInfo queryVideoDeviceList(int page, int count); + public PageInfo queryVideoDeviceList(int page, int count,Boolean online); /** * 获取多个设备 * * @return List 设备对象数组 */ - public List queryVideoDeviceList(); + public List queryVideoDeviceList(Boolean online); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceAlarmMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceAlarmMapper.java index bc651ce79..f67e152f4 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceAlarmMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceAlarmMapper.java @@ -16,19 +16,19 @@ import java.util.List; public interface DeviceAlarmMapper { @Insert("INSERT INTO device_alarm (deviceId, channelId, alarmPriority, alarmMethod, alarmTime, alarmDescription, longitude, latitude, alarmType , createTime ) " + - "VALUES ('${deviceId}', '${channelId}', '${alarmPriority}', '${alarmMethod}', '${alarmTime}', '${alarmDescription}', ${longitude}, ${latitude}, '${alarmType}', '${createTime}')") + "VALUES (#{deviceId}, #{channelId}, #{alarmPriority}, #{alarmMethod}, #{alarmTime}, #{alarmDescription}, #{longitude}, #{latitude}, #{alarmType}, #{createTime})") int add(DeviceAlarm alarm); @Select(value = {" "}) List query(String deviceId, String alarmPriority, String alarmMethod, @@ -38,10 +38,10 @@ public interface DeviceAlarmMapper { @Delete(" " ) int clearAlarmBeforeTime(Integer id, List deviceIdList, String time); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java index 53072b2db..8da1a09b8 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java @@ -20,46 +20,46 @@ public interface DeviceChannelMapper { "address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " + "ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, " + "longitudeWgs84, latitudeWgs84, hasAudio, createTime, updateTime, businessGroupId, gpsTime) " + - "VALUES ('${channelId}', '${deviceId}', '${name}', '${manufacture}', '${model}', '${owner}', '${civilCode}', '${block}'," + - "'${address}', ${parental}, '${parentId}', ${safetyWay}, ${registerWay}, '${certNum}', ${certifiable}, ${errCode}, '${secrecy}', " + - "'${ipAddress}', ${port}, '${password}', ${PTZType}, ${status}, '${streamId}', ${longitude}, ${latitude}, ${longitudeGcj02}, " + - "${latitudeGcj02}, ${longitudeWgs84}, ${latitudeWgs84}, ${hasAudio}, '${createTime}', '${updateTime}', '${businessGroupId}', '${gpsTime}')") + "VALUES (#{channelId}, #{deviceId}, #{name}, #{manufacture}, #{model}, #{owner}, #{civilCode}, #{block}," + + "#{address}, #{parental}, #{parentId}, #{safetyWay}, #{registerWay}, #{certNum}, #{certifiable}, #{errCode}, #{secrecy}, " + + "#{ipAddress}, #{port}, #{password}, #{PTZType}, #{status}, #{streamId}, #{longitude}, #{latitude}, #{longitudeGcj02}, " + + "#{latitudeGcj02}, #{longitudeWgs84}, #{latitudeWgs84}, #{hasAudio}, #{createTime}, #{updateTime}, #{businessGroupId}, #{gpsTime})") int add(DeviceChannel channel); @Update(value = {" "}) int update(DeviceChannel channel); @@ -70,15 +70,18 @@ public interface DeviceChannelMapper { "device_channel dc " + "WHERE " + "dc.deviceId = #{deviceId} " + - " AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%') " + +" AND (dc.channelId LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%')) " + " AND (dc.parentId=#{parentChannelId} OR dc.civilCode = #{parentChannelId}) " + " AND dc.status=1" + " AND dc.status=0" + " AND dc.subCount > 0 " + " AND dc.subCount = 0 " + + " AND dc.channelId in " + + "#{item} " + + " " + "ORDER BY dc.channelId " + " "}) - List queryChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online); + List queryChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online,List channelIds); @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND channelId=#{channelId}") DeviceChannel queryChannel(String deviceId, String channelId); @@ -110,7 +113,7 @@ public interface DeviceChannelMapper { " LEFT JOIN device de ON dc.deviceId = de.deviceId " + " LEFT JOIN platform_gb_channel pgc on pgc.deviceChannelId = dc.id " + " WHERE 1=1 " + - " AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%') " + + " AND (dc.channelId LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%')) " + " AND dc.status=1 " + " AND dc.status=0 " + " AND dc.subCount > 0 " + @@ -151,14 +154,14 @@ public interface DeviceChannelMapper { " longitudeWgs84, latitudeWgs84, hasAudio, createTime, updateTime, businessGroupId, gpsTime) " + "values " + " " + - "('${item.channelId}', '${item.deviceId}', '${item.name}', '${item.manufacture}', '${item.model}', " + - "'${item.owner}', '${item.civilCode}', '${item.block}',${item.subCount}," + - "'${item.address}', ${item.parental}, '${item.parentId}', ${item.safetyWay}, ${item.registerWay}, " + - "'${item.certNum}', ${item.certifiable}, ${item.errCode}, '${item.secrecy}', " + - "'${item.ipAddress}', ${item.port}, '${item.password}', ${item.PTZType}, ${item.status}, " + - "'${item.streamId}', ${item.longitude}, ${item.latitude},${item.longitudeGcj02}, " + - "${item.latitudeGcj02},${item.longitudeWgs84}, ${item.latitudeWgs84}, ${item.hasAudio},'${item.createTime}', '${item.updateTime}', " + - "'${item.businessGroupId}', '${item.gpsTime}') " + + "(#{item.channelId}, #{item.deviceId}, #{item.name}, #{item.manufacture}, #{item.model}, " + + "#{item.owner}, #{item.civilCode}, #{item.block},#{item.subCount}," + + "#{item.address}, #{item.parental}, #{item.parentId}, #{item.safetyWay}, #{item.registerWay}, " + + "#{item.certNum}, #{item.certifiable}, #{item.errCode}, #{item.secrecy}, " + + "#{item.ipAddress}, #{item.port}, #{item.password}, #{item.PTZType}, #{item.status}, " + + "#{item.streamId}, #{item.longitude}, #{item.latitude},#{item.longitudeGcj02}, " + + "#{item.latitudeGcj02},#{item.longitudeWgs84}, #{item.latitudeWgs84}, #{item.hasAudio}, now(), now(), " + + "#{item.businessGroupId}, #{item.gpsTime}) " + " " + "ON DUPLICATE KEY UPDATE " + "updateTime=VALUES(updateTime), " + @@ -203,39 +206,39 @@ public interface DeviceChannelMapper { "" + " UPDATE" + " device_channel" + - " SET updateTime='${item.updateTime}'" + - ", name='${item.name}'" + - ", manufacture='${item.manufacture}'" + - ", model='${item.model}'" + - ", owner='${item.owner}'" + - ", civilCode='${item.civilCode}'" + - ", block='${item.block}'" + - ", block=${item.subCount}" + - ", address='${item.address}'" + - ", parental=${item.parental}" + - ", parentId='${item.parentId}'" + - ", safetyWay=${item.safetyWay}" + - ", registerWay=${item.registerWay}" + - ", certNum='${item.certNum}'" + - ", certifiable=${item.certifiable}" + - ", errCode=${item.errCode}" + - ", secrecy='${item.secrecy}'" + - ", ipAddress='${item.ipAddress}'" + - ", port=${item.port}" + - ", password='${item.password}'" + - ", PTZType=${item.PTZType}" + - ", status='${item.status}'" + - ", streamId='${item.streamId}'" + - ", hasAudio=${item.hasAudio}" + - ", longitude=${item.longitude}" + - ", latitude=${item.latitude}" + - ", longitudeGcj02=${item.longitudeGcj02}" + - ", latitudeGcj02=${item.latitudeGcj02}" + - ", longitudeWgs84=${item.longitudeWgs84}" + - ", latitudeWgs84=${item.latitudeWgs84}" + + " SET updateTime=#{item.updateTime}" + + ", name=#{item.name}" + + ", manufacture=#{item.manufacture}" + + ", model=#{item.model}" + + ", owner=#{item.owner}" + + ", civilCode=#{item.civilCode}" + + ", block=#{item.block}" + + ", block=#{item.subCount}" + + ", address=#{item.address}" + + ", parental=#{item.parental}" + + ", parentId=#{item.parentId}" + + ", safetyWay=#{item.safetyWay}" + + ", registerWay=#{item.registerWay}" + + ", certNum=#{item.certNum}" + + ", certifiable=#{item.certifiable}" + + ", errCode=#{item.errCode}" + + ", secrecy=#{item.secrecy}" + + ", ipAddress=#{item.ipAddress}" + + ", port=#{item.port}" + + ", password=#{item.password}" + + ", PTZType=#{item.PTZType}" + + ", status=#{item.status}" + + ", streamId=#{item.streamId}" + + ", hasAudio=#{item.hasAudio}" + + ", longitude=#{item.longitude}" + + ", latitude=#{item.latitude}" + + ", longitudeGcj02=#{item.longitudeGcj02}" + + ", latitudeGcj02=#{item.latitudeGcj02}" + + ", longitudeWgs84=#{item.longitudeWgs84}" + + ", latitudeWgs84=#{item.latitudeWgs84}" + ", businessGroupId=#{item.businessGroupId}" + ", gpsTime=#{item.gpsTime}" + - "WHERE deviceId='${item.deviceId}' AND channelId='${item.channelId}'"+ + "WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}"+ "" + ""}) int batchUpdate(List updateChannels); @@ -248,17 +251,20 @@ public interface DeviceChannelMapper { "device_channel dc1 " + "WHERE " + "dc1.deviceId = #{deviceId} " + - " AND (dc1.channelId LIKE '%${query}%' OR dc1.name LIKE '%${query}%' OR dc1.name LIKE '%${query}%') " + + " AND (dc1.channelId LIKE concat('%',#{query},'%') OR dc1.name LIKE concat('%',#{query},'%') OR dc1.name LIKE concat('%',#{query},'%')) " + " AND dc1.parentId=#{parentChannelId} " + " AND dc1.status=1" + " AND dc1.status=0" + " AND dc1.subCount >0" + " AND dc1.subCount=0" + + " AND dc1.channelId in " + + "#{item} " + + " " + "ORDER BY dc1.channelId ASC " + "Limit #{limit} OFFSET #{start}" + " "}) List queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String parentChannelId, String query, - Boolean hasSubChannel, Boolean online, int start, int limit); + Boolean hasSubChannel, Boolean online, int start, int limit,List channelIds); @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND status=1") List queryOnlineChannelsByDeviceId(String deviceId); @@ -286,13 +292,13 @@ public interface DeviceChannelMapper { @Update(value = {" "}) @@ -309,10 +315,10 @@ public interface DeviceChannelMapper { "select * " + "from device_channel " + "where deviceId=#{deviceId}" + - " and parentId = #{parentId} or left(channelId, ${parentId.length()}) = #{parentId} and length(channelId)=${length} " + - " and parentId = #{parentId} or length(channelId)=${length} " + + " and parentId = #{parentId} or left(channelId, #{parentId.length()}) = #{parentId} and length(channelId)=#{length} " + + " and parentId = #{parentId} or length(channelId)=#{length} " + " and parentId = #{parentId} " + - " and parentId = #{parentId} or left(channelId, ${parentId.length()}) = #{parentId} " + + " and parentId = #{parentId} or left(channelId, #{parentId.length()}) = #{parentId} " + " "}) List getChannelsWithCivilCodeAndLength(String deviceId, String parentId, Integer length); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java index 0e616921c..8143d35ad 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java @@ -61,6 +61,7 @@ public interface DeviceMapper { "expires," + "registerTime," + "keepaliveTime," + + "keepaliveIntervalTime," + "createTime," + "updateTime," + "charset," + @@ -88,6 +89,7 @@ public interface DeviceMapper { "#{expires}," + "#{registerTime}," + "#{keepaliveTime}," + + "#{keepaliveIntervalTime}," + "#{createTime}," + "#{updateTime}," + "#{charset}," + @@ -104,25 +106,28 @@ public interface DeviceMapper { @Update(value = {" "}) int update(Device device); - @Select("SELECT " + + @Select( + " " + ) + List getDevices(Boolean online); @Delete("DELETE FROM device WHERE deviceId=#{deviceId}") int del(String deviceId); @@ -217,28 +225,28 @@ public interface DeviceMapper { "geoCoordSys," + "treeType," + "online" + - " FROM device WHERE ip = #{host} AND port=${port}") + " FROM device WHERE ip = #{host} AND port=#{port}") Device getDeviceByHostAndPort(String host, int port); @Update(value = {" "}) int updateCustom(Device device); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java index 616b1b742..358836c41 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMobilePositionMapper.java @@ -9,7 +9,7 @@ import org.apache.ibatis.annotations.*; public interface DeviceMobilePositionMapper { @Insert("INSERT INTO device_mobile_position (deviceId,channelId, deviceName, time, longitude, latitude, altitude, speed, direction, reportSource, longitudeGcj02, latitudeGcj02, longitudeWgs84, latitudeWgs84, createTime) " + - "VALUES ('${deviceId}','${channelId}', '${deviceName}', '${time}', ${longitude}, ${latitude}, ${altitude}, ${speed}, ${direction}, '${reportSource}', ${longitudeGcj02}, ${latitudeGcj02}, ${longitudeWgs84}, ${latitudeWgs84}, '${createTime}')") + "VALUES (#{deviceId},#{channelId}, #{deviceName}, #{time}, #{longitude}, #{latitude}, #{altitude}, #{speed}, #{direction}, #{reportSource}, #{longitudeGcj02}, #{latitudeGcj02}, #{longitudeWgs84}, #{latitudeWgs84}, #{createTime})") int insertNewPosition(MobilePosition mobilePosition); @Select(value = {" ") @@ -71,7 +71,7 @@ public interface GbStreamMapper { @Select("SELECT gs.*, pgs.platformId as platformId, pgs.catalogId as catalogId FROM gb_stream gs " + "LEFT JOIN platform_gb_stream pgs ON gs.gbStreamId = pgs.gbStreamId " + - "WHERE gs.gbId = '${gbId}' AND pgs.platformId = '${platformId}'") + "WHERE gs.gbId = #{gbId} AND pgs.platformId = #{platformId}") GbStream queryStreamInPlatform(String platformId, String gbId); @Select("") @Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId") @@ -134,7 +134,7 @@ public interface GbStreamMapper { "" + " UPDATE" + " gb_stream" + - " SET longitude=${item.lng}, latitude=${item.lat} " + + " SET longitude=#{item.lng}, latitude=#{item.lat} " + "WHERE gbId=#{item.id}"+ "" + ""}) diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/LogMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/LogMapper.java index 9716c75a8..fb1b4e30a 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/LogMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/LogMapper.java @@ -18,16 +18,16 @@ import java.util.List; public interface LogMapper { @Insert("insert into log ( name, type, uri, address, result, timing, username, createTime) " + - "values ('${name}', '${type}', '${uri}', '${address}', '${result}', ${timing}, '${username}', '${createTime}')") + "values (#{name}, #{type}, #{uri}, #{address}, #{result}, #{timing}, #{username}, #{createTime})") int add(LogDto logDto); @Select(value = {""}) List query(String query, String type, String startTime, String endTime); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java index e9254a563..97e74ae84 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java @@ -35,92 +35,92 @@ public interface MediaServerMapper { "hookAliveInterval" + ") VALUES " + "(" + - "'${id}', " + - "'${ip}', " + - "'${hookIp}', " + - "'${sdpIp}', " + - "'${streamIp}', " + - "${httpPort}, " + - "${httpSSlPort}, " + - "${rtmpPort}, " + - "${rtmpSSlPort}, " + - "${rtpProxyPort}, " + - "${rtspPort}, " + - "${rtspSSLPort}, " + - "${autoConfig}, " + - "'${secret}', " + - "${rtpEnable}, " + - "'${rtpPortRange}', " + - "${recordAssistPort}, " + - "${defaultServer}, " + - "'${createTime}', " + - "'${updateTime}', " + - "${hookAliveInterval})") + "#{id}, " + + "#{ip}, " + + "#{hookIp}, " + + "#{sdpIp}, " + + "#{streamIp}, " + + "#{httpPort}, " + + "#{httpSSlPort}, " + + "#{rtmpPort}, " + + "#{rtmpSSlPort}, " + + "#{rtpProxyPort}, " + + "#{rtspPort}, " + + "#{rtspSSLPort}, " + + "#{autoConfig}, " + + "#{secret}, " + + "#{rtpEnable}, " + + "#{rtpPortRange}, " + + "#{recordAssistPort}, " + + "#{defaultServer}, " + + "#{createTime}, " + + "#{updateTime}, " + + "#{hookAliveInterval})") int add(MediaServerItem mediaServerItem); @Update(value = {" "}) int update(MediaServerItem mediaServerItem); @Update(value = {" "}) int updateByHostAndPort(MediaServerItem mediaServerItem); - @Select("SELECT * FROM media_server WHERE id='${id}'") + @Select("SELECT * FROM media_server WHERE id=#{id}") MediaServerItem queryOne(String id); @Select("SELECT * FROM media_server") List queryAll(); - @Delete("DELETE FROM media_server WHERE id='${id}'") + @Delete("DELETE FROM media_server WHERE id=#{id}") void delOne(String id); - @Select("DELETE FROM media_server WHERE ip='${host}' and httpPort=${port}") + @Select("DELETE FROM media_server WHERE ip=#{host} and httpPort=#{port}") void delOneByIPAndPort(String host, int port); @Delete("DELETE FROM media_server WHERE defaultServer=1") int delDefault(); - @Select("SELECT * FROM media_server WHERE ip='${host}' and httpPort=${port}") + @Select("SELECT * FROM media_server WHERE ip=#{host} and httpPort=#{port}") MediaServerItem queryOneByHostAndPort(String host, int port); @Select("SELECT * FROM media_server WHERE defaultServer=1") diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java index 554354a8c..52025eb53 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java @@ -17,9 +17,9 @@ public interface ParentPlatformMapper { @Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp, " + " devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, " + " status, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime, treeType) " + - " VALUES (${enable}, '${name}', '${serverGBId}', '${serverGBDomain}', '${serverIP}', ${serverPort}, '${deviceGBId}', '${deviceIp}', " + - " '${devicePort}', '${username}', '${password}', '${expires}', '${keepTimeout}', '${transport}', '${characterSet}', ${ptz}, ${rtcp}, " + - " ${status}, ${startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{treeType})") + " VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIP}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " + + " #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, " + + " #{status}, #{startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{treeType})") int addParentPlatform(ParentPlatform parentPlatform); @Update("UPDATE parent_platform " + @@ -41,7 +41,7 @@ public interface ParentPlatformMapper { "ptz=#{ptz}, " + "rtcp=#{rtcp}, " + "status=#{status}, " + - "startOfflinePush=${startOfflinePush}, " + + "startOfflinePush=#{startOfflinePush}, " + "catalogGroup=#{catalogGroup}, " + "administrativeDivision=#{administrativeDivision}, " + "createTime=#{createTime}, " + diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java index 120ecb3e4..b98b9485c 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java @@ -21,22 +21,22 @@ public interface PlatformChannelMapper { * 查询列表里已经关联的 */ @Select("") List findChannelRelatedPlatform(String platformId, List channelReduces); @Insert("") int addChannels(String platformId, List channelReducesToAdd); @Delete("") int delChannelForGB(String platformId, List channelReducesToDel); @@ -50,14 +50,14 @@ public interface PlatformChannelMapper { int delChannelForDeviceId(String deviceId); @Delete("") int cleanChannelForGB(String platformId); - @Select("SELECT dc.* FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE dc.channelId='${channelId}' and pgc.platformId='${platformId}'") + @Select("SELECT dc.* FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE dc.channelId=#{channelId} and pgc.platformId=#{platformId}") List queryChannelInParentPlatform(String platformId, String channelId); - @Select("SELECT dc.* FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE pgc.platformId='${platformId}' and pgc.catalogId=#{catalogId}") + @Select("SELECT dc.* FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}") List queryAllChannelInCatalog(String platformId, String catalogId); @Select(" select dc.channelId as id, dc.name as name, pgc.platformId as platformId, pgc.catalogId as parentId, 0 as childrenCount, 1 as type " + diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformGbStreamMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformGbStreamMapper.java index 13094b98d..91a4a5f45 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformGbStreamMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformGbStreamMapper.java @@ -26,7 +26,7 @@ public interface PlatformGbStreamMapper { "(gbStreamId, platformId, catalogId) " + "values " + " " + - "(${item.gbStreamId}, '${item.platformId}', '${item.catalogId}')" + + "(#{item.gbStreamId}, #{item.platformId}, #{item.catalogId})" + " " + "") int batchAdd(List streamPushItems); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/RecordInfoDao.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/RecordInfoDao.java index 2d73982c0..a784472f6 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/RecordInfoDao.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/RecordInfoDao.java @@ -14,10 +14,10 @@ import java.util.List; public interface RecordInfoDao { @Insert("INSERT INTO recordInfo (app, stream, mediaServerId, createTime, type, deviceId, channelId, name) VALUES" + - "('${app}', '${stream}', '${mediaServerId}', datetime('now','localtime')), '${type}', '${deviceId}', '${channelId}', '${name}'") + "(#{app}, #{stream}, #{mediaServerId}, datetime('now','localtime')), #{type}, #{deviceId}, #{channelId}, #{name}") int add(RecordInfo recordInfo); - @Delete("DELETE FROM user WHERE createTime < '${beforeTime}'") + @Delete("DELETE FROM user WHERE createTime < #{beforeTime}") int deleteBefore(String beforeTime); @Select("select * FROM recordInfo") diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/RoleMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/RoleMapper.java index 66a60b95d..425f5e426 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/RoleMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/RoleMapper.java @@ -12,14 +12,14 @@ import java.util.List; public interface RoleMapper { @Insert("INSERT INTO user_role (name, authority, createTime, updateTime) VALUES" + - "('${name}', '${authority}', '${createTime}', '${updateTime}')") + "(#{name}, #{authority}, #{createTime}, #{updateTime})") int add(Role role); @Update(value = {" "}) int update(Role role); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java index 4ed214dac..5dbd8f04b 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java @@ -13,9 +13,9 @@ public interface StreamProxyMapper { @Insert("INSERT INTO stream_proxy (type, name, app, stream,mediaServerId, url, src_url, dst_url, " + "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_audio, enable_mp4, enable, status, enable_remove_none_reader, enable_disable_none_reader, createTime) VALUES" + - "('${type}','${name}', '${app}', '${stream}', '${mediaServerId}','${url}', '${src_url}', '${dst_url}', " + - "'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_audio}, ${enable_mp4}, ${enable}, ${status}, " + - "${enable_remove_none_reader}, ${enable_disable_none_reader}, '${createTime}' )") + "(#{type}, #{name}, #{app}, #{stream}, #{mediaServerId}, #{url}, #{src_url}, #{dst_url}, " + + "#{timeout_ms}, #{ffmpeg_cmd_key}, #{rtp_type}, #{enable_audio}, #{enable_mp4}, #{enable}, #{status}, " + + "#{enable_remove_none_reader}, #{enable_disable_none_reader}, #{createTime} )") int add(StreamProxyItem streamProxyDto); @Update("UPDATE stream_proxy " + @@ -45,7 +45,7 @@ public interface StreamProxyMapper { @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream order by st.createTime desc") List selectAll(); - @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream WHERE st.enable=${enable} order by st.createTime desc") + @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream WHERE st.enable=#{enable} order by st.createTime desc") List selectForEnable(boolean enable); @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream WHERE st.app=#{app} AND st.stream=#{stream} order by st.createTime desc") @@ -53,12 +53,12 @@ public interface StreamProxyMapper { @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st " + "LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream " + - "WHERE st.enable=${enable} and st.mediaServerId = #{id} order by st.createTime desc") + "WHERE st.enable=#{enable} and st.mediaServerId = #{id} order by st.createTime desc") List selectForEnableInMediaServer(String id, boolean enable); @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st " + "LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream " + - "WHERE st.mediaServerId = '${id}' order by st.createTime desc") + "WHERE st.mediaServerId = #{id} order by st.createTime desc") List selectInMediaServer(String id); @Update("UPDATE stream_proxy " + @@ -67,7 +67,7 @@ public interface StreamProxyMapper { void updateStatusByMediaServerId(String mediaServerId, boolean status); @Update("UPDATE stream_proxy " + - "SET status=${status} " + + "SET status=#{status} " + "WHERE app=#{app} AND stream=#{stream}") int updateStatus(String app, String stream, boolean status); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java index ec51f1126..492dfe38c 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java @@ -17,23 +17,23 @@ public interface StreamPushMapper { @Insert("INSERT INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " + "pushTime, aliveSecond, mediaServerId, serverId, updateTime, createTime, pushIng, self) VALUES" + - "('${app}', '${stream}', '${totalReaderCount}', '${originType}', '${originTypeStr}', " + - "'${pushTime}', '${aliveSecond}', '${mediaServerId}' , '${serverId}' , '${updateTime}' , '${createTime}', " + - "${pushIng}, ${self} )") + "(#{app}, #{stream}, #{totalReaderCount}, #{originType}, #{originTypeStr}, " + + "#{pushTime}, #{aliveSecond}, #{mediaServerId} , #{serverId} , #{updateTime} , #{createTime}, " + + "#{pushIng}, #{self} )") int add(StreamPushItem streamPushItem); @Update(value = {" "}) int update(StreamPushItem streamPushItem); @@ -76,7 +76,7 @@ public interface StreamPushMapper { "on st.app = gs.app AND st.stream = gs.stream " + "WHERE " + "1=1 " + - " AND (st.app LIKE '%${query}%' OR st.stream LIKE '%${query}%' OR gs.gbId LIKE '%${query}%' OR gs.name LIKE '%${query}%') " + + " AND (st.app LIKE concat('%',#{query},'%') OR st.stream LIKE concat('%',#{query},'%') OR gs.gbId LIKE concat('%',#{query},'%') OR gs.name LIKE concat('%',#{query},'%')) " + " AND (gs.gbId is null OR st.pushIng=1)" + " AND (st.pushIng is null OR st.pushIng=0) " + " AND st.mediaServerId=#{mediaServerId} " + @@ -94,9 +94,9 @@ public interface StreamPushMapper { "Insert IGNORE INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " + "createTime, aliveSecond, mediaServerId, status, pushIng) " + "VALUES " + - "( '${item.app}', '${item.stream}', '${item.totalReaderCount}', #{item.originType}, " + - "'${item.originTypeStr}',#{item.createTime}, #{item.aliveSecond}, '${item.mediaServerId}', ${item.status} ," + - " ${item.pushIng} )" + + "( #{item.app}, #{item.stream}, #{item.totalReaderCount}, #{item.originType}, " + + "#{item.originTypeStr},#{item.createTime}, #{item.aliveSecond}, #{item.mediaServerId}, #{item.status} ," + + " #{item.pushIng} )" + " " + "") @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id") @@ -115,12 +115,12 @@ public interface StreamPushMapper { List selectAllByMediaServerIdWithOutGbID(String mediaServerId); @Update("UPDATE stream_push " + - "SET status=${status} " + + "SET status=#{status} " + "WHERE app=#{app} AND stream=#{stream}") int updateStatus(String app, String stream, boolean status); @Update("UPDATE stream_push " + - "SET pushIng=${pushIng} " + + "SET pushIng=#{pushIng} " + "WHERE app=#{app} AND stream=#{stream}") int updatePushStatus(String app, String stream, boolean pushIng); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/UserMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/UserMapper.java index c7a44fd2c..ecaa165aa 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/UserMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/UserMapper.java @@ -11,16 +11,16 @@ import java.util.List; public interface UserMapper { @Insert("INSERT INTO user (username, password, roleId, pushKey, createTime, updateTime) VALUES" + - "('${username}', '${password}', '${role.id}', '${pushKey}', '${createTime}', '${updateTime}')") + "(#{username}, #{password}, #{role.id}, #{pushKey}, #{createTime}, #{updateTime})") int add(User user); @Update(value = {" "}) int update(User user); @@ -50,10 +50,10 @@ public interface UserMapper { @ResultMap(value="roleMap") List selectAll(); - @Select("select * from (select user.*, concat('${callId}_', pushKey) as str1 from user) as u where md5(u.str1) = '${sign}'") + @Select("select * from (select user.*, concat(concat(#{callId}, '_'), pushKey) as str1 from user) as u where md5(u.str1) = #{sign}") List checkPushAuthorityByCallIdAndSign(String callId, String sign); - @Select("select * from user where md5(pushKey) = '${sign}'") + @Select("select * from user where md5(pushKey) = #{sign}") List checkPushAuthorityByCallId(String sign); @Select("select u.id, u.username,u.pushKey,u.roleId, r.id as roleID, r.name as roleName, r.authority as roleAuthority , r.createTime as roleCreateTime , r.updateTime as roleUpdateTime FROM user u join user_role r on u.roleId=r.id") diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java index e8997cba5..139f018cb 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java @@ -224,31 +224,31 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { PageHelper.startPage(page, count); List all; if (catalogUnderDevice != null && catalogUnderDevice) { - all = deviceChannelMapper.queryChannels(deviceId, deviceId, query, hasSubChannel, online); + all = deviceChannelMapper.queryChannels(deviceId, deviceId, query, hasSubChannel, online,null); // 海康设备的parentId是SIP id - List deviceChannels = deviceChannelMapper.queryChannels(deviceId, sipConfig.getId(), query, hasSubChannel, online); + List deviceChannels = deviceChannelMapper.queryChannels(deviceId, sipConfig.getId(), query, hasSubChannel, online,null); all.addAll(deviceChannels); }else { - all = deviceChannelMapper.queryChannels(deviceId, null, query, hasSubChannel, online); + all = deviceChannelMapper.queryChannels(deviceId, null, query, hasSubChannel, online,null); } return new PageInfo<>(all); } @Override - public List queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit) { - return deviceChannelMapper.queryChannelsByDeviceIdWithStartAndLimit(deviceId, null, query, hasSubChannel, online, start, limit); + public List queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit,List channelIds) { + return deviceChannelMapper.queryChannelsByDeviceIdWithStartAndLimit(deviceId, null, query, hasSubChannel, online, start, limit,channelIds); } @Override - public List queryChannelsByDeviceId(String deviceId) { - return deviceChannelMapper.queryChannels(deviceId, null,null, null, null); + public List queryChannelsByDeviceId(String deviceId,Boolean online,List channelIds) { + return deviceChannelMapper.queryChannels(deviceId, null,null, null, online,channelIds); } @Override public PageInfo querySubChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online, int page, int count) { PageHelper.startPage(page, count); - List all = deviceChannelMapper.queryChannels(deviceId, parentChannelId, query, hasSubChannel, online); + List all = deviceChannelMapper.queryChannels(deviceId, parentChannelId, query, hasSubChannel, online,null); return new PageInfo<>(all); } @@ -271,9 +271,9 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { * @return PageInfo 分页设备对象数组 */ @Override - public PageInfo queryVideoDeviceList(int page, int count) { + public PageInfo queryVideoDeviceList(int page, int count,Boolean online) { PageHelper.startPage(page, count); - List all = deviceMapper.getDevices(); + List all = deviceMapper.getDevices(online); return new PageInfo<>(all); } @@ -283,9 +283,9 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { * @return List 设备对象数组 */ @Override - public List queryVideoDeviceList() { + public List queryVideoDeviceList(Boolean online) { - List deviceList = deviceMapper.getDevices(); + List deviceList = deviceMapper.getDevices(online); return deviceList; } diff --git a/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java b/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java index 3b4bec4c7..50152cda5 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/redis/RedisUtil.java @@ -1,14 +1,13 @@ package com.genersoft.iot.vmp.utils.redis; -import java.util.*; -import java.util.concurrent.TimeUnit; - import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.utils.SpringBeanFactory; -import gov.nist.javax.sip.stack.UDPMessageChannel; import org.springframework.data.redis.core.*; import org.springframework.util.CollectionUtils; +import java.util.*; +import java.util.concurrent.TimeUnit; + /** * Redis工具类 * @author swwheihei diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/ErrorCode.java b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/ErrorCode.java index b5fe8fb4d..7e2b5120e 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/ErrorCode.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/ErrorCode.java @@ -1,7 +1,5 @@ package com.genersoft.iot.vmp.vmanager.bean; -import io.swagger.v3.oas.annotations.media.Schema; - /** * 全局错误码 */ @@ -9,6 +7,7 @@ public enum ErrorCode { SUCCESS(0, "成功"), ERROR100(100, "失败"), ERROR400(400, "参数不全或者错误"), + ERROR404(404, "资源未找到"), ERROR403(403, "无权限操作"), ERROR401(401, "请登录后重新请求"), ERROR500(500, "系统异常"); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java new file mode 100644 index 000000000..e7c24aae1 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java @@ -0,0 +1,358 @@ +package com.genersoft.iot.vmp.vmanager.bean; + +import com.genersoft.iot.vmp.common.StreamInfo; + +public class StreamContent { + + private String app; + private String stream; + + private String ip; + + private String flv; + + private String https_flv; + private String ws_flv; + private String wss_flv; + private String fmp4; + private String https_fmp4; + private String ws_fmp4; + private String wss_fmp4; + private String hls; + private String https_hls; + private String ws_hls; + private String wss_hls; + private String ts; + private String https_ts; + private String ws_ts; + private String wss_ts; + private String rtmp; + private String rtmps; + private String rtsp; + private String rtsps; + private String rtc; + + private String rtcs; + private String mediaServerId; + private Object tracks; + + private String startTime; + + private String endTime; + + private double progress; + + public StreamContent(StreamInfo streamInfo) { + if (streamInfo == null) { + return; + } + this.app = streamInfo.getApp(); + this.stream = streamInfo.getStream(); + if (streamInfo.getFlv() != null) { + this.flv = streamInfo.getFlv().getUrl(); + } + if (streamInfo.getHttps_flv() != null) { + this.https_flv = streamInfo.getHttps_flv().getUrl(); + } + if (streamInfo.getWs_flv() != null) { + this.ws_flv = streamInfo.getWs_flv().getUrl(); + } + if (streamInfo.getWss_flv() != null) { + this.wss_flv = streamInfo.getWss_flv().getUrl(); + } + if (streamInfo.getFmp4() != null) { + this.fmp4 = streamInfo.getFmp4().getUrl(); + } + if (streamInfo.getWs_fmp4() != null) { + this.ws_fmp4 = streamInfo.getWs_fmp4().getUrl(); + } + if (streamInfo.getWss_fmp4() != null) { + this.wss_fmp4 = streamInfo.getWss_fmp4().getUrl(); + } + if (streamInfo.getHls() != null) { + this.hls = streamInfo.getHls().getUrl(); + } + if (streamInfo.getHttps_hls() != null) { + this.https_hls = streamInfo.getHttps_hls().getUrl(); + } + if (streamInfo.getWs_hls() != null) { + this.ws_hls = streamInfo.getWs_hls().getUrl(); + } + if (streamInfo.getWss_hls() != null) { + this.wss_hls = streamInfo.getWss_hls().getUrl(); + } + if (streamInfo.getTs() != null) { + this.ts = streamInfo.getTs().getUrl(); + } + if (streamInfo.getHttps_ts() != null) { + this.https_ts = streamInfo.getHttps_ts().getUrl(); + } + if (streamInfo.getWs_ts() != null) { + this.ws_ts = streamInfo.getWs_ts().getUrl(); + } + if (streamInfo.getRtmp() != null) { + this.rtmp = streamInfo.getRtmp().getUrl(); + } + if (streamInfo.getRtmps() != null) { + this.rtmps = streamInfo.getRtmps().getUrl(); + } + if (streamInfo.getRtsp() != null) { + this.rtsp = streamInfo.getRtsp().getUrl(); + } + if (streamInfo.getRtsps() != null) { + this.rtsps = streamInfo.getRtsps().getUrl(); + } + if (streamInfo.getRtc() != null) { + this.rtc = streamInfo.getRtc().getUrl(); + } + if (streamInfo.getRtcs() != null) { + this.rtcs = streamInfo.getRtcs().getUrl(); + } + + this.mediaServerId = streamInfo.getMediaServerId(); + this.tracks = streamInfo.getTracks(); + this.startTime = streamInfo.getStartTime(); + this.endTime = streamInfo.getEndTime(); + this.progress = streamInfo.getProgress(); + } + + public String getApp() { + return app; + } + + public void setApp(String app) { + this.app = app; + } + + public String getStream() { + return stream; + } + + public void setStream(String stream) { + this.stream = stream; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getFlv() { + return flv; + } + + public void setFlv(String flv) { + this.flv = flv; + } + + public String getHttps_flv() { + return https_flv; + } + + public void setHttps_flv(String https_flv) { + this.https_flv = https_flv; + } + + public String getWs_flv() { + return ws_flv; + } + + public void setWs_flv(String ws_flv) { + this.ws_flv = ws_flv; + } + + public String getWss_flv() { + return wss_flv; + } + + public void setWss_flv(String wss_flv) { + this.wss_flv = wss_flv; + } + + public String getFmp4() { + return fmp4; + } + + public void setFmp4(String fmp4) { + this.fmp4 = fmp4; + } + + public String getHttps_fmp4() { + return https_fmp4; + } + + public void setHttps_fmp4(String https_fmp4) { + this.https_fmp4 = https_fmp4; + } + + public String getWs_fmp4() { + return ws_fmp4; + } + + public void setWs_fmp4(String ws_fmp4) { + this.ws_fmp4 = ws_fmp4; + } + + public String getWss_fmp4() { + return wss_fmp4; + } + + public void setWss_fmp4(String wss_fmp4) { + this.wss_fmp4 = wss_fmp4; + } + + public String getHls() { + return hls; + } + + public void setHls(String hls) { + this.hls = hls; + } + + public String getHttps_hls() { + return https_hls; + } + + public void setHttps_hls(String https_hls) { + this.https_hls = https_hls; + } + + public String getWs_hls() { + return ws_hls; + } + + public void setWs_hls(String ws_hls) { + this.ws_hls = ws_hls; + } + + public String getWss_hls() { + return wss_hls; + } + + public void setWss_hls(String wss_hls) { + this.wss_hls = wss_hls; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + + public String getHttps_ts() { + return https_ts; + } + + public void setHttps_ts(String https_ts) { + this.https_ts = https_ts; + } + + public String getWs_ts() { + return ws_ts; + } + + public void setWs_ts(String ws_ts) { + this.ws_ts = ws_ts; + } + + public String getWss_ts() { + return wss_ts; + } + + public void setWss_ts(String wss_ts) { + this.wss_ts = wss_ts; + } + + public String getRtmp() { + return rtmp; + } + + public void setRtmp(String rtmp) { + this.rtmp = rtmp; + } + + public String getRtmps() { + return rtmps; + } + + public void setRtmps(String rtmps) { + this.rtmps = rtmps; + } + + public String getRtsp() { + return rtsp; + } + + public void setRtsp(String rtsp) { + this.rtsp = rtsp; + } + + public String getRtsps() { + return rtsps; + } + + public void setRtsps(String rtsps) { + this.rtsps = rtsps; + } + + public String getRtc() { + return rtc; + } + + public void setRtc(String rtc) { + this.rtc = rtc; + } + + public String getRtcs() { + return rtcs; + } + + public void setRtcs(String rtcs) { + this.rtcs = rtcs; + } + + public String getMediaServerId() { + return mediaServerId; + } + + public void setMediaServerId(String mediaServerId) { + this.mediaServerId = mediaServerId; + } + + public Object getTracks() { + return tracks; + } + + public void setTracks(Object tracks) { + this.tracks = tracks; + } + + public String getStartTime() { + return startTime; + } + + public void setStartTime(String startTime) { + this.startTime = startTime; + } + + public String getEndTime() { + return endTime; + } + + public void setEndTime(String endTime) { + this.endTime = endTime; + } + + public double getProgress() { + return progress; + } + + public void setProgress(double progress) { + this.progress = progress; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java index 5dc0f0395..18618e74f 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java @@ -14,7 +14,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; - import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -22,10 +21,8 @@ import io.swagger.v3.oas.annotations.tags.Tag; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; @@ -130,15 +127,14 @@ public class DeviceControl { */ @Operation(summary = "布防/撤防命令") @Parameter(name = "deviceId", description = "设备国标编号", required = true) - @Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "guardCmdStr", description = "命令, 可选值:SetGuard(布防),ResetGuard(撤防)", required = true) @GetMapping("/guard/{deviceId}/{guardCmdStr}") - public DeferredResult guardApi(@PathVariable String deviceId, String channelId, @PathVariable String guardCmdStr) { + public DeferredResult guardApi(@PathVariable String deviceId, @PathVariable String guardCmdStr) { if (logger.isDebugEnabled()) { logger.debug("布防/撤防API调用"); } Device device = storager.queryVideoDevice(deviceId); - String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId; + String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + deviceId; String uuid =UUID.randomUUID().toString(); try { cmder.guardCmd(device, guardCmdStr, event -> { diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java index d4694c524..11bc6211a 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java @@ -99,7 +99,7 @@ public class DeviceQuery { @GetMapping("/devices") public PageInfo devices(int page, int count){ - return storager.queryVideoDeviceList(page, count); + return storager.queryVideoDeviceList(page, count,null); } /** diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java index 7e73e0582..d135fa2f3 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java @@ -5,11 +5,11 @@ import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.security.SecurityUtils; import com.genersoft.iot.vmp.conf.security.dto.LoginUser; import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; -import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.service.IMediaService; +import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; +import com.genersoft.iot.vmp.vmanager.bean.StreamContent; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -53,11 +53,11 @@ public class MediaController { @Parameter(name = "useSourceIpAsStreamIp", description = "是否使用请求IP作为返回的地址IP") @GetMapping(value = "/stream_info_by_app_and_stream") @ResponseBody - public StreamInfo getStreamInfoByAppAndStream(HttpServletRequest request, @RequestParam String app, - @RequestParam String stream, - @RequestParam(required = false) String mediaServerId, - @RequestParam(required = false) String callId, - @RequestParam(required = false) Boolean useSourceIpAsStreamIp){ + public StreamContent getStreamInfoByAppAndStream(HttpServletRequest request, @RequestParam String app, + @RequestParam String stream, + @RequestParam(required = false) String mediaServerId, + @RequestParam(required = false) String callId, + @RequestParam(required = false) Boolean useSourceIpAsStreamIp){ boolean authority = false; if (callId != null) { // 权限校验 @@ -88,9 +88,8 @@ public class MediaController { streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority); } - WVPResult result = new WVPResult<>(); if (streamInfo != null){ - return streamInfo; + return new StreamContent(streamInfo); }else { //获取流失败,重启拉流后重试一次 streamProxyService.stop(app,stream); @@ -109,7 +108,7 @@ public class MediaController { streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority); } if (streamInfo != null){ - return streamInfo; + return new StreamContent(streamInfo); }else { throw new ControllerException(ErrorCode.ERROR100); } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java index 19b2adc6f..99fa4c131 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java @@ -22,6 +22,7 @@ import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx; import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; +import com.genersoft.iot.vmp.vmanager.bean.StreamContent; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -85,8 +86,8 @@ public class PlayController { @Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true) @GetMapping("/start/{deviceId}/{channelId}") - public DeferredResult> play(HttpServletRequest request, @PathVariable String deviceId, - @PathVariable String channelId) { + public DeferredResult> play(HttpServletRequest request, @PathVariable String deviceId, + @PathVariable String channelId) { // 获取可用的zlm Device device = storager.queryVideoDevice(deviceId); @@ -98,8 +99,8 @@ public class PlayController { msg.setKey(key); String uuid = UUID.randomUUID().toString(); msg.setId(uuid); - DeferredResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); - DeferredResultEx> deferredResultEx = new DeferredResultEx<>(result); + DeferredResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); + DeferredResultEx> deferredResultEx = new DeferredResultEx<>(result); result.onTimeout(()->{ logger.info("点播接口等待超时"); @@ -110,25 +111,22 @@ public class PlayController { msg.setData(wvpResult); resultHolder.invokeResult(msg); }); - - if (userSetting.getUseSourceIpAsStreamIp()) { - // TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误 - deferredResultEx.setFilter(result1 -> { - WVPResult wvpResult1 = (WVPResult)result1; - WVPResult clone = null; - try { - clone = (WVPResult)wvpResult1.clone(); - } catch (CloneNotSupportedException e) { - throw new RuntimeException(e); - } - if (clone.getCode() == ErrorCode.SUCCESS.getCode()) { - StreamInfo data = clone.getData().clone(); + // TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误 + deferredResultEx.setFilter(result1 -> { + WVPResult wvpResult1 = (WVPResult)result1; + WVPResult resultStream = new WVPResult<>(); + resultStream.setCode(wvpResult1.getCode()); + resultStream.setMsg(wvpResult1.getMsg()); + if (wvpResult1.getCode() == ErrorCode.SUCCESS.getCode()) { + StreamInfo data = wvpResult1.getData().clone(); + if (userSetting.getUseSourceIpAsStreamIp()) { data.channgeStreamIp(request.getLocalName()); - clone.setData(data); } - return clone; - }); - } + resultStream.setData(new StreamContent(wvpResult1.getData())); + } + return resultStream; + }); + // 录像查询以channelId作为deviceId查询 resultHolder.put(key, uuid, deferredResultEx); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java index 696fae0ed..511b98d5e 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; +import com.genersoft.iot.vmp.vmanager.bean.StreamContent; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -32,6 +33,7 @@ import org.springframework.web.context.request.async.DeferredResult; import javax.sip.InvalidArgumentException; import javax.sip.SipException; import java.text.ParseException; +import java.util.UUID; /** * @author lin @@ -68,24 +70,37 @@ public class PlaybackController { @Parameter(name = "startTime", description = "开始时间", required = true) @Parameter(name = "endTime", description = "结束时间", required = true) @GetMapping("/start/{deviceId}/{channelId}") - public DeferredResult> play(@PathVariable String deviceId, @PathVariable String channelId, - String startTime, String endTime) { + public DeferredResult> play(@PathVariable String deviceId, @PathVariable String channelId, + String startTime, String endTime) { if (logger.isDebugEnabled()) { logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId)); } + String uuid = UUID.randomUUID().toString(); + String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId; + DeferredResult> result = new DeferredResult<>(30000L); + resultHolder.put(key, uuid, result); - return playService.playBack(deviceId, channelId, startTime, endTime, null, + WVPResult wvpResult = new WVPResult<>(); + + RequestMessage msg = new RequestMessage(); + msg.setKey(key); + msg.setId(uuid); + + playService.playBack(deviceId, channelId, startTime, endTime, null, playBackResult->{ - if (playBackResult.getCode() != ErrorCode.SUCCESS.getCode()) { - RequestMessage data = playBackResult.getData(); - data.setData(WVPResult.fail(playBackResult.getCode(), playBackResult.getMsg())); - resultHolder.invokeResult(data); - }else { - resultHolder.invokeResult(playBackResult.getData()); + wvpResult.setCode(playBackResult.getCode()); + wvpResult.setMsg(playBackResult.getMsg()); + if (playBackResult.getCode() == ErrorCode.SUCCESS.getCode()) { + StreamInfo streamInfo = (StreamInfo)playBackResult.getData(); + wvpResult.setData(new StreamContent(streamInfo)); } + msg.setData(wvpResult); + resultHolder.invokeResult(msg); }); + + return result; } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java index 6625ba456..c3b9c7814 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; +import com.genersoft.iot.vmp.vmanager.bean.StreamContent; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import io.swagger.v3.oas.annotations.Operation; @@ -121,15 +122,33 @@ public class GBRecordController { @Parameter(name = "endTime", description = "结束时间", required = true) @Parameter(name = "downloadSpeed", description = "下载倍速", required = true) @GetMapping("/download/start/{deviceId}/{channelId}") - public DeferredResult> download(@PathVariable String deviceId, @PathVariable String channelId, + public DeferredResult> download(@PathVariable String deviceId, @PathVariable String channelId, String startTime, String endTime, String downloadSpeed) { if (logger.isDebugEnabled()) { logger.debug(String.format("历史媒体下载 API调用,deviceId:%s,channelId:%s,downloadSpeed:%s", deviceId, channelId, downloadSpeed)); } - DeferredResult> result = playService.download(deviceId, channelId, startTime, endTime, Integer.parseInt(downloadSpeed), null, hookCallBack->{ - resultHolder.invokeResult(hookCallBack.getData()); + String uuid = UUID.randomUUID().toString(); + String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId; + DeferredResult> result = new DeferredResult<>(30000L); + resultHolder.put(key, uuid, result); + RequestMessage msg = new RequestMessage(); + msg.setId(uuid); + msg.setKey(key); + + WVPResult wvpResult = new WVPResult<>(); + + playService.download(deviceId, channelId, startTime, endTime, Integer.parseInt(downloadSpeed), null, playBackResult->{ + + wvpResult.setCode(playBackResult.getCode()); + wvpResult.setMsg(playBackResult.getMsg()); + if (playBackResult.getCode() == ErrorCode.SUCCESS.getCode()) { + StreamInfo streamInfo = (StreamInfo)playBackResult.getData(); + wvpResult.setData(new StreamContent(streamInfo)); + } + msg.setData(wvpResult); + resultHolder.invokeResult(msg); }); return result; @@ -168,7 +187,11 @@ public class GBRecordController { @Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "stream", description = "流ID", required = true) @GetMapping("/download/progress/{deviceId}/{channelId}/{stream}") - public StreamInfo getProgress(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) { - return playService.getDownLoadInfo(deviceId, channelId, stream); + public StreamContent getProgress(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) { + StreamInfo downLoadInfo = playService.getDownLoadInfo(deviceId, channelId, stream); + if (downLoadInfo == null) { + throw new ControllerException(ErrorCode.ERROR404); + } + return new StreamContent(downLoadInfo); } } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java index d1368d818..65ec3d339 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java @@ -1,13 +1,13 @@ package com.genersoft.iot.vmp.vmanager.streamProxy; import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; +import com.genersoft.iot.vmp.vmanager.bean.StreamContent; import com.github.pagehelper.PageInfo; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -58,7 +58,7 @@ public class StreamProxyController { }) @PostMapping(value = "/save") @ResponseBody - public StreamInfo save(@RequestBody StreamProxyItem param){ + public StreamContent save(@RequestBody StreamProxyItem param){ logger.info("添加代理: " + JSONObject.toJSONString(param)); if (ObjectUtils.isEmpty(param.getMediaServerId())) { param.setMediaServerId("auto"); @@ -69,7 +69,7 @@ public class StreamProxyController { if (ObjectUtils.isEmpty(param.getGbId())) { param.setGbId(null); } - return streamProxyService.save(param); + return new StreamContent(streamProxyService.save(param)); } @GetMapping(value = "/ffmpeg_cmd/list") diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java index d0aff58e3..7506433f9 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java @@ -11,22 +11,16 @@ import com.genersoft.iot.vmp.conf.security.dto.LoginUser; import com.genersoft.iot.vmp.gb28181.bean.GbStream; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; -import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaService; import com.genersoft.iot.vmp.service.IStreamPushService; import com.genersoft.iot.vmp.service.impl.StreamPushUploadFileHandler; -import com.genersoft.iot.vmp.vmanager.bean.BatchGBStreamParam; -import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; -import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto; -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; +import com.genersoft.iot.vmp.vmanager.bean.*; import com.github.pagehelper.PageInfo; - import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import org.apache.poi.sl.usermodel.Sheet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -34,12 +28,10 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.util.ObjectUtils; -import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.multipart.MultipartFile; -import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; @@ -243,8 +235,8 @@ public class StreamPushController { @Parameter(name = "app", description = "应用名", required = true) @Parameter(name = "stream", description = "流id", required = true) @Parameter(name = "mediaServerId", description = "媒体服务器id") - public StreamInfo getPlayUrl(@RequestParam String app,@RequestParam String stream, - @RequestParam(required = false) String mediaServerId){ + public StreamContent getPlayUrl(@RequestParam String app, @RequestParam String stream, + @RequestParam(required = false) String mediaServerId){ boolean authority = false; // 是否登陆用户, 登陆用户返回完整信息 LoginUser userInfo = SecurityUtils.getUserInfo(); @@ -259,7 +251,7 @@ public class StreamPushController { if (streamInfo == null){ throw new ControllerException(ErrorCode.ERROR100.getCode(), "获取播放地址失败"); } - return streamInfo; + return new StreamContent(streamInfo); } /** diff --git a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java index 48dbbc449..e5f422728 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiDeviceController.java @@ -10,8 +10,10 @@ import com.github.pagehelper.PageInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; +import java.util.Arrays; import java.util.List; /** @@ -59,10 +61,10 @@ public class ApiDeviceController { JSONObject result = new JSONObject(); List devices; if (start == null || limit ==null) { - devices = storager.queryVideoDeviceList(); + devices = storager.queryVideoDeviceList(online); result.put("DeviceCount", devices.size()); }else { - PageInfo deviceList = storager.queryVideoDeviceList(start/limit, limit); + PageInfo deviceList = storager.queryVideoDeviceList(start/limit, limit,online); result.put("DeviceCount", deviceList.getTotal()); devices = deviceList.getList(); } @@ -94,6 +96,7 @@ public class ApiDeviceController { @RequestMapping(value = "/channellist") public JSONObject channellist( String serial, + @RequestParam(required = false)String code, @RequestParam(required = false)String channel_type, @RequestParam(required = false)String dir_serial , @RequestParam(required = false)Integer start, @@ -113,12 +116,17 @@ public class ApiDeviceController { return result; } List deviceChannels; - List allDeviceChannelList = storager.queryChannelsByDeviceId(serial); + List channelIds = null; + if (!StringUtils.isEmpty(code)) { + String[] split = code.trim().split(","); + channelIds = Arrays.asList(split); + } + List allDeviceChannelList = storager.queryChannelsByDeviceId(serial,online,channelIds); if (start == null || limit ==null) { deviceChannels = allDeviceChannelList; result.put("ChannelCount", deviceChannels.size()); }else { - deviceChannels = storager.queryChannelsByDeviceIdWithStartAndLimit(serial, null, null, null,start, limit); + deviceChannels = storager.queryChannelsByDeviceIdWithStartAndLimit(serial, null, null, online,start, limit,channelIds); int total = allDeviceChannelList.size(); result.put("ChannelCount", total); } @@ -148,9 +156,9 @@ public class ApiDeviceController { // 1-IETF RFC3261, // 2-基于口令的双向认证, // 3-基于数字证书的双向认证 - deviceJOSNChannel.put("Status", deviceChannel.getStatus()); - deviceJOSNChannel.put("Longitude", deviceChannel.getLongitudeWgs84()); - deviceJOSNChannel.put("Latitude", deviceChannel.getLatitudeWgs84()); + deviceJOSNChannel.put("Status", deviceChannel.getStatus() == 1 ? "ON":"OFF"); + deviceJOSNChannel.put("Longitude", deviceChannel.getLongitude()); + deviceJOSNChannel.put("Latitude", deviceChannel.getLatitude()); deviceJOSNChannel.put("PTZType ", deviceChannel.getPTZType()); // 云台类型, 0 - 未知, 1 - 球机, 2 - 半球, // 3 - 固定枪机, 4 - 遥控枪机 deviceJOSNChannel.put("CustomPTZType", ""); diff --git a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java index ab769f5bb..5381a3aec 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java @@ -12,7 +12,6 @@ import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; -import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -120,12 +119,12 @@ public class ApiStreamController { result.put("ChannelID", code); result.put("ChannelName", deviceChannel.getName()); result.put("ChannelCustomName", ""); - result.put("FLV", streamInfo.getFlv()); - result.put("WS_FLV", streamInfo.getWs_flv()); - result.put("RTMP", streamInfo.getRtmp()); - result.put("HLS", streamInfo.getHls()); - result.put("RTSP", streamInfo.getRtsp()); - result.put("WEBRTC", streamInfo.getRtc()); + result.put("FLV", streamInfo.getFlv().getUrl()); + result.put("WS_FLV", streamInfo.getWs_flv().getUrl()); + result.put("RTMP", streamInfo.getRtmp().getUrl()); + result.put("HLS", streamInfo.getHls().getUrl()); + result.put("RTSP", streamInfo.getRtsp().getUrl()); + result.put("WEBRTC", streamInfo.getRtc().getUrl()); result.put("CDN", ""); result.put("SnapURL", ""); result.put("Transport", device.getTransport()); diff --git a/src/main/resources/all-application.yml b/src/main/resources/all-application.yml index bd2038d3a..052fa7442 100644 --- a/src/main/resources/all-application.yml +++ b/src/main/resources/all-application.yml @@ -168,7 +168,7 @@ user-settings: # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认) save-position-history: false # 点播等待超时时间,单位:毫秒 - play-timeout: 3000 + play-timeout: 18000 # 上级点播等待超时时间,单位:毫秒 platform-play-timeout: 60000 # 是否开启接口鉴权 @@ -186,7 +186,7 @@ user-settings: use-pushing-as-status: true # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启 use-source-ip-as-stream-ip: true - # 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放 + # 国标点播 按需拉流, true:有人观看拉流,无人观看释放, false:拉起后不自动释放 stream-on-demand: true # 推流鉴权, 默认开启 push-authority: true @@ -195,6 +195,10 @@ user-settings: gb-send-stream-strict: false # 设备上线时是否自动同步通道 sync-channel-on-device-online: false + # 是否使用设备来源Ip作为回复IP, 不设置则为 false + sip-use-source-ip-as-remote-address: false + # 是否开启sip日志 + sip-log: true # 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流 push-stream-after-ack: false diff --git a/web_src/src/components/CloudRecordDetail.vue b/web_src/src/components/CloudRecordDetail.vue index 143448e6c..8d04eb045 100644 --- a/web_src/src/components/CloudRecordDetail.vue +++ b/web_src/src/components/CloudRecordDetail.vue @@ -30,7 +30,7 @@
- +
+
+ + + +
+ +
+
    +
  • + + + + {{ moment(item.startTime).format('HH:mm:ss')}}-{{ moment(item.endTime).format('HH:mm:ss')}} + + + + {{ moment(item.startTime).format('HH:mm:ss')}}-{{ moment(item.endTime).format('HH:mm:ss')}} + + +
  • +
+
+
暂无数据
+
+ +
+ +
+ +
+
+
+ + + + + + + + + + + 倍速 + + + 0.25倍速 + 0.5倍速 + 1倍速 + 2倍速 + 4倍速 + + + + + + +
+ + +
+
+
+
+ +
+
+ +
+ + + + + + diff --git a/web_src/src/components/channelList.vue b/web_src/src/components/channelList.vue index 136ddfe3b..f020f345e 100644 --- a/web_src/src/components/channelList.vue +++ b/web_src/src/components/channelList.vue @@ -269,10 +269,10 @@ export default { }); }, queryRecords: function (itemData) { - var format = moment().format("yyyy-MM-DD"); let deviceId = this.deviceId; let channelId = itemData.channelId; - this.$refs.devicePlayer.openDialog("record", deviceId, channelId, {date: format}) + + this.$router.push(`/gbRecordDetail/${deviceId}/${channelId}`) }, stopDevicePush: function (itemData) { var that = this; diff --git a/web_src/src/components/console.vue b/web_src/src/components/console.vue index 6e2dd830d..e192fb1b7 100644 --- a/web_src/src/components/console.vue +++ b/web_src/src/components/console.vue @@ -101,11 +101,14 @@ export default { window.clearTimeout(this.timer); } this.timer = setTimeout(()=>{ - this.getSystemInfo(); - this.getLoad(); - this.timer = null; - this.loopForSystemInfo() - this.getResourceInfo() + if (this.$route.path === "/console") { + this.getSystemInfo(); + this.getLoad(); + this.timer = null; + this.loopForSystemInfo() + this.getResourceInfo() + } + }, 2000) }, getSystemInfo: function (){ diff --git a/web_src/src/components/console/ConsoleResource.vue b/web_src/src/components/console/ConsoleResource.vue index bc307b98b..3aa77715e 100644 --- a/web_src/src/components/console/ConsoleResource.vue +++ b/web_src/src/components/console/ConsoleResource.vue @@ -1,28 +1,32 @@