Commit 8b0ff3767b23f9479a0b3ebe8e343ed6470bd194

Authored by 648540858
2 parents cfed8606 a88518f8

Merge branch 'wvp-28181-2.0'

# Conflicts:
#	sql/update.sql
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
#	src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
Showing 204 changed files with 4644 additions and 1894 deletions
README.md
1 ![logo](https://raw.githubusercontent.com/648540858/wvp-GB28181-pro/wvp-28181-2.0/web_src/static/logo.png) 1 ![logo](https://raw.githubusercontent.com/648540858/wvp-GB28181-pro/wvp-28181-2.0/web_src/static/logo.png)
2 -# 寮绠卞嵆鐢ㄧ殑8181鍗忚瑙嗛骞冲彴 2 +# 寮绠卞嵆鐢ㄧ殑28181鍗忚瑙嗛骞冲彴
3 3
4 [![Build Status](https://travis-ci.org/xia-chu/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xia-chu/ZLMediaKit) 4 [![Build Status](https://travis-ci.org/xia-chu/ZLMediaKit.svg?branch=master)](https://travis-ci.org/xia-chu/ZLMediaKit)
5 [![license](http://img.shields.io/badge/license-MIT-green.svg)](https://github.com/xia-chu/ZLMediaKit/blob/master/LICENSE) 5 [![license](http://img.shields.io/badge/license-MIT-green.svg)](https://github.com/xia-chu/ZLMediaKit/blob/master/LICENSE)
@@ -25,7 +25,7 @@ WEB VIDEO PLATFORM鏄竴涓熀浜嶨B28181-2016鏍囧噯瀹炵幇鐨勫紑绠卞嵆鐢ㄧ殑缃戠 @@ -25,7 +25,7 @@ WEB VIDEO PLATFORM鏄竴涓熀浜嶨B28181-2016鏍囧噯瀹炵幇鐨勫紑绠卞嵆鐢ㄧ殑缃戠
25 鏃ㄥ湪鎵撻犱竴涓槗閰嶇疆,鏄撲娇鐢,渚夸簬缁存姢鐨8181鍥芥爣淇′护绯荤粺, 渚濇墭浼樼鐨勫紑婧愭祦濯掍綋鏈嶅姟妗嗘灦ZLMediaKit, 瀹炵幇涓涓畬鏁存槗鐢℅B28181骞冲彴. 25 鏃ㄥ湪鎵撻犱竴涓槗閰嶇疆,鏄撲娇鐢,渚夸簬缁存姢鐨8181鍥芥爣淇′护绯荤粺, 渚濇墭浼樼鐨勫紑婧愭祦濯掍綋鏈嶅姟妗嗘灦ZLMediaKit, 瀹炵幇涓涓畬鏁存槗鐢℅B28181骞冲彴.
26 26
27 # 閮ㄧ讲鏂囨。 27 # 閮ㄧ讲鏂囨。
28 -[https://github.com/648540858/wvp-GB28181-pro/wiki](https://github.com/648540858/wvp-GB28181-pro/wiki) 28 +[doc.wvp-pro.cn](https://doc.wvp-pro.cn)
29 29
30 # gitee鍚屾浠撳簱 30 # gitee鍚屾浠撳簱
31 https://gitee.com/pan648540858/wvp-GB28181-pro.git 31 https://gitee.com/pan648540858/wvp-GB28181-pro.git
bootstrap.sh 100755 → 100644
doc/README.md 0 → 100644
  1 +# 介绍
  2 +
  3 +> 开箱即用的28181协议视频平台
  4 +
  5 +# 概述
  6 +- WVP-PRO基于GB/T 28181-2016标准实现的流媒体平台,依托优秀的开源流媒体服务[ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit),提供完善丰富的功能。
  7 +- GB/T 28181-2016 中文标准名称是《公共安全视频监控联网系统信息传输、交换、控制技术要求》是监控领域的国家标准。大量应用于政府视频平台。
  8 +- 通过28181协议你可以将IPC摄像头接入平台,可以观看也可以使用28181/rtsp/rtmp/flv等协议将视频流分发到其他平台。
  9 +
  10 +# 特性
  11 +- 实现标准的28181信令,兼容常见的品牌设备,比如海康、大华、宇视等品牌的IPC、NVR以及平台。
  12 +- 支持将国标设备级联到其他国标平台,也支持将不支持国标的设备的图像或者直播推送到其他国标平台
  13 +- 前端完善,自带完整前端页面,无需二次开发可直接部署使用。
  14 +- 完全开源,且使用MIT许可协议。保留版权的情况下可以用于商业项目。
  15 +- 支持多流媒体节点负载均衡。
  16 +
  17 +# 我们实现了哪些国标功能
  18 +**作为上级平台**
  19 +- [X] 注册
  20 +- [X] 注销
  21 +- [X] 实时视音频点播
  22 +- [X] 设备控制
  23 + - [X] 云台控制
  24 + - [ ] 远程启动
  25 + - [ ] 录像控制
  26 + - [ ] 报警布防/撤防
  27 + - [ ] 报警复位
  28 + - [X] 强制关键帧
  29 + - [ ] 拉框放大
  30 + - [ ] 拉框缩小
  31 + - [ ] 看守位控制
  32 + - [ ] 设备配置
  33 +- [X] 报警事件通知和分发
  34 +- [X] 设备目录订阅
  35 +- [X] 网络设备信息查询
  36 + - [X] 设备目录查询
  37 + - [X] 设备状态查询
  38 + - [ ] 设备配置查询
  39 + - [ ] 设备预置位查询
  40 +- [X] 状态信息报送
  41 +- [X] 设备视音频文件检索
  42 +- [X] 历史视音频的回放
  43 + - [X] 播放
  44 + - [X] 暂停
  45 + - [X] 进/退
  46 + - [X] 停止
  47 +- [X] 视音频文件下载
  48 +- [X] 校时
  49 +- [X] 订阅和通知
  50 + - [X] 事件订阅
  51 + - [X] 移动设备位置订阅
  52 + - [X] 报警订阅
  53 + - [X] 目录订阅
  54 +- [ ] 语音广播
  55 +- [ ] 语音对讲
  56 +
  57 +**作为下级平台**
  58 +- [X] 注册
  59 +- [X] 注销
  60 +- [X] 实时视音频点播
  61 +- [ ] 设备控制
  62 + - [ ] 云台控制
  63 + - [ ] 远程启动
  64 + - [ ] 录像控制
  65 + - [ ] 报警布防/撤防
  66 + - [ ] 报警复位
  67 + - [ ] 强制关键帧
  68 + - [ ] 拉框放大
  69 + - [ ] 拉框缩小
  70 + - [ ] 看守位控制
  71 + - [ ] 设备配置
  72 +- [ ] 报警事件通知和分发
  73 +- [X] 设备目录订阅
  74 +- [X] 网络设备信息查询
  75 + - [X] 设备目录查询
  76 + - [X] 设备状态查询
  77 + - [ ] 设备配置查询
  78 + - [ ] 设备预置位查询
  79 +- [X] 状态信息报送
  80 +- [X] 设备视音频文件检索
  81 +- [X] 历史视音频的回放
  82 + - [X] 播放
  83 + - [x] 暂停
  84 + - [x] 进/退
  85 + - [x] 停止
  86 +- [ ] 视音频文件下载
  87 +- [ ] ~~校时~~
  88 +- [X] 订阅和通知
  89 + - [X] 事件订阅
  90 + - [X] 移动设备位置订阅
  91 + - [ ] 报警订阅
  92 + - [X] 目录订阅
  93 +- [ ] 语音广播
  94 +- [ ] 语音对讲
  95 +
  96 +
  97 +
  98 +
  99 +# 社区
  100 +代码目前托管在GitHub和Gitee,Gitee目前作为加速仓库使用,不接受issue。
  101 +GitHub: [https://github.com/648540858/wvp-GB28181-pro](https://github.com/648540858/wvp-GB28181-pro)
  102 +Gitee: [https://gitee.com/pan648540858/wvp-GB28181-pro](https://gitee.com/pan648540858/wvp-GB28181-pro)
0 \ No newline at end of file 103 \ No newline at end of file
doc/_content/ability/_media/cascade1.png 0 → 100644

37.4 KB

doc/_content/ability/_media/cascade2.png 0 → 100644

162 KB

doc/_content/ability/_media/cascade3.png 0 → 100644

129 KB

doc/_content/ability/_media/cascade4.png 0 → 100644

119 KB

doc/_content/ability/_media/img.png 0 → 100644

13.1 KB

doc/_content/ability/_media/img_1.png 0 → 100644

17.1 KB

doc/_content/ability/_media/img_10.png 0 → 100644

65.1 KB

doc/_content/ability/_media/img_11.png 0 → 100644

80.5 KB

doc/_content/ability/_media/img_12.png 0 → 100644

66.2 KB

doc/_content/ability/_media/img_13.png 0 → 100644

58.1 KB

doc/_content/ability/_media/img_14.png 0 → 100644

692 Bytes

doc/_content/ability/_media/img_15.png 0 → 100644

98.9 KB

doc/_content/ability/_media/img_16.png 0 → 100644

41.5 KB

doc/_content/ability/_media/img_17.png 0 → 100644

56.3 KB

doc/_content/ability/_media/img_18.png 0 → 100644

64.6 KB

doc/_content/ability/_media/img_2.png 0 → 100644

41.1 KB

doc/_content/ability/_media/img_3.png 0 → 100644

16.2 KB

doc/_content/ability/_media/img_4.png 0 → 100644

136 KB

doc/_content/ability/_media/img_5.png 0 → 100644

152 KB

doc/_content/ability/_media/img_6.png 0 → 100644

62.2 KB

doc/_content/ability/_media/img_7.png 0 → 100644

46.3 KB

doc/_content/ability/_media/img_8.png 0 → 100644

43.8 KB

doc/_content/ability/_media/img_9.png 0 → 100644

80.1 KB

doc/_content/ability/auto_play.md 0 → 100644
  1 +<!-- 自动点播 -->
  2 +# 自动点播
doc/_content/ability/cascade.md 0 → 100644
  1 +<!-- 国标级联的使用 -->
  2 +# 国标级联的使用
  3 +国标28181不同平台之间支持两种连接方式,平级和上下级,WVP目前支持向上级级联。
  4 +## 1 接入平台
  5 +### 1.1 wvp-pro
  6 +#### 1.1.1 wvp-pro管理页面点击添加
  7 + ![cascade1](_media/cascade1.png)
  8 +#### 1.1.2 填入wvp-pro上级平台信息
  9 + ![cascade1](_media/img_4.png)
  10 + ![cascade1](_media/img_5.png)
  11 +#### 1.1.3 编辑wvp-pro上级设备信息,开启订阅
  12 + ![cascade1](_media/img_6.png)
  13 +### 1.2 大华平台
  14 +### 1.3 海康平台
  15 +### 1.4 liveGBS
  16 +#### 1.4.1. wvp-pro管理页面点击添加
  17 + ![添加](_media/cascade1.png)
  18 +#### 1.4.2. 填入liveGBS平台信息
  19 + ![填入liveGBS平台信息1](_media/cascade2.png)
  20 + ![填入liveGBS平台信息2](_media/cascade3.png)
  21 +#### 1.4.3. 编辑liveGBS设备信息,开启目录订阅
  22 + ![cascade1](_media/cascade4.png)
  23 +#### 1.4.4. 编辑liveGBS设备信息,开启GPS订阅
  24 + ![cascade1](_media/img_7.png)
  25 +
  26 +## 2 添加目录与通道
  27 +1. 级联平台添加目录信息
  28 + ![cascade1](_media/img_1.png)
  29 +2. 为目录添加通道
  30 + ![cascade1](_media/img_2.png)
  31 +3. 设置默认流目录
  32 +如果需要后续自动生成的流信息都在某一个节点下,可以在对应节点右键设置为默认
  33 + ![cascade1](_media/img_3.png)
  34 +
doc/_content/ability/cascade2.md 0 → 100644
  1 +<!-- 国标级联的使用 -->
  2 +# 国标级联的使用
  3 +国标28181不同平台之间支持两种连接方式,平级和上下级,WVP目前支持向上级级联。
  4 +## 添加上级平台
  5 +在国标级联页面点击“添加”按钮,以推送到上级WVP为例子,参看[接入设备](./_content/ability/device.md)
  6 +![cascade17](_media/img_17.png)
  7 +点击保存可以在上级的国标通道列表看到新增加的设备;
  8 +国标级联列表出现了级联的这个平台;同时状态显示为在线,如果状态为离线那么可能是你的服务信息配置有误或者网络不通。
  9 +订阅信息列有三个图标,表示上级开启订阅,从左到右依次是:报警订阅,目录订阅,移动位置订阅。
  10 +## 推送通道
  11 +点击你要推送的平台的“选择通道”按钮。
  12 +![cascade18](_media/img_18.png)
  13 +- **页面结构**
  14 + - 左侧为目录结构
  15 + 选择未分配,则右侧显示待分配的通道,可以点击“添加按钮”,在弹窗中选择要放置的位置,保存后即可添加通道成功
  16 + 选择其他的目录可以看到已经分配在这个目录下的通道,可以对其进行删除后重新在未分配中去分配。
  17 + - 右侧为数据展示以及操作
  18 + 国标通道栏内为来自其他国标设备/平台的通道;直播流通道为来自推流/拉流代理的通道。
0 \ No newline at end of file 19 \ No newline at end of file
doc/_content/ability/cloud_record.md 0 → 100644
  1 +<!-- 云端录像 -->
  2 +# 云端录像
  3 +云端录像是对录制在zlm服务下的录像文件的管理,录像的文件路径默认在ZLM/www/record下,使用云端录像功能必须部署wvp-pro-assist,主要通过调用wvp-pro-assist的接口完成各种功能。
  4 +如果你需要24小时的录像,目前有一个这种方案,可以参考[7*24不间断录像](./_content/ability/continuous_recording.md)。
  5 +1. 云段录像支持录像文件的查看,播放(可能因为编码的原因导致无法播放);
  6 +2. 支持录像的下载;
  7 +3. 支持录像的合并下载;
  8 +功能没有太多特殊的地方就不一一介绍了,大家自行体验吧。
doc/_content/ability/continuous_recording.md 0 → 100644
  1 +<!-- 7*24不间断录像 -->
  2 +# 7*24不间断录像
  3 +
  4 +目前如果要实现不间断录像如果只是关闭无人观看停止推流是不够的,设备可能经历断网,重启,都会导致录像的中断,目前给大家提供一种可用的临时方案。
  5 +
  6 +**原理:** wvp支持使用流地址自动点播,即你拿到一个流地址直接去播放,即使设备处于未点播状态,wvp会自动帮你点播;ZLM
  7 +的拉流代理成功后会无限重试,只要流一恢复就可以拉起来,基于这两个原理。
  8 +**方案如下:**
  9 +1. wvp的配置中user-settings->auto-apply-play设置为团true,开启自动点播;
  10 +2. 点击你要录像的通道,点击播放页面左下角的“更多地址”,点击rtsp,此时复制了rtsp地址到剪贴板;
  11 +3. 在拉流代理中添加一路流,地址填写你复制的地址,启用成功即可。
  12 +**前提:**
  13 +1. wvp使用多端口收流,不然你无法得到一个固定的流地址,也就无法实现自动点播。
  14 +
doc/_content/ability/device.md 0 → 100644
  1 +<!-- 接入设备 -->
  2 +# 接入设备
  3 +设备接入主要是需要在设备上配置28181上级也就是WVP-PRO的信息,只有信息一致的情况才可以注册成功。设备注册成功后打开WVP->国标设备,可以看到新增加的设备;[设备使用](./_content/ability/device_use.md),
  4 +主要有以下字段需要配置:
  5 +
  6 +- sip->ip
  7 +本机IP,不要使用127.0.0.1/0.0.0.0, 除非你对项目及其熟悉
  8 +
  9 +- sip->port
  10 +28181服务监听的端口
  11 +
  12 +- sip->domain
  13 +domain宜采用ID统一编码的前十位编码。
  14 +
  15 +- sip->id
  16 +28181服务ID
  17 +
  18 +- sip->password
  19 +28181服务密码
  20 +
  21 +- 配置信息在如下位置
  22 +
  23 +![_media/img_16.png](_media/img_16.png)
  24 +***
  25 +## 大华摄像头
  26 +![_media/img_10.png](_media/img_10.png)
  27 +## 大华NVR
  28 +![_media/img_11.png](_media/img_11.png)
  29 +## 艾科威视摄像头
  30 +![_media/img_15.png](_media/img_15.png)
  31 +## 水星摄像头
  32 +![_media/img_12.png](_media/img_12.png)
  33 +## 海康摄像头
  34 +![_media/img_9.png](_media/img_9.png)
  35 +
  36 +[设备使用](_content/ability/device_use.md)
doc/_content/ability/device_use.md 0 → 100644
  1 +<!-- 设备使用 -->
  2 +# 设备使用
  3 +### 更新设备通道
  4 + 点击列表末尾的“刷新”按钮,可以看到一个圆形进度条,等进度结束提示成功后即可更新完成,如果通道数量有变化你可以看点击左上角的![刷新](_media/img_14.png)即可看到通道数量的变化;如果通道数量仍未0,那么可能时对方尚未推送通道给你。
  5 +### 查看设备通道
  6 + 点击列表末尾的“通道”按钮,
  7 +### 查看设备定位
  8 + 点击列表末尾的“定位”按钮,即可跳转到地图页面看到设备的位置
  9 +### 编辑设备在WVP中一些功能
  10 +点击列表末尾的“编辑”按钮,即可在打开的弹窗中对设备功能进行修改
  11 +- 设备名称
  12 + 如何未能从设备里读取到设备名称或者需要自己重命名,那么可以修改此选项。
  13 +- 字符集
  14 + 修改读取设备数据时使用的字符集,默认为GB2312,但是GB2312收录的汉字不全,所以有时候回遇到乱码,可以修改为UTF-8来解决。
  15 +- 地理坐标系
  16 + 展示此设备定位信息时使用的设用什么坐标系来解析经纬度,一般不用修改,如果遇到定位不准,可以修改尝试修改此选项解决。
  17 +- 目录结构
  18 + 展示设备的通道信息时,使用设备作为树形结构的依据,国标28181定义了两种树形结构,详情查看[国标28181的树形结构](./_content/theory/channel_tree.md);
  19 +- 目录订阅
  20 + 填写订阅周期即可对设备开启目录订阅,设备如果支持目录订阅那么设备在通道信息发生变化时就会通知WVP哪些通道发生了那些变化,包括通道增加/删除/更新/上线/下线/视频丢失/故障。0为取消订阅。
  21 + 一般NVR和平台对接可以开启此选项,直接接摄像机开启此选项意义不大。
  22 +- 移动位置订阅
  23 + 对设备开启移动位置订阅,设备如果支持目录订阅那么设备位置发生变化时会通知到WVP,一般执法记录仪可以开启此选项,对固定位置的设备意义不大。
  24 +- SSRC校验
  25 + 为了解决部分设备出现的串流问题,可以打开此选项。ZLM会严格按照给定的ssrc处理视频流。部分设备流信息不标准,开启可能导致无法点播。
  26 +### 删除设备
  27 + 可以删除WVP中的设备信息,如果设备28181配置未更改,那么设备在下一次注册后仍然会注册上来。
  28 +### 点播视频
  29 + 进入通道列表后,点击列表末尾的“播放”按钮,稍等即可弹出播放页面
  30 +### 设备录像
  31 + 进入通道列表后,点击列表末尾的“设备录像”按钮,也可以在播放页面点击录像查询进入录像查看页面,选择要查看的日期即可对录像进行播放和下载。
  32 +### 云台控制
  33 + 可以对支持云台功能的设备进行上下左右的转动以及拉近拉远的操作。
  34 +### 获取视频的播放器地址
  35 + 视频点播成功后在实时视频页面,点击“更多地址”可以看到所有的播放地址,地址是否可以播放与你是否完整编译启用zlm功能有关,更与网络有关。
0 \ No newline at end of file 36 \ No newline at end of file
doc/_content/ability/gis.md 0 → 100644
  1 +<!-- 电子地图 -->
  2 +# 电子地图
  3 +WVP提供了简单的电子地图用于设备的定位以及移动设备的轨迹信息,电子地图基于开源的地图引擎openlayers开发。
  4 +### 查看设备定位
  5 +1. 可以在设备列表点击“定位”按钮,自动跳转到电子地图页面;
  6 +2. 在电子地图页面在设备上右键点击“定位”获取设备/平台下的所有通道位置。
  7 +3. 单击通道信息可以定位到具体的通道
  8 +
  9 +
  10 +### 查询设备轨迹
  11 +查询轨迹需要提前配置save-position-history选项开启轨迹信息的保存,目前WVP此处未支持分库分表,对于大数据量的轨迹信息无法胜任,有需求请自行二次开发或者定制开发。
  12 +在电子地图页面在设备上右键点击“查询轨迹”获取设备轨迹信息。
  13 +
  14 +PS: 目前的底图仅用用作演示和学习,商用情况请自行购买授权使用。
  15 +
  16 +### 更换底图以及底图配置
  17 +目前WVP支持使用了更换底图,配置文件在web_src/static/js/mapConfig.js,请修改后重新编译前端文件。
  18 +```javascript
  19 +window.mapParam = {
  20 + // 开启/关闭地图功能
  21 + enable: true,
  22 + // 坐标系 GCJ-02 WGS-84,
  23 + coordinateSystem: "GCJ-02",
  24 + // 地图瓦片地址
  25 + tilesUrl: "http://webrd0{1-4}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",
  26 + // 瓦片大小
  27 + tileSize: 256,
  28 + // 默认层级
  29 + zoom:10,
  30 + // 默认地图中心点
  31 + center:[116.41020, 39.915119],
  32 + // 地图最大层级
  33 + maxZoom:18,
  34 + // 地图最小层级
  35 + minZoom: 3
  36 +}
  37 +```
doc/_content/ability/node_manger.md 0 → 100644
  1 +<!-- 节点管理 -->
  2 +# 节点管理
  3 +WVP支持单个WVP多个ZLM的方案来扩展WVP的视频并发能力,并发点播是因为带宽和性能的原因,单个ZLM节点能支持的路数有限,所以WVP增加了ZLM集群来扩展并发并且保证ZLM的高可用。
  4 +## 默认节点
  5 +WVP中为了保证功能的完整性,ZLM节点至少要有一个默认节点,这个节点不是在管理页面添加的,而是在WVP的配置文件中配置的,这个节点不可在页面删除。每次启动会自动从配置文件中读取配置写入数据库备用。
  6 +## 新增节点
  7 +启动你要添加的zlm节点,然后点击“添加节点”按钮输入zlm的ip, http端口,SECRET。点击测试测试完成则开始对节点进行详细的设置,如果你的zlm是使用docker启动的,可能存在zlm使用的端口与宿主机端口不一致的情况,需要在这里一一配置。
  8 +## wvp使用多个节点的原理
  9 +wvp会把连接的节点统一记录在redis中,并记录zlm的负载情况,当新的请求到来时,会取出负载最低的那个zlm进行使用。以此保证节点负载均衡。
doc/_content/ability/online_doc.md 0 → 100644
  1 +<!-- 在线文档 -->
  2 +# 在线文档
doc/_content/ability/proxy.md 0 → 100644
  1 +<!-- 拉流代理 -->
  2 +# 拉流代理
  3 +不是所有的摄像机都支持国标或者推流的,但是这些设备可以得到一个视频播放地址,通常为rtsp协议,
  4 +以大华为例:
  5 +```text
  6 +rtsp://{user}:{passwd}@{ipc_ip}:{rtsp_port}/cam/realmonitor?channel=1&subtype=0
  7 +```
  8 +可以得到这样一个流地址,可以直接用vlc进行播放,此时我们可以通过拉流代理功能将这个设备推送给其他国标平台了。
  9 +流程如下:
  10 +```plantuml
  11 +@startuml
  12 +"摄像机" <- "ZLMediaKit": 1. 流去流信息到ZLM
  13 +"ZLMediaKit" -> "WVP-PRO": 2. 收到hook通知得到流信息
  14 +"上级国标平台" -> "WVP-PRO": 3. 点播这路视频
  15 +"WVP-PRO" -> "ZLMediaKit": 4. 通知推流到上级国标平台
  16 +@enduml
  17 +```
  18 +## 添加代理
  19 +拉流代理支持两种方式:
  20 +1. ZLM中直接代理流,支持RTSP/RTMP,不支持转码;
  21 +2. 借助ffmpeg完成拉转,可以通过修改ffmpeg拉转参数完成转码。
  22 +点击页面的“添加代理”,安装提示操作即可,保存并启用成功后,可以在国标级联中[添加通道推送给上级平台](./_content/ability/cascade?id=_2-%e6%b7%bb%e5%8a%a0%e7%9b%ae%e5%bd%95%e4%b8%8e%e9%80%9a%e9%81%93)
  23 +
  24 +PS: ffmpeg默认模板不需修改,需要修改参数自行去ZLM配置文件中添加一个即可。
doc/_content/ability/push.md 0 → 100644
  1 +<!-- 推流列表 -->
  2 +# 推流列表
  3 +## 功能说明
  4 +
  5 +WVP支持三种图像输入方式,直播,[拉流代理](_content/ability/proxy.md),[国标](_content/ability/device.md),直播设备接入流程如下
  6 +```plantuml
  7 +@startuml
  8 +"直播设备" -> "ZLMediaKit": 1. 发起推流
  9 +"ZLMediaKit" -> "WVP-PRO": 2. 收到hook通知得到流信息
  10 +"上级国标平台" -> "WVP-PRO": 3. 点播这路视频
  11 +"WVP-PRO" -> "ZLMediaKit": 4. 通知推流到上级国标平台
  12 +@enduml
  13 +```
  14 +1. 默认情况下WVP收到推流信息后,列表中出现这条推流信息,此时你可以点击“加入国标”按钮为此路推流配置名称以及国标编号,只有有国标编号的推流才可以添加到级联平台,保存成功后可以在国标级联中[添加通道推送给上级平台](_content/ability/cascade?id=_2-%e6%b7%bb%e5%8a%a0%e7%9b%ae%e5%bd%95%e4%b8%8e%e9%80%9a%e9%81%93)
  15 +2. WVP也支持推流前导入大量通道直接推送给上级,点击“下载模板”按钮,根据示例修改模板后,点击“通道导入”按钮导入通道数据,保存成功后可以在国标级联中[添加通道推送给上级平台](_content/ability/cascade?id=_2-%e6%b7%bb%e5%8a%a0%e7%9b%ae%e5%bd%95%e4%b8%8e%e9%80%9a%e9%81%93)
  16 +
  17 +## 推拉流鉴权规则
  18 +为了保护服务器的WVP默认开启推流鉴权(目前不支持关闭此功能)
  19 +
  20 +### 推流规则
  21 +推流时需要携带推流鉴权的签名sign,sign=md5(pushKey),pushKey来自用户表,每个用户会有一个不同的pushKey.
  22 +例如app=test,stream=live,pushKey=1000,ip=192.168.1.4, port=10554 那么推流地址为:
  23 +```
  24 +rtsp://192.168.1.4:10554/test/live?sign=a9b7ba70783b617e9998dc4dd82eb3c5
  25 +```
  26 +支持推流时自定义播放鉴权Id,参数名为callId,此时sign=md5(callId_pushKey)
  27 +例如app=test,stream=live,pushKey=1000,callId=12345678, ip=192.168.1.4, port=10554 那么推流地址为:
  28 +```
  29 +rtsp://192.168.1.4:10554/test/live?callId=12345678&sign=c8e6e01dde2d60c66dcea8d2498ffef1
  30 +```
  31 +### 播放规则
  32 +默认情况播放不需要鉴权,但是如果推流时携带了callId,那么播放时必须携带callId
  33 +例如app=test,stream=live,无callId, ip=192.168.1.4, port=10554 那么播放地址为:
  34 +```
  35 +rtsp://192.168.1.4:10554/test/live
  36 +```
  37 +例如app=test,stream=live,callId=12345678, ip=192.168.1.4, port=10554 那么播放地址为:
  38 +```
  39 +rtsp://192.168.1.4:10554/test/live?callId=12345678
  40 +```
  41 +
doc/_content/ability/user.md 0 → 100644
  1 +<!-- 用户管理 -->
  2 +# 用户管理
doc/_content/about_doc.md 0 → 100644
  1 +<!-- 关于本文档 -->
  2 +
  3 +# 关于本文档
  4 +本文档开源在gitee上,[https://gitee.com/pan648540858/wvp-pro-doc.git](https://gitee.com/pan648540858/wvp-pro-doc.git),如果文档出现任何错误或者不易理解的语句,请大家提ISSUE帮助我及时更正。欢迎大家提交PR一起维护这份文档,让更多的人可以使用到这个开源的视频平台。
  5 +
doc/_content/disclaimers.md 0 → 100644
  1 +# 免责声明
  2 +WVP-PRO自有代码使用宽松的MIT协议,在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。 但是本项目也零碎的使用了一些其他的开源代码,在商用的情况下请自行替代或剔除; 由于使用本项目而产生的商业纠纷或侵权行为一概与本项目及开发者无关,请自行承担法律风险。 在使用本项目代码时,也应该在授权协议中同时表明本项目依赖的第三方库的协议
0 \ No newline at end of file 3 \ No newline at end of file
doc/_content/donation.md 0 → 100644
  1 +# 捐赠
  2 +项目目前仍在积极开发。大家的捐赠以及start可以让我看到大家的支持于关注。更加有动力把项目维护下去。
  3 +
  4 +<div align="left">
  5 +<img src=_media/weixin.jpg style="height: 500px; border: 1px solid #e2e2e2"/>
  6 +<img src=_media/zhifubao.jpg style="height: 500px; border: 1px solid #e2e2e2; margin-left: 20px"/>
  7 +</div>
0 \ No newline at end of file 8 \ No newline at end of file
doc/_content/introduction/_media/img.png 0 → 100644

112 KB

doc/_content/introduction/_media/img_1.png 0 → 100644

150 KB

doc/_content/introduction/_media/img_2.png 0 → 100644

206 KB

doc/_content/introduction/compile.md 0 → 100644
  1 +<!-- 编译 -->
  2 +# 编译
  3 +WVP-PRO不只是实现了国标28181的协议,本身也是一个完整的视频平台。所以对于新手来说,你可能需要一些耐心来完成。遇到问题不要焦躁,你可以
  4 +1. 百度
  5 +2. 如果身边有熟悉java的朋友,可以咨询下朋友;
  6 +3. 来群里(901799015)咨询群友;
  7 +4. 向作者发送邮件648540858@qq.com;
  8 +5. 作者远程支持(有偿)。
  9 + 如果这些仍不能解决你的问题,那么你可能需要与作者我一起合作完成这个项目,解决你遇到的问题。
  10 +
  11 +
  12 +WVP-PRO使用Spring boot开发,maven管理依赖。对于熟悉spring开发的朋友是很容易进行编译部署以及运行的。
  13 +下面将提供一种通用方法方便大家运行项目。
  14 +## 1 服务介绍
  15 +| 服务 | 作用 | 是否必须 |
  16 +|----------------|------------------------------------------|-------------------------|
  17 +| WVP-PRO | 实现国标28181的信令以及视频平台相关的功能 | 是 |
  18 +| ZLMediaKit | 为WVP-PRO提供国标28181的媒体部分的实现,以及各种视频流格式的分发支持 | 是 |
  19 +| wvp-pro-assist | wvp的辅助录像程序,也可单独跟zlm一起使用,提供录像控制,录像合并下载接口 | 否(不安装只是影响云端录像功能和国标录像下载) |
  20 +
  21 +## 2 安装依赖
  22 +| 依赖 | 版本 | 用途 | 开发环境需要 | 生产环境需要 |
  23 +|--------|------------|-------------|--------|--------|
  24 +| jdk | >=1.8 | 运行与编译java代码 | 是 | 是 |
  25 +| maven | >=3.3 | 管理java代码依赖 | 否 | 否 |
  26 +| git || 下载/更新/提交代码 | 否 | 否 |
  27 +| nodejs || 编译于运行前端文件 | 否 | 否 |
  28 +| npm || 管理前端文件依赖 | 否 | 否 |
  29 +
  30 +如果你是一个新手,建议你使用linux或者macOS平台。windows不推荐。
  31 +
  32 +ubuntu环境,以ubuntu 18为例:
  33 +``` bash
  34 +apt-get install -y openjdk-11-jre git maven nodejs npm
  35 +```
  36 +centos环境,以centos 8为例:
  37 +```bash
  38 +yum install -y java-1.8.0-openjdk.x86_64 git maven nodejs npm
  39 +```
  40 +window环境,以windows10为例:
  41 +```bash
  42 +这里不细说了,百度或者谷歌一搜一大把,基本都是下一步下一步,然后配置环境变量。
  43 +```
  44 +## 3 安装mysql以及redis
  45 +这里依然是参考网上教程,自行安装吧。
  46 +
  47 +## 4 编译ZLMediaKit
  48 +参考ZLMediaKit[WIKI](https://github.com/ZLMediaKit/ZLMediaKit/wiki),截取一下关键步骤:
  49 +```bash
  50 +# 国内用户推荐从同步镜像网站gitee下载
  51 +git clone --depth 1 https://gitee.com/xia-chu/ZLMediaKit
  52 +cd ZLMediaKit
  53 +# 千万不要忘记执行这句命令
  54 +git submodule update --init
  55 +```
  56 +## 5 编译WVP-PRO
  57 +### 5.1 可以通过git克隆,也可以在项目下载点击下载
  58 +![点击下载](_media/img_1.png)
  59 +![点击下载](_media/img_2.png)
  60 +从gitee克隆
  61 +```bash
  62 +git clone https://gitee.com/pan648540858/wvp-GB28181-pro.git
  63 +```
  64 +从github克隆
  65 +```bash
  66 +git clone https://github.com/648540858/wvp-GB28181-pro.git
  67 +```
  68 +
  69 +### 5.2 编译前端页面
  70 +```shell script
  71 +cd wvp-GB28181-pro/web_src/
  72 +npm --registry=https://registry.npm.taobao.org install
  73 +npm run build
  74 +```
  75 +编译如果报错, 一般都是网络问题, 导致的依赖包下载失败
  76 +编译完成后在src/main/resources下出现static目录
  77 +**编译完成一般是这个样子,中间没有报红的错误信息**
  78 +![编译成功](_media/img.png)
  79 +
  80 +### 5.3 打包项目, 生成可执行jar
  81 +```bash
  82 +cd wvp-GB28181-pro
  83 +mvn package
  84 +```
  85 +编译如果报错, 一般都是网络问题, 导致的依赖包下载失败
  86 +编译完成后在target目录下出现wvp-pro-***.jar。
  87 +接下来[配置服务](./_content/introduction/config.md)
  88 +
  89 +
  90 +
  91 +
  92 +
  93 +
  94 +
  95 +
doc/_content/introduction/config.md 0 → 100644
  1 +<!-- 配置 -->
  2 +# 配置
  3 +对于首次测试或者新手同学,我建议在局域网测试,并且关闭服务器与客户机的防火墙测试。建议部署在linux进行测试。
  4 +
  5 +```plantuml
  6 +@startuml
  7 +"WVP-PRO" -> "ZLMediaKit": RESTful 接口
  8 +"WVP-PRO" <-- "ZLMediaKit": Web Hook 接口
  9 +@enduml
  10 +```
  11 +WVP-PRO通过调用ZLMediaKit的RESTful接口实现对ZLMediaKit行为的控制; ZLMediaKit通过Web Hook 接口把消息通知WVP-PRO。通过这种方式,实现了两者的互通。
  12 +对于最简单的配置,你不需要修改ZLMediaKit的任何默认配置。你只需要在WVP-PRO中配置的ZLMediaKit信息即可
  13 +## 1 WVP配置文件位置
  14 +基于spring boot的开发方式,配置文件的加载是很灵活的。默认在src/main/resources/application.yml,部分配置项是可选,你不需要全部配置在配置文件中,
  15 +完全的配置说明可以参看all-application.yml。
  16 +### 1.1 默认加载配置文件方式
  17 +使用maven打包后的jar包里,已经存在了配置文件,但是每次打开jar包修改配置文件或者修改后再打包都是比较麻烦的,所以大家可通过指定配置文件路径来加载指定位置的配置文件。
  18 +```shell
  19 +cd wvp-GB28181-pro/target
  20 +java -jar wvp-pro-*.jar --spring.config.location=../src/main/resources/application.yml
  21 +```
  22 +### 1.2 迁移配置文件以方便启动
  23 +由于配置文件的命令比较长,所以为了启动方便通常我会把配置文件放到jar包的同级目录,类似这样,
  24 +移除jar包内/BOOT-INF/classes/下所有以application开头的文件,使用解压缩工具打开jar即可,不需要解压出来。
  25 +```shell
  26 +cd wvp-GB28181-pro/target
  27 +mv ../src/main/resources/application-dev.yml application.yml
  28 +java -jar wvp-pro-*.jar
  29 +```
  30 +这也是我自己最常用的方式。
  31 +## 2 配置WVP-PRO
  32 +### 2.1 Mysql数据库配置
  33 +首先你需要创建一个名为wvp(也可使用其他名字)的数据库,并使用sql/mysql.sql导入数据库,初始化数据库结构。
  34 +在application-dev.yml中配置(使用1.2方式的是在jar包的同级目录的application.yml)配置数据库连接,包括数据库连接信息,密码。
  35 +### 2.2 Redis数据库配置
  36 +配置wvp中的redis连接信息,建议wvp自己单独使用一个db。
  37 +### 2.3 配置服务启动端口(可直接使用默认配置)
  38 +```yaml
  39 +# [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口
  40 +server:
  41 + port: 18080
  42 +```
  43 +### 2.4 配置28181相关信息(可直接使用默认配置)
  44 +```yaml
  45 +# 作为28181服务器的配置
  46 +sip:
  47 + # [必须修改] 本机的IP
  48 + ip: 192.168.1.3
  49 + # [可选] 28181服务监听的端口
  50 + port: 5060
  51 + # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
  52 + # 后两位为行业编码,定义参照附录D.3
  53 + # 3701020049标识山东济南历下区 信息行业接入
  54 + # [可选]
  55 + domain: 3402000000
  56 + # [可选]
  57 + id: 34020000002000000001
  58 + # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验
  59 + password: 12345678
  60 +```
  61 +### 2.5 配置ZLMediaKit连接信息
  62 +```yaml
  63 +#zlm 默认服务器配置
  64 +media:
  65 + # ZLMediaKit的服务ID,必须配置
  66 + id: FQ3TF8yT83wh5Wvz
  67 + # [必须修改] zlm服务器的内网IP,sdp-ip与stream-ip使用默认值的情况下,这里不要使用127.0.0.1/0.0.0.0
  68 + ip: 192.168.1.3
  69 + # [必须修改] zlm服务器的http.port
  70 + http-port: 6080
  71 + # [可选] zlm服务器的hook.admin_params=secret
  72 + secret: 035c73f7-bb6b-4889-a715-d9eb2d1925cc
  73 + # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
  74 + rtp:
  75 + # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
  76 + enable: true
  77 + # [可选] 在此范围内选择端口用于媒体流传输,
  78 + port-range: 30000,30500 # 端口范围
  79 + # [可选] 国标级联在此范围内选择端口发送媒体流,
  80 + send-port-range: 30000,30500 # 端口范围
  81 + # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
  82 + record-assist-port: 18081
  83 +```
  84 +### 2.4 个性化定制信息配置
  85 +```yaml
  86 +# [根据业务需求配置]
  87 +user-settings:
  88 + # [可选] 服务ID,不写则为000000
  89 + server-id:
  90 + # [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
  91 + auto-apply-play: false
  92 + # [可选] 部分设备需要扩展SDP,需要打开此设置
  93 + senior-sdp: false
  94 + # 保存移动位置历史轨迹:true:保留历史数据,false:仅保留最后的位置(默认)
  95 + save-position-history: false
  96 + # 点播等待超时时间,单位:毫秒
  97 + play-timeout: 3000
  98 + # 等待音视频编码信息再返回, true: 可以根据编码选择合适的播放器,false: 可以更快点播
  99 + wait-track: false
  100 + # 是否开启接口鉴权
  101 + interface-authentication: true
  102 + # 自动配置redis 可以过期事件
  103 + redis-config: true
  104 + # 接口鉴权例外的接口, 即不进行接口鉴权的接口,尽量详细书写,尽量不用/**,至少两级目录
  105 + interface-authentication-excludes:
  106 + - /api/v1/**
  107 + # 推流直播是否录制
  108 + record-push-live: true
  109 + # 国标是否录制
  110 + record-sip: true
  111 + # 是否将日志存储进数据库
  112 + logInDatebase: true
  113 + # 第三方匹配,用于从stream钟获取有效信息
  114 + thirdPartyGBIdReg: [\s\S]*
  115 +```
  116 +
  117 +
  118 +如果配置信息无误,你可以启动zlm,再启动wvp来测试了,启动成功的话,你可以在wvp的日志下看到zlm已连接的提示。
  119 +接下来[部署到服务器](./_content/introduction/deployment.md), 如何你只是本地运行直接再本地运行即可。
0 \ No newline at end of file 120 \ No newline at end of file
doc/_content/introduction/deployment.md 0 → 100644
  1 +<!-- 部署 -->
  2 +
  3 +# 部署
  4 +**请仔细阅读以下内容**
  5 +1. WVP-PRO与ZLM支持分开部署,但是wvp-pro-assist必须与zlm部署在同一台主机;
  6 +2. 需要开放的端口
  7 +| 服务 | 端口 | 类型 | 必选 |
  8 +|-----|:-------------------------|-------------|-------|
  9 +| wvp | server.port | tcp | 是 |
  10 +| wvp | sip.port | udp and tcp | 是 |
  11 +| zlm | http.port | tcp | 是 |
  12 +| zlm | http.sslport | tcp | 否 |
  13 +| zlm | rtmp.port | tcp | 否 |
  14 +| zlm | rtmp.sslport | tcp | 否 |
  15 +| zlm | rtsp.port | udp and tcp | 否 |
  16 +| zlm | rtsp.sslport | udp and tcp | 否 |
  17 +| zlm | rtp_proxy.port | udp and tcp | 单端口开放 |
  18 +| zlm | rtp.port-range(在wvp中配置) | udp and tcp | 多端口开放 |
  19 +
  20 +3. 测试环境部署建议所有服务部署在一台主机,关闭防火墙,减少因网络出现问题的可能;
  21 +4. WVP-PRO与ZLM支持分开部署,但是wvp-pro-assist必须与zlm部署在同一台主机;
  22 +5. 生产环境按需开放端口,但是建议修改默认端口,尤其是5060端口,易受到攻击;
  23 +6. zlm使用docker部署的情况,要求端口映射一致,比如映射5060,应将外部端口也映射为5060端口;
  24 +7. 启动服务,以linux为例
  25 +**启动WVP-PRO**
  26 +```shell
  27 +nohup java -jar java -jar wvp-pro-*.jar &
  28 +```
  29 +
  30 +**启动ZLM**
  31 +```shell
  32 +nohup ./MediaServer -d -m 3 &
  33 +```
  34 +
  35 +[接入设备](./_content/ability/device.md)
  36 +
doc/_content/qa/_media/img.png 0 → 100644

139 KB

doc/_content/qa/_media/img_1.png 0 → 100644

117 KB

doc/_content/qa/_media/img_2.png 0 → 100644

72.3 KB

doc/_content/qa/_media/img_3.png 0 → 100644

90.2 KB

doc/_content/qa/_media/img_4.png 0 → 100644

48 KB

doc/_content/qa/_media/img_5.png 0 → 100644

149 KB

doc/_content/qa/bug.md 0 → 100644
  1 +<!-- 反馈bug -->
  2 +# 反馈bug
  3 +代码是在不断的完善的,不断修改会修复旧的问题也有可能引入新的问题,所以遇到BUG是很正常的一件事。所以遇到问题不要烦燥,咱们就事论事就好了。
  4 +## 如何反馈
  5 +1. 更新代码,很可能你遇到问题别人已经更早的遇到了,或者是作者自己发现了,已经解决了,所以你可以更新代码再次进行测试;
  6 +2. 可以在github提ISSUE,我几乎每天都会去看issue,你的问题我会尽快给予答复;
  7 +3. 你可以来我的QQ群里,询问群友看看是否遇到了同样的问题;
  8 +4. 你可以私聊我的QQ,如果我有时间我会给你答复,但是除非你有明确的复现步骤或者修复方案,否则你可能等不到我的答复。
  9 +
  10 +## 如何快速解决BUG
  11 +目前解决BUG有三种方式:
  12 +1. 作者验证以及修复;
  13 +2. 热心开发者提来的PR;
  14 +3. 使用运维手段屏蔽BUG的影响。
  15 +
  16 +- 对于第一种:详细的复现步骤,完整的抓包文件,有条理的错误分析都可以帮助作者复现问题,进而解决问题。解决问题往往不是最难的,复现才是。
  17 +- 对于第二种:如果你是开发者,你已经发现了造成BUG的原因以及知道如何正确的修复,那么我很希望你PR,SRS的大佬经常说的,开源不是一个人的事。所以你的参与就是最大的鼓励。
  18 +- 对于第三种:如果你有一个有经验的运维伙伴,那么部分问题是可以通过运维的手段暂时屏蔽的,在等待修复的这段时间了以保证项目的运行。
  19 +
doc/_content/qa/development.md 0 → 100644
  1 +<!-- 参与开发 -->
  2 +# 参与到开发中来
  3 +非常欢迎有兴趣的小伙伴一起来维护这个项目
  4 +## 与开发有关的信息
  5 +- 开发语言:后端java + 前端vue;
  6 +- jdk版本: 1.8;
  7 +- 作者自用开发ide: jetbrains intellij idea;
  8 +- nodejs/npm版本:v10.19.0/6.14.4;
  9 +- 后端使用Spring boot框架开发;
  10 +- 项目大量使用了异步操作;
  11 +- 跟代码学流程需要参考28181文档,只看代码你会很懵的;
  12 +- 必须学会[抓包](_content/skill/tcpdump.md),这是必须的
  13 +
  14 +## 提交代码
  15 +大家可以通过fork项目的方式提交自己的代码,然后提交PR,我来合并到主线。提交代码的过程中我们需要遵循“**阿里编码规约**”,现有代码也有很多代码没有做到,但是我们在朝这个方向努力。
0 \ No newline at end of file 16 \ No newline at end of file
doc/_content/qa/img.png 0 → 100644

139 KB

doc/_content/qa/play_error.md 0 → 100644
  1 +<!-- 点播错误 -->
  2 +# 点播错误
  3 +排查点播错误你首先要清除[点播的基本流程](_content/theory/play.md),一般的流程如下:
  4 +```plantuml
  5 +@startuml
  6 +"WEB用户" -> "WVP-PRO": 1. 发起点播请求
  7 +"设备" <- "WVP-PRO": 2. Invite(携带SDP消息体)
  8 +"设备" --> "WVP-PRO": 3. 200OK(携带SDP消息体)
  9 +"设备" <-- "WVP-PRO": 4. Ack
  10 +"设备" -> "ZLMediaKit": 5. 发送实时流
  11 +"WVP-PRO" <- "ZLMediaKit": 6. 流改变事件
  12 +"WEB用户" <-- "WVP-PRO": 7. 回复流播放地址(携带流地址)
  13 +"WVP-PRO" <- "ZLMediaKit": 8. 无人观看事件
  14 +"设备" <- "WVP-PRO": 9 Bye消息
  15 +"设备" --> "WVP-PRO": 10 200OK
  16 +@enduml
  17 +```
  18 +针对几种常见的错误,我们来分析一下,也方便大家对号入座解决常见的问题
  19 +## 点播收到错误码
  20 +这个错误一般表现为点击"播放"按钮后很快得到一个错误。
  21 +1. **400错误码**
  22 +出现400错误玛时一般是这样的流程是这样的
  23 +```plantuml
  24 +@startuml
  25 +"WEB用户" -> "WVP-PRO": 1. 发起点播请求
  26 +"设备" <- "WVP-PRO": 2. Invite(携带SDP消息体)
  27 +"设备" --> "WVP-PRO": 3. 400错误
  28 +@enduml
  29 +```
  30 +此时通常是设备认为WVP发送了错误的消息给它,它认为消息不全或者错误所以直接返回400错误,此时我们需要[抓包](_content/skill/tcpdump.md)来分析是否缺失了内容,也可以直接联系对方询问为什么返回了400。
  31 +WVP不能保证兼容所有的设备,有些实现不规范的设备可能在对接时就会出现上述问题,你可以联系作者帮忙对接。
  32 +2. **500错误码**
  33 +500或者大于500小于600的错误码一般多是设备内部出了问题,解决方式有两个,第一种直接联系设备/平台客服寻求解决;第二种,如果你有确定可以对接这个设备的平台那么可以把对接这个平台的抓包和对接wvp的抓包同时发送给我,我来尝试解决。
  34 +
  35 +
  36 +## 点播超时
  37 +点播超时的情况大致分为两种:点播超时和收流超时
  38 +1. **点播超时**
  39 +点播超时错误一般为信令的超时,比如长时间为收到对方的回复,可能出现在流程中 “3. 200OK(携带SDP消息体)”这个位置,即我们发送点播消息,但是设备没有回复,可能的原因:
  40 +> 1. 设备内部错误,未能回复消息
  41 +> 2. 网络原因消息未到到达设备
  42 +
  43 +大部分时候是原因2,所以遇到这个错误我们首先要排查我们我的网路,如果你是公网部署,那么也可能时心跳周期太长,导致的路由NAT失效,WVP的消息无法通道原来的IP端口号发送给设备。
  44 +
  45 +2. **收流超时**
  46 +收流超时可能发生在流程中的5和6,可能的原因有:
  47 +> 1. 设备发送了流但是发送到了错误的ip和端口上,而这个信息是在invite消息的sdp中指定的,就是流程2Invite(携带SDP消息体)中,而这个错误很可能来自你的配置错误,比如你设置了127.0.0.1导致设备网127.0.0.1上发流,或者是你WVP在公网,但是你给设备了一个内网ip,导致设备无法把流发送过来;
  48 +> 2. 设备内部错误未发送流;
  49 +> 2. 设备发送了流,但是流无法识别,可能存在于流不规范和网络很差的情况下;
  50 +> 3. 设备发送了流,zlm也收到了,但是zlm无法通过hook通知到wvp,此时原因是你可以检查zlm的配置文件中的hook配置,看看是否无法从zlm连接到wvp;
  51 +> 4. 设备发送了流,但是开启SSRC校验,设备的流不够规范采用错误的ssrc,导致zlm选择丢弃;
  52 +
  53 +针对这些可能的错误原因我建议的排查顺序:
  54 +- 关闭ssrc校验;
  55 +- 查看zlm配置的hook是否可以连接到zlm;
  56 +- 查看zlm日志是否有流注册;
  57 +- 抓包查看流的信息,看看流是否正常发送,甚至可以导出发送原始流,用vlc播放,看看是否可以播放。
doc/_content/qa/regiser_error.md 0 → 100644
  1 +<!-- 设备注册不上来的解决办法 -->
  2 +# 设备注册不上来的解决办法
  3 +一般的原因有两个
  4 +1. 信息填写错误,比如密码错误;
  5 +2. 网络不通导致注册消息无法发送到WVP;
  6 +
  7 +
  8 +遇到问题首先仔细校验填写信息,例如海康可能需要勾选鉴权才可以输入密码。网络问题请自行测试。
0 \ No newline at end of file 9 \ No newline at end of file
doc/_content/qa/start_error.md 0 → 100644
  1 +<!-- 启动时报错 -->
  2 +# 启动时报错
  3 +启动时的报错大部分时候是因为你的配置有问题,比如mysql没连接上,redis没连接上,18080/15060端口占用了,这些都会导致启动是报错,修改配置配置之后都可以解决;
  4 +下面我整理的一些常见的错误,大家可以先对号入座的简单排查下。
  5 +> **常见错误**
  6 +
  7 +![_media/img.png](_media/img.png)
  8 +**错误原因:** redis配置错误,可能原因: redis未启动/ip错误/端口错误/网络不通
  9 +---
  10 +![_media/img_1.png](_media/img_1.png)
  11 +**错误原因:** redis配置错误,可能原因: 密码错误
  12 +---
  13 +![_media/img_2.png](_media/img_2.png)
  14 +**错误原因:** mysql配置错误,可能原因: mysql未启动/ip错误/端口错误/网络不通
  15 +---
  16 +![_media/img_3.png](_media/img_3.png)
  17 +**错误原因:** mysql配置错误,可能原因: 用户名/密码错误
  18 +---
  19 +![_media/img_4.png](_media/img_4.png)
  20 +**错误原因:** SIP配置错误,可能原因: SIP端口被占用
  21 +---
  22 +![_media/img_5.png](_media/img_5.png)
  23 +**错误原因:** WVP Tomcat端口配置错误,可能原因: server.port端口被占用
  24 +---
0 \ No newline at end of file 25 \ No newline at end of file
doc/_content/skill/_media/img.png 0 → 100644

43.8 KB

doc/_content/skill/_media/img_1.png 0 → 100644

105 KB

doc/_content/skill/_media/img_2.png 0 → 100644

15.9 KB

doc/_content/skill/tcpdump.md 0 → 100644
  1 +<!-- 抓包 -->
  2 +# 抓包
  3 +如果说对于网络编程,有什么工具是必会的,我觉得抓包肯定是其中之一了。作为GB/T 28181调试过程中最重要的手段,我觉得如果你真对他有兴趣,或者系统遇到问题可以最快的得到解决,那么抓包你就一定要学会了。
  4 +
  5 +## 抓包工具的选择
  6 +### 1. Wireshark
  7 +在具备图形界面的系统上,比如windows,linux发行版ubuntu,opensuse等,我一般直接使用Wireshark直接进行抓包,也方便进行内容的查看。
  8 +### 2. Tcpdump
  9 +在使用命令行的系统,比如linux服务器,我一般使用Tcpdump进行抓包,无需额外安装,系统一般自带,抓包的到的文件,可以使用Wireshark打开,在图形界面下方便查看内容。
  10 +
  11 +## 工具安装
  12 +Wireshark的安装很简单,根据提示一步步点击就好了,在linux需要解决权限的问题,如果和我一样使用图形界面的linux发行版的话,可以参看如下步骤; windows的小伙伴直接略过即可
  13 +```shell
  14 +# 1. 添加wireshark用户组
  15 +sudo groupadd wireshark
  16 +# 2. 将dumpcap更改为wireshark用户组
  17 +sudo chgrp wireshark /usr/bin/dumpcap
  18 +# 3. 让wireshark用户组有root权限使用dumpcap
  19 +sudo chmod 4755 /usr/bin/dumpcap
  20 +# 4. 将需要使用的用户名加入wireshark用户组
  21 +sudo gpasswd -a $USER wireshark
  22 +```
  23 +tcpdump一般linux都是自带,无需安装,可以这样验证;显示版本信息即是已安装
  24 +```shell
  25 +tcpdump --version
  26 +```
  27 +## 开始抓包
  28 +### 使用Wireshark
  29 +在28181中我一般只关注sip包和rtp包,所以我一般是直接过滤sip和rtp,可以输入框输入 `sip or rtp`这样即可,如果设备来源比较多还可以加上ip和端口号的过滤`(sip or rtp )and ip.addr==192.168.1.3 and udp.port==5060`
  30 +详细的过滤规则可以自行百度,我可以提供一些常用的给大家参考
  31 +![img.png](_media/img.png)
  32 +**只过滤SIP:**
  33 +```shell
  34 +sip
  35 +```
  36 +**只获取rtp数据:**
  37 +```shell
  38 +rtp
  39 +```
  40 +**默认方式:**
  41 +```shell
  42 +sip or rtp
  43 +```
  44 +**过滤IP:**
  45 +```shell
  46 + sip and ip.addr==192.168.1.3
  47 +```
  48 +**过滤端口:**
  49 +```shell
  50 + sip and udp.port==5060
  51 +```
  52 +输入命令开启抓包后,此时可以进行操作,比如点播,录像回访等,操作完成回到Wireshark点击红色的停止即可,需要保存文件可以点击`文件->导出特定分组`导出过滤后的数据,也可以直接`文件->另存为`保存未过滤的数据。
  53 +### 使用tcpdump
  54 +对于服务器抓包,为了得到足够完整的数据,我一般会要求直接抓取网卡数据而不过滤,如下:
  55 +抓取网卡首先需要获取网卡名,在linux我一般使用`ip addr`获取网卡信息,如下所示:
  56 +![img_1.png](_media/img_1.png)
  57 +```shell
  58 +sudo tcpdump -i wlp3s0 -w demo.pcap
  59 +```
  60 +![img_2.png](_media/img_2.png)
  61 +命令行会停留在这个位置,此时可以进行操作,比如点播,录像回放等,操作完成回到命令行使用`Ctrl+C`结束命令行,在当前目录下得到demo.pcap,将这个文件下载到图形界面操作系统里,即可使用Wireshark查看了
  62 +更多的操作可以参考: [https://www.cnblogs.com/jiujuan/p/9017495.html](https://www.cnblogs.com/jiujuan/p/9017495.html)
doc/_content/theory/_media/img.png 0 → 100644

96.4 KB

doc/_content/theory/_media/img_1.png 0 → 100644

105 KB

doc/_content/theory/_media/img_2.png 0 → 100644

16.8 KB

doc/_content/theory/_media/img_3.png 0 → 100644

82.8 KB

doc/_content/theory/_media/img_4.png 0 → 100644

45.6 KB

doc/_content/theory/_media/img_5.png 0 → 100644

59.5 KB

doc/_content/theory/_media/img_6.png 0 → 100644

51.7 KB

doc/_content/theory/_media/img_7.png 0 → 100644

80 KB

doc/_content/theory/_media/img_8.png 0 → 100644

23.7 KB

doc/_content/theory/_media/img_9.png 0 → 100644

28 KB

doc/_content/theory/channel_tree.md 0 → 100644
  1 +<!-- 通道的树形结构 -->
  2 +
  3 +# 通道的树形结构
  4 +
  5 +国标28181规定了两种组织设备树的方式
  6 +1. **行政区划**
  7 + 行政区划模式下主要是以行政区划作为目录节点例如:河北省->邯郸市->广平县
  8 + ![_media/img_8.png](_media/img_8.png)
  9 +2. **业务分组**
  10 + 业务分组主要自定义的目录树的一种组织形式,但是对定义的目录的国标编号有一定的要求。
  11 + 第一级别需要是业务分组类型,即国标编码中的11、12、13是215,例如:65010200002150000001;
  12 + 业务分组下是虚拟组织,即国标编码中的11、12、13是216,例如:65010200002160000002。
  13 + 虚拟组织下不可是业务分组,虚拟组织下可以继续添加虚拟组织。
  14 + ![_media/img_9.png](_media/img_9.png)
doc/_content/theory/code.md 0 → 100644
  1 +<!-- 统一编码规则 -->
  2 +
  3 +# 统一编码规则
  4 +## D.1 编码规则 A
  5 +>&emsp;&emsp;编码规则 A 由中心编码(8位)、行业编码(2位)、类型编码(3位)和序号(7位)四个码段共20位十
  6 +>进制数字字符构成,即系统编码 =中心编码 + 行业编码 + 类型编码 + 序号。
  7 +>&emsp;&emsp;编码规则 A 的详细说明见表 D.1。其中,中心编码指用户或设备所归属的监控中心的编码,按照监控中心所在地的行政区划代码确定,
  8 +> 当不是基层单位时空余位为0。行政区划代码采用 GB/T2260— 2007规定的行政区划代码表示。行业编码是指用户或设备所归属的行业,行业编码对照表见 D.3。
  9 +> 类型编码指定了设备或用户的具体类型,其中的前端设备包含公安系统和非公安系统的前端设备,终端用 户包含公安系统和非公安系统的终端用户。
  10 +![img_7.png](_media/img_7.png)
  11 +![img_1.png](_media/img_1.png)
  12 +![img_2.png](_media/img_2.png)
  13 +
  14 +
  15 +## D.2 编码规则 B
  16 +>&emsp;&emsp;编码规则 B由中心编码(8位)、行业编码(2位)、序号(4位)和类型编码(2位)四个码段构成,即系
  17 +>统编码 =中心编码 + 行业编码 +序号+类型编码。编码规则 B的详细说明见表 D.2。
  18 +![img_3.png](_media/img_3.png)
  19 +![img_4.png](_media/img_4.png)
  20 +
  21 +
  22 +## D.3 行业编码对照表
  23 +>&emsp;&emsp;行业编码对照表见表 D.3。
  24 +![img_5.png](_media/img_5.png)
  25 +![img_6.png](_media/img_6.png)
0 \ No newline at end of file 26 \ No newline at end of file
doc/_content/theory/img.png 0 → 100644

23.7 KB

doc/_content/theory/play.md 0 → 100644
  1 +<!-- 点播流程 -->
  2 +
  3 +# 点播流程
  4 +> 以下为WVP-PRO点播流程。点播成功前的任何一个环节出现问题都可能出现点播超时,这也是排查点播超时的依据。
  5 +
  6 +```plantuml
  7 +@startuml
  8 +"WEB用户" -> "WVP-PRO": 1. 发起点播请求
  9 +"设备" <- "WVP-PRO": 2. Invite(携带SDP消息体)
  10 +"设备" --> "WVP-PRO": 3. 200OK(携带SDP消息体)
  11 +"设备" <-- "WVP-PRO": 4. Ack
  12 +"设备" -> "ZLMediaKit": 5. 发送实时流
  13 +"WVP-PRO" <- "ZLMediaKit": 6. 流改变事件
  14 +"WEB用户" <-- "WVP-PRO": 7. 回复流播放地址(携带流地址)
  15 +"WVP-PRO" <- "ZLMediaKit": 8. 无人观看事件
  16 +"设备" <- "WVP-PRO": 9 Bye消息
  17 +"设备" --> "WVP-PRO": 10 200OK
  18 +@enduml
  19 +```
  20 +
  21 +
  22 +## 注册流程描述如下:
  23 +1. 用户从网页或调用接口发起点播请求;
  24 +2. WVP-PRO向摄像机发送Invite消息,消息头域中携带 Subject字段,表明点播的视频源ID、发送方媒体流序列号、ZLMediaKit接收流使用的IP、端口号、
  25 + 接收端媒体流序列号等参数,SDP消息体中 s字段为“Play”代表实时点播,y字段描述SSRC值,f字段描述媒体参数。
  26 +3. 摄像机向WVP-PRO回复200OK,消息体中描述了媒体流发送者发送媒体流的IP、端口、媒体格式、SSRC字段等内容。
  27 +4. WVP-PRO向设备回复Ack, 会话建立成功。
  28 +5. 设备向ZLMediaKit发送实时流。
  29 +6. ZLMediaKit向WVP-PRO发送流改变事件。
  30 +7. WVP-PRO向WEB用户回复播放地址。
  31 +8. ZLMediaKit向WVP发送流无人观看事件。
  32 +9. WVP-PRO向设备回复Bye, 结束会话。
  33 +10. 设备回复200OK,会话结束成功。
doc/_content/theory/register.md 0 → 100644
  1 +<!-- 注册流程 -->
  2 +
  3 +# 注册流程
  4 +WVP-PRO目前仅支持国标中描述的基本注册流程,也是最常用的,
  5 +> 基本注册即采用IETFRFC3261规定的基于数字摘要的挑战应答式安全技术进行注册.
  6 +
  7 +```plantuml
  8 +@startuml
  9 +"设备" -> "WVP-PRO": 1. Register
  10 +"设备" <-- "WVP-PRO": 2. 401 Unauthorized
  11 +"设备" -> "WVP-PRO": 3. Register
  12 +"设备" <-- "WVP-PRO": 4. 200 OK
  13 +@enduml
  14 +```
  15 +
  16 +
  17 +> 注册流程描述如下:
  18 +> 1. 摄像机向WVP-PRO服务器发送 Register请求;
  19 +> 2. WVP-PRO向摄像机发送响应401,并在响应的消息头 WWW_Authenticate字段中给出适合摄像机的认证体制和参数;
  20 +> 3. 摄像机重新向WVP-PRO发送 Register请求,在请求的 Authorization字段给出信任书, 包含认证信息;
  21 +> 4. WVP-PRO对请求进行验证,如果检查出 摄像机身份合法,向摄像机发送成功响应 200OK,如果身份不合法则发送拒绝服务应答。
doc/_coverpage.md 0 → 100644
  1 +<!-- 封面 -->
  2 +![logo](_media/logo-mini.png)
  3 +
  4 +# WVP-PRO <small>2.0</small>
  5 +
  6 +> 开箱即用的28181协议视频平台。
  7 +
  8 +- 基于GB/T28181-2016标准信令实现,兼容GB/T28181-2011。
  9 +- 自带完整前端页面,开箱即用。
  10 +- 完全开源,且使用MIT许可协议。可以在保留版权信息的基础上商用。
  11 +
  12 +[GitHub](https://github.com/648540858/wvp-GB28181-pro)
  13 +[Gitee](https://gitee.com/pan648540858/wvp-GB28181-pro)
  14 +
  15 +<!-- 背景色 -->
  16 +
  17 +[//]: # ([comment]: <> &#40;![color]&#40;#f0f0f0&#41;&#41;)
doc/_media/favicon.ico 0 → 100644
No preview for this file type
doc/_media/logo-mini.png 0 → 100644

22.4 KB

doc/_media/logo.png 0 → 100644

65.5 KB

doc/_media/weixin.jpg 0 → 100644

87.1 KB

doc/_media/zhifubao.jpg 0 → 100644

421 KB

doc/_navbar.md 0 → 100644
  1 +<!-- 导航栏 -->
doc/_sidebar.md 0 → 100644
  1 +<!-- 侧边栏 -->
  2 +
  3 +* **编译与部署**
  4 + * [编译](_content/introduction/compile.md)
  5 + * [配置](_content/introduction/config.md)
  6 + * [部署](_content/introduction/deployment.md)
  7 +* **功能与使用**
  8 + * [接入设备](_content/ability/device.md)
  9 + * [设备使用](_content/ability/device_use.md)
  10 + * [国标级联](_content/ability/cascade2.md)
  11 + * [推流列表](_content/ability/push.md)
  12 + * [拉流代理](_content/ability/proxy.md)
  13 + * [电子地图](_content/ability/gis.md)
  14 + * [节点管理](_content/ability/node_manger.md)
  15 + * [云端录像](_content/ability/cloud_record.md)
  16 + * [不间断录像](_content/ability/continuous_recording.md)
  17 +* **流程与原理**
  18 + * [统一编码规则](_content/theory/code.md)
  19 + * [树形结构](_content/theory/channel_tree.md)
  20 + * [注册流程](_content/theory/register.md)
  21 + * [点播流程](_content/theory/play.md)
  22 +* **必备技巧**
  23 + * [抓包](_content/skill/tcpdump.md)
  24 +
  25 +* **常见问答**
  26 + - [如何反馈BUG](_content/qa/bug.md)
  27 + - [如何参与开发](_content/qa/development.md)
  28 + - [启动报错的解决办法](_content/qa/start_error.md)
  29 + - [设备注册不上来的解决办法](_content/qa/regiser_error.md)
  30 + - [点播超时/报错的解决办法](_content/qa/play_error.md)
  31 +* [**免责声明**](_content/disclaimers.md)
  32 +* [**捐赠**](_content/donation.md)
  33 +* [**关于本文档**](_content/about_doc.md)
doc/index.html 0 → 100644
  1 +<!DOCTYPE html>
  2 +<html lang="en">
  3 +<head>
  4 + <meta charset="UTF-8">
  5 + <title>WVP-PRO文档</title>
  6 + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  7 + <meta name="description" content="Description">
  8 + <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
  9 + <link rel="icon" href="_media/favicon.ico" type="image/x-icon" />
  10 + <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify@4/lib/themes/vue.css">
  11 +<!-- <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/lib/themes/dark.css">-->
  12 + <style>
  13 + .cover{
  14 + background: linear-gradient(to left bottom, hsl(82, 100%, 85%) 0%,hsl(199, 100%, 85%) 100%) !important;
  15 + }
  16 + </style>
  17 +</head>
  18 +<body>
  19 + <div id="app">加载中</div>
  20 + <script>
  21 + window.$docsify = {
  22 + name: 'WVP-RPO使用文档',
  23 + repo: 'https://github.com/648540858/wvp-GB28181-pro',
  24 + loadSidebar: true, // 开启侧边栏
  25 + loadNavbar: true, // 开启导航栏
  26 + coverpage: true, // 开启封面
  27 +
  28 + subMaxLevel: 3,
  29 + plantuml: {
  30 + skin: 'default',
  31 + },
  32 + search: {
  33 + maxAge: 86400000, // 过期时间,单位毫秒,默认一天
  34 + paths: 'auto', // or 'auto'
  35 + placeholder: '搜索',
  36 + noData: '找不到结果',
  37 + // 搜索标题的最大层级, 1 - 6
  38 + depth: 4,
  39 + hideOtherSidebarContent: false, // 是否隐藏其他侧边栏内容
  40 + },
  41 + copyCode: {
  42 + buttonText : '复制',
  43 + errorText : '错误',
  44 + successText: '已复制'
  45 + },
  46 + // disqus: 'shortname'
  47 + }
  48 + </script>
  49 + <!-- Docsify v4 -->
  50 + <script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
  51 + <script src="//unpkg.com/docsify-plantuml/dist/docsify-plantuml.min.js"></script>
  52 + <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
  53 + <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/zoom-image.min.js"></script>
  54 + <script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
  55 +
  56 + </script>
  57 +<!-- <script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/disqus.min.js"></script>-->
  58 +</body>
  59 +</html>
@@ -61,6 +61,13 @@ @@ -61,6 +61,13 @@
61 <dependency> 61 <dependency>
62 <groupId>org.springframework.boot</groupId> 62 <groupId>org.springframework.boot</groupId>
63 <artifactId>spring-boot-starter-data-redis</artifactId> 63 <artifactId>spring-boot-starter-data-redis</artifactId>
  64 + <exclusions>
  65 + <!-- 去掉 Lettuce 的依赖, Spring Boot 优先使用 Lettuce 作为 Redis 客户端 -->
  66 + <exclusion>
  67 + <groupId>io.lettuce</groupId>
  68 + <artifactId>lettuce-core</artifactId>
  69 + </exclusion>
  70 + </exclusions>
64 </dependency> 71 </dependency>
65 <dependency> 72 <dependency>
66 <groupId>org.springframework.boot</groupId> 73 <groupId>org.springframework.boot</groupId>
@@ -75,6 +82,12 @@ @@ -75,6 +82,12 @@
75 <groupId>org.mybatis.spring.boot</groupId> 82 <groupId>org.mybatis.spring.boot</groupId>
76 <artifactId>mybatis-spring-boot-starter</artifactId> 83 <artifactId>mybatis-spring-boot-starter</artifactId>
77 <version>2.1.4</version> 84 <version>2.1.4</version>
  85 + <exclusions>
  86 + <exclusion>
  87 + <groupId>com.zaxxer</groupId>
  88 + <artifactId>HikariCP</artifactId>
  89 + </exclusion>
  90 + </exclusions>
78 </dependency> 91 </dependency>
79 <dependency> 92 <dependency>
80 <groupId>org.springframework.boot</groupId> 93 <groupId>org.springframework.boot</groupId>
@@ -84,7 +97,6 @@ @@ -84,7 +97,6 @@
84 <dependency> 97 <dependency>
85 <groupId>redis.clients</groupId> 98 <groupId>redis.clients</groupId>
86 <artifactId>jedis</artifactId> 99 <artifactId>jedis</artifactId>
87 - <version>${jedis-version}</version>  
88 </dependency> 100 </dependency>
89 101
90 <!-- druid数据库连接池 --> 102 <!-- druid数据库连接池 -->
@@ -265,14 +277,14 @@ @@ -265,14 +277,14 @@
265 </configuration> 277 </configuration>
266 </plugin> 278 </plugin>
267 279
268 - <plugin> 280 + <!-- <plugin>
269 <groupId>pl.project13.maven</groupId> 281 <groupId>pl.project13.maven</groupId>
270 <artifactId>git-commit-id-plugin</artifactId> 282 <artifactId>git-commit-id-plugin</artifactId>
271 <version>3.0.1</version> 283 <version>3.0.1</version>
272 <configuration> 284 <configuration>
273 <offline>true</offline> 285 <offline>true</offline>
274 </configuration> 286 </configuration>
275 - </plugin> 287 + </plugin>-->
276 288
277 <plugin> 289 <plugin>
278 <groupId>org.apache.maven.plugins</groupId> 290 <groupId>org.apache.maven.plugins</groupId>
sql/mysql.sql
@@ -2,55 +2,60 @@ @@ -2,55 +2,60 @@
2 -- 2 --
3 -- Host: 127.0.0.1 Database: wvp2 3 -- Host: 127.0.0.1 Database: wvp2
4 -- ------------------------------------------------------ 4 -- ------------------------------------------------------
5 --- Server version 8.0.29-0ubuntu0.22.04.2 5 +-- Server version 8.0.29-0ubuntu0.22.04.3
6 6
7 -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;  
8 -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;  
9 -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 7 +/*!40101 SET @OLD_CHARACTER_SET_CLIENT = @@CHARACTER_SET_CLIENT */;
  8 +/*!40101 SET @OLD_CHARACTER_SET_RESULTS = @@CHARACTER_SET_RESULTS */;
  9 +/*!40101 SET @OLD_COLLATION_CONNECTION = @@COLLATION_CONNECTION */;
10 /*!50503 SET NAMES utf8mb4 */; 10 /*!50503 SET NAMES utf8mb4 */;
11 -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;  
12 -/*!40103 SET TIME_ZONE='+00:00' */;  
13 -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;  
14 -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;  
15 -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;  
16 -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 11 +/*!40103 SET @OLD_TIME_ZONE = @@TIME_ZONE */;
  12 +/*!40103 SET TIME_ZONE = ' + 00:00' */;
  13 +/*!40014 SET @OLD_UNIQUE_CHECKS = @@UNIQUE_CHECKS, UNIQUE_CHECKS = 0 */;
  14 +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS = @@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS = 0 */;
  15 +/*!40101 SET @OLD_SQL_MODE = @@SQL_MODE, SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO' */;
  16 +/*!40111 SET @OLD_SQL_NOTES = @@SQL_NOTES, SQL_NOTES = 0 */;
17 17
18 -- 18 --
19 -- Table structure for table `device` 19 -- Table structure for table `device`
20 -- 20 --
21 21
22 DROP TABLE IF EXISTS `device`; 22 DROP TABLE IF EXISTS `device`;
23 -/*!40101 SET @saved_cs_client = @@character_set_client */; 23 +/*!40101 SET @saved_cs_client = @@character_set_client */;
24 /*!50503 SET character_set_client = utf8mb4 */; 24 /*!50503 SET character_set_client = utf8mb4 */;
25 -CREATE TABLE `device` (  
26 - `id` int NOT NULL AUTO_INCREMENT,  
27 - `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
28 - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
29 - `manufacturer` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
30 - `model` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
31 - `firmware` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
32 - `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
33 - `streamMode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
34 - `online` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
35 - `registerTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
36 - `keepaliveTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
37 - `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
38 - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
39 - `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
40 - `port` int NOT NULL,  
41 - `expires` int NOT NULL,  
42 - `subscribeCycleForCatalog` int NOT NULL,  
43 - `hostAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
44 - `charset` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
45 - `subscribeCycleForMobilePosition` int DEFAULT NULL,  
46 - `mobilePositionSubmissionInterval` int DEFAULT '5',  
47 - `subscribeCycleForAlarm` int DEFAULT NULL,  
48 - `ssrcCheck` int DEFAULT '0',  
49 - `geoCoordSys` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,  
50 - `treeType` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,  
51 - PRIMARY KEY (`id`) USING BTREE,  
52 - UNIQUE KEY `device_deviceId_uindex` (`deviceId`) USING BTREE  
53 -) ENGINE=InnoDB AUTO_INCREMENT=42 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 25 +CREATE TABLE `device`
  26 +(
  27 + `id` int NOT NULL AUTO_INCREMENT,
  28 + `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  29 + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  30 + `manufacturer` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  31 + `model` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  32 + `firmware` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  33 + `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  34 + `streamMode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  35 + `online` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  36 + `registerTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  37 + `keepaliveTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  38 + `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  39 + `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  40 + `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  41 + `port` int NOT NULL,
  42 + `expires` int NOT NULL,
  43 + `subscribeCycleForCatalog` int NOT NULL,
  44 + `hostAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  45 + `charset` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  46 + `subscribeCycleForMobilePosition` int DEFAULT NULL,
  47 + `mobilePositionSubmissionInterval` int DEFAULT '5 ',
  48 + `subscribeCycleForAlarm` int DEFAULT NULL,
  49 + `ssrcCheck` int DEFAULT '0 ',
  50 + `geoCoordSys` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  51 + `treeType` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  52 + PRIMARY KEY (`id`) USING BTREE,
  53 + UNIQUE KEY `device_deviceId_uindex` (`deviceId`) USING BTREE
  54 +) ENGINE = InnoDB
  55 + AUTO_INCREMENT = 53
  56 + DEFAULT CHARSET = utf8mb4
  57 + COLLATE = utf8mb4_general_ci
  58 + ROW_FORMAT = DYNAMIC;
54 /*!40101 SET character_set_client = @saved_cs_client */; 59 /*!40101 SET character_set_client = @saved_cs_client */;
55 60
56 -- 61 --
@@ -58,8 +63,10 @@ CREATE TABLE `device` ( @@ -58,8 +63,10 @@ CREATE TABLE `device` (
58 -- 63 --
59 64
60 LOCK TABLES `device` WRITE; 65 LOCK TABLES `device` WRITE;
61 -/*!40000 ALTER TABLE `device` DISABLE KEYS */;  
62 -/*!40000 ALTER TABLE `device` ENABLE KEYS */; 66 +/*!40000 ALTER TABLE `device`
  67 + DISABLE KEYS */;
  68 +/*!40000 ALTER TABLE `device`
  69 + ENABLE KEYS */;
63 UNLOCK TABLES; 70 UNLOCK TABLES;
64 71
65 -- 72 --
@@ -67,22 +74,26 @@ UNLOCK TABLES; @@ -67,22 +74,26 @@ UNLOCK TABLES;
67 -- 74 --
68 75
69 DROP TABLE IF EXISTS `device_alarm`; 76 DROP TABLE IF EXISTS `device_alarm`;
70 -/*!40101 SET @saved_cs_client = @@character_set_client */; 77 +/*!40101 SET @saved_cs_client = @@character_set_client */;
71 /*!50503 SET character_set_client = utf8mb4 */; 78 /*!50503 SET character_set_client = utf8mb4 */;
72 -CREATE TABLE `device_alarm` (  
73 - `id` int NOT NULL AUTO_INCREMENT,  
74 - `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
75 - `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
76 - `alarmPriority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
77 - `alarmMethod` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
78 - `alarmTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
79 - `alarmDescription` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
80 - `longitude` double DEFAULT NULL,  
81 - `latitude` double DEFAULT NULL,  
82 - `alarmType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
83 - `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,  
84 - PRIMARY KEY (`id`) USING BTREE  
85 -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 79 +CREATE TABLE `device_alarm`
  80 +(
  81 + `id` int NOT NULL AUTO_INCREMENT,
  82 + `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  83 + `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  84 + `alarmPriority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  85 + `alarmMethod` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  86 + `alarmTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  87 + `alarmDescription` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  88 + `longitude` double DEFAULT NULL,
  89 + `latitude` double DEFAULT NULL,
  90 + `alarmType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  91 + `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  92 + PRIMARY KEY (`id`) USING BTREE
  93 +) ENGINE = InnoDB
  94 + DEFAULT CHARSET = utf8mb4
  95 + COLLATE = utf8mb4_general_ci
  96 + ROW_FORMAT = DYNAMIC;
86 /*!40101 SET character_set_client = @saved_cs_client */; 97 /*!40101 SET character_set_client = @saved_cs_client */;
87 98
88 -- 99 --
@@ -90,8 +101,10 @@ CREATE TABLE `device_alarm` ( @@ -90,8 +101,10 @@ CREATE TABLE `device_alarm` (
90 -- 101 --
91 102
92 LOCK TABLES `device_alarm` WRITE; 103 LOCK TABLES `device_alarm` WRITE;
93 -/*!40000 ALTER TABLE `device_alarm` DISABLE KEYS */;  
94 -/*!40000 ALTER TABLE `device_alarm` ENABLE KEYS */; 104 +/*!40000 ALTER TABLE `device_alarm`
  105 + DISABLE KEYS */;
  106 +/*!40000 ALTER TABLE `device_alarm`
  107 + ENABLE KEYS */;
95 UNLOCK TABLES; 108 UNLOCK TABLES;
96 109
97 -- 110 --
@@ -99,50 +112,55 @@ UNLOCK TABLES; @@ -99,50 +112,55 @@ UNLOCK TABLES;
99 -- 112 --
100 113
101 DROP TABLE IF EXISTS `device_channel`; 114 DROP TABLE IF EXISTS `device_channel`;
102 -/*!40101 SET @saved_cs_client = @@character_set_client */; 115 +/*!40101 SET @saved_cs_client = @@character_set_client */;
103 /*!50503 SET character_set_client = utf8mb4 */; 116 /*!50503 SET character_set_client = utf8mb4 */;
104 -CREATE TABLE `device_channel` (  
105 - `id` int NOT NULL AUTO_INCREMENT,  
106 - `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
107 - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
108 - `manufacture` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
109 - `model` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
110 - `owner` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
111 - `civilCode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
112 - `block` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
113 - `address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
114 - `parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
115 - `safetyWay` int DEFAULT NULL,  
116 - `registerWay` int DEFAULT NULL,  
117 - `certNum` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
118 - `certifiable` int DEFAULT NULL,  
119 - `errCode` int DEFAULT NULL,  
120 - `endTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
121 - `secrecy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
122 - `ipAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
123 - `port` int DEFAULT NULL,  
124 - `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
125 - `PTZType` int DEFAULT NULL,  
126 - `status` int DEFAULT NULL,  
127 - `longitude` double DEFAULT NULL,  
128 - `latitude` double DEFAULT NULL,  
129 - `streamId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
130 - `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
131 - `parental` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
132 - `hasAudio` bit(1) DEFAULT NULL,  
133 - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
134 - `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
135 - `subCount` int DEFAULT '0',  
136 - `longitudeGcj02` double DEFAULT NULL,  
137 - `latitudeGcj02` double DEFAULT NULL,  
138 - `longitudeWgs84` double DEFAULT NULL,  
139 - `latitudeWgs84` double DEFAULT NULL,  
140 - `businessGroupId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
141 - `gpsTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,  
142 - PRIMARY KEY (`id`) USING BTREE,  
143 - UNIQUE KEY `device_channel_id_uindex` (`id`) USING BTREE,  
144 - UNIQUE KEY `device_channel_pk` (`channelId`,`deviceId`) USING BTREE  
145 -) ENGINE=InnoDB AUTO_INCREMENT=19331 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 117 +CREATE TABLE `device_channel`
  118 +(
  119 + `id` int NOT NULL AUTO_INCREMENT,
  120 + `channelId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  121 + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  122 + `manufacture` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  123 + `model` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  124 + `owner` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  125 + `civilCode` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  126 + `block` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  127 + `address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  128 + `parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  129 + `safetyWay` int DEFAULT NULL,
  130 + `registerWay` int DEFAULT NULL,
  131 + `certNum` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  132 + `certifiable` int DEFAULT NULL,
  133 + `errCode` int DEFAULT NULL,
  134 + `endTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  135 + `secrecy` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  136 + `ipAddress` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  137 + `port` int DEFAULT NULL,
  138 + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  139 + `PTZType` int DEFAULT NULL,
  140 + `status` int DEFAULT NULL,
  141 + `longitude` double DEFAULT NULL,
  142 + `latitude` double DEFAULT NULL,
  143 + `streamId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  144 + `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  145 + `parental` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  146 + `hasAudio` bit(1) DEFAULT NULL,
  147 + `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  148 + `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  149 + `subCount` int DEFAULT '0 ',
  150 + `longitudeGcj02` double DEFAULT NULL,
  151 + `latitudeGcj02` double DEFAULT NULL,
  152 + `longitudeWgs84` double DEFAULT NULL,
  153 + `latitudeWgs84` double DEFAULT NULL,
  154 + `businessGroupId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  155 + `gpsTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  156 + PRIMARY KEY (`id`) USING BTREE,
  157 + UNIQUE KEY `device_channel_id_uindex` (`id`) USING BTREE,
  158 + UNIQUE KEY `device_channel_pk` (`channelId`, `deviceId`) USING BTREE
  159 +) ENGINE = InnoDB
  160 + AUTO_INCREMENT = 19496
  161 + DEFAULT CHARSET = utf8mb4
  162 + COLLATE = utf8mb4_general_ci
  163 + ROW_FORMAT = DYNAMIC;
146 /*!40101 SET character_set_client = @saved_cs_client */; 164 /*!40101 SET character_set_client = @saved_cs_client */;
147 165
148 -- 166 --
@@ -150,8 +168,10 @@ CREATE TABLE `device_channel` ( @@ -150,8 +168,10 @@ CREATE TABLE `device_channel` (
150 -- 168 --
151 169
152 LOCK TABLES `device_channel` WRITE; 170 LOCK TABLES `device_channel` WRITE;
153 -/*!40000 ALTER TABLE `device_channel` DISABLE KEYS */;  
154 -/*!40000 ALTER TABLE `device_channel` ENABLE KEYS */; 171 +/*!40000 ALTER TABLE `device_channel`
  172 + DISABLE KEYS */;
  173 +/*!40000 ALTER TABLE `device_channel`
  174 + ENABLE KEYS */;
155 UNLOCK TABLES; 175 UNLOCK TABLES;
156 176
157 -- 177 --
@@ -159,27 +179,32 @@ UNLOCK TABLES; @@ -159,27 +179,32 @@ UNLOCK TABLES;
159 -- 179 --
160 180
161 DROP TABLE IF EXISTS `device_mobile_position`; 181 DROP TABLE IF EXISTS `device_mobile_position`;
162 -/*!40101 SET @saved_cs_client = @@character_set_client */; 182 +/*!40101 SET @saved_cs_client = @@character_set_client */;
163 /*!50503 SET character_set_client = utf8mb4 */; 183 /*!50503 SET character_set_client = utf8mb4 */;
164 -CREATE TABLE `device_mobile_position` (  
165 - `id` int NOT NULL AUTO_INCREMENT,  
166 - `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
167 - `channelId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,  
168 - `deviceName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
169 - `time` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
170 - `longitude` double NOT NULL,  
171 - `latitude` double NOT NULL,  
172 - `altitude` double DEFAULT NULL,  
173 - `speed` double DEFAULT NULL,  
174 - `direction` double DEFAULT NULL,  
175 - `reportSource` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
176 - `longitudeGcj02` double DEFAULT NULL,  
177 - `latitudeGcj02` double DEFAULT NULL,  
178 - `longitudeWgs84` double DEFAULT NULL,  
179 - `latitudeWgs84` double DEFAULT NULL,  
180 - `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,  
181 - PRIMARY KEY (`id`) USING BTREE  
182 -) ENGINE=InnoDB AUTO_INCREMENT=6751 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 184 +CREATE TABLE `device_mobile_position`
  185 +(
  186 + `id` int NOT NULL AUTO_INCREMENT,
  187 + `deviceId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  188 + `channelId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  189 + `deviceName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  190 + `time` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  191 + `longitude` double NOT NULL,
  192 + `latitude` double NOT NULL,
  193 + `altitude` double DEFAULT NULL,
  194 + `speed` double DEFAULT NULL,
  195 + `direction` double DEFAULT NULL,
  196 + `reportSource` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  197 + `longitudeGcj02` double DEFAULT NULL,
  198 + `latitudeGcj02` double DEFAULT NULL,
  199 + `longitudeWgs84` double DEFAULT NULL,
  200 + `latitudeWgs84` double DEFAULT NULL,
  201 + `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  202 + PRIMARY KEY (`id`) USING BTREE
  203 +) ENGINE = InnoDB
  204 + AUTO_INCREMENT = 6956
  205 + DEFAULT CHARSET = utf8mb4
  206 + COLLATE = utf8mb4_general_ci
  207 + ROW_FORMAT = DYNAMIC;
183 /*!40101 SET character_set_client = @saved_cs_client */; 208 /*!40101 SET character_set_client = @saved_cs_client */;
184 209
185 -- 210 --
@@ -187,8 +212,10 @@ CREATE TABLE `device_mobile_position` ( @@ -187,8 +212,10 @@ CREATE TABLE `device_mobile_position` (
187 -- 212 --
188 213
189 LOCK TABLES `device_mobile_position` WRITE; 214 LOCK TABLES `device_mobile_position` WRITE;
190 -/*!40000 ALTER TABLE `device_mobile_position` DISABLE KEYS */;  
191 -/*!40000 ALTER TABLE `device_mobile_position` ENABLE KEYS */; 215 +/*!40000 ALTER TABLE `device_mobile_position`
  216 + DISABLE KEYS */;
  217 +/*!40000 ALTER TABLE `device_mobile_position`
  218 + ENABLE KEYS */;
192 UNLOCK TABLES; 219 UNLOCK TABLES;
193 220
194 -- 221 --
@@ -196,24 +223,29 @@ UNLOCK TABLES; @@ -196,24 +223,29 @@ UNLOCK TABLES;
196 -- 223 --
197 224
198 DROP TABLE IF EXISTS `gb_stream`; 225 DROP TABLE IF EXISTS `gb_stream`;
199 -/*!40101 SET @saved_cs_client = @@character_set_client */; 226 +/*!40101 SET @saved_cs_client = @@character_set_client */;
200 /*!50503 SET character_set_client = utf8mb4 */; 227 /*!50503 SET character_set_client = utf8mb4 */;
201 -CREATE TABLE `gb_stream` (  
202 - `gbStreamId` int NOT NULL AUTO_INCREMENT,  
203 - `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
204 - `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
205 - `gbId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
206 - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
207 - `longitude` double DEFAULT NULL,  
208 - `latitude` double DEFAULT NULL,  
209 - `streamType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
210 - `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
211 - `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,  
212 - `gpsTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,  
213 - PRIMARY KEY (`gbStreamId`) USING BTREE,  
214 - UNIQUE KEY `app` (`app`,`stream`) USING BTREE,  
215 - UNIQUE KEY `gbId` (`gbId`) USING BTREE  
216 -) ENGINE=InnoDB AUTO_INCREMENT=301681 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 228 +CREATE TABLE `gb_stream`
  229 +(
  230 + `gbStreamId` int NOT NULL AUTO_INCREMENT,
  231 + `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  232 + `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  233 + `gbId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  234 + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  235 + `longitude` double DEFAULT NULL,
  236 + `latitude` double DEFAULT NULL,
  237 + `streamType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  238 + `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  239 + `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  240 + `gpsTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  241 + PRIMARY KEY (`gbStreamId`) USING BTREE,
  242 + UNIQUE KEY `app` (`app`, `stream`) USING BTREE,
  243 + UNIQUE KEY `gbId` (`gbId`) USING BTREE
  244 +) ENGINE = InnoDB
  245 + AUTO_INCREMENT = 301754
  246 + DEFAULT CHARSET = utf8mb4
  247 + COLLATE = utf8mb4_general_ci
  248 + ROW_FORMAT = DYNAMIC;
217 /*!40101 SET character_set_client = @saved_cs_client */; 249 /*!40101 SET character_set_client = @saved_cs_client */;
218 250
219 -- 251 --
@@ -221,8 +253,10 @@ CREATE TABLE `gb_stream` ( @@ -221,8 +253,10 @@ CREATE TABLE `gb_stream` (
221 -- 253 --
222 254
223 LOCK TABLES `gb_stream` WRITE; 255 LOCK TABLES `gb_stream` WRITE;
224 -/*!40000 ALTER TABLE `gb_stream` DISABLE KEYS */;  
225 -/*!40000 ALTER TABLE `gb_stream` ENABLE KEYS */; 256 +/*!40000 ALTER TABLE `gb_stream`
  257 + DISABLE KEYS */;
  258 +/*!40000 ALTER TABLE `gb_stream`
  259 + ENABLE KEYS */;
226 UNLOCK TABLES; 260 UNLOCK TABLES;
227 261
228 -- 262 --
@@ -230,20 +264,25 @@ UNLOCK TABLES; @@ -230,20 +264,25 @@ UNLOCK TABLES;
230 -- 264 --
231 265
232 DROP TABLE IF EXISTS `log`; 266 DROP TABLE IF EXISTS `log`;
233 -/*!40101 SET @saved_cs_client = @@character_set_client */; 267 +/*!40101 SET @saved_cs_client = @@character_set_client */;
234 /*!50503 SET character_set_client = utf8mb4 */; 268 /*!50503 SET character_set_client = utf8mb4 */;
235 -CREATE TABLE `log` (  
236 - `id` int NOT NULL AUTO_INCREMENT,  
237 - `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
238 - `type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
239 - `uri` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
240 - `address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
241 - `result` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
242 - `timing` bigint NOT NULL,  
243 - `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
244 - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
245 - PRIMARY KEY (`id`) USING BTREE  
246 -) ENGINE=InnoDB AUTO_INCREMENT=34997 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 269 +CREATE TABLE `log`
  270 +(
  271 + `id` int NOT NULL AUTO_INCREMENT,
  272 + `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  273 + `type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  274 + `uri` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  275 + `address` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  276 + `result` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  277 + `timing` bigint NOT NULL,
  278 + `username` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  279 + `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  280 + PRIMARY KEY (`id`) USING BTREE
  281 +) ENGINE = InnoDB
  282 + AUTO_INCREMENT = 42703
  283 + DEFAULT CHARSET = utf8mb4
  284 + COLLATE = utf8mb4_general_ci
  285 + ROW_FORMAT = DYNAMIC;
247 /*!40101 SET character_set_client = @saved_cs_client */; 286 /*!40101 SET character_set_client = @saved_cs_client */;
248 287
249 -- 288 --
@@ -251,8 +290,10 @@ CREATE TABLE `log` ( @@ -251,8 +290,10 @@ CREATE TABLE `log` (
251 -- 290 --
252 291
253 LOCK TABLES `log` WRITE; 292 LOCK TABLES `log` WRITE;
254 -/*!40000 ALTER TABLE `log` DISABLE KEYS */;  
255 -/*!40000 ALTER TABLE `log` ENABLE KEYS */; 293 +/*!40000 ALTER TABLE `log`
  294 + DISABLE KEYS */;
  295 +/*!40000 ALTER TABLE `log`
  296 + ENABLE KEYS */;
256 UNLOCK TABLES; 297 UNLOCK TABLES;
257 298
258 -- 299 --
@@ -260,35 +301,39 @@ UNLOCK TABLES; @@ -260,35 +301,39 @@ UNLOCK TABLES;
260 -- 301 --
261 302
262 DROP TABLE IF EXISTS `media_server`; 303 DROP TABLE IF EXISTS `media_server`;
263 -/*!40101 SET @saved_cs_client = @@character_set_client */; 304 +/*!40101 SET @saved_cs_client = @@character_set_client */;
264 /*!50503 SET character_set_client = utf8mb4 */; 305 /*!50503 SET character_set_client = utf8mb4 */;
265 -CREATE TABLE `media_server` (  
266 - `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
267 - `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
268 - `hookIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
269 - `sdpIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
270 - `streamIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
271 - `httpPort` int NOT NULL,  
272 - `httpSSlPort` int NOT NULL,  
273 - `rtmpPort` int NOT NULL,  
274 - `rtmpSSlPort` int NOT NULL,  
275 - `rtpProxyPort` int NOT NULL,  
276 - `rtspPort` int NOT NULL,  
277 - `rtspSSLPort` int NOT NULL,  
278 - `autoConfig` int NOT NULL,  
279 - `secret` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
280 - `streamNoneReaderDelayMS` int NOT NULL,  
281 - `rtpEnable` int NOT NULL,  
282 - `rtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
283 - `sendRtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
284 - `recordAssistPort` int NOT NULL,  
285 - `defaultServer` int NOT NULL,  
286 - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
287 - `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
288 - `hookAliveInterval` int NOT NULL,  
289 - PRIMARY KEY (`id`) USING BTREE,  
290 - UNIQUE KEY `media_server_i` (`ip`,`httpPort`) USING BTREE  
291 -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 306 +CREATE TABLE `media_server`
  307 +(
  308 + `id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  309 + `ip` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  310 + `hookIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  311 + `sdpIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  312 + `streamIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  313 + `httpPort` int NOT NULL,
  314 + `httpSSlPort` int NOT NULL,
  315 + `rtmpPort` int NOT NULL,
  316 + `rtmpSSlPort` int NOT NULL,
  317 + `rtpProxyPort` int NOT NULL,
  318 + `rtspPort` int NOT NULL,
  319 + `rtspSSLPort` int NOT NULL,
  320 + `autoConfig` int NOT NULL,
  321 + `secret` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  322 + `streamNoneReaderDelayMS` int NOT NULL,
  323 + `rtpEnable` int NOT NULL,
  324 + `rtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  325 + `sendRtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  326 + `recordAssistPort` int NOT NULL,
  327 + `defaultServer` int NOT NULL,
  328 + `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  329 + `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  330 + `hookAliveInterval` int NOT NULL,
  331 + PRIMARY KEY (`id`) USING BTREE,
  332 + UNIQUE KEY `media_server_i` (`ip`, `httpPort`) USING BTREE
  333 +) ENGINE = InnoDB
  334 + DEFAULT CHARSET = utf8mb4
  335 + COLLATE = utf8mb4_general_ci
  336 + ROW_FORMAT = DYNAMIC;
292 /*!40101 SET character_set_client = @saved_cs_client */; 337 /*!40101 SET character_set_client = @saved_cs_client */;
293 338
294 -- 339 --
@@ -296,8 +341,10 @@ CREATE TABLE `media_server` ( @@ -296,8 +341,10 @@ CREATE TABLE `media_server` (
296 -- 341 --
297 342
298 LOCK TABLES `media_server` WRITE; 343 LOCK TABLES `media_server` WRITE;
299 -/*!40000 ALTER TABLE `media_server` DISABLE KEYS */;  
300 -/*!40000 ALTER TABLE `media_server` ENABLE KEYS */; 344 +/*!40000 ALTER TABLE `media_server`
  345 + DISABLE KEYS */;
  346 +/*!40000 ALTER TABLE `media_server`
  347 + ENABLE KEYS */;
301 UNLOCK TABLES; 348 UNLOCK TABLES;
302 349
303 -- 350 --
@@ -305,39 +352,44 @@ UNLOCK TABLES; @@ -305,39 +352,44 @@ UNLOCK TABLES;
305 -- 352 --
306 353
307 DROP TABLE IF EXISTS `parent_platform`; 354 DROP TABLE IF EXISTS `parent_platform`;
308 -/*!40101 SET @saved_cs_client = @@character_set_client */; 355 +/*!40101 SET @saved_cs_client = @@character_set_client */;
309 /*!50503 SET character_set_client = utf8mb4 */; 356 /*!50503 SET character_set_client = utf8mb4 */;
310 -CREATE TABLE `parent_platform` (  
311 - `id` int NOT NULL AUTO_INCREMENT,  
312 - `enable` int DEFAULT NULL,  
313 - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
314 - `serverGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
315 - `serverGBDomain` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
316 - `serverIP` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
317 - `serverPort` int DEFAULT NULL,  
318 - `deviceGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
319 - `deviceIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
320 - `devicePort` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
321 - `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
322 - `password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
323 - `expires` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
324 - `keepTimeout` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
325 - `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
326 - `characterSet` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
327 - `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
328 - `ptz` int DEFAULT NULL,  
329 - `rtcp` int DEFAULT NULL,  
330 - `status` bit(1) DEFAULT NULL,  
331 - `shareAllLiveStream` int DEFAULT NULL,  
332 - `startOfflinePush` int DEFAULT '0',  
333 - `administrativeDivision` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
334 - `catalogGroup` int DEFAULT '1',  
335 - `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,  
336 - `updateTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,  
337 - PRIMARY KEY (`id`) USING BTREE,  
338 - UNIQUE KEY `parent_platform_id_uindex` (`id`) USING BTREE,  
339 - UNIQUE KEY `parent_platform_pk` (`serverGBId`) USING BTREE  
340 -) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 357 +CREATE TABLE `parent_platform`
  358 +(
  359 + `id` int NOT NULL AUTO_INCREMENT,
  360 + `enable` int DEFAULT NULL,
  361 + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  362 + `serverGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  363 + `serverGBDomain` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  364 + `serverIP` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  365 + `serverPort` int DEFAULT NULL,
  366 + `deviceGBId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  367 + `deviceIp` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  368 + `devicePort` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  369 + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  370 + `password` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  371 + `expires` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  372 + `keepTimeout` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  373 + `transport` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  374 + `characterSet` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  375 + `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  376 + `ptz` int DEFAULT NULL,
  377 + `rtcp` int DEFAULT NULL,
  378 + `status` bit(1) DEFAULT NULL,
  379 + `startOfflinePush` int DEFAULT '0 ',
  380 + `administrativeDivision` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  381 + `catalogGroup` int DEFAULT '1 ',
  382 + `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  383 + `updateTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  384 + `treeType` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  385 + PRIMARY KEY (`id`) USING BTREE,
  386 + UNIQUE KEY `parent_platform_id_uindex` (`id`) USING BTREE,
  387 + UNIQUE KEY `parent_platform_pk` (`serverGBId`) USING BTREE
  388 +) ENGINE = InnoDB
  389 + AUTO_INCREMENT = 40
  390 + DEFAULT CHARSET = utf8mb4
  391 + COLLATE = utf8mb4_general_ci
  392 + ROW_FORMAT = DYNAMIC;
341 /*!40101 SET character_set_client = @saved_cs_client */; 393 /*!40101 SET character_set_client = @saved_cs_client */;
342 394
343 -- 395 --
@@ -345,8 +397,10 @@ CREATE TABLE `parent_platform` ( @@ -345,8 +397,10 @@ CREATE TABLE `parent_platform` (
345 -- 397 --
346 398
347 LOCK TABLES `parent_platform` WRITE; 399 LOCK TABLES `parent_platform` WRITE;
348 -/*!40000 ALTER TABLE `parent_platform` DISABLE KEYS */;  
349 -/*!40000 ALTER TABLE `parent_platform` ENABLE KEYS */; 400 +/*!40000 ALTER TABLE `parent_platform`
  401 + DISABLE KEYS */;
  402 +/*!40000 ALTER TABLE `parent_platform`
  403 + ENABLE KEYS */;
350 UNLOCK TABLES; 404 UNLOCK TABLES;
351 405
352 -- 406 --
@@ -354,15 +408,21 @@ UNLOCK TABLES; @@ -354,15 +408,21 @@ UNLOCK TABLES;
354 -- 408 --
355 409
356 DROP TABLE IF EXISTS `platform_catalog`; 410 DROP TABLE IF EXISTS `platform_catalog`;
357 -/*!40101 SET @saved_cs_client = @@character_set_client */; 411 +/*!40101 SET @saved_cs_client = @@character_set_client */;
358 /*!50503 SET character_set_client = utf8mb4 */; 412 /*!50503 SET character_set_client = utf8mb4 */;
359 -CREATE TABLE `platform_catalog` (  
360 - `id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
361 - `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
362 - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
363 - `parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
364 - PRIMARY KEY (`id`) USING BTREE  
365 -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 413 +CREATE TABLE `platform_catalog`
  414 +(
  415 + `id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  416 + `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  417 + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  418 + `parentId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  419 + `civilCode` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  420 + `businessGroupId` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  421 + PRIMARY KEY (`id`) USING BTREE
  422 +) ENGINE = InnoDB
  423 + DEFAULT CHARSET = utf8mb4
  424 + COLLATE = utf8mb4_general_ci
  425 + ROW_FORMAT = DYNAMIC;
366 /*!40101 SET character_set_client = @saved_cs_client */; 426 /*!40101 SET character_set_client = @saved_cs_client */;
367 427
368 -- 428 --
@@ -370,8 +430,10 @@ CREATE TABLE `platform_catalog` ( @@ -370,8 +430,10 @@ CREATE TABLE `platform_catalog` (
370 -- 430 --
371 431
372 LOCK TABLES `platform_catalog` WRITE; 432 LOCK TABLES `platform_catalog` WRITE;
373 -/*!40000 ALTER TABLE `platform_catalog` DISABLE KEYS */;  
374 -/*!40000 ALTER TABLE `platform_catalog` ENABLE KEYS */; 433 +/*!40000 ALTER TABLE `platform_catalog`
  434 + DISABLE KEYS */;
  435 +/*!40000 ALTER TABLE `platform_catalog`
  436 + ENABLE KEYS */;
375 UNLOCK TABLES; 437 UNLOCK TABLES;
376 438
377 -- 439 --
@@ -379,15 +441,20 @@ UNLOCK TABLES; @@ -379,15 +441,20 @@ UNLOCK TABLES;
379 -- 441 --
380 442
381 DROP TABLE IF EXISTS `platform_gb_channel`; 443 DROP TABLE IF EXISTS `platform_gb_channel`;
382 -/*!40101 SET @saved_cs_client = @@character_set_client */; 444 +/*!40101 SET @saved_cs_client = @@character_set_client */;
383 /*!50503 SET character_set_client = utf8mb4 */; 445 /*!50503 SET character_set_client = utf8mb4 */;
384 -CREATE TABLE `platform_gb_channel` (  
385 - `id` int NOT NULL AUTO_INCREMENT,  
386 - `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
387 - `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
388 - `deviceChannelId` int NOT NULL,  
389 - PRIMARY KEY (`id`) USING BTREE  
390 -) ENGINE=InnoDB AUTO_INCREMENT=4889 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 446 +CREATE TABLE `platform_gb_channel`
  447 +(
  448 + `id` int NOT NULL AUTO_INCREMENT,
  449 + `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  450 + `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  451 + `deviceChannelId` int NOT NULL,
  452 + PRIMARY KEY (`id`) USING BTREE
  453 +) ENGINE = InnoDB
  454 + AUTO_INCREMENT = 4915
  455 + DEFAULT CHARSET = utf8mb4
  456 + COLLATE = utf8mb4_general_ci
  457 + ROW_FORMAT = DYNAMIC;
391 /*!40101 SET character_set_client = @saved_cs_client */; 458 /*!40101 SET character_set_client = @saved_cs_client */;
392 459
393 -- 460 --
@@ -395,8 +462,10 @@ CREATE TABLE `platform_gb_channel` ( @@ -395,8 +462,10 @@ CREATE TABLE `platform_gb_channel` (
395 -- 462 --
396 463
397 LOCK TABLES `platform_gb_channel` WRITE; 464 LOCK TABLES `platform_gb_channel` WRITE;
398 -/*!40000 ALTER TABLE `platform_gb_channel` DISABLE KEYS */;  
399 -/*!40000 ALTER TABLE `platform_gb_channel` ENABLE KEYS */; 465 +/*!40000 ALTER TABLE `platform_gb_channel`
  466 + DISABLE KEYS */;
  467 +/*!40000 ALTER TABLE `platform_gb_channel`
  468 + ENABLE KEYS */;
400 UNLOCK TABLES; 469 UNLOCK TABLES;
401 470
402 -- 471 --
@@ -404,16 +473,21 @@ UNLOCK TABLES; @@ -404,16 +473,21 @@ UNLOCK TABLES;
404 -- 473 --
405 474
406 DROP TABLE IF EXISTS `platform_gb_stream`; 475 DROP TABLE IF EXISTS `platform_gb_stream`;
407 -/*!40101 SET @saved_cs_client = @@character_set_client */; 476 +/*!40101 SET @saved_cs_client = @@character_set_client */;
408 /*!50503 SET character_set_client = utf8mb4 */; 477 /*!50503 SET character_set_client = utf8mb4 */;
409 -CREATE TABLE `platform_gb_stream` (  
410 - `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
411 - `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
412 - `gbStreamId` int NOT NULL,  
413 - `id` int NOT NULL AUTO_INCREMENT,  
414 - PRIMARY KEY (`id`) USING BTREE,  
415 - UNIQUE KEY `platform_gb_stream_pk` (`platformId`,`catalogId`,`gbStreamId`) USING BTREE  
416 -) ENGINE=InnoDB AUTO_INCREMENT=302077 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 478 +CREATE TABLE `platform_gb_stream`
  479 +(
  480 + `platformId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  481 + `catalogId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  482 + `gbStreamId` int NOT NULL,
  483 + `id` int NOT NULL AUTO_INCREMENT,
  484 + PRIMARY KEY (`id`) USING BTREE,
  485 + UNIQUE KEY `platform_gb_stream_pk` (`platformId`, `catalogId`, `gbStreamId`) USING BTREE
  486 +) ENGINE = InnoDB
  487 + AUTO_INCREMENT = 302149
  488 + DEFAULT CHARSET = utf8mb4
  489 + COLLATE = utf8mb4_general_ci
  490 + ROW_FORMAT = DYNAMIC;
417 /*!40101 SET character_set_client = @saved_cs_client */; 491 /*!40101 SET character_set_client = @saved_cs_client */;
418 492
419 -- 493 --
@@ -421,8 +495,10 @@ CREATE TABLE `platform_gb_stream` ( @@ -421,8 +495,10 @@ CREATE TABLE `platform_gb_stream` (
421 -- 495 --
422 496
423 LOCK TABLES `platform_gb_stream` WRITE; 497 LOCK TABLES `platform_gb_stream` WRITE;
424 -/*!40000 ALTER TABLE `platform_gb_stream` DISABLE KEYS */;  
425 -/*!40000 ALTER TABLE `platform_gb_stream` ENABLE KEYS */; 498 +/*!40000 ALTER TABLE `platform_gb_stream`
  499 + DISABLE KEYS */;
  500 +/*!40000 ALTER TABLE `platform_gb_stream`
  501 + ENABLE KEYS */;
426 UNLOCK TABLES; 502 UNLOCK TABLES;
427 503
428 -- 504 --
@@ -430,31 +506,36 @@ UNLOCK TABLES; @@ -430,31 +506,36 @@ UNLOCK TABLES;
430 -- 506 --
431 507
432 DROP TABLE IF EXISTS `stream_proxy`; 508 DROP TABLE IF EXISTS `stream_proxy`;
433 -/*!40101 SET @saved_cs_client = @@character_set_client */; 509 +/*!40101 SET @saved_cs_client = @@character_set_client */;
434 /*!50503 SET character_set_client = utf8mb4 */; 510 /*!50503 SET character_set_client = utf8mb4 */;
435 -CREATE TABLE `stream_proxy` (  
436 - `id` int NOT NULL AUTO_INCREMENT,  
437 - `type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
438 - `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
439 - `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
440 - `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
441 - `src_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
442 - `dst_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
443 - `timeout_ms` int DEFAULT NULL,  
444 - `ffmpeg_cmd_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
445 - `rtp_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
446 - `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
447 - `enable_hls` bit(1) DEFAULT NULL,  
448 - `enable_mp4` bit(1) DEFAULT NULL,  
449 - `enable` bit(1) NOT NULL,  
450 - `status` bit(1) NOT NULL,  
451 - `enable_remove_none_reader` bit(1) NOT NULL,  
452 - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
453 - `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
454 - `updateTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,  
455 - PRIMARY KEY (`id`) USING BTREE,  
456 - UNIQUE KEY `stream_proxy_pk` (`app`,`stream`) USING BTREE  
457 -) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 511 +CREATE TABLE `stream_proxy`
  512 +(
  513 + `id` int NOT NULL AUTO_INCREMENT,
  514 + `type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  515 + `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  516 + `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  517 + `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  518 + `src_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  519 + `dst_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  520 + `timeout_ms` int DEFAULT NULL,
  521 + `ffmpeg_cmd_key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  522 + `rtp_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  523 + `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  524 + `enable_hls` bit(1) DEFAULT NULL,
  525 + `enable_mp4` bit(1) DEFAULT NULL,
  526 + `enable` bit(1) NOT NULL,
  527 + `status` bit(1) NOT NULL,
  528 + `enable_remove_none_reader` bit(1) NOT NULL,
  529 + `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  530 + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  531 + `updateTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  532 + PRIMARY KEY (`id`) USING BTREE,
  533 + UNIQUE KEY `stream_proxy_pk` (`app`, `stream`) USING BTREE
  534 +) ENGINE = InnoDB
  535 + AUTO_INCREMENT = 66
  536 + DEFAULT CHARSET = utf8mb4
  537 + COLLATE = utf8mb4_general_ci
  538 + ROW_FORMAT = DYNAMIC;
458 /*!40101 SET character_set_client = @saved_cs_client */; 539 /*!40101 SET character_set_client = @saved_cs_client */;
459 540
460 -- 541 --
@@ -462,8 +543,10 @@ CREATE TABLE `stream_proxy` ( @@ -462,8 +543,10 @@ CREATE TABLE `stream_proxy` (
462 -- 543 --
463 544
464 LOCK TABLES `stream_proxy` WRITE; 545 LOCK TABLES `stream_proxy` WRITE;
465 -/*!40000 ALTER TABLE `stream_proxy` DISABLE KEYS */;  
466 -/*!40000 ALTER TABLE `stream_proxy` ENABLE KEYS */; 546 +/*!40000 ALTER TABLE `stream_proxy`
  547 + DISABLE KEYS */;
  548 +/*!40000 ALTER TABLE `stream_proxy`
  549 + ENABLE KEYS */;
467 UNLOCK TABLES; 550 UNLOCK TABLES;
468 551
469 -- 552 --
@@ -471,25 +554,32 @@ UNLOCK TABLES; @@ -471,25 +554,32 @@ UNLOCK TABLES;
471 -- 554 --
472 555
473 DROP TABLE IF EXISTS `stream_push`; 556 DROP TABLE IF EXISTS `stream_push`;
474 -/*!40101 SET @saved_cs_client = @@character_set_client */; 557 +/*!40101 SET @saved_cs_client = @@character_set_client */;
475 /*!50503 SET character_set_client = utf8mb4 */; 558 /*!50503 SET character_set_client = utf8mb4 */;
476 -CREATE TABLE `stream_push` (  
477 - `id` int NOT NULL AUTO_INCREMENT,  
478 - `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
479 - `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
480 - `totalReaderCount` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
481 - `originType` int DEFAULT NULL,  
482 - `originTypeStr` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
483 - `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,  
484 - `aliveSecond` int DEFAULT NULL,  
485 - `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,  
486 - `serverId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,  
487 - `pushTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,  
488 - `updateTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,  
489 - `status` int DEFAULT NULL,  
490 - PRIMARY KEY (`id`) USING BTREE,  
491 - UNIQUE KEY `stream_push_pk` (`app`,`stream`) USING BTREE  
492 -) ENGINE=InnoDB AUTO_INCREMENT=305315 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 559 +CREATE TABLE `stream_push`
  560 +(
  561 + `id` int NOT NULL AUTO_INCREMENT,
  562 + `app` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  563 + `stream` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  564 + `totalReaderCount` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  565 + `originType` int DEFAULT NULL,
  566 + `originTypeStr` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  567 + `createTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  568 + `aliveSecond` int DEFAULT NULL,
  569 + `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
  570 + `serverId` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  571 + `pushTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  572 + `updateTime` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  573 + `status` int DEFAULT NULL,
  574 + `pushIng` int DEFAULT NULL,
  575 + `self` int DEFAULT NULL,
  576 + PRIMARY KEY (`id`) USING BTREE,
  577 + UNIQUE KEY `stream_push_pk` (`app`, `stream`) USING BTREE
  578 +) ENGINE = InnoDB
  579 + AUTO_INCREMENT = 305415
  580 + DEFAULT CHARSET = utf8mb4
  581 + COLLATE = utf8mb4_general_ci
  582 + ROW_FORMAT = DYNAMIC;
493 /*!40101 SET character_set_client = @saved_cs_client */; 583 /*!40101 SET character_set_client = @saved_cs_client */;
494 584
495 -- 585 --
@@ -497,8 +587,10 @@ CREATE TABLE `stream_push` ( @@ -497,8 +587,10 @@ CREATE TABLE `stream_push` (
497 -- 587 --
498 588
499 LOCK TABLES `stream_push` WRITE; 589 LOCK TABLES `stream_push` WRITE;
500 -/*!40000 ALTER TABLE `stream_push` DISABLE KEYS */;  
501 -/*!40000 ALTER TABLE `stream_push` ENABLE KEYS */; 590 +/*!40000 ALTER TABLE `stream_push`
  591 + DISABLE KEYS */;
  592 +/*!40000 ALTER TABLE `stream_push`
  593 + ENABLE KEYS */;
502 UNLOCK TABLES; 594 UNLOCK TABLES;
503 595
504 -- 596 --
@@ -506,19 +598,24 @@ UNLOCK TABLES; @@ -506,19 +598,24 @@ UNLOCK TABLES;
506 -- 598 --
507 599
508 DROP TABLE IF EXISTS `user`; 600 DROP TABLE IF EXISTS `user`;
509 -/*!40101 SET @saved_cs_client = @@character_set_client */; 601 +/*!40101 SET @saved_cs_client = @@character_set_client */;
510 /*!50503 SET character_set_client = utf8mb4 */; 602 /*!50503 SET character_set_client = utf8mb4 */;
511 -CREATE TABLE `user` (  
512 - `id` int NOT NULL AUTO_INCREMENT,  
513 - `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
514 - `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
515 - `roleId` int NOT NULL,  
516 - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
517 - `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
518 - `pushKey` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,  
519 - PRIMARY KEY (`id`) USING BTREE,  
520 - UNIQUE KEY `user_username_uindex` (`username`) USING BTREE  
521 -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 603 +CREATE TABLE `user`
  604 +(
  605 + `id` int NOT NULL AUTO_INCREMENT,
  606 + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  607 + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  608 + `roleId` int NOT NULL,
  609 + `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  610 + `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  611 + `pushKey` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
  612 + PRIMARY KEY (`id`) USING BTREE,
  613 + UNIQUE KEY `user_username_uindex` (`username`) USING BTREE
  614 +) ENGINE = InnoDB
  615 + AUTO_INCREMENT = 2
  616 + DEFAULT CHARSET = utf8mb4
  617 + COLLATE = utf8mb4_general_ci
  618 + ROW_FORMAT = DYNAMIC;
522 /*!40101 SET character_set_client = @saved_cs_client */; 619 /*!40101 SET character_set_client = @saved_cs_client */;
523 620
524 -- 621 --
@@ -526,9 +623,13 @@ CREATE TABLE `user` ( @@ -526,9 +623,13 @@ CREATE TABLE `user` (
526 -- 623 --
527 624
528 LOCK TABLES `user` WRITE; 625 LOCK TABLES `user` WRITE;
529 -/*!40000 ALTER TABLE `user` DISABLE KEYS */;  
530 -INSERT INTO `user` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021 - 04 - 13 14:14:57','2021 - 04 - 13 14:14:57','453df297a57a5a7438934sda801fc3');  
531 -/*!40000 ALTER TABLE `user` ENABLE KEYS */; 626 +/*!40000 ALTER TABLE `user`
  627 + DISABLE KEYS */;
  628 +INSERT INTO `user`
  629 +VALUES (1, 'admin', '21232f297a57a5a743894a0e4a801fc3', 1, '2021 - 04 - 13 14:14:57', '2021 - 04 - 13 14:14:57',
  630 + '01685cb9573ae25ec6c52142402da7c5');
  631 +/*!40000 ALTER TABLE `user`
  632 + ENABLE KEYS */;
532 UNLOCK TABLES; 633 UNLOCK TABLES;
533 634
534 -- 635 --
@@ -536,16 +637,21 @@ UNLOCK TABLES; @@ -536,16 +637,21 @@ UNLOCK TABLES;
536 -- 637 --
537 638
538 DROP TABLE IF EXISTS `user_role`; 639 DROP TABLE IF EXISTS `user_role`;
539 -/*!40101 SET @saved_cs_client = @@character_set_client */; 640 +/*!40101 SET @saved_cs_client = @@character_set_client */;
540 /*!50503 SET character_set_client = utf8mb4 */; 641 /*!50503 SET character_set_client = utf8mb4 */;
541 -CREATE TABLE `user_role` (  
542 - `id` int NOT NULL AUTO_INCREMENT,  
543 - `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
544 - `authority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
545 - `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
546 - `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,  
547 - PRIMARY KEY (`id`) USING BTREE  
548 -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC; 642 +CREATE TABLE `user_role`
  643 +(
  644 + `id` int NOT NULL AUTO_INCREMENT,
  645 + `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  646 + `authority` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  647 + `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  648 + `updateTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  649 + PRIMARY KEY (`id`) USING BTREE
  650 +) ENGINE = InnoDB
  651 + AUTO_INCREMENT = 2
  652 + DEFAULT CHARSET = utf8mb4
  653 + COLLATE = utf8mb4_general_ci
  654 + ROW_FORMAT = DYNAMIC;
549 /*!40101 SET character_set_client = @saved_cs_client */; 655 /*!40101 SET character_set_client = @saved_cs_client */;
550 656
551 -- 657 --
@@ -553,18 +659,21 @@ CREATE TABLE `user_role` ( @@ -553,18 +659,21 @@ CREATE TABLE `user_role` (
553 -- 659 --
554 660
555 LOCK TABLES `user_role` WRITE; 661 LOCK TABLES `user_role` WRITE;
556 -/*!40000 ALTER TABLE `user_role` DISABLE KEYS */;  
557 -INSERT INTO `user_role` VALUES (1,'admin','0','2021-04-13 14:14:57','2021-04-13 14:14:57');  
558 -/*!40000 ALTER TABLE `user_role` ENABLE KEYS */; 662 +/*!40000 ALTER TABLE `user_role`
  663 + DISABLE KEYS */;
  664 +INSERT INTO `user_role`
  665 +VALUES (1, 'admin', '0 ', '2021 - 04 - 13 14:14:57', '2021 - 04 - 13 14:14:57');
  666 +/*!40000 ALTER TABLE `user_role`
  667 + ENABLE KEYS */;
559 UNLOCK TABLES; 668 UNLOCK TABLES;
560 -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 669 +/*!40103 SET TIME_ZONE = @OLD_TIME_ZONE */;
561 670
562 -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;  
563 -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;  
564 -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;  
565 -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;  
566 -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;  
567 -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;  
568 -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 671 +/*!40101 SET SQL_MODE = @OLD_SQL_MODE */;
  672 +/*!40014 SET FOREIGN_KEY_CHECKS = @OLD_FOREIGN_KEY_CHECKS */;
  673 +/*!40014 SET UNIQUE_CHECKS = @OLD_UNIQUE_CHECKS */;
  674 +/*!40101 SET CHARACTER_SET_CLIENT = @OLD_CHARACTER_SET_CLIENT */;
  675 +/*!40101 SET CHARACTER_SET_RESULTS = @OLD_CHARACTER_SET_RESULTS */;
  676 +/*!40101 SET COLLATION_CONNECTION = @OLD_COLLATION_CONNECTION */;
  677 +/*!40111 SET SQL_NOTES = @OLD_SQL_NOTES */;
569 678
570 --- Dump completed on 2022-07-11 17:32:51 679 +-- Dump completed on 2022-07-27 14:51:08
sql/update.sql
@@ -71,6 +71,8 @@ alter table stream_push @@ -71,6 +71,8 @@ alter table stream_push
71 alter table stream_push 71 alter table stream_push
72 add updateTime varchar(50) default null; 72 add updateTime varchar(50) default null;
73 alter table stream_push 73 alter table stream_push
  74 + add pushIng int DEFAULT NULL;
  75 +alter table stream_push
74 change createStamp createTime varchar(50) default null; 76 change createStamp createTime varchar(50) default null;
75 77
76 alter table gb_stream 78 alter table gb_stream
@@ -78,4 +80,20 @@ alter table gb_stream @@ -78,4 +80,20 @@ alter table gb_stream
78 80
79 alter table user 81 alter table user
80 add pushKey varchar(50) default null; 82 add pushKey varchar(50) default null;
  83 +update user set pushKey='453df297a57a5a7438934sda801fc3' where id=1;
  84 +
  85 +alter table parent_platform
  86 + add treeType varchar(50) not null;
  87 +update parent_platform set parent_platform.treeType='BusinessGroup';
  88 +alter table parent_platform drop shareAllLiveStream;
  89 +
  90 +alter table platform_catalog
  91 + add civilCode varchar(50) default null;
  92 +alter table platform_catalog
  93 + add businessGroupId varchar(50) default null;
  94 +
  95 +/********************* ADD ***************************/
  96 +alter table stream_push
  97 + add self int DEFAULT NULL;
  98 +
81 99
src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
@@ -11,7 +11,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; @@ -11,7 +11,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
11 import springfox.documentation.oas.annotations.EnableOpenApi; 11 import springfox.documentation.oas.annotations.EnableOpenApi;
12 12
13 /** 13 /**
14 - * 14 + * 启动类
15 */ 15 */
16 @ServletComponentScan("com.genersoft.iot.vmp.conf") 16 @ServletComponentScan("com.genersoft.iot.vmp.conf")
17 @SpringBootApplication 17 @SpringBootApplication
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -104,6 +104,10 @@ public class VideoManagerConstants { @@ -104,6 +104,10 @@ public class VideoManagerConstants {
104 // 设备状态订阅的通知 104 // 设备状态订阅的通知
105 public static final String VM_MSG_SUBSCRIBE_DEVICE_STATUS = "device"; 105 public static final String VM_MSG_SUBSCRIBE_DEVICE_STATUS = "device";
106 106
  107 +
  108 +
  109 +
  110 +
107 //************************** 第三方 **************************************** 111 //************************** 第三方 ****************************************
108 public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_"; 112 public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_";
109 public static final String WVP_STREAM_GPS_MSG_PREFIX = "WVP_STREAM_GPS_MSG_"; 113 public static final String WVP_STREAM_GPS_MSG_PREFIX = "WVP_STREAM_GPS_MSG_";
src/main/java/com/genersoft/iot/vmp/conf/RedisConfig.java
1 package com.genersoft.iot.vmp.conf; 1 package com.genersoft.iot.vmp.conf;
2 2
3 import com.genersoft.iot.vmp.common.VideoManagerConstants; 3 import com.genersoft.iot.vmp.common.VideoManagerConstants;
4 -import com.genersoft.iot.vmp.service.impl.RedisAlarmMsgListener;  
5 -import com.genersoft.iot.vmp.service.impl.RedisGpsMsgListener;  
6 -import com.genersoft.iot.vmp.service.impl.RedisGbPlayMsgListener;  
7 -import com.genersoft.iot.vmp.service.impl.RedisStreamMsgListener; 4 +import com.genersoft.iot.vmp.service.impl.*;
8 import org.apache.commons.lang3.StringUtils; 5 import org.apache.commons.lang3.StringUtils;
9 import org.springframework.beans.factory.annotation.Autowired; 6 import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.beans.factory.annotation.Value; 7 import org.springframework.beans.factory.annotation.Value;
@@ -60,6 +57,9 @@ public class RedisConfig extends CachingConfigurerSupport { @@ -60,6 +57,9 @@ public class RedisConfig extends CachingConfigurerSupport {
60 @Autowired 57 @Autowired
61 private RedisGbPlayMsgListener redisGbPlayMsgListener; 58 private RedisGbPlayMsgListener redisGbPlayMsgListener;
62 59
  60 + @Autowired
  61 + private RedisPushStreamStatusMsgListener redisPushStreamStatusMsgListener;
  62 +
63 @Bean 63 @Bean
64 public JedisPool jedisPool() { 64 public JedisPool jedisPool() {
65 if (StringUtils.isBlank(password)) { 65 if (StringUtils.isBlank(password)) {
@@ -108,6 +108,7 @@ public class RedisConfig extends CachingConfigurerSupport { @@ -108,6 +108,7 @@ public class RedisConfig extends CachingConfigurerSupport {
108 container.addMessageListener(redisAlarmMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE)); 108 container.addMessageListener(redisAlarmMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE));
109 container.addMessageListener(redisStreamMsgListener, new PatternTopic(VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + "PUSH")); 109 container.addMessageListener(redisStreamMsgListener, new PatternTopic(VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + "PUSH"));
110 container.addMessageListener(redisGbPlayMsgListener, new PatternTopic(RedisGbPlayMsgListener.WVP_PUSH_STREAM_KEY)); 110 container.addMessageListener(redisGbPlayMsgListener, new PatternTopic(RedisGbPlayMsgListener.WVP_PUSH_STREAM_KEY));
  111 + container.addMessageListener(redisPushStreamStatusMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_STATUS_CHANGE));
111 return container; 112 return container;
112 } 113 }
113 114
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
1 package com.genersoft.iot.vmp.conf; 1 package com.genersoft.iot.vmp.conf;
2 2
3 -import io.swagger.models.auth.In;  
4 import org.springframework.boot.context.properties.ConfigurationProperties; 3 import org.springframework.boot.context.properties.ConfigurationProperties;
5 import org.springframework.stereotype.Component; 4 import org.springframework.stereotype.Component;
6 5
src/main/java/com/genersoft/iot/vmp/conf/security/DefaultUserDetailsServiceImpl.java
1 package com.genersoft.iot.vmp.conf.security; 1 package com.genersoft.iot.vmp.conf.security;
2 2
3 -import com.genersoft.iot.vmp.conf.security.dto.LoginUser;  
4 -import com.genersoft.iot.vmp.service.IUserService;  
5 -import com.genersoft.iot.vmp.storager.dao.dto.User;  
6 -import com.github.xiaoymin.knife4j.core.util.StrUtil; 3 +import java.time.LocalDateTime;
  4 +
7 import org.slf4j.Logger; 5 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory; 6 import org.slf4j.LoggerFactory;
9 import org.springframework.beans.factory.annotation.Autowired; 7 import org.springframework.beans.factory.annotation.Autowired;
@@ -12,7 +10,10 @@ import org.springframework.security.core.userdetails.UserDetailsService; @@ -12,7 +10,10 @@ import org.springframework.security.core.userdetails.UserDetailsService;
12 import org.springframework.security.core.userdetails.UsernameNotFoundException; 10 import org.springframework.security.core.userdetails.UsernameNotFoundException;
13 import org.springframework.stereotype.Component; 11 import org.springframework.stereotype.Component;
14 12
15 -import java.time.LocalDateTime; 13 +import com.alibaba.excel.util.StringUtils;
  14 +import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
  15 +import com.genersoft.iot.vmp.service.IUserService;
  16 +import com.genersoft.iot.vmp.storager.dao.dto.User;
16 17
17 /** 18 /**
18 * 用户登录认证逻辑 19 * 用户登录认证逻辑
@@ -27,7 +28,7 @@ public class DefaultUserDetailsServiceImpl implements UserDetailsService { @@ -27,7 +28,7 @@ public class DefaultUserDetailsServiceImpl implements UserDetailsService {
27 28
28 @Override 29 @Override
29 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 30 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
30 - if (StrUtil.isBlank(username)) { 31 + if (StringUtils.isBlank(username)) {
31 logger.info("登录用户:{} 不存在", username); 32 logger.info("登录用户:{} 不存在", username);
32 throw new UsernameNotFoundException("登录用户:" + username + " 不存在"); 33 throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
33 } 34 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java
@@ -3,8 +3,14 @@ package com.genersoft.iot.vmp.gb28181.bean; @@ -3,8 +3,14 @@ package com.genersoft.iot.vmp.gb28181.bean;
3 import java.time.Instant; 3 import java.time.Instant;
4 import java.util.List; 4 import java.util.List;
5 5
  6 +/**
  7 + * @author lin
  8 + */
6 public class CatalogData { 9 public class CatalogData {
7 - private int sn; // 命令序列号 10 + /**
  11 + * 命令序列号
  12 + */
  13 + private int sn;
8 private int total; 14 private int total;
9 private List<DeviceChannel> channelList; 15 private List<DeviceChannel> channelList;
10 private Instant lastTime; 16 private Instant lastTime;
src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java
@@ -105,11 +105,6 @@ public class ParentPlatform { @@ -105,11 +105,6 @@ public class ParentPlatform {
105 private int channelCount; 105 private int channelCount;
106 106
107 /** 107 /**
108 - * 共享所有的直播流  
109 - */  
110 - private boolean shareAllLiveStream;  
111 -  
112 - /**  
113 * 默认目录Id,自动添加的通道多放在这个目录下 108 * 默认目录Id,自动添加的通道多放在这个目录下
114 */ 109 */
115 private String catalogId; 110 private String catalogId;
@@ -154,6 +149,11 @@ public class ParentPlatform { @@ -154,6 +149,11 @@ public class ParentPlatform {
154 */ 149 */
155 private String createTime; 150 private String createTime;
156 151
  152 + /**
  153 + * 树类型 国标规定了两种树的展现方式 行政区划 CivilCode 和业务分组:BusinessGroup
  154 + */
  155 + private String treeType;
  156 +
157 public Integer getId() { 157 public Integer getId() {
158 return id; 158 return id;
159 } 159 }
@@ -314,15 +314,6 @@ public class ParentPlatform { @@ -314,15 +314,6 @@ public class ParentPlatform {
314 this.channelCount = channelCount; 314 this.channelCount = channelCount;
315 } 315 }
316 316
317 -  
318 - public boolean isShareAllLiveStream() {  
319 - return shareAllLiveStream;  
320 - }  
321 -  
322 - public void setShareAllLiveStream(boolean shareAllLiveStream) {  
323 - this.shareAllLiveStream = shareAllLiveStream;  
324 - }  
325 -  
326 public String getCatalogId() { 317 public String getCatalogId() {
327 return catalogId; 318 return catalogId;
328 } 319 }
@@ -394,4 +385,12 @@ public class ParentPlatform { @@ -394,4 +385,12 @@ public class ParentPlatform {
394 public void setCreateTime(String createTime) { 385 public void setCreateTime(String createTime) {
395 this.createTime = createTime; 386 this.createTime = createTime;
396 } 387 }
  388 +
  389 + public String getTreeType() {
  390 + return treeType;
  391 + }
  392 +
  393 + public void setTreeType(String treeType) {
  394 + this.treeType = treeType;
  395 + }
397 } 396 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java
1 package com.genersoft.iot.vmp.gb28181.bean; 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2
  3 +/**
  4 + * 国标级联-目录
  5 + * @author lin
  6 + */
3 public class PlatformCatalog { 7 public class PlatformCatalog {
4 private String id; 8 private String id;
5 private String name; 9 private String name;
6 private String platformId; 10 private String platformId;
7 private String parentId; 11 private String parentId;
8 - private int childrenCount; // 子节点数  
9 - private int type; // 0 目录, 1 国标通道, 2 直播流 12 +
  13 + private String civilCode;
  14 +
  15 + private String businessGroupId;
  16 +
  17 + /**
  18 + * 子节点数
  19 + */
  20 + private int childrenCount;
  21 +
  22 + /**
  23 + * 0 目录, 1 国标通道, 2 直播流
  24 + */
  25 + private int type;
10 26
11 public String getId() { 27 public String getId() {
12 return id; 28 return id;
@@ -68,4 +84,19 @@ public class PlatformCatalog { @@ -68,4 +84,19 @@ public class PlatformCatalog {
68 this.type = 2; 84 this.type = 2;
69 } 85 }
70 86
  87 + public String getCivilCode() {
  88 + return civilCode;
  89 + }
  90 +
  91 + public void setCivilCode(String civilCode) {
  92 + this.civilCode = civilCode;
  93 + }
  94 +
  95 + public String getBusinessGroupId() {
  96 + return businessGroupId;
  97 + }
  98 +
  99 + public void setBusinessGroupId(String businessGroupId) {
  100 + this.businessGroupId = businessGroupId;
  101 + }
71 } 102 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SyncStatus.java
@@ -2,12 +2,15 @@ package com.genersoft.iot.vmp.gb28181.bean; @@ -2,12 +2,15 @@ package com.genersoft.iot.vmp.gb28181.bean;
2 2
3 /** 3 /**
4 * 摄像机同步状态 4 * 摄像机同步状态
  5 + * @author lin
5 */ 6 */
6 public class SyncStatus { 7 public class SyncStatus {
7 private int total; 8 private int total;
8 private int current; 9 private int current;
9 private String errorMsg; 10 private String errorMsg;
10 11
  12 + private boolean syncIng;
  13 +
11 public int getTotal() { 14 public int getTotal() {
12 return total; 15 return total;
13 } 16 }
@@ -31,4 +34,12 @@ public class SyncStatus { @@ -31,4 +34,12 @@ public class SyncStatus {
31 public void setErrorMsg(String errorMsg) { 34 public void setErrorMsg(String errorMsg) {
32 this.errorMsg = errorMsg; 35 this.errorMsg = errorMsg;
33 } 36 }
  37 +
  38 + public boolean isSyncIng() {
  39 + return syncIng;
  40 + }
  41 +
  42 + public void setSyncIng(boolean syncIng) {
  43 + this.syncIng = syncIng;
  44 + }
34 } 45 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/TreeType.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +/**
  4 + * 目录结构类型
  5 + * @author lin
  6 + */
  7 +public class TreeType {
  8 + public static final String BUSINESS_GROUP = "BusinessGroup";
  9 + public static final String CIVIL_CODE = "CivilCode";
  10 +}
src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java
@@ -65,7 +65,6 @@ public class PlatformNotRegisterEventLister implements ApplicationListener&lt;Platf @@ -65,7 +65,6 @@ public class PlatformNotRegisterEventLister implements ApplicationListener&lt;Platf
65 } 65 }
66 // 查询是否有推流, 如果有则都停止 66 // 查询是否有推流, 如果有则都停止
67 List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServer(event.getPlatformGbID()); 67 List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServer(event.getPlatformGbID());
68 - logger.info("[ 平台未注册事件 ] 停止[ {} ]的所有推流size", sendRtpItems.size());  
69 if (sendRtpItems != null && sendRtpItems.size() > 0) { 68 if (sendRtpItems != null && sendRtpItems.size() > 0) {
70 logger.info("[ 平台未注册事件 ] 停止[ {} ]的所有推流", event.getPlatformGbID()); 69 logger.info("[ 平台未注册事件 ] 停止[ {} ]的所有推流", event.getPlatformGbID());
71 for (SendRtpItem sendRtpItem : sendRtpItems) { 70 for (SendRtpItem sendRtpItem : sendRtpItems) {
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java
@@ -11,13 +11,40 @@ public class CatalogEvent extends ApplicationEvent { @@ -11,13 +11,40 @@ public class CatalogEvent extends ApplicationEvent {
11 super(source); 11 super(source);
12 } 12 }
13 13
14 - public static final String ON = "ON"; // 上线  
15 - public static final String OFF = "OFF"; // 离线  
16 - public static final String VLOST = "VLOST"; // 视频丢失  
17 - public static final String DEFECT = "DEFECT"; // 故障  
18 - public static final String ADD = "ADD"; // 增加  
19 - public static final String DEL = "DEL"; // 删除  
20 - public static final String UPDATE = "UPDATE"; // 更新 14 + /**
  15 + * 上线
  16 + */
  17 + public static final String ON = "ON";
  18 +
  19 + /**
  20 + * 离线
  21 + */
  22 + public static final String OFF = "OFF";
  23 +
  24 + /**
  25 + * 视频丢失
  26 + */
  27 + public static final String VLOST = "VLOST";
  28 +
  29 + /**
  30 + * 故障
  31 + */
  32 + public static final String DEFECT = "DEFECT";
  33 +
  34 + /**
  35 + * 增加
  36 + */
  37 + public static final String ADD = "ADD";
  38 +
  39 + /**
  40 + * 删除
  41 + */
  42 + public static final String DEL = "DEL";
  43 +
  44 + /**
  45 + * 更新
  46 + */
  47 + public static final String UPDATE = "UPDATE";
21 48
22 private List<DeviceChannel> deviceChannels; 49 private List<DeviceChannel> deviceChannels;
23 private List<GbStream> gbStreams; 50 private List<GbStream> gbStreams;
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
@@ -58,17 +58,16 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; { @@ -58,17 +58,16 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
58 ParentPlatform parentPlatform = null; 58 ParentPlatform parentPlatform = null;
59 59
60 Map<String, List<ParentPlatform>> parentPlatformMap = new HashMap<>(); 60 Map<String, List<ParentPlatform>> parentPlatformMap = new HashMap<>();
61 - if (event.getPlatformId() != null) { 61 + if (!StringUtils.isEmpty(event.getPlatformId())) {
  62 + subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId());
  63 + if (subscribe == null) {
  64 + return;
  65 + }
62 parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId()); 66 parentPlatform = storager.queryParentPlatByServerGBId(event.getPlatformId());
63 if (parentPlatform != null && !parentPlatform.isStatus()) { 67 if (parentPlatform != null && !parentPlatform.isStatus()) {
64 return; 68 return;
65 } 69 }
66 - subscribe = subscribeHolder.getCatalogSubscribe(event.getPlatformId());  
67 70
68 - if (subscribe == null) {  
69 - logger.info("发送订阅消息时发现订阅信息已经不存在: {}", event.getPlatformId());  
70 - return;  
71 - }  
72 }else { 71 }else {
73 // 获取所用订阅 72 // 获取所用订阅
74 List<String> platforms = subscribeHolder.getAllCatalogSubscribePlatform(); 73 List<String> platforms = subscribeHolder.getAllCatalogSubscribePlatform();
@@ -144,11 +143,8 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; { @@ -144,11 +143,8 @@ public class CatalogEventLister implements ApplicationListener&lt;CatalogEvent&gt; {
144 } 143 }
145 if (event.getGbStreams() != null && event.getGbStreams().size() > 0){ 144 if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
146 for (GbStream gbStream : event.getGbStreams()) { 145 for (GbStream gbStream : event.getGbStreams()) {
147 - DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform);  
148 - if (deviceChannelByStream.getParentId().length() <= 10) { // 父节点是行政区划,则设置CivilCode使用此行政区划  
149 - deviceChannelByStream.setCivilCode(deviceChannelByStream.getParentId());  
150 - }  
151 - deviceChannelList.add(deviceChannelByStream); 146 + deviceChannelList.add(
  147 + gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform));
152 } 148 }
153 } 149 }
154 if (deviceChannelList.size() > 0) { 150 if (deviceChannelList.size() > 0) {
src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java
@@ -84,6 +84,11 @@ public class CatalogDataCatch { @@ -84,6 +84,11 @@ public class CatalogDataCatch {
84 syncStatus.setCurrent(catalogData.getChannelList().size()); 84 syncStatus.setCurrent(catalogData.getChannelList().size());
85 syncStatus.setTotal(catalogData.getTotal()); 85 syncStatus.setTotal(catalogData.getTotal());
86 syncStatus.setErrorMsg(catalogData.getErrorMsg()); 86 syncStatus.setErrorMsg(catalogData.getErrorMsg());
  87 + if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end)) {
  88 + syncStatus.setSyncIng(false);
  89 + }else {
  90 + syncStatus.setSyncIng(true);
  91 + }
87 return syncStatus; 92 return syncStatus;
88 } 93 }
89 94
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java
@@ -57,23 +57,17 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask { @@ -57,23 +57,17 @@ public class MobilePositionSubscribeHandlerTask implements ISubscribeTask {
57 SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId()); 57 SubscribeInfo subscribe = subscribeHolder.getMobilePositionSubscribe(platform.getServerGBId());
58 if (subscribe != null) { 58 if (subscribe != null) {
59 59
60 -// if (!parentPlatform.isStatus()) {  
61 -// logger.info("发送订阅时发现平台已经离线:{}", platformId);  
62 -// return;  
63 -// }  
64 // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持 60 // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持
65 - List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId()); 61 + List<DeviceChannel> gbStreams = storager.queryGbStreamListInPlatform(platform.getServerGBId());
66 if (gbStreams.size() == 0) { 62 if (gbStreams.size() == 0) {
67 logger.info("发送订阅时发现平台已经没有关联的直播流:{}", platform.getServerGBId()); 63 logger.info("发送订阅时发现平台已经没有关联的直播流:{}", platform.getServerGBId());
68 return; 64 return;
69 } 65 }
70 - for (GbStream gbStream : gbStreams) {  
71 - String gbId = gbStream.getGbId(); 66 + for (DeviceChannel deviceChannel : gbStreams) {
  67 + String gbId = deviceChannel.getChannelId();
72 GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId); 68 GPSMsgInfo gpsMsgInfo = redisCatchStorage.getGpsMsgInfo(gbId);
73 - if (gpsMsgInfo != null) { // 无最新位置不发送  
74 - if (logger.isDebugEnabled()) {  
75 - logger.debug("无最新位置不发送");  
76 - } 69 + // 无最新位置不发送
  70 + if (gpsMsgInfo != null) {
77 // 经纬度都为0不发送 71 // 经纬度都为0不发送
78 if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) { 72 if (gpsMsgInfo.getLng() == 0 && gpsMsgInfo.getLat() == 0) {
79 continue; 73 continue;
src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java
@@ -39,9 +39,9 @@ public class MobilePositionSubscribeTask implements ISubscribeTask { @@ -39,9 +39,9 @@ public class MobilePositionSubscribeTask implements ISubscribeTask {
39 dynamicTask.stop(taskKey); 39 dynamicTask.stop(taskKey);
40 } 40 }
41 sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> { 41 sipCommander.mobilePositionSubscribe(device, dialog, eventResult -> {
42 -// if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {  
43 -// dialog = eventResult.dialog;  
44 -// } 42 + if (eventResult.dialog != null || eventResult.dialog.getState().equals(DialogState.CONFIRMED)) {
  43 + dialog = eventResult.dialog;
  44 + }
45 ResponseEvent event = (ResponseEvent) eventResult.event; 45 ResponseEvent event = (ResponseEvent) eventResult.event;
46 if (event.getResponse().getRawContent() != null) { 46 if (event.getResponse().getRawContent() != null) {
47 // 成功 47 // 成功
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -10,6 +10,9 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; @@ -10,6 +10,9 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
10 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 10 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
12 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; 12 import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider;
  13 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
  14 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
  15 +import com.genersoft.iot.vmp.media.zlm.dto.HookType;
13 import com.genersoft.iot.vmp.utils.DateUtil; 16 import com.genersoft.iot.vmp.utils.DateUtil;
14 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; 17 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
15 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; 18 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
@@ -348,25 +351,19 @@ public class SIPCommander implements ISIPCommander { @@ -348,25 +351,19 @@ public class SIPCommander implements ISIPCommander {
348 @Override 351 @Override
349 public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, 352 public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
350 ZLMHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) { 353 ZLMHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) {
351 - String streamId = ssrcInfo.getStream(); 354 + String stream = ssrcInfo.getStream();
352 try { 355 try {
353 if (device == null) { 356 if (device == null) {
354 return; 357 return;
355 } 358 }
356 String streamMode = device.getStreamMode().toUpperCase(); 359 String streamMode = device.getStreamMode().toUpperCase();
357 360
358 - logger.info("{} 分配的ZLM为: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());  
359 - // 添加订阅  
360 - JSONObject subscribeKey = new JSONObject();  
361 - subscribeKey.put("app", "rtp");  
362 - subscribeKey.put("stream", streamId);  
363 - subscribeKey.put("regist", true);  
364 - subscribeKey.put("schema", "rtmp");  
365 - subscribeKey.put("mediaServerId", mediaServerItem.getId());  
366 - subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,  
367 - (MediaServerItem mediaServerItemInUse, JSONObject json)->{ 361 + logger.info("{} 分配的ZLM为: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
  362 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtmp", mediaServerItem.getId());
  363 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
368 if (event != null) { 364 if (event != null) {
369 event.response(mediaServerItemInUse, json); 365 event.response(mediaServerItemInUse, json);
  366 + subscribe.removeSubscribe(hookSubscribe);
370 } 367 }
371 }); 368 });
372 // 369 //
@@ -440,7 +437,7 @@ public class SIPCommander implements ISIPCommander { @@ -440,7 +437,7 @@ public class SIPCommander implements ISIPCommander {
440 errorEvent.response(e); 437 errorEvent.response(e);
441 }), e ->{ 438 }), e ->{
442 // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值 439 // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
443 - streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction(), VideoStreamSessionManager.SessionType.play); 440 + streamSession.put(device.getDeviceId(), channelId ,"play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction(), VideoStreamSessionManager.SessionType.play);
444 streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog); 441 streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog);
445 okEvent.response(e); 442 okEvent.response(e);
446 }); 443 });
@@ -530,21 +527,14 @@ public class SIPCommander implements ISIPCommander { @@ -530,21 +527,14 @@ public class SIPCommander implements ISIPCommander {
530 527
531 CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() 528 CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
532 : udpSipProvider.getNewCallId(); 529 : udpSipProvider.getNewCallId();
533 - 530 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtmp", mediaServerItem.getId());
534 // 添加订阅 531 // 添加订阅
535 - JSONObject subscribeKey = new JSONObject();  
536 - subscribeKey.put("app", "rtp");  
537 - subscribeKey.put("stream", ssrcInfo.getStream());  
538 - subscribeKey.put("regist", true);  
539 - subscribeKey.put("schema", "rtmp");  
540 - subscribeKey.put("mediaServerId", mediaServerItem.getId());  
541 - logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey);  
542 - subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,  
543 - (MediaServerItem mediaServerItemInUse, JSONObject json)->{ 532 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
544 if (hookEvent != null) { 533 if (hookEvent != null) {
545 InviteStreamInfo inviteStreamInfo = new InviteStreamInfo(mediaServerItemInUse, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()); 534 InviteStreamInfo inviteStreamInfo = new InviteStreamInfo(mediaServerItemInUse, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream());
546 hookEvent.call(inviteStreamInfo); 535 hookEvent.call(inviteStreamInfo);
547 } 536 }
  537 + subscribe.removeSubscribe(hookSubscribe);
548 }); 538 });
549 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc()); 539 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc());
550 540
@@ -643,21 +633,15 @@ public class SIPCommander implements ISIPCommander { @@ -643,21 +633,15 @@ public class SIPCommander implements ISIPCommander {
643 CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() 633 CallIdHeader callIdHeader = device.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId()
644 : udpSipProvider.getNewCallId(); 634 : udpSipProvider.getNewCallId();
645 635
  636 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId());
646 // 添加订阅 637 // 添加订阅
647 - JSONObject subscribeKey = new JSONObject();  
648 - subscribeKey.put("app", "rtp");  
649 - subscribeKey.put("stream", ssrcInfo.getStream());  
650 - subscribeKey.put("regist", true);  
651 - subscribeKey.put("mediaServerId", mediaServerItem.getId());  
652 - logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());  
653 - subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,  
654 - (MediaServerItem mediaServerItemInUse, JSONObject json)->{ 638 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
655 hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream())); 639 hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream()));
656 - subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey);  
657 - subscribeKey.put("regist", false);  
658 - subscribeKey.put("schema", "rtmp"); 640 + subscribe.removeSubscribe(hookSubscribe);
  641 + hookSubscribe.getContent().put("regist", false);
  642 + hookSubscribe.getContent().put("schema", "rtmp");
659 // 添加流注销的订阅,注销了后向设备发送bye 643 // 添加流注销的订阅,注销了后向设备发送bye
660 - subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, 644 + subscribe.addSubscribe(hookSubscribe,
661 (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd)->{ 645 (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd)->{
662 ClientTransaction transaction = streamSession.getTransaction(device.getDeviceId(), channelId, ssrcInfo.getStream(), callIdHeader.getCallId()); 646 ClientTransaction transaction = streamSession.getTransaction(device.getDeviceId(), channelId, ssrcInfo.getStream(), callIdHeader.getCallId());
663 if (transaction != null) { 647 if (transaction != null) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -257,37 +257,37 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -257,37 +257,37 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
257 catalogXml.append("<DeviceList Num=\"" + channels.size() +"\">\r\n"); 257 catalogXml.append("<DeviceList Num=\"" + channels.size() +"\">\r\n");
258 if (channels.size() > 0) { 258 if (channels.size() > 0) {
259 for (DeviceChannel channel : channels) { 259 for (DeviceChannel channel : channels) {
  260 + if (parentPlatform.getServerGBId().equals(channel.getParentId())) {
  261 + channel.setParentId(parentPlatform.getDeviceGBId());
  262 + }
260 catalogXml.append("<Item>\r\n"); 263 catalogXml.append("<Item>\r\n");
  264 + // 行政区划分组只需要这两项就可以
261 catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n"); 265 catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
262 catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n"); 266 catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
263 - catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");  
264 if (channel.getParentId() != null) { 267 if (channel.getParentId() != null) {
  268 + // 业务分组加上这一项即可,提高兼容性,
265 catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n"); 269 catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
266 } 270 }
267 - if (channel.getChannelId().length() == 20) {  
268 - if (Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) { // 虚拟组织增加BusinessGroupID字段  
269 - catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");  
270 - } 271 + if (channel.getChannelId().length() == 20 && Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) {
  272 + // 虚拟组织增加BusinessGroupID字段
  273 + catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");
  274 + }
  275 + catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
  276 + if (channel.getParental() == 0) {
  277 + // 通道项
271 catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n"); 278 catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
  279 + catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
272 catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n"); 280 catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
273 - catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n");  
274 - if (channel.getChannelType() != 2) { // 业务分组/虚拟组织/行政区划 不设置以下字段  
275 - catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n"); 281 + catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
  282 +
  283 + if (channel.getChannelType() != 2) { // 业务分组/虚拟组织/行政区划 不设置以下属性
276 catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n"); 284 catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
277 - catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n"); 285 + catalogXml.append("<Owner> " + channel.getOwner()+ "</Owner>\r\n");
278 catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n"); 286 catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
279 catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n"); 287 catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
280 - catalogXml.append("<Longitude>" + channel.getLongitudeWgs84() + "</Longitude>\r\n");  
281 - catalogXml.append("<Latitude>" + channel.getLatitudeWgs84() + "</Latitude>\r\n");  
282 - catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n");  
283 - catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n");  
284 - catalogXml.append("<Info>\r\n");  
285 - catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n");  
286 - catalogXml.append("</Info>\r\n");  
287 } 288 }
288 - }  
289 -  
290 289
  290 + }
291 catalogXml.append("</Item>\r\n"); 291 catalogXml.append("</Item>\r\n");
292 } 292 }
293 } 293 }
@@ -592,27 +592,35 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -592,27 +592,35 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
592 channel.setParentId(parentPlatform.getDeviceGBId()); 592 channel.setParentId(parentPlatform.getDeviceGBId());
593 } 593 }
594 catalogXml.append("<Item>\r\n"); 594 catalogXml.append("<Item>\r\n");
  595 + // 行政区划分组只需要这两项就可以
595 catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n"); 596 catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n");
596 catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n"); 597 catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n");
597 - catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");  
598 - catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");  
599 if (channel.getParentId() != null) { 598 if (channel.getParentId() != null) {
  599 + // 业务分组加上这一项即可,提高兼容性,
600 catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n"); 600 catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n");
601 } 601 }
602 - catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");  
603 - catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");  
604 - catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");  
605 - if (channel.getChannelId().length() == 20 && Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) { // 虚拟组织增加BusinessGroupID字段 602 + if (channel.getChannelId().length() == 20 && Integer.parseInt(channel.getChannelId().substring(10, 13)) == 216) {
  603 + // 虚拟组织增加BusinessGroupID字段
606 catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n"); 604 catalogXml.append("<BusinessGroupID>" + channel.getParentId() + "</BusinessGroupID>\r\n");
607 } 605 }
608 - if (channel.getChannelType() == 2) { // 业务分组/虚拟组织/行政区划 不设置以下属性  
609 - catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");  
610 - catalogXml.append("<Owner>0</Owner>\r\n");  
611 - catalogXml.append("<CivilCode>CivilCode</CivilCode>\r\n");  
612 - catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");  
613 - }  
614 - if (!"presence".equals(subscribeInfo.getEventType())) {  
615 - catalogXml.append("<Event>" + type + "</Event>\r\n"); 606 + catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n");
  607 + if (channel.getParental() == 0) {
  608 + // 通道项
  609 + catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n");
  610 + catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n");
  611 + catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n");
  612 + catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n");
  613 +
  614 + if (channel.getChannelType() != 2) { // 业务分组/虚拟组织/行政区划 不设置以下属性
  615 + catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n");
  616 + catalogXml.append("<Owner> " + channel.getOwner()+ "</Owner>\r\n");
  617 + catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n");
  618 + catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n");
  619 + }
  620 + if (!"presence".equals(subscribeInfo.getEventType())) {
  621 + catalogXml.append("<Event>" + type + "</Event>\r\n");
  622 + }
  623 +
616 } 624 }
617 catalogXml.append("</Item>\r\n"); 625 catalogXml.append("</Item>\r\n");
618 } 626 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
@@ -133,7 +133,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -133,7 +133,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
133 SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null); 133 SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);
134 if (ssrcTransactionForPlay != null){ 134 if (ssrcTransactionForPlay != null){
135 SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog()); 135 SIPDialog dialogForPlay = (SIPDialog) SerializeUtils.deSerialize(ssrcTransactionForPlay.getDialog());
136 - if (dialogForPlay.getCallId().equals(callIdHeader.getCallId())){ 136 + if (dialogForPlay.getCallId().getCallId().equals(callIdHeader.getCallId())){
137 // 释放ssrc 137 // 释放ssrc
138 MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId()); 138 MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());
139 if (mediaServerItem != null) { 139 if (mediaServerItem != null) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -30,6 +30,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; @@ -30,6 +30,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
30 import com.genersoft.iot.vmp.service.IMediaServerService; 30 import com.genersoft.iot.vmp.service.IMediaServerService;
31 import com.genersoft.iot.vmp.service.IMediaService; 31 import com.genersoft.iot.vmp.service.IMediaService;
32 import com.genersoft.iot.vmp.service.IPlayService; 32 import com.genersoft.iot.vmp.service.IPlayService;
  33 +import com.genersoft.iot.vmp.service.IStreamProxyService;
33 import com.genersoft.iot.vmp.service.IStreamPushService; 34 import com.genersoft.iot.vmp.service.IStreamPushService;
34 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; 35 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
35 import com.genersoft.iot.vmp.service.bean.SSRCInfo; 36 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
@@ -81,6 +82,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -81,6 +82,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
81 private IStreamPushService streamPushService; 82 private IStreamPushService streamPushService;
82 83
83 @Autowired 84 @Autowired
  85 + private IStreamProxyService streamProxyService;
  86 +
  87 + @Autowired
84 private IRedisCatchStorage redisCatchStorage; 88 private IRedisCatchStorage redisCatchStorage;
85 89
86 @Autowired 90 @Autowired
@@ -94,7 +98,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -94,7 +98,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
94 98
95 @Autowired 99 @Autowired
96 private ISIPCommander commander; 100 private ISIPCommander commander;
97 - 101 +
98 @Autowired 102 @Autowired
99 private AudioBroadcastManager audioBroadcastManager; 103 private AudioBroadcastManager audioBroadcastManager;
100 104
@@ -153,10 +157,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -153,10 +157,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
153 // Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令 157 // Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令
154 try { 158 try {
155 Request request = evt.getRequest(); 159 Request request = evt.getRequest();
156 - SipURI sipUri = (SipURI) request.getRequestURI();  
157 - //从subject读取channelId,不再从request-line读取。 有些平台request-line是平台国标编码,不是设备国标编码。  
158 - //String channelId = sipURI.getUser();  
159 - String channelId = SipUtils.getChannelIdFromHeader(request); 160 + String channelId = SipUtils.getChannelIdFromRequest(request);
160 String requesterId = SipUtils.getUserIdFromFromHeader(request); 161 String requesterId = SipUtils.getUserIdFromFromHeader(request);
161 CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); 162 CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
162 if (requesterId == null || channelId == null) { 163 if (requesterId == null || channelId == null) {
@@ -178,6 +179,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -178,6 +179,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
178 179
179 MediaServerItem mediaServerItem = null; 180 MediaServerItem mediaServerItem = null;
180 StreamPushItem streamPushItem = null; 181 StreamPushItem streamPushItem = null;
  182 + StreamProxyItem proxyByAppAndStream =null;
181 // 不是通道可能是直播流 183 // 不是通道可能是直播流
182 if (channel != null && gbStream == null) { 184 if (channel != null && gbStream == null) {
183 if (channel.getStatus() == 0) { 185 if (channel.getStatus() == 0) {
@@ -211,6 +213,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -211,6 +213,13 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
211 responseAck(evt, Response.GONE); 213 responseAck(evt, Response.GONE);
212 return; 214 return;
213 } 215 }
  216 + }else if("proxy".equals(gbStream.getStreamType())){
  217 + proxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(gbStream.getApp(), gbStream.getStream());
  218 + if (proxyByAppAndStream == null) {
  219 + logger.info("[ app={}, stream={} ]找不到zlm {},返回410", gbStream.getApp(), gbStream.getStream(), mediaServerId);
  220 + responseAck(evt, Response.GONE);
  221 + return;
  222 + }
214 } 223 }
215 } 224 }
216 responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中 225 responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 通道存在,发181,呼叫转接中
@@ -452,18 +461,35 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -452,18 +461,35 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
452 } 461 }
453 } 462 }
454 } else if (gbStream != null) { 463 } else if (gbStream != null) {
455 - if (streamPushItem.isStatus()) {  
456 - // 在线状态  
457 - pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,  
458 - mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);  
459 - } else {  
460 - // 不在线 拉起  
461 - notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,  
462 - mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);  
463 - } 464 + if("push".equals(gbStream.getStreamType())) {
  465 + if (streamPushItem != null && streamPushItem.isPushIng()) {
  466 + // 推流状态
  467 + pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  468 + mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
  469 + } else {
  470 + // 未推流 拉起
  471 + notifyStreamOnline(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
  472 + mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
  473 + }
  474 + }else if ("proxy".equals(gbStream.getStreamType())){
  475 + if(null != proxyByAppAndStream &&proxyByAppAndStream.isStatus()){
  476 + pushProxyStream(evt, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
  477 + mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
  478 + }else{
  479 + //开启代理拉流
  480 + boolean start1 = streamProxyService.start(gbStream.getApp(), gbStream.getStream());
  481 + if(start1) {
  482 + pushProxyStream(evt, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive,
  483 + mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
  484 + }else{
  485 + //失败后通知
  486 + notifyStreamOnline(evt, gbStream, null, platform, callIdHeader, mediaServerItem, port, tcpActive,
  487 + mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
  488 + }
  489 + }
464 490
  491 + }
465 } 492 }
466 -  
467 } 493 }
468 494
469 } catch (SipException | InvalidArgumentException | ParseException e) { 495 } catch (SipException | InvalidArgumentException | ParseException e) {
@@ -480,13 +506,45 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -480,13 +506,45 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
480 /** 506 /**
481 * 安排推流 507 * 安排推流
482 */ 508 */
  509 + private void pushProxyStream(RequestEvent evt, GbStream gbStream, ParentPlatform platform,
  510 + CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
  511 + int port, Boolean tcpActive, boolean mediaTransmissionTCP,
  512 + String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
  513 + Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream());
  514 + if (streamReady) {
  515 + // 自平台内容
  516 + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
  517 + gbStream.getApp(), gbStream.getStream(), channelId,
  518 + mediaTransmissionTCP);
  519 +
  520 + if (sendRtpItem == null) {
  521 + logger.warn("服务器端口资源不足");
  522 + responseAck(evt, Response.BUSY_HERE);
  523 + return;
  524 + }
  525 + if (tcpActive != null) {
  526 + sendRtpItem.setTcpActive(tcpActive);
  527 + }
  528 + sendRtpItem.setPlayType(InviteStreamType.PUSH);
  529 + // 写入redis, 超时时回复
  530 + sendRtpItem.setStatus(1);
  531 + sendRtpItem.setCallId(callIdHeader.getCallId());
  532 + byte[] dialogByteArray = SerializeUtils.serialize(evt.getDialog());
  533 + sendRtpItem.setDialog(dialogByteArray);
  534 + byte[] transactionByteArray = SerializeUtils.serialize(evt.getServerTransaction());
  535 + sendRtpItem.setTransaction(transactionByteArray);
  536 + redisCatchStorage.updateSendRTPSever(sendRtpItem);
  537 + sendStreamAck(mediaServerItem, sendRtpItem, platform, evt);
  538 +
  539 + }
483 540
  541 + }
484 private void pushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, 542 private void pushStream(RequestEvent evt, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform,
485 CallIdHeader callIdHeader, MediaServerItem mediaServerItem, 543 CallIdHeader callIdHeader, MediaServerItem mediaServerItem,
486 int port, Boolean tcpActive, boolean mediaTransmissionTCP, 544 int port, Boolean tcpActive, boolean mediaTransmissionTCP,
487 String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException { 545 String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
488 // 推流 546 // 推流
489 - if (streamPushItem.getServerId().equals(userSetting.getServerId())) { 547 + if (streamPushItem.isSelf()) {
490 Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); 548 Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream());
491 if (streamReady) { 549 if (streamReady) {
492 // 自平台内容 550 // 自平台内容
@@ -525,7 +583,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -525,7 +583,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
525 } 583 }
526 584
527 } 585 }
528 -  
529 /** 586 /**
530 * 通知流上线 587 * 通知流上线
531 */ 588 */
@@ -535,7 +592,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -535,7 +592,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
535 String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException { 592 String channelId, String addressStr, String ssrc, String requesterId) throws InvalidArgumentException, ParseException, SipException {
536 if ("proxy".equals(gbStream.getStreamType())) { 593 if ("proxy".equals(gbStream.getStreamType())) {
537 // TODO 控制启用以使设备上线 594 // TODO 控制启用以使设备上线
538 - logger.info("[ app={}, stream={} ]通道离线,启用流后开始推流", gbStream.getApp(), gbStream.getStream()); 595 + logger.info("[ app={}, stream={} ]通道未推流,启用流后开始推流", gbStream.getApp(), gbStream.getStream());
539 responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline"); 596 responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline");
540 } else if ("push".equals(gbStream.getStreamType())) { 597 } else if ("push".equals(gbStream.getStreamType())) {
541 if (!platform.isStartOfflinePush()) { 598 if (!platform.isStartOfflinePush()) {
@@ -543,7 +600,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -543,7 +600,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
543 return; 600 return;
544 } 601 }
545 // 发送redis消息以使设备上线 602 // 发送redis消息以使设备上线
546 - logger.info("[ app={}, stream={} ]通道离线,发送redis信息控制设备开始推流", gbStream.getApp(), gbStream.getStream()); 603 + logger.info("[ app={}, stream={} ]通道未推流,发送redis信息控制设备开始推流", gbStream.getApp(), gbStream.getStream());
547 604
548 MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(1, 605 MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(1,
549 gbStream.getApp(), gbStream.getStream(), gbStream.getGbId(), gbStream.getPlatformId(), 606 gbStream.getApp(), gbStream.getStream(), gbStream.getGbId(), gbStream.getPlatformId(),
@@ -553,7 +610,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -553,7 +610,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
553 dynamicTask.startDelay(callIdHeader.getCallId(), () -> { 610 dynamicTask.startDelay(callIdHeader.getCallId(), () -> {
554 logger.info("[ app={}, stream={} ] 等待设备开始推流超时", gbStream.getApp(), gbStream.getStream()); 611 logger.info("[ app={}, stream={} ] 等待设备开始推流超时", gbStream.getApp(), gbStream.getStream());
555 try { 612 try {
556 - mediaListManager.removedChannelOnlineEventLister(gbStream.getGbId()); 613 + mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream());
557 responseAck(evt, Response.REQUEST_TIMEOUT); // 超时 614 responseAck(evt, Response.REQUEST_TIMEOUT); // 超时
558 } catch (SipException e) { 615 } catch (SipException e) {
559 e.printStackTrace(); 616 e.printStackTrace();
@@ -568,7 +625,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -568,7 +625,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
568 Boolean finalTcpActive = tcpActive; 625 Boolean finalTcpActive = tcpActive;
569 626
570 // 添加在本机上线的通知 627 // 添加在本机上线的通知
571 - mediaListManager.addChannelOnlineEventLister(gbStream.getGbId(), (app, stream, serverId) -> { 628 + mediaListManager.addChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream(), (app, stream, serverId) -> {
572 dynamicTask.stop(callIdHeader.getCallId()); 629 dynamicTask.stop(callIdHeader.getCallId());
573 if (serverId.equals(userSetting.getServerId())) { 630 if (serverId.equals(userSetting.getServerId())) {
574 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId, 631 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId,
@@ -656,7 +713,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -656,7 +713,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
656 // 离线 713 // 离线
657 // 查询是否在本机上线了 714 // 查询是否在本机上线了
658 StreamPushItem currentStreamPushItem = streamPushService.getPush(streamPushItem.getApp(), streamPushItem.getStream()); 715 StreamPushItem currentStreamPushItem = streamPushService.getPush(streamPushItem.getApp(), streamPushItem.getStream());
659 - if (currentStreamPushItem.isStatus()) { 716 + if (currentStreamPushItem.isPushIng()) {
660 // 在线状态 717 // 在线状态
661 pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive, 718 pushStream(evt, gbStream, streamPushItem, platform, callIdHeader, mediaServerItem, port, tcpActive,
662 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); 719 mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
@@ -15,6 +15,7 @@ import com.genersoft.iot.vmp.gb28181.utils.Coordtransform; @@ -15,6 +15,7 @@ import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
15 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; 15 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
16 import com.genersoft.iot.vmp.gb28181.utils.SipUtils; 16 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
17 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; 17 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
  18 +import com.genersoft.iot.vmp.service.IDeviceChannelService;
18 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 19 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
19 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 20 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
20 import com.genersoft.iot.vmp.utils.DateUtil; 21 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -71,6 +72,9 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -71,6 +72,9 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
71 @Autowired 72 @Autowired
72 private SIPProcessorObserver sipProcessorObserver; 73 private SIPProcessorObserver sipProcessorObserver;
73 74
  75 + @Autowired
  76 + private IDeviceChannelService deviceChannelService;
  77 +
74 private boolean taskQueueHandlerRun = false; 78 private boolean taskQueueHandlerRun = false;
75 79
76 private final ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>(); 80 private final ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
@@ -88,39 +92,36 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -88,39 +92,36 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
88 @Override 92 @Override
89 public void process(RequestEvent evt) { 93 public void process(RequestEvent evt) {
90 try { 94 try {
91 -  
92 taskQueue.offer(new HandlerCatchData(evt, null, null)); 95 taskQueue.offer(new HandlerCatchData(evt, null, null));
93 responseAck(evt, Response.OK); 96 responseAck(evt, Response.OK);
94 if (!taskQueueHandlerRun) { 97 if (!taskQueueHandlerRun) {
95 taskQueueHandlerRun = true; 98 taskQueueHandlerRun = true;
96 taskExecutor.execute(()-> { 99 taskExecutor.execute(()-> {
97 - while (!taskQueue.isEmpty()) {  
98 - try {  
99 - HandlerCatchData take = taskQueue.poll();  
100 - Element rootElement = getRootElement(take.getEvt());  
101 - String cmd = XmlUtil.getText(rootElement, "CmdType");  
102 -  
103 - if (CmdType.CATALOG.equals(cmd)) {  
104 - logger.info("接收到Catalog通知");  
105 - processNotifyCatalogList(take.getEvt());  
106 - } else if (CmdType.ALARM.equals(cmd)) {  
107 - logger.info("接收到Alarm通知");  
108 - processNotifyAlarm(take.getEvt());  
109 - } else if (CmdType.MOBILE_POSITION.equals(cmd)) {  
110 - logger.info("接收到MobilePosition通知");  
111 - processNotifyMobilePosition(take.getEvt());  
112 - } else {  
113 - logger.info("接收到消息:" + cmd);  
114 - }  
115 - } catch (DocumentException e) {  
116 - throw new RuntimeException(e);  
117 - } 100 + while (!taskQueue.isEmpty()) {
  101 + try {
  102 + HandlerCatchData take = taskQueue.poll();
  103 + Element rootElement = getRootElement(take.getEvt());
  104 + String cmd = XmlUtil.getText(rootElement, "CmdType");
  105 +
  106 + if (CmdType.CATALOG.equals(cmd)) {
  107 + logger.info("接收到Catalog通知");
  108 + processNotifyCatalogList(take.getEvt());
  109 + } else if (CmdType.ALARM.equals(cmd)) {
  110 + logger.info("接收到Alarm通知");
  111 + processNotifyAlarm(take.getEvt());
  112 + } else if (CmdType.MOBILE_POSITION.equals(cmd)) {
  113 + logger.info("接收到MobilePosition通知");
  114 + processNotifyMobilePosition(take.getEvt());
  115 + } else {
  116 + logger.info("接收到消息:" + cmd);
118 } 117 }
119 - taskQueueHandlerRun = false;  
120 - }); 118 + } catch (DocumentException e) {
  119 + throw new RuntimeException(e);
  120 + }
  121 + }
  122 + taskQueueHandlerRun = false;
  123 + });
121 } 124 }
122 -  
123 -  
124 } catch (SipException | InvalidArgumentException | ParseException e) { 125 } catch (SipException | InvalidArgumentException | ParseException e) {
125 e.printStackTrace(); 126 e.printStackTrace();
126 } 127 }
@@ -170,31 +171,10 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -170,31 +171,10 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
170 } else { 171 } else {
171 mobilePosition.setAltitude(0.0); 172 mobilePosition.setAltitude(0.0);
172 } 173 }
173 - logger.info("[收到 移动位置订阅]:{}/{}->{}.{}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(), 174 + logger.info("[收到移动位置订阅通知]:{}/{}->{}.{}", mobilePosition.getDeviceId(), mobilePosition.getChannelId(),
174 mobilePosition.getLongitude(), mobilePosition.getLatitude()); 175 mobilePosition.getLongitude(), mobilePosition.getLatitude());
175 mobilePosition.setReportSource("Mobile Position"); 176 mobilePosition.setReportSource("Mobile Position");
176 - // 默认来源坐标系为WGS-84处理  
177 - if ("WGS84".equals(device.getGeoCoordSys())) {  
178 - mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());  
179 - mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());  
180 - Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());  
181 - mobilePosition.setLongitudeGcj02(position[0]);  
182 - mobilePosition.setLatitudeGcj02(position[1]);  
183 - }else if ("GCJ02".equals(device.getGeoCoordSys())) {  
184 - mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());  
185 - mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());  
186 - Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());  
187 - mobilePosition.setLongitudeWgs84(position[0]);  
188 - mobilePosition.setLatitudeWgs84(position[1]);  
189 - }else {  
190 - mobilePosition.setLongitudeGcj02(0.00);  
191 - mobilePosition.setLatitudeGcj02(0.00);  
192 - mobilePosition.setLongitudeWgs84(0.00);  
193 - mobilePosition.setLatitudeWgs84(0.00);  
194 - }  
195 - if (userSetting.getSavePositionHistory()) {  
196 - storager.insertMobilePosition(mobilePosition);  
197 - } 177 +
198 178
199 // 更新device channel 的经纬度 179 // 更新device channel 的经纬度
200 DeviceChannel deviceChannel = new DeviceChannel(); 180 DeviceChannel deviceChannel = new DeviceChannel();
@@ -202,11 +182,18 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -202,11 +182,18 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
202 deviceChannel.setChannelId(channelId); 182 deviceChannel.setChannelId(channelId);
203 deviceChannel.setLongitude(mobilePosition.getLongitude()); 183 deviceChannel.setLongitude(mobilePosition.getLongitude());
204 deviceChannel.setLatitude(mobilePosition.getLatitude()); 184 deviceChannel.setLatitude(mobilePosition.getLatitude());
205 - deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());  
206 - deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());  
207 - deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());  
208 - deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());  
209 deviceChannel.setGpsTime(mobilePosition.getTime()); 185 deviceChannel.setGpsTime(mobilePosition.getTime());
  186 + deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
  187 +
  188 + mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
  189 + mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
  190 + mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
  191 + mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
  192 +
  193 + if (userSetting.getSavePositionHistory()) {
  194 + storager.insertMobilePosition(mobilePosition);
  195 + }
  196 +
210 storager.updateChannelPosition(deviceChannel); 197 storager.updateChannelPosition(deviceChannel);
211 // 发送redis消息。 通知位置信息的变化 198 // 发送redis消息。 通知位置信息的变化
212 JSONObject jsonObject = new JSONObject(); 199 JSONObject jsonObject = new JSONObject();
@@ -281,38 +268,28 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -281,38 +268,28 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
281 mobilePosition.setLongitude(deviceAlarm.getLongitude()); 268 mobilePosition.setLongitude(deviceAlarm.getLongitude());
282 mobilePosition.setLatitude(deviceAlarm.getLatitude()); 269 mobilePosition.setLatitude(deviceAlarm.getLatitude());
283 mobilePosition.setReportSource("GPS Alarm"); 270 mobilePosition.setReportSource("GPS Alarm");
284 - if ("WGS84".equals(device.getGeoCoordSys())) {  
285 - mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());  
286 - mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());  
287 - Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());  
288 - mobilePosition.setLongitudeGcj02(position[0]);  
289 - mobilePosition.setLatitudeGcj02(position[1]);  
290 - }else if ("GCJ02".equals(device.getGeoCoordSys())) {  
291 - mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());  
292 - mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());  
293 - Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());  
294 - mobilePosition.setLongitudeWgs84(position[0]);  
295 - mobilePosition.setLatitudeWgs84(position[1]);  
296 - }else {  
297 - mobilePosition.setLongitudeGcj02(0.00);  
298 - mobilePosition.setLatitudeGcj02(0.00);  
299 - mobilePosition.setLongitudeWgs84(0.00);  
300 - mobilePosition.setLatitudeWgs84(0.00);  
301 - }  
302 - if (userSetting.getSavePositionHistory()) {  
303 - storager.insertMobilePosition(mobilePosition);  
304 - } 271 +
  272 +
  273 +
305 // 更新device channel 的经纬度 274 // 更新device channel 的经纬度
306 DeviceChannel deviceChannel = new DeviceChannel(); 275 DeviceChannel deviceChannel = new DeviceChannel();
307 deviceChannel.setDeviceId(device.getDeviceId()); 276 deviceChannel.setDeviceId(device.getDeviceId());
308 deviceChannel.setChannelId(channelId); 277 deviceChannel.setChannelId(channelId);
309 deviceChannel.setLongitude(mobilePosition.getLongitude()); 278 deviceChannel.setLongitude(mobilePosition.getLongitude());
310 deviceChannel.setLatitude(mobilePosition.getLatitude()); 279 deviceChannel.setLatitude(mobilePosition.getLatitude());
311 - deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());  
312 - deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());  
313 - deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());  
314 - deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());  
315 deviceChannel.setGpsTime(mobilePosition.getTime()); 280 deviceChannel.setGpsTime(mobilePosition.getTime());
  281 +
  282 + deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
  283 +
  284 + mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
  285 + mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
  286 + mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
  287 + mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
  288 +
  289 + if (userSetting.getSavePositionHistory()) {
  290 + storager.insertMobilePosition(mobilePosition);
  291 + }
  292 +
316 storager.updateChannelPosition(deviceChannel); 293 storager.updateChannelPosition(deviceChannel);
317 } 294 }
318 // TODO: 需要实现存储报警信息、报警分类 295 // TODO: 需要实现存储报警信息、报警分类
@@ -338,7 +315,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -338,7 +315,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
338 315
339 Device device = redisCatchStorage.getDevice(deviceId); 316 Device device = redisCatchStorage.getDevice(deviceId);
340 if (device == null || device.getOnline() == 0) { 317 if (device == null || device.getOnline() == 0) {
341 - logger.warn("[收到 目录订阅]:{}, 但是设备已经离线", (device != null ? device.getDeviceId():"" )); 318 + logger.warn("[收到目录订阅]:{}, 但是设备已经离线", (device != null ? device.getDeviceId():"" ));
342 return; 319 return;
343 } 320 }
344 Element rootElement = getRootElement(evt, device.getCharset()); 321 Element rootElement = getRootElement(evt, device.getCharset());
@@ -359,28 +336,28 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -359,28 +336,28 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
359 Element eventElement = itemDevice.element("Event"); 336 Element eventElement = itemDevice.element("Event");
360 String event; 337 String event;
361 if (eventElement == null) { 338 if (eventElement == null) {
362 - logger.warn("[收到 目录订阅]:{}, 但是Event为空, 设为默认值 ADD", (device != null ? device.getDeviceId():"" )); 339 + logger.warn("[收到目录订阅]:{}, 但是Event为空, 设为默认值 ADD", (device != null ? device.getDeviceId():"" ));
363 event = CatalogEvent.ADD; 340 event = CatalogEvent.ADD;
364 }else { 341 }else {
365 event = eventElement.getText().toUpperCase(); 342 event = eventElement.getText().toUpperCase();
366 } 343 }
367 - DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device); 344 + DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device, event);
368 channel.setDeviceId(device.getDeviceId()); 345 channel.setDeviceId(device.getDeviceId());
369 - logger.info("[收到 目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId()); 346 + logger.info("[收到目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId());
370 switch (event) { 347 switch (event) {
371 case CatalogEvent.ON: 348 case CatalogEvent.ON:
372 // 上线 349 // 上线
373 - logger.info("收到来自设备【{}】的通道【{}】上线通知", device.getDeviceId(), channel.getChannelId()); 350 + logger.info("[收到通道上线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
374 storager.deviceChannelOnline(deviceId, channel.getChannelId()); 351 storager.deviceChannelOnline(deviceId, channel.getChannelId());
375 break; 352 break;
376 case CatalogEvent.OFF : 353 case CatalogEvent.OFF :
377 // 离线 354 // 离线
378 - logger.info("收到来自设备【{}】的通道【{}】离线通知", device.getDeviceId(), channel.getChannelId()); 355 + logger.info("[收到通道离线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
379 storager.deviceChannelOffline(deviceId, channel.getChannelId()); 356 storager.deviceChannelOffline(deviceId, channel.getChannelId());
380 break; 357 break;
381 case CatalogEvent.VLOST: 358 case CatalogEvent.VLOST:
382 // 视频丢失 359 // 视频丢失
383 - logger.info("收到来自设备【{}】的通道【{}】视频丢失通知", device.getDeviceId(), channel.getChannelId()); 360 + logger.info("[收到通道视频丢失通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
384 storager.deviceChannelOffline(deviceId, channel.getChannelId()); 361 storager.deviceChannelOffline(deviceId, channel.getChannelId());
385 break; 362 break;
386 case CatalogEvent.DEFECT: 363 case CatalogEvent.DEFECT:
@@ -388,18 +365,18 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements @@ -388,18 +365,18 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements
388 break; 365 break;
389 case CatalogEvent.ADD: 366 case CatalogEvent.ADD:
390 // 增加 367 // 增加
391 - logger.info("收到来自设备【{}】的增加通道【{}】通知", device.getDeviceId(), channel.getChannelId());  
392 - storager.updateChannel(deviceId, channel); 368 + logger.info("[收到增加通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  369 + deviceChannelService.updateChannel(deviceId, channel);
393 break; 370 break;
394 case CatalogEvent.DEL: 371 case CatalogEvent.DEL:
395 // 删除 372 // 删除
396 - logger.info("收到来自设备【{}】的删除通道【{}】通知", device.getDeviceId(), channel.getChannelId()); 373 + logger.info("[收到删除通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
397 storager.delChannel(deviceId, channel.getChannelId()); 374 storager.delChannel(deviceId, channel.getChannelId());
398 break; 375 break;
399 case CatalogEvent.UPDATE: 376 case CatalogEvent.UPDATE:
400 // 更新 377 // 更新
401 - logger.info("收到来自设备【{}】的更新通道【{}】通知", device.getDeviceId(), channel.getChannelId());  
402 - storager.updateChannel(deviceId, channel); 378 + logger.info("[收到更新通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  379 + deviceChannelService.updateChannel(deviceId, channel);
403 break; 380 break;
404 default: 381 default:
405 logger.warn("[ NotifyCatalog ] event not found : {}", event ); 382 logger.warn("[ NotifyCatalog ] event not found : {}", event );
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -143,6 +143,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -143,6 +143,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
143 device.setGeoCoordSys("WGS84"); 143 device.setGeoCoordSys("WGS84");
144 device.setTreeType("CivilCode"); 144 device.setTreeType("CivilCode");
145 device.setDeviceId(deviceId); 145 device.setDeviceId(deviceId);
  146 + device.setOnline(0);
146 } 147 }
147 device.setIp(received); 148 device.setIp(received);
148 device.setPort(rPort); 149 device.setPort(rPort);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java
@@ -27,6 +27,7 @@ import javax.sip.SipException; @@ -27,6 +27,7 @@ import javax.sip.SipException;
27 import javax.sip.address.SipURI; 27 import javax.sip.address.SipURI;
28 import javax.sip.header.CSeqHeader; 28 import javax.sip.header.CSeqHeader;
29 import javax.sip.header.CallIdHeader; 29 import javax.sip.header.CallIdHeader;
  30 +import javax.sip.message.Request;
30 import javax.sip.message.Response; 31 import javax.sip.message.Response;
31 import java.text.ParseException; 32 import java.text.ParseException;
32 import java.util.Map; 33 import java.util.Map;
@@ -68,22 +69,23 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement @@ -68,22 +69,23 @@ public class MessageRequestProcessor extends SIPRequestProcessorParent implement
68 69
69 @Override 70 @Override
70 public void process(RequestEvent evt) { 71 public void process(RequestEvent evt) {
  72 + SIPRequest sipRequest = (SIPRequest)evt.getRequest();
71 logger.debug("接收到消息:" + evt.getRequest()); 73 logger.debug("接收到消息:" + evt.getRequest());
72 String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest()); 74 String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
73 - CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); 75 + CallIdHeader callIdHeader = sipRequest.getCallIdHeader();
74 // 先从会话内查找 76 // 先从会话内查找
75 SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); 77 SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
76 - if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题 78 + // 兼容海康 媒体通知 消息from字段不是设备ID的问题
  79 + if (ssrcTransaction != null) {
77 deviceId = ssrcTransaction.getDeviceId(); 80 deviceId = ssrcTransaction.getDeviceId();
78 } 81 }
79 // 查询设备是否存在 82 // 查询设备是否存在
80 - CSeqHeader cseqHeader = (CSeqHeader) evt.getRequest().getHeader(CSeqHeader.NAME);  
81 - String method = cseqHeader.getMethod();  
82 Device device = redisCatchStorage.getDevice(deviceId); 83 Device device = redisCatchStorage.getDevice(deviceId);
83 // 查询上级平台是否存在 84 // 查询上级平台是否存在
84 ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId); 85 ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId);
85 try { 86 try {
86 if (device != null && parentPlatform != null) { 87 if (device != null && parentPlatform != null) {
  88 +
87 logger.warn("[重复]平台与设备编号重复:{}", deviceId); 89 logger.warn("[重复]平台与设备编号重复:{}", deviceId);
88 SIPRequest request = (SIPRequest) evt.getRequest(); 90 SIPRequest request = (SIPRequest) evt.getRequest();
89 String hostAddress = request.getRemoteAddress().getHostAddress(); 91 String hostAddress = request.getRemoteAddress().getHostAddress();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/NotifyMessageHandler.java
@@ -9,6 +9,7 @@ import org.springframework.stereotype.Component; @@ -9,6 +9,7 @@ import org.springframework.stereotype.Component;
9 /** 9 /**
10 * 命令类型: 通知命令 10 * 命令类型: 通知命令
11 * 命令类型: 状态信息(心跳)报送, 报警通知, 媒体通知, 移动设备位置数据,语音广播通知(TODO), 设备预置位(TODO) 11 * 命令类型: 状态信息(心跳)报送, 报警通知, 媒体通知, 移动设备位置数据,语音广播通知(TODO), 设备预置位(TODO)
  12 + * @author lin
12 */ 13 */
13 @Component 14 @Component
14 public class NotifyMessageHandler extends MessageHandlerAbstract implements InitializingBean { 15 public class NotifyMessageHandler extends MessageHandlerAbstract implements InitializingBean {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
@@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.utils.Coordtransform; @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
11 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; 11 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
12 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; 12 import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
13 import com.genersoft.iot.vmp.service.IDeviceAlarmService; 13 import com.genersoft.iot.vmp.service.IDeviceAlarmService;
  14 +import com.genersoft.iot.vmp.service.IDeviceChannelService;
14 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
15 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 16 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
16 import com.genersoft.iot.vmp.utils.DateUtil; 17 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -58,6 +59,9 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @@ -58,6 +59,9 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
58 @Autowired 59 @Autowired
59 private IDeviceAlarmService deviceAlarmService; 60 private IDeviceAlarmService deviceAlarmService;
60 61
  62 + @Autowired
  63 + private IDeviceChannelService deviceChannelService;
  64 +
61 @Override 65 @Override
62 public void afterPropertiesSet() throws Exception { 66 public void afterPropertiesSet() throws Exception {
63 notifyMessageHandler.addHandler(cmdType, this); 67 notifyMessageHandler.addHandler(cmdType, this);
@@ -65,7 +69,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @@ -65,7 +69,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
65 69
66 @Override 70 @Override
67 public void handForDevice(RequestEvent evt, Device device, Element rootElement) { 71 public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
68 - logger.info("收到来自设备[{}]的报警通知", device.getDeviceId()); 72 + logger.info("[收到报警通知]设备:{}", device.getDeviceId());
69 // 回复200 OK 73 // 回复200 OK
70 try { 74 try {
71 responseAck(evt, Response.OK); 75 responseAck(evt, Response.OK);
@@ -119,38 +123,26 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @@ -119,38 +123,26 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
119 mobilePosition.setLongitude(deviceAlarm.getLongitude()); 123 mobilePosition.setLongitude(deviceAlarm.getLongitude());
120 mobilePosition.setLatitude(deviceAlarm.getLatitude()); 124 mobilePosition.setLatitude(deviceAlarm.getLatitude());
121 mobilePosition.setReportSource("GPS Alarm"); 125 mobilePosition.setReportSource("GPS Alarm");
122 - if ("WGS84".equals(device.getGeoCoordSys())) {  
123 - mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());  
124 - mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());  
125 - Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());  
126 - mobilePosition.setLongitudeGcj02(position[0]);  
127 - mobilePosition.setLatitudeGcj02(position[1]);  
128 - }else if ("GCJ02".equals(device.getGeoCoordSys())) {  
129 - mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());  
130 - mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());  
131 - Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());  
132 - mobilePosition.setLongitudeWgs84(position[0]);  
133 - mobilePosition.setLatitudeWgs84(position[1]);  
134 - }else {  
135 - mobilePosition.setLongitudeGcj02(0.00);  
136 - mobilePosition.setLatitudeGcj02(0.00);  
137 - mobilePosition.setLongitudeWgs84(0.00);  
138 - mobilePosition.setLatitudeWgs84(0.00);  
139 - }  
140 - if (userSetting.getSavePositionHistory()) {  
141 - storager.insertMobilePosition(mobilePosition);  
142 - } 126 +
  127 +
143 // 更新device channel 的经纬度 128 // 更新device channel 的经纬度
144 DeviceChannel deviceChannel = new DeviceChannel(); 129 DeviceChannel deviceChannel = new DeviceChannel();
145 deviceChannel.setDeviceId(device.getDeviceId()); 130 deviceChannel.setDeviceId(device.getDeviceId());
146 deviceChannel.setChannelId(channelId); 131 deviceChannel.setChannelId(channelId);
147 deviceChannel.setLongitude(mobilePosition.getLongitude()); 132 deviceChannel.setLongitude(mobilePosition.getLongitude());
148 deviceChannel.setLatitude(mobilePosition.getLatitude()); 133 deviceChannel.setLatitude(mobilePosition.getLatitude());
149 - deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());  
150 - deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());  
151 - deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());  
152 - deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());  
153 deviceChannel.setGpsTime(mobilePosition.getTime()); 134 deviceChannel.setGpsTime(mobilePosition.getTime());
  135 +
  136 + deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
  137 +
  138 + mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
  139 + mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
  140 + mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
  141 + mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
  142 +
  143 + if (userSetting.getSavePositionHistory()) {
  144 + storager.insertMobilePosition(mobilePosition);
  145 + }
154 storager.updateChannelPosition(deviceChannel); 146 storager.updateChannelPosition(deviceChannel);
155 } 147 }
156 } 148 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java
@@ -58,85 +58,21 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple @@ -58,85 +58,21 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple
58 // 准备回复通道信息 58 // 准备回复通道信息
59 List<DeviceChannelInPlatform> deviceChannels = storage.queryChannelListInParentPlatform(parentPlatform.getServerGBId()); 59 List<DeviceChannelInPlatform> deviceChannels = storage.queryChannelListInParentPlatform(parentPlatform.getServerGBId());
60 // 查询关联的直播通道 60 // 查询关联的直播通道
61 - List<GbStream> gbStreams = storage.queryGbStreamListInPlatform(parentPlatform.getServerGBId()); 61 + List<DeviceChannel> gbStreams = storage.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
  62 + // 回复目录信息
  63 + List<DeviceChannel> catalogs = storage.queryCatalogInPlatform(parentPlatform.getServerGBId());
62 64
63 List<DeviceChannel> allChannels = new ArrayList<>(); 65 List<DeviceChannel> allChannels = new ArrayList<>();
64 - // 回复目录信息  
65 - List<PlatformCatalog> catalogs = storage.queryCatalogInPlatform(parentPlatform.getServerGBId());  
66 if (catalogs.size() > 0) { 66 if (catalogs.size() > 0) {
67 - for (PlatformCatalog catalog : catalogs) {  
68 - if (catalog.getParentId().equals(catalog.getPlatformId())) {  
69 - catalog.setParentId(parentPlatform.getDeviceGBId());  
70 - }  
71 - DeviceChannel deviceChannel = new DeviceChannel();  
72 - deviceChannel.setChannelId(catalog.getId());  
73 - deviceChannel.setName(catalog.getName());  
74 - deviceChannel.setLongitude(0.0);  
75 - deviceChannel.setLatitude(0.0);  
76 - deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());  
77 - deviceChannel.setManufacture("wvp-pro");  
78 - deviceChannel.setStatus(1);  
79 - deviceChannel.setParental(1);  
80 - deviceChannel.setParentId(catalog.getParentId());  
81 - deviceChannel.setRegisterWay(1);  
82 - if (catalog.getParentId() != null && catalog.getParentId().length() <= 10) {  
83 - deviceChannel.setCivilCode(catalog.getParentId());  
84 - }else {  
85 - deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());  
86 - }  
87 - deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());  
88 - deviceChannel.setModel("live");  
89 - deviceChannel.setOwner("wvp-pro");  
90 - deviceChannel.setSecrecy("0");  
91 - allChannels.add(deviceChannel);  
92 - } 67 + allChannels.addAll(catalogs);
93 } 68 }
94 // 回复级联的通道 69 // 回复级联的通道
95 if (deviceChannels.size() > 0) { 70 if (deviceChannels.size() > 0) {
96 - for (DeviceChannelInPlatform channel : deviceChannels) {  
97 - if (channel.getCatalogId().equals(parentPlatform.getServerGBId())) {  
98 - channel.setCatalogId(parentPlatform.getDeviceGBId());  
99 - }  
100 - DeviceChannel deviceChannel = storage.queryChannel(channel.getDeviceId(), channel.getChannelId());  
101 - deviceChannel.setParental(0);  
102 - deviceChannel.setParentId(channel.getCatalogId());  
103 - if (channel.getCatalogId() != null && channel.getCatalogId().length() <= 10) {  
104 - channel.setCivilCode(channel.getCatalogId());  
105 - }else {  
106 - deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());  
107 - }  
108 -  
109 - allChannels.add(deviceChannel);  
110 - } 71 + allChannels.addAll(deviceChannels);
111 } 72 }
112 // 回复直播的通道 73 // 回复直播的通道
113 if (gbStreams.size() > 0) { 74 if (gbStreams.size() > 0) {
114 - for (GbStream gbStream : gbStreams) {  
115 - if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) {  
116 - gbStream.setCatalogId(null);  
117 - }  
118 - DeviceChannel deviceChannel = new DeviceChannel();  
119 - deviceChannel.setChannelId(gbStream.getGbId());  
120 - deviceChannel.setName(gbStream.getName());  
121 - deviceChannel.setLongitude(gbStream.getLongitude());  
122 - deviceChannel.setLatitude(gbStream.getLatitude());  
123 - deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());  
124 - deviceChannel.setManufacture("wvp-pro");  
125 -// deviceChannel.setStatus(gbStream.isStatus()?1:0);  
126 - deviceChannel.setStatus(1);  
127 - deviceChannel.setParentId(gbStream.getCatalogId());  
128 - deviceChannel.setRegisterWay(1);  
129 - if (gbStream.getCatalogId() != null && gbStream.getCatalogId().length() <= 10) {  
130 - deviceChannel.setCivilCode(gbStream.getCatalogId());  
131 - }else {  
132 - deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());  
133 - }  
134 - deviceChannel.setModel("live");  
135 - deviceChannel.setOwner("wvp-pro");  
136 - deviceChannel.setParental(0);  
137 - deviceChannel.setSecrecy("0");  
138 - allChannels.add(deviceChannel);  
139 - } 75 + allChannels.addAll(gbStreams);
140 } 76 }
141 if (allChannels.size() > 0) { 77 if (allChannels.size() > 0) {
142 cmderFroPlatform.catalogQuery(allChannels, parentPlatform, sn, fromHeader.getTag()); 78 cmderFroPlatform.catalogQuery(allChannels, parentPlatform, sn, fromHeader.getTag());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java
@@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessag @@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessag
7 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; 7 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
8 import com.genersoft.iot.vmp.gb28181.utils.Coordtransform; 8 import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
9 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; 9 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
  10 +import com.genersoft.iot.vmp.service.IDeviceChannelService;
10 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 11 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
11 import com.genersoft.iot.vmp.utils.DateUtil; 12 import com.genersoft.iot.vmp.utils.DateUtil;
12 import com.genersoft.iot.vmp.utils.GpsUtil; 13 import com.genersoft.iot.vmp.utils.GpsUtil;
@@ -42,6 +43,9 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen @@ -42,6 +43,9 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
42 @Autowired 43 @Autowired
43 private IVideoManagerStorage storager; 44 private IVideoManagerStorage storager;
44 45
  46 + @Autowired
  47 + private IDeviceChannelService deviceChannelService;
  48 +
45 @Override 49 @Override
46 public void afterPropertiesSet() throws Exception { 50 public void afterPropertiesSet() throws Exception {
47 notifyMessageHandler.addHandler(cmdType, this); 51 notifyMessageHandler.addHandler(cmdType, this);
@@ -79,38 +83,26 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen @@ -79,38 +83,26 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen
79 mobilePosition.setAltitude(0.0); 83 mobilePosition.setAltitude(0.0);
80 } 84 }
81 mobilePosition.setReportSource("Mobile Position"); 85 mobilePosition.setReportSource("Mobile Position");
82 - if ("WGS84".equals(device.getGeoCoordSys())) {  
83 - mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());  
84 - mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());  
85 - Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());  
86 - mobilePosition.setLongitudeGcj02(position[0]);  
87 - mobilePosition.setLatitudeGcj02(position[1]);  
88 - }else if ("GCJ02".equals(device.getGeoCoordSys())) {  
89 - mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());  
90 - mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());  
91 - Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());  
92 - mobilePosition.setLongitudeWgs84(position[0]);  
93 - mobilePosition.setLatitudeWgs84(position[1]);  
94 - }else {  
95 - mobilePosition.setLongitudeGcj02(0.00);  
96 - mobilePosition.setLatitudeGcj02(0.00);  
97 - mobilePosition.setLongitudeWgs84(0.00);  
98 - mobilePosition.setLatitudeWgs84(0.00);  
99 - }  
100 - if (userSetting.getSavePositionHistory()) {  
101 - storager.insertMobilePosition(mobilePosition);  
102 - } 86 +
  87 +
103 // 更新device channel 的经纬度 88 // 更新device channel 的经纬度
104 DeviceChannel deviceChannel = new DeviceChannel(); 89 DeviceChannel deviceChannel = new DeviceChannel();
105 deviceChannel.setDeviceId(device.getDeviceId()); 90 deviceChannel.setDeviceId(device.getDeviceId());
106 deviceChannel.setChannelId(mobilePosition.getChannelId()); 91 deviceChannel.setChannelId(mobilePosition.getChannelId());
107 deviceChannel.setLongitude(mobilePosition.getLongitude()); 92 deviceChannel.setLongitude(mobilePosition.getLongitude());
108 deviceChannel.setLatitude(mobilePosition.getLatitude()); 93 deviceChannel.setLatitude(mobilePosition.getLatitude());
109 - deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());  
110 - deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());  
111 - deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());  
112 - deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());  
113 deviceChannel.setGpsTime(mobilePosition.getTime()); 94 deviceChannel.setGpsTime(mobilePosition.getTime());
  95 +
  96 + deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
  97 +
  98 + mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
  99 + mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
  100 + mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
  101 + mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
  102 +
  103 + if (userSetting.getSavePositionHistory()) {
  104 + storager.insertMobilePosition(mobilePosition);
  105 + }
114 storager.updateChannelPosition(deviceChannel); 106 storager.updateChannelPosition(deviceChannel);
115 //回复 200 OK 107 //回复 200 OK
116 responseAck(evt, Response.OK); 108 responseAck(evt, Response.OK);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
@@ -70,86 +70,24 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem @@ -70,86 +70,24 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem
70 Element snElement = rootElement.element("SN"); 70 Element snElement = rootElement.element("SN");
71 String sn = snElement.getText(); 71 String sn = snElement.getText();
72 // 准备回复通道信息 72 // 准备回复通道信息
73 - List<DeviceChannelInPlatform> deviceChannelInPlatforms = storager.queryChannelListInParentPlatform(parentPlatform.getServerGBId()); 73 + List<DeviceChannel> deviceChannelInPlatforms = storager.queryChannelWithCatalog(parentPlatform.getServerGBId());
74 // 查询关联的直播通道 74 // 查询关联的直播通道
75 - List<GbStream> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId()); 75 + List<DeviceChannel> gbStreams = storager.queryGbStreamListInPlatform(parentPlatform.getServerGBId());
76 // 回复目录信息 76 // 回复目录信息
77 - List<PlatformCatalog> catalogs = storager.queryCatalogInPlatform(parentPlatform.getServerGBId()); 77 + List<DeviceChannel> catalogs = storager.queryCatalogInPlatform(parentPlatform.getServerGBId());
78 78
79 List<DeviceChannel> allChannels = new ArrayList<>(); 79 List<DeviceChannel> allChannels = new ArrayList<>();
  80 +
80 if (catalogs.size() > 0) { 81 if (catalogs.size() > 0) {
81 - for (PlatformCatalog catalog : catalogs) {  
82 - if (catalog.getParentId().equals(catalog.getPlatformId())) {  
83 - catalog.setParentId(parentPlatform.getDeviceGBId());  
84 - }  
85 - DeviceChannel deviceChannel = new DeviceChannel();  
86 - // 通道的类型,0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划  
87 - deviceChannel.setChannelType(2);  
88 - deviceChannel.setChannelId(catalog.getId());  
89 - deviceChannel.setName(catalog.getName());  
90 - deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());  
91 - deviceChannel.setManufacture("wvp-pro");  
92 - deviceChannel.setStatus(1);  
93 - deviceChannel.setParental(1);  
94 - deviceChannel.setParentId(catalog.getParentId());  
95 - deviceChannel.setRegisterWay(1);  
96 - if (catalog.getParentId() != null && catalog.getParentId().length() < 10) {  
97 - deviceChannel.setCivilCode(catalog.getParentId());  
98 - }else {  
99 - deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());  
100 - }  
101 - allChannels.add(deviceChannel);  
102 - } 82 + allChannels.addAll(catalogs);
103 } 83 }
104 // 回复级联的通道 84 // 回复级联的通道
105 if (deviceChannelInPlatforms.size() > 0) { 85 if (deviceChannelInPlatforms.size() > 0) {
106 - for (DeviceChannelInPlatform channel : deviceChannelInPlatforms) {  
107 - if (channel.getCatalogId().equals(parentPlatform.getServerGBId())) {  
108 - channel.setCatalogId(parentPlatform.getDeviceGBId());  
109 - }  
110 - DeviceChannel deviceChannel = storage.queryChannel(channel.getDeviceId(), channel.getChannelId());  
111 - // 通道的类型,0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划  
112 - deviceChannel.setChannelType(0);  
113 - deviceChannel.setParental(0);  
114 - deviceChannel.setParentId(channel.getCatalogId());  
115 - if (channel.getCatalogId() != null && channel.getCatalogId().length() < 10) {  
116 - deviceChannel.setCivilCode(channel.getCatalogId());  
117 - }else {  
118 - deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());  
119 - }  
120 - allChannels.add(deviceChannel);  
121 - } 86 + allChannels.addAll(deviceChannelInPlatforms);
122 } 87 }
123 // 回复直播的通道 88 // 回复直播的通道
124 if (gbStreams.size() > 0) { 89 if (gbStreams.size() > 0) {
125 - for (GbStream gbStream : gbStreams) {  
126 - if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) {  
127 - gbStream.setCatalogId(null);  
128 - }  
129 - DeviceChannel deviceChannel = new DeviceChannel();  
130 - // 通道的类型,0->国标通道 1->直播流通道 2->业务分组/虚拟组织/行政区划  
131 - deviceChannel.setChannelType(1);  
132 - deviceChannel.setChannelId(gbStream.getGbId());  
133 - deviceChannel.setName(gbStream.getName());  
134 - deviceChannel.setLongitude(gbStream.getLongitude());  
135 - deviceChannel.setLatitude(gbStream.getLatitude());  
136 - deviceChannel.setDeviceId(parentPlatform.getDeviceGBId());  
137 - deviceChannel.setManufacture("wvp-pro");  
138 -// deviceChannel.setStatus(gbStream.isStatus()?1:0);  
139 - deviceChannel.setStatus(1);  
140 - deviceChannel.setParentId(gbStream.getCatalogId());  
141 - deviceChannel.setRegisterWay(1);  
142 - if (gbStream.getCatalogId() != null && gbStream.getCatalogId().length() < 10) {  
143 - deviceChannel.setCivilCode(gbStream.getCatalogId());  
144 - }else {  
145 - deviceChannel.setCivilCode(parentPlatform.getAdministrativeDivision());  
146 - }  
147 - deviceChannel.setModel("live");  
148 - deviceChannel.setOwner("wvp-pro");  
149 - deviceChannel.setParental(0);  
150 - deviceChannel.setSecrecy("0");  
151 - allChannels.add(deviceChannel);  
152 - } 90 + allChannels.addAll(gbStreams);
153 } 91 }
154 if (allChannels.size() > 0) { 92 if (allChannels.size() > 0) {
155 cmderFroPlatform.catalogQuery(allChannels, parentPlatform, sn, fromHeader.getTag()); 93 cmderFroPlatform.catalogQuery(allChannels, parentPlatform, sn, fromHeader.getTag());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java
@@ -44,7 +44,7 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp @@ -44,7 +44,7 @@ public class DeviceInfoQueryMessageHandler extends SIPRequestProcessorParent imp
44 44
45 @Override 45 @Override
46 public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) { 46 public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element rootElement) {
47 - logger.info("接收到DeviceInfo查询消息"); 47 + logger.info("[DeviceInfo查询]消息");
48 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); 48 FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
49 try { 49 try {
50 // 回复200 OK 50 // 回复200 OK
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java
@@ -111,6 +111,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -111,6 +111,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
111 int sumNum = Integer.parseInt(sumNumElement.getText()); 111 int sumNum = Integer.parseInt(sumNumElement.getText());
112 112
113 if (sumNum == 0) { 113 if (sumNum == 0) {
  114 + logger.info("[收到通道]设备:{}的: 0个", take.getDevice().getDeviceId());
114 // 数据已经完整接收 115 // 数据已经完整接收
115 storager.cleanChannelsForDevice(take.getDevice().getDeviceId()); 116 storager.cleanChannelsForDevice(take.getDevice().getDeviceId());
116 catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null); 117 catalogDataCatch.setChannelSyncEnd(take.getDevice().getDeviceId(), null);
@@ -125,18 +126,14 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @@ -125,18 +126,14 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp
125 if (channelDeviceElement == null) { 126 if (channelDeviceElement == null) {
126 continue; 127 continue;
127 } 128 }
128 - //by brewswang  
129 - // if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {//如果包含位置信息,就更新一下位置  
130 - // processNotifyMobilePosition(evt, itemDevice);  
131 - // }  
132 - DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device); 129 + DeviceChannel deviceChannel = XmlUtil.channelContentHander(itemDevice, device, null);
133 deviceChannel.setDeviceId(take.getDevice().getDeviceId()); 130 deviceChannel.setDeviceId(take.getDevice().getDeviceId());
134 131
135 channelList.add(deviceChannel); 132 channelList.add(deviceChannel);
136 } 133 }
137 int sn = Integer.parseInt(snElement.getText()); 134 int sn = Integer.parseInt(snElement.getText());
138 catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(), channelList); 135 catalogDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, take.getDevice(), channelList);
139 - logger.info("收到来自设备【{}】的通道: {}个,{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.get(take.getDevice().getDeviceId()) == null ? 0 :catalogDataCatch.get(take.getDevice().getDeviceId()).size(), sumNum); 136 + logger.info("[收到通道]设备: {} -> {}个,{}/{}", take.getDevice().getDeviceId(), channelList.size(), catalogDataCatch.get(take.getDevice().getDeviceId()) == null ? 0 :catalogDataCatch.get(take.getDevice().getDeviceId()).size(), sumNum);
140 if (catalogDataCatch.get(take.getDevice().getDeviceId()).size() == sumNum) { 137 if (catalogDataCatch.get(take.getDevice().getDeviceId()).size() == sumNum) {
141 // 数据已经完整接收 138 // 数据已经完整接收
142 boolean resetChannelsResult = storager.resetChannels(take.getDevice().getDeviceId(), catalogDataCatch.get(take.getDevice().getDeviceId())); 139 boolean resetChannelsResult = storager.resetChannels(take.getDevice().getDeviceId(), catalogDataCatch.get(take.getDevice().getDeviceId()));
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java
@@ -87,7 +87,6 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -87,7 +87,6 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent
87 device.setStreamMode("UDP"); 87 device.setStreamMode("UDP");
88 } 88 }
89 deviceService.updateDevice(device); 89 deviceService.updateDevice(device);
90 -// storager.updateDevice(device);  
91 90
92 RequestMessage msg = new RequestMessage(); 91 RequestMessage msg = new RequestMessage();
93 msg.setKey(key); 92 msg.setKey(key);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java
@@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessag @@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessag
7 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; 7 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler;
8 import com.genersoft.iot.vmp.gb28181.utils.Coordtransform; 8 import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
9 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; 9 import com.genersoft.iot.vmp.gb28181.utils.NumericUtil;
  10 +import com.genersoft.iot.vmp.service.IDeviceChannelService;
10 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 11 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
11 import com.genersoft.iot.vmp.utils.DateUtil; 12 import com.genersoft.iot.vmp.utils.DateUtil;
12 import com.genersoft.iot.vmp.utils.GpsUtil; 13 import com.genersoft.iot.vmp.utils.GpsUtil;
@@ -42,6 +43,9 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar @@ -42,6 +43,9 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
42 @Autowired 43 @Autowired
43 private IVideoManagerStorage storager; 44 private IVideoManagerStorage storager;
44 45
  46 + @Autowired
  47 + private IDeviceChannelService deviceChannelService;
  48 +
45 @Override 49 @Override
46 public void afterPropertiesSet() throws Exception { 50 public void afterPropertiesSet() throws Exception {
47 responseMessageHandler.addHandler(cmdType, this); 51 responseMessageHandler.addHandler(cmdType, this);
@@ -79,38 +83,25 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar @@ -79,38 +83,25 @@ public class MobilePositionResponseMessageHandler extends SIPRequestProcessorPar
79 mobilePosition.setAltitude(0.0); 83 mobilePosition.setAltitude(0.0);
80 } 84 }
81 mobilePosition.setReportSource("Mobile Position"); 85 mobilePosition.setReportSource("Mobile Position");
82 - if ("WGS84".equals(device.getGeoCoordSys())) {  
83 - mobilePosition.setLongitudeWgs84(mobilePosition.getLongitude());  
84 - mobilePosition.setLatitudeWgs84(mobilePosition.getLatitude());  
85 - Double[] position = Coordtransform.WGS84ToGCJ02(mobilePosition.getLongitude(), mobilePosition.getLatitude());  
86 - mobilePosition.setLongitudeGcj02(position[0]);  
87 - mobilePosition.setLatitudeGcj02(position[1]);  
88 - }else if ("GCJ02".equals(device.getGeoCoordSys())) {  
89 - mobilePosition.setLongitudeGcj02(mobilePosition.getLongitude());  
90 - mobilePosition.setLatitudeGcj02(mobilePosition.getLatitude());  
91 - Double[] position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());  
92 - mobilePosition.setLongitudeWgs84(position[0]);  
93 - mobilePosition.setLatitudeWgs84(position[1]);  
94 - }else {  
95 - mobilePosition.setLongitudeGcj02(0.00);  
96 - mobilePosition.setLatitudeGcj02(0.00);  
97 - mobilePosition.setLongitudeWgs84(0.00);  
98 - mobilePosition.setLatitudeWgs84(0.00);  
99 - }  
100 - if (userSetting.getSavePositionHistory()) {  
101 - storager.insertMobilePosition(mobilePosition);  
102 - } 86 +
103 // 更新device channel 的经纬度 87 // 更新device channel 的经纬度
104 DeviceChannel deviceChannel = new DeviceChannel(); 88 DeviceChannel deviceChannel = new DeviceChannel();
105 deviceChannel.setDeviceId(device.getDeviceId()); 89 deviceChannel.setDeviceId(device.getDeviceId());
106 deviceChannel.setChannelId(mobilePosition.getChannelId()); 90 deviceChannel.setChannelId(mobilePosition.getChannelId());
107 deviceChannel.setLongitude(mobilePosition.getLongitude()); 91 deviceChannel.setLongitude(mobilePosition.getLongitude());
108 deviceChannel.setLatitude(mobilePosition.getLatitude()); 92 deviceChannel.setLatitude(mobilePosition.getLatitude());
109 - deviceChannel.setLongitudeWgs84(mobilePosition.getLongitudeWgs84());  
110 - deviceChannel.setLatitudeWgs84(mobilePosition.getLatitudeWgs84());  
111 - deviceChannel.setLongitudeGcj02(mobilePosition.getLongitudeGcj02());  
112 - deviceChannel.setLatitudeGcj02(mobilePosition.getLatitudeGcj02());  
113 deviceChannel.setGpsTime(mobilePosition.getTime()); 93 deviceChannel.setGpsTime(mobilePosition.getTime());
  94 +
  95 + deviceChannel = deviceChannelService.updateGps(deviceChannel, device);
  96 +
  97 + mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84());
  98 + mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84());
  99 + mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02());
  100 + mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02());
  101 +
  102 + if (userSetting.getSavePositionHistory()) {
  103 + storager.insertMobilePosition(mobilePosition);
  104 + }
114 storager.updateChannelPosition(deviceChannel); 105 storager.updateChannelPosition(deviceChannel);
115 //回复 200 OK 106 //回复 200 OK
116 responseAck(evt, Response.OK); 107 responseAck(evt, Response.OK);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java
@@ -26,7 +26,7 @@ import javax.sip.message.Response; @@ -26,7 +26,7 @@ import javax.sip.message.Response;
26 @Component 26 @Component
27 public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { 27 public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
28 28
29 - private Logger logger = LoggerFactory.getLogger(RegisterResponseProcessor.class); 29 + private final Logger logger = LoggerFactory.getLogger(RegisterResponseProcessor.class);
30 private final String method = "REGISTER"; 30 private final String method = "REGISTER";
31 31
32 @Autowired 32 @Autowired
@@ -69,11 +69,11 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { @@ -69,11 +69,11 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
69 69
70 ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(platformGBId); 70 ParentPlatformCatch parentPlatformCatch = redisCatchStorage.queryPlatformCatchInfo(platformGBId);
71 if (parentPlatformCatch == null) { 71 if (parentPlatformCatch == null) {
72 - logger.warn(String.format("收到 %s 的注册/注销%S请求, 但是平台缓存信息未查询到!!!", platformGBId, response.getStatusCode())); 72 + logger.warn(String.format("[收到注册/注销%S请求]平台:%s,但是平台缓存信息未查询到!!!", response.getStatusCode(),platformGBId));
73 return; 73 return;
74 } 74 }
75 String action = parentPlatformCatch.getParentPlatform().getExpires().equals("0") ? "注销" : "注册"; 75 String action = parentPlatformCatch.getParentPlatform().getExpires().equals("0") ? "注销" : "注册";
76 - logger.info(String.format("收到 %s %s的%S响应", platformGBId, action, response.getStatusCode() )); 76 + logger.info(String.format("[%s %S响应]%s ", action, response.getStatusCode(), platformGBId ));
77 ParentPlatform parentPlatform = parentPlatformCatch.getParentPlatform(); 77 ParentPlatform parentPlatform = parentPlatformCatch.getParentPlatform();
78 if (parentPlatform == null) { 78 if (parentPlatform == null) {
79 logger.warn(String.format("收到 %s %s的%S请求, 但是平台信息未查询到!!!", platformGBId, action, response.getStatusCode())); 79 logger.warn(String.format("收到 %s %s的%S请求, 但是平台信息未查询到!!!", platformGBId, action, response.getStatusCode()));
src/main/java/com/genersoft/iot/vmp/gb28181/utils/SipUtils.java
@@ -23,9 +23,10 @@ public class SipUtils { @@ -23,9 +23,10 @@ public class SipUtils {
23 /** 23 /**
24 * 从subject读取channelId 24 * 从subject读取channelId
25 * */ 25 * */
26 - public static String getChannelIdFromHeader(Request request) { 26 + public static String getChannelIdFromRequest(Request request) {
27 Header subject = request.getHeader("subject"); 27 Header subject = request.getHeader("subject");
28 if (subject == null) { 28 if (subject == null) {
  29 + // 如果缺失subject
29 return null; 30 return null;
30 } 31 }
31 return ((Subject) subject).getSubject().split(":")[0]; 32 return ((Subject) subject).getSubject().split(":")[0];
src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
@@ -4,6 +4,8 @@ import com.alibaba.fastjson.JSONArray; @@ -4,6 +4,8 @@ import com.alibaba.fastjson.JSONArray;
4 import com.alibaba.fastjson.JSONObject; 4 import com.alibaba.fastjson.JSONObject;
5 import com.genersoft.iot.vmp.gb28181.bean.Device; 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; 6 import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  7 +import com.genersoft.iot.vmp.gb28181.bean.TreeType;
  8 +import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
7 import com.genersoft.iot.vmp.utils.DateUtil; 9 import com.genersoft.iot.vmp.utils.DateUtil;
8 import org.dom4j.Attribute; 10 import org.dom4j.Attribute;
9 import org.dom4j.Document; 11 import org.dom4j.Document;
@@ -29,7 +31,7 @@ public class XmlUtil { @@ -29,7 +31,7 @@ public class XmlUtil {
29 /** 31 /**
30 * 日志服务 32 * 日志服务
31 */ 33 */
32 - private static Logger LOG = LoggerFactory.getLogger(XmlUtil.class); 34 + private static Logger logger = LoggerFactory.getLogger(XmlUtil.class);
33 35
34 /** 36 /**
35 * 解析XML为Document对象 37 * 解析XML为Document对象
@@ -46,7 +48,7 @@ public class XmlUtil { @@ -46,7 +48,7 @@ public class XmlUtil {
46 try { 48 try {
47 document = saxReader.read(sr); 49 document = saxReader.read(sr);
48 } catch (DocumentException e) { 50 } catch (DocumentException e) {
49 - LOG.error("解析失败", e); 51 + logger.error("解析失败", e);
50 } 52 }
51 return null == document ? null : document.getRootElement(); 53 return null == document ? null : document.getRootElement();
52 } 54 }
@@ -182,47 +184,69 @@ public class XmlUtil { @@ -182,47 +184,69 @@ public class XmlUtil {
182 return xml.getRootElement(); 184 return xml.getRootElement();
183 } 185 }
184 186
185 - public static DeviceChannel channelContentHander(Element itemDevice, Device device){  
186 - Element channdelNameElement = itemDevice.element("Name");  
187 - String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim().toString() : "";  
188 - Element statusElement = itemDevice.element("Status");  
189 - String status = statusElement != null ? statusElement.getTextTrim().toString() : "ON"; 187 + private enum ChannelType{
  188 + CivilCode, BusinessGroup,VirtualOrganization,Other
  189 + }
  190 +
  191 + public static DeviceChannel channelContentHander(Element itemDevice, Device device, String event){
190 DeviceChannel deviceChannel = new DeviceChannel(); 192 DeviceChannel deviceChannel = new DeviceChannel();
191 - deviceChannel.setName(channelName); 193 + deviceChannel.setDeviceId(device.getDeviceId());
192 Element channdelIdElement = itemDevice.element("DeviceID"); 194 Element channdelIdElement = itemDevice.element("DeviceID");
193 - String channelId = channdelIdElement != null ? channdelIdElement.getTextTrim().toString() : ""; 195 + if (channdelIdElement == null) {
  196 + logger.warn("解析Catalog消息时发现缺少 DeviceID");
  197 + return null;
  198 + }
  199 + String channelId = channdelIdElement.getTextTrim();
  200 + if (StringUtils.isEmpty(channelId)) {
  201 + logger.warn("解析Catalog消息时发现缺少 DeviceID");
  202 + return null;
  203 + }
194 deviceChannel.setChannelId(channelId); 204 deviceChannel.setChannelId(channelId);
195 - // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理  
196 - if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) {  
197 - deviceChannel.setStatus(1); 205 + if (event != null && !event.equals(CatalogEvent.ADD) && !event.equals(CatalogEvent.UPDATE)) {
  206 + // 除了ADD和update情况下需要识别全部内容,
  207 + return deviceChannel;
198 } 208 }
199 - if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {  
200 - deviceChannel.setStatus(0); 209 +
  210 + ChannelType channelType = ChannelType.Other;
  211 + if (channelId.length() <= 8) {
  212 + channelType = ChannelType.CivilCode;
  213 + }else {
  214 + if (channelId.length() == 20) {
  215 + int code = Integer.parseInt(channelId.substring(10, 13));
  216 + switch (code){
  217 + case 215:
  218 + channelType = ChannelType.BusinessGroup;
  219 + break;
  220 + case 216:
  221 + channelType = ChannelType.VirtualOrganization;
  222 + break;
  223 + default:
  224 + break;
  225 +
  226 + }
  227 + }
201 } 228 }
202 229
203 - deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));  
204 - deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));  
205 - deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));  
206 - deviceChannel.setCivilCode(XmlUtil.getText(itemDevice, "CivilCode"));  
207 - deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));  
208 - deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));  
209 - String businessGroupID = XmlUtil.getText(itemDevice, "BusinessGroupID");  
210 - if (XmlUtil.getText(itemDevice, "Parental") == null  
211 - || XmlUtil.getText(itemDevice, "Parental").equals("")) {  
212 - if (deviceChannel.getChannelId().length() <= 10  
213 - || (deviceChannel.getChannelId().length() == 20 && (  
214 - Integer.parseInt(deviceChannel.getChannelId().substring(10, 13)) == 215  
215 - || Integer.parseInt(deviceChannel.getChannelId().substring(10, 13)) == 216  
216 - )  
217 - )  
218 - ) {  
219 - deviceChannel.setParental(1);  
220 - }else {  
221 - deviceChannel.setParental(0); 230 + Element channdelNameElement = itemDevice.element("Name");
  231 + String channelName = channdelNameElement != null ? channdelNameElement.getTextTrim() : "";
  232 + deviceChannel.setName(channelName);
  233 +
  234 + String civilCode = XmlUtil.getText(itemDevice, "CivilCode");
  235 + deviceChannel.setCivilCode(civilCode);
  236 + if (channelType == ChannelType.CivilCode && civilCode == null) {
  237 + deviceChannel.setParental(1);
  238 + // 行政区划如果没有传递具体值,则推测一个
  239 + if (channelId.length() > 2) {
  240 + deviceChannel.setCivilCode(channelId.substring(0, channelId.length() - 2));
222 } 241 }
223 - } else {  
224 - // 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1  
225 - deviceChannel.setParental(Integer.parseInt(XmlUtil.getText(itemDevice, "Parental")) == 1?1:0); 242 + }
  243 + if (channelType.equals(ChannelType.CivilCode)) {
  244 + // 行政区划其他字段没必要识别了,默认在线即可
  245 + deviceChannel.setStatus(1);
  246 + deviceChannel.setParental(1);
  247 + deviceChannel.setCreateTime(DateUtil.getNow());
  248 + deviceChannel.setUpdateTime(DateUtil.getNow());
  249 + return deviceChannel;
226 } 250 }
227 /** 251 /**
228 * 行政区划展示设备树与业务分组展示设备树是两种不同的模式 252 * 行政区划展示设备树与业务分组展示设备树是两种不同的模式
@@ -230,7 +254,17 @@ public class XmlUtil { @@ -230,7 +254,17 @@ public class XmlUtil {
230 * 河北省 254 * 河北省
231 * --> 石家庄市 255 * --> 石家庄市
232 * --> 摄像头 256 * --> 摄像头
233 - * --> 正定县 257 + *String parentId = XmlUtil.getText(itemDevice, "ParentID");
  258 + if (parentId != null) {
  259 + if (parentId.contains("/")) {
  260 + String lastParentId = parentId.substring(parentId.lastIndexOf("/") + 1);
  261 + String businessGroup = parentId.substring(0, parentId.indexOf("/"));
  262 + deviceChannel.setParentId(lastParentId);
  263 + }else {
  264 + deviceChannel.setParentId(parentId);
  265 + }
  266 + }
  267 + deviceCh --> 正定县
234 * --> 摄像头 268 * --> 摄像头
235 * --> 摄像头 269 * --> 摄像头
236 * 270 *
@@ -243,59 +277,88 @@ public class XmlUtil { @@ -243,59 +277,88 @@ public class XmlUtil {
243 * --> 摄像头 277 * --> 摄像头
244 */ 278 */
245 String parentId = XmlUtil.getText(itemDevice, "ParentID"); 279 String parentId = XmlUtil.getText(itemDevice, "ParentID");
  280 + String businessGroupID = XmlUtil.getText(itemDevice, "BusinessGroupID");
246 if (parentId != null) { 281 if (parentId != null) {
247 if (parentId.contains("/")) { 282 if (parentId.contains("/")) {
248 String lastParentId = parentId.substring(parentId.lastIndexOf("/") + 1); 283 String lastParentId = parentId.substring(parentId.lastIndexOf("/") + 1);
  284 + if (businessGroupID == null) {
  285 + businessGroupID = parentId.substring(0, parentId.indexOf("/"));
  286 + }
249 deviceChannel.setParentId(lastParentId); 287 deviceChannel.setParentId(lastParentId);
250 }else { 288 }else {
251 deviceChannel.setParentId(parentId); 289 deviceChannel.setParentId(parentId);
252 } 290 }
253 } 291 }
254 deviceChannel.setBusinessGroupId(businessGroupID); 292 deviceChannel.setBusinessGroupId(businessGroupID);
  293 + if (channelType.equals(ChannelType.BusinessGroup) || channelType.equals(ChannelType.VirtualOrganization)) {
  294 + // 业务分组和虚拟组织 其他字段没必要识别了,默认在线即可
  295 + deviceChannel.setStatus(1);
  296 + deviceChannel.setParental(1);
  297 + deviceChannel.setCreateTime(DateUtil.getNow());
  298 + deviceChannel.setUpdateTime(DateUtil.getNow());
  299 + return deviceChannel;
  300 + }
255 301
256 -// else {  
257 -// if (deviceChannel.getChannelId().length() <= 10) { // 此时为行政区划, 上下级行政区划使用DeviceId关联  
258 -// deviceChannel.setParentId(deviceChannel.getChannelId().substring(0, deviceChannel.getChannelId().length() - 2));  
259 -// }else if (deviceChannel.getChannelId().length() == 20) {  
260 -// if (Integer.parseInt(deviceChannel.getChannelId().substring(10, 13)) == 216) { // 虚拟组织  
261 -// deviceChannel.setBusinessGroupId(businessGroupID);  
262 -// }else if (Integer.parseInt(device.getDeviceId().substring(10, 13) )== 118) {//NVR 如果上级设备编号是NVR则直接将NVR的编号设置给通道的上级编号  
263 -// deviceChannel.setParentId(device.getDeviceId());  
264 -// }else if (deviceChannel.getCivilCode() != null) {  
265 -// // 设备, 无parentId的20位是使用CivilCode表示上级的设备,  
266 -// // 注:215 业务分组是需要有parentId的  
267 -// deviceChannel.setParentId(deviceChannel.getCivilCode());  
268 -// }  
269 -// }else {  
270 -// deviceChannel.setParentId(deviceChannel.getDeviceId());  
271 -// }  
272 -// }  
273 -  
274 - if (XmlUtil.getText(itemDevice, "SafetyWay") == null  
275 - || XmlUtil.getText(itemDevice, "SafetyWay") == "") { 302 + Element statusElement = itemDevice.element("Status");
  303 +
  304 + if (statusElement != null) {
  305 + String status = statusElement.getTextTrim().trim();
  306 + // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理
  307 + if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) {
  308 + deviceChannel.setStatus(1);
  309 + }
  310 + if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) {
  311 + deviceChannel.setStatus(0);
  312 + }
  313 + }else {
  314 + deviceChannel.setStatus(1);
  315 + }
  316 + // 识别自带的目录标识
  317 + String parental = XmlUtil.getText(itemDevice, "Parental");
  318 + // 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1
  319 + if (!StringUtils.isEmpty(parental) && parental.length() == 1 && Integer.parseInt(parental) == 0) {
  320 + deviceChannel.setParental(0);
  321 + }else {
  322 + deviceChannel.setParental(1);
  323 + }
  324 +
  325 +
  326 + deviceChannel.setManufacture(XmlUtil.getText(itemDevice, "Manufacturer"));
  327 + deviceChannel.setModel(XmlUtil.getText(itemDevice, "Model"));
  328 + deviceChannel.setOwner(XmlUtil.getText(itemDevice, "Owner"));
  329 + deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum"));
  330 + deviceChannel.setBlock(XmlUtil.getText(itemDevice, "Block"));
  331 + deviceChannel.setAddress(XmlUtil.getText(itemDevice, "Address"));
  332 + deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));
  333 +
  334 + String safetyWay = XmlUtil.getText(itemDevice, "SafetyWay");
  335 + if (StringUtils.isEmpty(safetyWay)) {
276 deviceChannel.setSafetyWay(0); 336 deviceChannel.setSafetyWay(0);
277 } else { 337 } else {
278 - deviceChannel.setSafetyWay(Integer.parseInt(XmlUtil.getText(itemDevice, "SafetyWay"))); 338 + deviceChannel.setSafetyWay(Integer.parseInt(safetyWay));
279 } 339 }
280 - if (XmlUtil.getText(itemDevice, "RegisterWay") == null  
281 - || XmlUtil.getText(itemDevice, "RegisterWay") == "") { 340 +
  341 + String registerWay = XmlUtil.getText(itemDevice, "RegisterWay");
  342 + if (StringUtils.isEmpty(registerWay)) {
282 deviceChannel.setRegisterWay(1); 343 deviceChannel.setRegisterWay(1);
283 } else { 344 } else {
284 - deviceChannel.setRegisterWay(Integer.parseInt(XmlUtil.getText(itemDevice, "RegisterWay"))); 345 + deviceChannel.setRegisterWay(Integer.parseInt(registerWay));
285 } 346 }
286 - deviceChannel.setCertNum(XmlUtil.getText(itemDevice, "CertNum")); 347 +
287 if (XmlUtil.getText(itemDevice, "Certifiable") == null 348 if (XmlUtil.getText(itemDevice, "Certifiable") == null
288 || XmlUtil.getText(itemDevice, "Certifiable") == "") { 349 || XmlUtil.getText(itemDevice, "Certifiable") == "") {
289 deviceChannel.setCertifiable(0); 350 deviceChannel.setCertifiable(0);
290 } else { 351 } else {
291 deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable"))); 352 deviceChannel.setCertifiable(Integer.parseInt(XmlUtil.getText(itemDevice, "Certifiable")));
292 } 353 }
  354 +
293 if (XmlUtil.getText(itemDevice, "ErrCode") == null 355 if (XmlUtil.getText(itemDevice, "ErrCode") == null
294 || XmlUtil.getText(itemDevice, "ErrCode") == "") { 356 || XmlUtil.getText(itemDevice, "ErrCode") == "") {
295 deviceChannel.setErrCode(0); 357 deviceChannel.setErrCode(0);
296 } else { 358 } else {
297 deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode"))); 359 deviceChannel.setErrCode(Integer.parseInt(XmlUtil.getText(itemDevice, "ErrCode")));
298 } 360 }
  361 +
299 deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime")); 362 deviceChannel.setEndTime(XmlUtil.getText(itemDevice, "EndTime"));
300 deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy")); 363 deviceChannel.setSecrecy(XmlUtil.getText(itemDevice, "Secrecy"));
301 deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress")); 364 deviceChannel.setIpAddress(XmlUtil.getText(itemDevice, "IPAddress"));
@@ -304,43 +367,23 @@ public class XmlUtil { @@ -304,43 +367,23 @@ public class XmlUtil {
304 } else { 367 } else {
305 deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port"))); 368 deviceChannel.setPort(Integer.parseInt(XmlUtil.getText(itemDevice, "Port")));
306 } 369 }
307 - deviceChannel.setPassword(XmlUtil.getText(itemDevice, "Password"));  
308 - if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Longitude"))) {  
309 - deviceChannel.setLongitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Longitude"))); 370 +
  371 +
  372 + String longitude = XmlUtil.getText(itemDevice, "Longitude");
  373 + if (NumericUtil.isDouble(longitude)) {
  374 + deviceChannel.setLongitude(Double.parseDouble(longitude));
310 } else { 375 } else {
311 deviceChannel.setLongitude(0.00); 376 deviceChannel.setLongitude(0.00);
312 } 377 }
313 - if (NumericUtil.isDouble(XmlUtil.getText(itemDevice, "Latitude"))) {  
314 - deviceChannel.setLatitude(Double.parseDouble(XmlUtil.getText(itemDevice, "Latitude"))); 378 + String latitude = XmlUtil.getText(itemDevice, "Latitude");
  379 + if (NumericUtil.isDouble(latitude)) {
  380 + deviceChannel.setLatitude(Double.parseDouble(latitude));
315 } else { 381 } else {
316 deviceChannel.setLatitude(0.00); 382 deviceChannel.setLatitude(0.00);
317 } 383 }
318 deviceChannel.setGpsTime(DateUtil.getNow()); 384 deviceChannel.setGpsTime(DateUtil.getNow());
319 - if (deviceChannel.getLongitude()*deviceChannel.getLatitude() > 0) {  
320 - if ("WGS84".equals(device.getGeoCoordSys())) {  
321 - deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());  
322 - deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());  
323 - Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude());  
324 - deviceChannel.setLongitudeGcj02(position[0]);  
325 - deviceChannel.setLatitudeGcj02(position[1]);  
326 - }else if ("GCJ02".equals(device.getGeoCoordSys())) {  
327 - deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());  
328 - deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());  
329 - Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude());  
330 - deviceChannel.setLongitudeWgs84(position[0]);  
331 - deviceChannel.setLatitudeWgs84(position[1]);  
332 - }else {  
333 - deviceChannel.setLongitudeGcj02(0.00);  
334 - deviceChannel.setLatitudeGcj02(0.00);  
335 - deviceChannel.setLongitudeWgs84(0.00);  
336 - deviceChannel.setLatitudeWgs84(0.00);  
337 - }  
338 - }else {  
339 - deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());  
340 - deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());  
341 - deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());  
342 - deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());  
343 - } 385 +
  386 +
344 if (XmlUtil.getText(itemDevice, "PTZType") == null || "".equals(XmlUtil.getText(itemDevice, "PTZType"))) { 387 if (XmlUtil.getText(itemDevice, "PTZType") == null || "".equals(XmlUtil.getText(itemDevice, "PTZType"))) {
345 //兼容INFO中的信息 388 //兼容INFO中的信息
346 Element info = itemDevice.element("Info"); 389 Element info = itemDevice.element("Info");
src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java
@@ -136,4 +136,12 @@ public class AssistRESTfulUtils { @@ -136,4 +136,12 @@ public class AssistRESTfulUtils {
136 return sendGet(mediaServerItem, "api/record/file/duration",param, callback); 136 return sendGet(mediaServerItem, "api/record/file/duration",param, callback);
137 } 137 }
138 138
  139 + public JSONObject addStreamCallInfo(MediaServerItem mediaServerItem, String app, String stream, String callId, RequestCallback callback){
  140 + Map<String, Object> param = new HashMap<>();
  141 + param.put("app",app);
  142 + param.put("stream",stream);
  143 + param.put("callId",callId);
  144 + return sendGet(mediaServerItem, "api/record/addStreamCallInfo",param, callback);
  145 + }
  146 +
139 } 147 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -87,6 +87,9 @@ public class ZLMHttpHookListener { @@ -87,6 +87,9 @@ public class ZLMHttpHookListener {
87 @Autowired 87 @Autowired
88 private VideoStreamSessionManager sessionManager; 88 private VideoStreamSessionManager sessionManager;
89 89
  90 + @Autowired
  91 + private AssistRESTfulUtils assistRESTfulUtils;
  92 +
90 /** 93 /**
91 * 服务器定时上报时间,上报间隔可配置,默认10s上报一次 94 * 服务器定时上报时间,上报间隔可配置,默认10s上报一次
92 * 95 *
@@ -99,12 +102,13 @@ public class ZLMHttpHookListener { @@ -99,12 +102,13 @@ public class ZLMHttpHookListener {
99 logger.debug("[ ZLM HOOK ] on_server_keepalive API调用,参数:" + json.toString()); 102 logger.debug("[ ZLM HOOK ] on_server_keepalive API调用,参数:" + json.toString());
100 } 103 }
101 String mediaServerId = json.getString("mediaServerId"); 104 String mediaServerId = json.getString("mediaServerId");
102 - List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(ZLMHttpHookSubscribe.HookType.on_server_keepalive); 105 + List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive);
103 if (subscribes != null && subscribes.size() > 0) { 106 if (subscribes != null && subscribes.size() > 0) {
104 for (ZLMHttpHookSubscribe.Event subscribe : subscribes) { 107 for (ZLMHttpHookSubscribe.Event subscribe : subscribes) {
105 subscribe.response(null, json); 108 subscribe.response(null, json);
106 } 109 }
107 } 110 }
  111 + mediaServerService.updateMediaServerKeepalive(mediaServerId, json.getJSONObject("data"));
108 112
109 JSONObject ret = new JSONObject(); 113 JSONObject ret = new JSONObject();
110 ret.put("code", 0); 114 ret.put("code", 0);
@@ -164,7 +168,7 @@ public class ZLMHttpHookListener { @@ -164,7 +168,7 @@ public class ZLMHttpHookListener {
164 logger.debug("[ ZLM HOOK ]on_play API调用,参数:" + JSON.toJSONString(param)); 168 logger.debug("[ ZLM HOOK ]on_play API调用,参数:" + JSON.toJSONString(param));
165 } 169 }
166 String mediaServerId = param.getMediaServerId(); 170 String mediaServerId = param.getMediaServerId();
167 - ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_play, json); 171 + ZLMHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_play, json);
168 if (subscribe != null ) { 172 if (subscribe != null ) {
169 MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); 173 MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
170 if (mediaInfo != null) { 174 if (mediaInfo != null) {
@@ -200,7 +204,9 @@ public class ZLMHttpHookListener { @@ -200,7 +204,9 @@ public class ZLMHttpHookListener {
200 204
201 logger.info("[ ZLM HOOK ]on_publish API调用,参数:" + json.toString()); 205 logger.info("[ ZLM HOOK ]on_publish API调用,参数:" + json.toString());
202 JSONObject ret = new JSONObject(); 206 JSONObject ret = new JSONObject();
203 - if (!"rtp".equals(param.getApp()) && !"broadcast".equals(param.getApp())) { 207 + String mediaServerId = json.getString("mediaServerId");
  208 + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
  209 + if (!"rtp".equals(param.getApp())) {
204 // 推流鉴权 210 // 推流鉴权
205 if (param.getParams() == null) { 211 if (param.getParams() == null) {
206 logger.info("推流鉴权失败: 缺少不要参数:sign=md5(user表的pushKey)"); 212 logger.info("推流鉴权失败: 缺少不要参数:sign=md5(user表的pushKey)");
@@ -231,6 +237,12 @@ public class ZLMHttpHookListener { @@ -231,6 +237,12 @@ public class ZLMHttpHookListener {
231 streamAuthorityInfo.setSign(sign); 237 streamAuthorityInfo.setSign(sign);
232 // 鉴权通过 238 // 鉴权通过
233 redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo); 239 redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo);
  240 + // 通知assist新的callId
  241 + if (mediaInfo != null) {
  242 + assistRESTfulUtils.addStreamCallInfo(mediaInfo, param.getApp(), param.getStream(), callId, null);
  243 + }
  244 + }else {
  245 + zlmMediaListManager.sendStreamEvent(param.getApp(),param.getStream(), param.getMediaServerId());
234 } 246 }
235 247
236 ret.put("code", 0); 248 ret.put("code", 0);
@@ -240,10 +252,9 @@ public class ZLMHttpHookListener { @@ -240,10 +252,9 @@ public class ZLMHttpHookListener {
240 ret.put("enable_audio", true); 252 ret.put("enable_audio", true);
241 } 253 }
242 254
243 - String mediaServerId = json.getString("mediaServerId");  
244 - ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json); 255 +
  256 + ZLMHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json);
245 if (subscribe != null) { 257 if (subscribe != null) {
246 - MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);  
247 if (mediaInfo != null) { 258 if (mediaInfo != null) {
248 subscribe.response(mediaInfo, json); 259 subscribe.response(mediaInfo, json);
249 }else { 260 }else {
@@ -270,10 +281,12 @@ public class ZLMHttpHookListener { @@ -270,10 +281,12 @@ public class ZLMHttpHookListener {
270 ret.put("mp4_max_second", 10); 281 ret.put("mp4_max_second", 10);
271 ret.put("enable_mp4", true); 282 ret.put("enable_mp4", true);
272 ret.put("enable_audio", true); 283 ret.put("enable_audio", true);
  284 +
273 } 285 }
274 } 286 }
275 287
276 288
  289 +
277 return new ResponseEntity<String>(ret.toString(), HttpStatus.OK); 290 return new ResponseEntity<String>(ret.toString(), HttpStatus.OK);
278 } 291 }
279 292
@@ -364,7 +377,7 @@ public class ZLMHttpHookListener { @@ -364,7 +377,7 @@ public class ZLMHttpHookListener {
364 logger.debug("[ ZLM HOOK ]on_shell_login API调用,参数:" + json.toString()); 377 logger.debug("[ ZLM HOOK ]on_shell_login API调用,参数:" + json.toString());
365 } 378 }
366 String mediaServerId = json.getString("mediaServerId"); 379 String mediaServerId = json.getString("mediaServerId");
367 - ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_shell_login, json); 380 + ZLMHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_shell_login, json);
368 if (subscribe != null ) { 381 if (subscribe != null ) {
369 MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); 382 MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
370 if (mediaInfo != null) { 383 if (mediaInfo != null) {
@@ -390,7 +403,7 @@ public class ZLMHttpHookListener { @@ -390,7 +403,7 @@ public class ZLMHttpHookListener {
390 logger.info("[ ZLM HOOK ]on_stream_changed API调用,参数:" + JSONObject.toJSONString(item)); 403 logger.info("[ ZLM HOOK ]on_stream_changed API调用,参数:" + JSONObject.toJSONString(item));
391 String mediaServerId = item.getMediaServerId(); 404 String mediaServerId = item.getMediaServerId();
392 JSONObject json = (JSONObject) JSON.toJSON(item); 405 JSONObject json = (JSONObject) JSON.toJSON(item);
393 - ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, json); 406 + ZLMHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json);
394 if (subscribe != null ) { 407 if (subscribe != null ) {
395 MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); 408 MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);
396 if (mediaInfo != null) { 409 if (mediaInfo != null) {
@@ -438,7 +451,6 @@ public class ZLMHttpHookListener { @@ -438,7 +451,6 @@ public class ZLMHttpHookListener {
438 redisCatchStorage.stopPlayback(streamInfo.getDeviceID(), streamInfo.getChannelId(), 451 redisCatchStorage.stopPlayback(streamInfo.getDeviceID(), streamInfo.getChannelId(),
439 streamInfo.getStream(), null); 452 streamInfo.getStream(), null);
440 } 453 }
441 -  
442 } 454 }
443 }else { 455 }else {
444 if (!"rtp".equals(app)){ 456 if (!"rtp".equals(app)){
@@ -451,7 +463,6 @@ public class ZLMHttpHookListener { @@ -451,7 +463,6 @@ public class ZLMHttpHookListener {
451 StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, 463 StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem,
452 app, stream, tracks, streamAuthorityInfo.getCallId()); 464 app, stream, tracks, streamAuthorityInfo.getCallId());
453 item.setStreamInfo(streamInfoByAppAndStream); 465 item.setStreamInfo(streamInfoByAppAndStream);
454 -  
455 redisCatchStorage.addStream(mediaServerItem, type, app, stream, item); 466 redisCatchStorage.addStream(mediaServerItem, type, app, stream, item);
456 if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal() 467 if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
457 || item.getOriginType() == OriginType.RTMP_PUSH.ordinal() 468 || item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
@@ -459,20 +470,6 @@ public class ZLMHttpHookListener { @@ -459,20 +470,6 @@ public class ZLMHttpHookListener {
459 item.setSeverId(userSetting.getServerId()); 470 item.setSeverId(userSetting.getServerId());
460 zlmMediaListManager.addPush(item); 471 zlmMediaListManager.addPush(item);
461 } 472 }
462 -  
463 -// List<GbStream> gbStreams = new ArrayList<>();  
464 -// if (streamPushItem == null || streamPushItem.getGbId() == null) {  
465 -// GbStream gbStream = storager.getGbStream(app, streamId);  
466 -// gbStreams.add(gbStream);  
467 -// }else {  
468 -// if (streamPushItem.getGbId() != null) {  
469 -// gbStreams.add(streamPushItem);  
470 -// }  
471 -// }  
472 -// if (gbStreams.size() > 0) {  
473 -// eventPublisher.catalogEventPublishForStream(null, gbStreams, CatalogEvent.ON);  
474 -// }  
475 -  
476 }else { 473 }else {
477 // 兼容流注销时类型从redis记录获取 474 // 兼容流注销时类型从redis记录获取
478 MediaItem mediaItem = redisCatchStorage.getStreamInfo(app, stream, mediaServerId); 475 MediaItem mediaItem = redisCatchStorage.getStreamInfo(app, stream, mediaServerId);
@@ -616,16 +613,21 @@ public class ZLMHttpHookListener { @@ -616,16 +613,21 @@ public class ZLMHttpHookListener {
616 } 613 }
617 String remoteAddr = request.getRemoteAddr(); 614 String remoteAddr = request.getRemoteAddr();
618 jsonObject.put("ip", remoteAddr); 615 jsonObject.put("ip", remoteAddr);
619 - List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(ZLMHttpHookSubscribe.HookType.on_server_started); 616 + List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_started);
620 if (subscribes != null && subscribes.size() > 0) { 617 if (subscribes != null && subscribes.size() > 0) {
621 for (ZLMHttpHookSubscribe.Event subscribe : subscribes) { 618 for (ZLMHttpHookSubscribe.Event subscribe : subscribes) {
622 subscribe.response(null, jsonObject); 619 subscribe.response(null, jsonObject);
623 } 620 }
624 } 621 }
  622 +
  623 + ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(jsonObject, ZLMServerConfig.class);
  624 + if (zlmServerConfig !=null ) {
  625 + mediaServerService.zlmServerOnline(zlmServerConfig);
  626 + }
625 JSONObject ret = new JSONObject(); 627 JSONObject ret = new JSONObject();
626 ret.put("code", 0); 628 ret.put("code", 0);
627 ret.put("msg", "success"); 629 ret.put("msg", "success");
628 - return new ResponseEntity<String>(ret.toString(),HttpStatus.OK); 630 + return new ResponseEntity<>(ret.toString(),HttpStatus.OK);
629 } 631 }
630 632
631 private Map<String, String> urlParamToMap(String params) { 633 private Map<String, String> urlParamToMap(String params) {
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
1 package com.genersoft.iot.vmp.media.zlm; 1 package com.genersoft.iot.vmp.media.zlm;
2 2
3 import com.alibaba.fastjson.JSONObject; 3 import com.alibaba.fastjson.JSONObject;
  4 +import com.genersoft.iot.vmp.media.zlm.dto.HookType;
  5 +import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe;
4 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 6 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
5 import org.springframework.stereotype.Component; 7 import org.springframework.stereotype.Component;
6 import org.springframework.util.CollectionUtils; 8 import org.springframework.util.CollectionUtils;
7 9
  10 +import java.time.Instant;
8 import java.util.*; 11 import java.util.*;
9 import java.util.concurrent.ConcurrentHashMap; 12 import java.util.concurrent.ConcurrentHashMap;
  13 +import java.util.concurrent.TimeUnit;
10 14
11 /** 15 /**
12 * @description:针对 ZLMediaServer的hook事件订阅 16 * @description:针对 ZLMediaServer的hook事件订阅
@@ -16,51 +20,39 @@ import java.util.concurrent.ConcurrentHashMap; @@ -16,51 +20,39 @@ import java.util.concurrent.ConcurrentHashMap;
16 @Component 20 @Component
17 public class ZLMHttpHookSubscribe { 21 public class ZLMHttpHookSubscribe {
18 22
19 - public enum HookType{  
20 - on_flow_report,  
21 - on_http_access,  
22 - on_play,  
23 - on_publish,  
24 - on_record_mp4,  
25 - on_rtsp_auth,  
26 - on_rtsp_realm,  
27 - on_shell_login,  
28 - on_stream_changed,  
29 - on_stream_none_reader,  
30 - on_stream_not_found,  
31 - on_server_started,  
32 - on_server_keepalive  
33 - }  
34 -  
35 @FunctionalInterface 23 @FunctionalInterface
36 public interface Event{ 24 public interface Event{
37 void response(MediaServerItem mediaServerItem, JSONObject response); 25 void response(MediaServerItem mediaServerItem, JSONObject response);
38 } 26 }
39 27
40 - private Map<HookType, Map<JSONObject, ZLMHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>(); 28 + private Map<HookType, Map<IHookSubscribe, ZLMHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>();
41 29
42 - public void addSubscribe(HookType type, JSONObject hookResponse, ZLMHttpHookSubscribe.Event event) {  
43 - allSubscribes.computeIfAbsent(type, k -> new ConcurrentHashMap<>()).put(hookResponse, event); 30 + public void addSubscribe(IHookSubscribe hookSubscribe, ZLMHttpHookSubscribe.Event event) {
  31 + if (hookSubscribe.getExpires() == null) {
  32 + // 默认5分钟过期
  33 + Instant expiresInstant = Instant.now().plusSeconds(TimeUnit.MINUTES.toSeconds(5));
  34 + hookSubscribe.setExpires(expiresInstant);
  35 + }
  36 + allSubscribes.computeIfAbsent(hookSubscribe.getHookType(), k -> new ConcurrentHashMap<>()).put(hookSubscribe, event);
44 } 37 }
45 38
46 - public ZLMHttpHookSubscribe.Event getSubscribe(HookType type, JSONObject hookResponse) { 39 + public ZLMHttpHookSubscribe.Event sendNotify(HookType type, JSONObject hookResponse) {
47 ZLMHttpHookSubscribe.Event event= null; 40 ZLMHttpHookSubscribe.Event event= null;
48 - Map<JSONObject, Event> eventMap = allSubscribes.get(type); 41 + Map<IHookSubscribe, Event> eventMap = allSubscribes.get(type);
49 if (eventMap == null) { 42 if (eventMap == null) {
50 return null; 43 return null;
51 } 44 }
52 - for (JSONObject key : eventMap.keySet()) { 45 + for (IHookSubscribe key : eventMap.keySet()) {
53 Boolean result = null; 46 Boolean result = null;
54 - for (String s : key.keySet()) { 47 + for (String s : key.getContent().keySet()) {
55 if (result == null) { 48 if (result == null) {
56 - result = key.getString(s).equals(hookResponse.getString(s)); 49 + result = key.getContent().getString(s).equals(hookResponse.getString(s));
57 }else { 50 }else {
58 - if (key.getString(s) == null) { 51 + if (key.getContent().getString(s) == null) {
59 continue; 52 continue;
60 } 53 }
61 - result = result && key.getString(s).equals(hookResponse.getString(s)); 54 + result = result && key.getContent().getString(s).equals(hookResponse.getString(s));
62 } 55 }
63 -  
64 } 56 }
65 if (null != result && result) { 57 if (null != result && result) {
66 event = eventMap.get(key); 58 event = eventMap.get(key);
@@ -69,26 +61,30 @@ public class ZLMHttpHookSubscribe { @@ -69,26 +61,30 @@ public class ZLMHttpHookSubscribe {
69 return event; 61 return event;
70 } 62 }
71 63
72 - public void removeSubscribe(HookType type, JSONObject hookResponse) {  
73 - Map<JSONObject, Event> eventMap = allSubscribes.get(type); 64 + public void removeSubscribe(IHookSubscribe hookSubscribe) {
  65 + Map<IHookSubscribe, Event> eventMap = allSubscribes.get(hookSubscribe.getHookType());
74 if (eventMap == null) { 66 if (eventMap == null) {
75 return; 67 return;
76 } 68 }
77 69
78 - Set<Map.Entry<JSONObject, Event>> entries = eventMap.entrySet(); 70 + Set<Map.Entry<IHookSubscribe, Event>> entries = eventMap.entrySet();
79 if (entries.size() > 0) { 71 if (entries.size() > 0) {
80 - List<Map.Entry<JSONObject, ZLMHttpHookSubscribe.Event>> entriesToRemove = new ArrayList<>();  
81 - for (Map.Entry<JSONObject, ZLMHttpHookSubscribe.Event> entry : entries) {  
82 - JSONObject key = entry.getKey(); 72 + List<Map.Entry<IHookSubscribe, ZLMHttpHookSubscribe.Event>> entriesToRemove = new ArrayList<>();
  73 + for (Map.Entry<IHookSubscribe, ZLMHttpHookSubscribe.Event> entry : entries) {
  74 + JSONObject content = entry.getKey().getContent();
  75 + if (content == null || content.size() == 0) {
  76 + entriesToRemove.add(entry);
  77 + continue;
  78 + }
83 Boolean result = null; 79 Boolean result = null;
84 - for (String s : key.keySet()) { 80 + for (String s : content.keySet()) {
85 if (result == null) { 81 if (result == null) {
86 - result = key.getString(s).equals(hookResponse.getString(s)); 82 + result = content.getString(s).equals(hookSubscribe.getContent().getString(s));
87 }else { 83 }else {
88 - if (key.getString(s) == null) { 84 + if (content.getString(s) == null) {
89 continue; 85 continue;
90 } 86 }
91 - result = result && key.getString(s).equals(hookResponse.getString(s)); 87 + result = result && content.getString(s).equals(hookSubscribe.getContent().getString(s));
92 } 88 }
93 } 89 }
94 if (null != result && result){ 90 if (null != result && result){
@@ -97,7 +93,7 @@ public class ZLMHttpHookSubscribe { @@ -97,7 +93,7 @@ public class ZLMHttpHookSubscribe {
97 } 93 }
98 94
99 if (!CollectionUtils.isEmpty(entriesToRemove)) { 95 if (!CollectionUtils.isEmpty(entriesToRemove)) {
100 - for (Map.Entry<JSONObject, ZLMHttpHookSubscribe.Event> entry : entriesToRemove) { 96 + for (Map.Entry<IHookSubscribe, ZLMHttpHookSubscribe.Event> entry : entriesToRemove) {
101 entries.remove(entry); 97 entries.remove(entry);
102 } 98 }
103 } 99 }
@@ -111,17 +107,25 @@ public class ZLMHttpHookSubscribe { @@ -111,17 +107,25 @@ public class ZLMHttpHookSubscribe {
111 * @return 107 * @return
112 */ 108 */
113 public List<ZLMHttpHookSubscribe.Event> getSubscribes(HookType type) { 109 public List<ZLMHttpHookSubscribe.Event> getSubscribes(HookType type) {
114 - // ZLMHttpHookSubscribe.Event event= null;  
115 - Map<JSONObject, Event> eventMap = allSubscribes.get(type); 110 + Map<IHookSubscribe, Event> eventMap = allSubscribes.get(type);
116 if (eventMap == null) { 111 if (eventMap == null) {
117 return null; 112 return null;
118 } 113 }
119 List<ZLMHttpHookSubscribe.Event> result = new ArrayList<>(); 114 List<ZLMHttpHookSubscribe.Event> result = new ArrayList<>();
120 - for (JSONObject key : eventMap.keySet()) { 115 + for (IHookSubscribe key : eventMap.keySet()) {
121 result.add(eventMap.get(key)); 116 result.add(eventMap.get(key));
122 } 117 }
123 return result; 118 return result;
124 } 119 }
125 120
  121 + public List<IHookSubscribe> getAll(){
  122 + ArrayList<IHookSubscribe> result = new ArrayList<>();
  123 + Collection<Map<IHookSubscribe, Event>> values = allSubscribes.values();
  124 + for (Map<IHookSubscribe, Event> value : values) {
  125 + result.addAll(value.keySet());
  126 + }
  127 + return result;
  128 + }
  129 +
126 130
127 } 131 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
4 import com.genersoft.iot.vmp.conf.UserSetting; 4 import com.genersoft.iot.vmp.conf.UserSetting;
5 import com.genersoft.iot.vmp.gb28181.bean.GbStream; 5 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
6 import com.genersoft.iot.vmp.media.zlm.dto.*; 6 import com.genersoft.iot.vmp.media.zlm.dto.*;
  7 +import com.genersoft.iot.vmp.service.IMediaServerService;
7 import com.genersoft.iot.vmp.service.IStreamProxyService; 8 import com.genersoft.iot.vmp.service.IStreamProxyService;
8 import com.genersoft.iot.vmp.service.IStreamPushService; 9 import com.genersoft.iot.vmp.service.IStreamPushService;
9 import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; 10 import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
@@ -63,125 +64,49 @@ public class ZLMMediaListManager { @@ -63,125 +64,49 @@ public class ZLMMediaListManager {
63 @Autowired 64 @Autowired
64 private UserSetting userSetting; 65 private UserSetting userSetting;
65 66
66 - private Map<String, ChannelOnlineEvent> channelOnlineEvents = new ConcurrentHashMap<>();  
67 -  
68 -  
69 - public void updateMediaList(MediaServerItem mediaServerItem) {  
70 - storager.clearMediaList();  
71 -  
72 - // 使用异步的当时更新媒体流列表  
73 - zlmresTfulUtils.getMediaList(mediaServerItem, (mediaList ->{  
74 - if (mediaList == null) {  
75 - return;  
76 - }  
77 - String dataStr = mediaList.getString("data");  
78 -  
79 - Integer code = mediaList.getInteger("code");  
80 - Map<String, StreamPushItem> result = new HashMap<>();  
81 - List<StreamPushItem> streamPushItems = null;  
82 - // 获取所有的国标关联  
83 -// List<GbStream> gbStreams = gbStreamMapper.selectAllByMediaServerId(mediaServerItem.getId());  
84 - if (code == 0 ) {  
85 - if (dataStr != null) {  
86 - streamPushItems = streamPushService.handleJSON(dataStr, mediaServerItem);  
87 - }  
88 - }else {  
89 - logger.warn("更新视频流失败,错误code: " + code);  
90 - }  
91 -  
92 - if (streamPushItems != null) {  
93 - storager.updateMediaList(streamPushItems);  
94 - for (StreamPushItem streamPushItem : streamPushItems) {  
95 - JSONObject jsonObject = new JSONObject();  
96 - jsonObject.put("app", streamPushItem.getApp());  
97 - jsonObject.put("stream", streamPushItem.getStream());  
98 - jsonObject.put("mediaServerId", mediaServerItem.getId());  
99 - subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_play,jsonObject,  
100 - (MediaServerItem mediaServerItemInuse, JSONObject response)->{  
101 - updateMedia(mediaServerItem, response.getString("app"), response.getString("stream"));  
102 - }  
103 - );  
104 - }  
105 - }  
106 - })); 67 + @Autowired
  68 + private ZLMRTPServerFactory zlmrtpServerFactory;
107 69
108 - } 70 + @Autowired
  71 + private IMediaServerService mediaServerService;
109 72
110 - public void addMedia(MediaServerItem mediaServerItem, String app, String streamId) {  
111 - //使用异步更新推流  
112 - updateMedia(mediaServerItem, app, streamId);  
113 - } 73 + private Map<String, ChannelOnlineEvent> channelOnPublishEvents = new ConcurrentHashMap<>();
114 74
115 public StreamPushItem addPush(MediaItem mediaItem) { 75 public StreamPushItem addPush(MediaItem mediaItem) {
116 // 查找此直播流是否存在redis预设gbId 76 // 查找此直播流是否存在redis预设gbId
117 StreamPushItem transform = streamPushService.transform(mediaItem); 77 StreamPushItem transform = streamPushService.transform(mediaItem);
118 StreamPushItem pushInDb = streamPushService.getPush(mediaItem.getApp(), mediaItem.getStream()); 78 StreamPushItem pushInDb = streamPushService.getPush(mediaItem.getApp(), mediaItem.getStream());
  79 + transform.setPushIng(mediaItem.isRegist());
119 transform.setUpdateTime(DateUtil.getNow()); 80 transform.setUpdateTime(DateUtil.getNow());
120 transform.setPushTime(DateUtil.getNow()); 81 transform.setPushTime(DateUtil.getNow());
  82 + transform.setSelf(userSetting.getServerId().equals(mediaItem.getSeverId()));
121 if (pushInDb == null) { 83 if (pushInDb == null) {
122 transform.setCreateTime(DateUtil.getNow()); 84 transform.setCreateTime(DateUtil.getNow());
123 streamPushMapper.add(transform); 85 streamPushMapper.add(transform);
124 }else { 86 }else {
125 streamPushMapper.update(transform); 87 streamPushMapper.update(transform);
126 -  
127 -  
128 -// if (!StringUtils.isEmpty(pushInDb.getGbId())) {  
129 -// List<GbStream> gbStreamList = gbStreamMapper.selectByGBId(transform.getGbId());  
130 -// if (gbStreamList != null && gbStreamList.size() == 1) {  
131 -// transform.setGbStreamId(gbStreamList.get(0).getGbStreamId());  
132 -// transform.setPlatformId(gbStreamList.get(0).getPlatformId());  
133 -// transform.setCatalogId(gbStreamList.get(0).getCatalogId());  
134 -// transform.setGbId(gbStreamList.get(0).getGbId());  
135 -// gbStreamMapper.update(transform);  
136 -// streamPushMapper.del(gbStreamList.get(0).getApp(), gbStreamList.get(0).getStream());  
137 -// }else {  
138 -// transform.setCreateTime(DateUtil.getNow());  
139 -// transform.setUpdateTime(DateUtil.getNow());  
140 -// gbStreamMapper.add(transform);  
141 -// }  
142 - // 通知通道上线  
143 -// if (transform != null) {  
144 -// if (channelOnlineEvents.get(transform.getGbId()) != null) {  
145 -// channelOnlineEvents.get(transform.getGbId()).run(transform.getApp(), transform.getStream(), transform.getServerId());  
146 -// channelOnlineEvents.remove(transform.getGbId());  
147 -// }  
148 -// }  
149 -// } 88 + gbStreamMapper.updateMediaServer(mediaItem.getApp(), mediaItem.getStream(), mediaItem.getMediaServerId());
  89 + }
  90 + if (transform != null) {
  91 + if (getChannelOnlineEventLister(transform.getApp(), transform.getStream()) != null) {
  92 + getChannelOnlineEventLister(transform.getApp(), transform.getStream()).run(transform.getApp(), transform.getStream(), transform.getServerId());
  93 + removedChannelOnlineEventLister(transform.getApp(), transform.getStream());
  94 + }
150 } 95 }
151 -  
152 -  
153 -  
154 return transform; 96 return transform;
155 } 97 }
156 98
157 -  
158 - public void updateMedia(MediaServerItem mediaServerItem, String app, String streamId) {  
159 - //使用异步更新推流  
160 - zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId, "rtmp", json->{  
161 -  
162 - if (json == null) {  
163 - return;  
164 - }  
165 - String dataStr = json.getString("data");  
166 -  
167 - Integer code = json.getInteger("code");  
168 - Map<String, StreamPushItem> result = new HashMap<>();  
169 - List<StreamPushItem> streamPushItems = null;  
170 - if (code == 0 ) {  
171 - if (dataStr != null) {  
172 - streamPushItems = streamPushService.handleJSON(dataStr, mediaServerItem);  
173 - }  
174 - }else {  
175 - logger.warn("更新视频流失败,错误code: " + code); 99 + public void sendStreamEvent(String app, String stream, String mediaServerId) {
  100 + MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
  101 + // 查看推流状态
  102 + if (zlmrtpServerFactory.isStreamReady(mediaServerItem, app, stream)) {
  103 + if (getChannelOnlineEventLister(app, stream) != null) {
  104 + getChannelOnlineEventLister(app, stream).run(app, stream, mediaServerId);
  105 + removedChannelOnlineEventLister(app, stream);
176 } 106 }
177 -  
178 - if (streamPushItems != null && streamPushItems.size() == 1) {  
179 - storager.updateMedia(streamPushItems.get(0));  
180 - }  
181 - }); 107 + }
182 } 108 }
183 109
184 -  
185 public int removeMedia(String app, String streamId) { 110 public int removeMedia(String app, String streamId) {
186 // 查找是否关联了国标, 关联了不删除, 置为离线 111 // 查找是否关联了国标, 关联了不删除, 置为离线
187 GbStream gbStream = gbStreamMapper.selectOne(app, streamId); 112 GbStream gbStream = gbStreamMapper.selectOne(app, streamId);
@@ -189,48 +114,21 @@ public class ZLMMediaListManager { @@ -189,48 +114,21 @@ public class ZLMMediaListManager {
189 if (gbStream == null) { 114 if (gbStream == null) {
190 result = storager.removeMedia(app, streamId); 115 result = storager.removeMedia(app, streamId);
191 }else { 116 }else {
192 - // TODO 暂不设置为离线  
193 result =storager.mediaOffline(app, streamId); 117 result =storager.mediaOffline(app, streamId);
194 } 118 }
195 return result; 119 return result;
196 } 120 }
197 121
198 - public void addChannelOnlineEventLister(String key, ChannelOnlineEvent callback) {  
199 - this.channelOnlineEvents.put(key,callback); 122 + public void addChannelOnlineEventLister(String app, String stream, ChannelOnlineEvent callback) {
  123 + this.channelOnPublishEvents.put(app + "_" + stream, callback);
200 } 124 }
201 125
202 - public void removedChannelOnlineEventLister(String key) {  
203 - this.channelOnlineEvents.remove(key); 126 + public void removedChannelOnlineEventLister(String app, String stream) {
  127 + this.channelOnPublishEvents.remove(app + "_" + stream);
204 } 128 }
205 129
  130 + public ChannelOnlineEvent getChannelOnlineEventLister(String app, String stream) {
  131 + return this.channelOnPublishEvents.get(app + "_" + stream);
  132 + }
206 133
207 -  
208 -// public void clearAllSessions() {  
209 -// logger.info("清空所有国标相关的session");  
210 -// JSONObject allSessionJSON = zlmresTfulUtils.getAllSession();  
211 -// ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo();  
212 -// HashSet<String> allLocalPorts = new HashSet();  
213 -// if (allSessionJSON.getInteger("code") == 0) {  
214 -// JSONArray data = allSessionJSON.getJSONArray("data");  
215 -// if (data.size() > 0) {  
216 -// for (int i = 0; i < data.size(); i++) {  
217 -// JSONObject sessionJOSN = data.getJSONObject(i);  
218 -// Integer local_port = sessionJOSN.getInteger("local_port");  
219 -// if (!local_port.equals(Integer.valueOf(mediaInfo.getHttpPort())) &&  
220 -// !local_port.equals(Integer.valueOf(mediaInfo.getHttpSSLport())) &&  
221 -// !local_port.equals(Integer.valueOf(mediaInfo.getRtmpPort())) &&  
222 -// !local_port.equals(Integer.valueOf(mediaInfo.getRtspPort())) &&  
223 -// !local_port.equals(Integer.valueOf(mediaInfo.getRtspSSlport())) &&  
224 -// !local_port.equals(Integer.valueOf(mediaInfo.getHookOnFlowReport()))){  
225 -// allLocalPorts.add(sessionJOSN.getInteger("local_port") + "");  
226 -// }  
227 -// }  
228 -// }  
229 -// }  
230 -// if (allLocalPorts.size() > 0) {  
231 -// List<String> result = new ArrayList<>(allLocalPorts);  
232 -// String localPortSStr = String.join(",", result);  
233 -// zlmresTfulUtils.kickSessions(localPortSStr);  
234 -// }  
235 -// }  
236 } 134 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
@@ -87,7 +87,7 @@ public class ZLMRTPServerFactory { @@ -87,7 +87,7 @@ public class ZLMRTPServerFactory {
87 return result; 87 return result;
88 } 88 }
89 89
90 - public int createRTPServer(MediaServerItem mediaServerItem, String streamId, int ssrc) { 90 + public int createRTPServer(MediaServerItem mediaServerItem, String streamId, int ssrc, Integer port) {
91 int result = -1; 91 int result = -1;
92 // 查询此rtp server 是否已经存在 92 // 查询此rtp server 是否已经存在
93 JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId); 93 JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId);
@@ -105,7 +105,11 @@ public class ZLMRTPServerFactory { @@ -105,7 +105,11 @@ public class ZLMRTPServerFactory {
105 param.put("enable_tcp", 1); 105 param.put("enable_tcp", 1);
106 param.put("stream_id", streamId); 106 param.put("stream_id", streamId);
107 // 推流端口设置0则使用随机端口 107 // 推流端口设置0则使用随机端口
108 - param.put("port", 0); 108 + if (port == null) {
  109 + param.put("port", 0);
  110 + }else {
  111 + param.put("port", port);
  112 + }
109 param.put("ssrc", ssrc); 113 param.put("ssrc", ssrc);
110 JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param); 114 JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
111 115
@@ -280,8 +284,10 @@ public class ZLMRTPServerFactory { @@ -280,8 +284,10 @@ public class ZLMRTPServerFactory {
280 * 查询待转推的流是否就绪 284 * 查询待转推的流是否就绪
281 */ 285 */
282 public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) { 286 public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) {
283 - JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtsp", streamId);  
284 - return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online") != null && mediaInfo.getBoolean("online")); 287 + JSONObject mediaInfo = zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId);
  288 + return (mediaInfo.getInteger("code") == 0
  289 + && mediaInfo.getJSONArray("data") != null
  290 + && mediaInfo.getJSONArray("data").size() > 0);
285 } 291 }
286 292
287 /** 293 /**
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
@@ -6,22 +6,22 @@ import com.alibaba.fastjson.JSONObject; @@ -6,22 +6,22 @@ import com.alibaba.fastjson.JSONObject;
6 import com.genersoft.iot.vmp.conf.DynamicTask; 6 import com.genersoft.iot.vmp.conf.DynamicTask;
7 import com.genersoft.iot.vmp.conf.MediaConfig; 7 import com.genersoft.iot.vmp.conf.MediaConfig;
8 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 8 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
  9 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
  10 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForServerStarted;
  11 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
9 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 12 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
10 import com.genersoft.iot.vmp.service.IMediaServerService; 13 import com.genersoft.iot.vmp.service.IMediaServerService;
11 -import com.genersoft.iot.vmp.service.IStreamProxyService;  
12 -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;  
13 import org.slf4j.Logger; 14 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory; 15 import org.slf4j.LoggerFactory;
15 import org.springframework.beans.factory.annotation.Autowired; 16 import org.springframework.beans.factory.annotation.Autowired;
16 -import org.springframework.beans.factory.annotation.Qualifier;  
17 import org.springframework.boot.CommandLineRunner; 17 import org.springframework.boot.CommandLineRunner;
18 import org.springframework.core.annotation.Order; 18 import org.springframework.core.annotation.Order;
19 import org.springframework.scheduling.annotation.Async; 19 import org.springframework.scheduling.annotation.Async;
20 -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;  
21 import org.springframework.stereotype.Component; 20 import org.springframework.stereotype.Component;
22 -import org.springframework.util.StringUtils;  
23 21
  22 +import java.time.Instant;
24 import java.util.*; 23 import java.util.*;
  24 +import java.util.concurrent.TimeUnit;
25 25
26 @Component 26 @Component
27 @Order(value=1) 27 @Order(value=1)
@@ -38,18 +38,12 @@ public class ZLMRunner implements CommandLineRunner { @@ -38,18 +38,12 @@ public class ZLMRunner implements CommandLineRunner {
38 private ZLMHttpHookSubscribe hookSubscribe; 38 private ZLMHttpHookSubscribe hookSubscribe;
39 39
40 @Autowired 40 @Autowired
41 - private IStreamProxyService streamProxyService;  
42 -  
43 - @Autowired  
44 private EventPublisher publisher; 41 private EventPublisher publisher;
45 42
46 @Autowired 43 @Autowired
47 private IMediaServerService mediaServerService; 44 private IMediaServerService mediaServerService;
48 45
49 @Autowired 46 @Autowired
50 - private IRedisCatchStorage redisCatchStorage;  
51 -  
52 - @Autowired  
53 private MediaConfig mediaConfig; 47 private MediaConfig mediaConfig;
54 48
55 @Autowired 49 @Autowired
@@ -67,26 +61,24 @@ public class ZLMRunner implements CommandLineRunner { @@ -67,26 +61,24 @@ public class ZLMRunner implements CommandLineRunner {
67 mediaServerService.updateToDatabase(mediaSerItem); 61 mediaServerService.updateToDatabase(mediaSerItem);
68 } 62 }
69 mediaServerService.syncCatchFromDatabase(); 63 mediaServerService.syncCatchFromDatabase();
  64 + HookSubscribeForServerStarted hookSubscribeForServerStarted = HookSubscribeFactory.on_server_started();
  65 +// Instant expiresInstant = Instant.now().plusSeconds(TimeUnit.SECONDS.toSeconds(60));
  66 +// hookSubscribeForStreamChange.setExpires(expiresInstant);
70 // 订阅 zlm启动事件, 新的zlm也会从这里进入系统 67 // 订阅 zlm启动事件, 新的zlm也会从这里进入系统
71 - hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,new JSONObject(), 68 + hookSubscribe.addSubscribe(hookSubscribeForServerStarted,
72 (MediaServerItem mediaServerItem, JSONObject response)->{ 69 (MediaServerItem mediaServerItem, JSONObject response)->{
73 ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(response, ZLMServerConfig.class); 70 ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(response, ZLMServerConfig.class);
74 if (zlmServerConfig !=null ) { 71 if (zlmServerConfig !=null ) {
75 if (startGetMedia != null) { 72 if (startGetMedia != null) {
76 startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId()); 73 startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId());
  74 + if (startGetMedia.size() == 0) {
  75 + hookSubscribe.removeSubscribe(HookSubscribeFactory.on_server_started());
  76 + }
77 } 77 }
78 - mediaServerService.zlmServerOnline(zlmServerConfig);  
79 } 78 }
80 }); 79 });
81 80
82 - // 订阅 zlm保活事件, 当zlm离线时做业务的处理  
83 - hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_keepalive,new JSONObject(),  
84 - (MediaServerItem mediaServerItem, JSONObject response)->{  
85 - String mediaServerId = response.getString("mediaServerId");  
86 - if (mediaServerId !=null ) {  
87 - mediaServerService.updateMediaServerKeepalive(mediaServerId, response.getJSONObject("data"));  
88 - }  
89 - }); 81 +
90 82
91 // 获取zlm信息 83 // 获取zlm信息
92 logger.info("[zlm] 等待默认zlm中..."); 84 logger.info("[zlm] 等待默认zlm中...");
@@ -125,6 +117,9 @@ public class ZLMRunner implements CommandLineRunner { @@ -125,6 +117,9 @@ public class ZLMRunner implements CommandLineRunner {
125 zlmServerConfigFirst.setIp(mediaServerItem.getIp()); 117 zlmServerConfigFirst.setIp(mediaServerItem.getIp());
126 zlmServerConfigFirst.setHttpPort(mediaServerItem.getHttpPort()); 118 zlmServerConfigFirst.setHttpPort(mediaServerItem.getHttpPort());
127 startGetMedia.remove(mediaServerItem.getId()); 119 startGetMedia.remove(mediaServerItem.getId());
  120 + if (startGetMedia.size() == 0) {
  121 + hookSubscribe.removeSubscribe(HookSubscribeFactory.on_server_started());
  122 + }
128 mediaServerService.zlmServerOnline(zlmServerConfigFirst); 123 mediaServerService.zlmServerOnline(zlmServerConfigFirst);
129 }else { 124 }else {
130 logger.info("[ {} ]-[ {}:{} ]主动连接失败, 清理相关资源, 开始尝试重试连接", 125 logger.info("[ {} ]-[ {}:{} ]主动连接失败, 清理相关资源, 开始尝试重试连接",
@@ -139,6 +134,9 @@ public class ZLMRunner implements CommandLineRunner { @@ -139,6 +134,9 @@ public class ZLMRunner implements CommandLineRunner {
139 zlmServerConfig.setIp(mediaServerItem.getIp()); 134 zlmServerConfig.setIp(mediaServerItem.getIp());
140 zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort()); 135 zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort());
141 startGetMedia.remove(mediaServerItem.getId()); 136 startGetMedia.remove(mediaServerItem.getId());
  137 + if (startGetMedia.size() == 0) {
  138 + hookSubscribe.removeSubscribe(HookSubscribeFactory.on_server_started());
  139 + }
142 mediaServerService.zlmServerOnline(zlmServerConfig); 140 mediaServerService.zlmServerOnline(zlmServerConfig);
143 } 141 }
144 }, 2000); 142 }, 2000);
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeFactory.java 0 → 100644
  1 +package com.genersoft.iot.vmp.media.zlm.dto;
  2 +
  3 +
  4 +import com.alibaba.fastjson.JSONObject;
  5 +
  6 +/**
  7 + * hook 订阅工厂
  8 + * @author lin
  9 + */
  10 +public class HookSubscribeFactory {
  11 +
  12 + public static HookSubscribeForStreamChange on_stream_changed(String app, String stream, boolean regist, String scheam, String mediaServerId) {
  13 + HookSubscribeForStreamChange hookSubscribe = new HookSubscribeForStreamChange();
  14 + JSONObject subscribeKey = new com.alibaba.fastjson.JSONObject();
  15 + subscribeKey.put("app", app);
  16 + subscribeKey.put("stream", stream);
  17 + subscribeKey.put("regist", regist);
  18 + if (scheam != null) {
  19 + subscribeKey.put("schema", scheam);
  20 + }
  21 + subscribeKey.put("mediaServerId", mediaServerId);
  22 + hookSubscribe.setContent(subscribeKey);
  23 +
  24 + return hookSubscribe;
  25 + }
  26 +
  27 + public static HookSubscribeForServerStarted on_server_started() {
  28 + HookSubscribeForServerStarted hookSubscribe = new HookSubscribeForServerStarted();
  29 + hookSubscribe.setContent(new JSONObject());
  30 +
  31 + return hookSubscribe;
  32 + }
  33 +}
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForServerStarted.java 0 → 100644
  1 +package com.genersoft.iot.vmp.media.zlm.dto;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.alibaba.fastjson.annotation.JSONField;
  5 +
  6 +import java.time.Instant;
  7 +
  8 +/**
  9 + * hook订阅-流变化
  10 + * @author lin
  11 + */
  12 +public class HookSubscribeForServerStarted implements IHookSubscribe{
  13 +
  14 + private HookType hookType = HookType.on_server_started;
  15 +
  16 + private JSONObject content;
  17 +
  18 + @JSONField(format="yyyy-MM-dd HH:mm:ss")
  19 + private Instant expires;
  20 +
  21 + @Override
  22 + public HookType getHookType() {
  23 + return hookType;
  24 + }
  25 +
  26 + @Override
  27 + public JSONObject getContent() {
  28 + return content;
  29 + }
  30 +
  31 + public void setContent(JSONObject content) {
  32 + this.content = content;
  33 + }
  34 +
  35 + @Override
  36 + public Instant getExpires() {
  37 + return expires;
  38 + }
  39 +
  40 + @Override
  41 + public void setExpires(Instant expires) {
  42 + this.expires = expires;
  43 + }
  44 +}
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamChange.java 0 → 100644
  1 +package com.genersoft.iot.vmp.media.zlm.dto;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import com.alibaba.fastjson.annotation.JSONField;
  5 +
  6 +import java.time.Instant;
  7 +
  8 +/**
  9 + * hook订阅-流变化
  10 + * @author lin
  11 + */
  12 +public class HookSubscribeForStreamChange implements IHookSubscribe{
  13 +
  14 + private HookType hookType = HookType.on_stream_changed;
  15 +
  16 + private JSONObject content;
  17 +
  18 + private Instant expires;
  19 +
  20 + @Override
  21 + public HookType getHookType() {
  22 + return hookType;
  23 + }
  24 +
  25 + @Override
  26 + public JSONObject getContent() {
  27 + return content;
  28 + }
  29 +
  30 + public void setContent(JSONObject content) {
  31 + this.content = content;
  32 + }
  33 +
  34 + @Override
  35 + public Instant getExpires() {
  36 + return expires;
  37 + }
  38 +
  39 + @Override
  40 + public void setExpires(Instant expires) {
  41 + this.expires = expires;
  42 + }
  43 +}
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookType.java 0 → 100644
  1 +package com.genersoft.iot.vmp.media.zlm.dto;
  2 +
  3 +/**
  4 + * hook类型
  5 + * @author lin
  6 + */
  7 +
  8 +public enum HookType {
  9 +
  10 + on_flow_report,
  11 + on_http_access,
  12 + on_play,
  13 + on_publish,
  14 + on_record_mp4,
  15 + on_rtsp_auth,
  16 + on_rtsp_realm,
  17 + on_shell_login,
  18 + on_stream_changed,
  19 + on_stream_none_reader,
  20 + on_stream_not_found,
  21 + on_server_started,
  22 + on_server_keepalive
  23 +}
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IHookSubscribe.java 0 → 100644
  1 +package com.genersoft.iot.vmp.media.zlm.dto;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +
  5 +import java.time.Instant;
  6 +
  7 +/**
  8 + * zlm hook事件的参数
  9 + * @author lin
  10 + */
  11 +public interface IHookSubscribe {
  12 +
  13 + /**
  14 + * 获取hook类型
  15 + * @return hook类型
  16 + */
  17 + HookType getHookType();
  18 +
  19 + /**
  20 + * 获取hook的具体内容
  21 + * @return hook的具体内容
  22 + */
  23 + JSONObject getContent();
  24 +
  25 + /**
  26 + * 设置过期时间
  27 + * @param instant 过期时间
  28 + */
  29 + void setExpires(Instant instant);
  30 +
  31 + /**
  32 + * 获取过期时间
  33 + * @return 过期时间
  34 + */
  35 + Instant getExpires();
  36 +}
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java
@@ -4,6 +4,9 @@ import com.genersoft.iot.vmp.common.StreamInfo; @@ -4,6 +4,9 @@ import com.genersoft.iot.vmp.common.StreamInfo;
4 4
5 import java.util.List; 5 import java.util.List;
6 6
  7 +/**
  8 + * @author lin
  9 + */
7 public class MediaItem { 10 public class MediaItem {
8 11
9 /** 12 /**
@@ -22,6 +25,11 @@ public class MediaItem { @@ -22,6 +25,11 @@ public class MediaItem {
22 private String stream; 25 private String stream;
23 26
24 /** 27 /**
  28 + * 推流鉴权Id
  29 + */
  30 + private String callId;
  31 +
  32 + /**
25 * 观看总人数,包括hls/rtsp/rtmp/http-flv/ws-flv 33 * 观看总人数,包括hls/rtsp/rtmp/http-flv/ws-flv
26 */ 34 */
27 private String totalReaderCount; 35 private String totalReaderCount;
@@ -427,4 +435,12 @@ public class MediaItem { @@ -427,4 +435,12 @@ public class MediaItem {
427 public void setSeverId(String severId) { 435 public void setSeverId(String severId) {
428 this.severId = severId; 436 this.severId = severId;
429 } 437 }
  438 +
  439 + public String getCallId() {
  440 + return callId;
  441 + }
  442 +
  443 + public void setCallId(String callId) {
  444 + this.callId = callId;
  445 + }
430 } 446 }
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java
@@ -103,6 +103,18 @@ public class StreamPushItem extends GbStream implements Comparable&lt;StreamPushIte @@ -103,6 +103,18 @@ public class StreamPushItem extends GbStream implements Comparable&lt;StreamPushIte
103 */ 103 */
104 private String createTime; 104 private String createTime;
105 105
  106 + /**
  107 + * 是否正在推流
  108 + */
  109 + private boolean pushIng;
  110 +
  111 + /**
  112 + * 是否自己平台的推流
  113 + */
  114 + private boolean self;
  115 +
  116 +
  117 +
106 public String getVhost() { 118 public String getVhost() {
107 return vhost; 119 return vhost;
108 } 120 }
@@ -277,5 +289,21 @@ public class StreamPushItem extends GbStream implements Comparable&lt;StreamPushIte @@ -277,5 +289,21 @@ public class StreamPushItem extends GbStream implements Comparable&lt;StreamPushIte
277 public void setCreateTime(String createTime) { 289 public void setCreateTime(String createTime) {
278 this.createTime = createTime; 290 this.createTime = createTime;
279 } 291 }
  292 +
  293 + public boolean isPushIng() {
  294 + return pushIng;
  295 + }
  296 +
  297 + public void setPushIng(boolean pushIng) {
  298 + this.pushIng = pushIng;
  299 + }
  300 +
  301 + public boolean isSelf() {
  302 + return self;
  303 + }
  304 +
  305 + public void setSelf(boolean self) {
  306 + this.self = self;
  307 + }
280 } 308 }
281 309
src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service;
  2 +
  3 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  4 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  5 +
  6 +import java.util.List;
  7 +
  8 +/**
  9 + * 国标通道业务类
  10 + * @author lin
  11 + */
  12 +public interface IDeviceChannelService {
  13 +
  14 + /**
  15 + * 更新gps信息
  16 + */
  17 + DeviceChannel updateGps(DeviceChannel deviceChannel, Device device);
  18 +
  19 + /**
  20 + * 添加设备通道
  21 + *
  22 + * @param deviceId 设备id
  23 + * @param channel 通道
  24 + */
  25 + void updateChannel(String deviceId, DeviceChannel channel);
  26 +
  27 + /**
  28 + * 批量添加设备通道
  29 + *
  30 + * @param deviceId 设备id
  31 + * @param channels 多个通道
  32 + */
  33 + int updateChannels(String deviceId, List<DeviceChannel> channels);
  34 +
  35 +}
src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java
@@ -18,7 +18,7 @@ public interface IGbStreamService { @@ -18,7 +18,7 @@ public interface IGbStreamService {
18 * @param count 18 * @param count
19 * @return 19 * @return
20 */ 20 */
21 - PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId,String query,Boolean pushing,String mediaServerId); 21 + PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId,String query,String mediaServerId);
22 22
23 23
24 /** 24 /**
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
@@ -47,6 +47,8 @@ public interface IMediaServerService { @@ -47,6 +47,8 @@ public interface IMediaServerService {
47 47
48 SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback); 48 SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback);
49 49
  50 + SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port);
  51 +
50 void closeRTPServer(String deviceId, String channelId, String ssrc); 52 void closeRTPServer(String deviceId, String channelId, String ssrc);
51 53
52 void clearRTPServer(MediaServerItem mediaServerItem); 54 void clearRTPServer(MediaServerItem mediaServerItem);
src/main/java/com/genersoft/iot/vmp/service/IPlatformChannelService.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service;
  2 +
  3 +import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
  4 +
  5 +import java.util.List;
  6 +
  7 +/**
  8 + * 平台关联通道管理
  9 + * @author lin
  10 + */
  11 +public interface IPlatformChannelService {
  12 +
  13 + /**
  14 + * 更新目录下的通道
  15 + * @param platformId 平台编号
  16 + * @param channelReduces 通道信息
  17 + * @param catalogId 目录编号
  18 + * @return
  19 + */
  20 + int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId);
  21 +
  22 +}
src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java
@@ -101,4 +101,9 @@ public interface IStreamProxyService { @@ -101,4 +101,9 @@ public interface IStreamProxyService {
101 void zlmServerOffline(String mediaServerId); 101 void zlmServerOffline(String mediaServerId);
102 102
103 void clean(); 103 void clean();
  104 +
  105 + /**
  106 + * 更新代理流
  107 + */
  108 + boolean updateStreamProxy(StreamProxyItem streamProxyItem);
104 } 109 }
src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
@@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
5 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; 5 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
6 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 6 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
7 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; 7 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
  8 +import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
8 import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto; 9 import com.genersoft.iot.vmp.vmanager.bean.StreamPushExcelDto;
9 import com.github.pagehelper.PageInfo; 10 import com.github.pagehelper.PageInfo;
10 11
@@ -44,31 +45,59 @@ public interface IStreamPushService { @@ -44,31 +45,59 @@ public interface IStreamPushService {
44 * 停止一路推流 45 * 停止一路推流
45 * @param app 应用名 46 * @param app 应用名
46 * @param streamId 流ID 47 * @param streamId 流ID
47 - * @return  
48 */ 48 */
49 boolean stop(String app, String streamId); 49 boolean stop(String app, String streamId);
50 50
51 /** 51 /**
52 * 新的节点加入 52 * 新的节点加入
53 - * @param mediaServerId  
54 - * @return  
55 */ 53 */
56 void zlmServerOnline(String mediaServerId); 54 void zlmServerOnline(String mediaServerId);
57 55
58 /** 56 /**
59 * 节点离线 57 * 节点离线
60 - * @param mediaServerId  
61 - * @return  
62 */ 58 */
63 void zlmServerOffline(String mediaServerId); 59 void zlmServerOffline(String mediaServerId);
64 60
  61 + /**
  62 + * 清空
  63 + */
65 void clean(); 64 void clean();
66 65
  66 +
67 boolean saveToRandomGB(); 67 boolean saveToRandomGB();
68 68
  69 + /**
  70 + * 批量添加
  71 + */
69 void batchAdd(List<StreamPushItem> streamPushExcelDtoList); 72 void batchAdd(List<StreamPushItem> streamPushExcelDtoList);
70 73
  74 + /**
  75 + * 中止多个推流
  76 + */
71 boolean batchStop(List<GbStream> streamPushItems); 77 boolean batchStop(List<GbStream> streamPushItems);
72 78
  79 + /**
  80 + * 导入时批量增加
  81 + */
73 void batchAddForUpload(List<StreamPushItem> streamPushItems, Map<String, List<String[]>> streamPushItemsForAll); 82 void batchAddForUpload(List<StreamPushItem> streamPushItems, Map<String, List<String[]>> streamPushItemsForAll);
  83 +
  84 + /**
  85 + * 全部离线
  86 + */
  87 + void allStreamOffline();
  88 +
  89 + /**
  90 + * 推流离线
  91 + */
  92 + void offline(List<StreamPushItemFromRedis> offlineStreams);
  93 +
  94 + /**
  95 + * 推流上线
  96 + */
  97 + void online(List<StreamPushItemFromRedis> onlineStreams);
  98 +
  99 + /**
  100 + * 增加推流
  101 + */
  102 + boolean add(StreamPushItem stream);
74 } 103 }
src/main/java/com/genersoft/iot/vmp/service/IUserService.java
1 package com.genersoft.iot.vmp.service; 1 package com.genersoft.iot.vmp.service;
2 2
3 import com.genersoft.iot.vmp.storager.dao.dto.User; 3 import com.genersoft.iot.vmp.storager.dao.dto.User;
  4 +import com.github.pagehelper.PageInfo;
4 5
5 import java.util.List; 6 import java.util.List;
6 7
@@ -21,4 +22,8 @@ public interface IUserService { @@ -21,4 +22,8 @@ public interface IUserService {
21 int updateUsers(User user); 22 int updateUsers(User user);
22 23
23 boolean checkPushAuthority(String callId, String sign); 24 boolean checkPushAuthority(String callId, String sign);
  25 +
  26 + PageInfo<User> getUsers(int page, int count);
  27 +
  28 + int changePushKey(int id, String pushKey);
24 } 29 }
src/main/java/com/genersoft/iot/vmp/service/StreamGPSSubscribeTask.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.service;  
2 -  
3 -import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;  
4 -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;  
5 -import com.genersoft.iot.vmp.storager.IVideoManagerStorage;  
6 -import org.springframework.beans.factory.annotation.Autowired;  
7 -import org.springframework.scheduling.annotation.Scheduled;  
8 -import org.springframework.stereotype.Component;  
9 -  
10 -import java.util.List;  
11 -  
12 -  
13 -/**  
14 - * 定时查找redis中的GPS推送消息,并保存到对应的流中  
15 - */  
16 -@Component  
17 -public class StreamGPSSubscribeTask {  
18 -  
19 - @Autowired  
20 - private IRedisCatchStorage redisCatchStorage;  
21 -  
22 - @Autowired  
23 - private IVideoManagerStorage storager;  
24 -  
25 -  
26 - @Scheduled(fixedRate = 30 * 1000) //每30秒执行一次  
27 - public void execute(){  
28 - List<GPSMsgInfo> gpsMsgInfo = redisCatchStorage.getAllGpsMsgInfo();  
29 - if (gpsMsgInfo.size() > 0) {  
30 - storager.updateStreamGPS(gpsMsgInfo);  
31 - for (GPSMsgInfo msgInfo : gpsMsgInfo) {  
32 - msgInfo.setStored(true);  
33 - redisCatchStorage.updateGpsMsgInfo(msgInfo);  
34 - }  
35 - }  
36 -  
37 - }  
38 -}  
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImpl.java
@@ -17,7 +17,6 @@ public class DeviceAlarmServiceImpl implements IDeviceAlarmService { @@ -17,7 +17,6 @@ public class DeviceAlarmServiceImpl implements IDeviceAlarmService {
17 @Autowired 17 @Autowired
18 private DeviceAlarmMapper deviceAlarmMapper; 18 private DeviceAlarmMapper deviceAlarmMapper;
19 19
20 -  
21 @Override 20 @Override
22 public PageInfo<DeviceAlarm> getAllAlarm(int page, int count, String deviceId, String alarmPriority, String alarmMethod, String alarmType, String startTime, String endTime) { 21 public PageInfo<DeviceAlarm> getAllAlarm(int page, int count, String deviceId, String alarmPriority, String alarmMethod, String alarmType, String startTime, String endTime) {
23 PageHelper.startPage(page, count); 22 PageHelper.startPage(page, count);
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service.impl;
  2 +
  3 +import com.genersoft.iot.vmp.common.StreamInfo;
  4 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  5 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  6 +import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
  7 +import com.genersoft.iot.vmp.service.IDeviceChannelService;
  8 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  9 +import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
  10 +import com.genersoft.iot.vmp.storager.dao.DeviceMapper;
  11 +import com.genersoft.iot.vmp.utils.DateUtil;
  12 +import org.slf4j.Logger;
  13 +import org.slf4j.LoggerFactory;
  14 +import org.springframework.beans.factory.annotation.Autowired;
  15 +import org.springframework.stereotype.Service;
  16 +
  17 +import java.util.ArrayList;
  18 +import java.util.HashMap;
  19 +import java.util.List;
  20 +
  21 +/**
  22 + * @author lin
  23 + */
  24 +@Service
  25 +public class DeviceChannelServiceImpl implements IDeviceChannelService {
  26 +
  27 + private final static Logger logger = LoggerFactory.getLogger(DeviceChannelServiceImpl.class);
  28 +
  29 + @Autowired
  30 + private IRedisCatchStorage redisCatchStorage;
  31 +
  32 + @Autowired
  33 + private DeviceChannelMapper channelMapper;
  34 +
  35 + @Autowired
  36 + private DeviceMapper deviceMapper;
  37 +
  38 + @Override
  39 + public DeviceChannel updateGps(DeviceChannel deviceChannel, Device device) {
  40 + if (deviceChannel.getLongitude()*deviceChannel.getLatitude() > 0) {
  41 + if (device == null) {
  42 + device = deviceMapper.getDeviceByDeviceId(deviceChannel.getDeviceId());
  43 + }
  44 +
  45 + if ("WGS84".equals(device.getGeoCoordSys())) {
  46 + deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
  47 + deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
  48 + Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude());
  49 + deviceChannel.setLongitudeGcj02(position[0]);
  50 + deviceChannel.setLatitudeGcj02(position[1]);
  51 + }else if ("GCJ02".equals(device.getGeoCoordSys())) {
  52 + deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
  53 + deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
  54 + Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude());
  55 + deviceChannel.setLongitudeWgs84(position[0]);
  56 + deviceChannel.setLatitudeWgs84(position[1]);
  57 + }else {
  58 + deviceChannel.setLongitudeGcj02(0.00);
  59 + deviceChannel.setLatitudeGcj02(0.00);
  60 + deviceChannel.setLongitudeWgs84(0.00);
  61 + deviceChannel.setLatitudeWgs84(0.00);
  62 + }
  63 + }else {
  64 + deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());
  65 + deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());
  66 + deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());
  67 + deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());
  68 + }
  69 + return deviceChannel;
  70 + }
  71 +
  72 + @Override
  73 + public void updateChannel(String deviceId, DeviceChannel channel) {
  74 + String channelId = channel.getChannelId();
  75 + channel.setDeviceId(deviceId);
  76 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
  77 + if (streamInfo != null) {
  78 + channel.setStreamId(streamInfo.getStream());
  79 + }
  80 + String now = DateUtil.getNow();
  81 + channel.setUpdateTime(now);
  82 + DeviceChannel deviceChannel = channelMapper.queryChannel(deviceId, channelId);
  83 + channel = updateGps(channel, null);
  84 + if (deviceChannel == null) {
  85 + channel.setCreateTime(now);
  86 + channelMapper.add(channel);
  87 + }else {
  88 + channelMapper.update(channel);
  89 + }
  90 + channelMapper.updateChannelSubCount(deviceId,channel.getParentId());
  91 + }
  92 +
  93 + @Override
  94 + public int updateChannels(String deviceId, List<DeviceChannel> channels) {
  95 + List<DeviceChannel> addChannels = new ArrayList<>();
  96 + List<DeviceChannel> updateChannels = new ArrayList<>();
  97 + HashMap<String, DeviceChannel> channelsInStore = new HashMap<>();
  98 + Device device = deviceMapper.getDeviceByDeviceId(deviceId);
  99 + if (channels != null && channels.size() > 0) {
  100 + List<DeviceChannel> channelList = channelMapper.queryChannels(deviceId, null, null, null, null);
  101 + if (channelList.size() == 0) {
  102 + for (DeviceChannel channel : channels) {
  103 + channel.setDeviceId(deviceId);
  104 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
  105 + if (streamInfo != null) {
  106 + channel.setStreamId(streamInfo.getStream());
  107 + }
  108 + String now = DateUtil.getNow();
  109 + channel.setUpdateTime(now);
  110 + channel.setCreateTime(now);
  111 + channel = updateGps(channel, device);
  112 + addChannels.add(channel);
  113 + }
  114 + }else {
  115 + for (DeviceChannel deviceChannel : channelList) {
  116 + channelsInStore.put(deviceChannel.getChannelId(), deviceChannel);
  117 + }
  118 + for (DeviceChannel channel : channels) {
  119 + channel.setDeviceId(deviceId);
  120 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
  121 + if (streamInfo != null) {
  122 + channel.setStreamId(streamInfo.getStream());
  123 + }
  124 + String now = DateUtil.getNow();
  125 + channel.setUpdateTime(now);
  126 + channel = updateGps(channel, device);
  127 + if (channelsInStore.get(channel.getChannelId()) != null) {
  128 + updateChannels.add(channel);
  129 + }else {
  130 + addChannels.add(channel);
  131 + channel.setCreateTime(now);
  132 + }
  133 + }
  134 + }
  135 + int limitCount = 300;
  136 + if (addChannels.size() > 0) {
  137 + if (addChannels.size() > limitCount) {
  138 + for (int i = 0; i < addChannels.size(); i += limitCount) {
  139 + int toIndex = i + limitCount;
  140 + if (i + limitCount > addChannels.size()) {
  141 + toIndex = addChannels.size();
  142 + }
  143 + channelMapper.batchAdd(addChannels.subList(i, toIndex));
  144 + }
  145 + }else {
  146 + channelMapper.batchAdd(addChannels);
  147 + }
  148 + }
  149 + if (updateChannels.size() > 0) {
  150 + if (updateChannels.size() > limitCount) {
  151 + for (int i = 0; i < updateChannels.size(); i += limitCount) {
  152 + int toIndex = i + limitCount;
  153 + if (i + limitCount > updateChannels.size()) {
  154 + toIndex = updateChannels.size();
  155 + }
  156 + channelMapper.batchUpdate(updateChannels.subList(i, toIndex));
  157 + }
  158 + }else {
  159 + channelMapper.batchUpdate(updateChannels);
  160 + }
  161 + }
  162 + }
  163 + return addChannels.size() + updateChannels.size();
  164 + }
  165 +}
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; @@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
8 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler; 8 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
9 import com.genersoft.iot.vmp.gb28181.utils.Coordtransform; 9 import com.genersoft.iot.vmp.gb28181.utils.Coordtransform;
  10 +import com.genersoft.iot.vmp.service.IDeviceChannelService;
10 import com.genersoft.iot.vmp.service.IDeviceService; 11 import com.genersoft.iot.vmp.service.IDeviceService;
11 import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; 12 import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
12 import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; 13 import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
@@ -56,6 +57,9 @@ public class DeviceServiceImpl implements IDeviceService { @@ -56,6 +57,9 @@ public class DeviceServiceImpl implements IDeviceService {
56 private DeviceMapper deviceMapper; 57 private DeviceMapper deviceMapper;
57 58
58 @Autowired 59 @Autowired
  60 + private IDeviceChannelService deviceChannelService;
  61 +
  62 + @Autowired
59 private DeviceChannelMapper deviceChannelMapper; 63 private DeviceChannelMapper deviceChannelMapper;
60 64
61 @Autowired 65 @Autowired
@@ -82,10 +86,10 @@ public class DeviceServiceImpl implements IDeviceService { @@ -82,10 +86,10 @@ public class DeviceServiceImpl implements IDeviceService {
82 redisCatchStorage.clearCatchByDeviceId(device.getDeviceId()); 86 redisCatchStorage.clearCatchByDeviceId(device.getDeviceId());
83 } 87 }
84 device.setUpdateTime(now); 88 device.setUpdateTime(now);
85 - device.setOnline(1);  
86 89
87 - // 第一次上线 90 + // 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询
88 if (device.getCreateTime() == null) { 91 if (device.getCreateTime() == null) {
  92 + device.setOnline(1);
89 device.setCreateTime(now); 93 device.setCreateTime(now);
90 logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId()); 94 logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId());
91 deviceMapper.add(device); 95 deviceMapper.add(device);
@@ -93,8 +97,19 @@ public class DeviceServiceImpl implements IDeviceService { @@ -93,8 +97,19 @@ public class DeviceServiceImpl implements IDeviceService {
93 commander.deviceInfoQuery(device); 97 commander.deviceInfoQuery(device);
94 sync(device); 98 sync(device);
95 }else { 99 }else {
96 - deviceMapper.update(device);  
97 - redisCatchStorage.updateDevice(device); 100 + if(device.getOnline() == 0){
  101 + device.setOnline(1);
  102 + device.setCreateTime(now);
  103 + logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId());
  104 + deviceMapper.update(device);
  105 + redisCatchStorage.updateDevice(device);
  106 + commander.deviceInfoQuery(device);
  107 + sync(device);
  108 + }else {
  109 + deviceMapper.update(device);
  110 + redisCatchStorage.updateDevice(device);
  111 + }
  112 +
98 } 113 }
99 114
100 // 上线添加订阅 115 // 上线添加订阅
@@ -121,6 +136,8 @@ public class DeviceServiceImpl implements IDeviceService { @@ -121,6 +136,8 @@ public class DeviceServiceImpl implements IDeviceService {
121 device.setOnline(0); 136 device.setOnline(0);
122 redisCatchStorage.updateDevice(device); 137 redisCatchStorage.updateDevice(device);
123 deviceMapper.update(device); 138 deviceMapper.update(device);
  139 + //进行通道离线
  140 + deviceChannelMapper.offlineByDeviceId(deviceId);
124 // 离线释放所有ssrc 141 // 离线释放所有ssrc
125 List<SsrcTransaction> ssrcTransactions = streamSession.getSsrcTransactionForAll(deviceId, null, null, null); 142 List<SsrcTransaction> ssrcTransactions = streamSession.getSsrcTransactionForAll(deviceId, null, null, null);
126 if (ssrcTransactions != null && ssrcTransactions.size() > 0) { 143 if (ssrcTransactions != null && ssrcTransactions.size() > 0) {
@@ -143,7 +160,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -143,7 +160,7 @@ public class DeviceServiceImpl implements IDeviceService {
143 logger.info("[添加目录订阅] 设备{}", device.getDeviceId()); 160 logger.info("[添加目录订阅] 设备{}", device.getDeviceId());
144 // 添加目录订阅 161 // 添加目录订阅
145 CatalogSubscribeTask catalogSubscribeTask = new CatalogSubscribeTask(device, sipCommander, dynamicTask); 162 CatalogSubscribeTask catalogSubscribeTask = new CatalogSubscribeTask(device, sipCommander, dynamicTask);
146 - // 提前开始刷新订阅 163 + // 刷新订阅
147 int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForCatalog(),30); 164 int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForCatalog(),30);
148 // 设置最小值为30 165 // 设置最小值为30
149 dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, (subscribeCycleForCatalog -1) * 1000); 166 dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, (subscribeCycleForCatalog -1) * 1000);
@@ -178,8 +195,8 @@ public class DeviceServiceImpl implements IDeviceService { @@ -178,8 +195,8 @@ public class DeviceServiceImpl implements IDeviceService {
178 MobilePositionSubscribeTask mobilePositionSubscribeTask = new MobilePositionSubscribeTask(device, sipCommander, dynamicTask); 195 MobilePositionSubscribeTask mobilePositionSubscribeTask = new MobilePositionSubscribeTask(device, sipCommander, dynamicTask);
179 // 设置最小值为30 196 // 设置最小值为30
180 int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForMobilePosition(),30); 197 int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForMobilePosition(),30);
181 - // 提前开始刷新订阅  
182 - dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, (subscribeCycleForCatalog -1 ) * 1000); 198 + // 刷新订阅
  199 + dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, (subscribeCycleForCatalog) * 1000);
183 return true; 200 return true;
184 } 201 }
185 202
@@ -324,23 +341,12 @@ public class DeviceServiceImpl implements IDeviceService { @@ -324,23 +341,12 @@ public class DeviceServiceImpl implements IDeviceService {
324 private void updateDeviceChannelGeoCoordSys(Device device) { 341 private void updateDeviceChannelGeoCoordSys(Device device) {
325 List<DeviceChannel> deviceChannels = deviceChannelMapper.getAllChannelWithCoordinate(device.getDeviceId()); 342 List<DeviceChannel> deviceChannels = deviceChannelMapper.getAllChannelWithCoordinate(device.getDeviceId());
326 if (deviceChannels.size() > 0) { 343 if (deviceChannels.size() > 0) {
  344 + List<DeviceChannel> deviceChannelsForStore = new ArrayList<>();
327 for (DeviceChannel deviceChannel : deviceChannels) { 345 for (DeviceChannel deviceChannel : deviceChannels) {
328 - if ("WGS84".equals(device.getGeoCoordSys())) {  
329 - deviceChannel.setLongitudeWgs84(deviceChannel.getLongitude());  
330 - deviceChannel.setLatitudeWgs84(deviceChannel.getLatitude());  
331 - Double[] position = Coordtransform.WGS84ToGCJ02(deviceChannel.getLongitude(), deviceChannel.getLatitude());  
332 - deviceChannel.setLongitudeGcj02(position[0]);  
333 - deviceChannel.setLatitudeGcj02(position[1]);  
334 - }else if ("GCJ02".equals(device.getGeoCoordSys())) {  
335 - deviceChannel.setLongitudeGcj02(deviceChannel.getLongitude());  
336 - deviceChannel.setLatitudeGcj02(deviceChannel.getLatitude());  
337 - Double[] position = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude());  
338 - deviceChannel.setLongitudeWgs84(position[0]);  
339 - deviceChannel.setLatitudeWgs84(position[1]);  
340 - } 346 + deviceChannelsForStore.add(deviceChannelService.updateGps(deviceChannel, device));
341 } 347 }
  348 + deviceChannelService.updateChannels(device.getDeviceId(), deviceChannelsForStore);
342 } 349 }
343 - storage.updateChannels(device.getDeviceId(), deviceChannels);  
344 } 350 }
345 351
346 352
@@ -352,11 +358,11 @@ public class DeviceServiceImpl implements IDeviceService { @@ -352,11 +358,11 @@ public class DeviceServiceImpl implements IDeviceService {
352 } 358 }
353 if (parentId == null || parentId.equals(deviceId)) { 359 if (parentId == null || parentId.equals(deviceId)) {
354 // 字根节点开始查询 360 // 字根节点开始查询
355 - List<DeviceChannel> rootNodes = getRootNodes(deviceId, "CivilCode".equals(device.getTreeType()), true, !onlyCatalog); 361 + List<DeviceChannel> rootNodes = getRootNodes(deviceId, TreeType.CIVIL_CODE.equals(device.getTreeType()), true, !onlyCatalog);
356 return transportChannelsToTree(rootNodes, ""); 362 return transportChannelsToTree(rootNodes, "");
357 } 363 }
358 364
359 - if ("CivilCode".equals(device.getTreeType())) { 365 + if (TreeType.CIVIL_CODE.equals(device.getTreeType())) {
360 if (parentId.length()%2 != 0) { 366 if (parentId.length()%2 != 0) {
361 return null; 367 return null;
362 } 368 }
@@ -386,7 +392,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -386,7 +392,7 @@ public class DeviceServiceImpl implements IDeviceService {
386 392
387 } 393 }
388 // 使用业务分组展示树 394 // 使用业务分组展示树
389 - if ("BusinessGroup".equals(device.getTreeType())) { 395 + if (TreeType.BUSINESS_GROUP.equals(device.getTreeType())) {
390 if (parentId.length() < 14 ) { 396 if (parentId.length() < 14 ) {
391 return null; 397 return null;
392 } 398 }
@@ -406,11 +412,11 @@ public class DeviceServiceImpl implements IDeviceService { @@ -406,11 +412,11 @@ public class DeviceServiceImpl implements IDeviceService {
406 } 412 }
407 if (parentId == null || parentId.equals(deviceId)) { 413 if (parentId == null || parentId.equals(deviceId)) {
408 // 字根节点开始查询 414 // 字根节点开始查询
409 - List<DeviceChannel> rootNodes = getRootNodes(deviceId, "CivilCode".equals(device.getTreeType()), false, true); 415 + List<DeviceChannel> rootNodes = getRootNodes(deviceId, TreeType.CIVIL_CODE.equals(device.getTreeType()), false, true);
410 return rootNodes; 416 return rootNodes;
411 } 417 }
412 418
413 - if ("CivilCode".equals(device.getTreeType())) { 419 + if (TreeType.CIVIL_CODE.equals(device.getTreeType())) {
414 if (parentId.length()%2 != 0) { 420 if (parentId.length()%2 != 0) {
415 return null; 421 return null;
416 } 422 }
@@ -431,7 +437,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -431,7 +437,7 @@ public class DeviceServiceImpl implements IDeviceService {
431 437
432 } 438 }
433 // 使用业务分组展示树 439 // 使用业务分组展示树
434 - if ("BusinessGroup".equals(device.getTreeType())) { 440 + if (TreeType.BUSINESS_GROUP.equals(device.getTreeType())) {
435 if (parentId.length() < 14 ) { 441 if (parentId.length() < 14 ) {
436 return null; 442 return null;
437 } 443 }
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
1 package com.genersoft.iot.vmp.service.impl; 1 package com.genersoft.iot.vmp.service.impl;
2 2
3 import com.genersoft.iot.vmp.conf.SipConfig; 3 import com.genersoft.iot.vmp.conf.SipConfig;
4 -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;  
5 -import com.genersoft.iot.vmp.gb28181.bean.GbStream;  
6 -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 4 +import com.genersoft.iot.vmp.gb28181.bean.*;
7 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 5 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
8 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; 6 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
9 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; 7 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
10 import com.genersoft.iot.vmp.storager.dao.GbStreamMapper; 8 import com.genersoft.iot.vmp.storager.dao.GbStreamMapper;
11 import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper; 9 import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
  10 +import com.genersoft.iot.vmp.storager.dao.PlatformCatalogMapper;
12 import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper; 11 import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper;
13 import com.genersoft.iot.vmp.service.IGbStreamService; 12 import com.genersoft.iot.vmp.service.IGbStreamService;
14 import com.github.pagehelper.PageHelper; 13 import com.github.pagehelper.PageHelper;
@@ -46,15 +45,15 @@ public class GbStreamServiceImpl implements IGbStreamService { @@ -46,15 +45,15 @@ public class GbStreamServiceImpl implements IGbStreamService {
46 private ParentPlatformMapper platformMapper; 45 private ParentPlatformMapper platformMapper;
47 46
48 @Autowired 47 @Autowired
49 - private SipConfig sipConfig; 48 + private PlatformCatalogMapper catalogMapper;
50 49
51 @Autowired 50 @Autowired
52 private EventPublisher eventPublisher; 51 private EventPublisher eventPublisher;
53 52
54 @Override 53 @Override
55 - public PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId, String query, Boolean pushing, String mediaServerId) { 54 + public PageInfo<GbStream> getAll(Integer page, Integer count, String platFormId, String catalogId, String query, String mediaServerId) {
56 PageHelper.startPage(page, count); 55 PageHelper.startPage(page, count);
57 - List<GbStream> all = gbStreamMapper.selectAll(platFormId, catalogId, query, pushing, mediaServerId); 56 + List<GbStream> all = gbStreamMapper.selectAll(platFormId, catalogId, query, mediaServerId);
58 return new PageInfo<>(all); 57 return new PageInfo<>(all);
59 } 58 }
60 59
@@ -102,16 +101,25 @@ public class GbStreamServiceImpl implements IGbStreamService { @@ -102,16 +101,25 @@ public class GbStreamServiceImpl implements IGbStreamService {
102 deviceChannel.setLatitude(gbStream.getLatitude()); 101 deviceChannel.setLatitude(gbStream.getLatitude());
103 deviceChannel.setDeviceId(platform.getDeviceGBId()); 102 deviceChannel.setDeviceId(platform.getDeviceGBId());
104 deviceChannel.setManufacture("wvp-pro"); 103 deviceChannel.setManufacture("wvp-pro");
105 -// deviceChannel.setStatus(gbStream.isStatus()?1:0);  
106 - deviceChannel.setStatus(1);  
107 - deviceChannel.setParentId(catalogId ==null?gbStream.getCatalogId():catalogId); 104 + deviceChannel.setStatus(gbStream.isStatus()?1:0);
  105 +
108 deviceChannel.setRegisterWay(1); 106 deviceChannel.setRegisterWay(1);
109 - if (catalogId.length() > 0 && catalogId.length() <= 10) {  
110 - // 父节点是行政区划,则设置CivilCode使用此行政区划 107 + deviceChannel.setCivilCode(platform.getAdministrativeDivision());
  108 +
  109 + if (platform.getTreeType().equals(TreeType.CIVIL_CODE)){
111 deviceChannel.setCivilCode(catalogId); 110 deviceChannel.setCivilCode(catalogId);
112 - }else {  
113 - deviceChannel.setCivilCode(platform.getAdministrativeDivision()); 111 + }else if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)){
  112 + PlatformCatalog catalog = catalogMapper.select(catalogId);
  113 + if (catalog == null) {
  114 + deviceChannel.setParentId(platform.getDeviceGBId());
  115 + deviceChannel.setBusinessGroupId(null);
  116 + }else {
  117 + deviceChannel.setParentId(catalog.getId());
  118 + deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
  119 + }
  120 +
114 } 121 }
  122 +
115 deviceChannel.setModel("live"); 123 deviceChannel.setModel("live");
116 deviceChannel.setOwner("wvp-pro"); 124 deviceChannel.setOwner("wvp-pro");
117 deviceChannel.setParental(0); 125 deviceChannel.setParental(0);
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
1 package com.genersoft.iot.vmp.service.impl; 1 package com.genersoft.iot.vmp.service.impl;
2 2
  3 +import java.time.LocalDateTime;
  4 +import java.util.ArrayList;
  5 +import java.util.Collections;
  6 +import java.util.HashMap;
  7 +import java.util.List;
  8 +import java.util.Map;
  9 +import java.util.Set;
  10 +
  11 +import com.genersoft.iot.vmp.media.zlm.ZLMRunner;
  12 +import com.genersoft.iot.vmp.service.IStreamProxyService;
  13 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  14 +import org.slf4j.Logger;
  15 +import org.slf4j.LoggerFactory;
  16 +import org.springframework.beans.factory.annotation.Autowired;
  17 +import org.springframework.beans.factory.annotation.Value;
  18 +import org.springframework.jdbc.datasource.DataSourceTransactionManager;
  19 +import org.springframework.stereotype.Service;
  20 +import org.springframework.transaction.TransactionDefinition;
  21 +import org.springframework.transaction.TransactionStatus;
  22 +import org.springframework.util.StringUtils;
  23 +
3 import com.alibaba.fastjson.JSON; 24 import com.alibaba.fastjson.JSON;
4 import com.alibaba.fastjson.JSONArray; 25 import com.alibaba.fastjson.JSONArray;
5 import com.alibaba.fastjson.JSONObject; 26 import com.alibaba.fastjson.JSONObject;
@@ -14,25 +35,16 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; @@ -14,25 +35,16 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
14 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; 35 import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
15 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 36 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
16 import com.genersoft.iot.vmp.service.IMediaServerService; 37 import com.genersoft.iot.vmp.service.IMediaServerService;
17 -import com.genersoft.iot.vmp.service.IStreamProxyService;  
18 import com.genersoft.iot.vmp.service.bean.SSRCInfo; 38 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
19 -import com.genersoft.iot.vmp.storager.IVideoManagerStorage;  
20 import com.genersoft.iot.vmp.storager.dao.MediaServerMapper; 39 import com.genersoft.iot.vmp.storager.dao.MediaServerMapper;
21 import com.genersoft.iot.vmp.utils.DateUtil; 40 import com.genersoft.iot.vmp.utils.DateUtil;
22 import com.genersoft.iot.vmp.utils.redis.JedisUtil; 41 import com.genersoft.iot.vmp.utils.redis.JedisUtil;
23 import com.genersoft.iot.vmp.utils.redis.RedisUtil; 42 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
24 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 43 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
25 -import okhttp3.*;  
26 -import org.slf4j.Logger;  
27 -import org.slf4j.LoggerFactory;  
28 -import org.springframework.beans.factory.annotation.Autowired;  
29 -import org.springframework.beans.factory.annotation.Value;  
30 -import org.springframework.jdbc.datasource.DataSourceTransactionManager;  
31 -import org.springframework.stereotype.Service;  
32 -import org.springframework.transaction.TransactionDefinition;  
33 -import org.springframework.transaction.TransactionStatus;  
34 -import org.springframework.util.StringUtils;  
35 44
  45 +import okhttp3.OkHttpClient;
  46 +import okhttp3.Request;
  47 +import okhttp3.Response;
36 import java.time.LocalDateTime; 48 import java.time.LocalDateTime;
37 import java.util.*; 49 import java.util.*;
38 50
@@ -47,6 +59,9 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -47,6 +59,9 @@ public class MediaServerServiceImpl implements IMediaServerService {
47 @Autowired 59 @Autowired
48 private SipConfig sipConfig; 60 private SipConfig sipConfig;
49 61
  62 + @Autowired
  63 + private ZLMRunner zlmRunner;
  64 +
50 @Value("${server.ssl.enabled:false}") 65 @Value("${server.ssl.enabled:false}")
51 private boolean sslEnabled; 66 private boolean sslEnabled;
52 67
@@ -120,7 +135,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -120,7 +135,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
120 } 135 }
121 136
122 @Override 137 @Override
123 - public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, boolean isPlayback) { 138 + public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, boolean isPlayback, Integer port) {
124 if (mediaServerItem == null || mediaServerItem.getId() == null) { 139 if (mediaServerItem == null || mediaServerItem.getId() == null) {
125 return null; 140 return null;
126 } 141 }
@@ -148,7 +163,7 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -148,7 +163,7 @@ public class MediaServerServiceImpl implements IMediaServerService {
148 } 163 }
149 int rtpServerPort = mediaServerItem.getRtpProxyPort(); 164 int rtpServerPort = mediaServerItem.getRtpProxyPort();
150 if (mediaServerItem.isRtpEnable()) { 165 if (mediaServerItem.isRtpEnable()) {
151 - rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0); 166 + rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck?Integer.parseInt(ssrc):0, port);
152 } 167 }
153 redisUtil.set(key, mediaServerItem); 168 redisUtil.set(key, mediaServerItem);
154 return new SSRCInfo(rtpServerPort, ssrc, streamId); 169 return new SSRCInfo(rtpServerPort, ssrc, streamId);
@@ -156,6 +171,11 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -156,6 +171,11 @@ public class MediaServerServiceImpl implements IMediaServerService {
156 } 171 }
157 172
158 @Override 173 @Override
  174 + public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback) {
  175 + return openRTPServer(mediaServerItem, streamId, ssrc, ssrcCheck, isPlayback, null);
  176 + }
  177 +
  178 + @Override
159 public void closeRTPServer(String deviceId, String channelId, String stream) { 179 public void closeRTPServer(String deviceId, String channelId, String stream) {
160 String mediaServerId = streamSession.getMediaServerId(deviceId, channelId, stream); 180 String mediaServerId = streamSession.getMediaServerId(deviceId, channelId, stream);
161 String ssrc = streamSession.getSSRC(deviceId, channelId, stream); 181 String ssrc = streamSession.getSSRC(deviceId, channelId, stream);
@@ -271,7 +291,13 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -271,7 +291,13 @@ public class MediaServerServiceImpl implements IMediaServerService {
271 return null; 291 return null;
272 } 292 }
273 String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerId; 293 String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerId;
274 - return (MediaServerItem)redisUtil.get(key); 294 + MediaServerItem serverItem=(MediaServerItem)redisUtil.get(key);
  295 + if(null==serverItem){
  296 + //zlm服务不在线,启动重连
  297 + reloadZlm();
  298 + serverItem=(MediaServerItem)redisUtil.get(key);
  299 + }
  300 + return serverItem;
275 } 301 }
276 302
277 @Override 303 @Override
@@ -351,14 +377,15 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -351,14 +377,15 @@ public class MediaServerServiceImpl implements IMediaServerService {
351 */ 377 */
352 @Override 378 @Override
353 public void zlmServerOnline(ZLMServerConfig zlmServerConfig) { 379 public void zlmServerOnline(ZLMServerConfig zlmServerConfig) {
354 - logger.info("[ZLM] 正在连接 : {} -> {}:{}",  
355 - zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());  
356 380
357 MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()); 381 MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId());
358 if (serverItem == null) { 382 if (serverItem == null) {
359 logger.warn("[未注册的zlm] 拒接接入:{}来自{}:{}", zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(),zlmServerConfig.getHttpPort() ); 383 logger.warn("[未注册的zlm] 拒接接入:{}来自{}:{}", zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(),zlmServerConfig.getHttpPort() );
360 logger.warn("请检查ZLM的<general.mediaServerId>配置是否与WVP的<media.id>一致"); 384 logger.warn("请检查ZLM的<general.mediaServerId>配置是否与WVP的<media.id>一致");
361 return; 385 return;
  386 + }else {
  387 + logger.info("[ZLM] 正在连接 : {} -> {}:{}",
  388 + zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort());
362 } 389 }
363 serverItem.setHookAliveInterval(zlmServerConfig.getHookAliveInterval()); 390 serverItem.setHookAliveInterval(zlmServerConfig.getHookAliveInterval());
364 if (serverItem.getHttpPort() == 0) { 391 if (serverItem.getHttpPort() == 0) {
@@ -463,8 +490,13 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -463,8 +490,13 @@ public class MediaServerServiceImpl implements IMediaServerService {
463 String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(); 490 String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId();
464 491
465 if (redisUtil.zSize(key) == null || redisUtil.zSize(key) == 0) { 492 if (redisUtil.zSize(key) == null || redisUtil.zSize(key) == 0) {
466 - logger.info("获取负载最低的节点时无在线节点");  
467 - return null; 493 + logger.info("获取负载最低的节点时无在线节点,启动重连机制");
  494 + //启动重连
  495 + reloadZlm();
  496 + if (redisUtil.zSize(key) == null || redisUtil.zSize(key) == 0) {
  497 + logger.info("获取负载最低的节点时无在线节点");
  498 + return null;
  499 + }
468 } 500 }
469 501
470 // 获取分数最低的,及并发最低的 502 // 获取分数最低的,及并发最低的
@@ -595,9 +627,6 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -595,9 +627,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
595 boolean result = false; 627 boolean result = false;
596 OkHttpClient client = new OkHttpClient(); 628 OkHttpClient client = new OkHttpClient();
597 String url = String.format("http://%s:%s/index/api/record", ip, port); 629 String url = String.format("http://%s:%s/index/api/record", ip, port);
598 -  
599 - FormBody.Builder builder = new FormBody.Builder();  
600 -  
601 Request request = new Request.Builder() 630 Request request = new Request.Builder()
602 .get() 631 .get()
603 .url(url) 632 .url(url)
@@ -629,9 +658,14 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -629,9 +658,14 @@ public class MediaServerServiceImpl implements IMediaServerService {
629 MediaServerItem mediaServerItem = getOne(mediaServerId); 658 MediaServerItem mediaServerItem = getOne(mediaServerId);
630 if (mediaServerItem == null) { 659 if (mediaServerItem == null) {
631 // zlm连接重试 660 // zlm连接重试
632 -  
633 - logger.warn("[更新ZLM 保活信息]失败,未找到流媒体信息");  
634 - return; 661 + logger.warn("[更新ZLM 保活信息]失败,未找到流媒体信息,尝试重连zlm");
  662 + reloadZlm();
  663 + mediaServerItem = getOne(mediaServerId);
  664 + if (mediaServerItem == null) {
  665 + // zlm连接重试
  666 + logger.warn("[更新ZLM 保活信息]失败,未找到流媒体信息");
  667 + return;
  668 + }
635 } 669 }
636 String key = VideoManagerConstants.MEDIA_SERVER_KEEPALIVE_PREFIX + userSetting.getServerId() + "_" + mediaServerId; 670 String key = VideoManagerConstants.MEDIA_SERVER_KEEPALIVE_PREFIX + userSetting.getServerId() + "_" + mediaServerId;
637 int hookAliveInterval = mediaServerItem.getHookAliveInterval() + 2; 671 int hookAliveInterval = mediaServerItem.getHookAliveInterval() + 2;
@@ -648,10 +682,18 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -648,10 +682,18 @@ public class MediaServerServiceImpl implements IMediaServerService {
648 mediaServerItemMap.put(mediaServerItem.getId(), mediaServerItem); 682 mediaServerItemMap.put(mediaServerItem.getId(), mediaServerItem);
649 } 683 }
650 for (MediaServerItem mediaServerItem : allInCatch) { 684 for (MediaServerItem mediaServerItem : allInCatch) {
651 - if (mediaServerItemMap.get(mediaServerItem) == null) { 685 + if (!mediaServerItemMap.containsKey(mediaServerItem.getId())) {
652 delete(mediaServerItem.getId()); 686 delete(mediaServerItem.getId());
653 } 687 }
654 } 688 }
655 } 689 }
656 690
  691 + public void reloadZlm(){
  692 + try {
  693 + zlmRunner.run();
  694 + Thread.sleep(500);//延迟0.5秒缓冲时间
  695 + } catch (Exception e) {
  696 + logger.warn("尝试重连zlm失败!",e);
  697 + }
  698 + }
657 } 699 }
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
@@ -67,9 +67,9 @@ public class MediaServiceImpl implements IMediaService { @@ -67,9 +67,9 @@ public class MediaServiceImpl implements IMediaService {
67 JSONObject mediaJSON = JSON.parseObject(JSON.toJSONString(data.get(0)), JSONObject.class); 67 JSONObject mediaJSON = JSON.parseObject(JSON.toJSONString(data.get(0)), JSONObject.class);
68 JSONArray tracks = mediaJSON.getJSONArray("tracks"); 68 JSONArray tracks = mediaJSON.getJSONArray("tracks");
69 if (authority) { 69 if (authority) {
70 - streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null, streamAuthorityInfo.getCallId(), true); 70 + streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,streamAuthorityInfo.getCallId(), true);
71 }else { 71 }else {
72 - streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null); 72 + streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,null);
73 } 73 }
74 74
75 } 75 }
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service.impl;
  2 +
  3 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  4 +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  5 +import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
  6 +import com.genersoft.iot.vmp.gb28181.bean.TreeType;
  7 +import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
  8 +import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
  9 +import com.genersoft.iot.vmp.service.IPlatformChannelService;
  10 +import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
  11 +import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
  12 +import com.genersoft.iot.vmp.storager.dao.PlatformCatalogMapper;
  13 +import com.genersoft.iot.vmp.storager.dao.PlatformChannelMapper;
  14 +import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce;
  15 +import org.slf4j.Logger;
  16 +import org.slf4j.LoggerFactory;
  17 +import org.springframework.beans.factory.annotation.Autowired;
  18 +import org.springframework.stereotype.Service;
  19 +
  20 +import java.util.ArrayList;
  21 +import java.util.HashMap;
  22 +import java.util.List;
  23 +import java.util.Map;
  24 +
  25 +/**
  26 + * @author lin
  27 + */
  28 +@Service
  29 +public class PlatformChannelServiceImpl implements IPlatformChannelService {
  30 +
  31 + private final static Logger logger = LoggerFactory.getLogger(PlatformChannelServiceImpl.class);
  32 +
  33 + @Autowired
  34 + private PlatformChannelMapper platformChannelMapper;
  35 +
  36 + @Autowired
  37 + private DeviceChannelMapper deviceChannelMapper;
  38 +
  39 + @Autowired
  40 + private PlatformCatalogMapper catalogManager;
  41 +
  42 + @Autowired
  43 + private ParentPlatformMapper platformMapper;
  44 +
  45 + @Autowired
  46 + EventPublisher eventPublisher;
  47 +
  48 + @Override
  49 + public int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId) {
  50 + ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformId);
  51 + if (platform == null) {
  52 + logger.warn("更新级联通道信息时未找到平台{}的信息", platformId);
  53 + return 0;
  54 + }
  55 + Map<Integer, ChannelReduce> deviceAndChannels = new HashMap<>();
  56 + for (ChannelReduce channelReduce : channelReduces) {
  57 + channelReduce.setCatalogId(catalogId);
  58 + deviceAndChannels.put(channelReduce.getId(), channelReduce);
  59 + }
  60 + List<Integer> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet());
  61 + // 查询当前已经存在的
  62 + List<Integer> channelIds = platformChannelMapper.findChannelRelatedPlatform(platformId, channelReduces);
  63 + if (deviceAndChannelList != null) {
  64 + deviceAndChannelList.removeAll(channelIds);
  65 + }
  66 + for (Integer channelId : channelIds) {
  67 + deviceAndChannels.remove(channelId);
  68 + }
  69 + List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values());
  70 + // 对剩下的数据进行存储
  71 + int result = 0;
  72 + if (channelReducesToAdd.size() > 0) {
  73 + result = platformChannelMapper.addChannels(platformId, channelReducesToAdd);
  74 + // TODO 后续给平台增加控制开关以控制是否响应目录订阅
  75 + List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId, platform);
  76 + eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);
  77 + }
  78 +
  79 + return result;
  80 + }
  81 +
  82 + private List<DeviceChannel> getDeviceChannelListByChannelReduceList(List<ChannelReduce> channelReduces, String catalogId, ParentPlatform platform) {
  83 + List<DeviceChannel> deviceChannelList = new ArrayList<>();
  84 + if (channelReduces.size() > 0){
  85 + PlatformCatalog catalog = catalogManager.select(catalogId);
  86 + if (catalog == null && !catalogId.equals(platform.getServerGBId())) {
  87 + logger.warn("未查询到目录{}的信息", catalogId);
  88 + return null;
  89 + }
  90 + for (ChannelReduce channelReduce : channelReduces) {
  91 + DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId());
  92 + deviceChannel.setParental(0);
  93 + deviceChannelList.add(deviceChannel);
  94 + if (platform.getTreeType().equals(TreeType.CIVIL_CODE)){
  95 + deviceChannel.setCivilCode(catalogId);
  96 + }else if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)){
  97 + deviceChannel.setParentId(catalogId);
  98 + if (catalog != null) {
  99 + deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
  100 + }
  101 + }
  102 + }
  103 + }
  104 + return deviceChannelList;
  105 + }
  106 +}
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
1 package com.genersoft.iot.vmp.service.impl; 1 package com.genersoft.iot.vmp.service.impl;
2 2
  3 +import java.math.BigDecimal;
  4 +import java.math.RoundingMode;
  5 +import java.util.List;
  6 +import java.util.Objects;
  7 +import java.util.UUID;
  8 +
  9 +import javax.sip.ResponseEvent;
  10 +
  11 +import org.slf4j.Logger;
  12 +import org.slf4j.LoggerFactory;
  13 +import org.springframework.beans.factory.annotation.Autowired;
  14 +import org.springframework.http.HttpStatus;
  15 +import org.springframework.http.ResponseEntity;
  16 +import org.springframework.stereotype.Service;
  17 +import org.springframework.web.context.request.async.DeferredResult;
  18 +
3 import com.alibaba.fastjson.JSON; 19 import com.alibaba.fastjson.JSON;
4 import com.alibaba.fastjson.JSONArray; 20 import com.alibaba.fastjson.JSONArray;
5 import com.alibaba.fastjson.JSONObject; 21 import com.alibaba.fastjson.JSONObject;
@@ -7,7 +23,13 @@ import com.genersoft.iot.vmp.common.StreamInfo; @@ -7,7 +23,13 @@ import com.genersoft.iot.vmp.common.StreamInfo;
7 import com.genersoft.iot.vmp.conf.DynamicTask; 23 import com.genersoft.iot.vmp.conf.DynamicTask;
8 import com.genersoft.iot.vmp.conf.SipConfig; 24 import com.genersoft.iot.vmp.conf.SipConfig;
9 import com.genersoft.iot.vmp.conf.UserSetting; 25 import com.genersoft.iot.vmp.conf.UserSetting;
10 -import com.genersoft.iot.vmp.gb28181.bean.*; 26 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  27 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
  28 +import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
  29 +import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;
  30 +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  31 +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
  32 +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
11 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 33 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
12 import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; 34 import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager;
13 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 35 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
@@ -16,6 +38,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; @@ -16,6 +38,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
16 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 38 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
17 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; 39 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
18 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; 40 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
  41 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
  42 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
  43 +import com.genersoft.iot.vmp.media.zlm.dto.HookType;
19 import com.genersoft.iot.vmp.utils.DateUtil; 44 import com.genersoft.iot.vmp.utils.DateUtil;
20 import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; 45 import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
21 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; 46 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
@@ -32,9 +57,11 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage; @@ -32,9 +57,11 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
32 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 57 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
33 import com.genersoft.iot.vmp.utils.redis.RedisUtil; 58 import com.genersoft.iot.vmp.utils.redis.RedisUtil;
34 import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; 59 import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
  60 +import com.genersoft.iot.vmp.utils.DateUtil;
35 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 61 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
36 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; 62 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent;
37 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; 63 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
  64 +
38 import gov.nist.javax.sip.stack.SIPDialog; 65 import gov.nist.javax.sip.stack.SIPDialog;
39 import org.slf4j.Logger; 66 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory; 67 import org.slf4j.LoggerFactory;
@@ -313,16 +340,10 @@ public class PlayServiceImpl implements IPlayService { @@ -313,16 +340,10 @@ public class PlayServiceImpl implements IPlayService {
313 // 单端口模式streamId也有变化,需要重新设置监听 340 // 单端口模式streamId也有变化,需要重新设置监听
314 if (!mediaServerItem.isRtpEnable()) { 341 if (!mediaServerItem.isRtpEnable()) {
315 // 添加订阅 342 // 添加订阅
316 - JSONObject subscribeKey = new JSONObject();  
317 - subscribeKey.put("app", "rtp");  
318 - subscribeKey.put("stream", stream);  
319 - subscribeKey.put("regist", true);  
320 - subscribeKey.put("schema", "rtmp");  
321 - subscribeKey.put("mediaServerId", mediaServerItem.getId());  
322 - subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed,subscribeKey);  
323 - subscribeKey.put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());  
324 - subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,  
325 - (MediaServerItem mediaServerItemInUse, JSONObject response)->{ 343 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtmp", mediaServerItem.getId());
  344 + subscribe.removeSubscribe(hookSubscribe);
  345 + hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
  346 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response)->{
326 logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString()); 347 logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());
327 dynamicTask.stop(timeOutTaskKey); 348 dynamicTask.stop(timeOutTaskKey);
328 // hook响应 349 // hook响应
@@ -333,7 +354,7 @@ public class PlayServiceImpl implements IPlayService { @@ -333,7 +354,7 @@ public class PlayServiceImpl implements IPlayService {
333 // 关闭rtp server 354 // 关闭rtp server
334 mediaServerService.closeRTPServer(device.getDeviceId(), channelId, finalSsrcInfo.getStream()); 355 mediaServerService.closeRTPServer(device.getDeviceId(), channelId, finalSsrcInfo.getStream());
335 // 重新开启ssrc server 356 // 重新开启ssrc server
336 - mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false); 357 + mediaServerService.openRTPServer(mediaServerItem, finalSsrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), false, finalSsrcInfo.getPort());
337 358
338 } 359 }
339 } 360 }
src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java
@@ -8,6 +8,9 @@ import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; @@ -8,6 +8,9 @@ import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
8 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; 8 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
9 import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; 9 import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
10 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; 10 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
  11 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
  12 +import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
  13 +import com.genersoft.iot.vmp.media.zlm.dto.HookType;
11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 14 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
12 import com.genersoft.iot.vmp.service.IMediaServerService; 15 import com.genersoft.iot.vmp.service.IMediaServerService;
13 import com.genersoft.iot.vmp.service.bean.*; 16 import com.genersoft.iot.vmp.service.bean.*;
@@ -270,14 +273,9 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -270,14 +273,9 @@ public class RedisGbPlayMsgListener implements MessageListener {
270 }, userSetting.getPlatformPlayTimeout()); 273 }, userSetting.getPlatformPlayTimeout());
271 274
272 // 添加订阅 275 // 添加订阅
273 - JSONObject subscribeKey = new JSONObject();  
274 - subscribeKey.put("app", content.getApp());  
275 - subscribeKey.put("stream", content.getStream());  
276 - subscribeKey.put("regist", true);  
277 - subscribeKey.put("schema", "rtmp");  
278 - subscribeKey.put("mediaServerId", mediaServerItem.getId());  
279 - subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey,  
280 - (MediaServerItem mediaServerItemInUse, JSONObject json)->{ 276 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed(content.getApp(), content.getStream(), true, "rtmp", mediaServerItem.getId());
  277 +
  278 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json)->{
281 dynamicTask.stop(taskKey); 279 dynamicTask.stop(taskKey);
282 responseSendItem(mediaServerItem, content, toId, serial); 280 responseSendItem(mediaServerItem, content, toId, serial);
283 }); 281 });
src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java
1 package com.genersoft.iot.vmp.service.impl; 1 package com.genersoft.iot.vmp.service.impl;
2 2
3 import com.alibaba.fastjson.JSON; 3 import com.alibaba.fastjson.JSON;
  4 +import com.genersoft.iot.vmp.gb28181.bean.HandlerCatchData;
4 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 5 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
5 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 6 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  7 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
6 import org.jetbrains.annotations.NotNull; 8 import org.jetbrains.annotations.NotNull;
7 import org.slf4j.Logger; 9 import org.slf4j.Logger;
8 import org.slf4j.LoggerFactory; 10 import org.slf4j.LoggerFactory;
9 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.beans.factory.annotation.Autowired;
  12 +import org.springframework.beans.factory.annotation.Qualifier;
10 import org.springframework.data.redis.connection.Message; 13 import org.springframework.data.redis.connection.Message;
11 import org.springframework.data.redis.connection.MessageListener; 14 import org.springframework.data.redis.connection.MessageListener;
  15 +import org.springframework.scheduling.annotation.Scheduled;
  16 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
12 import org.springframework.stereotype.Component; 17 import org.springframework.stereotype.Component;
13 18
  19 +import java.util.List;
  20 +import java.util.concurrent.ConcurrentLinkedQueue;
  21 +
14 /** 22 /**
15 * 接收来自redis的GPS更新通知 23 * 接收来自redis的GPS更新通知
16 * @author lin 24 * @author lin
@@ -20,12 +28,50 @@ public class RedisGpsMsgListener implements MessageListener { @@ -20,12 +28,50 @@ public class RedisGpsMsgListener implements MessageListener {
20 28
21 private final static Logger logger = LoggerFactory.getLogger(RedisGpsMsgListener.class); 29 private final static Logger logger = LoggerFactory.getLogger(RedisGpsMsgListener.class);
22 30
  31 + private boolean taskQueueHandlerRun = false;
  32 +
23 @Autowired 33 @Autowired
24 private IRedisCatchStorage redisCatchStorage; 34 private IRedisCatchStorage redisCatchStorage;
25 35
  36 + @Autowired
  37 + private IVideoManagerStorage storager;
  38 +
  39 + private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
  40 +
  41 + @Qualifier("taskExecutor")
  42 + @Autowired
  43 + private ThreadPoolTaskExecutor taskExecutor;
  44 +
  45 +
26 @Override 46 @Override
27 public void onMessage(@NotNull Message message, byte[] bytes) { 47 public void onMessage(@NotNull Message message, byte[] bytes) {
28 - GPSMsgInfo gpsMsgInfo = JSON.parseObject(message.getBody(), GPSMsgInfo.class);  
29 - redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo); 48 + taskQueue.offer(message);
  49 + if (!taskQueueHandlerRun) {
  50 + taskQueueHandlerRun = true;
  51 + taskExecutor.execute(() -> {
  52 + while (!taskQueue.isEmpty()) {
  53 + Message msg = taskQueue.poll();
  54 + GPSMsgInfo gpsMsgInfo = JSON.parseObject(msg.getBody(), GPSMsgInfo.class);
  55 + // 只是放入redis缓存起来
  56 + redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo);
  57 + }
  58 + taskQueueHandlerRun = false;
  59 + });
  60 + }
  61 + }
  62 +
  63 + /**
  64 + * 定时将经纬度更新到数据库
  65 + */
  66 + @Scheduled(fixedRate = 2 * 1000) //每2秒执行一次
  67 + public void execute(){
  68 + List<GPSMsgInfo> gpsMsgInfo = redisCatchStorage.getAllGpsMsgInfo();
  69 + if (gpsMsgInfo.size() > 0) {
  70 + storager.updateStreamGPS(gpsMsgInfo);
  71 + for (GPSMsgInfo msgInfo : gpsMsgInfo) {
  72 + msgInfo.setStored(true);
  73 + redisCatchStorage.updateGpsMsgInfo(msgInfo);
  74 + }
  75 + }
30 } 76 }
31 } 77 }
src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusMsgListener.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service.impl;
  2 +
  3 +import com.alibaba.fastjson.JSON;
  4 +import com.alibaba.fastjson.JSONObject;
  5 +import com.genersoft.iot.vmp.common.VideoManagerConstants;
  6 +import com.genersoft.iot.vmp.conf.DynamicTask;
  7 +import com.genersoft.iot.vmp.conf.UserSetting;
  8 +import com.genersoft.iot.vmp.gb28181.bean.GbStream;
  9 +import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
  10 +import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
  11 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
  12 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
  13 +import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
  14 +import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
  15 +import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
  16 +import com.genersoft.iot.vmp.service.IStreamPushService;
  17 +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
  18 +import com.genersoft.iot.vmp.service.bean.PushStreamStatusChangeFromRedisDto;
  19 +import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
  20 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  21 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
  22 +import org.slf4j.Logger;
  23 +import org.slf4j.LoggerFactory;
  24 +import org.springframework.beans.factory.annotation.Autowired;
  25 +import org.springframework.beans.factory.annotation.Qualifier;
  26 +import org.springframework.boot.ApplicationArguments;
  27 +import org.springframework.boot.ApplicationRunner;
  28 +import org.springframework.data.redis.connection.Message;
  29 +import org.springframework.data.redis.connection.MessageListener;
  30 +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
  31 +import org.springframework.stereotype.Component;
  32 +
  33 +import java.util.ArrayList;
  34 +import java.util.List;
  35 +import java.util.concurrent.ConcurrentLinkedQueue;
  36 +
  37 +
  38 +/**
  39 + * 接收redis发送的推流设备上线下线通知
  40 + * @author lin
  41 + */
  42 +@Component
  43 +public class RedisPushStreamStatusMsgListener implements MessageListener, ApplicationRunner {
  44 +
  45 + private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamStatusMsgListener.class);
  46 +
  47 + private boolean taskQueueHandlerRun = false;
  48 +
  49 + @Autowired
  50 + private IRedisCatchStorage redisCatchStorage;
  51 +
  52 + @Autowired
  53 + private IStreamPushService streamPushService;
  54 +
  55 + @Autowired
  56 + private DynamicTask dynamicTask;
  57 +
  58 +
  59 +
  60 + private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>();
  61 +
  62 + @Qualifier("taskExecutor")
  63 + @Autowired
  64 + private ThreadPoolTaskExecutor taskExecutor;
  65 +
  66 + @Override
  67 + public void onMessage(Message message, byte[] bytes) {
  68 + // TODO 增加队列
  69 + logger.warn("[REDIS消息-推流设备状态变化]: {}", new String(message.getBody()));
  70 + taskQueue.offer(message);
  71 +
  72 + if (!taskQueueHandlerRun) {
  73 + taskQueueHandlerRun = true;
  74 + taskExecutor.execute(() -> {
  75 + while (!taskQueue.isEmpty()) {
  76 + Message msg = taskQueue.poll();
  77 + PushStreamStatusChangeFromRedisDto statusChangeFromPushStream = JSON.parseObject(msg.getBody(), PushStreamStatusChangeFromRedisDto.class);
  78 + if (statusChangeFromPushStream == null) {
  79 + logger.warn("[REDIS消息]推流设备状态变化消息解析失败");
  80 + return;
  81 + }
  82 + // 取消定时任务
  83 + dynamicTask.stop(VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED);
  84 + if (statusChangeFromPushStream.isSetAllOffline()) {
  85 + // 所有设备离线
  86 + streamPushService.allStreamOffline();
  87 + }
  88 + if (statusChangeFromPushStream.getOfflineStreams() != null
  89 + && statusChangeFromPushStream.getOfflineStreams().size() > 0) {
  90 + // 更新部分设备离线
  91 + streamPushService.offline(statusChangeFromPushStream.getOfflineStreams());
  92 + }
  93 + if (statusChangeFromPushStream.getOnlineStreams() != null &&
  94 + statusChangeFromPushStream.getOnlineStreams().size() > 0) {
  95 + // 更新部分设备上线
  96 + streamPushService.online(statusChangeFromPushStream.getOnlineStreams());
  97 + }
  98 + }
  99 + taskQueueHandlerRun = false;
  100 + });
  101 + }
  102 + }
  103 +
  104 + @Override
  105 + public void run(ApplicationArguments args) throws Exception {
  106 + // 启动时设置所有推流通道离线,发起查询请求
  107 + redisCatchStorage.sendStreamPushRequestedMsgForStatus();
  108 + dynamicTask.startDelay(VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED, ()->{
  109 + logger.info("[REDIS消息]未收到redis回复推流设备状态,执行推流设备离线");
  110 + // 五秒收不到请求就设置通道离线,然后通知上级离线
  111 + streamPushService.allStreamOffline();
  112 + }, 5000);
  113 + }
  114 +
  115 +}
src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java
@@ -3,16 +3,12 @@ package com.genersoft.iot.vmp.service.impl; @@ -3,16 +3,12 @@ package com.genersoft.iot.vmp.service.impl;
3 import com.alibaba.fastjson.JSON; 3 import com.alibaba.fastjson.JSON;
4 import com.alibaba.fastjson.JSONObject; 4 import com.alibaba.fastjson.JSONObject;
5 import com.genersoft.iot.vmp.conf.UserSetting; 5 import com.genersoft.iot.vmp.conf.UserSetting;
6 -import com.genersoft.iot.vmp.gb28181.bean.AlarmChannelMessage;  
7 -import com.genersoft.iot.vmp.gb28181.bean.Device;  
8 -import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;  
9 -import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 6 +
10 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; 7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 8 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
12 import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; 9 import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager;
13 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
14 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 11 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
15 -import com.genersoft.iot.vmp.utils.DateUtil;  
16 import org.slf4j.Logger; 12 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory; 13 import org.slf4j.LoggerFactory;
18 import org.springframework.beans.factory.annotation.Autowired; 14 import org.springframework.beans.factory.annotation.Autowired;
@@ -22,6 +18,7 @@ import org.springframework.stereotype.Component; @@ -22,6 +18,7 @@ import org.springframework.stereotype.Component;
22 18
23 19
24 /** 20 /**
  21 + * 接收其他wvp发送流变化通知
25 * @author lin 22 * @author lin
26 */ 23 */
27 @Component 24 @Component
@@ -49,7 +46,7 @@ public class RedisStreamMsgListener implements MessageListener { @@ -49,7 +46,7 @@ public class RedisStreamMsgListener implements MessageListener {
49 46
50 JSONObject steamMsgJson = JSON.parseObject(message.getBody(), JSONObject.class); 47 JSONObject steamMsgJson = JSON.parseObject(message.getBody(), JSONObject.class);
51 if (steamMsgJson == null) { 48 if (steamMsgJson == null) {
52 - logger.warn("[REDIS的ALARM通知]消息解析失败"); 49 + logger.warn("[收到redis 流变化]消息解析失败");
53 return; 50 return;
54 } 51 }
55 String serverId = steamMsgJson.getString("serverId"); 52 String serverId = steamMsgJson.getString("serverId");
@@ -58,7 +55,7 @@ public class RedisStreamMsgListener implements MessageListener { @@ -58,7 +55,7 @@ public class RedisStreamMsgListener implements MessageListener {
58 // 自己发送的消息忽略即可 55 // 自己发送的消息忽略即可
59 return; 56 return;
60 } 57 }
61 - logger.info("[REDIS通知] 流变化: {}", new String(message.getBody())); 58 + logger.info("[收到redis 流变化]: {}", new String(message.getBody()));
62 String app = steamMsgJson.getString("app"); 59 String app = steamMsgJson.getString("app");
63 String stream = steamMsgJson.getString("stream"); 60 String stream = steamMsgJson.getString("stream");
64 boolean register = steamMsgJson.getBoolean("register"); 61 boolean register = steamMsgJson.getBoolean("register");
@@ -75,9 +72,10 @@ public class RedisStreamMsgListener implements MessageListener { @@ -75,9 +72,10 @@ public class RedisStreamMsgListener implements MessageListener {
75 mediaItem.setOriginType(0); 72 mediaItem.setOriginType(0);
76 mediaItem.setOriginTypeStr("0"); 73 mediaItem.setOriginTypeStr("0");
77 mediaItem.setOriginTypeStr("unknown"); 74 mediaItem.setOriginTypeStr("unknown");
78 -  
79 - zlmMediaListManager.addPush(mediaItem);  
80 -  
81 - 75 + if (register) {
  76 + zlmMediaListManager.addPush(mediaItem);
  77 + }else {
  78 + zlmMediaListManager.removeMedia(app, stream);
  79 + }
82 } 80 }
83 } 81 }
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
@@ -3,10 +3,10 @@ package com.genersoft.iot.vmp.service.impl; @@ -3,10 +3,10 @@ package com.genersoft.iot.vmp.service.impl;
3 import com.alibaba.fastjson.JSONArray; 3 import com.alibaba.fastjson.JSONArray;
4 import com.alibaba.fastjson.JSONObject; 4 import com.alibaba.fastjson.JSONObject;
5 import com.genersoft.iot.vmp.common.StreamInfo; 5 import com.genersoft.iot.vmp.common.StreamInfo;
6 -import com.genersoft.iot.vmp.conf.SipConfig;  
7 import com.genersoft.iot.vmp.conf.UserSetting; 6 import com.genersoft.iot.vmp.conf.UserSetting;
8 import com.genersoft.iot.vmp.gb28181.bean.GbStream; 7 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
9 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 8 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  9 +import com.genersoft.iot.vmp.gb28181.bean.TreeType;
10 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 10 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
11 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; 11 import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
12 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; 12 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
@@ -23,14 +23,19 @@ import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper; @@ -23,14 +23,19 @@ import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper;
23 import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper; 23 import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper;
24 import com.genersoft.iot.vmp.storager.dao.StreamProxyMapper; 24 import com.genersoft.iot.vmp.storager.dao.StreamProxyMapper;
25 import com.genersoft.iot.vmp.service.IStreamProxyService; 25 import com.genersoft.iot.vmp.service.IStreamProxyService;
  26 +import com.genersoft.iot.vmp.utils.DateUtil;
26 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 27 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
27 import com.github.pagehelper.PageInfo; 28 import com.github.pagehelper.PageInfo;
28 import org.slf4j.Logger; 29 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory; 30 import org.slf4j.LoggerFactory;
30 import org.springframework.beans.factory.annotation.Autowired; 31 import org.springframework.beans.factory.annotation.Autowired;
  32 +import org.springframework.jdbc.datasource.DataSourceTransactionManager;
31 import org.springframework.stereotype.Service; 33 import org.springframework.stereotype.Service;
  34 +import org.springframework.transaction.TransactionDefinition;
  35 +import org.springframework.transaction.TransactionStatus;
32 import org.springframework.util.StringUtils; 36 import org.springframework.util.StringUtils;
33 37
  38 +import java.net.InetAddress;
34 import java.util.*; 39 import java.util.*;
35 40
36 /** 41 /**
@@ -48,7 +53,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -48,7 +53,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
48 private IMediaService mediaService; 53 private IMediaService mediaService;
49 54
50 @Autowired 55 @Autowired
51 - private ZLMRESTfulUtils zlmresTfulUtils;; 56 + private ZLMRESTfulUtils zlmresTfulUtils;
52 57
53 @Autowired 58 @Autowired
54 private StreamProxyMapper streamProxyMapper; 59 private StreamProxyMapper streamProxyMapper;
@@ -63,9 +68,6 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -63,9 +68,6 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
63 private UserSetting userSetting; 68 private UserSetting userSetting;
64 69
65 @Autowired 70 @Autowired
66 - private SipConfig sipConfig;  
67 -  
68 - @Autowired  
69 private GbStreamMapper gbStreamMapper; 71 private GbStreamMapper gbStreamMapper;
70 72
71 @Autowired 73 @Autowired
@@ -83,6 +85,12 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -83,6 +85,12 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
83 @Autowired 85 @Autowired
84 private IMediaServerService mediaServerService; 86 private IMediaServerService mediaServerService;
85 87
  88 + @Autowired
  89 + DataSourceTransactionManager dataSourceTransactionManager;
  90 +
  91 + @Autowired
  92 + TransactionDefinition transactionDefinition;
  93 +
86 94
87 @Override 95 @Override
88 public WVPResult<StreamInfo> save(StreamProxyItem param) { 96 public WVPResult<StreamInfo> save(StreamProxyItem param) {
@@ -99,6 +107,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -99,6 +107,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
99 wvpResult.setMsg("保存失败"); 107 wvpResult.setMsg("保存失败");
100 return wvpResult; 108 return wvpResult;
101 } 109 }
  110 +
102 String dstUrl = String.format("rtmp://%s:%s/%s/%s", "127.0.0.1", mediaInfo.getRtmpPort(), param.getApp(), 111 String dstUrl = String.format("rtmp://%s:%s/%s/%s", "127.0.0.1", mediaInfo.getRtmpPort(), param.getApp(),
103 param.getStream() ); 112 param.getStream() );
104 param.setDst_url(dstUrl); 113 param.setDst_url(dstUrl);
@@ -108,9 +117,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -108,9 +117,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
108 boolean saveResult; 117 boolean saveResult;
109 // 更新 118 // 更新
110 if (videoManagerStorager.queryStreamProxy(param.getApp(), param.getStream()) != null) { 119 if (videoManagerStorager.queryStreamProxy(param.getApp(), param.getStream()) != null) {
111 - saveResult = videoManagerStorager.updateStreamProxy(param); 120 + saveResult = updateStreamProxy(param);
112 }else { // 新增 121 }else { // 新增
113 - saveResult = videoManagerStorager.addStreamProxy(param); 122 + saveResult = addStreamProxy(param);
114 } 123 }
115 if (saveResult) { 124 if (saveResult) {
116 result.append("保存成功"); 125 result.append("保存成功");
@@ -124,7 +133,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -124,7 +133,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
124 if (param.isEnable_remove_none_reader()) { 133 if (param.isEnable_remove_none_reader()) {
125 del(param.getApp(), param.getStream()); 134 del(param.getApp(), param.getStream());
126 }else { 135 }else {
127 - videoManagerStorager.updateStreamProxy(param); 136 + updateStreamProxy(param);
128 } 137 }
129 138
130 }else { 139 }else {
@@ -147,25 +156,79 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -147,25 +156,79 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
147 result.append(", 关联国标平台[ " + param.getPlatformGbId() + " ]失败"); 156 result.append(", 关联国标平台[ " + param.getPlatformGbId() + " ]失败");
148 } 157 }
149 } 158 }
150 - if (!StringUtils.isEmpty(param.getGbId())) {  
151 - // 查找开启了全部直播流共享的上级平台  
152 - List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();  
153 - if (parentPlatforms.size() > 0) {  
154 - for (ParentPlatform parentPlatform : parentPlatforms) {  
155 - param.setPlatformId(parentPlatform.getServerGBId());  
156 - param.setCatalogId(parentPlatform.getCatalogId());  
157 - String stream = param.getStream();  
158 - StreamProxyItem streamProxyItems = platformGbStreamMapper.selectOne(param.getApp(), stream, parentPlatform.getServerGBId());  
159 - if (streamProxyItems == null) {  
160 - platformGbStreamMapper.add(param);  
161 - eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), param, CatalogEvent.ADD); 159 + wvpResult.setMsg(result.toString());
  160 + return wvpResult;
  161 + }
  162 +
  163 + /**
  164 + * 新增代理流
  165 + * @param streamProxyItem
  166 + * @return
  167 + */
  168 + private boolean addStreamProxy(StreamProxyItem streamProxyItem) {
  169 + TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
  170 + boolean result = false;
  171 + streamProxyItem.setStreamType("proxy");
  172 + streamProxyItem.setStatus(true);
  173 + String now = DateUtil.getNow();
  174 + streamProxyItem.setCreateTime(now);
  175 + try {
  176 + if (streamProxyMapper.add(streamProxyItem) > 0) {
  177 + if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
  178 + if (gbStreamMapper.add(streamProxyItem) < 0) {
  179 + //事务回滚
  180 + dataSourceTransactionManager.rollback(transactionStatus);
  181 + return false;
162 } 182 }
163 } 183 }
  184 + }else {
  185 + //事务回滚
  186 + dataSourceTransactionManager.rollback(transactionStatus);
  187 + return false;
164 } 188 }
  189 + result = true;
  190 + dataSourceTransactionManager.commit(transactionStatus); //手动提交
  191 + }catch (Exception e) {
  192 + logger.error("向数据库添加流代理失败:", e);
  193 + dataSourceTransactionManager.rollback(transactionStatus);
165 } 194 }
166 195
167 - wvpResult.setMsg(result.toString());  
168 - return wvpResult; 196 +
  197 + return result;
  198 + }
  199 +
  200 + /**
  201 + * 更新代理流
  202 + * @param streamProxyItem
  203 + * @return
  204 + */
  205 + @Override
  206 + public boolean updateStreamProxy(StreamProxyItem streamProxyItem) {
  207 + TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
  208 + boolean result = false;
  209 + streamProxyItem.setStreamType("proxy");
  210 + try {
  211 + if (streamProxyMapper.update(streamProxyItem) > 0) {
  212 + if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {
  213 + if (gbStreamMapper.updateByAppAndStream(streamProxyItem) == 0) {
  214 + //事务回滚
  215 + dataSourceTransactionManager.rollback(transactionStatus);
  216 + return false;
  217 + }
  218 + }
  219 + } else {
  220 + //事务回滚
  221 + dataSourceTransactionManager.rollback(transactionStatus);
  222 + return false;
  223 + }
  224 +
  225 + dataSourceTransactionManager.commit(transactionStatus); //手动提交
  226 + result = true;
  227 + }catch (Exception e) {
  228 + e.printStackTrace();
  229 + dataSourceTransactionManager.rollback(transactionStatus);
  230 + }
  231 + return result;
169 } 232 }
170 233
171 @Override 234 @Override
@@ -239,7 +302,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -239,7 +302,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
239 if (jsonObject.getInteger("code") == 0) { 302 if (jsonObject.getInteger("code") == 0) {
240 result = true; 303 result = true;
241 streamProxy.setEnable(true); 304 streamProxy.setEnable(true);
242 - videoManagerStorager.updateStreamProxy(streamProxy); 305 + updateStreamProxy(streamProxy);
243 } 306 }
244 } 307 }
245 return result; 308 return result;
@@ -253,7 +316,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -253,7 +316,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
253 JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto); 316 JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto);
254 if (jsonObject != null && jsonObject.getInteger("code") == 0) { 317 if (jsonObject != null && jsonObject.getInteger("code") == 0) {
255 streamProxyDto.setEnable(false); 318 streamProxyDto.setEnable(false);
256 - result = videoManagerStorager.updateStreamProxy(streamProxyDto); 319 + result = updateStreamProxy(streamProxyDto);
257 } 320 }
258 } 321 }
259 return result; 322 return result;
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
4 import com.alibaba.fastjson.JSONArray; 4 import com.alibaba.fastjson.JSONArray;
5 import com.alibaba.fastjson.JSONObject; 5 import com.alibaba.fastjson.JSONObject;
6 import com.alibaba.fastjson.TypeReference; 6 import com.alibaba.fastjson.TypeReference;
  7 +import com.genersoft.iot.vmp.conf.MediaConfig;
7 import com.genersoft.iot.vmp.conf.UserSetting; 8 import com.genersoft.iot.vmp.conf.UserSetting;
8 import com.genersoft.iot.vmp.gb28181.bean.*; 9 import com.genersoft.iot.vmp.gb28181.bean.*;
9 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 10 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
@@ -13,6 +14,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.*; @@ -13,6 +14,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.*;
13 import com.genersoft.iot.vmp.service.IGbStreamService; 14 import com.genersoft.iot.vmp.service.IGbStreamService;
14 import com.genersoft.iot.vmp.service.IMediaServerService; 15 import com.genersoft.iot.vmp.service.IMediaServerService;
15 import com.genersoft.iot.vmp.service.IStreamPushService; 16 import com.genersoft.iot.vmp.service.IStreamPushService;
  17 +import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
16 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 18 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
17 import com.genersoft.iot.vmp.storager.dao.*; 19 import com.genersoft.iot.vmp.storager.dao.*;
18 import com.genersoft.iot.vmp.utils.DateUtil; 20 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -21,7 +23,10 @@ import com.github.pagehelper.PageInfo; @@ -21,7 +23,10 @@ import com.github.pagehelper.PageInfo;
21 import org.slf4j.Logger; 23 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory; 24 import org.slf4j.LoggerFactory;
23 import org.springframework.beans.factory.annotation.Autowired; 25 import org.springframework.beans.factory.annotation.Autowired;
  26 +import org.springframework.jdbc.datasource.DataSourceTransactionManager;
24 import org.springframework.stereotype.Service; 27 import org.springframework.stereotype.Service;
  28 +import org.springframework.transaction.TransactionDefinition;
  29 +import org.springframework.transaction.TransactionStatus;
25 import org.springframework.util.StringUtils; 30 import org.springframework.util.StringUtils;
26 31
27 import java.util.*; 32 import java.util.*;
@@ -68,6 +73,16 @@ public class StreamPushServiceImpl implements IStreamPushService { @@ -68,6 +73,16 @@ public class StreamPushServiceImpl implements IStreamPushService {
68 @Autowired 73 @Autowired
69 private IMediaServerService mediaServerService; 74 private IMediaServerService mediaServerService;
70 75
  76 + @Autowired
  77 + DataSourceTransactionManager dataSourceTransactionManager;
  78 +
  79 + @Autowired
  80 + TransactionDefinition transactionDefinition;
  81 +
  82 + @Autowired
  83 + private MediaConfig mediaConfig;
  84 +
  85 +
71 @Override 86 @Override
72 public List<StreamPushItem> handleJSON(String jsonData, MediaServerItem mediaServerItem) { 87 public List<StreamPushItem> handleJSON(String jsonData, MediaServerItem mediaServerItem) {
73 if (jsonData == null) { 88 if (jsonData == null) {
@@ -132,30 +147,9 @@ public class StreamPushServiceImpl implements IStreamPushService { @@ -132,30 +147,9 @@ public class StreamPushServiceImpl implements IStreamPushService {
132 stream.setStreamType("push"); 147 stream.setStreamType("push");
133 stream.setStatus(true); 148 stream.setStatus(true);
134 stream.setCreateTime(DateUtil.getNow()); 149 stream.setCreateTime(DateUtil.getNow());
  150 + stream.setStreamType("push");
  151 + stream.setMediaServerId(mediaConfig.getId());
135 int add = gbStreamMapper.add(stream); 152 int add = gbStreamMapper.add(stream);
136 -  
137 - // 查找开启了全部直播流共享的上级平台  
138 - List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();  
139 - if (parentPlatforms.size() > 0) {  
140 - for (ParentPlatform parentPlatform : parentPlatforms) {  
141 - stream.setCatalogId(parentPlatform.getCatalogId());  
142 - stream.setPlatformId(parentPlatform.getServerGBId());  
143 - String streamId = stream.getStream();  
144 - StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(stream.getApp(), streamId, parentPlatform.getServerGBId());  
145 - if (streamProxyItem == null) {  
146 - platformGbStreamMapper.add(stream);  
147 - eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);  
148 - }else {  
149 - if (!streamProxyItem.getGbId().equals(stream.getGbId())) {  
150 - // 此流使用另一个国标Id已经与该平台关联,移除此记录  
151 - platformGbStreamMapper.delByAppAndStreamAndPlatform(stream.getApp(), streamId, parentPlatform.getServerGBId());  
152 - platformGbStreamMapper.add(stream);  
153 - eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);  
154 - }  
155 - }  
156 - }  
157 - }  
158 -  
159 return add > 0; 153 return add > 0;
160 } 154 }
161 155
@@ -181,7 +175,6 @@ public class StreamPushServiceImpl implements IStreamPushService { @@ -181,7 +175,6 @@ public class StreamPushServiceImpl implements IStreamPushService {
181 175
182 @Override 176 @Override
183 public StreamPushItem getPush(String app, String streamId) { 177 public StreamPushItem getPush(String app, String streamId) {
184 -  
185 return streamPushMapper.selectOne(app, streamId); 178 return streamPushMapper.selectOne(app, streamId);
186 } 179 }
187 180
@@ -345,31 +338,6 @@ public class StreamPushServiceImpl implements IStreamPushService { @@ -345,31 +338,6 @@ public class StreamPushServiceImpl implements IStreamPushService {
345 public void batchAdd(List<StreamPushItem> streamPushItems) { 338 public void batchAdd(List<StreamPushItem> streamPushItems) {
346 streamPushMapper.addAll(streamPushItems); 339 streamPushMapper.addAll(streamPushItems);
347 gbStreamMapper.batchAdd(streamPushItems); 340 gbStreamMapper.batchAdd(streamPushItems);
348 - // 查找开启了全部直播流共享的上级平台  
349 - List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();  
350 - if (parentPlatforms.size() > 0) {  
351 - for (StreamPushItem stream : streamPushItems) {  
352 - for (ParentPlatform parentPlatform : parentPlatforms) {  
353 - stream.setCatalogId(parentPlatform.getCatalogId());  
354 - stream.setPlatformId(parentPlatform.getServerGBId());  
355 - String streamId = stream.getStream();  
356 - StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(stream.getApp(), streamId, parentPlatform.getServerGBId());  
357 - if (streamProxyItem == null) {  
358 - platformGbStreamMapper.add(stream);  
359 - eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);  
360 - }else {  
361 - if (!streamProxyItem.getGbId().equals(stream.getGbId())) {  
362 - // 此流使用另一个国标Id已经与该平台关联,移除此记录  
363 - platformGbStreamMapper.delByAppAndStreamAndPlatform(stream.getApp(), streamId, parentPlatform.getServerGBId());  
364 - platformGbStreamMapper.add(stream);  
365 - eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.ADD);  
366 - stream.setGbId(streamProxyItem.getGbId());  
367 - eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), stream, CatalogEvent.DEL);  
368 - }  
369 - }  
370 - }  
371 - }  
372 - }  
373 } 341 }
374 342
375 @Override 343 @Override
@@ -481,4 +449,58 @@ public class StreamPushServiceImpl implements IStreamPushService { @@ -481,4 +449,58 @@ public class StreamPushServiceImpl implements IStreamPushService {
481 } 449 }
482 return true; 450 return true;
483 } 451 }
  452 +
  453 + @Override
  454 + public void allStreamOffline() {
  455 + List<GbStream> onlinePushers = streamPushMapper.getOnlinePusherForGb();
  456 + if (onlinePushers.size() == 0) {
  457 + return;
  458 + }
  459 + streamPushMapper.setAllStreamOffline();
  460 +
  461 + // 发送通知
  462 + eventPublisher.catalogEventPublishForStream(null, onlinePushers, CatalogEvent.OFF);
  463 + }
  464 +
  465 + @Override
  466 + public void offline(List<StreamPushItemFromRedis> offlineStreams) {
  467 + // 更新部分设备离线
  468 + List<GbStream> onlinePushers = streamPushMapper.getOnlinePusherForGbInList(offlineStreams);
  469 + streamPushMapper.offline(offlineStreams);
  470 + // 发送通知
  471 + eventPublisher.catalogEventPublishForStream(null, onlinePushers, CatalogEvent.OFF);
  472 + }
  473 +
  474 + @Override
  475 + public void online(List<StreamPushItemFromRedis> onlineStreams) {
  476 + // 更新部分设备上线streamPushService
  477 + List<GbStream> onlinePushers = streamPushMapper.getOfflinePusherForGbInList(onlineStreams);
  478 + streamPushMapper.online(onlineStreams);
  479 + // 发送通知
  480 + eventPublisher.catalogEventPublishForStream(null, onlinePushers, CatalogEvent.ON);
  481 + }
  482 +
  483 + @Override
  484 + public boolean add(StreamPushItem stream) {
  485 + stream.setUpdateTime(DateUtil.getNow());
  486 + stream.setCreateTime(DateUtil.getNow());
  487 + stream.setServerId(userSetting.getServerId());
  488 +
  489 + // 放在事务内执行
  490 + boolean result = false;
  491 + TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
  492 + try {
  493 + int addStreamResult = streamPushMapper.add(stream);
  494 + if (!StringUtils.isEmpty(stream.getGbId())) {
  495 + stream.setStreamType("push");
  496 + gbStreamMapper.add(stream);
  497 + }
  498 + dataSourceTransactionManager.commit(transactionStatus);
  499 + result = true;
  500 + }catch (Exception e) {
  501 + logger.error("批量移除流与平台的关系时错误", e);
  502 + dataSourceTransactionManager.rollback(transactionStatus);
  503 + }
  504 + return result;
  505 + }
484 } 506 }
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushUploadFileHandler.java
@@ -14,38 +14,60 @@ import java.util.*; @@ -14,38 +14,60 @@ import java.util.*;
14 14
15 public class StreamPushUploadFileHandler extends AnalysisEventListener<StreamPushExcelDto> { 15 public class StreamPushUploadFileHandler extends AnalysisEventListener<StreamPushExcelDto> {
16 16
17 - // 错误数据的回调,用于将错误数据发送给页面 17 + /**
  18 + * 错误数据的回调,用于将错误数据发送给页面
  19 + */
18 private ErrorDataHandler errorDataHandler; 20 private ErrorDataHandler errorDataHandler;
19 21
20 - // 推流的业务类用于存储数据 22 + /**
  23 + * 推流的业务类用于存储数据
  24 + */
21 private IStreamPushService pushService; 25 private IStreamPushService pushService;
22 26
23 - // 默认流媒体节点ID 27 + /**
  28 + * 默认流媒体节点ID
  29 + */
24 private String defaultMediaServerId; 30 private String defaultMediaServerId;
25 31
26 - // 用于存储不加过滤的所有数据 32 + /**
  33 + * 用于存储不加过滤的所有数据
  34 + */
27 private List<StreamPushItem> streamPushItems = new ArrayList<>(); 35 private List<StreamPushItem> streamPushItems = new ArrayList<>();
28 36
29 - // 用于存储更具APP+Stream过滤后的数据,可以直接存入stream_push表与gb_stream表 37 + /**
  38 + * 用于存储更具APP+Stream过滤后的数据,可以直接存入stream_push表与gb_stream表
  39 + */
30 private Map<String,StreamPushItem> streamPushItemForSave = new HashMap<>(); 40 private Map<String,StreamPushItem> streamPushItemForSave = new HashMap<>();
31 41
32 - // 用于存储按照APP+Stream为KEY, 平台ID+目录Id 为value的数据,用于存储到gb_stream表后获取app+Stream对应的平台与目录信息,然后存入关联表 42 + /**
  43 + * 用于存储按照APP+Stream为KEY, 平台ID+目录Id 为value的数据,用于存储到gb_stream表后获取app+Stream对应的平台与目录信息,然后存入关联表
  44 + */
33 private Map<String, List<String[]>> streamPushItemsForPlatform = new HashMap<>(); 45 private Map<String, List<String[]>> streamPushItemsForPlatform = new HashMap<>();
34 46
35 - // 用于判断文件是否存在重复的app+Stream+平台ID 47 + /**
  48 + * 用于判断文件是否存在重复的app+Stream+平台ID
  49 + */
36 private Set<String> streamPushStreamSet = new HashSet<>(); 50 private Set<String> streamPushStreamSet = new HashSet<>();
37 51
38 - // 用于存储APP+Stream->国标ID 的数据结构, 数据一一对应,全局判断APP+Stream->国标ID是否存在不对应 52 + /**
  53 + * 用于存储APP+Stream->国标ID 的数据结构, 数据一一对应,全局判断APP+Stream->国标ID是否存在不对应
  54 + */
39 private BiMap<String,String> gBMap = HashBiMap.create(); 55 private BiMap<String,String> gBMap = HashBiMap.create();
40 56
41 - // 记录错误的APP+Stream 57 + /**
  58 + * 记录错误的APP+Stream
  59 + */
42 private List<String> errorStreamList = new ArrayList<>(); 60 private List<String> errorStreamList = new ArrayList<>();
43 61
44 62
45 - // 记录错误的国标ID 63 + /**
  64 + * 记录错误的国标ID
  65 + */
46 private List<String> errorGBList = new ArrayList<>(); 66 private List<String> errorGBList = new ArrayList<>();
47 67
48 - // 读取数量计数器 68 + /**
  69 + * 读取数量计数器
  70 + */
49 private int loadedSize = 0; 71 private int loadedSize = 0;
50 72
51 public StreamPushUploadFileHandler(IStreamPushService pushService, String defaultMediaServerId, ErrorDataHandler errorDataHandler) { 73 public StreamPushUploadFileHandler(IStreamPushService pushService, String defaultMediaServerId, ErrorDataHandler errorDataHandler) {
src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java
@@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.service.impl; @@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.service.impl;
3 import com.genersoft.iot.vmp.service.IUserService; 3 import com.genersoft.iot.vmp.service.IUserService;
4 import com.genersoft.iot.vmp.storager.dao.UserMapper; 4 import com.genersoft.iot.vmp.storager.dao.UserMapper;
5 import com.genersoft.iot.vmp.storager.dao.dto.User; 5 import com.genersoft.iot.vmp.storager.dao.dto.User;
  6 +import com.github.pagehelper.PageHelper;
  7 +import com.github.pagehelper.PageInfo;
6 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.stereotype.Service; 9 import org.springframework.stereotype.Service;
8 import org.springframework.util.StringUtils; 10 import org.springframework.util.StringUtils;
@@ -11,7 +13,7 @@ import java.util.List; @@ -11,7 +13,7 @@ import java.util.List;
11 13
12 @Service 14 @Service
13 public class UserServiceImpl implements IUserService { 15 public class UserServiceImpl implements IUserService {
14 - 16 +
15 @Autowired 17 @Autowired
16 private UserMapper userMapper; 18 private UserMapper userMapper;
17 19
@@ -64,4 +66,16 @@ public class UserServiceImpl implements IUserService { @@ -64,4 +66,16 @@ public class UserServiceImpl implements IUserService {
64 return userMapper.checkPushAuthorityByCallIdAndSign(callId, sign).size() > 0; 66 return userMapper.checkPushAuthorityByCallIdAndSign(callId, sign).size() > 0;
65 } 67 }
66 } 68 }
  69 +
  70 + @Override
  71 + public PageInfo<User> getUsers(int page, int count) {
  72 + PageHelper.startPage(page, count);
  73 + List<User> users = userMapper.getUsers();
  74 + return new PageInfo<>(users);
  75 + }
  76 +
  77 + @Override
  78 + public int changePushKey(int id, String pushKey) {
  79 + return userMapper.changePushKey(id,pushKey);
  80 + }
67 } 81 }
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -233,4 +233,9 @@ public interface IRedisCatchStorage { @@ -233,4 +233,9 @@ public interface IRedisCatchStorage {
233 * @return 233 * @return
234 */ 234 */
235 StreamAuthorityInfo getStreamAuthorityInfo(String app, String stream); 235 StreamAuthorityInfo getStreamAuthorityInfo(String app, String stream);
  236 +
  237 + /**
  238 + * 发送redis消息 查询所有推流设备的状态
  239 + */
  240 + void sendStreamPushRequestedMsgForStatus();
236 } 241 }
src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java
@@ -27,22 +27,6 @@ public interface IVideoManagerStorage { @@ -27,22 +27,6 @@ public interface IVideoManagerStorage {
27 public boolean exists(String deviceId); 27 public boolean exists(String deviceId);
28 28
29 /** 29 /**
30 - * 添加设备通道  
31 - *  
32 - * @param deviceId 设备id  
33 - * @param channel 通道  
34 - */  
35 - public void updateChannel(String deviceId, DeviceChannel channel);  
36 -  
37 - /**  
38 - * 批量添加设备通道  
39 - *  
40 - * @param deviceId 设备id  
41 - * @param channels 多个通道  
42 - */  
43 - public int updateChannels(String deviceId, List<DeviceChannel> channels);  
44 -  
45 - /**  
46 * 开始播放 30 * 开始播放
47 * @param deviceId 设备id 31 * @param deviceId 设备id
48 * @param channelId 通道ID 32 * @param channelId 通道ID
@@ -224,13 +208,6 @@ public interface IVideoManagerStorage { @@ -224,13 +208,6 @@ public interface IVideoManagerStorage {
224 List<DeviceChannelInPlatform> queryChannelListInParentPlatform(String platformId); 208 List<DeviceChannelInPlatform> queryChannelListInParentPlatform(String platformId);
225 209
226 210
227 - /**  
228 - * 更新上级平台的通道信息  
229 - * @param platformId  
230 - * @param channelReduces  
231 - * @return  
232 - */  
233 - int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId);  
234 211
235 /** 212 /**
236 * 移除上级平台的通道信息 213 * 移除上级平台的通道信息
@@ -277,20 +254,6 @@ public interface IVideoManagerStorage { @@ -277,20 +254,6 @@ public interface IVideoManagerStorage {
277 public int clearMobilePositionsByDeviceId(String deviceId); 254 public int clearMobilePositionsByDeviceId(String deviceId);
278 255
279 /** 256 /**
280 - * 新增代理流  
281 - * @param streamProxyDto  
282 - * @return  
283 - */  
284 - public boolean addStreamProxy(StreamProxyItem streamProxyDto);  
285 -  
286 - /**  
287 - * 更新代理流  
288 - * @param streamProxyDto  
289 - * @return  
290 - */  
291 - public boolean updateStreamProxy(StreamProxyItem streamProxyDto);  
292 -  
293 - /**  
294 * 移除代理流 257 * 移除代理流
295 * @param app 258 * @param app
296 * @param stream 259 * @param stream
@@ -334,19 +297,7 @@ public interface IVideoManagerStorage { @@ -334,19 +297,7 @@ public interface IVideoManagerStorage {
334 * @param platformId 297 * @param platformId
335 * @return 298 * @return
336 */ 299 */
337 - List<GbStream> queryGbStreamListInPlatform(String platformId);  
338 -  
339 - /**  
340 - * 批量更新推流列表  
341 - * @param streamPushItems  
342 - */  
343 - void updateMediaList(List<StreamPushItem> streamPushItems);  
344 -  
345 - /**  
346 - * 更新单个推流  
347 - * @param streamPushItem  
348 - */  
349 - void updateMedia(StreamPushItem streamPushItem); 300 + List<DeviceChannel> queryGbStreamListInPlatform(String platformId);
350 301
351 /** 302 /**
352 * 移除单个推流 303 * 移除单个推流
@@ -355,21 +306,6 @@ public interface IVideoManagerStorage { @@ -355,21 +306,6 @@ public interface IVideoManagerStorage {
355 */ 306 */
356 int removeMedia(String app, String stream); 307 int removeMedia(String app, String stream);
357 308
358 -  
359 - /**  
360 - * 获取但个推流  
361 - * @param app  
362 - * @param stream  
363 - * @return  
364 - */  
365 - StreamPushItem getMedia(String app, String stream);  
366 -  
367 -  
368 - /**  
369 - * 清空推流列表  
370 - */  
371 - void clearMediaList();  
372 -  
373 /** 309 /**
374 * 设置流离线 310 * 设置流离线
375 */ 311 */
@@ -445,7 +381,7 @@ public interface IVideoManagerStorage { @@ -445,7 +381,7 @@ public interface IVideoManagerStorage {
445 381
446 int setDefaultCatalog(String platformId, String catalogId); 382 int setDefaultCatalog(String platformId, String catalogId);
447 383
448 - List<PlatformCatalog> queryCatalogInPlatform(String serverGBId); 384 + List<DeviceChannel> queryCatalogInPlatform(String serverGBId);
449 385
450 int delRelation(PlatformCatalog platformCatalog); 386 int delRelation(PlatformCatalog platformCatalog);
451 387
@@ -466,4 +402,8 @@ public interface IVideoManagerStorage { @@ -466,4 +402,8 @@ public interface IVideoManagerStorage {
466 List<ChannelSourceInfo> getChannelSource(String platformId, String gbId); 402 List<ChannelSourceInfo> getChannelSource(String platformId, String gbId);
467 403
468 void updateChannelPosition(DeviceChannel deviceChannel); 404 void updateChannelPosition(DeviceChannel deviceChannel);
  405 +
  406 + void cleanContentForPlatform(String serverGBId);
  407 +
  408 + List<DeviceChannel> queryChannelWithCatalog(String serverGBId);
469 } 409 }
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
@@ -140,6 +140,9 @@ public interface DeviceChannelMapper { @@ -140,6 +140,9 @@ public interface DeviceChannelMapper {
140 @Update(value = {"UPDATE device_channel SET status=0 WHERE deviceId=#{deviceId} AND channelId=#{channelId}"}) 140 @Update(value = {"UPDATE device_channel SET status=0 WHERE deviceId=#{deviceId} AND channelId=#{channelId}"})
141 void offline(String deviceId, String channelId); 141 void offline(String deviceId, String channelId);
142 142
  143 + @Update(value = {"UPDATE device_channel SET status=0 WHERE deviceId=#{deviceId}"})
  144 + void offlineByDeviceId(String deviceId);
  145 +
143 @Update(value = {"UPDATE device_channel SET status=1 WHERE deviceId=#{deviceId} AND channelId=#{channelId}"}) 146 @Update(value = {"UPDATE device_channel SET status=1 WHERE deviceId=#{deviceId} AND channelId=#{channelId}"})
144 void online(String deviceId, String channelId); 147 void online(String deviceId, String channelId);
145 148
@@ -329,5 +332,13 @@ public interface DeviceChannelMapper { @@ -329,5 +332,13 @@ public interface DeviceChannelMapper {
329 @Select("select * from device_channel where deviceId=#{deviceId} and SUBSTRING(channelId, 11, 3)=#{typeCode}") 332 @Select("select * from device_channel where deviceId=#{deviceId} and SUBSTRING(channelId, 11, 3)=#{typeCode}")
330 List<DeviceChannel> getBusinessGroups(String deviceId, String typeCode); 333 List<DeviceChannel> getBusinessGroups(String deviceId, String typeCode);
331 334
332 - 335 + @Select("select dc.id, dc.channelId, dc.deviceId, dc.name, dc.manufacture,dc.model,dc.owner, pc.civilCode,dc.block, " +
  336 + " dc.address, '0' as parental,'0' as channelType, pc.id as parentId, dc.safetyWay, dc.registerWay,dc.certNum, dc.certifiable, " +
  337 + " dc.errCode,dc.endTime, dc.secrecy, dc.ipAddress, dc.port, dc.PTZType, dc.password, dc.status, " +
  338 + " dc.longitudeWgs84 as longitude, dc.latitudeWgs84 as latitude, pc.businessGroupId " +
  339 + " from device_channel dc" +
  340 + " left join platform_gb_channel pgc on dc.id = pgc.deviceChannelId" +
  341 + " left join platform_catalog pc on pgc.catalogId = pc.id and pgc.platformId = pc.platformId" +
  342 + " where pgc.platformId=#{serverGBId}")
  343 + List<DeviceChannel> queryChannelWithCatalog(String serverGBId);
333 } 344 }
src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
1 package com.genersoft.iot.vmp.storager.dao; 1 package com.genersoft.iot.vmp.storager.dao;
2 2
  3 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
3 import com.genersoft.iot.vmp.gb28181.bean.GbStream; 4 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
4 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; 5 import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem;
5 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; 6 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
@@ -15,10 +16,10 @@ import java.util.List; @@ -15,10 +16,10 @@ import java.util.List;
15 public interface GbStreamMapper { 16 public interface GbStreamMapper {
16 17
17 @Insert("REPLACE INTO gb_stream (app, stream, gbId, name, " + 18 @Insert("REPLACE INTO gb_stream (app, stream, gbId, name, " +
18 - "longitude, latitude, streamType, mediaServerId, status, createTime) VALUES" + 19 + "longitude, latitude, streamType, mediaServerId, createTime) VALUES" +
19 "('${app}', '${stream}', '${gbId}', '${name}', " + 20 "('${app}', '${stream}', '${gbId}', '${name}', " +
20 "'${longitude}', '${latitude}', '${streamType}', " + 21 "'${longitude}', '${latitude}', '${streamType}', " +
21 - "'${mediaServerId}', ${status}, '${createTime}')") 22 + "'${mediaServerId}', '${createTime}')")
22 @Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId") 23 @Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId")
23 int add(GbStream gbStream); 24 int add(GbStream gbStream);
24 25
@@ -30,8 +31,7 @@ public interface GbStreamMapper { @@ -30,8 +31,7 @@ public interface GbStreamMapper {
30 "streamType=#{streamType}," + 31 "streamType=#{streamType}," +
31 "longitude=#{longitude}, " + 32 "longitude=#{longitude}, " +
32 "latitude=#{latitude}," + 33 "latitude=#{latitude}," +
33 - "mediaServerId=#{mediaServerId}," +  
34 - "status=${status} " + 34 + "mediaServerId=#{mediaServerId}" +
35 "WHERE app=#{app} AND stream=#{stream}") 35 "WHERE app=#{app} AND stream=#{stream}")
36 int updateByAppAndStream(GbStream gbStream); 36 int updateByAppAndStream(GbStream gbStream);
37 37
@@ -43,8 +43,7 @@ public interface GbStreamMapper { @@ -43,8 +43,7 @@ public interface GbStreamMapper {
43 "streamType=#{streamType}," + 43 "streamType=#{streamType}," +
44 "longitude=#{longitude}, " + 44 "longitude=#{longitude}, " +
45 "latitude=#{latitude}," + 45 "latitude=#{latitude}," +
46 - "mediaServerId=#{mediaServerId}," +  
47 - "status=${status} " + 46 + "mediaServerId=#{mediaServerId}" +
48 "WHERE gbStreamId=#{gbStreamId}") 47 "WHERE gbStreamId=#{gbStreamId}")
49 int update(GbStream gbStream); 48 int update(GbStream gbStream);
50 49
@@ -60,12 +59,10 @@ public interface GbStreamMapper { @@ -60,12 +59,10 @@ public interface GbStreamMapper {
60 " <if test='catalogId == null'> AND gs.gbStreamId not in" + 59 " <if test='catalogId == null'> AND gs.gbStreamId not in" +
61 "(select pgs.gbStreamId from platform_gb_stream pgs where pgs.platformId = #{platformId}) </if> " + 60 "(select pgs.gbStreamId from platform_gb_stream pgs where pgs.platformId = #{platformId}) </if> " +
62 " <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> " + 61 " <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> " +
63 - " <if test='pushing == true' > AND gs.status=1</if>" +  
64 - " <if test='pushing == false' > AND gs.status=0</if>" +  
65 " <if test='mediaServerId != null' > AND gs.mediaServerId=#{mediaServerId} </if>" + 62 " <if test='mediaServerId != null' > AND gs.mediaServerId=#{mediaServerId} </if>" +
66 " order by gs.gbStreamId asc " + 63 " order by gs.gbStreamId asc " +
67 "</script>") 64 "</script>")
68 - List<GbStream> selectAll(String platformId, String catalogId, String query, Boolean pushing, String mediaServerId); 65 + List<GbStream> selectAll(String platformId, String catalogId, String query, String mediaServerId);
69 66
70 @Select("SELECT * FROM gb_stream WHERE app=#{app} AND stream=#{stream}") 67 @Select("SELECT * FROM gb_stream WHERE app=#{app} AND stream=#{stream}")
71 GbStream selectOne(String app, String stream); 68 GbStream selectOne(String app, String stream);
@@ -78,10 +75,18 @@ public interface GbStreamMapper { @@ -78,10 +75,18 @@ public interface GbStreamMapper {
78 "WHERE gs.gbId = '${gbId}' AND pgs.platformId = '${platformId}'") 75 "WHERE gs.gbId = '${gbId}' AND pgs.platformId = '${platformId}'")
79 GbStream queryStreamInPlatform(String platformId, String gbId); 76 GbStream queryStreamInPlatform(String platformId, String gbId);
80 77
81 - @Select("SELECT gs.*, pgs.platformId as platformId, pgs.catalogId as catalogId FROM gb_stream gs " +  
82 - "LEFT JOIN platform_gb_stream pgs ON gs.gbStreamId = pgs.gbStreamId " +  
83 - "WHERE pgs.platformId = #{platformId}")  
84 - List<GbStream> queryGbStreamListInPlatform(String platformId); 78 + @Select("select gt.gbId as channelId, gt.name, 'wvp-pro' as manufacture, st.status, gt.longitude, gt.latitude, pc.id as parentId," +
  79 + " '1' as registerWay, pc.civilCode, 'live' as model, 'wvp-pro' as owner, '0' as parental,'0' as secrecy" +
  80 + " from gb_stream gt " +
  81 + " left join (" +
  82 + " select sp.status, sp.app, sp.stream from stream_push sp" +
  83 + " union all" +
  84 + " select spxy.status, spxy.app, spxy.stream from stream_proxy spxy" +
  85 + " ) st on st.app = gt.app and st.stream = gt.stream" +
  86 + " left join platform_gb_stream pgs on gt.gbStreamId = pgs.gbStreamId" +
  87 + " left join platform_catalog pc on pgs.catalogId = pc.id and pgs.platformId = pc.platformId" +
  88 + " where pgs.platformId=#{platformId}")
  89 + List<DeviceChannel> queryGbStreamListInPlatform(String platformId);
85 90
86 91
87 @Select("SELECT gs.* FROM gb_stream gs LEFT JOIN platform_gb_stream pgs " + 92 @Select("SELECT gs.* FROM gb_stream gs LEFT JOIN platform_gb_stream pgs " +
@@ -110,12 +115,12 @@ public interface GbStreamMapper { @@ -110,12 +115,12 @@ public interface GbStreamMapper {
110 @Insert("<script> " + 115 @Insert("<script> " +
111 "INSERT IGNORE into gb_stream " + 116 "INSERT IGNORE into gb_stream " +
112 "(app, stream, gbId, name, " + 117 "(app, stream, gbId, name, " +
113 - "longitude, latitude, streamType, mediaServerId, status, createTime)" + 118 + "longitude, latitude, streamType, mediaServerId, createTime)" +
114 "values " + 119 "values " +
115 "<foreach collection='subList' index='index' item='item' separator=','> " + 120 "<foreach collection='subList' index='index' item='item' separator=','> " +
116 "('${item.app}', '${item.stream}', '${item.gbId}', '${item.name}', " + 121 "('${item.app}', '${item.stream}', '${item.gbId}', '${item.name}', " +
117 "'${item.longitude}', '${item.latitude}', '${item.streamType}', " + 122 "'${item.longitude}', '${item.latitude}', '${item.streamType}', " +
118 - "'${item.mediaServerId}', ${item.status}, '${item.createTime}') "+ 123 + "'${item.mediaServerId}', '${item.createTime}') "+
119 "</foreach> " + 124 "</foreach> " +
120 "</script>") 125 "</script>")
121 @Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId") 126 @Options(useGeneratedKeys = true, keyProperty = "gbStreamId", keyColumn = "gbStreamId")
@@ -138,4 +143,9 @@ public interface GbStreamMapper { @@ -138,4 +143,9 @@ public interface GbStreamMapper {
138 "</foreach>" + 143 "</foreach>" +
139 "</script>") 144 "</script>")
140 List<GbStream> selectAllForAppAndStream(List<StreamPushItem> streamPushItems); 145 List<GbStream> selectAllForAppAndStream(List<StreamPushItem> streamPushItems);
  146 +
  147 + @Update("UPDATE gb_stream " +
  148 + "SET mediaServerId=#{mediaServerId}" +
  149 + "WHERE app=#{app} AND stream=#{stream}")
  150 + void updateMediaServer(String app, String stream, String mediaServerId);
141 } 151 }
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
@@ -16,10 +16,10 @@ public interface ParentPlatformMapper { @@ -16,10 +16,10 @@ public interface ParentPlatformMapper {
16 16
17 @Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp, " + 17 @Insert("INSERT INTO parent_platform (enable, name, serverGBId, serverGBDomain, serverIP, serverPort, deviceGBId, deviceIp, " +
18 " devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, " + 18 " devicePort, username, password, expires, keepTimeout, transport, characterSet, ptz, rtcp, " +
19 - " status, shareAllLiveStream, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime) " + 19 + " status, startOfflinePush, catalogId, administrativeDivision, catalogGroup, createTime, updateTime, treeType) " +
20 " VALUES (${enable}, '${name}', '${serverGBId}', '${serverGBDomain}', '${serverIP}', ${serverPort}, '${deviceGBId}', '${deviceIp}', " + 20 " VALUES (${enable}, '${name}', '${serverGBId}', '${serverGBDomain}', '${serverIP}', ${serverPort}, '${deviceGBId}', '${deviceIp}', " +
21 " '${devicePort}', '${username}', '${password}', '${expires}', '${keepTimeout}', '${transport}', '${characterSet}', ${ptz}, ${rtcp}, " + 21 " '${devicePort}', '${username}', '${password}', '${expires}', '${keepTimeout}', '${transport}', '${characterSet}', ${ptz}, ${rtcp}, " +
22 - " ${status}, ${shareAllLiveStream}, ${startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime})") 22 + " ${status}, ${startOfflinePush}, #{catalogId}, #{administrativeDivision}, #{catalogGroup}, #{createTime}, #{updateTime}, #{treeType})")
23 int addParentPlatform(ParentPlatform parentPlatform); 23 int addParentPlatform(ParentPlatform parentPlatform);
24 24
25 @Update("UPDATE parent_platform " + 25 @Update("UPDATE parent_platform " +
@@ -41,12 +41,12 @@ public interface ParentPlatformMapper { @@ -41,12 +41,12 @@ public interface ParentPlatformMapper {
41 "ptz=#{ptz}, " + 41 "ptz=#{ptz}, " +
42 "rtcp=#{rtcp}, " + 42 "rtcp=#{rtcp}, " +
43 "status=#{status}, " + 43 "status=#{status}, " +
44 - "shareAllLiveStream=#{shareAllLiveStream}, " +  
45 "startOfflinePush=${startOfflinePush}, " + 44 "startOfflinePush=${startOfflinePush}, " +
46 "catalogGroup=#{catalogGroup}, " + 45 "catalogGroup=#{catalogGroup}, " +
47 "administrativeDivision=#{administrativeDivision}, " + 46 "administrativeDivision=#{administrativeDivision}, " +
48 "createTime=#{createTime}, " + 47 "createTime=#{createTime}, " +
49 "updateTime=#{updateTime}, " + 48 "updateTime=#{updateTime}, " +
  49 + "treeType=#{treeType}, " +
50 "catalogId=#{catalogId} " + 50 "catalogId=#{catalogId} " +
51 "WHERE id=#{id}") 51 "WHERE id=#{id}")
52 int updateParentPlatform(ParentPlatform parentPlatform); 52 int updateParentPlatform(ParentPlatform parentPlatform);
@@ -83,9 +83,6 @@ public interface ParentPlatformMapper { @@ -83,9 +83,6 @@ public interface ParentPlatformMapper {
83 @Update("UPDATE parent_platform SET status=#{online} WHERE serverGBId=#{platformGbID}" ) 83 @Update("UPDATE parent_platform SET status=#{online} WHERE serverGBId=#{platformGbID}" )
84 int updateParentPlatformStatus(String platformGbID, boolean online); 84 int updateParentPlatformStatus(String platformGbID, boolean online);
85 85
86 - @Select("SELECT * FROM parent_platform WHERE shareAllLiveStream=true")  
87 - List<ParentPlatform> selectAllAhareAllLiveStream();  
88 -  
89 @Update(value = {" <script>" + 86 @Update(value = {" <script>" +
90 "UPDATE parent_platform " + 87 "UPDATE parent_platform " +
91 "SET catalogId=#{catalogId}, updateTime=#{updateTime}" + 88 "SET catalogId=#{catalogId}, updateTime=#{updateTime}" +
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformCatalogMapper.java
1 package com.genersoft.iot.vmp.storager.dao; 1 package com.genersoft.iot.vmp.storager.dao;
2 2
  3 +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
3 import com.genersoft.iot.vmp.gb28181.bean.GbStream; 4 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
4 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog; 5 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
5 import com.genersoft.iot.vmp.gb28181.bean.PlatformGbStream; 6 import com.genersoft.iot.vmp.gb28181.bean.PlatformGbStream;
@@ -14,8 +15,8 @@ import java.util.List; @@ -14,8 +15,8 @@ import java.util.List;
14 @Repository 15 @Repository
15 public interface PlatformCatalogMapper { 16 public interface PlatformCatalogMapper {
16 17
17 - @Insert("INSERT INTO platform_catalog (id, name, platformId, parentId) VALUES" +  
18 - "(#{id}, #{name}, #{platformId}, #{parentId})") 18 + @Insert("INSERT INTO platform_catalog (id, name, platformId, parentId, civilCode, businessGroupId) VALUES" +
  19 + "(#{id}, #{name}, #{platformId}, #{parentId}, #{civilCode}, #{businessGroupId})")
19 int add(PlatformCatalog platformCatalog); 20 int add(PlatformCatalog platformCatalog);
20 21
21 @Delete("DELETE FROM platform_catalog WHERE id=#{id}") 22 @Delete("DELETE FROM platform_catalog WHERE id=#{id}")
@@ -44,4 +45,12 @@ public interface PlatformCatalogMapper { @@ -44,4 +45,12 @@ public interface PlatformCatalogMapper {
44 45
45 @Select("SELECT pc.* FROM platform_catalog pc WHERE pc.id = (SELECT pp.catalogId from parent_platform pp WHERE pp.serverGBId=#{platformId})") 46 @Select("SELECT pc.* FROM platform_catalog pc WHERE pc.id = (SELECT pp.catalogId from parent_platform pp WHERE pp.serverGBId=#{platformId})")
46 PlatformCatalog selectDefaultByPlatFormId(String platformId); 47 PlatformCatalog selectDefaultByPlatFormId(String platformId);
  48 +
  49 +
  50 + @Select("SELECT pc.* FROM platform_catalog pc WHERE pc.id = #{id}")
  51 + PlatformCatalog selectParentCatalog(String id);
  52 +
  53 + @Select("SELECT pc.id as channelId, pc.name, pc.civilCode, pc.businessGroupId,'1' as parental, pc.parentId " +
  54 + " FROM platform_catalog pc WHERE pc.platformId=#{platformId}")
  55 + List<DeviceChannel> queryCatalogInPlatform(String platformId);
47 } 56 }
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.storager.dao; @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.storager.dao;
2 2
3 import com.genersoft.iot.vmp.gb28181.bean.GbStream; 3 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
4 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; 4 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
  5 +import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis;
5 import org.apache.ibatis.annotations.*; 6 import org.apache.ibatis.annotations.*;
6 // import org.omg.PortableInterceptor.INACTIVE; 7 // import org.omg.PortableInterceptor.INACTIVE;
7 import org.springframework.stereotype.Repository; 8 import org.springframework.stereotype.Repository;
@@ -14,9 +15,10 @@ import java.util.List; @@ -14,9 +15,10 @@ import java.util.List;
14 public interface StreamPushMapper { 15 public interface StreamPushMapper {
15 16
16 @Insert("INSERT INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " + 17 @Insert("INSERT INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " +
17 - "pushTime, aliveSecond, mediaServerId, serverId, updateTime, createTime) VALUES" + 18 + "pushTime, aliveSecond, mediaServerId, serverId, updateTime, createTime, pushIng, self) VALUES" +
18 "('${app}', '${stream}', '${totalReaderCount}', '${originType}', '${originTypeStr}', " + 19 "('${app}', '${stream}', '${totalReaderCount}', '${originType}', '${originTypeStr}', " +
19 - "'${pushTime}', '${aliveSecond}', '${mediaServerId}' , '${serverId}' , '${updateTime}' , '${createTime}' )") 20 + "'${pushTime}', '${aliveSecond}', '${mediaServerId}' , '${serverId}' , '${updateTime}' , '${createTime}', " +
  21 + "${pushIng}, ${self} )")
20 int add(StreamPushItem streamPushItem); 22 int add(StreamPushItem streamPushItem);
21 23
22 24
@@ -29,6 +31,8 @@ public interface StreamPushMapper { @@ -29,6 +31,8 @@ public interface StreamPushMapper {
29 "<if test=\"originTypeStr != null\">, originTypeStr='${originTypeStr}'</if>" + 31 "<if test=\"originTypeStr != null\">, originTypeStr='${originTypeStr}'</if>" +
30 "<if test=\"pushTime != null\">, pushTime='${pushTime}'</if>" + 32 "<if test=\"pushTime != null\">, pushTime='${pushTime}'</if>" +
31 "<if test=\"aliveSecond != null\">, aliveSecond='${aliveSecond}'</if>" + 33 "<if test=\"aliveSecond != null\">, aliveSecond='${aliveSecond}'</if>" +
  34 + "<if test=\"pushIng != null\">, pushIng=${pushIng}</if>" +
  35 + "<if test=\"self != null\">, self=${self}</if>" +
32 "WHERE app=#{app} AND stream=#{stream}"+ 36 "WHERE app=#{app} AND stream=#{stream}"+
33 " </script>"}) 37 " </script>"})
34 int update(StreamPushItem streamPushItem); 38 int update(StreamPushItem streamPushItem);
@@ -87,10 +91,11 @@ public interface StreamPushMapper { @@ -87,10 +91,11 @@ public interface StreamPushMapper {
87 91
88 @Insert("<script>" + 92 @Insert("<script>" +
89 "Insert IGNORE INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " + 93 "Insert IGNORE INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " +
90 - "createTime, aliveSecond, mediaServerId) " + 94 + "createTime, aliveSecond, mediaServerId, status, pushIng) " +
91 "VALUES <foreach collection='streamPushItems' item='item' index='index' separator=','>" + 95 "VALUES <foreach collection='streamPushItems' item='item' index='index' separator=','>" +
92 "( '${item.app}', '${item.stream}', '${item.totalReaderCount}', #{item.originType}, " + 96 "( '${item.app}', '${item.stream}', '${item.totalReaderCount}', #{item.originType}, " +
93 - "'${item.originTypeStr}',#{item.createTime}, #{item.aliveSecond}, '${item.mediaServerId}' )" + 97 + "'${item.originTypeStr}',#{item.createTime}, #{item.aliveSecond}, '${item.mediaServerId}', ${item.status} ," +
  98 + " ${item.pushIng} )" +
94 " </foreach>" + 99 " </foreach>" +
95 "</script>") 100 "</script>")
96 @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id") 101 @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
@@ -114,7 +119,53 @@ public interface StreamPushMapper { @@ -114,7 +119,53 @@ public interface StreamPushMapper {
114 int updateStatus(String app, String stream, boolean status); 119 int updateStatus(String app, String stream, boolean status);
115 120
116 @Update("UPDATE stream_push " + 121 @Update("UPDATE stream_push " +
  122 + "SET pushIng=${pushIng} " +
  123 + "WHERE app=#{app} AND stream=#{stream}")
  124 + int updatePushStatus(String app, String stream, boolean pushIng);
  125 +
  126 + @Update("UPDATE stream_push " +
117 "SET status=#{status} " + 127 "SET status=#{status} " +
118 "WHERE mediaServerId=#{mediaServerId}") 128 "WHERE mediaServerId=#{mediaServerId}")
119 void updateStatusByMediaServerId(String mediaServerId, boolean status); 129 void updateStatusByMediaServerId(String mediaServerId, boolean status);
  130 +
  131 +
  132 + @Select("<script> "+
  133 + "SELECT gs.* FROM stream_push sp left join gb_stream gs on sp.app = gs.app AND sp.stream = gs.stream " +
  134 + "where sp.status = 1 and (gs.app, gs.stream) in (" +
  135 + "<foreach collection='offlineStreams' item='item' separator=','>" +
  136 + "(#{item.app}, #{item.stream}) " +
  137 + "</foreach>" +
  138 + ")</script>")
  139 + List<GbStream> getOnlinePusherForGbInList(List<StreamPushItemFromRedis> offlineStreams);
  140 +
  141 + @Update("<script> "+
  142 + "UPDATE stream_push SET status=0 where (app, stream) in (" +
  143 + "<foreach collection='offlineStreams' item='item' separator=','>" +
  144 + "(#{item.app}, #{item.stream}) " +
  145 + "</foreach>" +
  146 + ")</script>")
  147 + void offline(List<StreamPushItemFromRedis> offlineStreams);
  148 +
  149 + @Select("<script> "+
  150 + "SELECT * FROM stream_push sp left join gb_stream gs on sp.app = gs.app AND sp.stream = gs.stream " +
  151 + "where sp.status = 0 and (gs.app, gs.stream) in (" +
  152 + "<foreach collection='onlineStreams' item='item' separator=','>" +
  153 + "(#{item.app}, #{item.stream}) " +
  154 + "</foreach>" +
  155 + ") </script>")
  156 + List<GbStream> getOfflinePusherForGbInList(List<StreamPushItemFromRedis> onlineStreams);
  157 +
  158 + @Update("<script> "+
  159 + "UPDATE stream_push SET status=1 where (app, stream) in (" +
  160 + "<foreach collection='onlineStreams' item='item' separator=','>" +
  161 + "(#{item.app}, #{item.stream}) " +
  162 + "</foreach>" +
  163 + ")</script>")
  164 + void online(List<StreamPushItemFromRedis> onlineStreams);
  165 +
  166 + @Select("SELECT gs.* FROM stream_push sp left join gb_stream gs on sp.app = gs.app AND sp.stream = gs.stream where sp.status = 1")
  167 + List<GbStream> getOnlinePusherForGb();
  168 +
  169 + @Update("UPDATE stream_push SET status=0")
  170 + void setAllStreamOffline();
120 } 171 }
src/main/java/com/genersoft/iot/vmp/storager/dao/UserMapper.java
@@ -55,4 +55,11 @@ public interface UserMapper { @@ -55,4 +55,11 @@ public interface UserMapper {
55 55
56 @Select("select * from user where md5(pushKey) = '${sign}'") 56 @Select("select * from user where md5(pushKey) = '${sign}'")
57 List<User> checkPushAuthorityByCallId(String sign); 57 List<User> checkPushAuthorityByCallId(String sign);
  58 +
  59 + @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")
  60 + @ResultMap(value="roleMap")
  61 + List<User> getUsers();
  62 +
  63 + @Update("update user set pushKey=#{pushKey} where id=#{id}")
  64 + int changePushKey(int id, String pushKey);
58 } 65 }
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -479,13 +479,18 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -479,13 +479,18 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
479 @Override 479 @Override
480 public void sendStreamChangeMsg(String type, JSONObject jsonObject) { 480 public void sendStreamChangeMsg(String type, JSONObject jsonObject) {
481 String key = VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + type; 481 String key = VideoManagerConstants.WVP_MSG_STREAM_CHANGE_PREFIX + type;
482 - logger.debug("[redis 流变化事件] {}: {}", key, jsonObject.toString()); 482 + logger.info("[redis 流变化事件] {}: {}", key, jsonObject.toString());
483 redis.convertAndSend(key, jsonObject); 483 redis.convertAndSend(key, jsonObject);
484 } 484 }
485 485
486 @Override 486 @Override
487 public void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, MediaItem mediaItem) { 487 public void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, MediaItem mediaItem) {
  488 + // 查找是否使用了callID
  489 + StreamAuthorityInfo streamAuthorityInfo = getStreamAuthorityInfo(app, streamId);
488 String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetting.getServerId() + "_" + type + "_" + app + "_" + streamId + "_" + mediaServerItem.getId(); 490 String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetting.getServerId() + "_" + type + "_" + app + "_" + streamId + "_" + mediaServerItem.getId();
  491 + if (streamAuthorityInfo != null) {
  492 + mediaItem.setCallId(streamAuthorityInfo.getCallId());
  493 + }
489 redis.set(key, mediaItem); 494 redis.set(key, mediaItem);
490 } 495 }
491 496
@@ -683,21 +688,21 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -683,21 +688,21 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
683 @Override 688 @Override
684 public void sendMobilePositionMsg(JSONObject jsonObject) { 689 public void sendMobilePositionMsg(JSONObject jsonObject) {
685 String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION; 690 String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_MOBILE_POSITION;
686 - logger.info("[redis 移动位置订阅通知] {}: {}", key, jsonObject.toString()); 691 + logger.info("[redis发送通知]移动位置 {}: {}", key, jsonObject.toString());
687 redis.convertAndSend(key, jsonObject); 692 redis.convertAndSend(key, jsonObject);
688 } 693 }
689 694
690 @Override 695 @Override
691 public void sendStreamPushRequestedMsg(MessageForPushChannel msg) { 696 public void sendStreamPushRequestedMsg(MessageForPushChannel msg) {
692 String key = VideoManagerConstants.VM_MSG_STREAM_PUSH_REQUESTED; 697 String key = VideoManagerConstants.VM_MSG_STREAM_PUSH_REQUESTED;
693 - logger.info("[redis 推流被请求通知] {}: {}/{}", key, msg.getApp(), msg.getStream()); 698 + logger.info("[redis发送通知]推流被请求 {}: {}/{}", key, msg.getApp(), msg.getStream());
694 redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg)); 699 redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
695 } 700 }
696 701
697 @Override 702 @Override
698 public void sendAlarmMsg(AlarmChannelMessage msg) { 703 public void sendAlarmMsg(AlarmChannelMessage msg) {
699 String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM; 704 String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM;
700 - logger.info("[redis 报警通知] {}: {}", key, JSON.toJSON(msg)); 705 + logger.info("[redis发送通知] 报警{}: {}", key, JSON.toJSON(msg));
701 redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg)); 706 redis.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
702 } 707 }
703 708
@@ -707,4 +712,12 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -707,4 +712,12 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
707 } 712 }
708 713
709 714
  715 + @Override
  716 + public void sendStreamPushRequestedMsgForStatus() {
  717 + String key = VideoManagerConstants.VM_MSG_GET_ALL_ONLINE_REQUESTED;
  718 + logger.info("[redis通知]获取所有推流设备的状态");
  719 + JSONObject jsonObject = new JSONObject();
  720 + jsonObject.put(key, key);
  721 + redis.convertAndSend(key, jsonObject);
  722 + }
710 } 723 }
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
@@ -48,13 +48,14 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -48,13 +48,14 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
48 @Autowired 48 @Autowired
49 SipConfig sipConfig; 49 SipConfig sipConfig;
50 50
51 - @Autowired  
52 - DataSourceTransactionManager dataSourceTransactionManager;  
53 51
54 @Autowired 52 @Autowired
55 TransactionDefinition transactionDefinition; 53 TransactionDefinition transactionDefinition;
56 54
57 @Autowired 55 @Autowired
  56 + DataSourceTransactionManager dataSourceTransactionManager;
  57 +
  58 + @Autowired
58 private DeviceMapper deviceMapper; 59 private DeviceMapper deviceMapper;
59 60
60 @Autowired 61 @Autowired
@@ -105,96 +106,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -105,96 +106,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
105 } 106 }
106 107
107 @Override 108 @Override
108 - public synchronized void updateChannel(String deviceId, DeviceChannel channel) {  
109 - String channelId = channel.getChannelId();  
110 - channel.setDeviceId(deviceId);  
111 - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);  
112 - if (streamInfo != null) {  
113 - channel.setStreamId(streamInfo.getStream());  
114 - }  
115 - String now = DateUtil.getNow();  
116 - channel.setUpdateTime(now);  
117 - DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId);  
118 - if (deviceChannel == null) {  
119 - channel.setCreateTime(now);  
120 - deviceChannelMapper.add(channel);  
121 - }else {  
122 - deviceChannelMapper.update(channel);  
123 - }  
124 - deviceChannelMapper.updateChannelSubCount(deviceId,channel.getParentId());  
125 - }  
126 -  
127 - @Override  
128 - public int updateChannels(String deviceId, List<DeviceChannel> channels) {  
129 - List<DeviceChannel> addChannels = new ArrayList<>();  
130 - List<DeviceChannel> updateChannels = new ArrayList<>();  
131 - HashMap<String, DeviceChannel> channelsInStore = new HashMap<>();  
132 - if (channels != null && channels.size() > 0) {  
133 - List<DeviceChannel> channelList = deviceChannelMapper.queryChannels(deviceId, null, null, null, null);  
134 - if (channelList.size() == 0) {  
135 - for (DeviceChannel channel : channels) {  
136 - channel.setDeviceId(deviceId);  
137 - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());  
138 - if (streamInfo != null) {  
139 - channel.setStreamId(streamInfo.getStream());  
140 - }  
141 - String now = DateUtil.getNow();  
142 - channel.setUpdateTime(now);  
143 - channel.setCreateTime(now);  
144 - addChannels.add(channel);  
145 - }  
146 - }else {  
147 - for (DeviceChannel deviceChannel : channelList) {  
148 - channelsInStore.put(deviceChannel.getChannelId(), deviceChannel);  
149 - }  
150 - for (DeviceChannel channel : channels) {  
151 - channel.setDeviceId(deviceId);  
152 - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());  
153 - if (streamInfo != null) {  
154 - channel.setStreamId(streamInfo.getStream());  
155 - }  
156 - String now = DateUtil.getNow();  
157 - channel.setUpdateTime(now);  
158 - if (channelsInStore.get(channel.getChannelId()) != null) {  
159 - updateChannels.add(channel);  
160 - }else {  
161 - addChannels.add(channel);  
162 - channel.setCreateTime(now);  
163 - }  
164 - }  
165 - }  
166 - int limitCount = 300;  
167 - if (addChannels.size() > 0) {  
168 - if (addChannels.size() > limitCount) {  
169 - for (int i = 0; i < addChannels.size(); i += limitCount) {  
170 - int toIndex = i + limitCount;  
171 - if (i + limitCount > addChannels.size()) {  
172 - toIndex = addChannels.size();  
173 - }  
174 - deviceChannelMapper.batchAdd(addChannels.subList(i, toIndex));  
175 - }  
176 - }else {  
177 - deviceChannelMapper.batchAdd(addChannels);  
178 - }  
179 - }  
180 - if (updateChannels.size() > 0) {  
181 - if (updateChannels.size() > limitCount) {  
182 - for (int i = 0; i < updateChannels.size(); i += limitCount) {  
183 - int toIndex = i + limitCount;  
184 - if (i + limitCount > updateChannels.size()) {  
185 - toIndex = updateChannels.size();  
186 - }  
187 - deviceChannelMapper.batchUpdate(updateChannels.subList(i, toIndex));  
188 - }  
189 - }else {  
190 - deviceChannelMapper.batchUpdate(updateChannels);  
191 - }  
192 - }  
193 - }  
194 - return addChannels.size() + updateChannels.size();  
195 - }  
196 -  
197 - @Override  
198 public boolean resetChannels(String deviceId, List<DeviceChannel> deviceChannelList) { 109 public boolean resetChannels(String deviceId, List<DeviceChannel> deviceChannelList) {
199 if (CollectionUtils.isEmpty(deviceChannelList)) { 110 if (CollectionUtils.isEmpty(deviceChannelList)) {
200 return false; 111 return false;
@@ -532,20 +443,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -532,20 +443,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
532 // 更新缓存 443 // 更新缓存
533 parentPlatformCatch.setParentPlatform(parentPlatform); 444 parentPlatformCatch.setParentPlatform(parentPlatform);
534 redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); 445 redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
535 - if (parentPlatform.isEnable()) {  
536 - // 共享所有视频流,需要将现有视频流添加到此平台  
537 - List<GbStream> gbStreams = gbStreamMapper.queryStreamNotInPlatform();  
538 - if (gbStreams.size() > 0) {  
539 - for (GbStream gbStream : gbStreams) {  
540 - gbStream.setCatalogId(parentPlatform.getCatalogId());  
541 - }  
542 - if (parentPlatform.isShareAllLiveStream()) {  
543 - gbStreamService.addPlatformInfo(gbStreams, parentPlatform.getServerGBId(), parentPlatform.getCatalogId());  
544 - }else {  
545 - gbStreamService.delPlatformInfo(parentPlatform.getServerGBId(), gbStreams);  
546 - }  
547 - }  
548 - }  
549 446
550 return result > 0; 447 return result > 0;
551 } 448 }
@@ -596,36 +493,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -596,36 +493,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
596 return deviceChannelMapper.queryChannelByPlatformId(platformId); 493 return deviceChannelMapper.queryChannelByPlatformId(platformId);
597 } 494 }
598 495
599 - @Override  
600 - public int updateChannelForGB(String platformId, List<ChannelReduce> channelReduces, String catalogId) {  
601 -  
602 - Map<Integer, ChannelReduce> deviceAndChannels = new HashMap<>();  
603 - for (ChannelReduce channelReduce : channelReduces) {  
604 - channelReduce.setCatalogId(catalogId);  
605 - deviceAndChannels.put(channelReduce.getId(), channelReduce);  
606 - }  
607 - List<Integer> deviceAndChannelList = new ArrayList<>(deviceAndChannels.keySet());  
608 - // 查询当前已经存在的  
609 - List<Integer> channelIds = platformChannelMapper.findChannelRelatedPlatform(platformId, channelReduces);  
610 - if (deviceAndChannelList != null) {  
611 - deviceAndChannelList.removeAll(channelIds);  
612 - }  
613 - for (Integer channelId : channelIds) {  
614 - deviceAndChannels.remove(channelId);  
615 - }  
616 - List<ChannelReduce> channelReducesToAdd = new ArrayList<>(deviceAndChannels.values());  
617 - // 对剩下的数据进行存储  
618 - int result = 0;  
619 - if (channelReducesToAdd.size() > 0) {  
620 - result = platformChannelMapper.addChannels(platformId, channelReducesToAdd);  
621 - // TODO 后续给平台增加控制开关以控制是否响应目录订阅  
622 - List<DeviceChannel> deviceChannelList = getDeviceChannelListByChannelReduceList(channelReducesToAdd, catalogId);  
623 - eventPublisher.catalogEventPublish(platformId, deviceChannelList, CatalogEvent.ADD);  
624 - }  
625 -  
626 - return result;  
627 - }  
628 -  
629 496
630 @Override 497 @Override
631 public int delChannelForGB(String platformId, List<ChannelReduce> channelReduces) { 498 public int delChannelForGB(String platformId, List<ChannelReduce> channelReduces) {
@@ -701,77 +568,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -701,77 +568,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
701 return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId); 568 return deviceMobilePositionMapper.clearMobilePositionsByDeviceId(deviceId);
702 } 569 }
703 570
704 - /**  
705 - * 新增代理流  
706 - * @param streamProxyItem  
707 - * @return  
708 - */  
709 - @Override  
710 - public boolean addStreamProxy(StreamProxyItem streamProxyItem) {  
711 - TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);  
712 - boolean result = false;  
713 - streamProxyItem.setStreamType("proxy");  
714 - streamProxyItem.setStatus(true);  
715 - String now = DateUtil.getNow();  
716 - streamProxyItem.setCreateTime(now);  
717 - try {  
718 - if (streamProxyMapper.add(streamProxyItem) > 0) {  
719 - if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {  
720 - if (gbStreamMapper.add(streamProxyItem) < 0) {  
721 - //事务回滚  
722 - dataSourceTransactionManager.rollback(transactionStatus);  
723 - return false;  
724 - }  
725 - }  
726 - }else {  
727 - //事务回滚  
728 - dataSourceTransactionManager.rollback(transactionStatus);  
729 - return false;  
730 - }  
731 - result = true;  
732 - dataSourceTransactionManager.commit(transactionStatus); //手动提交  
733 - }catch (Exception e) {  
734 - logger.error("向数据库添加流代理失败:", e);  
735 - dataSourceTransactionManager.rollback(transactionStatus);  
736 - }  
737 -  
738 -  
739 - return result;  
740 - }  
741 -  
742 - /**  
743 - * 更新代理流  
744 - * @param streamProxyItem  
745 - * @return  
746 - */  
747 - @Override  
748 - public boolean updateStreamProxy(StreamProxyItem streamProxyItem) {  
749 - TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);  
750 - boolean result = false;  
751 - streamProxyItem.setStreamType("proxy");  
752 - try {  
753 - if (streamProxyMapper.update(streamProxyItem) > 0) {  
754 - if (!StringUtils.isEmpty(streamProxyItem.getGbId())) {  
755 - if (gbStreamMapper.updateByAppAndStream(streamProxyItem) == 0) {  
756 - //事务回滚  
757 - dataSourceTransactionManager.rollback(transactionStatus);  
758 - return false;  
759 - }  
760 - }  
761 - } else {  
762 - //事务回滚  
763 - dataSourceTransactionManager.rollback(transactionStatus);  
764 - return false;  
765 - }  
766 -  
767 - dataSourceTransactionManager.commit(transactionStatus); //手动提交  
768 - result = true;  
769 - }catch (Exception e) {  
770 - e.printStackTrace();  
771 - dataSourceTransactionManager.rollback(transactionStatus);  
772 - }  
773 - return result;  
774 - }  
775 571
776 /** 572 /**
777 * 移除代理流 573 * 移除代理流
@@ -824,7 +620,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -824,7 +620,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
824 * @return 620 * @return
825 */ 621 */
826 @Override 622 @Override
827 - public List<GbStream> queryGbStreamListInPlatform(String platformId) { 623 + public List<DeviceChannel> queryGbStreamListInPlatform(String platformId) {
828 return gbStreamMapper.queryGbStreamListInPlatform(platformId); 624 return gbStreamMapper.queryGbStreamListInPlatform(platformId);
829 } 625 }
830 626
@@ -840,83 +636,30 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -840,83 +636,30 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
840 } 636 }
841 637
842 @Override 638 @Override
843 - public void updateMediaList(List<StreamPushItem> streamPushItems) {  
844 - if (streamPushItems == null || streamPushItems.size() == 0) {  
845 - return;  
846 - }  
847 - logger.info("updateMediaList: " + streamPushItems.size());  
848 - streamPushMapper.addAll(streamPushItems);  
849 - // TODO 待优化  
850 - for (int i = 0; i < streamPushItems.size(); i++) {  
851 - int onlineResult = mediaOnline(streamPushItems.get(i).getApp(), streamPushItems.get(i).getStream());  
852 - if (onlineResult > 0) {  
853 - // 发送上线通知  
854 - eventPublisher.catalogEventPublishForStream(null, streamPushItems.get(i), CatalogEvent.ON);  
855 - }  
856 - }  
857 - }  
858 -  
859 -  
860 -  
861 - @Override  
862 - public void updateMedia(StreamPushItem streamPushItem) {  
863 - streamPushMapper.del(streamPushItem.getApp(), streamPushItem.getStream());  
864 - streamPushMapper.add(streamPushItem);  
865 - mediaOffline(streamPushItem.getApp(), streamPushItem.getStream());  
866 -  
867 - if(!StringUtils.isEmpty(streamPushItem.getGbId() )){  
868 - // 查找开启了全部直播流共享的上级平台  
869 - List<ParentPlatform> parentPlatforms = parentPlatformMapper.selectAllAhareAllLiveStream();  
870 - if (parentPlatforms.size() > 0) {  
871 - for (ParentPlatform parentPlatform : parentPlatforms) {  
872 - StreamProxyItem streamProxyItem = platformGbStreamMapper.selectOne(streamPushItem.getApp(), streamPushItem.getStream(),  
873 - parentPlatform.getServerGBId());  
874 - if (streamProxyItem == null) {  
875 - streamPushItem.setCatalogId(parentPlatform.getCatalogId());  
876 - streamPushItem.setPlatformId(parentPlatform.getServerGBId());  
877 - platformGbStreamMapper.add(streamPushItem);  
878 - eventPublisher.catalogEventPublishForStream(parentPlatform.getServerGBId(), streamPushItem, CatalogEvent.ADD);  
879 - }  
880 - }  
881 - }  
882 - }  
883 -  
884 - }  
885 -  
886 - @Override  
887 public int removeMedia(String app, String stream) { 639 public int removeMedia(String app, String stream) {
888 return streamPushMapper.del(app, stream); 640 return streamPushMapper.del(app, stream);
889 } 641 }
890 642
891 @Override 643 @Override
892 - public StreamPushItem getMedia(String app, String stream) {  
893 - return streamPushMapper.selectOne(app, stream);  
894 - }  
895 -  
896 - @Override  
897 - public void clearMediaList() {  
898 - streamPushMapper.clear();  
899 - }  
900 -  
901 - @Override  
902 public int mediaOffline(String app, String stream) { 644 public int mediaOffline(String app, String stream) {
903 GbStream gbStream = gbStreamMapper.selectOne(app, stream); 645 GbStream gbStream = gbStreamMapper.selectOne(app, stream);
904 int result; 646 int result;
905 if ("proxy".equals(gbStream.getStreamType())) { 647 if ("proxy".equals(gbStream.getStreamType())) {
906 result = streamProxyMapper.updateStatus(app, stream, false); 648 result = streamProxyMapper.updateStatus(app, stream, false);
907 }else { 649 }else {
908 - result = streamPushMapper.updateStatus(app, stream, false); 650 + result = streamPushMapper.updatePushStatus(app, stream, false);
909 } 651 }
910 return result; 652 return result;
911 } 653 }
912 654
  655 + @Override
913 public int mediaOnline(String app, String stream) { 656 public int mediaOnline(String app, String stream) {
914 GbStream gbStream = gbStreamMapper.selectOne(app, stream); 657 GbStream gbStream = gbStreamMapper.selectOne(app, stream);
915 int result; 658 int result;
916 if ("proxy".equals(gbStream.getStreamType())) { 659 if ("proxy".equals(gbStream.getStreamType())) {
917 result = streamProxyMapper.updateStatus(app, stream, true); 660 result = streamProxyMapper.updateStatus(app, stream, true);
918 }else { 661 }else {
919 - result = streamPushMapper.updateStatus(app, stream, true); 662 + result = streamPushMapper.updatePushStatus(app, stream, true);
920 } 663 }
921 return result; 664 return result;
922 } 665 }
@@ -954,6 +697,29 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -954,6 +697,29 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
954 697
955 @Override 698 @Override
956 public int addCatalog(PlatformCatalog platformCatalog) { 699 public int addCatalog(PlatformCatalog platformCatalog) {
  700 + ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformCatalog.getPlatformId());
  701 + if (platform == null) {
  702 + return 0;
  703 + }
  704 + if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)) {
  705 + if (platformCatalog.getPlatformId().equals(platformCatalog.getParentId())) {
  706 + // 第一层节点
  707 + platformCatalog.setBusinessGroupId(platformCatalog.getId());
  708 + platformCatalog.setParentId(platform.getDeviceGBId());
  709 + }else {
  710 + // 获取顶层的
  711 + PlatformCatalog topCatalog = getTopCatalog(platformCatalog.getParentId(), platform.getDeviceGBId());
  712 + platformCatalog.setBusinessGroupId(topCatalog.getId());
  713 + }
  714 + }
  715 + if (platform.getTreeType().equals(TreeType.CIVIL_CODE)) {
  716 + platformCatalog.setCivilCode(platformCatalog.getId());
  717 + if (platformCatalog.getPlatformId().equals(platformCatalog.getParentId())) {
  718 + // 第一层节点
  719 + platformCatalog.setParentId(platform.getDeviceGBId());
  720 + }
  721 + }
  722 +
957 int result = catalogMapper.add(platformCatalog); 723 int result = catalogMapper.add(platformCatalog);
958 if (result > 0) { 724 if (result > 0) {
959 DeviceChannel deviceChannel = getDeviceChannelByCatalog(platformCatalog); 725 DeviceChannel deviceChannel = getDeviceChannelByCatalog(platformCatalog);
@@ -962,6 +728,15 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -962,6 +728,15 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
962 return result; 728 return result;
963 } 729 }
964 730
  731 + private PlatformCatalog getTopCatalog(String id, String platformId) {
  732 + PlatformCatalog catalog = catalogMapper.selectParentCatalog(id);
  733 + if (catalog.getParentId().equals(platformId)) {
  734 + return catalog;
  735 + }else {
  736 + return getTopCatalog(catalog.getParentId(), platformId);
  737 + }
  738 + }
  739 +
965 @Override 740 @Override
966 public PlatformCatalog getCatalog(String id) { 741 public PlatformCatalog getCatalog(String id) {
967 return catalogMapper.select(id); 742 return catalogMapper.select(id);
@@ -1032,8 +807,8 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -1032,8 +807,8 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
1032 } 807 }
1033 808
1034 @Override 809 @Override
1035 - public List<PlatformCatalog> queryCatalogInPlatform(String platformId) {  
1036 - return catalogMapper.selectByPlatForm(platformId); 810 + public List<DeviceChannel> queryCatalogInPlatform(String platformId) {
  811 + return catalogMapper.queryCatalogInPlatform(platformId);
1037 } 812 }
1038 813
1039 @Override 814 @Override
@@ -1076,20 +851,24 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -1076,20 +851,24 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
1076 } 851 }
1077 852
1078 private DeviceChannel getDeviceChannelByCatalog(PlatformCatalog catalog) { 853 private DeviceChannel getDeviceChannelByCatalog(PlatformCatalog catalog) {
1079 - ParentPlatform parentPlatByServerGBId = platformMapper.getParentPlatByServerGBId(catalog.getPlatformId()); 854 + ParentPlatform platform = platformMapper.getParentPlatByServerGBId(catalog.getPlatformId());
1080 DeviceChannel deviceChannel = new DeviceChannel(); 855 DeviceChannel deviceChannel = new DeviceChannel();
1081 deviceChannel.setChannelId(catalog.getId()); 856 deviceChannel.setChannelId(catalog.getId());
1082 deviceChannel.setName(catalog.getName()); 857 deviceChannel.setName(catalog.getName());
1083 deviceChannel.setLongitude(0.0); 858 deviceChannel.setLongitude(0.0);
1084 deviceChannel.setLatitude(0.0); 859 deviceChannel.setLatitude(0.0);
1085 - deviceChannel.setDeviceId(parentPlatByServerGBId.getDeviceGBId()); 860 + deviceChannel.setDeviceId(platform.getDeviceGBId());
1086 deviceChannel.setManufacture("wvp-pro"); 861 deviceChannel.setManufacture("wvp-pro");
1087 deviceChannel.setStatus(1); 862 deviceChannel.setStatus(1);
1088 deviceChannel.setParental(1); 863 deviceChannel.setParental(1);
1089 - deviceChannel.setParentId(catalog.getParentId()); 864 +
1090 deviceChannel.setRegisterWay(1); 865 deviceChannel.setRegisterWay(1);
1091 // 行政区划应该是Domain的前八位 866 // 行政区划应该是Domain的前八位
1092 - deviceChannel.setCivilCode(parentPlatByServerGBId.getAdministrativeDivision()); 867 + if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)) {
  868 + deviceChannel.setParentId(catalog.getParentId());
  869 + deviceChannel.setBusinessGroupId(catalog.getBusinessGroupId());
  870 + }
  871 +
1093 deviceChannel.setModel("live"); 872 deviceChannel.setModel("live");
1094 deviceChannel.setOwner("wvp-pro"); 873 deviceChannel.setOwner("wvp-pro");
1095 deviceChannel.setSecrecy("0"); 874 deviceChannel.setSecrecy("0");
@@ -1151,4 +930,27 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -1151,4 +930,27 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
1151 930
1152 deviceChannelMapper.updatePosition(deviceChannel); 931 deviceChannelMapper.updatePosition(deviceChannel);
1153 } 932 }
  933 +
  934 + @Override
  935 + public void cleanContentForPlatform(String serverGBId) {
  936 +// List<PlatformCatalog> catalogList = catalogMapper.selectByPlatForm(serverGBId);
  937 +// if (catalogList.size() > 0) {
  938 +// int result = catalogMapper.delByPlatformId(serverGBId);
  939 +// if (result > 0) {
  940 +// List<DeviceChannel> deviceChannels = new ArrayList<>();
  941 +// for (PlatformCatalog catalog : catalogList) {
  942 +// deviceChannels.add(getDeviceChannelByCatalog(catalog));
  943 +// }
  944 +// eventPublisher.catalogEventPublish(serverGBId, deviceChannels, CatalogEvent.DEL);
  945 +// }
  946 +// }
  947 + catalogMapper.delByPlatformId(serverGBId);
  948 + platformChannelMapper.delByPlatformId(serverGBId);
  949 + platformGbStreamMapper.delByPlatformId(serverGBId);
  950 + }
  951 +
  952 + @Override
  953 + public List<DeviceChannel> queryChannelWithCatalog(String serverGBId) {
  954 + return deviceChannelMapper.queryChannelWithCatalog(serverGBId);
  955 + }
1154 } 956 }
src/main/java/com/genersoft/iot/vmp/vmanager/bean/WVPResult.java
@@ -12,6 +12,7 @@ public class WVPResult&lt;T&gt; { @@ -12,6 +12,7 @@ public class WVPResult&lt;T&gt; {
12 this.data = data; 12 this.data = data;
13 } 13 }
14 14
  15 +
15 private int code; 16 private int code;
16 private String msg; 17 private String msg;
17 private T data; 18 private T data;
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
@@ -12,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; @@ -12,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
12 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 12 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
13 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 13 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
14 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 14 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
  15 +import com.genersoft.iot.vmp.service.IDeviceChannelService;
15 import com.genersoft.iot.vmp.service.IDeviceService; 16 import com.genersoft.iot.vmp.service.IDeviceService;
16 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 17 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
17 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 18 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
@@ -53,6 +54,9 @@ public class DeviceQuery { @@ -53,6 +54,9 @@ public class DeviceQuery {
53 private IVideoManagerStorage storager; 54 private IVideoManagerStorage storager;
54 55
55 @Autowired 56 @Autowired
  57 + private IDeviceChannelService deviceChannelService;
  58 +
  59 + @Autowired
56 private IRedisCatchStorage redisCatchStorage; 60 private IRedisCatchStorage redisCatchStorage;
57 61
58 @Autowired 62 @Autowired
@@ -280,7 +284,7 @@ public class DeviceQuery { @@ -280,7 +284,7 @@ public class DeviceQuery {
280 }) 284 })
281 @PostMapping("/channel/update/{deviceId}") 285 @PostMapping("/channel/update/{deviceId}")
282 public ResponseEntity<PageInfo> updateChannel(@PathVariable String deviceId,DeviceChannel channel){ 286 public ResponseEntity<PageInfo> updateChannel(@PathVariable String deviceId,DeviceChannel channel){
283 - storager.updateChannel(deviceId, channel); 287 + deviceChannelService.updateChannel(deviceId, channel);
284 return new ResponseEntity<>(null,HttpStatus.OK); 288 return new ResponseEntity<>(null,HttpStatus.OK);
285 } 289 }
286 290
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/gbStream/GbStreamController.java
@@ -44,7 +44,6 @@ public class GbStreamController { @@ -44,7 +44,6 @@ public class GbStreamController {
44 @ApiImplicitParam(name = "platformId", value = "平台ID", required = true , dataTypeClass = String.class), 44 @ApiImplicitParam(name = "platformId", value = "平台ID", required = true , dataTypeClass = String.class),
45 @ApiImplicitParam(name = "catalogId", value = "目录ID", required = false , dataTypeClass = String.class), 45 @ApiImplicitParam(name = "catalogId", value = "目录ID", required = false , dataTypeClass = String.class),
46 @ApiImplicitParam(name="query", value = "查询内容", required = false , dataTypeClass = String.class), 46 @ApiImplicitParam(name="query", value = "查询内容", required = false , dataTypeClass = String.class),
47 - @ApiImplicitParam(name="pushing", value = "是否正在推流", required = false , dataTypeClass = Boolean.class),  
48 @ApiImplicitParam(name="mediaServerId", value = "流媒体ID", required = false , dataTypeClass = String.class), 47 @ApiImplicitParam(name="mediaServerId", value = "流媒体ID", required = false , dataTypeClass = String.class),
49 48
50 }) 49 })
@@ -55,7 +54,6 @@ public class GbStreamController { @@ -55,7 +54,6 @@ public class GbStreamController {
55 @RequestParam(required = true)String platformId, 54 @RequestParam(required = true)String platformId,
56 @RequestParam(required = false)String catalogId, 55 @RequestParam(required = false)String catalogId,
57 @RequestParam(required = false)String query, 56 @RequestParam(required = false)String query,
58 - @RequestParam(required = false)Boolean pushing,  
59 @RequestParam(required = false)String mediaServerId){ 57 @RequestParam(required = false)String mediaServerId){
60 if (StringUtils.isEmpty(catalogId)) { 58 if (StringUtils.isEmpty(catalogId)) {
61 catalogId = null; 59 catalogId = null;
@@ -69,7 +67,7 @@ public class GbStreamController { @@ -69,7 +67,7 @@ public class GbStreamController {
69 67
70 // catalogId 为null 查询未在平台下分配的数据 68 // catalogId 为null 查询未在平台下分配的数据
71 // catalogId 不为null 查询平台下这个,目录下的通道 69 // catalogId 不为null 查询平台下这个,目录下的通道
72 - return gbStreamService.getAll(page, count, platformId, catalogId, query, pushing, mediaServerId); 70 + return gbStreamService.getAll(page, count, platformId, catalogId, query, mediaServerId);
73 } 71 }
74 72
75 73
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java
@@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.conf.security.dto.LoginUser; @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
6 import com.genersoft.iot.vmp.media.zlm.dto.OnPublishHookParam; 6 import com.genersoft.iot.vmp.media.zlm.dto.OnPublishHookParam;
7 import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; 7 import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
8 import com.genersoft.iot.vmp.service.IMediaServerService; 8 import com.genersoft.iot.vmp.service.IMediaServerService;
  9 +import com.genersoft.iot.vmp.service.IStreamProxyService;
9 import com.genersoft.iot.vmp.service.IStreamPushService; 10 import com.genersoft.iot.vmp.service.IStreamPushService;
10 import com.genersoft.iot.vmp.service.IMediaService; 11 import com.genersoft.iot.vmp.service.IMediaService;
11 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 12 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
@@ -37,6 +38,8 @@ public class MediaController { @@ -37,6 +38,8 @@ public class MediaController {
37 38
38 @Autowired 39 @Autowired
39 private IMediaService mediaService; 40 private IMediaService mediaService;
  41 + @Autowired
  42 + private IStreamProxyService streamProxyService;
40 43
41 44
42 /** 45 /**
@@ -95,8 +98,30 @@ public class MediaController { @@ -95,8 +98,30 @@ public class MediaController {
95 result.setMsg("scccess"); 98 result.setMsg("scccess");
96 result.setData(streamInfo); 99 result.setData(streamInfo);
97 }else { 100 }else {
98 - result.setCode(-1);  
99 - result.setMsg("fail"); 101 + //获取流失败,重启拉流后重试一次
  102 + streamProxyService.stop(app,stream);
  103 + boolean start = streamProxyService.start(app, stream);
  104 + try {
  105 + Thread.sleep(1000);
  106 + } catch (InterruptedException e) {
  107 + e.printStackTrace();
  108 + }
  109 + if (useSourceIpAsStreamIp != null && useSourceIpAsStreamIp) {
  110 + String host = request.getHeader("Host");
  111 + String localAddr = host.split(":")[0];
  112 + logger.info("使用{}作为返回流的ip", localAddr);
  113 + streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, localAddr, authority);
  114 + }else {
  115 + streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority);
  116 + }
  117 + if (streamInfo != null){
  118 + result.setCode(0);
  119 + result.setMsg("scccess");
  120 + result.setData(streamInfo);
  121 + }else {
  122 + result.setCode(-1);
  123 + result.setMsg("fail");
  124 + }
100 } 125 }
101 return result; 126 return result;
102 } 127 }
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
@@ -8,7 +8,9 @@ import com.genersoft.iot.vmp.conf.UserSetting; @@ -8,7 +8,9 @@ import com.genersoft.iot.vmp.conf.UserSetting;
8 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 8 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
9 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog; 9 import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog;
10 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder; 10 import com.genersoft.iot.vmp.gb28181.bean.SubscribeHolder;
  11 +import com.genersoft.iot.vmp.gb28181.bean.TreeType;
11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 12 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
  13 +import com.genersoft.iot.vmp.service.IPlatformChannelService;
12 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 14 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
13 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 15 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
14 import com.genersoft.iot.vmp.utils.DateUtil; 16 import com.genersoft.iot.vmp.utils.DateUtil;
@@ -49,6 +51,9 @@ public class PlatformController { @@ -49,6 +51,9 @@ public class PlatformController {
49 private IVideoManagerStorage storager; 51 private IVideoManagerStorage storager;
50 52
51 @Autowired 53 @Autowired
  54 + private IPlatformChannelService platformChannelService;
  55 +
  56 + @Autowired
52 private IRedisCatchStorage redisCatchStorage; 57 private IRedisCatchStorage redisCatchStorage;
53 58
54 @Autowired 59 @Autowired
@@ -236,6 +241,12 @@ public class PlatformController { @@ -236,6 +241,12 @@ public class PlatformController {
236 parentPlatform.setCharacterSet(parentPlatform.getCharacterSet().toUpperCase()); 241 parentPlatform.setCharacterSet(parentPlatform.getCharacterSet().toUpperCase());
237 ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId()); 242 ParentPlatform parentPlatformOld = storager.queryParentPlatByServerGBId(parentPlatform.getServerGBId());
238 parentPlatform.setUpdateTime(DateUtil.getNow()); 243 parentPlatform.setUpdateTime(DateUtil.getNow());
  244 + if (!parentPlatformOld.getTreeType().equals(parentPlatform.getTreeType())) {
  245 + // 目录结构发生变化,清空之前的关联关系
  246 + logger.info("保存平台{}时发现目录结构变化,清空关联关系", parentPlatform.getDeviceGBId());
  247 + storager.cleanContentForPlatform(parentPlatform.getServerGBId());
  248 +
  249 + }
239 boolean updateResult = storager.updateParentPlatform(parentPlatform); 250 boolean updateResult = storager.updateParentPlatform(parentPlatform);
240 251
241 if (updateResult) { 252 if (updateResult) {
@@ -256,6 +267,8 @@ public class PlatformController { @@ -256,6 +267,8 @@ public class PlatformController {
256 } 267 }
257 } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()) { // 关闭启用时注销 268 } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()) { // 关闭启用时注销
258 commanderForPlatform.unregister(parentPlatformOld, null, null); 269 commanderForPlatform.unregister(parentPlatformOld, null, null);
  270 + // 停止订阅相关的定时任务
  271 + subscribeHolder.removeAllSubscribe(parentPlatform.getServerGBId());
259 } 272 }
260 wvpResult.setCode(0); 273 wvpResult.setCode(0);
261 wvpResult.setMsg("success"); 274 wvpResult.setMsg("success");
@@ -405,7 +418,7 @@ public class PlatformController { @@ -405,7 +418,7 @@ public class PlatformController {
405 if (logger.isDebugEnabled()) { 418 if (logger.isDebugEnabled()) {
406 logger.debug("给上级平台添加国标通道API调用"); 419 logger.debug("给上级平台添加国标通道API调用");
407 } 420 }
408 - int result = storager.updateChannelForGB(param.getPlatformId(), param.getChannelReduces(), param.getCatalogId()); 421 + int result = platformChannelService.updateChannelForGB(param.getPlatformId(), param.getChannelReduces(), param.getCatalogId());
409 422
410 return new ResponseEntity<>(String.valueOf(result > 0), HttpStatus.OK); 423 return new ResponseEntity<>(String.valueOf(result > 0), HttpStatus.OK);
411 } 424 }
@@ -451,13 +464,20 @@ public class PlatformController { @@ -451,13 +464,20 @@ public class PlatformController {
451 if (logger.isDebugEnabled()) { 464 if (logger.isDebugEnabled()) {
452 logger.debug("查询目录,platformId: {}, parentId: {}", platformId, parentId); 465 logger.debug("查询目录,platformId: {}, parentId: {}", platformId, parentId);
453 } 466 }
  467 + ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
  468 + if (platform == null) {
  469 + return new ResponseEntity<>(new WVPResult<>(400, "平台未找到", null), HttpStatus.OK);
  470 + }
  471 + if (platformId.equals(parentId)) {
  472 + parentId = platform.getDeviceGBId();
  473 + }
454 List<PlatformCatalog> platformCatalogList = storager.getChildrenCatalogByPlatform(platformId, parentId); 474 List<PlatformCatalog> platformCatalogList = storager.getChildrenCatalogByPlatform(platformId, parentId);
455 - // 查询下属的国标通道  
456 -// List<PlatformCatalog> catalogsForChannel = storager.queryChannelInParentPlatformAndCatalog(platformId, parentId);  
457 - // 查询下属的直播流通道  
458 -// List<PlatformCatalog> catalogsForStream = storager.queryStreamInParentPlatformAndCatalog(platformId, parentId);  
459 -// platformCatalogList.addAll(catalogsForChannel);  
460 -// platformCatalogList.addAll(catalogsForStream); 475 +// if (platform.getTreeType().equals(TreeType.BUSINESS_GROUP)) {
  476 +// platformCatalogList = storager.getChildrenCatalogByPlatform(platformId, parentId);
  477 +// }else {
  478 +//
  479 +// }
  480 +
461 WVPResult<List<PlatformCatalog>> result = new WVPResult<>(); 481 WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
462 result.setCode(0); 482 result.setCode(0);
463 result.setMsg("success"); 483 result.setMsg("success");
@@ -485,7 +505,6 @@ public class PlatformController { @@ -485,7 +505,6 @@ public class PlatformController {
485 PlatformCatalog platformCatalogInStore = storager.getCatalog(platformCatalog.getId()); 505 PlatformCatalog platformCatalogInStore = storager.getCatalog(platformCatalog.getId());
486 WVPResult<List<PlatformCatalog>> result = new WVPResult<>(); 506 WVPResult<List<PlatformCatalog>> result = new WVPResult<>();
487 507
488 -  
489 if (platformCatalogInStore != null) { 508 if (platformCatalogInStore != null) {
490 result.setCode(-1); 509 result.setCode(-1);
491 result.setMsg(platformCatalog.getId() + " already exists"); 510 result.setMsg(platformCatalog.getId() + " already exists");
src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java
@@ -8,6 +8,8 @@ import com.genersoft.iot.vmp.conf.DynamicTask; @@ -8,6 +8,8 @@ import com.genersoft.iot.vmp.conf.DynamicTask;
8 import com.genersoft.iot.vmp.conf.SipConfig; 8 import com.genersoft.iot.vmp.conf.SipConfig;
9 import com.genersoft.iot.vmp.conf.UserSetting; 9 import com.genersoft.iot.vmp.conf.UserSetting;
10 import com.genersoft.iot.vmp.conf.VersionInfo; 10 import com.genersoft.iot.vmp.conf.VersionInfo;
  11 +import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
  12 +import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe;
11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 13 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
12 import com.genersoft.iot.vmp.service.IMediaServerService; 14 import com.genersoft.iot.vmp.service.IMediaServerService;
13 import com.genersoft.iot.vmp.utils.SpringBeanFactory; 15 import com.genersoft.iot.vmp.utils.SpringBeanFactory;
@@ -38,7 +40,7 @@ import java.util.Set; @@ -38,7 +40,7 @@ import java.util.Set;
38 public class ServerController { 40 public class ServerController {
39 41
40 @Autowired 42 @Autowired
41 - private ConfigurableApplicationContext context; 43 + private ZLMHttpHookSubscribe zlmHttpHookSubscribe;
42 44
43 @Autowired 45 @Autowired
44 private IMediaServerService mediaServerService; 46 private IMediaServerService mediaServerService;
@@ -254,6 +256,18 @@ public class ServerController { @@ -254,6 +256,18 @@ public class ServerController {
254 return result; 256 return result;
255 } 257 }
256 258
  259 + @ApiOperation("获取当前所有hook")
  260 + @GetMapping(value = "/hooks")
  261 + @ResponseBody
  262 + public WVPResult<List<IHookSubscribe>> getHooks(){
  263 + WVPResult<List<IHookSubscribe>> result = new WVPResult<>();
  264 + result.setCode(0);
  265 + result.setMsg("success");
  266 + List<IHookSubscribe> all = zlmHttpHookSubscribe.getAll();
  267 + result.setData(all);
  268 + return result;
  269 + }
  270 +
257 // @ApiOperation("当前进行中的动态任务") 271 // @ApiOperation("当前进行中的动态任务")
258 // @GetMapping(value = "/dynamicTask") 272 // @GetMapping(value = "/dynamicTask")
259 // @ResponseBody 273 // @ResponseBody
src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java
@@ -4,6 +4,7 @@ import com.alibaba.excel.EasyExcel; @@ -4,6 +4,7 @@ import com.alibaba.excel.EasyExcel;
4 import com.alibaba.excel.ExcelReader; 4 import com.alibaba.excel.ExcelReader;
5 import com.alibaba.excel.read.metadata.ReadSheet; 5 import com.alibaba.excel.read.metadata.ReadSheet;
6 import com.genersoft.iot.vmp.common.StreamInfo; 6 import com.genersoft.iot.vmp.common.StreamInfo;
  7 +import com.genersoft.iot.vmp.conf.UserSetting;
7 import com.genersoft.iot.vmp.conf.security.SecurityUtils; 8 import com.genersoft.iot.vmp.conf.security.SecurityUtils;
8 import com.genersoft.iot.vmp.conf.security.dto.LoginUser; 9 import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
9 import com.genersoft.iot.vmp.gb28181.bean.GbStream; 10 import com.genersoft.iot.vmp.gb28181.bean.GbStream;
@@ -63,6 +64,9 @@ public class StreamPushController { @@ -63,6 +64,9 @@ public class StreamPushController {
63 @Autowired 64 @Autowired
64 private IMediaService mediaService; 65 private IMediaService mediaService;
65 66
  67 + @Autowired
  68 + private UserSetting userSetting;
  69 +
66 @ApiOperation("推流列表查询") 70 @ApiOperation("推流列表查询")
67 @ApiImplicitParams({ 71 @ApiImplicitParams({
68 @ApiImplicitParam(name="page", value = "当前页", required = true, dataTypeClass = Integer.class), 72 @ApiImplicitParam(name="page", value = "当前页", required = true, dataTypeClass = Integer.class),
@@ -260,29 +264,63 @@ public class StreamPushController { @@ -260,29 +264,63 @@ public class StreamPushController {
260 }) 264 })
261 @GetMapping(value = "/getPlayUrl") 265 @GetMapping(value = "/getPlayUrl")
262 @ResponseBody 266 @ResponseBody
263 - public WVPResult<StreamInfo> getPlayUrl(HttpServletRequest request, @RequestParam String app,  
264 - @RequestParam String stream,  
265 - @RequestParam(required = false) String mediaServerId){ 267 + public WVPResult<StreamInfo> getPlayUrl(@RequestParam String app,@RequestParam String stream,
  268 + @RequestParam(required = false) String mediaServerId){
266 boolean authority = false; 269 boolean authority = false;
267 // 是否登陆用户, 登陆用户返回完整信息 270 // 是否登陆用户, 登陆用户返回完整信息
268 LoginUser userInfo = SecurityUtils.getUserInfo(); 271 LoginUser userInfo = SecurityUtils.getUserInfo();
269 if (userInfo!= null) { 272 if (userInfo!= null) {
270 authority = true; 273 authority = true;
271 } 274 }
272 -  
273 - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority);  
274 -  
275 WVPResult<StreamInfo> result = new WVPResult<>(); 275 WVPResult<StreamInfo> result = new WVPResult<>();
  276 + StreamPushItem push = streamPushService.getPush(app, stream);
  277 + if (push != null && !push.isSelf()) {
  278 + result.setCode(-1);
  279 + result.setMsg("来自其他平台的推流信息");
  280 + return result;
  281 + }
  282 + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority);
276 if (streamInfo != null){ 283 if (streamInfo != null){
277 result.setCode(0); 284 result.setCode(0);
278 - result.setMsg("scccess"); 285 + result.setMsg("success");
279 result.setData(streamInfo); 286 result.setData(streamInfo);
280 }else { 287 }else {
281 result.setCode(-1); 288 result.setCode(-1);
282 - result.setMsg("fail"); 289 + result.setMsg("获取播放地址失败");
283 } 290 }
  291 +
284 return result; 292 return result;
285 } 293 }
286 294
  295 + /**
  296 + * 获取推流播放地址
  297 + * @param stream 推流信息
  298 + * @return
  299 + */
  300 + @ApiOperation("获取推流播放地址")
  301 + @ApiImplicitParams({
  302 + @ApiImplicitParam(name = "stream", value = "推流信息", dataTypeClass = StreamPushItem.class),
  303 + })
  304 + @PostMapping(value = "/add")
  305 + @ResponseBody
  306 + public WVPResult<StreamInfo> add(@RequestBody StreamPushItem stream){
  307 + if (StringUtils.isEmpty(stream.getGbId())) {
  308 +
  309 + return new WVPResult<>(400, "国标ID不可为空", null);
  310 + }
  311 + if (StringUtils.isEmpty(stream.getApp()) && StringUtils.isEmpty(stream.getStream())) {
  312 + return new WVPResult<>(400, "app或stream不可为空", null);
  313 + }
  314 + stream.setStatus(false);
  315 + stream.setPushIng(false);
  316 + stream.setAliveSecond(0L);
  317 + stream.setTotalReaderCount("0");
  318 + boolean result = streamPushService.add(stream);
287 319
  320 + if (result) {
  321 + return new WVPResult<>(0, "success", null);
  322 + }else {
  323 + return new WVPResult<>(-1, "fail", null);
  324 + }
  325 + }
288 } 326 }
src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java
@@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.storager.dao.dto.Role; @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.storager.dao.dto.Role;
8 import com.genersoft.iot.vmp.storager.dao.dto.User; 8 import com.genersoft.iot.vmp.storager.dao.dto.User;
9 import com.genersoft.iot.vmp.utils.DateUtil; 9 import com.genersoft.iot.vmp.utils.DateUtil;
10 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 10 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
  11 +import com.github.pagehelper.PageInfo;
11 import io.swagger.annotations.Api; 12 import io.swagger.annotations.Api;
12 import io.swagger.annotations.ApiImplicitParam; 13 import io.swagger.annotations.ApiImplicitParam;
13 import io.swagger.annotations.ApiImplicitParams; 14 import io.swagger.annotations.ApiImplicitParams;
@@ -123,7 +124,8 @@ public class UserController { @@ -123,7 +124,8 @@ public class UserController {
123 User user = new User(); 124 User user = new User();
124 user.setUsername(username); 125 user.setUsername(username);
125 user.setPassword(DigestUtils.md5DigestAsHex(password.getBytes())); 126 user.setPassword(DigestUtils.md5DigestAsHex(password.getBytes()));
126 - 127 + //新增用户的pushKey的生成规则为md5(时间戳+用户名)
  128 + user.setPushKey(DigestUtils.md5DigestAsHex((System.currentTimeMillis()+password).getBytes()));
127 Role role = roleService.getRoleById(roleId); 129 Role role = roleService.getRoleById(roleId);
128 130
129 if (role == null) { 131 if (role == null) {
@@ -137,6 +139,7 @@ public class UserController { @@ -137,6 +139,7 @@ public class UserController {
137 user.setUpdateTime(DateUtil.getNow()); 139 user.setUpdateTime(DateUtil.getNow());
138 int addResult = userService.addUser(user); 140 int addResult = userService.addUser(user);
139 141
  142 +
140 result.setCode(addResult > 0 ? 0 : -1); 143 result.setCode(addResult > 0 ? 0 : -1);
141 result.setMsg(addResult > 0 ? "success" : "fail"); 144 result.setMsg(addResult > 0 ? "success" : "fail");
142 result.setData(addResult); 145 result.setData(addResult);
@@ -177,4 +180,68 @@ public class UserController { @@ -177,4 +180,68 @@ public class UserController {
177 result.setData(allUsers); 180 result.setData(allUsers);
178 return new ResponseEntity<>(result, HttpStatus.OK); 181 return new ResponseEntity<>(result, HttpStatus.OK);
179 } 182 }
  183 +
  184 + /**
  185 + * 分页查询用户
  186 + *
  187 + * @param page 当前页
  188 + * @param count 每页查询数量
  189 + * @return 分页用户列表
  190 + */
  191 + @ApiOperation("分页查询用户")
  192 + @ApiImplicitParams({
  193 + @ApiImplicitParam(name = "page", value = "当前页", required = true, dataTypeClass = Integer.class),
  194 + @ApiImplicitParam(name = "count", value = "每页查询数量", required = true, dataTypeClass = Integer.class),
  195 + })
  196 + @GetMapping("/users")
  197 + public PageInfo<User> users(int page, int count) {
  198 + return userService.getUsers(page, count);
  199 + }
  200 +
  201 + @ApiOperation("修改pushkey")
  202 + @ApiImplicitParams({
  203 + @ApiImplicitParam(name = "userId", required = true, value = "用户Id", dataTypeClass = Integer.class),
  204 + @ApiImplicitParam(name = "pushKey", required = true, value = "新的pushKey", dataTypeClass = String.class),
  205 + })
  206 + @RequestMapping("/changePushKey")
  207 + public ResponseEntity<WVPResult<String>> changePushKey(@RequestParam Integer userId,@RequestParam String pushKey) {
  208 + // 获取当前登录用户id
  209 + int currenRoleId = SecurityUtils.getUserInfo().getRole().getId();
  210 + WVPResult<String> result = new WVPResult<>();
  211 + if (currenRoleId != 1) {
  212 + // 只用角色id为0才可以删除和添加用户
  213 + result.setCode(-1);
  214 + result.setMsg("用户无权限");
  215 + return new ResponseEntity<>(result, HttpStatus.FORBIDDEN);
  216 + }
  217 + int resetPushKeyResult = userService.changePushKey(userId,pushKey);
  218 +
  219 + result.setCode(resetPushKeyResult > 0 ? 0 : -1);
  220 + result.setMsg(resetPushKeyResult > 0 ? "success" : "fail");
  221 + return new ResponseEntity<>(result, HttpStatus.OK);
  222 + }
  223 +
  224 + @ApiOperation("管理员修改普通用户密码")
  225 + @ApiImplicitParams({
  226 + @ApiImplicitParam(name = "adminId", required = true, value = "管理员id", dataTypeClass = String.class),
  227 + @ApiImplicitParam(name = "userId", required = true, value = "用户id", dataTypeClass = String.class),
  228 + @ApiImplicitParam(name = "password", required = true, value = "新密码(未md5加密的密码)", dataTypeClass = String.class),
  229 + })
  230 + @PostMapping("/changePasswordForAdmin")
  231 + public String changePasswordForAdmin(@RequestParam int userId, @RequestParam String password) {
  232 + // 获取当前登录用户id
  233 + LoginUser userInfo = SecurityUtils.getUserInfo();
  234 + if (userInfo == null) {
  235 + return "fail";
  236 + }
  237 + Role role = userInfo.getRole();
  238 + if (role != null && role.getId() == 1) {
  239 + boolean result = userService.changePassword(userId, DigestUtils.md5DigestAsHex(password.getBytes()));
  240 + if (result) {
  241 + return "success";
  242 + }
  243 + }
  244 +
  245 + return "fail";
  246 + }
180 } 247 }
src/main/resources/all-application.yml
@@ -149,7 +149,7 @@ media: @@ -149,7 +149,7 @@ media:
149 enable: true 149 enable: true
150 # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功 150 # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
151 port-range: 30000,30500 # 端口范围 151 port-range: 30000,30500 # 端口范围
152 - # [可选] 国标级联在此范围内选择端口发送媒体流, 152 + # [可选] 国标级联在此范围内选择端口发送媒体流
153 send-port-range: 30000,30500 # 端口范围 153 send-port-range: 30000,30500 # 端口范围
154 # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用 154 # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
155 record-assist-port: 0 155 record-assist-port: 0
web_src/src/components/Login.vue
@@ -86,7 +86,7 @@ export default { @@ -86,7 +86,7 @@ export default {
86 }).then(function (res) { 86 }).then(function (res) {
87 console.log(JSON.stringify(res)); 87 console.log(JSON.stringify(res));
88 if (res.data.code == 0 && res.data.msg == "success") { 88 if (res.data.code == 0 && res.data.msg == "success") {
89 - that.$cookies.set("session", {"username": that.username}) ; 89 + that.$cookies.set("session", {"username": that.username,"roleId":res.data.data.role.id}) ;
90 //登录成功后 90 //登录成功后
91 that.cancelEnterkeyDefaultAction(); 91 that.cancelEnterkeyDefaultAction();
92 that.$router.push('/'); 92 that.$router.push('/');
web_src/src/components/ParentPlatformList.vue
@@ -143,7 +143,7 @@ export default { @@ -143,7 +143,7 @@ export default {
143 }); 143 });
144 }, 144 },
145 chooseChannel: function(platform) { 145 chooseChannel: function(platform) {
146 - this.$refs.chooseChannelDialog.openDialog(platform.serverGBId, platform.name, platform.catalogId, this.initData) 146 + this.$refs.chooseChannelDialog.openDialog(platform.serverGBId, platform.name, platform.catalogId, platform.treeType, this.initData)
147 }, 147 },
148 initData: function() { 148 initData: function() {
149 this.getPlatformList(); 149 this.getPlatformList();
web_src/src/components/PushVideoList.vue
@@ -34,6 +34,8 @@ @@ -34,6 +34,8 @@
34 <el-button icon="el-icon-delete" size="mini" style="margin-right: 1rem;" 34 <el-button icon="el-icon-delete" size="mini" style="margin-right: 1rem;"
35 :disabled="multipleSelection.length === 0" type="danger" @click="batchDel">批量移除 35 :disabled="multipleSelection.length === 0" type="danger" @click="batchDel">批量移除
36 </el-button> 36 </el-button>
  37 + <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStream">添加通道
  38 + </el-button>
37 <el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button> 39 <el-button icon="el-icon-refresh-right" circle size="mini" @click="refresh()"></el-button>
38 </div> 40 </div>
39 </div> 41 </div>
@@ -56,20 +58,25 @@ @@ -56,20 +58,25 @@
56 <el-table-column label="开始时间" min-width="200"> 58 <el-table-column label="开始时间" min-width="200">
57 <template slot-scope="scope"> 59 <template slot-scope="scope">
58 <el-button-group> 60 <el-button-group>
59 - {{ dateFormat(parseInt(scope.row.createStamp)) }} 61 + {{ scope.row.pushTime == null? "-":scope.row.pushTime }}
60 </el-button-group> 62 </el-button-group>
61 </template> 63 </template>
62 </el-table-column> 64 </el-table-column>
63 <el-table-column label="正在推流" min-width="100"> 65 <el-table-column label="正在推流" min-width="100">
64 <template slot-scope="scope"> 66 <template slot-scope="scope">
65 - {{ (scope.row.status == false && scope.row.gbId == null) || scope.row.status ? '是' : '否' }} 67 + {{scope.row.pushIng ? '是' : '否' }}
  68 + </template>
  69 + </el-table-column>
  70 + <el-table-column label="本平台推流" min-width="100">
  71 + <template slot-scope="scope">
  72 + {{scope.row.pushIng && !!scope.row.self ? '是' : '否' }}
66 </template> 73 </template>
67 </el-table-column> 74 </el-table-column>
68 75
69 <el-table-column label="操作" min-width="360" fixed="right"> 76 <el-table-column label="操作" min-width="360" fixed="right">
70 <template slot-scope="scope"> 77 <template slot-scope="scope">
71 <el-button size="medium" icon="el-icon-video-play" 78 <el-button size="medium" icon="el-icon-video-play"
72 - v-if="(scope.row.status == false && scope.row.gbId == null) || scope.row.status" 79 + v-if="scope.row.pushIng === true"
73 @click="playPush(scope.row)" type="text">播放 80 @click="playPush(scope.row)" type="text">播放
74 </el-button> 81 </el-button>
75 <el-divider direction="vertical"></el-divider> 82 <el-divider direction="vertical"></el-divider>
@@ -103,7 +110,7 @@ @@ -103,7 +110,7 @@
103 <script> 110 <script>
104 import streamProxyEdit from './dialog/StreamProxyEdit.vue' 111 import streamProxyEdit from './dialog/StreamProxyEdit.vue'
105 import devicePlayer from './dialog/devicePlayer.vue' 112 import devicePlayer from './dialog/devicePlayer.vue'
106 -import addStreamTOGB from './dialog/addStreamTOGB.vue' 113 +import addStreamTOGB from './dialog/pushStreamEdit.vue'
107 import uiHeader from '../layout/UiHeader.vue' 114 import uiHeader from '../layout/UiHeader.vue'
108 import importChannel from './dialog/importChannel.vue' 115 import importChannel from './dialog/importChannel.vue'
109 import MediaServer from './service/MediaServer' 116 import MediaServer from './service/MediaServer'
@@ -195,10 +202,15 @@ export default { @@ -195,10 +202,15 @@ export default {
195 } 202 }
196 }).then(function (res) { 203 }).then(function (res) {
197 that.getListLoading = false; 204 that.getListLoading = false;
198 - that.$refs.devicePlayer.openDialog("streamPlay", null, null, {  
199 - streamInfo: res.data.data,  
200 - hasAudio: true  
201 - }); 205 + if (res.data.code === 0 ) {
  206 + that.$refs.devicePlayer.openDialog("streamPlay", null, null, {
  207 + streamInfo: res.data.data,
  208 + hasAudio: true
  209 + });
  210 + }else {
  211 + that.$message.error(res.data.msg);
  212 + }
  213 +
202 }).catch(function (error) { 214 }).catch(function (error) {
203 console.error(error); 215 console.error(error);
204 that.getListLoading = false; 216 that.getListLoading = false;
@@ -242,24 +254,14 @@ export default { @@ -242,24 +254,14 @@ export default {
242 console.error(error); 254 console.error(error);
243 }); 255 });
244 }, 256 },
245 - dateFormat: function (/** timestamp=0 **/) {  
246 - let ts = arguments[0] || 0;  
247 - let t, y, m, d, h, i, s;  
248 - t = ts ? new Date(ts) : new Date();  
249 - y = t.getFullYear();  
250 - m = t.getMonth() + 1;  
251 - d = t.getDate();  
252 - h = t.getHours();  
253 - i = t.getMinutes();  
254 - s = t.getSeconds();  
255 - // 可根据需要在这里定义时间格式  
256 - return y + '-' + (m < 10 ? '0' + m : m) + '-' + (d < 10 ? '0' + d : d) + ' ' + (h < 10 ? '0' + h : h) + ':' + (i < 10 ? '0' + i : i) + ':' + (s < 10 ? '0' + s : s);  
257 - },  
258 importChannel: function () { 257 importChannel: function () {
259 this.$refs.importChannel.openDialog(() => { 258 this.$refs.importChannel.openDialog(() => {
260 259
261 }) 260 })
262 }, 261 },
  262 + addStream: function (){
  263 + this.$refs.addStreamTOGB.openDialog(null, this.initData);
  264 + },
263 batchDel: function () { 265 batchDel: function () {
264 this.$confirm(`确定删除选中的${this.multipleSelection.length}个通道?`, '提示', { 266 this.$confirm(`确定删除选中的${this.multipleSelection.length}个通道?`, '提示', {
265 confirmButtonText: '确定', 267 confirmButtonText: '确定',
web_src/src/components/UserManager.vue 0 → 100644
  1 +<template>
  2 +
  3 + <div id="app" style="width: 100%">
  4 + <div class="page-header">
  5 +
  6 + <div class="page-title">用户列表</div>
  7 + <div class="page-header-btn">
  8 + <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addUser">
  9 + 添加用户
  10 + </el-button>
  11 +
  12 + </div>
  13 + </div>
  14 + <!--用户列表-->
  15 + <el-table :data="userList" style="width: 100%;font-size: 12px;" :height="winHeight"
  16 + header-row-class-name="table-header">
  17 + <el-table-column prop="username" label="用户名" min-width="160"/>
  18 + <el-table-column prop="pushKey" label="pushkey" min-width="160"/>
  19 + <el-table-column prop="role.name" label="类型" min-width="160"/>
  20 + <el-table-column label="操作" min-width="450" fixed="right">
  21 + <template slot-scope="scope">
  22 + <el-button size="medium" icon="el-icon-edit" type="text" @click="edit(scope.row)">修改密码</el-button>
  23 + <el-divider direction="vertical"></el-divider>
  24 + <el-button size="medium" icon="el-icon-edit" type="text" @click="changePushKey(scope.row)">修改pushkey</el-button>
  25 + <el-divider direction="vertical"></el-divider>
  26 + <el-button size="medium" icon="el-icon-delete" type="text" @click="deleteUser(scope.row)"
  27 + style="color: #f56c6c">删除
  28 + </el-button>
  29 + </template>
  30 + </el-table-column>
  31 + </el-table>
  32 + <changePasswordForAdmin ref="changePasswordForAdmin"></changePasswordForAdmin>
  33 + <changePushKey ref="changePushKey"></changePushKey>
  34 + <addUser ref="addUser"></addUser>
  35 + <el-pagination
  36 + style="float: right"
  37 + @size-change="handleSizeChange"
  38 + @current-change="currentChange"
  39 + :current-page="currentPage"
  40 + :page-size="count"
  41 + :page-sizes="[15, 25, 35, 50]"
  42 + layout="total, sizes, prev, pager, next"
  43 + :total="total">
  44 + </el-pagination>
  45 + </div>
  46 +</template>
  47 +
  48 +<script>
  49 +import uiHeader from '../layout/UiHeader.vue'
  50 +import changePasswordForAdmin from './dialog/changePasswordForAdmin.vue'
  51 +import changePushKey from './dialog/changePushKey.vue'
  52 +import addUser from '../components/dialog/addUser.vue'
  53 +
  54 +export default {
  55 + name: 'userManager',
  56 + components: {
  57 + uiHeader,
  58 + changePasswordForAdmin,
  59 + changePushKey,
  60 + addUser
  61 + },
  62 + data() {
  63 + return {
  64 + userList: [], //设备列表
  65 + currentUser: {}, //当前操作设备对象
  66 +
  67 + videoComponentList: [],
  68 + updateLooper: 0, //数据刷新轮训标志
  69 + currentUserLenth: 0,
  70 + winHeight: window.innerHeight - 200,
  71 + currentPage: 1,
  72 + count: 15,
  73 + total: 0,
  74 + getUserListLoading: false
  75 + };
  76 + },
  77 + mounted() {
  78 + this.initData();
  79 + this.updateLooper = setInterval(this.initData, 10000);
  80 + },
  81 + destroyed() {
  82 + this.$destroy('videojs');
  83 + clearTimeout(this.updateLooper);
  84 + },
  85 + methods: {
  86 + initData: function () {
  87 + this.getUserList();
  88 + },
  89 + currentChange: function (val) {
  90 + this.currentPage = val;
  91 + this.getUserList();
  92 + },
  93 + handleSizeChange: function (val) {
  94 + this.count = val;
  95 + this.getUserList();
  96 + },
  97 + getUserList: function () {
  98 + let that = this;
  99 + this.getUserListLoading = true;
  100 + this.$axios({
  101 + method: 'get',
  102 + url: `/api/user/users`,
  103 + params: {
  104 + page: that.currentPage,
  105 + count: that.count
  106 + }
  107 + }).then(function (res) {
  108 + that.total = res.data.total;
  109 + that.userList = res.data.list;
  110 + that.getUserListLoading = false;
  111 + }).catch(function (error) {
  112 + that.getUserListLoading = false;
  113 + });
  114 +
  115 + },
  116 + edit: function (row) {
  117 + this.$refs.changePasswordForAdmin.openDialog(row, () => {
  118 + this.$refs.changePasswordForAdmin.close();
  119 + this.$message({
  120 + showClose: true,
  121 + message: "密码修改成功",
  122 + type: "success",
  123 + });
  124 + setTimeout(this.getUserList, 200)
  125 +
  126 + })
  127 + },
  128 + deleteUser: function (row) {
  129 + let msg = "确定删除此用户?"
  130 + if (row.online !== 0) {
  131 + msg = "<strong>确定删除此用户?</strong>"
  132 + }
  133 + this.$confirm(msg, '提示', {
  134 + dangerouslyUseHTMLString: true,
  135 + confirmButtonText: '确定',
  136 + cancelButtonText: '取消',
  137 + center: true,
  138 + type: 'warning'
  139 + }).then(() => {
  140 + this.$axios({
  141 + method: 'delete',
  142 + url: `/api/user/delete?id=${row.id}`
  143 + }).then((res) => {
  144 + this.getUserList();
  145 + }).catch((error) => {
  146 + console.error(error);
  147 + });
  148 + }).catch(() => {
  149 +
  150 + });
  151 +
  152 +
  153 + },
  154 +
  155 + changePushKey: function (row) {
  156 + this.$refs.changePushKey.openDialog(row, () => {
  157 + this.$refs.changePushKey.close();
  158 + this.$message({
  159 + showClose: true,
  160 + message: "pushKey修改成功",
  161 + type: "success",
  162 + });
  163 + setTimeout(this.getUserList, 200)
  164 +
  165 + })
  166 + },
  167 + addUser: function () {
  168 + // this.$refs.addUser.openDialog()
  169 + this.$refs.addUser.openDialog( () => {
  170 + this.$refs.addUser.close();
  171 + this.$message({
  172 + showClose: true,
  173 + message: "用户添加成功",
  174 + type: "success",
  175 + });
  176 + setTimeout(this.getUserList, 200)
  177 +
  178 + })
  179 + }
  180 + }
  181 +}
  182 +</script>
  183 +<style>
  184 +.videoList {
  185 + display: flex;
  186 + flex-wrap: wrap;
  187 + align-content: flex-start;
  188 +}
  189 +
  190 +.video-item {
  191 + position: relative;
  192 + width: 15rem;
  193 + height: 10rem;
  194 + margin-right: 1rem;
  195 + background-color: #000000;
  196 +}
  197 +
  198 +.video-item-img {
  199 + position: absolute;
  200 + top: 0;
  201 + bottom: 0;
  202 + left: 0;
  203 + right: 0;
  204 + margin: auto;
  205 + width: 100%;
  206 + height: 100%;
  207 +}
  208 +
  209 +.video-item-img:after {
  210 + content: "";
  211 + display: inline-block;
  212 + position: absolute;
  213 + z-index: 2;
  214 + top: 0;
  215 + bottom: 0;
  216 + left: 0;
  217 + right: 0;
  218 + margin: auto;
  219 + width: 3rem;
  220 + height: 3rem;
  221 + background-image: url("../assets/loading.png");
  222 + background-size: cover;
  223 + background-color: #000000;
  224 +}
  225 +
  226 +.video-item-title {
  227 + position: absolute;
  228 + bottom: 0;
  229 + color: #000000;
  230 + background-color: #ffffff;
  231 + line-height: 1.5rem;
  232 + padding: 0.3rem;
  233 + width: 14.4rem;
  234 +}
  235 +
  236 +</style>
web_src/src/components/channelList.vue
@@ -32,7 +32,7 @@ @@ -32,7 +32,7 @@
32 <el-button v-if="!showTree" icon="iconfont icon-tree" circle size="mini" @click="switchTree()"></el-button> 32 <el-button v-if="!showTree" icon="iconfont icon-tree" circle size="mini" @click="switchTree()"></el-button>
33 </div> 33 </div>
34 </div> 34 </div>
35 - <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer> 35 + <devicePlayer ref="devicePlayer" ></devicePlayer>
36 <el-container v-loading="isLoging" style="height: 82vh;"> 36 <el-container v-loading="isLoging" style="height: 82vh;">
37 <el-aside width="auto" style="height: 82vh; background-color: #ffffff; overflow: auto" v-if="showTree" > 37 <el-aside width="auto" style="height: 82vh; background-color: #ffffff; overflow: auto" v-if="showTree" >
38 <DeviceTree ref="deviceTree" :device="device" :onlyCatalog="true" :clickEvent="treeNodeClickEvent" ></DeviceTree> 38 <DeviceTree ref="deviceTree" :device="device" :onlyCatalog="true" :clickEvent="treeNodeClickEvent" ></DeviceTree>
@@ -124,7 +124,6 @@ @@ -124,7 +124,6 @@
124 import devicePlayer from './dialog/devicePlayer.vue' 124 import devicePlayer from './dialog/devicePlayer.vue'
125 import uiHeader from '../layout/UiHeader.vue' 125 import uiHeader from '../layout/UiHeader.vue'
126 import moment from "moment"; 126 import moment from "moment";
127 -import DviceService from "./service/DeviceService";  
128 import DeviceService from "./service/DeviceService"; 127 import DeviceService from "./service/DeviceService";
129 import DeviceTree from "./common/DeviceTree"; 128 import DeviceTree from "./common/DeviceTree";
130 129
@@ -318,7 +317,7 @@ export default { @@ -318,7 +317,7 @@ export default {
318 changeSubchannel(itemData) { 317 changeSubchannel(itemData) {
319 this.beforeUrl = this.$router.currentRoute.path; 318 this.beforeUrl = this.$router.currentRoute.path;
320 319
321 - var url = `/${this.$router.currentRoute.name}/${this.$router.currentRoute.params.deviceId}/${itemData.channelId}/${this.$router.currentRoute.params.count}/1` 320 + var url = `/${this.$router.currentRoute.name}/${this.$router.currentRoute.params.deviceId}/${itemData.channelId}`
322 this.$router.push(url).then(() => { 321 this.$router.push(url).then(() => {
323 this.searchSrt = ""; 322 this.searchSrt = "";
324 this.channelType = ""; 323 this.channelType = "";
web_src/src/components/common/jessibuca.vue
@@ -5,8 +5,8 @@ @@ -5,8 +5,8 @@
5 <i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick"></i> 5 <i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick"></i>
6 <i v-if="playing" class="iconfont icon-pause jessibuca-btn" @click="pause"></i> 6 <i v-if="playing" class="iconfont icon-pause jessibuca-btn" @click="pause"></i>
7 <i class="iconfont icon-stop jessibuca-btn" @click="destroy"></i> 7 <i class="iconfont icon-stop jessibuca-btn" @click="destroy"></i>
8 - <i v-if="isNotMute" class="iconfont icon-audio-high jessibuca-btn" @click="jessibuca.mute()"></i>  
9 - <i v-if="!isNotMute" class="iconfont icon-audio-mute jessibuca-btn" @click="jessibuca.cancelMute()"></i> 8 + <i v-if="isNotMute" class="iconfont icon-audio-high jessibuca-btn" @click="mute()"></i>
  9 + <i v-if="!isNotMute" class="iconfont icon-audio-mute jessibuca-btn" @click="cancelMute()"></i>
10 </div> 10 </div>
11 <div class="buttons-box-right"> 11 <div class="buttons-box-right">
12 <span class="jessibuca-btn">{{ kBps }} kb/s</span> 12 <span class="jessibuca-btn">{{ kBps }} kb/s</span>
@@ -243,6 +243,16 @@ export default { @@ -243,6 +243,16 @@ export default {
243 this.err = ""; 243 this.err = "";
244 this.performance = ""; 244 this.performance = "";
245 }, 245 },
  246 + mute: function () {
  247 + if (jessibucaPlayer[this._uid]) {
  248 + jessibucaPlayer[this._uid].mute();
  249 + }
  250 + },
  251 + cancelMute: function () {
  252 + if (jessibucaPlayer[this._uid]) {
  253 + jessibucaPlayer[this._uid].cancelMute();
  254 + }
  255 + },
246 destroy: function () { 256 destroy: function () {
247 if (jessibucaPlayer[this._uid]) { 257 if (jessibucaPlayer[this._uid]) {
248 jessibucaPlayer[this._uid].destroy(); 258 jessibucaPlayer[this._uid].destroy();
web_src/src/components/control.vue
@@ -324,7 +324,7 @@ export default { @@ -324,7 +324,7 @@ export default {
324 */ 324 */
325 getThreadsLoad: function () { 325 getThreadsLoad: function () {
326 let that = this; 326 let that = this;
327 - if (that.mediaServerChoose != null) { 327 + if (!!that.mediaServerChoose) {
328 this.$axios({ 328 this.$axios({
329 method: 'get', 329 method: 'get',
330 url: '/zlm/' + that.mediaServerChoose + '/index/api/getThreadsLoad' 330 url: '/zlm/' + that.mediaServerChoose + '/index/api/getThreadsLoad'
@@ -375,7 +375,7 @@ export default { @@ -375,7 +375,7 @@ export default {
375 }, 375 },
376 getLoadCount: function () { 376 getLoadCount: function () {
377 let that = this; 377 let that = this;
378 - if (that.mediaServerChoose != null) { 378 + if (!!that.mediaServerChoose) {
379 that.mediaServer.getMediaServer(that.mediaServerChoose, (data) => { 379 that.mediaServer.getMediaServer(that.mediaServerChoose, (data) => {
380 if (data.code == 0) { 380 if (data.code == 0) {
381 that.loadCount = data.data.count 381 that.loadCount = data.data.count
@@ -473,42 +473,46 @@ export default { @@ -473,42 +473,46 @@ export default {
473 }, 473 },
474 474
475 getAllSession: function () { 475 getAllSession: function () {
476 - let that = this;  
477 - that.allSessionData = [];  
478 - this.$axios({  
479 - method: 'get',  
480 - url: '/zlm/' + that.mediaServerChoose + '/index/api/getAllSession'  
481 - }).then(function (res) {  
482 - res.data.data.forEach(item => {  
483 - let data = {  
484 - peer_ip: item.peer_ip,  
485 - local_ip: item.local_ip,  
486 - typeid: item.typeid,  
487 - id: item.id  
488 - };  
489 - that.allSessionData.push(data); 476 + this.allSessionData = [];
  477 + if (!!this.mediaServerChoose) {
  478 + this.$axios({
  479 + method: 'get',
  480 + url: '/zlm/' + this.mediaServerChoose + '/index/api/getAllSession'
  481 + }).then((res)=> {
  482 + res.data.data.forEach(item => {
  483 + let data = {
  484 + peer_ip: item.peer_ip,
  485 + local_ip: item.local_ip,
  486 + typeid: item.typeid,
  487 + id: item.id
  488 + };
  489 + this.allSessionData.push(data);
  490 + });
490 }); 491 });
491 - }); 492 + }
  493 +
492 }, 494 },
493 getServerConfig: function () { 495 getServerConfig: function () {
494 - let that = this;  
495 - this.$axios({  
496 - method: 'get',  
497 - url: '/zlm/' + that.mediaServerChoose + '/index/api/getServerConfig'  
498 - }).then(function (res) {  
499 - let info = res.data.data[0];  
500 - let serverInfo = {}  
501 - for (let i = 0; i < Object.keys(info).length; i++) {  
502 - let key = Object.keys(info)[i];  
503 - let group = key.substring(0, key.indexOf("."))  
504 - let itemKey = key.substring(key.indexOf(".") + 1)  
505 - if (!serverInfo[group]) serverInfo[group] = {}  
506 - serverInfo[group][itemKey] = info[key]  
507 - } 496 + if (!!this.mediaServerChoose) {
  497 + this.$axios({
  498 + method: 'get',
  499 + url: '/zlm/' + this.mediaServerChoose + '/index/api/getServerConfig'
  500 + }).then((res)=> {
  501 + let info = res.data.data[0];
  502 + let serverInfo = {}
  503 + for (let i = 0; i < Object.keys(info).length; i++) {
  504 + let key = Object.keys(info)[i];
  505 + let group = key.substring(0, key.indexOf("."))
  506 + let itemKey = key.substring(key.indexOf(".") + 1)
  507 + if (!serverInfo[group]) serverInfo[group] = {}
  508 + serverInfo[group][itemKey] = info[key]
  509 + }
  510 +
  511 + this.serverConfig = serverInfo;
  512 + this.visible = true;
  513 + });
  514 + }
508 515
509 - that.serverConfig = serverInfo;  
510 - that.visible = true;  
511 - });  
512 }, 516 },
513 getWVPServerConfig: function () { 517 getWVPServerConfig: function () {
514 let that = this; 518 let that = this;
@@ -531,6 +535,14 @@ export default { @@ -531,6 +535,14 @@ export default {
531 }, 535 },
532 reStartServer: function () { 536 reStartServer: function () {
533 let that = this; 537 let that = this;
  538 + if (!!!this.mediaServerChoose) {
  539 + this.$message({
  540 + type: 'info',
  541 + message: '未选择节点'
  542 + });
  543 + return;
  544 + }
  545 +
534 this.$confirm('此操作将重启媒体服务器, 是否继续?', '提示', { 546 this.$confirm('此操作将重启媒体服务器, 是否继续?', '提示', {
535 confirmButtonText: '确定', 547 confirmButtonText: '确定',
536 cancelButtonText: '取消', 548 cancelButtonText: '取消',
@@ -571,17 +583,19 @@ export default { @@ -571,17 +583,19 @@ export default {
571 console.log(JSON.stringify(tabledata[index])); 583 console.log(JSON.stringify(tabledata[index]));
572 }, 584 },
573 deleteSession: function (id) { 585 deleteSession: function (id) {
574 - let that = this;  
575 - this.$axios({  
576 - method: 'get',  
577 - url: '/zlm/' + that.mediaServerChoose + '/index/api/kick_session?id=' + id  
578 - }).then(function (res) {  
579 - that.getAllSession();  
580 - that.$message({  
581 - type: 'success',  
582 - message: '删除成功!' 586 + if (!!this.mediaServerChoose) {
  587 + this.$axios({
  588 + method: 'get',
  589 + url: '/zlm/' + this.mediaServerChoose + '/index/api/kick_session?id=' + id
  590 + }).then((res)=>{
  591 + this.getAllSession();
  592 + this.$message({
  593 + type: 'success',
  594 + message: '删除成功!'
  595 + });
583 }); 596 });
584 - }); 597 + }
  598 +
585 }, 599 },
586 getNameFromKey: function (key) { 600 getNameFromKey: function (key) {
587 let nameData = { 601 let nameData = {
web_src/src/components/dialog/SyncChannelProgress.vue
@@ -63,34 +63,39 @@ export default { @@ -63,34 +63,39 @@ export default {
63 } 63 }
64 64
65 if (res.data.data != null) { 65 if (res.data.data != null) {
66 - if (res.data.data.total == 0) {  
67 - if (res.data.data.errorMsg !== null ){  
68 - this.msg = res.data.data.errorMsg;  
69 - this.syncStatus = "exception"  
70 - }else {  
71 - this.msg = `等待同步中`;  
72 - this.timmer = setTimeout(this.getProgress, 300)  
73 - }  
74 - }else {  
75 - if (res.data.data.total == res.data.data.current) {  
76 - this.syncStatus = "success"  
77 - this.percentage = 100;  
78 - this.msg = '同步成功';  
79 - }else { 66 + if (res.data.syncIng) {
  67 + if (res.data.data.total == 0) {
80 if (res.data.data.errorMsg !== null ){ 68 if (res.data.data.errorMsg !== null ){
81 this.msg = res.data.data.errorMsg; 69 this.msg = res.data.data.errorMsg;
82 this.syncStatus = "exception" 70 this.syncStatus = "exception"
83 }else { 71 }else {
84 - this.total = res.data.data.total;  
85 - this.current = res.data.data.current;  
86 - this.percentage = Math.floor(Number(res.data.data.current)/Number(res.data.data.total)* 10000)/100;  
87 - this.msg = `同步中...[${res.data.data.current}/${res.data.data.total}]`; 72 + this.msg = `等待同步中`;
88 this.timmer = setTimeout(this.getProgress, 300) 73 this.timmer = setTimeout(this.getProgress, 300)
89 } 74 }
  75 + }else {
  76 + if (res.data.data.total == res.data.data.current) {
  77 + this.syncStatus = "success"
  78 + this.percentage = 100;
  79 + this.msg = '同步成功';
  80 + }else {
  81 + if (res.data.data.errorMsg !== null ){
  82 + this.msg = res.data.data.errorMsg;
  83 + this.syncStatus = "exception"
  84 + }else {
  85 + this.total = res.data.data.total;
  86 + this.current = res.data.data.current;
  87 + this.percentage = Math.floor(Number(res.data.data.current)/Number(res.data.data.total)* 10000)/100;
  88 + this.msg = `同步中...[${res.data.data.current}/${res.data.data.total}]`;
  89 + this.timmer = setTimeout(this.getProgress, 300)
  90 + }
  91 + }
90 } 92 }
  93 + }else {
  94 + this.syncStatus = "success"
  95 + this.percentage = 100;
  96 + this.msg = '同步成功';
91 } 97 }
92 } 98 }
93 -  
94 }else { 99 }else {
95 if (this.syncFlag) { 100 if (this.syncFlag) {
96 this.syncStatus = "success" 101 this.syncStatus = "success"
web_src/src/components/dialog/addUser.vue 0 → 100644
  1 +<template>
  2 + <div id="addUser" v-loading="isLoging">
  3 + <el-dialog
  4 + title="添加用户"
  5 + width="40%"
  6 + top="2rem"
  7 + :close-on-click-modal="false"
  8 + :visible.sync="showDialog"
  9 + :destroy-on-close="true"
  10 + @close="close()"
  11 + >
  12 + <div id="shared" style="margin-right: 20px;">
  13 + <el-form ref="passwordForm" :rules="rules" status-icon label-width="80px">
  14 + <el-form-item label="用户名" prop="username">
  15 + <el-input v-model="username" autocomplete="off"></el-input>
  16 + </el-form-item>
  17 + <el-form-item label="用户类型" prop="roleId" >
  18 + <el-select v-model="roleId" placeholder="请选择" style="width: 100%">
  19 + <el-option
  20 + v-for="item in options"
  21 + :key="item.id"
  22 + :label="item.name"
  23 + :value="item.id">
  24 + </el-option>
  25 + </el-select>
  26 + </el-form-item>
  27 + <el-form-item label="密码" prop="password">
  28 + <el-input v-model="password" autocomplete="off"></el-input>
  29 + </el-form-item>
  30 + <el-form-item label="确认密码" prop="confirmPassword">
  31 + <el-input v-model="confirmPassword" autocomplete="off"></el-input>
  32 + </el-form-item>
  33 +
  34 + <el-form-item>
  35 + <div style="float: right;">
  36 + <el-button type="primary" @click="onSubmit">保存</el-button>
  37 + <el-button @click="close">取消</el-button>
  38 + </div>
  39 + </el-form-item>
  40 + </el-form>
  41 + </div>
  42 + </el-dialog>
  43 + </div>
  44 +</template>
  45 +
  46 +<script>
  47 +
  48 +export default {
  49 + name: "addUser",
  50 + props: {},
  51 + computed: {},
  52 + created() {
  53 + this.getAllRole();
  54 + },
  55 + data() {
  56 + let validatePass1 = (rule, value, callback) => {
  57 + if (value === '') {
  58 + callback(new Error('请输入新密码'));
  59 + } else {
  60 + if (this.confirmPassword !== '') {
  61 + this.$refs.passwordForm.validateField('confirmPassword');
  62 + }
  63 + callback();
  64 + }
  65 + };
  66 + let validatePass2 = (rule, value, callback) => {
  67 + if (this.confirmPassword === '') {
  68 + callback(new Error('请再次输入密码'));
  69 + } else if (this.confirmPassword !== this.password) {
  70 + callback(new Error('两次输入密码不一致!'));
  71 + } else {
  72 + callback();
  73 + }
  74 + };
  75 + return {
  76 + value:"",
  77 + options: [],
  78 + loading: false,
  79 + username: null,
  80 + password: null,
  81 + roleId: null,
  82 + confirmPassword: null,
  83 + listChangeCallback: null,
  84 + showDialog: false,
  85 + isLoging: false,
  86 + rules: {
  87 + newPassword: [{required: true, validator: validatePass1, trigger: "blur"}, {
  88 + pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/]).{8,20}$/,
  89 + message: "密码长度在8-20位之间,由字母+数字+特殊字符组成",
  90 + },],
  91 + confirmPassword: [{required: true, validator: validatePass2, trigger: "blur"}],
  92 + },
  93 + };
  94 + },
  95 + methods: {
  96 + openDialog: function (callback) {
  97 + this.listChangeCallback = callback;
  98 + this.showDialog = true;
  99 + },
  100 + onSubmit: function () {
  101 + this.$axios({
  102 + method: 'post',
  103 + url: "/api/user/add",
  104 + params: {
  105 + username: this.username,
  106 + password: this.password,
  107 + roleId: this.roleId
  108 + }
  109 + }).then((res) => {
  110 + if (res.data.code === 0) {
  111 + this.$message({
  112 + showClose: true,
  113 + message: '添加成功',
  114 + type: 'success',
  115 +
  116 + });
  117 + this.showDialog = false;
  118 + this.listChangeCallback()
  119 +
  120 + } else {
  121 + this.$message({
  122 + showClose: true,
  123 + message: res.data.msg,
  124 + type: 'error'
  125 + });
  126 + }
  127 + }).catch((error) => {
  128 + console.error(error)
  129 + });
  130 + },
  131 + close: function () {
  132 + this.showDialog = false;
  133 + this.password = null;
  134 + this.confirmPassword = null;
  135 + this.username = null;
  136 + this.roleId = null;
  137 + },
  138 + getAllRole:function () {
  139 +
  140 + this.$axios({
  141 + method: 'get',
  142 + url: "/api/role/all"
  143 + }).then((res) => {
  144 + this.loading = true;
  145 + console.info(res)
  146 + res.data
  147 + console.info(res.data.code)
  148 + if (res.data.code === 0) {
  149 + console.info(res.data.data)
  150 + this.options=res.data.data
  151 +
  152 + }
  153 + }).catch((error) => {
  154 + console.error(error)
  155 + });
  156 + }
  157 + },
  158 +};
  159 +</script>
web_src/src/components/dialog/catalogEdit.vue
@@ -49,11 +49,42 @@ export default { @@ -49,11 +49,42 @@ export default {
49 props: ['platformId'], 49 props: ['platformId'],
50 created() {}, 50 created() {},
51 data() { 51 data() {
  52 + let checkId = (rule, value, callback) => {
  53 + console.log("checkId")
  54 + console.log(this.treeType)
  55 + console.log(rule)
  56 + console.log(value)
  57 + console.log(value.length)
  58 + console.log(this.level)
  59 + if (!value) {
  60 + return callback(new Error('编号不能为空'));
  61 + }
  62 + if (this.treeType === "BusinessGroup" && value.length !== 20) {
  63 + return callback(new Error('编号必须由20位数字组成'));
  64 + }
  65 + if (this.treeType === "CivilCode" && value.length <= 8 && value.length%2 !== 0) {
  66 + return callback(new Error('行政区划必须是八位以下的偶数个数字组成'));
  67 + }
  68 + if (this.treeType === "BusinessGroup") {
  69 + let catalogType = value.substring(10, 13);
  70 + console.log(catalogType)
  71 + // 216 为虚拟组织 215 为业务分组;目录第一级必须为业务分组, 业务分组下为虚拟组织,虚拟组织下可以有其他虚拟组织
  72 + if (this.level === 1 && catalogType !== "215") {
  73 + return callback(new Error('业务分组模式下第一层目录的编号11到13位必须为215'));
  74 + }
  75 + if (this.level > 1 && catalogType !== "216") {
  76 + return callback(new Error('业务分组模式下第一层以下目录的编号11到13位必须为216'));
  77 + }
  78 + }
  79 + callback();
  80 + }
52 return { 81 return {
53 submitCallback: null, 82 submitCallback: null,
54 showDialog: false, 83 showDialog: false,
55 isLoging: false, 84 isLoging: false,
56 isEdit: false, 85 isEdit: false,
  86 + treeType: null,
  87 + level: 0,
57 form: { 88 form: {
58 id: null, 89 id: null,
59 name: null, 90 name: null,
@@ -62,12 +93,12 @@ export default { @@ -62,12 +93,12 @@ export default {
62 }, 93 },
63 rules: { 94 rules: {
64 name: [{ required: true, message: "请输入名称", trigger: "blur" }], 95 name: [{ required: true, message: "请输入名称", trigger: "blur" }],
65 - id: [{ required: true, message: "请输入ID", trigger: "blur" }] 96 + id: [{ required: true, trigger: "blur",validator: checkId }]
66 }, 97 },
67 }; 98 };
68 }, 99 },
69 methods: { 100 methods: {
70 - openDialog: function (isEdit, id, name, parentId, callback) { 101 + openDialog: function (isEdit, id, name, parentId, treeType, level, callback) {
71 console.log("parentId: " + parentId) 102 console.log("parentId: " + parentId)
72 console.log(this.form) 103 console.log(this.form)
73 this.isEdit = isEdit; 104 this.isEdit = isEdit;
@@ -77,6 +108,8 @@ export default { @@ -77,6 +108,8 @@ export default {
77 this.form.parentId = parentId; 108 this.form.parentId = parentId;
78 this.showDialog = true; 109 this.showDialog = true;
79 this.submitCallback = callback; 110 this.submitCallback = callback;
  111 + this.treeType = treeType;
  112 + this.level = level;
80 }, 113 },
81 onSubmit: function () { 114 onSubmit: function () {
82 console.log("onSubmit"); 115 console.log("onSubmit");
web_src/src/components/dialog/changePasswordForAdmin.vue 0 → 100644
  1 +<template>
  2 + <div id="changePassword" v-loading="isLoging">
  3 + <el-dialog
  4 + title="修改密码"
  5 + width="40%"
  6 + top="2rem"
  7 + :close-on-click-modal="false"
  8 + :visible.sync="showDialog"
  9 + :destroy-on-close="true"
  10 + @close="close()"
  11 + >
  12 + <div id="shared" style="margin-right: 20px;">
  13 + <el-form ref="passwordForm" :rules="rules" status-icon label-width="80px">
  14 + <el-form-item label="新密码" prop="newPassword" >
  15 + <el-input v-model="newPassword" autocomplete="off"></el-input>
  16 + </el-form-item>
  17 + <el-form-item label="确认密码" prop="confirmPassword">
  18 + <el-input v-model="confirmPassword" autocomplete="off"></el-input>
  19 + </el-form-item>
  20 +
  21 + <el-form-item>
  22 + <div style="float: right;">
  23 + <el-button type="primary" @click="onSubmit">保存</el-button>
  24 + <el-button @click="close">取消</el-button>
  25 + </div>
  26 + </el-form-item>
  27 + </el-form>
  28 + </div>
  29 + </el-dialog>
  30 + </div>
  31 +</template>
  32 +
  33 +<script>
  34 +export default {
  35 + name: "changePasswordForAdmin",
  36 + props: {},
  37 + computed: {},
  38 + created() {},
  39 + data() {
  40 + let validatePass1 = (rule, value, callback) => {
  41 + if (value === '') {
  42 + callback(new Error('请输入新密码'));
  43 + } else {
  44 + if (this.confirmPassword !== '') {
  45 + this.$refs.passwordForm.validateField('confirmPassword');
  46 + }
  47 + callback();
  48 + }
  49 + };
  50 + let validatePass2 = (rule, value, callback) => {
  51 + if (this.confirmPassword === '') {
  52 + callback(new Error('请再次输入密码'));
  53 + } else if (this.confirmPassword !== this.newPassword) {
  54 + callback(new Error('两次输入密码不一致!'));
  55 + } else {
  56 + callback();
  57 + }
  58 + };
  59 + return {
  60 + newPassword: null,
  61 + confirmPassword: null,
  62 + userId: null,
  63 + showDialog: false,
  64 + isLoging: false,
  65 + listChangeCallback: null,
  66 + form: {},
  67 + rules: {
  68 + newPassword: [{ required: true, validator: validatePass1, trigger: "blur" }, {
  69 + pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/]).{8,20}$/,
  70 + message: "密码长度在8-20位之间,由字母+数字+特殊字符组成",
  71 + },],
  72 + confirmPassword: [{ required: true, validator: validatePass2, trigger: "blur" }],
  73 + },
  74 + };
  75 + },
  76 + methods: {
  77 + openDialog: function (row, callback) {
  78 + console.log(row)
  79 + this.showDialog = true;
  80 + this.listChangeCallback = callback;
  81 + if (row != null) {
  82 + this.form = row;
  83 + }
  84 + },
  85 + onSubmit: function () {
  86 + this.$axios({
  87 + method: 'post',
  88 + url:"/api/user/changePasswordForAdmin",
  89 + params: {
  90 + password: this.newPassword,
  91 + userId: this.form.id,
  92 + }
  93 + }).then((res)=> {
  94 + if (res.data === "success"){
  95 + this.$message({
  96 + showClose: true,
  97 + message: '修改成功',
  98 + type: 'success'
  99 + });
  100 + this.showDialog = false;
  101 + }else {
  102 + this.$message({
  103 + showClose: true,
  104 + message: '修改密码失败,是否已登录(接口鉴权关闭无法修改密码)',
  105 + type: 'error'
  106 + });
  107 + }
  108 + }).catch((error)=> {
  109 + console.error(error)
  110 + });
  111 + },
  112 + close: function () {
  113 + this.showDialog = false;
  114 + this.newPassword = null;
  115 + this.confirmPassword = null;
  116 + this.userId=null;
  117 + this.adminId=null;
  118 + },
  119 + },
  120 +};
  121 +</script>
web_src/src/components/dialog/changePushKey.vue 0 → 100644
  1 +<template>
  2 + <div id="changepushKey" v-loading="isLoging">
  3 + <el-dialog
  4 + title="修改pushKey"
  5 + width="42%"
  6 + top="2rem"
  7 + :close-on-click-modal="false"
  8 + :visible.sync="showDialog"
  9 + :destroy-on-close="true"
  10 + @close="close()"
  11 + >
  12 + <div id="shared" style="margin-right: 18px;">
  13 + <el-form ref="pushKeyForm" :rules="rules" status-icon label-width="86px">
  14 + <el-form-item label="新pushKey" prop="newPushKey" >
  15 + <el-input v-model="newPushKey" autocomplete="off"></el-input>
  16 + </el-form-item>
  17 + <el-form-item>
  18 + <div style="float: right;">
  19 + <el-button type="primary" @click="onSubmit">保存</el-button>
  20 + <el-button @click="close">取消</el-button>
  21 + </div>
  22 + </el-form-item>
  23 + </el-form>
  24 + </div>
  25 + </el-dialog>
  26 + </div>
  27 +</template>
  28 +
  29 +<script>
  30 +export default {
  31 + name: "changePushKey",
  32 + props: {},
  33 + computed: {},
  34 + created() {},
  35 + data() {
  36 + let validatePass1 = (rule, value, callback) => {
  37 + if (value === '') {
  38 + callback(new Error('请输入新pushKey'));
  39 + } else {
  40 + callback();
  41 + }
  42 + };
  43 + return {
  44 + newPushKey: null,
  45 + confirmpushKey: null,
  46 + userId: null,
  47 + showDialog: false,
  48 + isLoging: false,
  49 + listChangeCallback: null,
  50 + form: {},
  51 + rules: {
  52 + newpushKey: [{ required: true, validator: validatePass1, trigger: "blur" }],
  53 + },
  54 + };
  55 + },
  56 + methods: {
  57 + openDialog: function (row, callback) {
  58 + console.log(row)
  59 + this.showDialog = true;
  60 + this.listChangeCallback = callback;
  61 + if (row != null) {
  62 + this.form = row;
  63 + }
  64 + },
  65 + onSubmit: function () {
  66 + this.$axios({
  67 + method: 'post',
  68 + url:"/api/user/changePushKey",
  69 + params: {
  70 + pushKey: this.newPushKey,
  71 + userId: this.form.id,
  72 + }
  73 + }).then((res)=> {
  74 + console.log(res.data)
  75 + if (res.data.msg === "success"){
  76 + this.$message({
  77 + showClose: true,
  78 + message: '修改成功',
  79 + type: 'success'
  80 + });
  81 + this.showDialog = false;
  82 + this.listChangeCallback();
  83 + }else {
  84 + this.$message({
  85 + showClose: true,
  86 + message: '修改pushKey失败,是否已登录(接口鉴权关闭无法修改pushKey)',
  87 + type: 'error'
  88 + });
  89 + }
  90 + }).catch((error)=> {
  91 + console.error(error)
  92 + });
  93 + },
  94 + close: function () {
  95 + this.showDialog = false;
  96 + this.newpushKey = null;
  97 + this.userId=null;
  98 + this.adminId=null;
  99 + },
  100 + },
  101 +};
  102 +</script>
web_src/src/components/dialog/chooseChannel.vue
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 <el-tab-pane label="目录结构" name="catalog"> 8 <el-tab-pane label="目录结构" name="catalog">
9 <el-container> 9 <el-container>
10 <el-main v-bind:style="{backgroundColor: '#FFF', maxHeight: winHeight + 'px'}"> 10 <el-main v-bind:style="{backgroundColor: '#FFF', maxHeight: winHeight + 'px'}">
11 - <chooseChannelForCatalog ref="chooseChannelForCatalog" :platformId=platformId :platformName=platformName :defaultCatalogId=defaultCatalogId :catalogIdChange="catalogIdChange" ></chooseChannelForCatalog> 11 + <chooseChannelForCatalog ref="chooseChannelForCatalog" :platformId=platformId :platformName=platformName :defaultCatalogId=defaultCatalogId :catalogIdChange="catalogIdChange" :treeType=treeType ></chooseChannelForCatalog>
12 </el-main> 12 </el-main>
13 </el-container> 13 </el-container>
14 </el-tab-pane> 14 </el-tab-pane>
@@ -66,18 +66,20 @@ export default { @@ -66,18 +66,20 @@ export default {
66 platformName: "", 66 platformName: "",
67 defaultCatalogId: "", 67 defaultCatalogId: "",
68 showDialog: false, 68 showDialog: false,
  69 + treeType: null,
69 chooseData: {}, 70 chooseData: {},
70 winHeight: window.innerHeight - 250, 71 winHeight: window.innerHeight - 250,
71 72
72 }; 73 };
73 }, 74 },
74 methods: { 75 methods: {
75 - openDialog(platformId, platformName, defaultCatalogId, closeCallback) { 76 + openDialog(platformId, platformName, defaultCatalogId, treeType, closeCallback) {
76 this.platformId = platformId 77 this.platformId = platformId
77 this.platformName = platformName 78 this.platformName = platformName
78 this.defaultCatalogId = defaultCatalogId 79 this.defaultCatalogId = defaultCatalogId
79 this.showDialog = true 80 this.showDialog = true
80 this.closeCallback = closeCallback 81 this.closeCallback = closeCallback
  82 + this.treeType = treeType
81 }, 83 },
82 tabClick (tab, event){ 84 tabClick (tab, event){
83 85
web_src/src/components/dialog/chooseChannelForCatalog.vue
@@ -38,7 +38,7 @@ @@ -38,7 +38,7 @@
38 import catalogEdit from './catalogEdit.vue' 38 import catalogEdit from './catalogEdit.vue'
39 export default { 39 export default {
40 name: 'chooseChannelForCatalog', 40 name: 'chooseChannelForCatalog',
41 - props: ['platformId', 'platformName', 'defaultCatalogId', 'catalogIdChange'], 41 + props: ['platformId', 'platformName', 'defaultCatalogId', 'catalogIdChange', 'treeType'],
42 created() { 42 created() {
43 this.chooseId = this.defaultCatalogId; 43 this.chooseId = this.defaultCatalogId;
44 this.defaultCatalogIdSign = this.defaultCatalogId; 44 this.defaultCatalogIdSign = this.defaultCatalogId;
@@ -102,8 +102,9 @@ export default { @@ -102,8 +102,9 @@ export default {
102 }, 102 },
103 addCatalog: function (parentId, node){ 103 addCatalog: function (parentId, node){
104 let that = this; 104 let that = this;
  105 + console.log(this.treeType)
105 // 打开添加弹窗 106 // 打开添加弹窗
106 - that.$refs.catalogEdit.openDialog(false, null, null, parentId, ()=>{ 107 + that.$refs.catalogEdit.openDialog(false, null, null, parentId, this.treeType, node.level, ()=>{
107 node.loaded = false 108 node.loaded = false
108 node.expand(); 109 node.expand();
109 }); 110 });
web_src/src/components/dialog/chooseChannelForStream.vue
@@ -174,7 +174,6 @@ export default { @@ -174,7 +174,6 @@ export default {
174 page: that.currentPage, 174 page: that.currentPage,
175 count: that.count, 175 count: that.count,
176 query: that.searchSrt, 176 query: that.searchSrt,
177 - pushing: that.pushing,  
178 platformId: that.platformId, 177 platformId: that.platformId,
179 catalogId: that.catalogId, 178 catalogId: that.catalogId,
180 mediaServerId: that.mediaServerId 179 mediaServerId: that.mediaServerId
web_src/src/components/dialog/devicePlayer.vue
@@ -388,7 +388,7 @@ export default { @@ -388,7 +388,7 @@ export default {
388 url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtmp&app='+ this.app +'&stream='+ this.streamId 388 url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtmp&app='+ this.app +'&stream='+ this.streamId
389 }).then(function (res) { 389 }).then(function (res) {
390 that.tracksLoading = false; 390 that.tracksLoading = false;
391 - if (res.data.code == 0 && res.data.online) { 391 + if (res.data.code == 0 && res.data.tracks) {
392 that.tracks = res.data.tracks; 392 that.tracks = res.data.tracks;
393 }else{ 393 }else{
394 that.tracksNotLoaded = true; 394 that.tracksNotLoaded = true;
web_src/src/components/dialog/platformEdit.vue
@@ -78,6 +78,12 @@ @@ -78,6 +78,12 @@
78 <el-option label="8" value="8"></el-option> 78 <el-option label="8" value="8"></el-option>
79 </el-select> 79 </el-select>
80 </el-form-item> 80 </el-form-item>
  81 + <el-form-item label="目录结构" prop="treeType" >
  82 + <el-select v-model="platform.treeType" style="width: 100%" >
  83 + <el-option key="WGS84" label="行政区划" value="CivilCode"></el-option>
  84 + <el-option key="GCJ02" label="业务分组" value="BusinessGroup"></el-option>
  85 + </el-select>
  86 + </el-form-item>
81 <el-form-item label="字符集" prop="characterSet"> 87 <el-form-item label="字符集" prop="characterSet">
82 <el-select 88 <el-select
83 v-model="platform.characterSet" 89 v-model="platform.characterSet"
@@ -91,7 +97,6 @@ @@ -91,7 +97,6 @@
91 <el-form-item label="其他选项"> 97 <el-form-item label="其他选项">
92 <el-checkbox label="启用" v-model="platform.enable" @change="checkExpires"></el-checkbox> 98 <el-checkbox label="启用" v-model="platform.enable" @change="checkExpires"></el-checkbox>
93 <el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox> 99 <el-checkbox label="云台控制" v-model="platform.ptz"></el-checkbox>
94 - <el-checkbox label="共享所有直播流" v-model="platform.shareAllLiveStream"></el-checkbox>  
95 <el-checkbox label="拉起离线推流" v-model="platform.startOfflinePush"></el-checkbox> 100 <el-checkbox label="拉起离线推流" v-model="platform.startOfflinePush"></el-checkbox>
96 </el-form-item> 101 </el-form-item>
97 <el-form-item> 102 <el-form-item>
@@ -153,10 +158,10 @@ export default { @@ -153,10 +158,10 @@ export default {
153 keepTimeout: 60, 158 keepTimeout: 60,
154 transport: "UDP", 159 transport: "UDP",
155 characterSet: "GB2312", 160 characterSet: "GB2312",
156 - shareAllLiveStream: false,  
157 startOfflinePush: false, 161 startOfflinePush: false,
158 catalogGroup: 1, 162 catalogGroup: 1,
159 administrativeDivision: null, 163 administrativeDivision: null,
  164 + treeType: "BusinessGroup",
160 }, 165 },
161 rules: { 166 rules: {
162 name: [{ required: true, message: "请输入平台名称", trigger: "blur" }], 167 name: [{ required: true, message: "请输入平台名称", trigger: "blur" }],
@@ -194,6 +199,7 @@ export default { @@ -194,6 +199,7 @@ export default {
194 that.platform.devicePort = res.data.devicePort; 199 that.platform.devicePort = res.data.devicePort;
195 that.platform.username = res.data.username; 200 that.platform.username = res.data.username;
196 that.platform.password = res.data.password; 201 that.platform.password = res.data.password;
  202 + that.platform.treeType = "BusinessGroup";
197 that.platform.administrativeDivision = res.data.username.substr(0, 6); 203 that.platform.administrativeDivision = res.data.username.substr(0, 6);
198 }).catch(function (error) { 204 }).catch(function (error) {
199 console.log(error); 205 console.log(error);
@@ -217,11 +223,11 @@ export default { @@ -217,11 +223,11 @@ export default {
217 this.platform.keepTimeout = platform.keepTimeout; 223 this.platform.keepTimeout = platform.keepTimeout;
218 this.platform.transport = platform.transport; 224 this.platform.transport = platform.transport;
219 this.platform.characterSet = platform.characterSet; 225 this.platform.characterSet = platform.characterSet;
220 - this.platform.shareAllLiveStream = platform.shareAllLiveStream;  
221 this.platform.catalogId = platform.catalogId; 226 this.platform.catalogId = platform.catalogId;
222 this.platform.startOfflinePush = platform.startOfflinePush; 227 this.platform.startOfflinePush = platform.startOfflinePush;
223 this.platform.catalogGroup = platform.catalogGroup; 228 this.platform.catalogGroup = platform.catalogGroup;
224 this.platform.administrativeDivision = platform.administrativeDivision; 229 this.platform.administrativeDivision = platform.administrativeDivision;
  230 + this.platform.treeType = platform.treeType;
225 this.onSubmit_text = "保存"; 231 this.onSubmit_text = "保存";
226 this.saveUrl = "/api/platform/save"; 232 this.saveUrl = "/api/platform/save";
227 } 233 }
@@ -242,32 +248,49 @@ export default { @@ -242,32 +248,49 @@ export default {
242 248
243 }, 249 },
244 onSubmit: function () { 250 onSubmit: function () {
  251 + if (this.onSubmit_text === "保存") {
  252 + this.$confirm("修改目录结构会导致关联目录与通道数据被清空", '提示', {
  253 + dangerouslyUseHTMLString: true,
  254 + confirmButtonText: '确定',
  255 + cancelButtonText: '取消',
  256 + center: true,
  257 + type: 'warning'
  258 + }).then(() => {
  259 + this.saveForm()
  260 + }).catch(() => {
  261 +
  262 + });
  263 + }else {
  264 + this.saveForm()
  265 + }
  266 + },
  267 + saveForm: function (){
245 var that = this; 268 var that = this;
246 that.$axios({ 269 that.$axios({
247 method: 'post', 270 method: 'post',
248 url: this.saveUrl, 271 url: this.saveUrl,
249 data: that.platform 272 data: that.platform
250 }).then(function (res) { 273 }).then(function (res) {
251 - if (res.data.code === 0) {  
252 - that.$message({  
253 - showClose: true,  
254 - message: "保存成功",  
255 - type: "success",  
256 - });  
257 - that.showDialog = false;  
258 - if (that.listChangeCallback != null) {  
259 - that.listChangeCallback();  
260 - }  
261 - }else {  
262 - that.$message({  
263 - showClose: true,  
264 - message: res.data.msg,  
265 - type: "error",  
266 - }); 274 + if (res.data.code === 0) {
  275 + that.$message({
  276 + showClose: true,
  277 + message: "保存成功",
  278 + type: "success",
  279 + });
  280 + that.showDialog = false;
  281 + if (that.listChangeCallback != null) {
  282 + that.listChangeCallback();
267 } 283 }
268 - }).catch(function (error) {  
269 - console.log(error);  
270 - }); 284 + }else {
  285 + that.$message({
  286 + showClose: true,
  287 + message: res.data.msg,
  288 + type: "error",
  289 + });
  290 + }
  291 + }).catch(function (error) {
  292 + console.log(error);
  293 + });
271 }, 294 },
272 close: function () { 295 close: function () {
273 this.showDialog = false; 296 this.showDialog = false;
@@ -293,7 +316,7 @@ export default { @@ -293,7 +316,7 @@ export default {
293 keepTimeout: 60, 316 keepTimeout: 60,
294 transport: "UDP", 317 transport: "UDP",
295 characterSet: "GB2312", 318 characterSet: "GB2312",
296 - shareAllLiveStream: false, 319 + treeType: "BusinessGroup",
297 startOfflinePush: false, 320 startOfflinePush: false,
298 catalogGroup: 1, 321 catalogGroup: 1,
299 } 322 }
web_src/src/components/dialog/addStreamTOGB.vue renamed to web_src/src/components/dialog/pushStreamEdit.vue
@@ -15,20 +15,25 @@ @@ -15,20 +15,25 @@
15 <el-input v-model="proxyParam.name" clearable></el-input> 15 <el-input v-model="proxyParam.name" clearable></el-input>
16 </el-form-item> 16 </el-form-item>
17 <el-form-item label="流应用名" prop="app"> 17 <el-form-item label="流应用名" prop="app">
18 - <el-input v-model="proxyParam.app" clearable :disabled="true"></el-input> 18 + <el-input v-model="proxyParam.app" clearable :disabled="edit"></el-input>
19 </el-form-item> 19 </el-form-item>
20 <el-form-item label="流ID" prop="stream"> 20 <el-form-item label="流ID" prop="stream">
21 - <el-input v-model="proxyParam.stream" clearable :disabled="true"></el-input> 21 + <el-input v-model="proxyParam.stream" clearable :disabled="edit"></el-input>
22 </el-form-item> 22 </el-form-item>
23 <el-form-item label="国标编码" prop="gbId"> 23 <el-form-item label="国标编码" prop="gbId">
24 <el-input v-model="proxyParam.gbId" placeholder="设置国标编码可推送到国标" clearable></el-input> 24 <el-input v-model="proxyParam.gbId" placeholder="设置国标编码可推送到国标" clearable></el-input>
25 </el-form-item> 25 </el-form-item>
  26 + <el-form-item label="经度" prop="longitude" v-if="proxyParam.gbId">
  27 + <el-input v-model="proxyParam.longitude" placeholder="经度" clearable></el-input>
  28 + </el-form-item>
  29 + <el-form-item label="纬度" prop="latitude" v-if="proxyParam.gbId">
  30 + <el-input v-model="proxyParam.latitude" placeholder="经度" clearable></el-input>
  31 + </el-form-item>
26 <el-form-item> 32 <el-form-item>
27 <div style="float: right;"> 33 <div style="float: right;">
28 <el-button type="primary" @click="onSubmit">保存</el-button> 34 <el-button type="primary" @click="onSubmit">保存</el-button>
29 <el-button @click="close">取消</el-button> 35 <el-button @click="close">取消</el-button>
30 </div> 36 </div>
31 -  
32 </el-form-item> 37 </el-form-item>
33 </el-form> 38 </el-form>
34 </div> 39 </div>
@@ -38,7 +43,7 @@ @@ -38,7 +43,7 @@
38 43
39 <script> 44 <script>
40 export default { 45 export default {
41 - name: "streamProxyEdit", 46 + name: "pushStreamEdit",
42 props: {}, 47 props: {},
43 computed: {}, 48 computed: {},
44 created() {}, 49 created() {},
@@ -63,13 +68,15 @@ export default { @@ -63,13 +68,15 @@ export default {
63 listChangeCallback: null, 68 listChangeCallback: null,
64 showDialog: false, 69 showDialog: false,
65 isLoging: false, 70 isLoging: false,
  71 + edit: false,
66 proxyParam: { 72 proxyParam: {
67 name: null, 73 name: null,
68 app: null, 74 app: null,
69 stream: null, 75 stream: null,
70 gbId: null, 76 gbId: null,
  77 + longitude: null,
  78 + latitude: null,
71 }, 79 },
72 -  
73 rules: { 80 rules: {
74 name: [{ required: true, message: "请输入名称", trigger: "blur" }], 81 name: [{ required: true, message: "请输入名称", trigger: "blur" }],
75 app: [{ required: true, message: "请输入应用名", trigger: "blur" }], 82 app: [{ required: true, message: "请输入应用名", trigger: "blur" }],
@@ -84,30 +91,63 @@ export default { @@ -84,30 +91,63 @@ export default {
84 this.listChangeCallback = callback; 91 this.listChangeCallback = callback;
85 if (proxyParam != null) { 92 if (proxyParam != null) {
86 this.proxyParam = proxyParam; 93 this.proxyParam = proxyParam;
87 - } 94 + this.edit = true
  95 + }else{
  96 + this.proxyParam= {
  97 + name: null,
  98 + app: null,
  99 + stream: null,
  100 + gbId: null,
  101 + longitude: null,
  102 + latitude: null,
  103 + }
  104 + this.edit = false
  105 + }
88 }, 106 },
89 onSubmit: function () { 107 onSubmit: function () {
90 console.log("onSubmit"); 108 console.log("onSubmit");
91 - var that = this;  
92 - that.$axios({  
93 - method:"post",  
94 - url:`/api/push/save_to_gb`,  
95 - data: that.proxyParam  
96 - }).then(function (res) { 109 + if (this.edit) {
  110 + this.$axios({
  111 + method:"post",
  112 + url:`/api/push/save_to_gb`,
  113 + data: this.proxyParam
  114 + }).then( (res) => {
97 if (res.data == "success") { 115 if (res.data == "success") {
98 - that.$message({ 116 + this.$message({
99 showClose: true, 117 showClose: true,
100 message: "保存成功", 118 message: "保存成功",
101 type: "success", 119 type: "success",
102 }); 120 });
103 - that.showDialog = false;  
104 - if (that.listChangeCallback != null) {  
105 - that.listChangeCallback(); 121 + this.showDialog = false;
  122 + if (this.listChangeCallback != null) {
  123 + this.listChangeCallback();
106 } 124 }
107 } 125 }
108 - }).catch(function (error) { 126 + }).catch((error)=> {
109 console.log(error); 127 console.log(error);
110 - }); 128 + });
  129 + }else {
  130 + this.$axios({
  131 + method:"post",
  132 + url:`/api/push/add`,
  133 + data: this.proxyParam
  134 + }).then( (res) => {
  135 + if (res.data.code === 0) {
  136 + this.$message({
  137 + showClose: true,
  138 + message: "保存成功",
  139 + type: "success",
  140 + });
  141 + this.showDialog = false;
  142 + if (this.listChangeCallback != null) {
  143 + this.listChangeCallback();
  144 + }
  145 + }
  146 + }).catch((error)=> {
  147 + console.log(error);
  148 + });
  149 + }
  150 +
111 }, 151 },
112 close: function () { 152 close: function () {
113 console.log("关闭加入GB"); 153 console.log("关闭加入GB");
@@ -131,6 +171,9 @@ export default { @@ -131,6 +171,9 @@ export default {
131 if (this.platform.enable && this.platform.expires == "0") { 171 if (this.platform.enable && this.platform.expires == "0") {
132 this.platform.expires = "300"; 172 this.platform.expires = "300";
133 } 173 }
  174 + },
  175 + handleNodeClick: function (node){
  176 +
134 } 177 }
135 }, 178 },
136 }; 179 };
web_src/src/layout/UiHeader.vue
@@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
13 <el-menu-item index="/cloudRecord">云端录像</el-menu-item> 13 <el-menu-item index="/cloudRecord">云端录像</el-menu-item>
14 <el-menu-item index="/mediaServerManger">节点管理</el-menu-item> 14 <el-menu-item index="/mediaServerManger">节点管理</el-menu-item>
15 <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item> 15 <el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>
  16 + <el-menu-item v-if="editUser" index="/userManager">用户管理</el-menu-item>
16 17
17 <!-- <el-submenu index="/setting">--> 18 <!-- <el-submenu index="/setting">-->
18 <!-- <template slot="title">系统设置</template>--> 19 <!-- <template slot="title">系统设置</template>-->
@@ -47,9 +48,11 @@ export default { @@ -47,9 +48,11 @@ export default {
47 alarmNotify: false, 48 alarmNotify: false,
48 sseSource: null, 49 sseSource: null,
49 activeIndex: this.$route.path, 50 activeIndex: this.$route.path,
  51 + editUser: this.$cookies.get("session").roleId==1
50 }; 52 };
51 }, 53 },
52 created() { 54 created() {
  55 + console.log(this.$cookies.get("session"))
53 if (this.$route.path.startsWith("/channelList")) { 56 if (this.$route.path.startsWith("/channelList")) {
54 this.activeIndex = "/deviceList" 57 this.activeIndex = "/deviceList"
55 } 58 }
web_src/src/router/index.js
@@ -17,6 +17,7 @@ import sip from &#39;../components/setting/Sip.vue&#39; @@ -17,6 +17,7 @@ import sip from &#39;../components/setting/Sip.vue&#39;
17 import media from '../components/setting/Media.vue' 17 import media from '../components/setting/Media.vue'
18 import live from '../components/live.vue' 18 import live from '../components/live.vue'
19 import deviceTree from '../components/common/DeviceTree.vue' 19 import deviceTree from '../components/common/DeviceTree.vue'
  20 +import userManager from '../components/UserManager.vue'
20 21
21 import wasmPlayer from '../components/common/jessibuca.vue' 22 import wasmPlayer from '../components/common/jessibuca.vue'
22 import rtcPlayer from '../components/dialog/rtcPlayer.vue' 23 import rtcPlayer from '../components/dialog/rtcPlayer.vue'
@@ -103,6 +104,11 @@ export default new VueRouter({ @@ -103,6 +104,11 @@ export default new VueRouter({
103 name: 'map', 104 name: 'map',
104 component: map, 105 component: map,
105 }, 106 },
  107 + {
  108 + path: '/userManager',
  109 + name: 'userManager',
  110 + component: userManager,
  111 + }
106 ] 112 ]
107 }, 113 },
108 { 114 {
web_src/static/file/推流通道导入.zip
No preview for this file type
web_src/static/js/jessibuca/decoder.wasm 100755 → 100644
No preview for this file type