Merge branch 'main' into main2

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
#	src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
#	src/main/resources/all-application.yml
#	web_src/src/components/dialog/devicePlayer.vue
This commit is contained in:
648540858 2023-02-10 15:54:42 +08:00
commit ec95a42985
85 changed files with 2638 additions and 1856 deletions

141
README.md
View File

@ -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协议视频平台 # 开箱即用的28181协议视频平台
[![Build Status](https://travis-ci.org/xia-chu/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xia-chu/ZLMediaKit) [![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等设备接入。 支持摄像机、平台、NVR等设备接入。
支持国标级联。 支持国标级联。多平台级联。跨网视频预览。
支持rtsp/rtmp等视频流转发到国标平台。 支持rtsp/rtmp等视频流转发到国标平台。
支持rtsp/rtmp等推流转发到国标平台。 支持rtsp/rtmp等推流转发到国标平台。
@ -31,62 +31,49 @@ WEB VIDEO PLATFORM是一个基于GB28181-2016标准实现的开箱即用的网
https://gitee.com/pan648540858/wvp-GB28181-pro.git 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") ![index](doc/_media/index.png "index.png")
![build_1.png](https://images.gitee.com/uploads/images/2022/0304/103025_5df016f9_1018729.png "2022-03-04_10-27.png") ![2](doc/_media/2.png "2.png")
![build_1.png](https://images.gitee.com/uploads/images/2022/0304/101706_088fbafa_1018729.png "2022-03-04_09-52_1.png") ![3](doc/_media/3.png "3.png")
![build_1.png](https://images.gitee.com/uploads/images/2022/0304/101756_3d662828_1018729.png "2022-03-04_10-00_1.png") ![3-1](doc/_media/3-1.png "3-1.png")
![build_1.png](https://images.gitee.com/uploads/images/2022/0304/101823_19050c66_1018729.png "2022-03-04_10-12_1.png") ![3-2](doc/_media/3-2.png "3-2.png")
![build_1.png](https://images.gitee.com/uploads/images/2022/0304/101848_e5a39557_1018729.png "2022-03-04_10-12_2.png") ![3-3](doc/_media/3-3.png "3-3.png")
![build_1.png](https://images.gitee.com/uploads/images/2022/0304/101919_ee5b8c79_1018729.png "2022-03-04_10-13.png") ![build_1](https://images.gitee.com/uploads/images/2022/0304/101919_ee5b8c79_1018729.png "2022-03-04_10-13.png")
# 1.0 基础特性 # 功能特性
1. 视频预览; - [X] 集成web界面
2. 云台控制(方向、缩放控制); - [X] 兼容性良好
3. 视频设备信息同步; - [X] 支持电子地图支持接入WGS84和GCJ02两种坐标系并且自动转化为合适的坐标系进行展示和分发
4. 离在线监控; - [X] 接入设备
5. 录像查询与回放基于NVR\DVR暂不支持快进、seek操作; - [X] 视频预览
6. 无人观看自动断流; - [X] 无限制接入路数,能接入多少设备只取决于你的服务器性能
7. 支持UDP和TCP两种国标信令传输模式; - [X] 云台控制,控制设备转向,拉近,拉远
8. 集成web界面, 不需要单独部署前端服务, 直接利用wvp内置文件服务部署, 随wvp一起部署; - [X] 预置位查询,使用与设置
9. 支持平台接入, 针对大平台大量设备的情况进行优化; - [X] 查询NVR/IPC上的录像与播放支持指定时间播放与下载
10. 支持检索,通道筛选; - [X] 无人观看自动断流,节省流量
11. 支持自动配置ZLM媒体服务, 减少因配置问题所出现的问题; - [X] 视频设备信息同步
12. 支持启用udp多端口模式, 提高udp模式下媒体传输性能; - [X] 离在线监控
13. 支持通道是否含有音频的设置; - [X] 支持直接输出RTSP、RTMP、HTTP-FLV、Websocket-FLV、HLS多种协议流地址
14. 支持通道子目录查询; - [X] 支持通过一个流地址直接观看摄像头,无需登录以及调用任何接口
15. 支持udp/tcp国标流传输模式; - [X] 支持UDP和TCP两种国标信令传输模式
16. 支持直接输出RTSP、RTMP、HTTP-FLV、Websocket-FLV、HLS多种协议流地址 - [X] 支持UDP和TCP两种国标流传输模式
17. 支持国标网络校时 - [X] 支持检索,通道筛选
18. 支持公网部署, 支持wvp与zlm分开部署 - [X] 支持通道子目录查询
19. 支持播放h265, g.711格式的流(需要将closeWaitRTPInfo设为false) - [X] 支持过滤音频,防止杂音影响观看
20. 报警信息处理,支持向前端推送报警信息 - [X] 支持国标网络校时
- [X] 支持播放H264和H265
# 1.0 新支持特性 - [X] 报警信息处理,支持向前端推送报警信息
1. 集成web界面, 不需要单独部署前端服务, 直接利用wvp内置文件服务部署, 随wvp一起部署; - [X] 支持订阅与通知方法
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] 报警事件订阅
- [X] 报警事件通知处理 - [X] 报警事件通知处理
- [X] 设备目录订阅 - [X] 设备目录订阅
- [X] 设备目录通知处理 - [X] 设备目录通知处理
16. 移动位置查询和显示,可通过配置文件设置移动位置历史是否存储 - [X] 移动位置查询和显示
- [X] 支持手动添加设备和给设备设置单独的密码
# 2.0 支持特性 - [X] 支持平台对接接入
- [X] 国标通道向上级联 - [X] 支持国标级联
- [X] 国标通道向上级联
- [X] WEB添加上级平台 - [X] WEB添加上级平台
- [X] 注册 - [X] 注册
- [X] 心跳保活 - [X] 心跳保活
@ -101,61 +88,33 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
- [X] 目录订阅与通知 - [X] 目录订阅与通知
- [X] 录像查看与播放 - [X] 录像查看与播放
- [X] GPS订阅与通知直播推流 - [X] GPS订阅与通知直播推流
- [X] 支持手动添加设备和给设备设置单独的密码 - [X] 支持自动配置ZLM媒体服务, 减少因配置问题所出现的问题;
- [X] 添加RTSP视频
- [X] 添加接口鉴权
- [X] 添加RTMP视频
- [X] 云端录像(需要部署单独服务配合使用)
- [X] 多流媒体节点,自动选择负载最低的节点使用。 - [X] 多流媒体节点,自动选择负载最低的节点使用。
- [X] WEB端支持播放H264与H265音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。 - [X] 支持启用udp多端口模式, 提高udp模式下媒体传输性能;
- [X] 支持电子地图。 - [X] 支持公网部署;
- [X] 支持接入WGS84和GCJ02两种坐标系。 - [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仔细的阅读可以帮你避免几乎所有的问题 1. 查看wiki仔细的阅读可以帮你避免几乎所有的问题
2. 搜索issues这里有大部分的答案 2. 搜索issues这里有大部分的答案
3. 加QQ群这里有大量热心的小伙伴但是前提新希望你已经仔细阅读了wiki和搜索了issues。 3. 加QQ群901799015这里有大量热心的小伙伴但是前提新希望你已经仔细阅读了wiki和搜索了issues。
4. 你可以请作者为你解答,但是我不是免费的。 4. 你可以请作者为你解答,但是我不是免费的。
5. 你可以把遇到问题的设备寄给我,可以更容易的复现问题。 5. 你可以把遇到问题的设备寄给我,可以更容易的复现问题。
# 合作
目前很多打着合作的幌子来私聊的其实大家大可不必目前作者没有精力你有问题可以付费找我解答也可以提PR
如果对代码有建议可以提ISSUE也可以加群一起聊聊。我们欢迎所有有兴趣参与到项目中来的人。
# 使用帮助 # 使用帮助
QQ群: 901799015, ZLM使用文档[https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit) QQ群: 901799015, ZLM使用文档[https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit)
QQ私信一般不回, 精力有限.欢迎大家在群里讨论.觉得项目对你有帮助欢迎star和提交pr。 QQ私信一般不回, 精力有限.欢迎大家在群里讨论.觉得项目对你有帮助欢迎star和提交pr。
# 授权协议 # 授权协议
本项目自有代码使用宽松的MIT协议在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。 但是本项目也零碎的使用了一些其他的开源代码,在商用的情况下请自行替代或剔除; 由于使用本项目而产生的商业纠纷或侵权行为一概与本项目及开发者无关,请自行承担法律风险。 在使用本项目代码时,也应该在授权协议中同时表明本项目依赖的第三方库的协议 本项目自有代码使用宽松的MIT协议在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。 但是本项目也零碎的使用了一些其他的开源代码,在商用的情况下请自行替代或剔除; 由于使用本项目而产生的商业纠纷或侵权行为一概与本项目及开发者无关,请自行承担法律风险。 在使用本项目代码时,也应该在授权协议中同时表明本项目依赖的第三方库的协议
# 致谢 # 致谢
感谢作者[夏楚](https://github.com/xia-chu) 提供这么棒的开源流媒体服务框架,并在开发过程中给予支持与帮助。 感谢作者[夏楚](https://github.com/xia-chu) 提供这么棒的开源流媒体服务框架,并在开发过程中给予支持与帮助。
感谢作者[dexter langhuihui](https://github.com/langhuihui) 开源这么好用的WEB播放器。 感谢作者[dexter langhuihui](https://github.com/langhuihui) 开源这么好用的WEB播放器。

27
doc/_content/broadcast.md Normal file
View File

@ -0,0 +1,27 @@
# 原理图
## 使用ffmpeg测试语音对讲原理
```plantuml
@startuml
"FFMPEG" -> "ZLMediaKit": 推流到zlm
"WVP-PRO" <- "ZLMediaKit": 通知收到语音对讲推流携带设备和通道信息
"WVP-PRO" -> "设备": 开始语音对讲
"WVP-PRO" <-- "设备": 语音对讲建立成功携带收流端口
"WVP-PRO" -> "ZLMediaKit": 通知zlm将流推送到设备收流端口
"ZLMediaKit" -> "设备": 向设备推流
@enduml
```
## 使用网页测试语音对讲原理
```plantuml
@startuml
"前端页面" -> "WVP-PRO": 请求推流地址
"前端页面" <-- "WVP-PRO": 返回推流地址
"前端页面" -> "ZLMediaKit": 使用webrtc推流到zlm以下过程相同
"WVP-PRO" <- "ZLMediaKit": 通知收到语音对讲推流携带设备和通道信息
"WVP-PRO" -> "设备": 开始语音对讲
"WVP-PRO" <-- "设备": 语音对讲建立成功携带收流端口
"WVP-PRO" -> "ZLMediaKit": 通知zlm将流推送到设备收流端口
"ZLMediaKit" -> "设备": 向设备推流
@enduml
```

BIN
doc/_media/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 KiB

BIN
doc/_media/3-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

BIN
doc/_media/3-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 KiB

BIN
doc/_media/3-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

BIN
doc/_media/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

BIN
doc/_media/index.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

View File

@ -11,7 +11,7 @@
<groupId>com.genersoft</groupId> <groupId>com.genersoft</groupId>
<artifactId>wvp-pro</artifactId> <artifactId>wvp-pro</artifactId>
<version>2.6.6</version> <version>2.6.7</version>
<name>web video platform</name> <name>web video platform</name>
<description>国标28181视频平台</description> <description>国标28181视频平台</description>

View File

@ -54,7 +54,7 @@ CREATE TABLE `device` (
`localIp` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL, `localIp` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `device_deviceId_uindex` (`deviceId`) 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 */; /*!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, `alarmType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`createTime` 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 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 */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
@ -146,7 +146,7 @@ CREATE TABLE `device_channel` (
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `device_channel_id_uindex` (`id`), UNIQUE KEY `device_channel_id_uindex` (`id`),
UNIQUE KEY `device_channel_pk` (`channelId`,`deviceId`) 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 */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
@ -183,7 +183,7 @@ CREATE TABLE `device_mobile_position` (
`latitudeWgs84` double DEFAULT NULL, `latitudeWgs84` double DEFAULT NULL,
`createTime` 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`) 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 */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
@ -216,7 +216,7 @@ CREATE TABLE `gb_stream` (
PRIMARY KEY (`gbStreamId`) USING BTREE, PRIMARY KEY (`gbStreamId`) USING BTREE,
UNIQUE KEY `app` (`app`,`stream`) USING BTREE, UNIQUE KEY `app` (`app`,`stream`) USING BTREE,
UNIQUE KEY `gbId` (`gbId`) 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 */; /*!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, `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`createTime` 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 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 */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
@ -338,7 +338,7 @@ CREATE TABLE `parent_platform` (
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `parent_platform_id_uindex` (`id`), UNIQUE KEY `parent_platform_id_uindex` (`id`),
UNIQUE KEY `parent_platform_pk` (`serverGBId`) 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 */; /*!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, `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`deviceChannelId` int NOT NULL, `deviceChannelId` int NOT NULL,
PRIMARY KEY (`id`) 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 */; /*!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 */; /*!40101 SET @saved_cs_client = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */; /*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `platform_gb_stream` ( CREATE TABLE `platform_gb_stream` (
`id` int NOT NULL AUTO_INCREMENT,
`platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`catalogId` 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, `gbStreamId` int NOT NULL,
`id` int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `platform_gb_stream_pk` (`platformId`,`catalogId`,`gbStreamId`) 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 */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
@ -458,7 +458,7 @@ CREATE TABLE `stream_proxy` (
`enable_disable_none_reader` bit(1) DEFAULT NULL, `enable_disable_none_reader` bit(1) DEFAULT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `stream_proxy_pk` (`app`,`stream`) 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 */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
@ -495,7 +495,7 @@ CREATE TABLE `stream_push` (
`self` int DEFAULT NULL, `self` int DEFAULT NULL,
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `stream_push_pk` (`app`,`stream`) 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 */; /*!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, `pushKey` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE, PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `user_username_uindex` (`username`) 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 */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --
@ -533,7 +533,7 @@ CREATE TABLE `user` (
LOCK TABLES `user` WRITE; LOCK TABLES `user` WRITE;
/*!40000 ALTER TABLE `user` DISABLE KEYS */; /*!40000 ALTER TABLE `user` DISABLE KEYS */;
INSERT INTO `user` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021 - 04 - 13 14:14:57','2021 - 04 - 13 14:14:57','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 */; /*!40000 ALTER TABLE `user` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
@ -551,7 +551,7 @@ CREATE TABLE `user_role` (
`createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE 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 */; /*!40101 SET character_set_client = @saved_cs_client */;
-- --

View File

@ -1,43 +1,3 @@
alter table media_server -- 2.6.6->2.6.7
drop column streamNoneReaderDelayMS;
alter table media_server
drop column sendRtpPortRange;
alter table stream_proxy
add enable_disable_none_reader bit(1) default null;
alter table device alter table device
add mediaServerId varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'auto'; add keepaliveIntervalTime int default null;
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;

View File

@ -71,6 +71,8 @@ public class VideoManagerConstants {
public static final String SYSTEM_INFO_DISK_PREFIX = "VMP_SYSTEM_INFO_DISK_"; 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 BROADCAST_WAITE_INVITE = "task_broadcast_waite_invite_";
public static final String REGISTER_EXPIRE_TASK_KEY_PREFIX = "VMP_device_register_expire_";

View File

@ -10,6 +10,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.util.ObjectUtils;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.*; import javax.servlet.*;
@ -51,6 +52,9 @@ public class ApiAccessFilter extends OncePerRequestFilter {
LogDto logDto = new LogDto(); LogDto logDto = new LogDto();
logDto.setName(uriName); logDto.setName(uriName);
if (ObjectUtils.isEmpty(username)) {
username = "";
}
logDto.setUsername(username); logDto.setUsername(username);
logDto.setAddress(servletRequest.getRemoteAddr()); logDto.setAddress(servletRequest.getRemoteAddr());
logDto.setResult(HttpStatus.valueOf(servletResponse.getStatus()).toString()); logDto.setResult(HttpStatus.valueOf(servletResponse.getStatus()).toString());

View File

@ -35,6 +35,8 @@ public class UserSetting {
private Boolean useSourceIpAsStreamIp = Boolean.FALSE; private Boolean useSourceIpAsStreamIp = Boolean.FALSE;
private Boolean sipUseSourceIpAsRemoteAddress = Boolean.FALSE;
private Boolean streamOnDemand = Boolean.TRUE; private Boolean streamOnDemand = Boolean.TRUE;
private Boolean pushAuthority = Boolean.TRUE; private Boolean pushAuthority = Boolean.TRUE;
@ -45,6 +47,8 @@ public class UserSetting {
private Boolean pushStreamAfterAck = Boolean.FALSE; private Boolean pushStreamAfterAck = Boolean.FALSE;
private Boolean sipLog = Boolean.FALSE;
private String serverId = "000000"; private String serverId = "000000";
private String thirdPartyGBIdReg = "[\\s\\S]*"; private String thirdPartyGBIdReg = "[\\s\\S]*";
@ -216,4 +220,20 @@ public class UserSetting {
public void setPushStreamAfterAck(Boolean pushStreamAfterAck) { public void setPushStreamAfterAck(Boolean pushStreamAfterAck) {
this.pushStreamAfterAck = 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;
}
} }

View File

@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.gb28181; package com.genersoft.iot.vmp.gb28181;
import com.genersoft.iot.vmp.conf.SipConfig; 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.conf.DefaultProperties;
import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver;
import gov.nist.javax.sip.SipProviderImpl; import gov.nist.javax.sip.SipProviderImpl;
@ -29,6 +30,9 @@ public class SipLayer implements CommandLineRunner {
@Autowired @Autowired
private ISIPProcessorObserver sipProcessorObserver; private ISIPProcessorObserver sipProcessorObserver;
@Autowired
private UserSetting userSetting;
private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>(); private final Map<String, SipProviderImpl> tcpSipProviderMap = new ConcurrentHashMap<>();
private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>(); private final Map<String, SipProviderImpl> udpSipProviderMap = new ConcurrentHashMap<>();
@ -61,7 +65,7 @@ public class SipLayer implements CommandLineRunner {
private void addListeningPoint(String monitorIp, int port){ private void addListeningPoint(String monitorIp, int port){
SipStackImpl sipStack; SipStackImpl sipStack;
try { try {
sipStack = (SipStackImpl)sipFactory.createSipStack(DefaultProperties.getProperties(monitorIp, false)); sipStack = (SipStackImpl)sipFactory.createSipStack(DefaultProperties.getProperties(monitorIp, false, userSetting.getSipLog()));
} catch (PeerUnavailableException e) { } catch (PeerUnavailableException e) {
logger.error("[Sip Server] SIP服务启动失败 监听地址{}失败,请检查ip是否正确", monitorIp); logger.error("[Sip Server] SIP服务启动失败 监听地址{}失败,请检查ip是否正确", monitorIp);
return; return;

View File

@ -94,6 +94,13 @@ public class Device {
@Schema(description = "心跳时间") @Schema(description = "心跳时间")
private String keepaliveTime; private String keepaliveTime;
/**
* 心跳间隔
*/
@Schema(description = "心跳间隔")
private int keepaliveIntervalTime;
/** /**
* 通道个数 * 通道个数
*/ */
@ -414,4 +421,12 @@ public class Device {
public void setLocalIp(String localIp) { public void setLocalIp(String localIp) {
this.localIp = localIp; this.localIp = localIp;
} }
public int getKeepaliveIntervalTime() {
return keepaliveIntervalTime;
}
public void setKeepaliveIntervalTime(int keepaliveIntervalTime) {
this.keepaliveIntervalTime = keepaliveIntervalTime;
}
} }

View File

@ -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;
}
}

View File

@ -9,14 +9,15 @@ public class SipTransactionInfo {
private String toTag; private String toTag;
private String viaBranch; private String viaBranch;
private boolean fromServer; // 自己是否媒体流发送者
private boolean asSender;
public SipTransactionInfo(SIPResponse response, boolean fromServer) { public SipTransactionInfo(SIPResponse response, boolean asSender) {
this.callId = response.getCallIdHeader().getCallId(); this.callId = response.getCallIdHeader().getCallId();
this.fromTag = response.getFromTag(); this.fromTag = response.getFromTag();
this.toTag = response.getToTag(); this.toTag = response.getToTag();
this.viaBranch = response.getTopmostViaHeader().getBranch(); this.viaBranch = response.getTopmostViaHeader().getBranch();
this.fromServer = fromServer; this.asSender = asSender;
} }
public SipTransactionInfo(SIPResponse response) { public SipTransactionInfo(SIPResponse response) {
@ -24,7 +25,7 @@ public class SipTransactionInfo {
this.fromTag = response.getFromTag(); this.fromTag = response.getFromTag();
this.toTag = response.getToTag(); this.toTag = response.getToTag();
this.viaBranch = response.getTopmostViaHeader().getBranch(); this.viaBranch = response.getTopmostViaHeader().getBranch();
this.fromServer = true; this.asSender = false;
} }
public SipTransactionInfo() { public SipTransactionInfo() {
@ -62,11 +63,11 @@ public class SipTransactionInfo {
this.viaBranch = viaBranch; this.viaBranch = viaBranch;
} }
public boolean isFromServer() { public boolean isAsSender() {
return fromServer; return asSender;
} }
public void setFromServer(boolean fromServer) { public void setAsSender(boolean asSender) {
this.fromServer = fromServer; this.asSender = asSender;
} }
} }

View File

@ -1,5 +1,9 @@
package com.genersoft.iot.vmp.gb28181.conf; 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; import java.util.Properties;
/** /**
@ -8,10 +12,11 @@ import java.util.Properties;
*/ */
public class DefaultProperties { 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 properties = new Properties();
properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
properties.setProperty("javax.sip.IP_ADDRESS", ip); properties.setProperty("javax.sip.IP_ADDRESS", ip);
// 关闭自动会话
properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off");
/** /**
* 完整配置参考 gov.nist.javax.sip.SipStackImpl需要下载源码 * 完整配置参考 gov.nist.javax.sip.SipStackImpl需要下载源码
@ -26,7 +31,7 @@ public class DefaultProperties {
// 接收所有notify请求即使没有订阅 // 接收所有notify请求即使没有订阅
properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true"); 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.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 _对话框传递_终止的_事件 // 为_NULL _对话框传递_终止的_事件
properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true"); 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"); properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "60");
// 获取实际内容长度不使用header中的长度信息 // 获取实际内容长度不使用header中的长度信息
properties.setProperty("gov.nist.javax.sip.COMPUTE_CONTENT_LENGTH_FROM_MESSAGE_BODY", "true"); 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 * sip_server_log.log sip_debug_log.log ERROR, INFO, WARNING, OFF, DEBUG, TRACE
*/ */
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"); 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; return properties;
} }

View File

@ -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;
}
}

View File

@ -51,6 +51,7 @@ public class VideoStreamSessionManager {
ssrcTransaction.setSsrc(ssrc); ssrcTransaction.setSsrc(ssrc);
ssrcTransaction.setMediaServerId(mediaServerId); ssrcTransaction.setMediaServerId(mediaServerId);
ssrcTransaction.setType(type); ssrcTransaction.setType(type);
RedisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() RedisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId()
+ "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction); + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
} }

View File

@ -170,11 +170,11 @@ public class SIPRequestHeaderProvider {
//from //from
SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain()); SipURI fromSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI); Address fromAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(fromSipURI);
FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.isFromServer()?transactionInfo.getFromTag():transactionInfo.getToTag()); FromHeader fromHeader = sipLayer.getSipFactory().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
//to //to
SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId,device.getHostAddress()); SipURI toSipURI = sipLayer.getSipFactory().createAddressFactory().createSipURI(channelId,device.getHostAddress());
Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI); Address toAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(toSipURI);
ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress,transactionInfo.isFromServer()?transactionInfo.getToTag():transactionInfo.getFromTag()); ToHeader toHeader = sipLayer.getSipFactory().createHeaderFactory().createToHeader(toAddress, transactionInfo.getToTag());
//Forwards //Forwards
MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70); MaxForwardsHeader maxForwards = sipLayer.getSipFactory().createHeaderFactory().createMaxForwardsHeader(70);
@ -186,11 +186,6 @@ public class SIPRequestHeaderProvider {
request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil)); request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
Address concatAddress = sipLayer.getSipFactory().createAddressFactory().createAddress(sipLayer.getSipFactory().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
request.addHeader(sipLayer.getSipFactory().createHeaderFactory().createContactHeader(concatAddress));
request.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
return request; return request;
} }

View File

@ -574,10 +574,11 @@ public class SIPCommander implements ISIPCommander {
if (inviteStreamCallback != null) { if (inviteStreamCallback != null) {
inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream())); 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 -> { sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent -> {
ResponseEvent responseEvent = (ResponseEvent) okEvent.event; ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
SIPResponse response = (SIPResponse) responseEvent.getResponse(); 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);
}); });
} }
@ -655,7 +656,12 @@ public class SIPCommander implements ISIPCommander {
*/ */
@Override @Override
public void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException { public void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException {
SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callId, stream); SsrcTransaction ssrcTransaction;
if (callId != null) {
ssrcTransaction = streamSession.getSsrcTransaction(null, null, callId, null);
}else {
ssrcTransaction = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, null, stream);
}
if (ssrcTransaction == null) { if (ssrcTransaction == null) {
throw new SsrcTransactionNotFoundException(device.getDeviceId(), channelId, callId, stream); throw new SsrcTransactionNotFoundException(device.getDeviceId(), channelId, callId, stream);
} }

View File

@ -307,19 +307,20 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
* @return * @return
*/ */
@Override @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) { if (parentPlatform == null) {
return ; return ;
} }
String statusStr = (status==1)?"ONLINE":"OFFLINE";
String characterSet = parentPlatform.getCharacterSet(); String characterSet = parentPlatform.getCharacterSet();
StringBuffer deviceStatusXml = new StringBuffer(600); StringBuffer deviceStatusXml = new StringBuffer(600);
deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n"); deviceStatusXml.append("<?xml version=\"1.0\" encoding=\"" + characterSet + "\"?>\r\n");
deviceStatusXml.append("<Response>\r\n"); deviceStatusXml.append("<Response>\r\n");
deviceStatusXml.append("<CmdType>DeviceStatus</CmdType>\r\n"); deviceStatusXml.append("<CmdType>DeviceStatus</CmdType>\r\n");
deviceStatusXml.append("<SN>" +sn + "</SN>\r\n"); deviceStatusXml.append("<SN>" +sn + "</SN>\r\n");
deviceStatusXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n"); deviceStatusXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
deviceStatusXml.append("<Result>OK</Result>\r\n"); deviceStatusXml.append("<Result>OK</Result>\r\n");
deviceStatusXml.append("<Online>ONLINE</Online>\r\n"); deviceStatusXml.append("<Online>"+statusStr+"</Online>\r\n");
deviceStatusXml.append("<Status>OK</Status>\r\n"); deviceStatusXml.append("<Status>OK</Status>\r\n");
deviceStatusXml.append("</Response>\r\n"); deviceStatusXml.append("</Response>\r\n");
@ -327,7 +328,6 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader); Request request = headerProviderPlatformProvider.createMessageRequest(parentPlatform, deviceStatusXml.toString(), fromTag, SipUtils.getNewViaTag(), callIdHeader);
sipSender.transmitRequest(parentPlatform.getDeviceIp(), request); sipSender.transmitRequest(parentPlatform.getDeviceIp(), request);
} }
@Override @Override

View File

@ -1,13 +1,16 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl;
import com.genersoft.iot.vmp.conf.SipConfig; 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.auth.DigestServerAuthenticationHelper;
import com.genersoft.iot.vmp.gb28181.bean.Device; 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.bean.WvpSipDate;
import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver;
import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; 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.ISIPRequestProcessor;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import gov.nist.javax.sip.RequestEventExt; import gov.nist.javax.sip.RequestEventExt;
@ -59,6 +62,9 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
@Autowired @Autowired
private SIPSender sipSender; private SIPSender sipSender;
@Autowired
private UserSetting userSetting;
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
// 添加消息处理的订阅 // 添加消息处理的订阅
@ -128,15 +134,9 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
// 添加Expires头 // 添加Expires头
response.addHeader(request.getExpires()); response.addHeader(request.getExpires());
// 获取到通信地址等信息 RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request,
ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); userSetting.getSipUseSourceIpAsRemoteAddress());
String received = viaHeader.getReceived();
int rPort = viaHeader.getRPort();
// 解析本地地址替代
if (ObjectUtils.isEmpty(received) || rPort == -1) {
received = viaHeader.getHost();
rPort = viaHeader.getPort();
}
if (device == null) { if (device == null) {
device = new Device(); device = new Device();
device.setStreamMode("UDP"); device.setStreamMode("UDP");
@ -146,9 +146,9 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
device.setDeviceId(deviceId); device.setDeviceId(deviceId);
device.setOnline(0); device.setOnline(0);
} }
device.setIp(received); device.setIp(remoteAddressInfo.getIp());
device.setPort(rPort); device.setPort(remoteAddressInfo.getPort());
device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));
device.setLocalIp(request.getLocalAddress().getHostAddress()); device.setLocalIp(request.getLocalAddress().getHostAddress());
if (request.getExpires().getExpires() == 0) { if (request.getExpires().getExpires() == 0) {
// 注销成功 // 注销成功

View File

@ -67,6 +67,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
@Override @Override
public void process(RequestEvent evt) { public void process(RequestEvent evt) {
SIPRequest sipRequest = (SIPRequest)evt.getRequest(); SIPRequest sipRequest = (SIPRequest)evt.getRequest();
logger.info("接收到消息:" + evt.getRequest());
logger.debug("接收到消息:" + evt.getRequest()); logger.debug("接收到消息:" + evt.getRequest());
String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
CallIdHeader callIdHeader = sipRequest.getCallIdHeader(); CallIdHeader callIdHeader = sipRequest.getCallIdHeader();
@ -94,7 +95,7 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
if (device == null && parentPlatform == null) { if (device == null && parentPlatform == null) {
// 不存在则回复404 // 不存在则回复404
responseAck(request, Response.NOT_FOUND, "device "+ deviceId +" not found"); 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){ if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){
DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog()); DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog());
deviceNotFoundEvent.setCallId(callIdHeader.getCallId()); deviceNotFoundEvent.setCallId(callIdHeader.getCallId());

View File

@ -1,14 +1,16 @@
package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
import com.genersoft.iot.vmp.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.Device;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 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.SIPRequestProcessorParent;
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; 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.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.service.IDeviceService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPRequest;
import org.dom4j.Element; import org.dom4j.Element;
@ -17,13 +19,10 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent; import javax.sip.RequestEvent;
import javax.sip.SipException; import javax.sip.SipException;
import javax.sip.header.ViaHeader;
import javax.sip.message.Response; import javax.sip.message.Response;
import java.text.ParseException; import java.text.ParseException;
@ -33,6 +32,7 @@ import java.text.ParseException;
@Component @Component
public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
private Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class); private Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class);
private final static String cmdType = "Keepalive"; private final static String cmdType = "Keepalive";
@ -42,6 +42,12 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
@Autowired @Autowired
private IDeviceService deviceService; private IDeviceService deviceService;
@Autowired
private UserSetting userSetting;
@Autowired
private DynamicTask dynamicTask;
@Override @Override
public void afterPropertiesSet() throws Exception { public void afterPropertiesSet() throws Exception {
notifyMessageHandler.addHandler(cmdType, this); notifyMessageHandler.addHandler(cmdType, this);
@ -53,26 +59,27 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
// 未注册的设备不做处理 // 未注册的设备不做处理
return; return;
} }
SIPRequest request = (SIPRequest) evt.getRequest();
// 回复200 OK // 回复200 OK
try { try {
responseAck((SIPRequest) evt.getRequest(), Response.OK); responseAck(request, Response.OK);
} catch (SipException | InvalidArgumentException | ParseException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 心跳回复: {}", e.getMessage()); logger.error("[命令发送失败] 心跳回复: {}", e.getMessage());
} }
// 判断RPort是否改变改变则说明路由nat信息变化修改设备信息
// 获取到通信地址等信息 RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
ViaHeader viaHeader = (ViaHeader) evt.getRequest().getHeader(ViaHeader.NAME); if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) {
String received = viaHeader.getReceived(); device.setPort(remoteAddressInfo.getPort());
int rPort = viaHeader.getRPort(); device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));
// 解析本地地址替代 device.setIp(remoteAddressInfo.getIp());
if (ObjectUtils.isEmpty(received) || rPort == -1) {
received = viaHeader.getHost();
rPort = viaHeader.getPort();
} }
if (device.getPort() != rPort) { if (device.getKeepaliveTime() == null) {
device.setPort(rPort); device.setKeepaliveIntervalTime(60);
device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); }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()); device.setKeepaliveTime(DateUtil.getNow());
if (device.getOnline() == 1) { if (device.getOnline() == 1) {
@ -80,9 +87,15 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
}else { }else {
// 对于已经离线的设备判断他的注册是否已经过期 // 对于已经离线的设备判断他的注册是否已经过期
if (!deviceService.expire(device)){ if (!deviceService.expire(device)){
device.setOnline(0);
deviceService.online(device); 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 @Override

View File

@ -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.conf.SipConfig;
import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; 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 javax.sip.message.Response;
import java.text.ParseException; import java.text.ParseException;
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
@Component @Component
public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
@ -67,8 +70,14 @@ public class DeviceStatusQueryMessageHandler extends SIPRequestProcessorParent i
logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复200OK: {}", e.getMessage()); logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复200OK: {}", e.getMessage());
} }
String sn = rootElement.element("SN").getText(); 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 { try {
cmderFroPlatform.deviceStatusResponse(parentPlatform, sn, fromHeader.getTag()); cmderFroPlatform.deviceStatusResponse(parentPlatform,channelId, sn, fromHeader.getTag(),deviceChannel.getStatus());
} catch (SipException | InvalidArgumentException | ParseException e) { } catch (SipException | InvalidArgumentException | ParseException e) {
logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复: {}", e.getMessage()); logger.error("[命令发送失败] 国标级联 DeviceStatus查询回复: {}", e.getMessage());
} }

View File

@ -63,7 +63,12 @@ public class BroadcastResponseMessageHandler extends SIPRequestProcessorParent i
return; return;
} }
String result = getText(rootElement, "Result"); String result = getText(rootElement, "Result");
logger.info("[语音广播]回复:{}, {}/{}", result, device.getDeviceId(), channelId ); Element infoElement = rootElement.element("Info");
String reason = null;
if (infoElement != null) {
reason = getText(infoElement, "Reason");
}
logger.info("[语音广播]回复:{}, {}/{}", reason == null? result : result + ": " + reason, device.getDeviceId(), channelId );
// 回复200 OK // 回复200 OK
responseAck(request, Response.OK); responseAck(request, Response.OK);

View File

@ -1,9 +1,11 @@
package com.genersoft.iot.vmp.gb28181.utils; package com.genersoft.iot.vmp.gb28181.utils;
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
import com.genersoft.iot.vmp.utils.GitUtil; import com.genersoft.iot.vmp.utils.GitUtil;
import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.address.AddressImpl;
import gov.nist.javax.sip.address.SipUri; import gov.nist.javax.sip.address.SipUri;
import gov.nist.javax.sip.header.Subject; import gov.nist.javax.sip.header.Subject;
import gov.nist.javax.sip.message.SIPRequest;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import javax.sip.PeerUnavailableException; import javax.sip.PeerUnavailableException;
@ -139,4 +141,31 @@ public class SipUtils {
int typeCodeFromGbCode = getTypeCodeFromGbCode(deviceId); int typeCodeFromGbCode = getTypeCodeFromGbCode(deviceId);
return typeCodeFromGbCode > 130 && typeCodeFromGbCode < 199; 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);
}
} }

View File

@ -19,6 +19,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.hook.*;
import com.genersoft.iot.vmp.service.*; import com.genersoft.iot.vmp.service.*;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -347,7 +348,7 @@ public class ZLMHttpHookListener {
} }
} }
}else if ("broadcast".equals(param.getApp())){ }else if ("broadcast".equals(param.getApp())){
// 语音喊话推流 stream需要满足格式deviceId_channelId // 语音对讲推流 stream需要满足格式deviceId_channelId
if (param.isRegist() && param.getStream().indexOf("_") > 0) { if (param.isRegist() && param.getStream().indexOf("_") > 0) {
String[] streamArray = param.getStream().split("_"); String[] streamArray = param.getStream().split("_");
if (streamArray.length == 2) { if (streamArray.length == 2) {
@ -355,8 +356,7 @@ public class ZLMHttpHookListener {
String channelId = streamArray[1]; String channelId = streamArray[1];
Device device = deviceService.getDevice(deviceId); Device device = deviceService.getDevice(deviceId);
if (device != null) { if (device != null) {
DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); if (param.isRegist()) {
if (deviceChannel != null) {
if (audioBroadcastManager.exit(deviceId, channelId)) { if (audioBroadcastManager.exit(deviceId, channelId)) {
// 直接推流 // 直接推流
SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, param.getStream(), null); SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, param.getStream(), null);
@ -381,18 +381,17 @@ public class ZLMHttpHookListener {
logger.error("[命令发送失败] 语音喊话: {}", e.getMessage()); logger.error("[命令发送失败] 语音喊话: {}", e.getMessage());
} }
} }
}else { }else {
logger.info("[语音对讲] 未找到通道:{}", channelId); // 流注销
playService.stopAudioBroadcast(deviceId, channelId);
} }
}else{ } else{
logger.info("[语音对讲] 未找到设备:{}", deviceId); logger.info("[语音对讲] 未找到设备:{}", deviceId);
} }
}else { }else {
logger.info("[语音喊话] 推流格式有误, 格式为: broadcast/设备编号_通道编号 "); logger.info("[语音喊话] 推流格式有误, 格式为: broadcast/设备编号_通道编号 ");
} }
} }
}else if ("talk".equals(param.getApp())){ }else if ("talk".equals(param.getApp())){
// 语音喊话推流 stream需要满足格式deviceId_channelId // 语音喊话推流 stream需要满足格式deviceId_channelId
if (param.isRegist() && param.getStream().indexOf("_") > 0) { if (param.isRegist() && param.getStream().indexOf("_") > 0) {
@ -444,7 +443,7 @@ public class ZLMHttpHookListener {
} }
StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem,
param.getApp(), param.getStream(), param.getTracks(), callId); param.getApp(), param.getStream(), param.getTracks(), callId);
param.setStreamInfo(streamInfoByAppAndStream); param.setStreamInfo(new StreamContent(streamInfoByAppAndStream));
redisCatchStorage.addStream(mediaServerItem, type, param.getApp(), param.getStream(), param); redisCatchStorage.addStream(mediaServerItem, type, param.getApp(), param.getStream(), param);
if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal() if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
|| param.getOriginType() == OriginType.RTMP_PUSH.ordinal() || param.getOriginType() == OriginType.RTMP_PUSH.ordinal()
@ -531,7 +530,7 @@ public class ZLMHttpHookListener {
logger.info("[ZLM HOOK]流无人观看:{]->{}->{}/{}" + param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); logger.info("[ZLM HOOK]流无人观看:{]->{}->{}/{}" + param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream());
JSONObject ret = new JSONObject(); JSONObject ret = new JSONObject();
ret.put("code", 0); ret.put("code", 0);
// 录像下载 // 国标类型的流
if ("rtp".equals(param.getApp())){ if ("rtp".equals(param.getApp())){
ret.put("close", userSetting.getStreamOnDemand()); ret.put("close", userSetting.getStreamOnDemand());
// 国标流 点播/录像回放/录像下载 // 国标流 点播/录像回放/录像下载
@ -638,7 +637,7 @@ public class ZLMHttpHookListener {
@ResponseBody @ResponseBody
@PostMapping(value = "/on_stream_not_found", produces = "application/json;charset=UTF-8") @PostMapping(value = "/on_stream_not_found", produces = "application/json;charset=UTF-8")
public JSONObject onStreamNotFound(@RequestBody OnStreamNotFoundHookParam param){ 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(()->{ taskExecutor.execute(()->{
MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId());
if (userSetting.isAutoApplyPlay() && mediaInfo != null) { if (userSetting.isAutoApplyPlay() && mediaInfo != null) {
@ -706,7 +705,7 @@ public class ZLMHttpHookListener {
@PostMapping(value = "/on_send_rtp_stopped", produces = "application/json;charset=UTF-8") @PostMapping(value = "/on_send_rtp_stopped", produces = "application/json;charset=UTF-8")
public JSONObject onSendRtpStopped(HttpServletRequest request, @RequestBody OnSendRtpStoppedHookParam param){ 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(); JSONObject ret = new JSONObject();
ret.put("code", 0); ret.put("code", 0);

View File

@ -1,6 +1,6 @@
package com.genersoft.iot.vmp.media.zlm.dto.hook; 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; import java.util.List;
@ -291,7 +291,7 @@ public class OnStreamChangedHookParam extends HookParam{
} }
} }
private StreamInfo streamInfo; private StreamContent streamInfo;
public String getApp() { public String getApp() {
return app; return app;
@ -407,11 +407,11 @@ public class OnStreamChangedHookParam extends HookParam{
this.docker = docker; this.docker = docker;
} }
public StreamInfo getStreamInfo() { public StreamContent getStreamInfo() {
return streamInfo; return streamInfo;
} }
public void setStreamInfo(StreamInfo streamInfo) { public void setStreamInfo(StreamContent streamInfo) {
this.streamInfo = streamInfo; this.streamInfo = streamInfo;
} }

View File

@ -37,7 +37,7 @@ public interface IMediaServerService {
*/ */
void zlmServerOffline(String mediaServerId); void zlmServerOffline(String mediaServerId);
MediaServerItem getMediaServerForMinimumLoad(); MediaServerItem getMediaServerForMinimumLoad(Boolean hasAssist);
void setZLMConfig(MediaServerItem mediaServerItem, boolean restart); void setZLMConfig(MediaServerItem mediaServerItem, boolean restart);

View File

@ -40,15 +40,20 @@ public interface IPlayService {
MediaServerItem getNewMediaServerItem(Device device); MediaServerItem getNewMediaServerItem(Device device);
/**
* 获取包含assist服务的节点
*/
MediaServerItem getNewMediaServerItemHasAssist(Device device);
void onPublishHandlerForDownload(InviteStreamInfo inviteStreamInfo, String deviceId, String channelId, String toString); void onPublishHandlerForDownload(InviteStreamInfo inviteStreamInfo, String deviceId, String channelId, String toString);
DeferredResult<WVPResult<StreamInfo>> playBack(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);
DeferredResult<WVPResult<StreamInfo>> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack);
void zlmServerOffline(String mediaServerId); void zlmServerOffline(String mediaServerId);
DeferredResult<WVPResult<StreamInfo>> download(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);
DeferredResult<WVPResult<StreamInfo>> download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); 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); StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream);

View File

@ -1,10 +1,7 @@
package com.genersoft.iot.vmp.service.bean; package com.genersoft.iot.vmp.service.bean;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; public interface PlayBackCallback<T> {
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
public interface PlayBackCallback { void call(PlayBackResult<T> msg);
void call(PlayBackResult<RequestMessage> msg);
} }

View File

@ -99,7 +99,7 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
HashMap<String, DeviceChannel> channelsInStore = new HashMap<>(); HashMap<String, DeviceChannel> channelsInStore = new HashMap<>();
Device device = deviceMapper.getDeviceByDeviceId(deviceId); Device device = deviceMapper.getDeviceByDeviceId(deviceId);
if (channels != null && channels.size() > 0) { if (channels != null && channels.size() > 0) {
List<DeviceChannel> channelList = channelMapper.queryChannels(deviceId, null, null, null, null); List<DeviceChannel> channelList = channelMapper.queryChannels(deviceId, null, null, null, null,null);
if (channelList.size() == 0) { if (channelList.size() == 0) {
for (DeviceChannel channel : channels) { for (DeviceChannel channel : channels) {
channel.setDeviceId(deviceId); channel.setDeviceId(deviceId);

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.service.impl; 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.DynamicTask;
import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.*; 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 static Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class);
private final String registerExpireTaskKeyPrefix = "device-register-expire-";
@Autowired @Autowired
private DynamicTask dynamicTask; private DynamicTask dynamicTask;
@ -108,7 +107,10 @@ public class DeviceServiceImpl implements IDeviceService {
redisCatchStorage.clearCatchByDeviceId(device.getDeviceId()); redisCatchStorage.clearCatchByDeviceId(device.getDeviceId());
} }
device.setUpdateTime(now); device.setUpdateTime(now);
if (device.getKeepaliveIntervalTime() == 0) {
// 默认心跳间隔60
device.setKeepaliveIntervalTime(60);
}
// 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询 // 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询
if (device.getCreateTime() == null) { if (device.getCreateTime() == null) {
device.setOnline(1); device.setOnline(1);
@ -123,7 +125,6 @@ public class DeviceServiceImpl implements IDeviceService {
} }
sync(device); sync(device);
}else { }else {
if(device.getOnline() == 0){ if(device.getOnline() == 0){
device.setOnline(1); device.setOnline(1);
device.setCreateTime(now); device.setCreateTime(now);
@ -160,18 +161,19 @@ public class DeviceServiceImpl implements IDeviceService {
addMobilePositionSubscribe(device); addMobilePositionSubscribe(device);
} }
// 刷新过期任务 // 刷新过期任务
String registerExpireTaskKey = registerExpireTaskKeyPrefix + device.getDeviceId(); String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId();
dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getExpires() * 1000); // 如果第一次注册那么必须在60 * 3时间内收到一个心跳否则设备离线
dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getKeepaliveIntervalTime() * 1000 * 3);
} }
@Override @Override
public void offline(String deviceId) { public void offline(String deviceId) {
logger.info("[设备离线] device{}", deviceId); logger.error("[设备离线] device{}", deviceId);
Device device = deviceMapper.getDeviceByDeviceId(deviceId); Device device = deviceMapper.getDeviceByDeviceId(deviceId);
if (device == null) { if (device == null) {
return; return;
} }
String registerExpireTaskKey = registerExpireTaskKeyPrefix + deviceId; String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + deviceId;
dynamicTask.stop(registerExpireTaskKey); dynamicTask.stop(registerExpireTaskKey);
device.setOnline(0); device.setOnline(0);
redisCatchStorage.updateDevice(device); redisCatchStorage.updateDevice(device);
@ -356,7 +358,6 @@ public class DeviceServiceImpl implements IDeviceService {
device.setUpdateTime(DateUtil.getNow()); device.setUpdateTime(DateUtil.getNow());
if (deviceMapper.update(device) > 0) { if (deviceMapper.update(device) > 0) {
redisCatchStorage.updateDevice(device); redisCatchStorage.updateDevice(device);
} }
} }
@ -432,7 +433,7 @@ public class DeviceServiceImpl implements IDeviceService {
if (parentId.length() < 14 ) { if (parentId.length() < 14 ) {
return null; return null;
} }
List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null); List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null,null);
List<BaseTree<DeviceChannel>> trees = transportChannelsToTree(deviceChannels, parentId); List<BaseTree<DeviceChannel>> trees = transportChannelsToTree(deviceChannels, parentId);
return trees; return trees;
} }
@ -477,7 +478,7 @@ public class DeviceServiceImpl implements IDeviceService {
if (parentId.length() < 14 ) { if (parentId.length() < 14 ) {
return null; return null;
} }
List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null); List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null,null);
return deviceChannels; return deviceChannels;
} }
@ -541,7 +542,7 @@ public class DeviceServiceImpl implements IDeviceService {
} }
}else { }else {
if (haveChannel) { if (haveChannel) {
List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, null, null, null, null); List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, null, null, null, null,null);
if (deviceChannels != null && deviceChannels.size() > 0) { if (deviceChannels != null && deviceChannels.size() > 0) {
result.addAll(deviceChannels); result.addAll(deviceChannels);
} }

View File

@ -501,7 +501,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
* @return MediaServerItem * @return MediaServerItem
*/ */
@Override @Override
public MediaServerItem getMediaServerForMinimumLoad() { public MediaServerItem getMediaServerForMinimumLoad(Boolean hasAssist) {
String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(); String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
if (RedisUtil.zSize(key) == null || RedisUtil.zSize(key) == 0) { if (RedisUtil.zSize(key) == null || RedisUtil.zSize(key) == 0) {
@ -514,9 +514,31 @@ public class MediaServerServiceImpl implements IMediaServerService {
// 获取分数最低的及并发最低的 // 获取分数最低的及并发最低的
Set<Object> objects = RedisUtil.zRange(key, 0, -1); Set<Object> objects = RedisUtil.zRange(key, 0, -1);
ArrayList<Object> mediaServerObjectS = new ArrayList<>(objects); ArrayList<Object> mediaServerObjectS = new ArrayList<>(objects);
MediaServerItem mediaServerItem = null;
if (hasAssist == null) {
String mediaServerId = (String)mediaServerObjectS.get(0); String mediaServerId = (String)mediaServerObjectS.get(0);
return getOne(mediaServerId); 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;
}
}
}
return mediaServerItem;
} }
/** /**

View File

@ -157,14 +157,7 @@ public class PlatformServiceImpl implements IPlatformService {
dynamicTask.startCron(registerTaskKey, dynamicTask.startCron(registerTaskKey,
// 注册失败注册成功时由程序直接调用了online方法 // 注册失败注册成功时由程序直接调用了online方法
()-> { ()-> {
try { registerTask(parentPlatform);
logger.info("[国标级联] 平台:{}注册即将到期,重新注册", parentPlatform.getServerGBId());
commanderForPlatform.register(parentPlatform, eventResult -> {
offline(parentPlatform, false);
},null);
} catch (InvalidArgumentException | ParseException | SipException e) {
logger.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage());
}
}, },
(parentPlatform.getExpires() - 10) *1000); (parentPlatform.getExpires() - 10) *1000);
} }
@ -216,6 +209,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 @Override
public void offline(ParentPlatform parentPlatform, boolean stopRegister) { public void offline(ParentPlatform parentPlatform, boolean stopRegister) {
logger.info("[平台离线]{}", parentPlatform.getServerGBId()); logger.info("[平台离线]{}", parentPlatform.getServerGBId());

View File

@ -39,6 +39,7 @@ import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.utils.redis.RedisUtil; import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 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 com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent;
import gov.nist.javax.sip.message.SIPResponse; import gov.nist.javax.sip.message.SIPResponse;
@ -49,7 +50,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.web.context.request.async.DeferredResult;
import javax.sip.InvalidArgumentException; import javax.sip.InvalidArgumentException;
import javax.sip.ResponseEvent; import javax.sip.ResponseEvent;
@ -454,6 +454,9 @@ public class PlayServiceImpl implements IPlayService {
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
mediaServerService.closeRTPServer(mediaServerItem, 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()); }, userSetting.getPlayTimeout());
@ -463,7 +466,6 @@ public class PlayServiceImpl implements IPlayService {
dynamicTask.stop(timeOutTaskKey); dynamicTask.stop(timeOutTaskKey);
// 释放ssrc // 释放ssrc
mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
RequestMessage msg = new RequestMessage(); RequestMessage msg = new RequestMessage();
@ -481,7 +483,7 @@ public class PlayServiceImpl implements IPlayService {
onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId); onPublishHandlerForPlay(mediaServerItemInuse, response, device.getDeviceId(), channelId);
hookEvent.response(mediaServerItemInuse, response); hookEvent.response(mediaServerItemInuse, response);
logger.info("[点播成功] deviceId: {}, channelId: {}", device.getDeviceId(), channelId); 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 path = "snap";
String fileName = device.getDeviceId() + "_" + channelId + ".jpg"; String fileName = device.getDeviceId() + "_" + channelId + ".jpg";
// 请求截图 // 请求截图
@ -589,14 +591,10 @@ public class PlayServiceImpl implements IPlayService {
} }
} }
private void onPublishHandlerForPlayback(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String uuid) { private void onPublishHandlerForPlayback(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, PlayBackCallback playBackCallback) {
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);
StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId);
PlayBackResult<StreamInfo> playBackResult = new PlayBackResult<>();
if (streamInfo != null) { if (streamInfo != null) {
DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
if (deviceChannel != null) { if (deviceChannel != null) {
@ -605,17 +603,16 @@ public class PlayServiceImpl implements IPlayService {
} }
redisCatchStorage.startPlay(streamInfo); 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 { } else {
logger.warn("录像回放调用失败!"); logger.warn("录像回放调用失败!");
msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "录像回放调用失败!")); playBackResult.setCode(ErrorCode.ERROR100.getCode());
resultHolder.invokeAllResult(msg); playBackResult.setMsg("录像回放调用失败!");
playBackCallback.call(playBackResult);
} }
} }
@ -626,7 +623,7 @@ public class PlayServiceImpl implements IPlayService {
} }
MediaServerItem mediaServerItem; MediaServerItem mediaServerItem;
if (ObjectUtils.isEmpty(device.getMediaServerId()) || "auto".equals(device.getMediaServerId())) { if (ObjectUtils.isEmpty(device.getMediaServerId()) || "auto".equals(device.getMediaServerId())) {
mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(); mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null);
} else { } else {
mediaServerItem = mediaServerService.getOne(device.getMediaServerId()); mediaServerItem = mediaServerService.getOne(device.getMediaServerId());
} }
@ -637,45 +634,56 @@ public class PlayServiceImpl implements IPlayService {
} }
@Override @Override
public DeferredResult<WVPResult<StreamInfo>> 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, String endTime, InviteStreamCallback inviteStreamCallback,
PlayBackCallback callback) { PlayBackCallback callback) {
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
if (device == null) { if (device == null) {
return null; return;
} }
MediaServerItem newMediaServerItem = getNewMediaServerItem(device); MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, device.isSsrcCheck(), true); 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 @Override
public DeferredResult<WVPResult<StreamInfo>> playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,
String deviceId, String channelId, String startTime, String deviceId, String channelId, String startTime,
String endTime, InviteStreamCallback infoCallBack, String endTime, InviteStreamCallback infoCallBack,
PlayBackCallback playBackCallback) { PlayBackCallback playBackCallback) {
if (mediaServerItem == null || ssrcInfo == null) { 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); Device device = storager.queryVideoDevice(deviceId);
if (device == null) { if (device == null) {
throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备: " + deviceId + "不存在"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备: " + deviceId + "不存在");
} }
DeferredResult<WVPResult<StreamInfo>> result = new DeferredResult<>(30000L);
resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid, result); PlayBackResult<StreamInfo> playBackResult = new PlayBackResult<>();
RequestMessage requestMessage = new RequestMessage();
requestMessage.setId(uuid);
requestMessage.setKey(key);
PlayBackResult<RequestMessage> playBackResult = new PlayBackResult<>();
String playBackTimeOutTaskKey = UUID.randomUUID().toString(); String playBackTimeOutTaskKey = UUID.randomUUID().toString();
dynamicTask.startDelay(playBackTimeOutTaskKey, () -> { dynamicTask.startDelay(playBackTimeOutTaskKey, () -> {
logger.warn(String.format("设备回放超时deviceId%s channelId%s", deviceId, channelId)); logger.warn(String.format("设备回放超时deviceId%s channelId%s", deviceId, channelId));
playBackResult.setCode(ErrorCode.ERROR100.getCode()); playBackResult.setCode(ErrorCode.ERROR100.getCode());
playBackResult.setMsg("回放超时"); playBackResult.setMsg("回放超时");
playBackResult.setData(requestMessage);
try { try {
cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
@ -687,19 +695,14 @@ public class PlayServiceImpl implements IPlayService {
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
} }
// 回复之前所有的点播请求 // 回复之前所有的点播请求
playBackCallback.call(playBackResult); playBackCallback.call(playBackResult);
result.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "回放超时"));
resultHolder.exist(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId, uuid);
}, userSetting.getPlayTimeout()); }, userSetting.getPlayTimeout());
SipSubscribe.Event errorEvent = event -> { SipSubscribe.Event errorEvent = event -> {
dynamicTask.stop(playBackTimeOutTaskKey); dynamicTask.stop(playBackTimeOutTaskKey);
requestMessage.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)));
playBackResult.setCode(ErrorCode.ERROR100.getCode()); playBackResult.setCode(ErrorCode.ERROR100.getCode());
playBackResult.setMsg(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)); playBackResult.setMsg(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg));
playBackResult.setData(requestMessage);
playBackResult.setEvent(event); playBackResult.setEvent(event);
playBackCallback.call(playBackResult); playBackCallback.call(playBackResult);
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
@ -717,11 +720,9 @@ public class PlayServiceImpl implements IPlayService {
return; return;
} }
redisCatchStorage.startPlayback(streamInfo, inviteStreamInfo.getCallId()); redisCatchStorage.startPlayback(streamInfo, inviteStreamInfo.getCallId());
WVPResult<StreamInfo> success = WVPResult.success(streamInfo);
requestMessage.setData(success);
playBackResult.setCode(ErrorCode.SUCCESS.getCode()); playBackResult.setCode(ErrorCode.SUCCESS.getCode());
playBackResult.setMsg(ErrorCode.SUCCESS.getMsg()); playBackResult.setMsg(ErrorCode.SUCCESS.getMsg());
playBackResult.setData(requestMessage); playBackResult.setData(streamInfo);
playBackResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); playBackResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
playBackResult.setResponse(inviteStreamInfo.getResponse()); playBackResult.setResponse(inviteStreamInfo.getResponse());
playBackCallback.call(playBackResult); playBackCallback.call(playBackResult);
@ -768,7 +769,7 @@ public class PlayServiceImpl implements IPlayService {
logger.info("[ZLM HOOK] ssrc修正后收到订阅消息 " + response.toJSONString()); logger.info("[ZLM HOOK] ssrc修正后收到订阅消息 " + response.toJSONString());
dynamicTask.stop(playBackTimeOutTaskKey); dynamicTask.stop(playBackTimeOutTaskKey);
// hook响应 // 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())); hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream()));
}); });
} }
@ -788,50 +789,45 @@ public class PlayServiceImpl implements IPlayService {
eventResult.msg = "命令发送失败"; eventResult.msg = "命令发送失败";
errorEvent.response(eventResult); errorEvent.response(eventResult);
} }
return result;
} }
@Override @Override
public DeferredResult<WVPResult<StreamInfo>> 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); Device device = storager.queryVideoDevice(deviceId);
if (device == null) { if (device == null) {
return null; return;
}
MediaServerItem newMediaServerItem = getNewMediaServerItemHasAssist(device);
if (newMediaServerItem == null) {
PlayBackResult<StreamInfo> 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); 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 @Override
public DeferredResult<WVPResult<StreamInfo>> 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) { if (mediaServerItem == null || ssrcInfo == null) {
return null; return;
} }
String uuid = UUID.randomUUID().toString();
String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId;
DeferredResult<WVPResult<StreamInfo>> result = new DeferredResult<>(30000L);
Device device = storager.queryVideoDevice(deviceId); Device device = storager.queryVideoDevice(deviceId);
if (device == null) { if (device == null) {
throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + "不存在"); throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + "不存在");
} }
PlayBackResult<StreamInfo> downloadResult = new PlayBackResult<>();
resultHolder.put(key, uuid, result);
RequestMessage requestMessage = new RequestMessage();
requestMessage.setId(uuid);
requestMessage.setKey(key);
WVPResult<StreamInfo> wvpResult = new WVPResult<>();
requestMessage.setData(wvpResult);
PlayBackResult<RequestMessage> downloadResult = new PlayBackResult<>();
downloadResult.setData(requestMessage);
String downLoadTimeOutTaskKey = UUID.randomUUID().toString(); String downLoadTimeOutTaskKey = UUID.randomUUID().toString();
dynamicTask.startDelay(downLoadTimeOutTaskKey, () -> { dynamicTask.startDelay(downLoadTimeOutTaskKey, () -> {
logger.warn(String.format("录像下载请求超时deviceId%s channelId%s", deviceId, channelId)); logger.warn(String.format("录像下载请求超时deviceId%s channelId%s", deviceId, channelId));
wvpResult.setCode(ErrorCode.ERROR100.getCode());
wvpResult.setMsg("录像下载请求超时");
downloadResult.setCode(ErrorCode.ERROR100.getCode()); downloadResult.setCode(ErrorCode.ERROR100.getCode());
downloadResult.setMsg("录像下载请求超时"); downloadResult.setMsg("录像下载请求超时");
hookCallBack.call(downloadResult); hookCallBack.call(downloadResult);
@ -846,16 +842,12 @@ public class PlayServiceImpl implements IPlayService {
mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
} }
// 回复之前所有的点播请求
hookCallBack.call(downloadResult);
}, userSetting.getPlayTimeout()); }, userSetting.getPlayTimeout());
SipSubscribe.Event errorEvent = event -> { SipSubscribe.Event errorEvent = event -> {
dynamicTask.stop(downLoadTimeOutTaskKey); dynamicTask.stop(downLoadTimeOutTaskKey);
downloadResult.setCode(ErrorCode.ERROR100.getCode()); downloadResult.setCode(ErrorCode.ERROR100.getCode());
downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg)); 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); downloadResult.setEvent(event);
hookCallBack.call(downloadResult); hookCallBack.call(downloadResult);
streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
@ -870,11 +862,9 @@ public class PlayServiceImpl implements IPlayService {
streamInfo.setStartTime(startTime); streamInfo.setStartTime(startTime);
streamInfo.setEndTime(endTime); streamInfo.setEndTime(endTime);
redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId()); redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());
wvpResult.setCode(ErrorCode.SUCCESS.getCode());
wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
wvpResult.setData(streamInfo);
downloadResult.setCode(ErrorCode.SUCCESS.getCode()); downloadResult.setCode(ErrorCode.SUCCESS.getCode());
downloadResult.setMsg(ErrorCode.SUCCESS.getMsg()); downloadResult.setMsg(ErrorCode.SUCCESS.getMsg());
downloadResult.setData(streamInfo);
downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());
downloadResult.setResponse(inviteStreamInfo.getResponse()); downloadResult.setResponse(inviteStreamInfo.getResponse());
hookCallBack.call(downloadResult); hookCallBack.call(downloadResult);
@ -886,7 +876,6 @@ public class PlayServiceImpl implements IPlayService {
eventResult.msg = "命令发送失败"; eventResult.msg = "命令发送失败";
errorEvent.response(eventResult); errorEvent.response(eventResult);
} }
return result;
} }
@Override @Override
@ -906,7 +895,10 @@ public class PlayServiceImpl implements IPlayService {
} }
if (mediaServerItem.getRecordAssistPort() > 0) { if (mediaServerItem.getRecordAssistPort() > 0) {
JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, streamInfo.getApp(), streamInfo.getStream(), null); 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"); long duration = jsonObject.getLong("data");
if (duration == 0) { if (duration == 0) {
@ -1004,7 +996,7 @@ public class PlayServiceImpl implements IPlayService {
logger.warn("开启语音广播的时候未找到通道: {}", channelId); logger.warn("开启语音广播的时候未找到通道: {}", channelId);
return null; return null;
} }
MediaServerItem mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(); MediaServerItem mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null);
String app = "broadcast"; String app = "broadcast";
// TODO 从sip user agent中判断是什么品牌设备大华默认使用talk模式其他使用broadcast模式 // TODO 从sip user agent中判断是什么品牌设备大华默认使用talk模式其他使用broadcast模式
// String app = "talk"; // String app = "talk";
@ -1013,7 +1005,7 @@ public class PlayServiceImpl implements IPlayService {
AudioBroadcastResult audioBroadcastResult = new AudioBroadcastResult(); AudioBroadcastResult audioBroadcastResult = new AudioBroadcastResult();
audioBroadcastResult.setApp(app); audioBroadcastResult.setApp(app);
audioBroadcastResult.setStream(stream); audioBroadcastResult.setStream(stream);
audioBroadcastResult.setStreamInfo(mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, stream, null, null, null,false)); audioBroadcastResult.setStreamInfo(new StreamContent(mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, stream, null, null, null,false)));
audioBroadcastResult.setCodec("G.711"); audioBroadcastResult.setCodec("G.711");
return audioBroadcastResult; return audioBroadcastResult;
} }
@ -1103,6 +1095,12 @@ public class PlayServiceImpl implements IPlayService {
param.put("app", sendRtpItem.getApp()); param.put("app", sendRtpItem.getApp());
param.put("stream", sendRtpItem.getStreamId()); param.put("stream", sendRtpItem.getStreamId());
zlmresTfulUtils.stopSendRtp(mediaInfo, param); zlmresTfulUtils.stopSendRtp(mediaInfo, param);
try {
cmder.streamByeCmd(device, sendRtpItem.getChannelId(), audioBroadcastCatch.getSipTransactionInfo(), null);
} catch (InvalidArgumentException | ParseException | SipException |
SsrcTransactionNotFoundException e) {
logger.error("[消息发送失败] 发送语音喊话BYE失败");
}
} }
audioBroadcastManager.del(deviceId, channelId); audioBroadcastManager.del(deviceId, channelId);

View File

@ -90,7 +90,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
public StreamInfo save(StreamProxyItem param) { public StreamInfo save(StreamProxyItem param) {
MediaServerItem mediaInfo; MediaServerItem mediaInfo;
if (ObjectUtils.isEmpty(param.getMediaServerId()) || "auto".equals(param.getMediaServerId())){ if (ObjectUtils.isEmpty(param.getMediaServerId()) || "auto".equals(param.getMediaServerId())){
mediaInfo = mediaServerService.getMediaServerForMinimumLoad(); mediaInfo = mediaServerService.getMediaServerForMinimumLoad(null);
}else { }else {
mediaInfo = mediaServerService.getOne(param.getMediaServerId()); mediaInfo = mediaServerService.getOne(param.getMediaServerId());
} }

View File

@ -117,7 +117,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
Message msg = taskQueue.poll(); Message msg = taskQueue.poll();
try { try {
JSONObject msgJSON = JSON.parseObject(msg.getBody(), JSONObject.class); 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())) { if (!userSetting.getServerId().equals(wvpRedisMsg.getToId())) {
continue; continue;
} }
@ -126,11 +126,11 @@ public class RedisGbPlayMsgListener implements MessageListener {
switch (wvpRedisMsg.getCmd()){ switch (wvpRedisMsg.getCmd()){
case WvpRedisMsgCmd.GET_SEND_ITEM: 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()); requestSendItemMsgHand(content, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial());
break; break;
case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: 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()); requestPushStreamMsgHand(param, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial());
break; break;
default: default:
@ -142,12 +142,12 @@ public class RedisGbPlayMsgListener implements MessageListener {
switch (wvpRedisMsg.getCmd()){ switch (wvpRedisMsg.getCmd()){
case WvpRedisMsgCmd.GET_SEND_ITEM: 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(); String key = wvpRedisMsg.getSerial();
switch (content.getCode()) { switch (content.getCode()) {
case 0: case 0:
ResponseSendItemMsg responseSendItemMsg =JSON.toJavaObject((JSONObject)content.getData(), ResponseSendItemMsg.class); ResponseSendItemMsg responseSendItemMsg =JSON.to(ResponseSendItemMsg.class, content.getData());
PlayMsgCallback playMsgCallback = callbacks.get(key); PlayMsgCallback playMsgCallback = callbacks.get(key);
if (playMsgCallback != null) { if (playMsgCallback != null) {
callbacksForError.remove(key); callbacksForError.remove(key);
@ -172,7 +172,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
} }
break; break;
case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: 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(); String serial = wvpRedisMsg.getSerial();
switch (wvpResult.getCode()) { switch (wvpResult.getCode()) {
case 0: case 0:
@ -199,6 +199,7 @@ public class RedisGbPlayMsgListener implements MessageListener {
default: default:
break; break;
} }
} }
}catch (Exception e) { }catch (Exception e) {
logger.warn("[RedisGbPlayMsg] 发现未处理的异常, {}",e.getMessage()); logger.warn("[RedisGbPlayMsg] 发现未处理的异常, {}",e.getMessage());

View File

@ -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 PageInfo queryChannelsByDeviceId(String deviceId, String query, Boolean hasSubChannel, Boolean online, Boolean catalogUnderDevice, int page, int count);
public List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit); public List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit,List<String> channelIds);
/** /**
@ -68,7 +68,7 @@ public interface IVideoManagerStorage {
* @param deviceId 设备ID * @param deviceId 设备ID
* @return * @return
*/ */
public List<DeviceChannel> queryChannelsByDeviceId(String deviceId); public List<DeviceChannel> queryChannelsByDeviceId(String deviceId,Boolean online,List<String> channelIds);
public List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId); public List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId);
/** /**
@ -91,14 +91,14 @@ public interface IVideoManagerStorage {
* @param count 每页数量 * @param count 每页数量
* @return List<Device> 设备对象数组 * @return List<Device> 设备对象数组
*/ */
public PageInfo<Device> queryVideoDeviceList(int page, int count); public PageInfo<Device> queryVideoDeviceList(int page, int count,Boolean online);
/** /**
* 获取多个设备 * 获取多个设备
* *
* @return List<Device> 设备对象数组 * @return List<Device> 设备对象数组
*/ */
public List<Device> queryVideoDeviceList(); public List<Device> queryVideoDeviceList(Boolean online);

View File

@ -16,19 +16,19 @@ import java.util.List;
public interface DeviceAlarmMapper { public interface DeviceAlarmMapper {
@Insert("INSERT INTO device_alarm (deviceId, channelId, alarmPriority, alarmMethod, alarmTime, alarmDescription, longitude, latitude, alarmType , createTime ) " + @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); int add(DeviceAlarm alarm);
@Select(value = {" <script>" + @Select(value = {" <script>" +
" SELECT * FROM device_alarm " + " SELECT * FROM device_alarm " +
" WHERE 1=1 " + " WHERE 1=1 " +
" <if test=\"deviceId != null\" > AND deviceId = '${deviceId}'</if>" + " <if test=\"deviceId != null\" > AND deviceId = #{deviceId}</if>" +
" <if test=\"alarmPriority != null\" > AND alarmPriority = '${alarmPriority}' </if>" + " <if test=\"alarmPriority != null\" > AND alarmPriority = #{alarmPriority} </if>" +
" <if test=\"alarmMethod != null\" > AND alarmMethod = '${alarmMethod}' </if>" + " <if test=\"alarmMethod != null\" > AND alarmMethod = #{alarmMethod} </if>" +
" <if test=\"alarmType != null\" > AND alarmType = '${alarmType}' </if>" + " <if test=\"alarmType != null\" > AND alarmType = #{alarmType} </if>" +
" <if test=\"startTime != null\" > AND alarmTime &gt;= '${startTime}' </if>" + " <if test=\"startTime != null\" > AND alarmTime &gt;= #{startTime} </if>" +
" <if test=\"endTime != null\" > AND alarmTime &lt;= '${endTime}' </if>" + " <if test=\"endTime != null\" > AND alarmTime &lt;= #{endTime} </if>" +
" ORDER BY alarmTime ASC " + " ORDER BY alarmTime ASC " +
" </script>"}) " </script>"})
List<DeviceAlarm> query(String deviceId, String alarmPriority, String alarmMethod, List<DeviceAlarm> query(String deviceId, String alarmPriority, String alarmMethod,
@ -38,10 +38,10 @@ public interface DeviceAlarmMapper {
@Delete(" <script>" + @Delete(" <script>" +
"DELETE FROM device_alarm WHERE 1=1 " + "DELETE FROM device_alarm WHERE 1=1 " +
" <if test=\"deviceIdList != null and id == null \" > AND deviceId in " + " <if test=\"deviceIdList != null and id == null \" > AND deviceId in " +
"<foreach collection='deviceIdList' item='item' open='(' separator=',' close=')' > '${item}'</foreach>" + "<foreach collection='deviceIdList' item='item' open='(' separator=',' close=')' > #{item}</foreach>" +
"</if>" + "</if>" +
" <if test=\"time != null and id == null \" > AND alarmTime &lt;= '${time}'</if>" + " <if test=\"time != null and id == null \" > AND alarmTime &lt;= #{time}</if>" +
" <if test=\"id != null\" > AND id = ${id}</if>" + " <if test=\"id != null\" > AND id = #{id}</if>" +
" </script>" " </script>"
) )
int clearAlarmBeforeTime(Integer id, List<String> deviceIdList, String time); int clearAlarmBeforeTime(Integer id, List<String> deviceIdList, String time);

View File

@ -20,46 +20,46 @@ public interface DeviceChannelMapper {
"address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " + "address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " +
"ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, " + "ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, " +
"longitudeWgs84, latitudeWgs84, hasAudio, createTime, updateTime, businessGroupId, gpsTime) " + "longitudeWgs84, latitudeWgs84, hasAudio, createTime, updateTime, businessGroupId, gpsTime) " +
"VALUES ('${channelId}', '${deviceId}', '${name}', '${manufacture}', '${model}', '${owner}', '${civilCode}', '${block}'," + "VALUES (#{channelId}, #{deviceId}, #{name}, #{manufacture}, #{model}, #{owner}, #{civilCode}, #{block}," +
"'${address}', ${parental}, '${parentId}', ${safetyWay}, ${registerWay}, '${certNum}', ${certifiable}, ${errCode}, '${secrecy}', " + "#{address}, #{parental}, #{parentId}, #{safetyWay}, #{registerWay}, #{certNum}, #{certifiable}, #{errCode}, #{secrecy}, " +
"'${ipAddress}', ${port}, '${password}', ${PTZType}, ${status}, '${streamId}', ${longitude}, ${latitude}, ${longitudeGcj02}, " + "#{ipAddress}, #{port}, #{password}, #{PTZType}, #{status}, #{streamId}, #{longitude}, #{latitude}, #{longitudeGcj02}, " +
"${latitudeGcj02}, ${longitudeWgs84}, ${latitudeWgs84}, ${hasAudio}, '${createTime}', '${updateTime}', '${businessGroupId}', '${gpsTime}')") "#{latitudeGcj02}, #{longitudeWgs84}, #{latitudeWgs84}, #{hasAudio}, #{createTime}, #{updateTime}, #{businessGroupId}, #{gpsTime})")
int add(DeviceChannel channel); int add(DeviceChannel channel);
@Update(value = {" <script>" + @Update(value = {" <script>" +
"UPDATE device_channel " + "UPDATE device_channel " +
"SET updateTime='${updateTime}'" + "SET updateTime=#{updateTime}" +
"<if test='name != null'>, name='${name}'</if>" + "<if test='name != null'>, name=#{name}</if>" +
"<if test='manufacture != null'>, manufacture='${manufacture}'</if>" + "<if test='manufacture != null'>, manufacture=#{manufacture}</if>" +
"<if test='model != null'>, model='${model}'</if>" + "<if test='model != null'>, model=#{model}</if>" +
"<if test='owner != null'>, owner='${owner}'</if>" + "<if test='owner != null'>, owner=#{owner}</if>" +
"<if test='civilCode != null'>, civilCode='${civilCode}'</if>" + "<if test='civilCode != null'>, civilCode=#{civilCode}</if>" +
"<if test='block != null'>, block='${block}'</if>" + "<if test='block != null'>, block=#{block}</if>" +
"<if test='address != null'>, address='${address}'</if>" + "<if test='address != null'>, address=#{address}</if>" +
"<if test='parental != null'>, parental=${parental}</if>" + "<if test='parental != null'>, parental=#{parental}</if>" +
"<if test='parentId != null'>, parentId='${parentId}'</if>" + "<if test='parentId != null'>, parentId=#{parentId}</if>" +
"<if test='safetyWay != null'>, safetyWay=${safetyWay}</if>" + "<if test='safetyWay != null'>, safetyWay=#{safetyWay}</if>" +
"<if test='registerWay != null'>, registerWay=${registerWay}</if>" + "<if test='registerWay != null'>, registerWay=#{registerWay}</if>" +
"<if test='certNum != null'>, certNum='${certNum}'</if>" + "<if test='certNum != null'>, certNum=#{certNum}</if>" +
"<if test='certifiable != null'>, certifiable=${certifiable}</if>" + "<if test='certifiable != null'>, certifiable=#{certifiable}</if>" +
"<if test='errCode != null'>, errCode=${errCode}</if>" + "<if test='errCode != null'>, errCode=#{errCode}</if>" +
"<if test='secrecy != null'>, secrecy='${secrecy}'</if>" + "<if test='secrecy != null'>, secrecy=#{secrecy}</if>" +
"<if test='ipAddress != null'>, ipAddress='${ipAddress}'</if>" + "<if test='ipAddress != null'>, ipAddress=#{ipAddress}</if>" +
"<if test='port != null'>, port=${port}</if>" + "<if test='port != null'>, port=#{port}</if>" +
"<if test='password != null'>, password='${password}'</if>" + "<if test='password != null'>, password=#{password}</if>" +
"<if test='PTZType != null'>, PTZType=${PTZType}</if>" + "<if test='PTZType != null'>, PTZType=#{PTZType}</if>" +
"<if test='status != null'>, status='${status}'</if>" + "<if test='status != null'>, status=#{status}</if>" +
"<if test='streamId != null'>, streamId='${streamId}'</if>" + "<if test='streamId != null'>, streamId=#{streamId}</if>" +
"<if test='hasAudio != null'>, hasAudio=${hasAudio}</if>" + "<if test='hasAudio != null'>, hasAudio=#{hasAudio}</if>" +
"<if test='longitude != null'>, longitude=${longitude}</if>" + "<if test='longitude != null'>, longitude=#{longitude}</if>" +
"<if test='latitude != null'>, latitude=${latitude}</if>" + "<if test='latitude != null'>, latitude=#{latitude}</if>" +
"<if test='longitudeGcj02 != null'>, longitudeGcj02=${longitudeGcj02}</if>" + "<if test='longitudeGcj02 != null'>, longitudeGcj02=#{longitudeGcj02}</if>" +
"<if test='latitudeGcj02 != null'>, latitudeGcj02=${latitudeGcj02}</if>" + "<if test='latitudeGcj02 != null'>, latitudeGcj02=#{latitudeGcj02}</if>" +
"<if test='longitudeWgs84 != null'>, longitudeWgs84=${longitudeWgs84}</if>" + "<if test='longitudeWgs84 != null'>, longitudeWgs84=#{longitudeWgs84}</if>" +
"<if test='latitudeWgs84 != null'>, latitudeWgs84=${latitudeWgs84}</if>" + "<if test='latitudeWgs84 != null'>, latitudeWgs84=#{latitudeWgs84}</if>" +
"<if test='businessGroupId != null'>, businessGroupId=#{businessGroupId}</if>" + "<if test='businessGroupId != null'>, businessGroupId=#{businessGroupId}</if>" +
"<if test='gpsTime != null'>, gpsTime=#{gpsTime}</if>" + "<if test='gpsTime != null'>, gpsTime=#{gpsTime}</if>" +
"WHERE deviceId='${deviceId}' AND channelId='${channelId}'"+ "WHERE deviceId=#{deviceId} AND channelId=#{channelId}"+
" </script>"}) " </script>"})
int update(DeviceChannel channel); int update(DeviceChannel channel);
@ -70,15 +70,18 @@ public interface DeviceChannelMapper {
"device_channel dc " + "device_channel dc " +
"WHERE " + "WHERE " +
"dc.deviceId = #{deviceId} " + "dc.deviceId = #{deviceId} " +
" <if test='query != null'> AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%')</if> " + " <if test='query != null'> AND (dc.channelId LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%'))</if> " +
" <if test='parentChannelId != null'> AND (dc.parentId=#{parentChannelId} OR dc.civilCode = #{parentChannelId}) </if> " + " <if test='parentChannelId != null'> AND (dc.parentId=#{parentChannelId} OR dc.civilCode = #{parentChannelId}) </if> " +
" <if test='online == true' > AND dc.status=1</if>" + " <if test='online == true' > AND dc.status=1</if>" +
" <if test='online == false' > AND dc.status=0</if>" + " <if test='online == false' > AND dc.status=0</if>" +
" <if test='hasSubChannel == true' > AND dc.subCount > 0 </if>" + " <if test='hasSubChannel == true' > AND dc.subCount > 0 </if>" +
" <if test='hasSubChannel == false' > AND dc.subCount = 0 </if>" + " <if test='hasSubChannel == false' > AND dc.subCount = 0 </if>" +
"<if test='channelIds != null'> AND dc.channelId in <foreach item='item' index='index' collection='channelIds' open='(' separator=',' close=')'>" +
"#{item} " +
"</foreach> </if>" +
"ORDER BY dc.channelId " + "ORDER BY dc.channelId " +
" </script>"}) " </script>"})
List<DeviceChannel> queryChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online); List<DeviceChannel> queryChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online,List<String> channelIds);
@Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND channelId=#{channelId}") @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND channelId=#{channelId}")
DeviceChannel queryChannel(String deviceId, String 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 device de ON dc.deviceId = de.deviceId " +
" LEFT JOIN platform_gb_channel pgc on pgc.deviceChannelId = dc.id " + " LEFT JOIN platform_gb_channel pgc on pgc.deviceChannelId = dc.id " +
" WHERE 1=1 " + " WHERE 1=1 " +
" <if test='query != null'> AND (dc.channelId LIKE '%${query}%' OR dc.name LIKE '%${query}%' OR dc.name LIKE '%${query}%')</if> " + " <if test='query != null'> AND (dc.channelId LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%') OR dc.name LIKE concat('%',#{query},'%'))</if> " +
" <if test='online == true' > AND dc.status=1</if> " + " <if test='online == true' > AND dc.status=1</if> " +
" <if test='online == false' > AND dc.status=0</if> " + " <if test='online == false' > AND dc.status=0</if> " +
" <if test='hasSubChannel!= null and hasSubChannel == true' > AND dc.subCount > 0</if> " + " <if test='hasSubChannel!= null and hasSubChannel == true' > AND dc.subCount > 0</if> " +
@ -151,14 +154,14 @@ public interface DeviceChannelMapper {
" longitudeWgs84, latitudeWgs84, hasAudio, createTime, updateTime, businessGroupId, gpsTime) " + " longitudeWgs84, latitudeWgs84, hasAudio, createTime, updateTime, businessGroupId, gpsTime) " +
"values " + "values " +
"<foreach collection='addChannels' index='index' item='item' separator=','> " + "<foreach collection='addChannels' index='index' item='item' separator=','> " +
"('${item.channelId}', '${item.deviceId}', '${item.name}', '${item.manufacture}', '${item.model}', " + "(#{item.channelId}, #{item.deviceId}, #{item.name}, #{item.manufacture}, #{item.model}, " +
"'${item.owner}', '${item.civilCode}', '${item.block}',${item.subCount}," + "#{item.owner}, #{item.civilCode}, #{item.block},#{item.subCount}," +
"'${item.address}', ${item.parental}, '${item.parentId}', ${item.safetyWay}, ${item.registerWay}, " + "#{item.address}, #{item.parental}, #{item.parentId}, #{item.safetyWay}, #{item.registerWay}, " +
"'${item.certNum}', ${item.certifiable}, ${item.errCode}, '${item.secrecy}', " + "#{item.certNum}, #{item.certifiable}, #{item.errCode}, #{item.secrecy}, " +
"'${item.ipAddress}', ${item.port}, '${item.password}', ${item.PTZType}, ${item.status}, " + "#{item.ipAddress}, #{item.port}, #{item.password}, #{item.PTZType}, #{item.status}, " +
"'${item.streamId}', ${item.longitude}, ${item.latitude},${item.longitudeGcj02}, " + "#{item.streamId}, #{item.longitude}, #{item.latitude},#{item.longitudeGcj02}, " +
"${item.latitudeGcj02},${item.longitudeWgs84}, ${item.latitudeWgs84}, ${item.hasAudio},'${item.createTime}', '${item.updateTime}', " + "#{item.latitudeGcj02},#{item.longitudeWgs84}, #{item.latitudeWgs84}, #{item.hasAudio}, now(), now(), " +
"'${item.businessGroupId}', '${item.gpsTime}') " + "#{item.businessGroupId}, #{item.gpsTime}) " +
"</foreach> " + "</foreach> " +
"ON DUPLICATE KEY UPDATE " + "ON DUPLICATE KEY UPDATE " +
"updateTime=VALUES(updateTime), " + "updateTime=VALUES(updateTime), " +
@ -203,39 +206,39 @@ public interface DeviceChannelMapper {
"<foreach collection='updateChannels' item='item' separator=';'>" + "<foreach collection='updateChannels' item='item' separator=';'>" +
" UPDATE" + " UPDATE" +
" device_channel" + " device_channel" +
" SET updateTime='${item.updateTime}'" + " SET updateTime=#{item.updateTime}" +
"<if test='item.name != null'>, name='${item.name}'</if>" + "<if test='item.name != null'>, name=#{item.name}</if>" +
"<if test='item.manufacture != null'>, manufacture='${item.manufacture}'</if>" + "<if test='item.manufacture != null'>, manufacture=#{item.manufacture}</if>" +
"<if test='item.model != null'>, model='${item.model}'</if>" + "<if test='item.model != null'>, model=#{item.model}</if>" +
"<if test='item.owner != null'>, owner='${item.owner}'</if>" + "<if test='item.owner != null'>, owner=#{item.owner}</if>" +
"<if test='item.civilCode != null'>, civilCode='${item.civilCode}'</if>" + "<if test='item.civilCode != null'>, civilCode=#{item.civilCode}</if>" +
"<if test='item.block != null'>, block='${item.block}'</if>" + "<if test='item.block != null'>, block=#{item.block}</if>" +
"<if test='item.subCount != null'>, block=${item.subCount}</if>" + "<if test='item.subCount != null'>, block=#{item.subCount}</if>" +
"<if test='item.address != null'>, address='${item.address}'</if>" + "<if test='item.address != null'>, address=#{item.address}</if>" +
"<if test='item.parental != null'>, parental=${item.parental}</if>" + "<if test='item.parental != null'>, parental=#{item.parental}</if>" +
"<if test='item.parentId != null'>, parentId='${item.parentId}'</if>" + "<if test='item.parentId != null'>, parentId=#{item.parentId}</if>" +
"<if test='item.safetyWay != null'>, safetyWay=${item.safetyWay}</if>" + "<if test='item.safetyWay != null'>, safetyWay=#{item.safetyWay}</if>" +
"<if test='item.registerWay != null'>, registerWay=${item.registerWay}</if>" + "<if test='item.registerWay != null'>, registerWay=#{item.registerWay}</if>" +
"<if test='item.certNum != null'>, certNum='${item.certNum}'</if>" + "<if test='item.certNum != null'>, certNum=#{item.certNum}</if>" +
"<if test='item.certifiable != null'>, certifiable=${item.certifiable}</if>" + "<if test='item.certifiable != null'>, certifiable=#{item.certifiable}</if>" +
"<if test='item.errCode != null'>, errCode=${item.errCode}</if>" + "<if test='item.errCode != null'>, errCode=#{item.errCode}</if>" +
"<if test='item.secrecy != null'>, secrecy='${item.secrecy}'</if>" + "<if test='item.secrecy != null'>, secrecy=#{item.secrecy}</if>" +
"<if test='item.ipAddress != null'>, ipAddress='${item.ipAddress}'</if>" + "<if test='item.ipAddress != null'>, ipAddress=#{item.ipAddress}</if>" +
"<if test='item.port != null'>, port=${item.port}</if>" + "<if test='item.port != null'>, port=#{item.port}</if>" +
"<if test='item.password != null'>, password='${item.password}'</if>" + "<if test='item.password != null'>, password=#{item.password}</if>" +
"<if test='item.PTZType != null'>, PTZType=${item.PTZType}</if>" + "<if test='item.PTZType != null'>, PTZType=#{item.PTZType}</if>" +
"<if test='item.status != null'>, status='${item.status}'</if>" + "<if test='item.status != null'>, status=#{item.status}</if>" +
"<if test='item.streamId != null'>, streamId='${item.streamId}'</if>" + "<if test='item.streamId != null'>, streamId=#{item.streamId}</if>" +
"<if test='item.hasAudio != null'>, hasAudio=${item.hasAudio}</if>" + "<if test='item.hasAudio != null'>, hasAudio=#{item.hasAudio}</if>" +
"<if test='item.longitude != null'>, longitude=${item.longitude}</if>" + "<if test='item.longitude != null'>, longitude=#{item.longitude}</if>" +
"<if test='item.latitude != null'>, latitude=${item.latitude}</if>" + "<if test='item.latitude != null'>, latitude=#{item.latitude}</if>" +
"<if test='item.longitudeGcj02 != null'>, longitudeGcj02=${item.longitudeGcj02}</if>" + "<if test='item.longitudeGcj02 != null'>, longitudeGcj02=#{item.longitudeGcj02}</if>" +
"<if test='item.latitudeGcj02 != null'>, latitudeGcj02=${item.latitudeGcj02}</if>" + "<if test='item.latitudeGcj02 != null'>, latitudeGcj02=#{item.latitudeGcj02}</if>" +
"<if test='item.longitudeWgs84 != null'>, longitudeWgs84=${item.longitudeWgs84}</if>" + "<if test='item.longitudeWgs84 != null'>, longitudeWgs84=#{item.longitudeWgs84}</if>" +
"<if test='item.latitudeWgs84 != null'>, latitudeWgs84=${item.latitudeWgs84}</if>" + "<if test='item.latitudeWgs84 != null'>, latitudeWgs84=#{item.latitudeWgs84}</if>" +
"<if test='item.businessGroupId != null'>, businessGroupId=#{item.businessGroupId}</if>" + "<if test='item.businessGroupId != null'>, businessGroupId=#{item.businessGroupId}</if>" +
"<if test='item.gpsTime != null'>, gpsTime=#{item.gpsTime}</if>" + "<if test='item.gpsTime != null'>, gpsTime=#{item.gpsTime}</if>" +
"WHERE deviceId='${item.deviceId}' AND channelId='${item.channelId}'"+ "WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}"+
"</foreach>" + "</foreach>" +
"</script>"}) "</script>"})
int batchUpdate(List<DeviceChannel> updateChannels); int batchUpdate(List<DeviceChannel> updateChannels);
@ -248,17 +251,20 @@ public interface DeviceChannelMapper {
"device_channel dc1 " + "device_channel dc1 " +
"WHERE " + "WHERE " +
"dc1.deviceId = #{deviceId} " + "dc1.deviceId = #{deviceId} " +
" <if test='query != null'> AND (dc1.channelId LIKE '%${query}%' OR dc1.name LIKE '%${query}%' OR dc1.name LIKE '%${query}%')</if> " + " <if test='query != null'> AND (dc1.channelId LIKE concat('%',#{query},'%') OR dc1.name LIKE concat('%',#{query},'%') OR dc1.name LIKE concat('%',#{query},'%'))</if> " +
" <if test='parentChannelId != null'> AND dc1.parentId=#{parentChannelId} </if> " + " <if test='parentChannelId != null'> AND dc1.parentId=#{parentChannelId} </if> " +
" <if test='online == true' > AND dc1.status=1</if>" + " <if test='online == true' > AND dc1.status=1</if>" +
" <if test='online == false' > AND dc1.status=0</if>" + " <if test='online == false' > AND dc1.status=0</if>" +
" <if test='hasSubChannel == true' > AND dc1.subCount >0</if>" + " <if test='hasSubChannel == true' > AND dc1.subCount >0</if>" +
" <if test='hasSubChannel == false' > AND dc1.subCount=0</if>" + " <if test='hasSubChannel == false' > AND dc1.subCount=0</if>" +
"<if test='channelIds != null'> AND dc1.channelId in <foreach item='item' index='index' collection='channelIds' open='(' separator=',' close=')'>" +
"#{item} " +
"</foreach> </if>" +
"ORDER BY dc1.channelId ASC " + "ORDER BY dc1.channelId ASC " +
"Limit #{limit} OFFSET #{start}" + "Limit #{limit} OFFSET #{start}" +
" </script>"}) " </script>"})
List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String parentChannelId, String query, List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String parentChannelId, String query,
Boolean hasSubChannel, Boolean online, int start, int limit); Boolean hasSubChannel, Boolean online, int start, int limit,List<String> channelIds);
@Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND status=1") @Select("SELECT * FROM device_channel WHERE deviceId=#{deviceId} AND status=1")
List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId); List<DeviceChannel> queryOnlineChannelsByDeviceId(String deviceId);
@ -286,13 +292,13 @@ public interface DeviceChannelMapper {
@Update(value = {" <script>" + @Update(value = {" <script>" +
"UPDATE device_channel " + "UPDATE device_channel " +
"SET " + "SET " +
"latitude=${latitude}, " + "latitude=#{latitude}, " +
"longitude=${longitude}, " + "longitude=#{longitude}, " +
"longitudeGcj02=${longitudeGcj02}, " + "longitudeGcj02=#{longitudeGcj02}, " +
"latitudeGcj02=${latitudeGcj02}, " + "latitudeGcj02=#{latitudeGcj02}, " +
"longitudeWgs84=${longitudeWgs84}, " + "longitudeWgs84=#{longitudeWgs84}, " +
"latitudeWgs84=${latitudeWgs84}, " + "latitudeWgs84=#{latitudeWgs84}, " +
"gpsTime='${gpsTime}' " + "gpsTime=#{gpsTime} " +
"WHERE deviceId=#{deviceId} " + "WHERE deviceId=#{deviceId} " +
" <if test='channelId != null' > AND channelId=#{channelId}</if>" + " <if test='channelId != null' > AND channelId=#{channelId}</if>" +
" </script>"}) " </script>"})
@ -309,10 +315,10 @@ public interface DeviceChannelMapper {
"select * " + "select * " +
"from device_channel " + "from device_channel " +
"where deviceId=#{deviceId}" + "where deviceId=#{deviceId}" +
" <if test='parentId != null and length != null' > and parentId = #{parentId} or left(channelId, ${parentId.length()}) = #{parentId} and length(channelId)=${length} </if>" + " <if test='parentId != null and length != null' > and parentId = #{parentId} or left(channelId, #{parentId.length()}) = #{parentId} and length(channelId)=#{length} </if>" +
" <if test='parentId == null and length != null' > and parentId = #{parentId} or length(channelId)=${length} </if>" + " <if test='parentId == null and length != null' > and parentId = #{parentId} or length(channelId)=#{length} </if>" +
" <if test='parentId == null and length == null' > and parentId = #{parentId} </if>" + " <if test='parentId == null and length == null' > and parentId = #{parentId} </if>" +
" <if test='parentId != null and length == null' > and parentId = #{parentId} or left(channelId, ${parentId.length()}) = #{parentId} </if>" + " <if test='parentId != null and length == null' > and parentId = #{parentId} or left(channelId, #{parentId.length()}) = #{parentId} </if>" +
" </script>"}) " </script>"})
List<DeviceChannel> getChannelsWithCivilCodeAndLength(String deviceId, String parentId, Integer length); List<DeviceChannel> getChannelsWithCivilCodeAndLength(String deviceId, String parentId, Integer length);

View File

@ -61,6 +61,7 @@ public interface DeviceMapper {
"expires," + "expires," +
"registerTime," + "registerTime," +
"keepaliveTime," + "keepaliveTime," +
"keepaliveIntervalTime," +
"createTime," + "createTime," +
"updateTime," + "updateTime," +
"charset," + "charset," +
@ -88,6 +89,7 @@ public interface DeviceMapper {
"#{expires}," + "#{expires}," +
"#{registerTime}," + "#{registerTime}," +
"#{keepaliveTime}," + "#{keepaliveTime}," +
"#{keepaliveIntervalTime}," +
"#{createTime}," + "#{createTime}," +
"#{updateTime}," + "#{updateTime}," +
"#{charset}," + "#{charset}," +
@ -104,25 +106,28 @@ public interface DeviceMapper {
@Update(value = {" <script>" + @Update(value = {" <script>" +
"UPDATE device " + "UPDATE device " +
"SET updateTime='${updateTime}'" + "SET updateTime=#{updateTime}" +
"<if test=\"name != null\">, name='${name}'</if>" + "<if test=\"name != null\">, name=#{name}</if>" +
"<if test=\"manufacturer != null\">, manufacturer='${manufacturer}'</if>" + "<if test=\"manufacturer != null\">, manufacturer=#{manufacturer}</if>" +
"<if test=\"model != null\">, model='${model}'</if>" + "<if test=\"model != null\">, model=#{model}</if>" +
"<if test=\"firmware != null\">, firmware='${firmware}'</if>" + "<if test=\"firmware != null\">, firmware=#{firmware}</if>" +
"<if test=\"transport != null\">, transport='${transport}'</if>" + "<if test=\"transport != null\">, transport=#{transport}</if>" +
"<if test=\"ip != null\">, ip='${ip}'</if>" + "<if test=\"ip != null\">, ip=#{ip}</if>" +
"<if test=\"localIp != null\">, localIp='${localIp}'</if>" + "<if test=\"localIp != null\">, localIp=#{localIp}</if>" +
"<if test=\"port != null\">, port=${port}</if>" + "<if test=\"port != null\">, port=#{port}</if>" +
"<if test=\"hostAddress != null\">, hostAddress='${hostAddress}'</if>" + "<if test=\"hostAddress != null\">, hostAddress=#{hostAddress}</if>" +
"<if test=\"online != null\">, online=${online}</if>" + "<if test=\"online != null\">, online=#{online}</if>" +
"<if test=\"registerTime != null\">, registerTime='${registerTime}'</if>" + "<if test=\"registerTime != null\">, registerTime=#{registerTime}</if>" +
"<if test=\"keepaliveTime != null\">, keepaliveTime='${keepaliveTime}'</if>" + "<if test=\"keepaliveTime != null\">, keepaliveTime=#{keepaliveTime}</if>" +
"<if test=\"expires != null\">, expires=${expires}</if>" + "<if test=\"keepaliveIntervalTime != null\">, keepaliveIntervalTime=#{keepaliveIntervalTime}</if>" +
"WHERE deviceId='${deviceId}'"+ "<if test=\"expires != null\">, expires=#{expires}</if>" +
"WHERE deviceId=#{deviceId}"+
" </script>"}) " </script>"})
int update(Device device); int update(Device device);
@Select("SELECT " + @Select(
" <script>" +
"SELECT " +
"deviceId, " + "deviceId, " +
"coalesce(custom_name, name) as name, " + "coalesce(custom_name, name) as name, " +
"password, " + "password, " +
@ -150,8 +155,11 @@ public interface DeviceMapper {
"geoCoordSys," + "geoCoordSys," +
"treeType," + "treeType," +
"online," + "online," +
"(SELECT count(0) FROM device_channel WHERE deviceId=de.deviceId) as channelCount FROM device de") "(SELECT count(0) FROM device_channel WHERE deviceId=de.deviceId) as channelCount FROM device de" +
List<Device> getDevices(); "<if test=\"online != null\"> where online=${online}</if>"+
" </script>"
)
List<Device> getDevices(Boolean online);
@Delete("DELETE FROM device WHERE deviceId=#{deviceId}") @Delete("DELETE FROM device WHERE deviceId=#{deviceId}")
int del(String deviceId); int del(String deviceId);
@ -217,28 +225,28 @@ public interface DeviceMapper {
"geoCoordSys," + "geoCoordSys," +
"treeType," + "treeType," +
"online" + "online" +
" FROM device WHERE ip = #{host} AND port=${port}") " FROM device WHERE ip = #{host} AND port=#{port}")
Device getDeviceByHostAndPort(String host, int port); Device getDeviceByHostAndPort(String host, int port);
@Update(value = {" <script>" + @Update(value = {" <script>" +
"UPDATE device " + "UPDATE device " +
"SET updateTime='${updateTime}'" + "SET updateTime=#{updateTime}" +
"<if test=\"name != null\">, custom_name='${name}'</if>" + "<if test=\"name != null\">, custom_name=#{name}</if>" +
"<if test=\"password != null\">, password='${password}'</if>" + "<if test=\"password != null\">, password=#{password}</if>" +
"<if test=\"streamMode != null\">, streamMode='${streamMode}'</if>" + "<if test=\"streamMode != null\">, streamMode=#{streamMode}</if>" +
"<if test=\"ip != null\">, ip='${ip}'</if>" + "<if test=\"ip != null\">, ip=#{ip}</if>" +
"<if test=\"sdpIp != null\">, sdpIp='${sdpIp}'</if>" + "<if test=\"sdpIp != null\">, sdpIp=#{sdpIp}</if>" +
"<if test=\"port != null\">, port=${port}</if>" + "<if test=\"port != null\">, port=#{port}</if>" +
"<if test=\"charset != null\">, charset='${charset}'</if>" + "<if test=\"charset != null\">, charset=#{charset}</if>" +
"<if test=\"subscribeCycleForCatalog != null\">, subscribeCycleForCatalog=${subscribeCycleForCatalog}</if>" + "<if test=\"subscribeCycleForCatalog != null\">, subscribeCycleForCatalog=#{subscribeCycleForCatalog}</if>" +
"<if test=\"subscribeCycleForMobilePosition != null\">, subscribeCycleForMobilePosition=${subscribeCycleForMobilePosition}</if>" + "<if test=\"subscribeCycleForMobilePosition != null\">, subscribeCycleForMobilePosition=#{subscribeCycleForMobilePosition}</if>" +
"<if test=\"mobilePositionSubmissionInterval != null\">, mobilePositionSubmissionInterval=${mobilePositionSubmissionInterval}</if>" + "<if test=\"mobilePositionSubmissionInterval != null\">, mobilePositionSubmissionInterval=#{mobilePositionSubmissionInterval}</if>" +
"<if test=\"subscribeCycleForAlarm != null\">, subscribeCycleForAlarm=${subscribeCycleForAlarm}</if>" + "<if test=\"subscribeCycleForAlarm != null\">, subscribeCycleForAlarm=#{subscribeCycleForAlarm}</if>" +
"<if test=\"ssrcCheck != null\">, ssrcCheck=${ssrcCheck}</if>" + "<if test=\"ssrcCheck != null\">, ssrcCheck=#{ssrcCheck}</if>" +
"<if test=\"geoCoordSys != null\">, geoCoordSys=#{geoCoordSys}</if>" + "<if test=\"geoCoordSys != null\">, geoCoordSys=#{geoCoordSys}</if>" +
"<if test=\"treeType != null\">, treeType=#{treeType}</if>" + "<if test=\"treeType != null\">, treeType=#{treeType}</if>" +
"<if test=\"mediaServerId != null\">, mediaServerId=#{mediaServerId}</if>" + "<if test=\"mediaServerId != null\">, mediaServerId=#{mediaServerId}</if>" +
"WHERE deviceId='${deviceId}'"+ "WHERE deviceId=#{deviceId}"+
" </script>"}) " </script>"})
int updateCustom(Device device); int updateCustom(Device device);

View File

@ -9,7 +9,7 @@ import org.apache.ibatis.annotations.*;
public interface DeviceMobilePositionMapper { public interface DeviceMobilePositionMapper {
@Insert("INSERT INTO device_mobile_position (deviceId,channelId, deviceName, time, longitude, latitude, altitude, speed, direction, reportSource, longitudeGcj02, latitudeGcj02, longitudeWgs84, latitudeWgs84, createTime) " + @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); int insertNewPosition(MobilePosition mobilePosition);
@Select(value = {" <script>" + @Select(value = {" <script>" +

View File

@ -16,9 +16,9 @@ public interface GbStreamMapper {
@Insert("REPLACE INTO gb_stream (app, stream, gbId, name, " + @Insert("REPLACE INTO gb_stream (app, stream, gbId, name, " +
"longitude, latitude, streamType, mediaServerId, createTime) VALUES" + "longitude, latitude, streamType, mediaServerId, createTime) VALUES" +
"('${app}', '${stream}', '${gbId}', '${name}', " + "(#{app}, #{stream}, #{gbId}, #{name}, " +
"'${longitude}', '${latitude}', '${streamType}', " + "#{longitude}, #{latitude}, #{streamType}, " +
"'${mediaServerId}', '${createTime}')") "#{mediaServerId}, #{createTime})")
@Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId") @Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId")
int add(GbStream gbStream); int add(GbStream gbStream);
@ -57,7 +57,7 @@ public interface GbStreamMapper {
"(select pgs.gbStreamId from platform_gb_stream pgs where pgs.platformId = #{platformId} and pgs.catalogId=#{catalogId})</if> " + "(select pgs.gbStreamId from platform_gb_stream pgs where pgs.platformId = #{platformId} and pgs.catalogId=#{catalogId})</if> " +
" <if test='catalogId == null'> AND gs.gbStreamId not in" + " <if test='catalogId == null'> AND gs.gbStreamId not in" +
"(select pgs.gbStreamId from platform_gb_stream pgs where pgs.platformId = #{platformId}) </if> " + "(select pgs.gbStreamId from platform_gb_stream pgs where pgs.platformId = #{platformId}) </if> " +
" <if test='query != null'> AND (gs.app LIKE '%${query}%' OR gs.stream LIKE '%${query}%' OR gs.gbId LIKE '%${query}%' OR gs.name LIKE '%${query}%')</if> " + " <if test='query != null'> AND (gs.app LIKE concat('%',#{query},'%') OR gs.stream LIKE concat('%',#{query},'%') OR gs.gbId LIKE concat('%',#{query},'%') OR gs.name LIKE concat('%',#{query},'%'))</if> " +
" <if test='mediaServerId != null' > AND gs.mediaServerId=#{mediaServerId} </if>" + " <if test='mediaServerId != null' > AND gs.mediaServerId=#{mediaServerId} </if>" +
" order by gs.gbStreamId asc " + " order by gs.gbStreamId asc " +
"</script>") "</script>")
@ -71,7 +71,7 @@ public interface GbStreamMapper {
@Select("SELECT gs.*, pgs.platformId as platformId, pgs.catalogId as catalogId FROM gb_stream gs " + @Select("SELECT gs.*, pgs.platformId as platformId, pgs.catalogId as catalogId FROM gb_stream gs " +
"LEFT JOIN platform_gb_stream pgs ON gs.gbStreamId = pgs.gbStreamId " + "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); GbStream queryStreamInPlatform(String platformId, String gbId);
@Select("<script> "+ @Select("<script> "+
@ -122,9 +122,9 @@ public interface GbStreamMapper {
"longitude, latitude, streamType, mediaServerId, createTime)" + "longitude, latitude, streamType, mediaServerId, createTime)" +
"values " + "values " +
"<foreach collection='subList' index='index' item='item' separator=','> " + "<foreach collection='subList' index='index' item='item' separator=','> " +
"('${item.app}', '${item.stream}', '${item.gbId}', '${item.name}', " + "(#{item.app}, #{item.stream}, #{item.gbId}, #{item.name}, " +
"'${item.longitude}', '${item.latitude}', '${item.streamType}', " + "#{item.longitude}, #{item.latitude}, #{item.streamType}, " +
"'${item.mediaServerId}', '${item.createTime}') "+ "#{item.mediaServerId}, #{item.createTime}) "+
"</foreach> " + "</foreach> " +
"</script>") "</script>")
@Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId") @Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId")
@ -134,7 +134,7 @@ public interface GbStreamMapper {
"<foreach collection='gpsMsgInfos' item='item' separator=';'>" + "<foreach collection='gpsMsgInfos' item='item' separator=';'>" +
" UPDATE" + " UPDATE" +
" gb_stream" + " gb_stream" +
" SET longitude=${item.lng}, latitude=${item.lat} " + " SET longitude=#{item.lng}, latitude=#{item.lat} " +
"WHERE gbId=#{item.id}"+ "WHERE gbId=#{item.id}"+
"</foreach>" + "</foreach>" +
"</script>"}) "</script>"})

View File

@ -18,16 +18,16 @@ import java.util.List;
public interface LogMapper { public interface LogMapper {
@Insert("insert into log ( name, type, uri, address, result, timing, username, createTime) " + @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); int add(LogDto logDto);
@Select(value = {"<script>" + @Select(value = {"<script>" +
" SELECT * FROM log " + " SELECT * FROM log " +
" WHERE 1=1 " + " WHERE 1=1 " +
" <if test=\"query != null\"> AND (name LIKE '%${query}%')</if> " + " <if test=\"query != null\"> AND (name LIKE concat('%',#{query},'%'))</if> " +
" <if test=\"type != null\" > AND type = '${type}'</if>" + " <if test=\"type != null\" > AND type = #{type}</if>" +
" <if test=\"startTime != null\" > AND createTime &gt;= '${startTime}' </if>" + " <if test=\"startTime != null\" > AND createTime &gt;= #{startTime} </if>" +
" <if test=\"endTime != null\" > AND createTime &lt;= '${endTime}' </if>" + " <if test=\"endTime != null\" > AND createTime &lt;= #{endTime} </if>" +
" ORDER BY createTime DESC " + " ORDER BY createTime DESC " +
" </script>"}) " </script>"})
List<LogDto> query(String query, String type, String startTime, String endTime); List<LogDto> query(String query, String type, String startTime, String endTime);

View File

@ -35,92 +35,92 @@ public interface MediaServerMapper {
"hookAliveInterval" + "hookAliveInterval" +
") VALUES " + ") VALUES " +
"(" + "(" +
"'${id}', " + "#{id}, " +
"'${ip}', " + "#{ip}, " +
"'${hookIp}', " + "#{hookIp}, " +
"'${sdpIp}', " + "#{sdpIp}, " +
"'${streamIp}', " + "#{streamIp}, " +
"${httpPort}, " + "#{httpPort}, " +
"${httpSSlPort}, " + "#{httpSSlPort}, " +
"${rtmpPort}, " + "#{rtmpPort}, " +
"${rtmpSSlPort}, " + "#{rtmpSSlPort}, " +
"${rtpProxyPort}, " + "#{rtpProxyPort}, " +
"${rtspPort}, " + "#{rtspPort}, " +
"${rtspSSLPort}, " + "#{rtspSSLPort}, " +
"${autoConfig}, " + "#{autoConfig}, " +
"'${secret}', " + "#{secret}, " +
"${rtpEnable}, " + "#{rtpEnable}, " +
"'${rtpPortRange}', " + "#{rtpPortRange}, " +
"${recordAssistPort}, " + "#{recordAssistPort}, " +
"${defaultServer}, " + "#{defaultServer}, " +
"'${createTime}', " + "#{createTime}, " +
"'${updateTime}', " + "#{updateTime}, " +
"${hookAliveInterval})") "#{hookAliveInterval})")
int add(MediaServerItem mediaServerItem); int add(MediaServerItem mediaServerItem);
@Update(value = {" <script>" + @Update(value = {" <script>" +
"UPDATE media_server " + "UPDATE media_server " +
"SET updateTime='${updateTime}'" + "SET updateTime=#{updateTime}" +
"<if test=\"ip != null\">, ip='${ip}'</if>" + "<if test=\"ip != null\">, ip=#{ip}</if>" +
"<if test=\"hookIp != null\">, hookIp='${hookIp}'</if>" + "<if test=\"hookIp != null\">, hookIp=#{hookIp}</if>" +
"<if test=\"sdpIp != null\">, sdpIp='${sdpIp}'</if>" + "<if test=\"sdpIp != null\">, sdpIp=#{sdpIp}</if>" +
"<if test=\"streamIp != null\">, streamIp='${streamIp}'</if>" + "<if test=\"streamIp != null\">, streamIp=#{streamIp}</if>" +
"<if test=\"httpPort != null\">, httpPort=${httpPort}</if>" + "<if test=\"httpPort != null\">, httpPort=#{httpPort}</if>" +
"<if test=\"httpSSlPort != null\">, httpSSlPort=${httpSSlPort}</if>" + "<if test=\"httpSSlPort != null\">, httpSSlPort=#{httpSSlPort}</if>" +
"<if test=\"rtmpPort != null\">, rtmpPort=${rtmpPort}</if>" + "<if test=\"rtmpPort != null\">, rtmpPort=#{rtmpPort}</if>" +
"<if test=\"rtmpSSlPort != null\">, rtmpSSlPort=${rtmpSSlPort}</if>" + "<if test=\"rtmpSSlPort != null\">, rtmpSSlPort=#{rtmpSSlPort}</if>" +
"<if test=\"rtpProxyPort != null\">, rtpProxyPort=${rtpProxyPort}</if>" + "<if test=\"rtpProxyPort != null\">, rtpProxyPort=#{rtpProxyPort}</if>" +
"<if test=\"rtspPort != null\">, rtspPort=${rtspPort}</if>" + "<if test=\"rtspPort != null\">, rtspPort=#{rtspPort}</if>" +
"<if test=\"rtspSSLPort != null\">, rtspSSLPort=${rtspSSLPort}</if>" + "<if test=\"rtspSSLPort != null\">, rtspSSLPort=#{rtspSSLPort}</if>" +
"<if test=\"autoConfig != null\">, autoConfig=${autoConfig}</if>" + "<if test=\"autoConfig != null\">, autoConfig=#{autoConfig}</if>" +
"<if test=\"rtpEnable != null\">, rtpEnable=${rtpEnable}</if>" + "<if test=\"rtpEnable != null\">, rtpEnable=#{rtpEnable}</if>" +
"<if test=\"rtpPortRange != null\">, rtpPortRange='${rtpPortRange}'</if>" + "<if test=\"rtpPortRange != null\">, rtpPortRange=#{rtpPortRange}</if>" +
"<if test=\"secret != null\">, secret='${secret}'</if>" + "<if test=\"secret != null\">, secret=#{secret}</if>" +
"<if test=\"recordAssistPort != null\">, recordAssistPort=${recordAssistPort}</if>" + "<if test=\"recordAssistPort != null\">, recordAssistPort=#{recordAssistPort}</if>" +
"<if test=\"hookAliveInterval != null\">, hookAliveInterval=${hookAliveInterval}</if>" + "<if test=\"hookAliveInterval != null\">, hookAliveInterval=#{hookAliveInterval}</if>" +
"WHERE id='${id}'"+ "WHERE id=#{id}"+
" </script>"}) " </script>"})
int update(MediaServerItem mediaServerItem); int update(MediaServerItem mediaServerItem);
@Update(value = {" <script>" + @Update(value = {" <script>" +
"UPDATE media_server " + "UPDATE media_server " +
"SET updateTime='${updateTime}'" + "SET updateTime=#{updateTime}" +
"<if test=\"id != null\">, id='${id}'</if>" + "<if test=\"id != null\">, id=#{id}</if>" +
"<if test=\"hookIp != null\">, hookIp='${hookIp}'</if>" + "<if test=\"hookIp != null\">, hookIp=#{hookIp}</if>" +
"<if test=\"sdpIp != null\">, sdpIp='${sdpIp}'</if>" + "<if test=\"sdpIp != null\">, sdpIp=#{sdpIp}</if>" +
"<if test=\"streamIp != null\">, streamIp='${streamIp}'</if>" + "<if test=\"streamIp != null\">, streamIp=#{streamIp}</if>" +
"<if test=\"httpSSlPort != null\">, httpSSlPort=${httpSSlPort}</if>" + "<if test=\"httpSSlPort != null\">, httpSSlPort=#{httpSSlPort}</if>" +
"<if test=\"rtmpPort != null\">, rtmpPort=${rtmpPort}</if>" + "<if test=\"rtmpPort != null\">, rtmpPort=#{rtmpPort}</if>" +
"<if test=\"rtmpSSlPort != null\">, rtmpSSlPort=${rtmpSSlPort}</if>" + "<if test=\"rtmpSSlPort != null\">, rtmpSSlPort=#{rtmpSSlPort}</if>" +
"<if test=\"rtpProxyPort != null\">, rtpProxyPort=${rtpProxyPort}</if>" + "<if test=\"rtpProxyPort != null\">, rtpProxyPort=#{rtpProxyPort}</if>" +
"<if test=\"rtspPort != null\">, rtspPort=${rtspPort}</if>" + "<if test=\"rtspPort != null\">, rtspPort=#{rtspPort}</if>" +
"<if test=\"rtspSSLPort != null\">, rtspSSLPort=${rtspSSLPort}</if>" + "<if test=\"rtspSSLPort != null\">, rtspSSLPort=#{rtspSSLPort}</if>" +
"<if test=\"autoConfig != null\">, autoConfig=${autoConfig}</if>" + "<if test=\"autoConfig != null\">, autoConfig=#{autoConfig}</if>" +
"<if test=\"rtpEnable != null\">, rtpEnable=${rtpEnable}</if>" + "<if test=\"rtpEnable != null\">, rtpEnable=#{rtpEnable}</if>" +
"<if test=\"rtpPortRange != null\">, rtpPortRange='${rtpPortRange}'</if>" + "<if test=\"rtpPortRange != null\">, rtpPortRange=#{rtpPortRange}</if>" +
"<if test=\"secret != null\">, secret='${secret}'</if>" + "<if test=\"secret != null\">, secret=#{secret}</if>" +
"<if test=\"recordAssistPort != null\">, recordAssistPort=${recordAssistPort}</if>" + "<if test=\"recordAssistPort != null\">, recordAssistPort=#{recordAssistPort}</if>" +
"<if test=\"hookAliveInterval != null\">, hookAliveInterval=${hookAliveInterval}</if>" + "<if test=\"hookAliveInterval != null\">, hookAliveInterval=#{hookAliveInterval}</if>" +
"WHERE ip='${ip}' and httpPort=${httpPort}"+ "WHERE ip=#{ip} and httpPort=#{httpPort}"+
" </script>"}) " </script>"})
int updateByHostAndPort(MediaServerItem mediaServerItem); int updateByHostAndPort(MediaServerItem mediaServerItem);
@Select("SELECT * FROM media_server WHERE id='${id}'") @Select("SELECT * FROM media_server WHERE id=#{id}")
MediaServerItem queryOne(String id); MediaServerItem queryOne(String id);
@Select("SELECT * FROM media_server") @Select("SELECT * FROM media_server")
List<MediaServerItem> queryAll(); List<MediaServerItem> queryAll();
@Delete("DELETE FROM media_server WHERE id='${id}'") @Delete("DELETE FROM media_server WHERE id=#{id}")
void delOne(String 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); void delOneByIPAndPort(String host, int port);
@Delete("DELETE FROM media_server WHERE defaultServer=1") @Delete("DELETE FROM media_server WHERE defaultServer=1")
int delDefault(); 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); MediaServerItem queryOneByHostAndPort(String host, int port);
@Select("SELECT * FROM media_server WHERE defaultServer=1") @Select("SELECT * FROM media_server WHERE defaultServer=1")

View File

@ -17,9 +17,9 @@ public interface ParentPlatformMapper {
@Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp, " + @Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp, " +
" devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, " + " devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, " +
" status, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime, treeType) " + " status, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime, treeType) " +
" VALUES (${enable}, '${name}', '${serverGBId}', '${serverGBDomain}', '${serverIP}', ${serverPort}, '${deviceGBId}', '${deviceIp}', " + " VALUES (#{enable}, #{name}, #{serverGBId}, #{serverGBDomain}, #{serverIP}, #{serverPort}, #{deviceGBId}, #{deviceIp}, " +
" '${devicePort}', '${username}', '${password}', '${expires}', '${keepTimeout}', '${transport}', '${characterSet}', ${ptz}, ${rtcp}, " + " #{devicePort}, #{username}, #{password}, #{expires}, #{keepTimeout}, #{transport}, #{characterSet}, #{ptz}, #{rtcp}, " +
" ${status}, ${startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{treeType})") " #{status}, #{startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{treeType})")
int addParentPlatform(ParentPlatform parentPlatform); int addParentPlatform(ParentPlatform parentPlatform);
@Update("UPDATE parent_platform " + @Update("UPDATE parent_platform " +
@ -41,7 +41,7 @@ public interface ParentPlatformMapper {
"ptz=#{ptz}, " + "ptz=#{ptz}, " +
"rtcp=#{rtcp}, " + "rtcp=#{rtcp}, " +
"status=#{status}, " + "status=#{status}, " +
"startOfflinePush=${startOfflinePush}, " + "startOfflinePush=#{startOfflinePush}, " +
"catalogGroup=#{catalogGroup}, " + "catalogGroup=#{catalogGroup}, " +
"administrativeDivision=#{administrativeDivision}, " + "administrativeDivision=#{administrativeDivision}, " +
"createTime=#{createTime}, " + "createTime=#{createTime}, " +

View File

@ -21,22 +21,22 @@ public interface PlatformChannelMapper {
* 查询列表里已经关联的 * 查询列表里已经关联的
*/ */
@Select("<script> "+ @Select("<script> "+
"SELECT deviceChannelId FROM platform_gb_channel WHERE platformId='${platformId}' AND deviceChannelId in" + "SELECT deviceChannelId FROM platform_gb_channel WHERE platformId=#{platformId} AND deviceChannelId in" +
"<foreach collection='channelReduces' open='(' item='item' separator=',' close=')'> '${item.id}'</foreach>" + "<foreach collection='channelReduces' open='(' item='item' separator=',' close=')'> #{item.id}</foreach>" +
"</script>") "</script>")
List<Integer> findChannelRelatedPlatform(String platformId, List<ChannelReduce> channelReduces); List<Integer> findChannelRelatedPlatform(String platformId, List<ChannelReduce> channelReduces);
@Insert("<script> "+ @Insert("<script> "+
"INSERT INTO platform_gb_channel (platformId, deviceChannelId, catalogId) VALUES" + "INSERT INTO platform_gb_channel (platformId, deviceChannelId, catalogId) VALUES" +
"<foreach collection='channelReducesToAdd' item='item' separator=','>" + "<foreach collection='channelReducesToAdd' item='item' separator=','>" +
" ('${platformId}', '${item.id}' , '${item.catalogId}' )" + " (#{platformId}, #{item.id} , #{item.catalogId} )" +
"</foreach>" + "</foreach>" +
"</script>") "</script>")
int addChannels(String platformId, List<ChannelReduce> channelReducesToAdd); int addChannels(String platformId, List<ChannelReduce> channelReducesToAdd);
@Delete("<script> "+ @Delete("<script> "+
"DELETE FROM platform_gb_channel WHERE platformId='${platformId}' AND deviceChannelId in" + "DELETE FROM platform_gb_channel WHERE platformId=#{platformId} AND deviceChannelId in" +
"<foreach collection='channelReducesToDel' item='item' open='(' separator=',' close=')' > '${item.id}'</foreach>" + "<foreach collection='channelReducesToDel' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
"</script>") "</script>")
int delChannelForGB(String platformId, List<ChannelReduce> channelReducesToDel); int delChannelForGB(String platformId, List<ChannelReduce> channelReducesToDel);
@ -50,14 +50,14 @@ public interface PlatformChannelMapper {
int delChannelForDeviceId(String deviceId); int delChannelForDeviceId(String deviceId);
@Delete("<script> "+ @Delete("<script> "+
"DELETE FROM platform_gb_channel WHERE platformId='${platformId}'" + "DELETE FROM platform_gb_channel WHERE platformId=#{platformId}" +
"</script>") "</script>")
int cleanChannelForGB(String platformId); 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<DeviceChannel> queryChannelInParentPlatform(String platformId, String channelId); List<DeviceChannel> 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<DeviceChannel> queryAllChannelInCatalog(String platformId, String catalogId); List<DeviceChannel> 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 " + @Select(" select dc.channelId as id, dc.name as name, pgc.platformId as platformId, pgc.catalogId as parentId, 0 as childrenCount, 1 as type " +

View File

@ -26,7 +26,7 @@ public interface PlatformGbStreamMapper {
"(gbStreamId, platformId, catalogId) " + "(gbStreamId, platformId, catalogId) " +
"values " + "values " +
"<foreach collection='streamPushItems' index='index' item='item' separator=','> " + "<foreach collection='streamPushItems' index='index' item='item' separator=','> " +
"(${item.gbStreamId}, '${item.platformId}', '${item.catalogId}')" + "(#{item.gbStreamId}, #{item.platformId}, #{item.catalogId})" +
"</foreach> " + "</foreach> " +
"</script>") "</script>")
int batchAdd(List<StreamPushItem> streamPushItems); int batchAdd(List<StreamPushItem> streamPushItems);

View File

@ -14,10 +14,10 @@ import java.util.List;
public interface RecordInfoDao { public interface RecordInfoDao {
@Insert("INSERT INTO recordInfo (app, stream, mediaServerId, createTime, type, deviceId, channelId, name) VALUES" + @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); int add(RecordInfo recordInfo);
@Delete("DELETE FROM user WHERE createTime < '${beforeTime}'") @Delete("DELETE FROM user WHERE createTime < #{beforeTime}")
int deleteBefore(String beforeTime); int deleteBefore(String beforeTime);
@Select("select * FROM recordInfo") @Select("select * FROM recordInfo")

View File

@ -12,14 +12,14 @@ import java.util.List;
public interface RoleMapper { public interface RoleMapper {
@Insert("INSERT INTO user_role (name, authority, createTime, updateTime) VALUES" + @Insert("INSERT INTO user_role (name, authority, createTime, updateTime) VALUES" +
"('${name}', '${authority}', '${createTime}', '${updateTime}')") "(#{name}, #{authority}, #{createTime}, #{updateTime})")
int add(Role role); int add(Role role);
@Update(value = {" <script>" + @Update(value = {" <script>" +
"UPDATE user_role " + "UPDATE user_role " +
"SET updateTime='${updateTime}' " + "SET updateTime=#{updateTime} " +
"<if test=\"name != null\">, name='${name}'</if>" + "<if test=\"name != null\">, name=#{name}</if>" +
"<if test=\"authority != null\">, authority='${authority}'</if>" + "<if test=\"authority != null\">, authority=#{authority}</if>" +
"WHERE id != 1 and id=#{id}" + "WHERE id != 1 and id=#{id}" +
" </script>"}) " </script>"})
int update(Role role); int update(Role role);

View File

@ -13,9 +13,9 @@ public interface StreamProxyMapper {
@Insert("INSERT INTO stream_proxy (type, name, app, stream,mediaServerId, url, src_url, dst_url, " + @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" + "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}', " + "(#{type}, #{name}, #{app}, #{stream}, #{mediaServerId}, #{url}, #{src_url}, #{dst_url}, " +
"'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_audio}, ${enable_mp4}, ${enable}, ${status}, " + "#{timeout_ms}, #{ffmpeg_cmd_key}, #{rtp_type}, #{enable_audio}, #{enable_mp4}, #{enable}, #{status}, " +
"${enable_remove_none_reader}, ${enable_disable_none_reader}, '${createTime}' )") "#{enable_remove_none_reader}, #{enable_disable_none_reader}, #{createTime} )")
int add(StreamProxyItem streamProxyDto); int add(StreamProxyItem streamProxyDto);
@Update("UPDATE stream_proxy " + @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") @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<StreamProxyItem> selectAll(); List<StreamProxyItem> 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<StreamProxyItem> selectForEnable(boolean enable); List<StreamProxyItem> 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") @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 " + @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 " + "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<StreamProxyItem> selectForEnableInMediaServer(String id, boolean enable); List<StreamProxyItem> selectForEnableInMediaServer(String id, boolean enable);
@Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st " + @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 " + "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<StreamProxyItem> selectInMediaServer(String id); List<StreamProxyItem> selectInMediaServer(String id);
@Update("UPDATE stream_proxy " + @Update("UPDATE stream_proxy " +
@ -67,7 +67,7 @@ public interface StreamProxyMapper {
void updateStatusByMediaServerId(String mediaServerId, boolean status); void updateStatusByMediaServerId(String mediaServerId, boolean status);
@Update("UPDATE stream_proxy " + @Update("UPDATE stream_proxy " +
"SET status=${status} " + "SET status=#{status} " +
"WHERE app=#{app} AND stream=#{stream}") "WHERE app=#{app} AND stream=#{stream}")
int updateStatus(String app, String stream, boolean status); int updateStatus(String app, String stream, boolean status);

View File

@ -17,23 +17,23 @@ public interface StreamPushMapper {
@Insert("INSERT INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " + @Insert("INSERT INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " +
"pushTime, aliveSecond, mediaServerId, serverId, updateTime, createTime, pushIng, self) VALUES" + "pushTime, aliveSecond, mediaServerId, serverId, updateTime, createTime, pushIng, self) VALUES" +
"('${app}', '${stream}', '${totalReaderCount}', '${originType}', '${originTypeStr}', " + "(#{app}, #{stream}, #{totalReaderCount}, #{originType}, #{originTypeStr}, " +
"'${pushTime}', '${aliveSecond}', '${mediaServerId}' , '${serverId}' , '${updateTime}' , '${createTime}', " + "#{pushTime}, #{aliveSecond}, #{mediaServerId} , #{serverId} , #{updateTime} , #{createTime}, " +
"${pushIng}, ${self} )") "#{pushIng}, #{self} )")
int add(StreamPushItem streamPushItem); int add(StreamPushItem streamPushItem);
@Update(value = {" <script>" + @Update(value = {" <script>" +
"UPDATE stream_push " + "UPDATE stream_push " +
"SET updateTime='${updateTime}'" + "SET updateTime=#{updateTime}" +
"<if test=\"mediaServerId != null\">, mediaServerId='${mediaServerId}'</if>" + "<if test=\"mediaServerId != null\">, mediaServerId=#{mediaServerId}</if>" +
"<if test=\"totalReaderCount != null\">, totalReaderCount='${totalReaderCount}'</if>" + "<if test=\"totalReaderCount != null\">, totalReaderCount=#{totalReaderCount}</if>" +
"<if test=\"originType != null\">, originType=${originType}</if>" + "<if test=\"originType != null\">, originType=#{originType}</if>" +
"<if test=\"originTypeStr != null\">, originTypeStr='${originTypeStr}'</if>" + "<if test=\"originTypeStr != null\">, originTypeStr=#{originTypeStr}</if>" +
"<if test=\"pushTime != null\">, pushTime='${pushTime}'</if>" + "<if test=\"pushTime != null\">, pushTime=#{pushTime}</if>" +
"<if test=\"aliveSecond != null\">, aliveSecond='${aliveSecond}'</if>" + "<if test=\"aliveSecond != null\">, aliveSecond=#{aliveSecond}</if>" +
"<if test=\"pushIng != null\">, pushIng=${pushIng}</if>" + "<if test=\"pushIng != null\">, pushIng=#{pushIng}</if>" +
"<if test=\"self != null\">, self=${self}</if>" + "<if test=\"self != null\">, self=#{self}</if>" +
"WHERE app=#{app} AND stream=#{stream}"+ "WHERE app=#{app} AND stream=#{stream}"+
" </script>"}) " </script>"})
int update(StreamPushItem streamPushItem); int update(StreamPushItem streamPushItem);
@ -76,7 +76,7 @@ public interface StreamPushMapper {
"on st.app = gs.app AND st.stream = gs.stream " + "on st.app = gs.app AND st.stream = gs.stream " +
"WHERE " + "WHERE " +
"1=1 " + "1=1 " +
" <if test='query != null'> AND (st.app LIKE '%${query}%' OR st.stream LIKE '%${query}%' OR gs.gbId LIKE '%${query}%' OR gs.name LIKE '%${query}%')</if> " + " <if test='query != null'> AND (st.app LIKE concat('%',#{query},'%') OR st.stream LIKE concat('%',#{query},'%') OR gs.gbId LIKE concat('%',#{query},'%') OR gs.name LIKE concat('%',#{query},'%'))</if> " +
" <if test='pushing == true' > AND (gs.gbId is null OR st.pushIng=1)</if>" + " <if test='pushing == true' > AND (gs.gbId is null OR st.pushIng=1)</if>" +
" <if test='pushing == false' > AND (st.pushIng is null OR st.pushIng=0) </if>" + " <if test='pushing == false' > AND (st.pushIng is null OR st.pushIng=0) </if>" +
" <if test='mediaServerId != null' > AND st.mediaServerId=#{mediaServerId} </if>" + " <if test='mediaServerId != null' > AND st.mediaServerId=#{mediaServerId} </if>" +
@ -94,9 +94,9 @@ public interface StreamPushMapper {
"Insert IGNORE INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " + "Insert IGNORE INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " +
"createTime, aliveSecond, mediaServerId, status, pushIng) " + "createTime, aliveSecond, mediaServerId, status, pushIng) " +
"VALUES <foreach collection='streamPushItems' item='item' index='index' separator=','>" + "VALUES <foreach collection='streamPushItems' item='item' index='index' separator=','>" +
"( '${item.app}', '${item.stream}', '${item.totalReaderCount}', #{item.originType}, " + "( #{item.app}, #{item.stream}, #{item.totalReaderCount}, #{item.originType}, " +
"'${item.originTypeStr}',#{item.createTime}, #{item.aliveSecond}, '${item.mediaServerId}', ${item.status} ," + "#{item.originTypeStr},#{item.createTime}, #{item.aliveSecond}, #{item.mediaServerId}, #{item.status} ," +
" ${item.pushIng} )" + " #{item.pushIng} )" +
" </foreach>" + " </foreach>" +
"</script>") "</script>")
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id") @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@ -115,12 +115,12 @@ public interface StreamPushMapper {
List<StreamPushItem> selectAllByMediaServerIdWithOutGbID(String mediaServerId); List<StreamPushItem> selectAllByMediaServerIdWithOutGbID(String mediaServerId);
@Update("UPDATE stream_push " + @Update("UPDATE stream_push " +
"SET status=${status} " + "SET status=#{status} " +
"WHERE app=#{app} AND stream=#{stream}") "WHERE app=#{app} AND stream=#{stream}")
int updateStatus(String app, String stream, boolean status); int updateStatus(String app, String stream, boolean status);
@Update("UPDATE stream_push " + @Update("UPDATE stream_push " +
"SET pushIng=${pushIng} " + "SET pushIng=#{pushIng} " +
"WHERE app=#{app} AND stream=#{stream}") "WHERE app=#{app} AND stream=#{stream}")
int updatePushStatus(String app, String stream, boolean pushIng); int updatePushStatus(String app, String stream, boolean pushIng);

View File

@ -11,16 +11,16 @@ import java.util.List;
public interface UserMapper { public interface UserMapper {
@Insert("INSERT INTO user (username, password, roleId, pushKey, createTime, updateTime) VALUES" + @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); int add(User user);
@Update(value = {" <script>" + @Update(value = {" <script>" +
"UPDATE user " + "UPDATE user " +
"SET updateTime='${updateTime}' " + "SET updateTime=#{updateTime} " +
"<if test=\"pushKey != null\">, pushKey='${pushKey}'</if>" + "<if test=\"pushKey != null\">, pushKey=#{pushKey}</if>" +
"<if test=\"role != null\">, roleId='${role.id}'</if>" + "<if test=\"role != null\">, roleId=#{role.id}</if>" +
"<if test=\"password != null\">, password='${password}'</if>" + "<if test=\"password != null\">, password=#{password}</if>" +
"<if test=\"username != null\">, username='${username}'</if>" + "<if test=\"username != null\">, username=#{username}</if>" +
"WHERE id=#{id}" + "WHERE id=#{id}" +
" </script>"}) " </script>"})
int update(User user); int update(User user);
@ -50,10 +50,10 @@ public interface UserMapper {
@ResultMap(value="roleMap") @ResultMap(value="roleMap")
List<User> selectAll(); List<User> 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<User> checkPushAuthorityByCallIdAndSign(String callId, String sign); List<User> checkPushAuthorityByCallIdAndSign(String callId, String sign);
@Select("select * from user where md5(pushKey) = '${sign}'") @Select("select * from user where md5(pushKey) = #{sign}")
List<User> checkPushAuthorityByCallId(String sign); List<User> checkPushAuthorityByCallId(String sign);
@Select("select u.id, u.username,u.pushKey,u.roleId, r.id as roleID, r.name as roleName, r.authority as roleAuthority , r.createTime as roleCreateTime , r.updateTime as roleUpdateTime FROM user u join user_role r on u.roleId=r.id") @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")

View File

@ -224,31 +224,31 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
PageHelper.startPage(page, count); PageHelper.startPage(page, count);
List<DeviceChannel> all; List<DeviceChannel> all;
if (catalogUnderDevice != null && catalogUnderDevice) { if (catalogUnderDevice != null && catalogUnderDevice) {
all = deviceChannelMapper.queryChannels(deviceId, deviceId, query, hasSubChannel, online); all = deviceChannelMapper.queryChannels(deviceId, deviceId, query, hasSubChannel, online,null);
// 海康设备的parentId是SIP id // 海康设备的parentId是SIP id
List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, sipConfig.getId(), query, hasSubChannel, online); List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, sipConfig.getId(), query, hasSubChannel, online,null);
all.addAll(deviceChannels); all.addAll(deviceChannels);
}else { }else {
all = deviceChannelMapper.queryChannels(deviceId, null, query, hasSubChannel, online); all = deviceChannelMapper.queryChannels(deviceId, null, query, hasSubChannel, online,null);
} }
return new PageInfo<>(all); return new PageInfo<>(all);
} }
@Override @Override
public List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit) { public List<DeviceChannel> queryChannelsByDeviceIdWithStartAndLimit(String deviceId, String query, Boolean hasSubChannel, Boolean online, int start, int limit,List<String> channelIds) {
return deviceChannelMapper.queryChannelsByDeviceIdWithStartAndLimit(deviceId, null, query, hasSubChannel, online, start, limit); return deviceChannelMapper.queryChannelsByDeviceIdWithStartAndLimit(deviceId, null, query, hasSubChannel, online, start, limit,channelIds);
} }
@Override @Override
public List<DeviceChannel> queryChannelsByDeviceId(String deviceId) { public List<DeviceChannel> queryChannelsByDeviceId(String deviceId,Boolean online,List<String> channelIds) {
return deviceChannelMapper.queryChannels(deviceId, null,null, null, null); return deviceChannelMapper.queryChannels(deviceId, null,null, null, online,channelIds);
} }
@Override @Override
public PageInfo<DeviceChannel> querySubChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online, int page, int count) { public PageInfo<DeviceChannel> querySubChannels(String deviceId, String parentChannelId, String query, Boolean hasSubChannel, Boolean online, int page, int count) {
PageHelper.startPage(page, count); PageHelper.startPage(page, count);
List<DeviceChannel> all = deviceChannelMapper.queryChannels(deviceId, parentChannelId, query, hasSubChannel, online); List<DeviceChannel> all = deviceChannelMapper.queryChannels(deviceId, parentChannelId, query, hasSubChannel, online,null);
return new PageInfo<>(all); return new PageInfo<>(all);
} }
@ -271,9 +271,9 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
* @return PageInfo<Device> 分页设备对象数组 * @return PageInfo<Device> 分页设备对象数组
*/ */
@Override @Override
public PageInfo<Device> queryVideoDeviceList(int page, int count) { public PageInfo<Device> queryVideoDeviceList(int page, int count,Boolean online) {
PageHelper.startPage(page, count); PageHelper.startPage(page, count);
List<Device> all = deviceMapper.getDevices(); List<Device> all = deviceMapper.getDevices(online);
return new PageInfo<>(all); return new PageInfo<>(all);
} }
@ -283,9 +283,9 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
* @return List<Device> 设备对象数组 * @return List<Device> 设备对象数组
*/ */
@Override @Override
public List<Device> queryVideoDeviceList() { public List<Device> queryVideoDeviceList(Boolean online) {
List<Device> deviceList = deviceMapper.getDevices(); List<Device> deviceList = deviceMapper.getDevices(online);
return deviceList; return deviceList;
} }

View File

@ -1,14 +1,13 @@
package com.genersoft.iot.vmp.utils.redis; package com.genersoft.iot.vmp.utils.redis;
import java.util.*;
import java.util.concurrent.TimeUnit;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.genersoft.iot.vmp.utils.SpringBeanFactory; import com.genersoft.iot.vmp.utils.SpringBeanFactory;
import gov.nist.javax.sip.stack.UDPMessageChannel;
import org.springframework.data.redis.core.*; import org.springframework.data.redis.core.*;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.concurrent.TimeUnit;
/** /**
* Redis工具类 * Redis工具类
* @author swwheihei * @author swwheihei

View File

@ -1,9 +1,5 @@
package com.genersoft.iot.vmp.vmanager.bean; package com.genersoft.iot.vmp.vmanager.bean;
import com.genersoft.iot.vmp.common.StreamInfo;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItemLite;
/** /**
* @author lin * @author lin
*/ */
@ -11,7 +7,7 @@ public class AudioBroadcastResult {
/** /**
* 推流的各个方式流地址 * 推流的各个方式流地址
*/ */
private StreamInfo streamInfo; private StreamContent streamInfo;
/** /**
* 编码格式 * 编码格式
@ -29,11 +25,11 @@ public class AudioBroadcastResult {
private String stream; private String stream;
public StreamInfo getStreamInfo() { public StreamContent getStreamInfo() {
return streamInfo; return streamInfo;
} }
public void setStreamInfo(StreamInfo streamInfo) { public void setStreamInfo(StreamContent streamInfo) {
this.streamInfo = streamInfo; this.streamInfo = streamInfo;
} }

View File

@ -1,7 +1,5 @@
package com.genersoft.iot.vmp.vmanager.bean; package com.genersoft.iot.vmp.vmanager.bean;
import io.swagger.v3.oas.annotations.media.Schema;
/** /**
* 全局错误码 * 全局错误码
*/ */
@ -9,6 +7,7 @@ public enum ErrorCode {
SUCCESS(0, "成功"), SUCCESS(0, "成功"),
ERROR100(100, "失败"), ERROR100(100, "失败"),
ERROR400(400, "参数不全或者错误"), ERROR400(400, "参数不全或者错误"),
ERROR404(404, "资源未找到"),
ERROR403(403, "无权限操作"), ERROR403(403, "无权限操作"),
ERROR401(401, "请登录后重新请求"), ERROR401(401, "请登录后重新请求"),
ERROR500(500, "系统异常"); ERROR500(500, "系统异常");

View File

@ -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;
}
}

View File

@ -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.callback.RequestMessage;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; 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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
@ -130,15 +127,14 @@ public class DeviceControl {
*/ */
@Operation(summary = "布防/撤防命令") @Operation(summary = "布防/撤防命令")
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true)
@Parameter(name = "guardCmdStr", description = "命令, 可选值SetGuard布防ResetGuard撤防", required = true) @Parameter(name = "guardCmdStr", description = "命令, 可选值SetGuard布防ResetGuard撤防", required = true)
@GetMapping("/guard/{deviceId}/{guardCmdStr}") @GetMapping("/guard/{deviceId}/{guardCmdStr}")
public DeferredResult<String> guardApi(@PathVariable String deviceId, String channelId, @PathVariable String guardCmdStr) { public DeferredResult<String> guardApi(@PathVariable String deviceId, @PathVariable String guardCmdStr) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("布防/撤防API调用"); logger.debug("布防/撤防API调用");
} }
Device device = storager.queryVideoDevice(deviceId); 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(); String uuid =UUID.randomUUID().toString();
try { try {
cmder.guardCmd(device, guardCmdStr, event -> { cmder.guardCmd(device, guardCmdStr, event -> {

View File

@ -99,7 +99,7 @@ public class DeviceQuery {
@GetMapping("/devices") @GetMapping("/devices")
public PageInfo<Device> devices(int page, int count){ public PageInfo<Device> devices(int page, int count){
return storager.queryVideoDeviceList(page, count); return storager.queryVideoDeviceList(page, count,null);
} }
/** /**

View File

@ -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.SecurityUtils;
import com.genersoft.iot.vmp.conf.security.dto.LoginUser; import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; 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.IMediaService;
import com.genersoft.iot.vmp.service.IStreamProxyService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 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.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@ -53,7 +53,7 @@ public class MediaController {
@Parameter(name = "useSourceIpAsStreamIp", description = "是否使用请求IP作为返回的地址IP") @Parameter(name = "useSourceIpAsStreamIp", description = "是否使用请求IP作为返回的地址IP")
@GetMapping(value = "/stream_info_by_app_and_stream") @GetMapping(value = "/stream_info_by_app_and_stream")
@ResponseBody @ResponseBody
public StreamInfo getStreamInfoByAppAndStream(HttpServletRequest request, @RequestParam String app, public StreamContent getStreamInfoByAppAndStream(HttpServletRequest request, @RequestParam String app,
@RequestParam String stream, @RequestParam String stream,
@RequestParam(required = false) String mediaServerId, @RequestParam(required = false) String mediaServerId,
@RequestParam(required = false) String callId, @RequestParam(required = false) String callId,
@ -88,9 +88,8 @@ public class MediaController {
streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority); streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority);
} }
WVPResult<StreamInfo> result = new WVPResult<>();
if (streamInfo != null){ if (streamInfo != null){
return streamInfo; return new StreamContent(streamInfo);
}else { }else {
//获取流失败重启拉流后重试一次 //获取流失败重启拉流后重试一次
streamProxyService.stop(app,stream); streamProxyService.stop(app,stream);
@ -109,7 +108,7 @@ public class MediaController {
streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority); streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority);
} }
if (streamInfo != null){ if (streamInfo != null){
return streamInfo; return new StreamContent(streamInfo);
}else { }else {
throw new ControllerException(ErrorCode.ERROR100); throw new ControllerException(ErrorCode.ERROR100);
} }

View File

@ -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.DeferredResultEx;
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 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 com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
@ -85,7 +86,7 @@ public class PlayController {
@Parameter(name = "deviceId", description = "设备国标编号", required = true) @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@GetMapping("/start/{deviceId}/{channelId}") @GetMapping("/start/{deviceId}/{channelId}")
public DeferredResult<WVPResult<StreamInfo>> play(HttpServletRequest request, @PathVariable String deviceId, public DeferredResult<WVPResult<StreamContent>> play(HttpServletRequest request, @PathVariable String deviceId,
@PathVariable String channelId) { @PathVariable String channelId) {
// 获取可用的zlm // 获取可用的zlm
@ -98,8 +99,8 @@ public class PlayController {
msg.setKey(key); msg.setKey(key);
String uuid = UUID.randomUUID().toString(); String uuid = UUID.randomUUID().toString();
msg.setId(uuid); msg.setId(uuid);
DeferredResult<WVPResult<StreamInfo>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
DeferredResultEx<WVPResult<StreamInfo>> deferredResultEx = new DeferredResultEx<>(result); DeferredResultEx<WVPResult<StreamContent>> deferredResultEx = new DeferredResultEx<>(result);
result.onTimeout(()->{ result.onTimeout(()->{
logger.info("点播接口等待超时"); logger.info("点播接口等待超时");
@ -110,25 +111,22 @@ public class PlayController {
msg.setData(wvpResult); msg.setData(wvpResult);
resultHolder.invokeResult(msg); resultHolder.invokeResult(msg);
}); });
if (userSetting.getUseSourceIpAsStreamIp()) {
// TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误 // TODO 在点播未成功的情况下在此调用接口点播会导致返回的流地址ip错误
deferredResultEx.setFilter(result1 -> { deferredResultEx.setFilter(result1 -> {
WVPResult<StreamInfo> wvpResult1 = (WVPResult<StreamInfo>)result1; WVPResult<StreamInfo> wvpResult1 = (WVPResult<StreamInfo>)result1;
WVPResult<StreamInfo> clone = null; WVPResult<StreamContent> resultStream = new WVPResult<>();
try { resultStream.setCode(wvpResult1.getCode());
clone = (WVPResult<StreamInfo>)wvpResult1.clone(); resultStream.setMsg(wvpResult1.getMsg());
} catch (CloneNotSupportedException e) { if (wvpResult1.getCode() == ErrorCode.SUCCESS.getCode()) {
throw new RuntimeException(e); StreamInfo data = wvpResult1.getData().clone();
} if (userSetting.getUseSourceIpAsStreamIp()) {
if (clone.getCode() == ErrorCode.SUCCESS.getCode()) {
StreamInfo data = clone.getData().clone();
data.channgeStreamIp(request.getLocalName()); data.channgeStreamIp(request.getLocalName());
clone.setData(data);
} }
return clone; resultStream.setData(new StreamContent(wvpResult1.getData()));
}
return resultStream;
}); });
}
// 录像查询以channelId作为deviceId查询 // 录像查询以channelId作为deviceId查询
resultHolder.put(key, uuid, deferredResultEx); resultHolder.put(key, uuid, deferredResultEx);
@ -273,7 +271,7 @@ public class PlayController {
@GetMapping("/1111") @GetMapping("/1111")
public void broadcastApi1() { public void broadcastApi1() {
MediaServerItem defaultMediaServer = mediaServerService.getMediaServerForMinimumLoad(); MediaServerItem defaultMediaServer = mediaServerService.getMediaServerForMinimumLoad(null);
Device device = storager.queryVideoDevice("34020000001320090001"); Device device = storager.queryVideoDevice("34020000001320090001");
playService.talk(defaultMediaServer, device, "34020000001370000001", null, null, null); playService.talk(defaultMediaServer, device, "34020000001370000001", null, null, null);

View File

@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.IPlayService;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 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 com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; 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.InvalidArgumentException;
import javax.sip.SipException; import javax.sip.SipException;
import java.text.ParseException; import java.text.ParseException;
import java.util.UUID;
/** /**
* @author lin * @author lin
@ -68,24 +70,37 @@ public class PlaybackController {
@Parameter(name = "startTime", description = "开始时间", required = true) @Parameter(name = "startTime", description = "开始时间", required = true)
@Parameter(name = "endTime", description = "结束时间", required = true) @Parameter(name = "endTime", description = "结束时间", required = true)
@GetMapping("/start/{deviceId}/{channelId}") @GetMapping("/start/{deviceId}/{channelId}")
public DeferredResult<WVPResult<StreamInfo>> play(@PathVariable String deviceId, @PathVariable String channelId, public DeferredResult<WVPResult<StreamContent>> play(@PathVariable String deviceId, @PathVariable String channelId,
String startTime, String endTime) { String startTime, String endTime) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(String.format("设备回放 API调用deviceId%s channelId%s", deviceId, channelId)); 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<WVPResult<StreamContent>> result = new DeferredResult<>(30000L);
resultHolder.put(key, uuid, result);
return playService.playBack(deviceId, channelId, startTime, endTime, null, WVPResult<StreamContent> wvpResult = new WVPResult<>();
RequestMessage msg = new RequestMessage();
msg.setKey(key);
msg.setId(uuid);
playService.playBack(deviceId, channelId, startTime, endTime, null,
playBackResult->{ playBackResult->{
if (playBackResult.getCode() != ErrorCode.SUCCESS.getCode()) { wvpResult.setCode(playBackResult.getCode());
RequestMessage data = playBackResult.getData(); wvpResult.setMsg(playBackResult.getMsg());
data.setData(WVPResult.fail(playBackResult.getCode(), playBackResult.getMsg())); if (playBackResult.getCode() == ErrorCode.SUCCESS.getCode()) {
resultHolder.invokeResult(data); StreamInfo streamInfo = (StreamInfo)playBackResult.getData();
}else { wvpResult.setData(new StreamContent(streamInfo));
resultHolder.invokeResult(playBackResult.getData());
} }
msg.setData(wvpResult);
resultHolder.invokeResult(msg);
}); });
return result;
} }

View File

@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.IPlayService;
import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.DateUtil;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 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 com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@ -121,15 +122,33 @@ public class GBRecordController {
@Parameter(name = "endTime", description = "结束时间", required = true) @Parameter(name = "endTime", description = "结束时间", required = true)
@Parameter(name = "downloadSpeed", description = "下载倍速", required = true) @Parameter(name = "downloadSpeed", description = "下载倍速", required = true)
@GetMapping("/download/start/{deviceId}/{channelId}") @GetMapping("/download/start/{deviceId}/{channelId}")
public DeferredResult<WVPResult<StreamInfo>> download(@PathVariable String deviceId, @PathVariable String channelId, public DeferredResult<WVPResult<StreamContent>> download(@PathVariable String deviceId, @PathVariable String channelId,
String startTime, String endTime, String downloadSpeed) { String startTime, String endTime, String downloadSpeed) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(String.format("历史媒体下载 API调用deviceId%schannelId%sdownloadSpeed%s", deviceId, channelId, downloadSpeed)); logger.debug(String.format("历史媒体下载 API调用deviceId%schannelId%sdownloadSpeed%s", deviceId, channelId, downloadSpeed));
} }
DeferredResult<WVPResult<StreamInfo>> result = playService.download(deviceId, channelId, startTime, endTime, Integer.parseInt(downloadSpeed), null, hookCallBack->{ String uuid = UUID.randomUUID().toString();
resultHolder.invokeResult(hookCallBack.getData()); String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId;
DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(30000L);
resultHolder.put(key, uuid, result);
RequestMessage msg = new RequestMessage();
msg.setId(uuid);
msg.setKey(key);
WVPResult<StreamContent> 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; return result;
@ -168,7 +187,11 @@ public class GBRecordController {
@Parameter(name = "channelId", description = "通道国标编号", required = true) @Parameter(name = "channelId", description = "通道国标编号", required = true)
@Parameter(name = "stream", description = "流ID", required = true) @Parameter(name = "stream", description = "流ID", required = true)
@GetMapping("/download/progress/{deviceId}/{channelId}/{stream}") @GetMapping("/download/progress/{deviceId}/{channelId}/{stream}")
public StreamInfo getProgress(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) { public StreamContent getProgress(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
return playService.getDownLoadInfo(deviceId, channelId, stream); StreamInfo downLoadInfo = playService.getDownLoadInfo(deviceId, channelId, stream);
if (downLoadInfo == null) {
throw new ControllerException(ErrorCode.ERROR404);
}
return new StreamContent(downLoadInfo);
} }
} }

View File

@ -1,13 +1,13 @@
package com.genersoft.iot.vmp.vmanager.streamProxy; package com.genersoft.iot.vmp.vmanager.streamProxy;
import com.alibaba.fastjson2.JSONObject; 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.conf.exception.ControllerException;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.service.IStreamProxyService;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
@ -58,7 +58,7 @@ public class StreamProxyController {
}) })
@PostMapping(value = "/save") @PostMapping(value = "/save")
@ResponseBody @ResponseBody
public StreamInfo save(@RequestBody StreamProxyItem param){ public StreamContent save(@RequestBody StreamProxyItem param){
logger.info("添加代理: " + JSONObject.toJSONString(param)); logger.info("添加代理: " + JSONObject.toJSONString(param));
if (ObjectUtils.isEmpty(param.getMediaServerId())) { if (ObjectUtils.isEmpty(param.getMediaServerId())) {
param.setMediaServerId("auto"); param.setMediaServerId("auto");
@ -69,7 +69,7 @@ public class StreamProxyController {
if (ObjectUtils.isEmpty(param.getGbId())) { if (ObjectUtils.isEmpty(param.getGbId())) {
param.setGbId(null); param.setGbId(null);
} }
return streamProxyService.save(param); return new StreamContent(streamProxyService.save(param));
} }
@GetMapping(value = "/ffmpeg_cmd/list") @GetMapping(value = "/ffmpeg_cmd/list")

View File

@ -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.bean.GbStream;
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 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.media.zlm.dto.StreamPushItem;
import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.IMediaService; import com.genersoft.iot.vmp.service.IMediaService;
import com.genersoft.iot.vmp.service.IStreamPushService; import com.genersoft.iot.vmp.service.IStreamPushService;
import com.genersoft.iot.vmp.service.impl.StreamPushUploadFileHandler; import com.genersoft.iot.vmp.service.impl.StreamPushUploadFileHandler;
import com.genersoft.iot.vmp.vmanager.bean.BatchGBStreamParam; import com.genersoft.iot.vmp.vmanager.bean.*;
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.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.poi.sl.usermodel.Sheet;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -34,12 +28,10 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.HashMap; import java.util.HashMap;
@ -243,7 +235,7 @@ public class StreamPushController {
@Parameter(name = "app", description = "应用名", required = true) @Parameter(name = "app", description = "应用名", required = true)
@Parameter(name = "stream", description = "流id", required = true) @Parameter(name = "stream", description = "流id", required = true)
@Parameter(name = "mediaServerId", description = "媒体服务器id") @Parameter(name = "mediaServerId", description = "媒体服务器id")
public StreamInfo getPlayUrl(@RequestParam String app,@RequestParam String stream, public StreamContent getPlayUrl(@RequestParam String app, @RequestParam String stream,
@RequestParam(required = false) String mediaServerId){ @RequestParam(required = false) String mediaServerId){
boolean authority = false; boolean authority = false;
// 是否登陆用户, 登陆用户返回完整信息 // 是否登陆用户, 登陆用户返回完整信息
@ -259,7 +251,7 @@ public class StreamPushController {
if (streamInfo == null){ if (streamInfo == null){
throw new ControllerException(ErrorCode.ERROR100.getCode(), "获取播放地址失败"); throw new ControllerException(ErrorCode.ERROR100.getCode(), "获取播放地址失败");
} }
return streamInfo; return new StreamContent(streamInfo);
} }
/** /**

View File

@ -10,8 +10,10 @@ import com.github.pagehelper.PageInfo;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
@ -59,10 +61,10 @@ public class ApiDeviceController {
JSONObject result = new JSONObject(); JSONObject result = new JSONObject();
List<Device> devices; List<Device> devices;
if (start == null || limit ==null) { if (start == null || limit ==null) {
devices = storager.queryVideoDeviceList(); devices = storager.queryVideoDeviceList(online);
result.put("DeviceCount", devices.size()); result.put("DeviceCount", devices.size());
}else { }else {
PageInfo<Device> deviceList = storager.queryVideoDeviceList(start/limit, limit); PageInfo<Device> deviceList = storager.queryVideoDeviceList(start/limit, limit,online);
result.put("DeviceCount", deviceList.getTotal()); result.put("DeviceCount", deviceList.getTotal());
devices = deviceList.getList(); devices = deviceList.getList();
} }
@ -94,6 +96,7 @@ public class ApiDeviceController {
@RequestMapping(value = "/channellist") @RequestMapping(value = "/channellist")
public JSONObject channellist( String serial, public JSONObject channellist( String serial,
@RequestParam(required = false)String code,
@RequestParam(required = false)String channel_type, @RequestParam(required = false)String channel_type,
@RequestParam(required = false)String dir_serial , @RequestParam(required = false)String dir_serial ,
@RequestParam(required = false)Integer start, @RequestParam(required = false)Integer start,
@ -113,12 +116,17 @@ public class ApiDeviceController {
return result; return result;
} }
List<DeviceChannel> deviceChannels; List<DeviceChannel> deviceChannels;
List<DeviceChannel> allDeviceChannelList = storager.queryChannelsByDeviceId(serial); List<String> channelIds = null;
if (!StringUtils.isEmpty(code)) {
String[] split = code.trim().split(",");
channelIds = Arrays.asList(split);
}
List<DeviceChannel> allDeviceChannelList = storager.queryChannelsByDeviceId(serial,online,channelIds);
if (start == null || limit ==null) { if (start == null || limit ==null) {
deviceChannels = allDeviceChannelList; deviceChannels = allDeviceChannelList;
result.put("ChannelCount", deviceChannels.size()); result.put("ChannelCount", deviceChannels.size());
}else { }else {
deviceChannels = storager.queryChannelsByDeviceIdWithStartAndLimit(serial, null, null, null,start, limit); deviceChannels = storager.queryChannelsByDeviceIdWithStartAndLimit(serial, null, null, online,start, limit,channelIds);
int total = allDeviceChannelList.size(); int total = allDeviceChannelList.size();
result.put("ChannelCount", total); result.put("ChannelCount", total);
} }
@ -148,9 +156,9 @@ public class ApiDeviceController {
// 1-IETF RFC3261, // 1-IETF RFC3261,
// 2-基于口令的双向认证, // 2-基于口令的双向认证,
// 3-基于数字证书的双向认证 // 3-基于数字证书的双向认证
deviceJOSNChannel.put("Status", deviceChannel.getStatus()); deviceJOSNChannel.put("Status", deviceChannel.getStatus() == 1 ? "ON":"OFF");
deviceJOSNChannel.put("Longitude", deviceChannel.getLongitudeWgs84()); deviceJOSNChannel.put("Longitude", deviceChannel.getLongitude());
deviceJOSNChannel.put("Latitude", deviceChannel.getLatitudeWgs84()); deviceJOSNChannel.put("Latitude", deviceChannel.getLatitude());
deviceJOSNChannel.put("PTZType ", deviceChannel.getPTZType()); // 云台类型, 0 - 未知, 1 - 球机, 2 - 半球, deviceJOSNChannel.put("PTZType ", deviceChannel.getPTZType()); // 云台类型, 0 - 未知, 1 - 球机, 2 - 半球,
// 3 - 固定枪机, 4 - 遥控枪机 // 3 - 固定枪机, 4 - 遥控枪机
deviceJOSNChannel.put("CustomPTZType", ""); deviceJOSNChannel.put("CustomPTZType", "");

View File

@ -12,7 +12,6 @@ import com.genersoft.iot.vmp.service.IDeviceService;
import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.IPlayService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -120,12 +119,12 @@ public class ApiStreamController {
result.put("ChannelID", code); result.put("ChannelID", code);
result.put("ChannelName", deviceChannel.getName()); result.put("ChannelName", deviceChannel.getName());
result.put("ChannelCustomName", ""); result.put("ChannelCustomName", "");
result.put("FLV", streamInfo.getFlv()); result.put("FLV", streamInfo.getFlv().getUrl());
result.put("WS_FLV", streamInfo.getWs_flv()); result.put("WS_FLV", streamInfo.getWs_flv().getUrl());
result.put("RTMP", streamInfo.getRtmp()); result.put("RTMP", streamInfo.getRtmp().getUrl());
result.put("HLS", streamInfo.getHls()); result.put("HLS", streamInfo.getHls().getUrl());
result.put("RTSP", streamInfo.getRtsp()); result.put("RTSP", streamInfo.getRtsp().getUrl());
result.put("WEBRTC", streamInfo.getRtc()); result.put("WEBRTC", streamInfo.getRtc().getUrl());
result.put("CDN", ""); result.put("CDN", "");
result.put("SnapURL", ""); result.put("SnapURL", "");
result.put("Transport", device.getTransport()); result.put("Transport", device.getTransport());

View File

@ -186,7 +186,7 @@ user-settings:
use-pushing-as-status: true use-pushing-as-status: true
# 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启 # 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
use-source-ip-as-stream-ip: true use-source-ip-as-stream-ip: true
# 按需拉流, true有人观看拉流无人观看释放 false拉起后不自动释放 # 国标点播 按需拉流, true有人观看拉流无人观看释放 false拉起后不自动释放
stream-on-demand: true stream-on-demand: true
# 推流鉴权, 默认开启 # 推流鉴权, 默认开启
push-authority: true push-authority: true
@ -197,6 +197,10 @@ user-settings:
sync-channel-on-device-online: false sync-channel-on-device-online: false
# 国标级联语音喊话发流模式 * UDP:udp传输 TCP-ACTIVEtcp主动模式 TCP-PASSIVEtcp被动模式 # 国标级联语音喊话发流模式 * UDP:udp传输 TCP-ACTIVEtcp主动模式 TCP-PASSIVEtcp被动模式
broadcast-for-platform: UDP broadcast-for-platform: UDP
# 是否使用设备来源Ip作为回复IP 不设置则为 false
sip-use-source-ip-as-remote-address: false
# 是否开启sip日志
sip-log: true
# 收到ack消息后开始发流默认false 回复200ok后直接开始发流 # 收到ack消息后开始发流默认false 回复200ok后直接开始发流
push-stream-after-ack: false push-stream-after-ack: false

View File

@ -30,7 +30,7 @@
</el-aside> </el-aside>
<el-main style="padding: 22px"> <el-main style="padding: 22px">
<div class="playBox" :style="playerStyle"> <div class="playBox" :style="playerStyle">
<player ref="recordVideoPlayer" :videoUrl="videoUrl" fluent autoplay :height="true" ></player> <player ref="recordVideoPlayer" :videoUrl="videoUrl" :height="true" style="width: 100%" ></player>
</div> </div>
<div class="player-option-box" > <div class="player-option-box" >
<el-slider <el-slider
@ -310,7 +310,20 @@
let h = parseInt(val/3600); let h = parseInt(val/3600);
let m = parseInt((val - h*3600)/60); let m = parseInt((val - h*3600)/60);
let s = parseInt(val - h*3600 - m*60); let s = parseInt(val - h*3600 - m*60);
return h + ":" + m + ":" + s
let hStr = h;
let mStr = m;
let sStr = s;
if (h < 10) {
hStr = "0" + hStr;
}
if (m < 10) {
mStr = "0" + mStr;s
}
if (s < 10) {
sStr = "0" + sStr;
}
return hStr + ":" + mStr + ":" + sStr
}, },
deleteRecord(){ deleteRecord(){
// TODO // TODO

View File

@ -0,0 +1,513 @@
<template>
<div style="width: 100%">
<div class="page-header" >
<div class="page-title">
<el-page-header @back="goBack" content="国标录像"></el-page-header>
</div>
</div>
<el-container>
<el-aside width="300px">
<div class="record-list-box-box">
<el-date-picker size="mini" v-model="chooseDate" type="date" value-format="yyyy-MM-dd" placeholder="日期" @change="dateChange()"></el-date-picker>
<div class="record-list-box" v-loading="recordsLoading" :style="recordListStyle">
<ul v-if="detailFiles.length >0" class="infinite-list record-list" >
<li v-for="item in detailFiles" class="infinite-list-item record-list-item" >
<el-tag v-if="chooseFile != item" @click="checkedFile(item)">
<i class="el-icon-video-camera" ></i>
{{ moment(item.startTime).format('HH:mm:ss')}}-{{ moment(item.endTime).format('HH:mm:ss')}}
</el-tag>
<el-tag v-if="chooseFile == item" type="danger" >
<i class="el-icon-video-camera" ></i>
{{ moment(item.startTime).format('HH:mm:ss')}}-{{ moment(item.endTime).format('HH:mm:ss')}}
</el-tag>
<i style="color: #409EFF;margin-left: 5px;" class="el-icon-download" @click="downloadRecord(item)" ></i>
</li>
</ul>
</div>
<div size="mini" v-if="detailFiles.length ==0" class="record-list-no-val" >暂无数据</div>
</div>
</el-aside>
<el-main style="padding-bottom: 10px;">
<div class="playBox" :style="playerStyle">
<player ref="recordVideoPlayer"
:videoUrl="videoUrl"
:error="videoError"
:message="videoError"
:hasAudio="hasAudio"
style="max-height: 100%"
fluent autoplay live ></player>
</div>
<div class="player-option-box">
<div>
<el-button-group >
<el-time-picker
size="mini"
is-range
align="left"
v-model="timeRange"
value-format="yyyy-MM-dd HH:mm:ss"
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
@change="timePickerChange"
placeholder="选择时间范围">
</el-time-picker>
</el-button-group>
<el-button-group >
<el-button size="mini" class="iconfont icon-zanting" title="开始" @click="gbPause()"></el-button>
<el-button size="mini" class="iconfont icon-kaishi" title="暂停" @click="gbPlay()"></el-button>
<el-dropdown size="mini" title="播放倍速" @command="gbScale">
<el-button size="mini">
倍速 <i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="0.25">0.25倍速</el-dropdown-item>
<el-dropdown-item command="0.5">0.5倍速</el-dropdown-item>
<el-dropdown-item command="1.0">1倍速</el-dropdown-item>
<el-dropdown-item command="2.0">2倍速</el-dropdown-item>
<el-dropdown-item command="4.0">4倍速</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button size="mini" class="iconfont icon-xiazai1" title="下载选定录像" @click="downloadRecord()"></el-button>
<el-button v-if="sliderMIn === 0 && sliderMax === 86400" size="mini" class="iconfont icon-slider" title="放大滑块" @click="setSliderFit()"></el-button>
<el-button v-if="sliderMIn !== 0 || sliderMax !== 86400" size="mini" class="iconfont icon-slider-right" title="恢复滑块" @click="setSliderFit()"></el-button>
</el-button-group>
</div>
<el-slider
class="playtime-slider"
v-model="playTime"
id="playtimeSlider"
:disabled="detailFiles.length === 0"
:min="sliderMIn"
:max="sliderMax"
:range="true"
:format-tooltip="playTimeFormat"
@change="playTimeChange"
:marks="playTimeSliderMarks">
</el-slider>
<div class="slider-val-box">
<div class="slider-val" v-for="item of detailFiles" :style="'width:' + getDataWidth(item) + '%; left:' + getDataLeft(item) + '%'"></div>
</div>
</div>
</el-main>
</el-container>
<recordDownload ref="recordDownload"></recordDownload>
</div>
</template>
<script>
import uiHeader from '../layout/UiHeader.vue'
import player from './common/jessibuca.vue'
import moment from 'moment'
import recordDownload from './dialog/recordDownload.vue'
export default {
name: 'app',
components: {
uiHeader, player,recordDownload
},
data() {
return {
deviceId: this.$route.params.deviceId,
channelId: this.$route.params.channelId,
recordsLoading: false,
streamId: "",
hasAudio: false,
detailFiles: [],
chooseDate: null,
videoUrl: null,
chooseFile: null,
streamInfo: null,
app: null,
mediaServerId: null,
ssrc: null,
sliderMIn: 0,
sliderMax: 86400,
autoPlay: true,
taskUpdate: null,
tabVal: "running",
recordListStyle: {
height: this.winHeight + "px",
overflow: "auto",
margin: "10px auto 10px auto"
},
playerStyle: {
"margin": "0 auto 20px auto",
"height": this.winHeight + "px",
},
winHeight: window.innerHeight - 240,
playTime: null,
timeRange: null,
startTime: null,
endTime: null,
playTimeSliderMarks: {
0: "00:00",
3600: "01:00",
7200: "02:00",
10800: "03:00",
14400: "04:00",
18000: "05:00",
21600: "06:00",
25200: "07:00",
28800: "08:00",
32400: "09:00",
36000: "10:00",
39600: "11:00",
43200: "12:00",
46800: "13:00",
50400: "14:00",
54000: "15:00",
57600: "16:00",
61200: "17:00",
64800: "18:00",
68400: "19:00",
72000: "20:00",
75600: "21:00",
79200: "22:00",
82800: "23:00",
86400: "24:00",
},
};
},
computed: {
},
mounted() {
this.recordListStyle.height = this.winHeight + "px";
this.playerStyle["height"] = this.winHeight + "px";
this.chooseDate = moment().format('YYYY-MM-DD')
this.dateChange();
},
destroyed() {
this.$destroy('recordVideoPlayer');
},
methods: {
dateChange(){
if (!this.chooseDate) {
return;
}
this.setTime(this.chooseDate + " 00:00:00", this.chooseDate + " 23:59:59");
this.recordsLoading = true;
this.detailFiles = [];
this.$axios({
method: 'get',
url: '/api/gb_record/query/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.startTime + '&endTime=' + this.endTime
}).then((res)=>{
this.recordsLoading = false;
if(res.data.code === 0) {
//
this.detailFiles = res.data.data.recordList;
}else {
this.$message({
showClose: true,
message: res.data.msg,
type: "error",
});
}
}).catch((e)=> {
this.recordsLoading = false;
// that.videoHistory.searchHistoryResult = falsificationData.recordData;
});
},
moment: function (v) {
return moment(v)
},
setTime: function (startTime, endTime){
this.startTime = startTime;
this.endTime = endTime;
let start = (new Date(this.startTime).getTime() - new Date(this.chooseDate + " 00:00:00").getTime())/1000;
let end = (new Date(this.endTime).getTime() - new Date(this.chooseDate + " 00:00:00").getTime())/1000;
console.log(start)
console.log(end)
this.playTime = [start, end];
this.timeRange = [startTime, endTime];
},
videoError: function (e) {
console.log("播放器错误:" + JSON.stringify(e));
},
checkedFile(file){
this.chooseFile = file;
this.setTime(file.startTime, file.endTime);
//
this.playRecord()
},
playRecord: function () {
if (this.streamId !== "") {
this.stopPlayRecord(()=> {
this.streamId = "";
this.playRecord();
})
} else {
this.$axios({
method: 'get',
url: '/api/playback/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.startTime + '&endTime=' +
this.endTime
}).then((res)=> {
if (res.data.code === 0) {
this.streamInfo = res.data.data;
this.app = this.streamInfo.app;
this.streamId = this.streamInfo.stream;
this.mediaServerId = this.streamInfo.mediaServerId;
this.ssrc = this.streamInfo.ssrc;
this.videoUrl = this.getUrlByStreamInfo();
}else {
this.$message({
showClose: true,
message: res.data.msg,
type: "error",
});
}
});
}
},
gbPlay(){
console.log('前端控制:播放');
this.$axios({
method: 'get',
url: '/api/playback/resume/' + this.streamId
}).then((res)=> {
this.$refs["recordVideoPlayer"].play(this.videoUrl)
});
},
gbPause(){
console.log('前端控制:暂停');
this.$axios({
method: 'get',
url: '/api/playback/pause/' + this.streamId
}).then(function (res) {});
},
gbScale(command){
console.log('前端控制:倍速 ' + command);
this.$axios({
method: 'get',
url: `/api/playback/speed/${this.streamId }/${command}`
}).then(function (res) {});
},
downloadRecord: function (row) {
if (!row) {
let startTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + this.playTime[0]*1000).format("YYYY-MM-DD HH:mm:ss");
let endTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + this.playTime[1]*1000).format("YYYY-MM-DD HH:mm:ss");
console.log(startTimeStr);
console.log(endTimeStr);
row = {
startTime: startTimeStr,
endTime: endTimeStr
}
}
if (this.streamId !== "") {
this.stopPlayRecord(()=> {
this.streamId = "";
this.downloadRecord(row);
})
}else {
this.$axios({
method: 'get',
url: '/api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
row.endTime + '&downloadSpeed=4'
}).then( (res)=> {
if (res.data.code === 0) {
let streamInfo = res.data.data;
this.$refs.recordDownload.openDialog(this.deviceId, this.channelId, streamInfo.app, streamInfo.stream, streamInfo.mediaServerId);
}else {
this.$message({
showClose: true,
message: res.data.msg,
type: "error",
});
}
});
}
},
stopDownloadRecord: function (callback) {
this.$refs["recordVideoPlayer"].pause();
this.videoUrl = '';
this.$axios({
method: 'get',
url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId
}).then((res)=> {
if (callback) callback(res)
});
},
stopPlayRecord: function (callback) {
this.$refs["recordVideoPlayer"].pause();
this.videoUrl = '';
this.$axios({
method: 'get',
url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId
}).then(function (res) {
if (callback) callback()
});
},
getDataWidth(item){
let timeForFile = this.getTimeForFile(item);
let result = (timeForFile[2])/((this.sliderMax - this.sliderMIn)*1000)
return result*100
},
getDataLeft(item){
let timeForFile = this.getTimeForFile(item);
let differenceTime = timeForFile[0].getTime() - new Date(this.chooseDate + " 00:00:00").getTime()
return parseFloat((differenceTime - this.sliderMIn * 1000)/((this.sliderMax - this.sliderMIn)*1000))*100 ;
},
getUrlByStreamInfo(){
if (location.protocol === "https:") {
this.videoUrl = this.streamInfo["wss_flv"]
}else {
this.videoUrl = this.streamInfo["ws_flv"]
}
return this.videoUrl;
},
timePickerChange: function (val){
this.setTime(val[0], val[1])
},
playTimeChange(val){
console.log(val)
let startTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + val[0]*1000).format("YYYY-MM-DD HH:mm:ss");
let endTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + val[1]*1000).format("YYYY-MM-DD HH:mm:ss");
this.setTime(startTimeStr, endTimeStr)
this.playRecord();
},
setSliderFit() {
if (this.sliderMIn === 0 && this.sliderMax === 86400) {
if (this.detailFiles.length > 0){
let timeForFile = this.getTimeForFile(this.detailFiles[0]);
let lastTimeForFile = this.getTimeForFile(this.detailFiles[this.detailFiles.length - 1]);
let timeNum = timeForFile[0].getTime() - new Date(this.chooseDate + " " + "00:00:00").getTime()
let lastTimeNum = lastTimeForFile[1].getTime() - new Date(this.chooseDate + " " + "00:00:00").getTime()
this.playTime = parseInt(timeNum/1000)
this.sliderMIn = parseInt(timeNum/1000 - timeNum/1000%(60*60))
this.sliderMax = parseInt(lastTimeNum/1000 - lastTimeNum/1000%(60*60)) + 60*60
this.playTime = [this.sliderMIn, this.sliderMax];
}
}else {
this.sliderMIn = 0;
this.sliderMax = 86400;
}
},
getTimeForFile(file){
let startTime = new Date(file.startTime);
let endTime = new Date(file.endTime);
return [startTime, endTime, endTime.getTime() - startTime.getTime()];
},
playTimeFormat(val){
let h = parseInt(val/3600);
let m = parseInt((val - h*3600)/60);
let s = parseInt(val - h*3600 - m*60);
let hStr = h;
let mStr = m;
let sStr = s;
if (h < 10) {
hStr = "0" + hStr;
}
if (m < 10) {
mStr = "0" + mStr;s
}
if (s < 10) {
sStr = "0" + sStr;
}
return hStr + ":" + mStr + ":" + sStr
},
goBack(){
window.history.go(-1);
}
}
};
</script>
<style>
.el-slider__runway {
background-color:rgba(206, 206, 206, 0.47) !important;
}
.el-slider__bar {
background-color: rgba(153, 153, 153, 0) !important;
}
.playtime-slider {
position: relative;
z-index: 100;
}
.data-picker-true{
}
.data-picker-true:after{
content: "";
position: absolute;
width: 4px;
height: 4px;
background-color: #606060;
border-radius: 4px;
left: 45%;
top: 74%;
}
.data-picker-false{
}
.slider-val-box{
height: 6px;
position: relative;
top: -22px;
}
.slider-val{
height: 6px;
background-color: #007CFF;
position: absolute;
}
.record-list-box-box{
width: 250px;
float: left;
}
.record-list-box{
overflow: auto;
width: 220px;
list-style: none;
padding: 0;
margin: 0;
margin-top: 0px;
padding: 1rem 0;
background-color: #FFF;
margin-top: 10px;
}
.record-list{
list-style: none;
padding: 0;
margin: 0;
background-color: #FFF;
}
.record-list-no-val {
position: absolute;
color: #9f9f9f;
top: 50%;
left: 110px;
}
.record-list-item{
padding: 0;
margin: 0;
margin: 0.5rem 0;
cursor: pointer;
}
.record-list-option {
width: 10px;
float: left;
margin-top: 39px;
}
.player-option-box{
padding: 0 20px;
}
</style>

View File

@ -269,10 +269,10 @@ export default {
}); });
}, },
queryRecords: function (itemData) { queryRecords: function (itemData) {
var format = moment().format("yyyy-MM-DD");
let deviceId = this.deviceId; let deviceId = this.deviceId;
let channelId = itemData.channelId; let channelId = itemData.channelId;
this.$refs.devicePlayer.openDialog("record", deviceId, channelId, {date: format})
this.$router.push(`/gbRecordDetail/${deviceId}/${channelId}`)
}, },
stopDevicePush: function (itemData) { stopDevicePush: function (itemData) {
var that = this; var that = this;

View File

@ -101,11 +101,14 @@ export default {
window.clearTimeout(this.timer); window.clearTimeout(this.timer);
} }
this.timer = setTimeout(()=>{ this.timer = setTimeout(()=>{
if (this.$route.path === "/console") {
this.getSystemInfo(); this.getSystemInfo();
this.getLoad(); this.getLoad();
this.timer = null; this.timer = null;
this.loopForSystemInfo() this.loopForSystemInfo()
this.getResourceInfo() this.getResourceInfo()
}
}, 2000) }, 2000)
}, },
getSystemInfo: function (){ getSystemInfo: function (){

View File

@ -1,28 +1,32 @@
<template > <template >
<div id="consoleResource" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center"> <div id="consoleResource" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
<div style="width: 50%;height: 50%; float:left; "> <div style="width: 50%;height: 50%; float:left; ">
<el-progress :width="100" :stroke-width="8" type="circle" :percentage="Math.floor(deviceInfo.online/deviceInfo.total*100)" style="margin-top: 20px; font-size: 18px"></el-progress> <el-progress v-if="deviceInfo.total > 0" :width="100" :stroke-width="8" type="circle" :percentage="Math.floor(deviceInfo.online/deviceInfo.total*100)" style="margin-top: 20px; font-size: 18px"></el-progress>
<el-progress v-if="deviceInfo.total === 0" :width="100" :stroke-width="8" type="circle" :percentage="0" style="margin-top: 20px; font-size: 18px"></el-progress>
<div class="resourceInfo"> <div class="resourceInfo">
设备总数:{{deviceInfo.total}}<br/> 设备总数:{{deviceInfo.total}}<br/>
在线数:{{deviceInfo.online}} 在线数:{{deviceInfo.online}}
</div> </div>
</div> </div>
<div style="width: 50%;height: 50%; float:left; "> <div style="width: 50%;height: 50%; float:left; ">
<el-progress :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(channelInfo.online/channelInfo.total*100)" style="margin-top: 20px"></el-progress> <el-progress v-if="channelInfo.total > 0" :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(channelInfo.online/channelInfo.total*100)" style="margin-top: 20px"></el-progress>
<el-progress v-if="channelInfo.total === 0" :width="100" :stroke-width="10" type="circle" :percentage="0" style="margin-top: 20px"></el-progress>
<div class="resourceInfo"> <div class="resourceInfo">
通道总数:{{channelInfo.total}}<br/> 通道总数:{{channelInfo.total}}<br/>
在线数:{{channelInfo.online}} 在线数:{{channelInfo.online}}
</div> </div>
</div> </div>
<div style="width: 50%;height: 50%; float:left; "> <div style="width: 50%;height: 50%; float:left; ">
<el-progress :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(pushInfo.online/pushInfo.total*100)" style="margin-top: 20px"></el-progress> <el-progress v-if="pushInfo.total > 0" :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(pushInfo.online/pushInfo.total*100)" style="margin-top: 20px"></el-progress>
<el-progress v-if="pushInfo.total === 0" :width="100" :stroke-width="10" type="circle" :percentage="0" style="margin-top: 20px"></el-progress>
<div class="resourceInfo"> <div class="resourceInfo">
推流总数:{{pushInfo.total}}<br/> 推流总数:{{pushInfo.total}}<br/>
在线数:{{pushInfo.online}} 在线数:{{pushInfo.online}}
</div> </div>
</div> </div>
<div style="width: 50%;height: 50%; float:left; "> <div style="width: 50%;height: 50%; float:left; ">
<el-progress :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(proxyInfo.online/proxyInfo.total*100)" style="margin-top: 20px"></el-progress> <el-progress v-if="proxyInfo.total > 0" :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(proxyInfo.online/proxyInfo.total*100)" style="margin-top: 20px"></el-progress>
<el-progress v-if="proxyInfo.total === 0" :width="100" :stroke-width="10" type="circle" :percentage="0" style="margin-top: 20px"></el-progress>
<div class="resourceInfo"> <div class="resourceInfo">
拉流代理总数:{{proxyInfo.total}}<br/> 拉流代理总数:{{proxyInfo.total}}<br/>
在线数:{{proxyInfo.online}} 在线数:{{proxyInfo.online}}

View File

@ -1,142 +1,150 @@
<template> <template>
<div id="devicePlayer" v-loading="isLoging"> <div id="devicePlayer" v-loading="isLoging">
<el-dialog title="视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" @close="close()"> <el-dialog title="视频播放" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" @close="close()">
<div style="width: 100%; height: 100%"> <div style="width: 100%; height: 100%">
<el-tabs type="card" :stretch="true" v-model="activePlayer" @tab-click="changePlayer" v-if="Object.keys(this.player).length > 1"> <el-tabs type="card" :stretch="true" v-model="activePlayer" @tab-click="changePlayer"
v-if="Object.keys(this.player).length > 1">
<el-tab-pane label="Jessibuca" name="jessibuca"> <el-tab-pane label="Jessibuca" name="jessibuca">
<jessibucaPlayer v-if="activePlayer === 'jessibuca'" ref="jessibuca" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></jessibucaPlayer> <jessibucaPlayer v-if="activePlayer === 'jessibuca'" ref="jessibuca" :visible.sync="showVideoDialog"
:videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px"
:hasAudio="hasAudio" fluent autoplay live></jessibucaPlayer>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="WebRTC" name="webRTC"> <el-tab-pane label="WebRTC" name="webRTC">
<rtc-player v-if="activePlayer === 'webRTC'" ref="webRTC" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></rtc-player> <rtc-player v-if="activePlayer === 'webRTC'" ref="webRTC" :visible.sync="showVideoDialog"
:videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px"
:hasAudio="hasAudio" fluent autoplay live></rtc-player>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="h265web">h265web敬请期待</el-tab-pane> <el-tab-pane label="h265web">h265web敬请期待</el-tab-pane>
<el-tab-pane label="wsPlayer">wsPlayer 敬请期待</el-tab-pane> <el-tab-pane label="wsPlayer">wsPlayer 敬请期待</el-tab-pane>
</el-tabs> </el-tabs>
<jessibucaPlayer v-if="Object.keys(this.player).length == 1 && this.player.jessibuca" ref="jessibuca" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></jessibucaPlayer> <jessibucaPlayer v-if="Object.keys(this.player).length == 1 && this.player.jessibuca" ref="jessibuca"
<rtc-player v-if="Object.keys(this.player).length == 1 && this.player.webRTC" ref="jessibuca" :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError" height="100px" :hasAudio="hasAudio" fluent autoplay live ></rtc-player> :visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError"
height="100px" :hasAudio="hasAudio" fluent autoplay live></jessibucaPlayer>
<rtc-player v-if="Object.keys(this.player).length == 1 && this.player.webRTC" ref="jessibuca"
:visible.sync="showVideoDialog" :videoUrl="videoUrl" :error="videoError" :message="videoError"
height="100px" :hasAudio="hasAudio" fluent autoplay live></rtc-player>
</div> </div>
<div id="shared" style="text-align: right; margin-top: 1rem;"> <div id="shared" style="text-align: right; margin-top: 1rem;">
<el-tabs v-model="tabActiveName" @tab-click="tabHandleClick" > <el-tabs v-model="tabActiveName" @tab-click="tabHandleClick">
<el-tab-pane label="实时视频" name="media"> <el-tab-pane label="实时视频" name="media">
<div style="margin-bottom: 0.5rem;">
<!-- <el-button type="primary" size="small" @click="playRecord(true, '')">播放</el-button>-->
<!-- <el-button type="primary" size="small" @click="startRecord()">录制</el-button>-->
<!-- <el-button type="primary" size="small" @click="stopRecord()">停止录制</el-button>-->
</div>
<div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
<span style="width: 5rem; line-height: 2.5rem; text-align: right;">播放地址</span> <span style="width: 5rem; line-height: 2.5rem; text-align: right;">播放地址</span>
<el-input v-model="getPlayerShared.sharedUrl" :disabled="true" > <el-input v-model="getPlayerShared.sharedUrl" :disabled="true">
<template slot="append"> <template slot="append">
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedUrl" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i> <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedUrl"
@success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
</template> </template>
</el-input> </el-input>
</div> </div>
<div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
<span style="width: 5rem; line-height: 2.5rem; text-align: right;">iframe</span> <span style="width: 5rem; line-height: 2.5rem; text-align: right;">iframe</span>
<el-input v-model="getPlayerShared.sharedIframe" :disabled="true" > <el-input v-model="getPlayerShared.sharedIframe" :disabled="true">
<template slot="append"> <template slot="append">
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedIframe" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i> <i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedIframe"
@success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
</template> </template>
</el-input> </el-input>
</div> </div>
<div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
<span style="width: 5rem; line-height: 2.5rem; text-align: right;">资源地址</span> <span style="width: 5rem; line-height: 2.5rem; text-align: right;">资源地址</span>
<el-input v-model="getPlayerShared.sharedRtmp" :disabled="true" > <el-input v-model="getPlayerShared.sharedRtmp" :disabled="true">
<el-button slot="append" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="getPlayerShared.sharedRtmp" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button> <el-button slot="append" icon="el-icon-document-copy" title="点击拷贝"
v-clipboard="getPlayerShared.sharedRtmp"
@success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button>
<el-dropdown slot="prepend" v-if="streamInfo" trigger="click" @command="copyUrl"> <el-dropdown slot="prepend" v-if="streamInfo" trigger="click" @command="copyUrl">
<el-button > <el-button>
更多地址<i class="el-icon-arrow-down el-icon--right"></i> 更多地址<i class="el-icon-arrow-down el-icon--right"></i>
</el-button> </el-button>
<el-dropdown-menu slot="dropdown" > <el-dropdown-menu slot="dropdown">
<el-dropdown-item v-if="streamInfo.flv" :command="streamInfo.flv.url"> <el-dropdown-item v-if="streamInfo.flv" :command="streamInfo.flv">
<el-tag >FLV:</el-tag> <el-tag>FLV:</el-tag>
<span>{{ streamInfo.flv.url }}</span> <span>{{ streamInfo.flv }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.https_flv" :command="streamInfo.https_flv.url"> <el-dropdown-item v-if="streamInfo.https_flv" :command="streamInfo.https_flv">
<el-tag >FLV(https):</el-tag> <el-tag>FLV(https):</el-tag>
<span>{{ streamInfo.https_flv.url }}</span> <span>{{ streamInfo.https_flv }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.ws_flv" :command="streamInfo.ws_flv.url"> <el-dropdown-item v-if="streamInfo.ws_flv" :command="streamInfo.ws_flv">
<el-tag >FLV(ws):</el-tag> <el-tag>FLV(ws):</el-tag>
<span >{{ streamInfo.ws_flv.url }}</span> <span>{{ streamInfo.ws_flv }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.wss_flv" :command="streamInfo.wss_flv.url"> <el-dropdown-item v-if="streamInfo.wss_flv" :command="streamInfo.wss_flv">
<el-tag >FLV(wss):</el-tag> <el-tag>FLV(wss):</el-tag>
<span>{{ streamInfo.wss_flv.url }}</span> <span>{{ streamInfo.wss_flv }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.fmp4" :command="streamInfo.fmp4.url"> <el-dropdown-item v-if="streamInfo.fmp4" :command="streamInfo.fmp4">
<el-tag >FMP4:</el-tag> <el-tag>FMP4:</el-tag>
<span>{{ streamInfo.fmp4.url }}</span> <span>{{ streamInfo.fmp4 }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.https_fmp4" :command="streamInfo.https_fmp4.url"> <el-dropdown-item v-if="streamInfo.https_fmp4" :command="streamInfo.https_fmp4">
<el-tag >FMP4(https):</el-tag> <el-tag>FMP4(https):</el-tag>
<span>{{ streamInfo.https_fmp4.url }}</span> <span>{{ streamInfo.https_fmp4 }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.ws_fmp4" :command="streamInfo.ws_fmp4.url"> <el-dropdown-item v-if="streamInfo.ws_fmp4" :command="streamInfo.ws_fmp4">
<el-tag >FMP4(ws):</el-tag> <el-tag>FMP4(ws):</el-tag>
<span>{{ streamInfo.ws_fmp4.url }}</span> <span>{{ streamInfo.ws_fmp4 }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.wss_fmp4" :command="streamInfo.wss_fmp4.url"> <el-dropdown-item v-if="streamInfo.wss_fmp4" :command="streamInfo.wss_fmp4">
<el-tag >FMP4(wss):</el-tag> <el-tag>FMP4(wss):</el-tag>
<span>{{ streamInfo.wss_fmp4.url }}</span> <span>{{ streamInfo.wss_fmp4 }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.hls" :command="streamInfo.hls.url"> <el-dropdown-item v-if="streamInfo.hls" :command="streamInfo.hls">
<el-tag>HLS:</el-tag> <el-tag>HLS:</el-tag>
<span>{{ streamInfo.hls.url }}</span> <span>{{ streamInfo.hls }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.https_hls" :command="streamInfo.https_hls.url"> <el-dropdown-item v-if="streamInfo.https_hls" :command="streamInfo.https_hls">
<el-tag >HLS(https):</el-tag> <el-tag>HLS(https):</el-tag>
<span>{{ streamInfo.https_hls.url }}</span> <span>{{ streamInfo.https_hls }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.ws_hls" :command="streamInfo.ws_hls.url"> <el-dropdown-item v-if="streamInfo.ws_hls" :command="streamInfo.ws_hls">
<el-tag >HLS(ws):</el-tag> <el-tag>HLS(ws):</el-tag>
<span>{{ streamInfo.ws_hls.url }}</span> <span>{{ streamInfo.ws_hls }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.wss_hls" :command="streamInfo.wss_hls.url"> <el-dropdown-item v-if="streamInfo.wss_hls" :command="streamInfo.wss_hls">
<el-tag >HLS(wss):</el-tag> <el-tag>HLS(wss):</el-tag>
<span>{{ streamInfo.wss_hls.url }}</span> <span>{{ streamInfo.wss_hls }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.ts" :command="streamInfo.ts.url"> <el-dropdown-item v-if="streamInfo.ts" :command="streamInfo.ts">
<el-tag>TS:</el-tag> <el-tag>TS:</el-tag>
<span>{{ streamInfo.ts.url }}</span> <span>{{ streamInfo.ts }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.https_ts" :command="streamInfo.https_ts.url"> <el-dropdown-item v-if="streamInfo.https_ts" :command="streamInfo.https_ts">
<el-tag>TS(https):</el-tag> <el-tag>TS(https):</el-tag>
<span>{{ streamInfo.https_ts.url }}</span> <span>{{ streamInfo.https_ts }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.ws_ts" :command="streamInfo.ws_ts.url"> <el-dropdown-item v-if="streamInfo.ws_ts" :command="streamInfo.ws_ts">
<el-tag>TS(ws):</el-tag> <el-tag>TS(ws):</el-tag>
<span>{{ streamInfo.ws_ts.url }}</span> <span>{{ streamInfo.ws_ts }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.wss_ts" :command="streamInfo.wss_ts.url"> <el-dropdown-item v-if="streamInfo.wss_ts" :command="streamInfo.wss_ts">
<el-tag>TS(wss):</el-tag> <el-tag>TS(wss):</el-tag>
<span>{{ streamInfo.wss_ts.url }}</span> <span>{{ streamInfo.wss_ts }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.rtc" :command="streamInfo.rtc.url"> <el-dropdown-item v-if="streamInfo.rtc" :command="streamInfo.rtc">
<el-tag >RTC:</el-tag> <el-tag>RTC:</el-tag>
<span>{{ streamInfo.rtc.url }}</span> <span>{{ streamInfo.rtc }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.rtcs" :command="streamInfo.rtcs.url"> <el-dropdown-item v-if="streamInfo.rtcs" :command="streamInfo.rtcs">
<el-tag >RTCS:</el-tag> <el-tag>RTCS:</el-tag>
<span>{{ streamInfo.rtcs }}</span> <span>{{ streamInfo.rtcs }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.rtmp" :command="streamInfo.rtmp.url"> <el-dropdown-item v-if="streamInfo.rtmp" :command="streamInfo.rtmp">
<el-tag >RTMP:</el-tag> <el-tag>RTMP:</el-tag>
<span>{{ streamInfo.rtmp.url }}</span> <span>{{ streamInfo.rtmp }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.rtmps" :command="streamInfo.rtmps.url"> <el-dropdown-item v-if="streamInfo.rtmps" :command="streamInfo.rtmps">
<el-tag >RTMPS:</el-tag> <el-tag>RTMPS:</el-tag>
<span>{{ streamInfo.rtmps.url }}</span> <span>{{ streamInfo.rtmps }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.rtsp" :command="streamInfo.rtsp.url"> <el-dropdown-item v-if="streamInfo.rtsp" :command="streamInfo.rtsp">
<el-tag >RTSP:</el-tag> <el-tag>RTSP:</el-tag>
<span>{{ streamInfo.rtsp.url }}</span> <span>{{ streamInfo.rtsp }}</span>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item v-if="streamInfo.rtsps" :command="streamInfo.rtsps.url"> <el-dropdown-item v-if="streamInfo.rtsps" :command="streamInfo.rtsps">
<el-tag >RTSPS:</el-tag> <el-tag>RTSPS:</el-tag>
<span>{{ streamInfo.rtsps.url }}</span> <span>{{ streamInfo.rtsps }}</span>
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
@ -145,51 +153,6 @@
</div> </div>
</el-tab-pane> </el-tab-pane>
<!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}--> <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->
<el-tab-pane label="录像查询" name="record" v-if="showRrecord">
<div style="width: 100%;">
<div style="width: 100%; text-align: left">
<span>录像控制</span>
<el-button-group style="margin-left: 1rem;">
<el-button size="mini" class="iconfont icon-zanting" title="开始" @click="gbPause()"></el-button>
<el-button size="mini" class="iconfont icon-kaishi" title="暂停" @click="gbPlay()"></el-button>
<el-dropdown size="mini" title="播放倍速" style="margin-left: 1px;" @command="gbScale">
<el-button size="mini">
倍速 <i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="0.25">0.25倍速</el-dropdown-item>
<el-dropdown-item command="0.5">0.5倍速</el-dropdown-item>
<el-dropdown-item command="1.0">1倍速</el-dropdown-item>
<el-dropdown-item command="2.0">2倍速</el-dropdown-item>
<el-dropdown-item command="4.0">4倍速</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</el-button-group>
<el-date-picker style="float: right;" size="mini" v-model="videoHistory.date" type="date" value-format="yyyy-MM-dd" placeholder="日期" @change="queryRecords()"></el-date-picker>
</div>
<div style="width: 100%; text-align: left">
<span class="demonstration" style="padding: 12px 36px 12px 0;float: left;">{{showTimeText}}</span>
<el-slider style="width: 80%; float:left;" v-model="sliderTime" @change="gbSeek" :show-tooltip="false"></el-slider>
</div>
</div>
<el-table :data="videoHistory.searchHistoryResult" height="150" v-loading="recordsLoading">
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="文件" prop="filePath"></el-table-column>
<el-table-column label="开始时间" prop="startTime" :formatter="timeFormatter"></el-table-column>
<el-table-column label="结束时间" prop="endTime" :formatter="timeFormatter"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button-group>
<el-button icon="el-icon-video-play" size="mini" @click="playRecord(scope.row)">播放</el-button>
<el-button icon="el-icon-download" size="mini" @click="downloadRecord(scope.row)">下载</el-button>
</el-button-group>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<!--遥控界面--> <!--遥控界面-->
<el-tab-pane label="云台控制" name="control" v-if="showPtz"> <el-tab-pane label="云台控制" name="control" v-if="showPtz">
<div style="display: flex; justify-content: left;"> <div style="display: flex; justify-content: left;">
@ -213,8 +176,12 @@
<div class="control-round"> <div class="control-round">
<div class="control-round-inner"><i class="fa fa-pause-circle"></i></div> <div class="control-round-inner"><i class="fa fa-pause-circle"></i></div>
</div> </div>
<div style="position: absolute; left: 7.25rem; top: 1.25rem" @mousedown="ptzCamera('zoomin')" @mouseup="ptzCamera('stop')"><i class="el-icon-zoom-in control-zoom-btn" style="font-size: 1.875rem;"></i></div> <div style="position: absolute; left: 7.25rem; top: 1.25rem" @mousedown="ptzCamera('zoomin')"
<div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;" @mousedown="ptzCamera('zoomout')" @mouseup="ptzCamera('stop')"><i class="el-icon-zoom-out control-zoom-btn"></i></div> @mouseup="ptzCamera('stop')"><i class="el-icon-zoom-in control-zoom-btn"
style="font-size: 1.875rem;"></i></div>
<div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;"
@mousedown="ptzCamera('zoomout')" @mouseup="ptzCamera('stop')"><i
class="el-icon-zoom-out control-zoom-btn"></i></div>
<div class="contro-speed" style="position: absolute; left: 4px; top: 7rem; width: 9rem;"> <div class="contro-speed" style="position: absolute; left: 4px; top: 7rem; width: 9rem;">
<el-slider v-model="controSpeed" :max="255"></el-slider> <el-slider v-model="controSpeed" :max="255"></el-slider>
</div> </div>
@ -222,32 +189,84 @@
<div class="control-panel"> <div class="control-panel">
<el-button-group> <el-button-group>
<el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center" size="medium">预置位编号</el-tag> <el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center"
<el-input-number style="position: absolute; left: 5rem; top: 0rem; width: 6rem" size="mini" v-model="presetPos" controls-position="right" :precision="0" :step="1" :min="1" :max="255"></el-input-number> size="medium">预置位编号
<el-button style="position: absolute; left: 11rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="presetPosition(129, presetPos)">设置</el-button> </el-tag>
<el-button style="position: absolute; left: 27rem; top: 0rem; width: 5rem" size="mini" type="primary" icon="el-icon-place" @click="presetPosition(130, presetPos)">调用</el-button> <el-input-number style="position: absolute; left: 5rem; top: 0rem; width: 6rem" size="mini"
<el-button style="position: absolute; left: 16rem; top: 0rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="presetPosition(131, presetPos)">删除</el-button> v-model="presetPos" controls-position="right" :precision="0" :step="1" :min="1"
<el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">巡航速度</el-tag> :max="255"></el-input-number>
<el-input-number style="position: absolute; left: 5rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number> <el-button style="position: absolute; left: 11rem; top: 0rem; width: 5rem" size="mini"
<el-button style="position: absolute; left: 11rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(134, cruisingGroup, cruisingSpeed)">设置</el-button> icon="el-icon-add-location" @click="presetPosition(129, presetPos)">设置
<el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center" size="medium">停留时间</el-tag> </el-button>
<el-input-number style="position: absolute; left: 21rem; top: 2.5rem; width: 6rem" size="mini" v-model="cruisingTime" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number> <el-button style="position: absolute; left: 27rem; top: 0rem; width: 5rem" size="mini" type="primary"
<el-button style="position: absolute; left: 27rem; top: 2.5rem; width: 5rem" size="mini" icon="el-icon-timer" @click="setSpeedOrTime(135, cruisingGroup, cruisingTime)">设置</el-button> icon="el-icon-place" @click="presetPosition(130, presetPos)">调用
<el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center" size="medium">巡航组编号</el-tag> </el-button>
<el-input-number style="position: absolute; left: 5rem; top: 4.5rem; width: 6rem" size="mini" v-model="cruisingGroup" controls-position="right" :precision="0" :min="0" :max="255"></el-input-number> <el-button style="position: absolute; left: 16rem; top: 0rem; width: 5rem" size="mini"
<el-button style="position: absolute; left: 11rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-add-location" @click="setCommand(132, cruisingGroup, presetPos)">添加点</el-button> icon="el-icon-delete-location" @click="presetPosition(131, presetPos)">删除
<el-button style="position: absolute; left: 16rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete-location" @click="setCommand(133, cruisingGroup, presetPos)">删除点</el-button> </el-button>
<el-button style="position: absolute; left: 21rem; top: 4.5rem; width: 5rem" size="mini" icon="el-icon-delete" @click="setCommand(133, cruisingGroup, 0)">删除组</el-button> <el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center"
<el-button style="position: absolute; left: 27rem; top: 5rem; width: 5rem" size="mini" type="primary" icon="el-icon-video-camera-solid" @click="setCommand(136, cruisingGroup, 0)">巡航</el-button> size="medium">巡航速度
<el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center" size="medium">扫描速度</el-tag> </el-tag>
<el-input-number style="position: absolute; left: 5rem; top: 7rem; width: 6rem" size="mini" v-model="scanSpeed" controls-position="right" :precision="0" :min="1" :max="4095"></el-input-number> <el-input-number style="position: absolute; left: 5rem; top: 2.5rem; width: 6rem" size="mini"
<el-button style="position: absolute; left: 11rem; top: 7rem; width: 5rem" size="mini" icon="el-icon-loading" @click="setSpeedOrTime(138, scanGroup, scanSpeed)">设置</el-button> v-model="cruisingSpeed" controls-position="right" :precision="0" :min="1"
<el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center" size="medium">扫描组编号</el-tag> :max="4095"></el-input-number>
<el-input-number style="position: absolute; left: 5rem; top: 9rem; width: 6rem" size="mini" v-model="scanGroup" controls-position="right" :precision="0" :step="1" :min="0" :max="255"></el-input-number> <el-button style="position: absolute; left: 11rem; top: 2.5rem; width: 5rem" size="mini"
<el-button style="position: absolute; left: 11rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-left" @click="setCommand(137, scanGroup, 1)">左边界</el-button> icon="el-icon-loading" @click="setSpeedOrTime(134, cruisingGroup, cruisingSpeed)">设置
<el-button style="position: absolute; left: 16rem; top: 9rem; width: 5rem" size="mini" icon="el-icon-d-arrow-right" @click="setCommand(137, scanGroup, 2)">右边界</el-button> </el-button>
<el-button style="position: absolute; left: 27rem; top: 7rem; width: 5rem" size="mini" type="primary" icon="el-icon-video-camera-solid" @click="setCommand(137, scanGroup, 0)">扫描</el-button> <el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center"
<el-button style="position: absolute; left: 27rem; top: 9rem; width: 5rem" size="mini" type="danger" icon="el-icon-switch-button" @click="ptzCamera('stop')">停止</el-button> size="medium">停留时间
</el-tag>
<el-input-number style="position: absolute; left: 21rem; top: 2.5rem; width: 6rem" size="mini"
v-model="cruisingTime" controls-position="right" :precision="0" :min="1"
:max="4095"></el-input-number>
<el-button style="position: absolute; left: 27rem; top: 2.5rem; width: 5rem" size="mini"
icon="el-icon-timer" @click="setSpeedOrTime(135, cruisingGroup, cruisingTime)">设置
</el-button>
<el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center"
size="medium">巡航组编号
</el-tag>
<el-input-number style="position: absolute; left: 5rem; top: 4.5rem; width: 6rem" size="mini"
v-model="cruisingGroup" controls-position="right" :precision="0" :min="0"
:max="255"></el-input-number>
<el-button style="position: absolute; left: 11rem; top: 4.5rem; width: 5rem" size="mini"
icon="el-icon-add-location" @click="setCommand(132, cruisingGroup, presetPos)">添加点
</el-button>
<el-button style="position: absolute; left: 16rem; top: 4.5rem; width: 5rem" size="mini"
icon="el-icon-delete-location" @click="setCommand(133, cruisingGroup, presetPos)">删除点
</el-button>
<el-button style="position: absolute; left: 21rem; top: 4.5rem; width: 5rem" size="mini"
icon="el-icon-delete" @click="setCommand(133, cruisingGroup, 0)">删除组
</el-button>
<el-button style="position: absolute; left: 27rem; top: 5rem; width: 5rem" size="mini" type="primary"
icon="el-icon-video-camera-solid" @click="setCommand(136, cruisingGroup, 0)">巡航
</el-button>
<el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center"
size="medium">扫描速度
</el-tag>
<el-input-number style="position: absolute; left: 5rem; top: 7rem; width: 6rem" size="mini"
v-model="scanSpeed" controls-position="right" :precision="0" :min="1"
:max="4095"></el-input-number>
<el-button style="position: absolute; left: 11rem; top: 7rem; width: 5rem" size="mini"
icon="el-icon-loading" @click="setSpeedOrTime(138, scanGroup, scanSpeed)">设置
</el-button>
<el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center"
size="medium">扫描组编号
</el-tag>
<el-input-number style="position: absolute; left: 5rem; top: 9rem; width: 6rem" size="mini"
v-model="scanGroup" controls-position="right" :precision="0" :step="1" :min="0"
:max="255"></el-input-number>
<el-button style="position: absolute; left: 11rem; top: 9rem; width: 5rem" size="mini"
icon="el-icon-d-arrow-left" @click="setCommand(137, scanGroup, 1)">左边界
</el-button>
<el-button style="position: absolute; left: 16rem; top: 9rem; width: 5rem" size="mini"
icon="el-icon-d-arrow-right" @click="setCommand(137, scanGroup, 2)">右边界
</el-button>
<el-button style="position: absolute; left: 27rem; top: 7rem; width: 5rem" size="mini" type="primary"
icon="el-icon-video-camera-solid" @click="setCommand(137, scanGroup, 0)">扫描
</el-button>
<el-button style="position: absolute; left: 27rem; top: 9rem; width: 5rem" size="mini" type="danger"
icon="el-icon-switch-button" @click="ptzCamera('stop')">停止
</el-button>
</el-button-group> </el-button-group>
</div> </div>
</div> </div>
@ -258,30 +277,31 @@
<el-button size="mini" type="primary" v-if="!coverPlaying" @click="coverPlay">转码播放</el-button> <el-button size="mini" type="primary" v-if="!coverPlaying" @click="coverPlay">转码播放</el-button>
<el-button size="mini" type="danger" v-if="coverPlaying" @click="convertStopClick">停止转码</el-button> <el-button size="mini" type="danger" v-if="coverPlaying" @click="convertStopClick">停止转码</el-button>
</p> </p>
<div class="trank" > <div class="trank">
<p v-if="tracksNotLoaded" style="text-align: center;padding-top: 3rem;">暂无数据</p> <p v-if="tracksNotLoaded" style="text-align: center;padding-top: 3rem;">暂无数据</p>
<div v-for="(item, index) in tracks" style="width: 50%; float: left" loading> <div v-for="(item, index) in tracks" style="width: 50%; float: left" loading>
<span > {{index}}</span> <span> {{ index }}</span>
<div class="trankInfo" v-if="item.codec_type == 0"> <div class="trankInfo" v-if="item.codec_type == 0">
<p>格式: {{item.codec_id_name}}</p> <p>格式: {{ item.codec_id_name }}</p>
<p>类型: 视频</p> <p>类型: 视频</p>
<p>分辨率: {{item.width}} x {{item.height}}</p> <p>分辨率: {{ item.width }} x {{ item.height }}</p>
<p>帧率: {{item.fps}}</p> <p>帧率: {{ item.fps }}</p>
</div> </div>
<div class="trankInfo" v-if="item.codec_type == 1"> <div class="trankInfo" v-if="item.codec_type == 1">
<p>格式: {{item.codec_id_name}}</p> <p>格式: {{ item.codec_id_name }}</p>
<p>类型: 音频</p> <p>类型: 音频</p>
<p>采样位数: {{item.sample_bit}}</p> <p>采样位数: {{ item.sample_bit }}</p>
<p>采样率: {{item.sample_rate}}</p> <p>采样率: {{ item.sample_rate }}</p>
</div> </div>
</div> </div>
</div> </div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="语音喊话" name="broadcast" > <el-tab-pane label="语音对讲" name="broadcast">
<div class="trank" style="text-align: center;"> <div class="trank" style="text-align: center;">
<el-button @click="broadcastStatusClick()" :type="getBroadcastStatus()" :disabled="broadcastStatus === -2" circle icon="el-icon-microphone" style="font-size: 32px; padding: 24px;margin-top: 24px;"/> <el-button @click="broadcastStatusClick()" :type="getBroadcastStatus()" :disabled="broadcastStatus === -2"
circle icon="el-icon-microphone" style="font-size: 32px; padding: 24px;margin-top: 24px;"/>
<p> <p>
<span v-if="broadcastStatus === -2">正在释放资源</span> <span v-if="broadcastStatus === -2">正在释放资源</span>
<span v-if="broadcastStatus === -1">点击开始对讲</span> <span v-if="broadcastStatus === -1">点击开始对讲</span>
@ -295,20 +315,20 @@
</el-tabs> </el-tabs>
</div> </div>
</el-dialog> </el-dialog>
<recordDownload ref="recordDownload"></recordDownload> </div>
</div>
</template> </template>
<script> <script>
import rtcPlayer from '../dialog/rtcPlayer.vue' import rtcPlayer from '../dialog/rtcPlayer.vue'
import LivePlayer from '@liveqing/liveplayer'
import crypto from 'crypto' import crypto from 'crypto'
import jessibucaPlayer from '../common/jessibuca.vue' import jessibucaPlayer from '../common/jessibuca.vue'
import recordDownload from '../dialog/recordDownload.vue'
export default { export default {
name: 'devicePlayer', name: 'devicePlayer',
props: {}, props: {},
components: { components: {
jessibucaPlayer, rtcPlayer, recordDownload, LivePlayer, jessibucaPlayer, rtcPlayer,
}, },
computed: { computed: {
getPlayerShared: function () { getPlayerShared: function () {
@ -334,17 +354,13 @@ export default {
activePlayer: "jessibuca", activePlayer: "jessibuca",
// //
player: { player: {
jessibuca : ["ws_flv", "wss_flv"], jessibuca: ["ws_flv", "wss_flv"],
webRTC: ["rtc", "rtcs"], webRTC: ["rtc", "rtcs"],
}, },
videoHistory: {
date: '',
searchHistoryResult: [] //
},
showVideoDialog: false, showVideoDialog: false,
streamId: '', streamId: '',
app : '', app: '',
mediaServerId : '', mediaServerId: '',
convertKey: '', convertKey: '',
deviceId: '', deviceId: '',
channelId: '', channelId: '',
@ -364,9 +380,8 @@ export default {
scanSpeed: 100, scanSpeed: 100,
scanGroup: 0, scanGroup: 0,
tracks: [], tracks: [],
coverPlaying:false, coverPlaying: false,
tracksLoading: false, tracksLoading: false,
recordPlay: "",
showPtz: true, showPtz: true,
showRrecord: true, showRrecord: true,
tracksNotLoaded: false, tracksNotLoaded: false,
@ -380,7 +395,7 @@ export default {
}; };
}, },
methods: { methods: {
tabHandleClick: function(tab, event) { tabHandleClick: function (tab, event) {
console.log(tab) console.log(tab)
var that = this; var that = this;
that.tracks = []; that.tracks = [];
@ -389,12 +404,12 @@ export default {
if (tab.name === "codec") { if (tab.name === "codec") {
this.$axios({ this.$axios({
method: 'get', method: 'get',
url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtsp&app='+ this.app +'&stream='+ this.streamId url: '/zlm/' + this.mediaServerId + '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtsp&app=' + this.app + '&stream=' + this.streamId
}).then(function (res) { }).then(function (res) {
that.tracksLoading = false; that.tracksLoading = false;
if (res.data.code == 0 && res.data.tracks) { if (res.data.code == 0 && res.data.tracks) {
that.tracks = res.data.tracks; that.tracks = res.data.tracks;
}else{ } else {
that.tracksNotLoaded = true; that.tracksNotLoaded = true;
that.$message({ that.$message({
showClose: true, showClose: true,
@ -402,7 +417,8 @@ export default {
type: 'warning' type: 'warning'
}); });
} }
}).catch(function (e) {}); }).catch(function (e) {
});
} }
}, },
changePlayer: function (tab) { changePlayer: function (tab) {
@ -429,11 +445,6 @@ export default {
case "media": case "media":
this.play(param.streamInfo, param.hasAudio) this.play(param.streamInfo, param.hasAudio)
break; break;
case "record":
this.showVideoDialog = true;
this.videoHistory.date = param.date;
this.queryRecords()
break;
case "streamPlay": case "streamPlay":
this.tabActiveName = "media"; this.tabActiveName = "media";
this.showRrecord = false; this.showRrecord = false;
@ -444,9 +455,6 @@ export default {
break; break;
} }
}, },
timeAxisSelTime: function (val) {
console.log(val)
},
play: function (streamInfo, hasAudio) { play: function (streamInfo, hasAudio) {
this.streamInfo = streamInfo; this.streamInfo = streamInfo;
this.hasAudio = hasAudio; this.hasAudio = hasAudio;
@ -458,12 +466,12 @@ export default {
this.mediaServerId = streamInfo.mediaServerId; this.mediaServerId = streamInfo.mediaServerId;
this.playFromStreamInfo(false, streamInfo) this.playFromStreamInfo(false, streamInfo)
}, },
getUrlByStreamInfo(){ getUrlByStreamInfo() {
console.log(this.streamInfo) console.log(this.streamInfo)
if (location.protocol === "https:") { if (location.protocol === "https:") {
this.videoUrl = this.streamInfo[this.player[this.activePlayer][1]].url this.videoUrl = this.streamInfo[this.player[this.activePlayer][1]]
}else { } else {
this.videoUrl = this.streamInfo[this.player[this.activePlayer][0]].url this.videoUrl = this.streamInfo[this.player[this.activePlayer][0]]
} }
return this.videoUrl; return this.videoUrl;
@ -478,7 +486,7 @@ export default {
}).then(function (res) { }).then(function (res) {
if (res.data.code === 0) { if (res.data.code === 0) {
that.convertKey = res.data.key; that.convertKey = res.data.key;
setTimeout(()=>{ setTimeout(() => {
that.isLoging = false; that.isLoging = false;
that.playFromStreamInfo(false, res.data.data); that.playFromStreamInfo(false, res.data.data);
}, 2000) }, 2000)
@ -501,12 +509,12 @@ export default {
}); });
}); });
}, },
convertStopClick: function() { convertStopClick: function () {
this.convertStop(()=>{ this.convertStop(() => {
this.$refs[this.activePlayer].play(this.videoUrl) this.$refs[this.activePlayer].play(this.videoUrl)
}); });
}, },
convertStop: function(callback) { convertStop: function (callback) {
var that = this; var that = this;
that.$refs.videoPlayer.pause() that.$refs.videoPlayer.pause()
this.$axios({ this.$axios({
@ -515,11 +523,12 @@ export default {
}).then(function (res) { }).then(function (res) {
if (res.data.code == 0) { if (res.data.code == 0) {
console.log(res.data.msg) console.log(res.data.msg)
}else { } else {
console.error(res.data.msg) console.error(res.data.msg)
} }
if (callback )callback(); if (callback) callback();
}).catch(function (e) {}); }).catch(function (e) {
});
that.coverPlaying = false; that.coverPlaying = false;
that.convertKey = ""; that.convertKey = "";
// if (callback )callback(); // if (callback )callback();
@ -532,7 +541,7 @@ export default {
}, },
close: function () { close: function () {
console.log('关闭视频'); console.log('关闭视频');
if (!!this.$refs[this.activePlayer]){ if (!!this.$refs[this.activePlayer]) {
this.$refs[this.activePlayer].pause(); this.$refs[this.activePlayer].pause();
} }
this.videoUrl = ''; this.videoUrl = '';
@ -542,10 +551,6 @@ export default {
this.convertStop(); this.convertStop();
} }
this.convertKey = '' this.convertKey = ''
if (this.recordPlay != '') {
this.stopPlayRecord();
}
this.recordPlay = ''
this.stopBroadcast() this.stopBroadcast()
}, },
@ -571,144 +576,14 @@ export default {
} }
); );
}, },
queryRecords: function () {
if (!this.videoHistory.date) {
return;
}
this.recordsLoading = true;
this.videoHistory.searchHistoryResult = [];
let that = this;
var startTime = this.videoHistory.date + " 00:00:00";
var endTime = this.videoHistory.date + " 23:59:59";
this.$axios({
method: 'get',
url: '/api/gb_record/query/' + this.deviceId + '/' + this.channelId + '?startTime=' + startTime + '&endTime=' + endTime
}).then(function (res) {
console.log(res)
that.recordsLoading = false;
if(res.data.code === 0) {
//
that.videoHistory.searchHistoryResult = res.data.data.recordList;
}else {
this.$message({
showClose: true,
message: res.data.msg,
type: "error",
});
}
}).catch(function (e) {
console.log(e.message);
// that.videoHistory.searchHistoryResult = falsificationData.recordData;
});
},
onTimeChange: function (video) {
// this.queryRecords()
},
playRecord: function (row) {
let that = this;
let startTime = row.startTime
this.recordStartTime = row.startTime
this.showTimeText = row.startTime.split(" ")[1]
let endtime = row.endTime
this.sliderTime = 0;
this.seekTime = new Date(endtime).getTime() - new Date(startTime).getTime();
console.log(this.seekTime)
if (that.streamId != "") {
that.stopPlayRecord(function () {
that.streamId = "";
that.playRecord(row);
})
} else {
this.$axios({
method: 'get',
url: '/api/playback/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
row.endTime
}).then(function (res) {
if (res.data.code === 0) {
that.streamInfo = res.data.data;
that.app = that.streamInfo.app;
that.streamId = that.streamInfo.stream;
that.mediaServerId = that.streamInfo.mediaServerId;
that.ssrc = that.streamInfo.ssrc;
that.videoUrl = that.getUrlByStreamInfo();
}else {
that.$message({
showClose: true,
message: res.data.msg,
type: "error",
});
}
that.recordPlay = true;
});
}
},
stopPlayRecord: function (callback) {
this.$refs[this.activePlayer].pause();
this.videoUrl = '';
this.$axios({
method: 'get',
url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId
}).then(function (res) {
if (callback) callback()
});
},
downloadRecord: function (row) {
let that = this;
if (that.streamId != "") {
that.stopDownloadRecord(function (res) {
if (res.code == 0) {
that.streamId = "";
that.downloadRecord(row);
}else {
this.$message({
showClose: true,
message: res.data.msg,
type: "error",
});
}
})
} else {
this.$axios({
method: 'get',
url: '/api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
row.endTime + '&downloadSpeed=4'
}).then(function (res) {
if (res.data.code == 0) {
let streamInfo = res.data.data;
that.recordPlay = false;
that.$refs.recordDownload.openDialog(that.deviceId, that.channelId, streamInfo.app, streamInfo.stream, streamInfo.mediaServerId);
}else {
that.$message({
showClose: true,
message: res.data.msg,
type: "error",
});
}
});
}
},
stopDownloadRecord: function (callback) {
this.$refs[this.activePlayer].pause();
this.videoUrl = '';
this.$axios({
method: 'get',
url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId
}).then((res)=> {
if (callback) callback(res)
});
},
ptzCamera: function (command) { ptzCamera: function (command) {
console.log('云台控制:' + command); console.log('云台控制:' + command);
let that = this; let that = this;
this.$axios({ this.$axios({
method: 'post', method: 'post',
url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed
}).then(function (res) {}); }).then(function (res) {
});
}, },
//////////////////////////////////////////////// ////////////////////////////////////////////////
videoError: function (e) { videoError: function (e) {
@ -720,7 +595,8 @@ export default {
this.$axios({ this.$axios({
method: 'post', method: 'post',
url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=0&parameter2=' + presetPos + '&combindCode2=0' url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=0&parameter2=' + presetPos + '&combindCode2=0'
}).then(function (res) {}); }).then(function (res) {
});
}, },
setSpeedOrTime: function (cmdCode, groupNum, parameter) { setSpeedOrTime: function (cmdCode, groupNum, parameter) {
let that = this; let that = this;
@ -730,7 +606,8 @@ export default {
this.$axios({ this.$axios({
method: 'post', method: 'post',
url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=' + groupNum + '&parameter2=' + parameter2 + '&combindCode2=' + combindCode2 url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=' + groupNum + '&parameter2=' + parameter2 + '&combindCode2=' + combindCode2
}).then(function (res) {}); }).then(function (res) {
});
}, },
setCommand: function (cmdCode, groupNum, parameter) { setCommand: function (cmdCode, groupNum, parameter) {
let that = this; let that = this;
@ -738,103 +615,17 @@ export default {
this.$axios({ this.$axios({
method: 'post', method: 'post',
url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=' + groupNum + '&parameter2=' + parameter + '&combindCode2=0' url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=' + groupNum + '&parameter2=' + parameter + '&combindCode2=0'
}).then(function (res) {}); }).then(function (res) {
});
}, },
formatTooltip: function (val) { copyUrl: function (dropdownItem) {
var h = parseInt(val / 60);
var hStr = h < 10 ? ("0" + h) : h;
var s = val % 60;
var sStr = s < 10 ? ("0" + s) : s;
return h + ":" + sStr;
},
timeFormatter: function (row, column, cellValue, index) {
return cellValue.split(" ")[1];
},
mergeTime: function (timeArray) {
var resultArray = [];
for (let i = 0; i < timeArray.length; i++) {
var startTime = new Date(timeArray[i].startTime);
var endTime = new Date(timeArray[i].endTime);
if (i == 0) {
resultArray[0] = {
startTime: startTime,
endTime: endTime
}
}
for (let j = 0; j < resultArray.length; j++) {
if (startTime > resultArray[j].endTime) { //
if (startTime - resultArray[j].endTime <= 1000) {
resultArray[j].endTime = endTime;
} else {
resultArray[resultArray.length] = {
startTime: startTime,
endTime: endTime
}
}
} else if (resultArray[j].startTime > endTime) { //
if (resultArray[j].startTime - endTime <= 1000) {
resultArray[j].startTime = startTime;
} else {
resultArray[resultArray.length] = {
startTime: startTime,
endTime: endTime
}
}
}
}
}
console.log(resultArray)
return resultArray;
},
copyUrl: function (dropdownItem){
console.log(dropdownItem) console.log(dropdownItem)
this.$copyText(dropdownItem).then((e)=> { this.$copyText(dropdownItem).then((e) => {
this.$message.success("成功拷贝到粘贴板"); this.$message.success("成功拷贝到粘贴板");
}, (e)=> { }, (e) => {
}) })
}, },
gbPlay(){
console.log('前端控制:播放');
this.$axios({
method: 'get',
url: '/api/playback/resume/' + this.streamId
}).then((res)=> {
this.$refs[this.activePlayer].play(this.videoUrl)
});
},
gbPause(){
console.log('前端控制:暂停');
this.$axios({
method: 'get',
url: '/api/playback/pause/' + this.streamId
}).then(function (res) {});
},
gbScale(command){
console.log('前端控制:倍速 ' + command);
this.$axios({
method: 'get',
url: `/api/playback/speed/${this.streamId }/${command}`
}).then(function (res) {});
},
gbSeek(val){
console.log('前端控制seek ');
console.log(this.seekTime);
console.log(this.sliderTime);
let showTime = new Date(new Date(this.recordStartTime).getTime() + this.seekTime * val / 100)
let hour = showTime.getHours();
let minutes = showTime.getMinutes();
let seconds = showTime.getSeconds();
this.showTimeText = (hour < 10?("0" + hour):hour) + ":" + (minutes<10?("0" + minutes):minutes) + ":" + (seconds<10?("0" + seconds):seconds)
this.$axios({
method: 'get',
url: `/api/playback/seek/${this.streamId }/` + Math.floor(this.seekTime * val / 100000)
}).then( (res)=> {
setTimeout(()=>{
this.$refs[this.activePlayer].play(this.videoUrl)
}, 600)
});
},
getBroadcastStatus() { getBroadcastStatus() {
if (this.broadcastStatus == -2) { if (this.broadcastStatus == -2) {
return "primary" return "primary"
@ -929,7 +720,7 @@ export default {
this.broadcastStatus = -1; this.broadcastStatus = -1;
}); });
this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR,(e)=>{// ICE this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR, (e) => {// ICE
console.error('ICE 协商出错') console.error('ICE 协商出错')
this.$message({ this.$message({
showClose: true, showClose: true,
@ -939,8 +730,8 @@ export default {
this.broadcastStatus = -1; this.broadcastStatus = -1;
}); });
this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED,(e)=>{// offer anwser this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED, (e) => {// offer anwser
console.error('offer anwser 交换失败',e) console.error('offer anwser 交换失败', e)
this.$message({ this.$message({
showClose: true, showClose: true,
message: 'offer anwser 交换失败' + e, message: 'offer anwser 交换失败' + e,
@ -948,18 +739,18 @@ export default {
}); });
this.broadcastStatus = -1; this.broadcastStatus = -1;
}); });
this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_ON_CONNECTION_STATE_CHANGE,(e)=>{// offer anwser this.broadcastRtc.on(ZLMRTCClient.Events.WEBRTC_ON_CONNECTION_STATE_CHANGE, (e) => {// offer anwser
console.log('状态改变',e) console.log('状态改变', e)
if (e === "connecting") { if (e === "connecting") {
this.broadcastStatus = 0; this.broadcastStatus = 0;
}else if (e === "connected") { } else if (e === "connected") {
this.broadcastStatus = 1; this.broadcastStatus = 1;
}else if (e === "disconnected") { } else if (e === "disconnected") {
this.broadcastStatus = -1; this.broadcastStatus = -1;
} }
}); });
this.broadcastRtc.on(ZLMRTCClient.Events.CAPTURE_STREAM_FAILED,(e)=>{// offer anwser this.broadcastRtc.on(ZLMRTCClient.Events.CAPTURE_STREAM_FAILED, (e) => {// offer anwser
console.log('捕获流失败',e) console.log('捕获流失败', e)
this.$message({ this.$message({
showClose: true, showClose: true,
message: '捕获流失败' + e, message: '捕获流失败' + e,
@ -979,17 +770,17 @@ export default {
}, },
stopBroadcast(){ stopBroadcast() {
this.broadcastRtc.close(); this.broadcastRtc.close();
this.broadcastStatus = -1; this.broadcastStatus = -1;
this.$axios({ this.$axios({
method: 'get', method: 'get',
url: '/api/play/broadcast/stop/' + this.deviceId + '/' + this.channelId url: '/api/play/broadcast/stop/' + this.deviceId + '/' + this.channelId
}).then( (res)=> { }).then((res) => {
if (res.data.code == 0) { if (res.data.code == 0) {
// this.broadcastStatus = -1; // this.broadcastStatus = -1;
// this.broadcastRtc.close() // this.broadcastRtc.close()
}else { } else {
this.$message({ this.$message({
showClose: true, showClose: true,
message: res.data.msg, message: res.data.msg,
@ -1034,8 +825,9 @@ export default {
box-sizing: border-box; box-sizing: border-box;
transition: all 0.3s linear; transition: all 0.3s linear;
} }
.control-btn:hover { .control-btn:hover {
cursor:pointer cursor: pointer
} }
.control-btn i { .control-btn i {
@ -1045,11 +837,13 @@ export default {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.control-btn i:hover { .control-btn i:hover {
cursor:pointer cursor: pointer
} }
.control-zoom-btn:hover { .control-zoom-btn:hover {
cursor:pointer cursor: pointer
} }
.control-round { .control-round {
@ -1177,6 +971,7 @@ export default {
.control-bottom .fa { .control-bottom .fa {
transform: rotate(-45deg) translateY(7px); transform: rotate(-45deg) translateY(7px);
} }
.trank { .trank {
width: 80%; width: 80%;
height: 180px; height: 180px;
@ -1184,6 +979,7 @@ export default {
padding: 0 10%; padding: 0 10%;
overflow: auto; overflow: auto;
} }
.trankInfo { .trankInfo {
width: 80%; width: 80%;
padding: 0 10%; padding: 0 10%;

View File

@ -6,18 +6,6 @@
<el-progress :percentage="percentage"></el-progress> <el-progress :percentage="percentage"></el-progress>
</el-col> </el-col>
<el-col :span="6" > <el-col :span="6" >
<!-- <el-dropdown size="mini" title="播放倍速" style="margin-left: 1px;" @command="gbScale">-->
<!-- <el-button-group>-->
<!-- <el-button size="mini" style="width: 100%">-->
<!-- {{scale}}倍速 <i class="el-icon-arrow-down el-icon&#45;&#45;right"></i>-->
<!-- </el-button>-->
<!-- </el-button-group>-->
<!-- <el-dropdown-menu slot="dropdown">-->
<!-- <el-dropdown-item command="1">1倍速</el-dropdown-item>-->
<!-- <el-dropdown-item command="2">2倍速</el-dropdown-item>-->
<!-- <el-dropdown-item command="4">4倍速</el-dropdown-item>-->
<!-- </el-dropdown-menu>-->
<!-- </el-dropdown>-->
<el-button icon="el-icon-download" v-if="percentage < 100" size="mini" title="点击下载可将以缓存部分下载到本地" @click="download()">停止缓存并下载</el-button> <el-button icon="el-icon-download" v-if="percentage < 100" size="mini" title="点击下载可将以缓存部分下载到本地" @click="download()">停止缓存并下载</el-button>
</el-col> </el-col>
</el-row> </el-row>
@ -51,6 +39,7 @@ export default {
taskId: null, taskId: null,
getProgressRun: false, getProgressRun: false,
getProgressForFileRun: false, getProgressForFileRun: false,
timer: null
}; };
}, },
@ -66,7 +55,7 @@ export default {
this.percentage = 0.0; this.percentage = 0.0;
this.getProgressTimer() this.getProgressTimer()
}, },
getProgressTimer(){ getProgressTimer: function (){
if (!this.getProgressRun) { if (!this.getProgressRun) {
return; return;
} }
@ -93,15 +82,24 @@ export default {
this.percentage = (parseFloat(res.data.data.progress)*100).toFixed(1); this.percentage = (parseFloat(res.data.data.progress)*100).toFixed(1);
} }
if (callback)callback(); if (callback)callback();
}else {
this.$message({
showClose: true,
message: res.data.msg,
type: "error",
});
this.close();
} }
}).catch((e) =>{ }).catch((e) =>{
console.log(e)
}); });
}, },
close: function (){ close: function (){
if (this.streamInfo.progress < 100) {
this.stopDownloadRecord(); this.stopDownloadRecord();
if (this.timer !== null) {
window.clearTimeout(this.timer);
this.timer = null;
} }
this.showDialog=false; this.showDialog=false;
this.getProgressRun = false; this.getProgressRun = false;

View File

@ -140,9 +140,9 @@ export default {
if (res.data.code === 0 && res.data.data) { if (res.data.code === 0 && res.data.data) {
let videoUrl; let videoUrl;
if (location.protocol === "https:") { if (location.protocol === "https:") {
videoUrl = res.data.data.wss_flv.url; videoUrl = res.data.data.wss_flv;
} else { } else {
videoUrl = res.data.data.ws_flv.url; videoUrl = res.data.data.ws_flv;
} }
itemData.playUrl = videoUrl; itemData.playUrl = videoUrl;
that.setPlayUrl(videoUrl, idxTmp); that.setPlayUrl(videoUrl, idxTmp);

View File

@ -5,6 +5,7 @@ import Layout from "../layout/index.vue"
import console from '../components/console.vue' import console from '../components/console.vue'
import deviceList from '../components/DeviceList.vue' import deviceList from '../components/DeviceList.vue'
import channelList from '../components/channelList.vue' import channelList from '../components/channelList.vue'
import gbRecordDetail from '../components/GBRecordDetail.vue'
import pushVideoList from '../components/PushVideoList.vue' import pushVideoList from '../components/PushVideoList.vue'
import streamProxyList from '../components/StreamProxyList.vue' import streamProxyList from '../components/StreamProxyList.vue'
import map from '../components/map.vue' import map from '../components/map.vue'
@ -64,6 +65,11 @@ export default new VueRouter({
name: 'channelList', name: 'channelList',
component: channelList, component: channelList,
}, },
{
path: '/gbRecordDetail/:deviceId/:channelId/',
name: 'gbRecordDetail',
component: gbRecordDetail,
},
{ {
path: '/parentPlatformList/:count/:page', path: '/parentPlatformList/:count/:page',
name: 'parentPlatformList', name: 'parentPlatformList',

View File

@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 1291092 */ font-family: "iconfont"; /* Project id 1291092 */
src: url('iconfont.woff2?t=1655453611360') format('woff2'), src: url('iconfont.woff2?t=1673251105600') format('woff2'),
url('iconfont.woff?t=1655453611360') format('woff'), url('iconfont.woff?t=1673251105600') format('woff'),
url('iconfont.ttf?t=1655453611360') format('truetype'); url('iconfont.ttf?t=1673251105600') format('truetype');
} }
.iconfont { .iconfont {
@ -13,6 +13,14 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-slider:before {
content: "\e7e0";
}
.icon-slider-right:before {
content: "\ea19";
}
.icon-list:before { .icon-list:before {
content: "\e7de"; content: "\e7de";
} }

Binary file not shown.