Merge branch 'master' into dev/springBoot3
# Conflicts: # src/main/java/com/genersoft/iot/vmp/gb28181/controller/MediaController.java # src/main/java/com/genersoft/iot/vmp/jt1078/config/JT1078Controller.java
This commit is contained in:
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
||||
docker/volumes
|
||||
75
.github/workflows/build.yml
vendored
Normal file
75
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
name: release-ubuntu
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*" # 触发条件是推送标签 如git tag v2.7.4 git push origin v2.7.4
|
||||
|
||||
jobs:
|
||||
build-ubuntu:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [amd64]
|
||||
max-parallel: 1 # 最大并行数
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4 # github action运行环境
|
||||
|
||||
- name: Create release # 创建文件夹
|
||||
run: |
|
||||
rm -rf release
|
||||
mkdir release
|
||||
echo ${{ github.sha }} > Release.txt
|
||||
cp Release.txt LICENSE release/
|
||||
cat Release.txt
|
||||
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
# Eclipse基金会维护的开源Java发行版 因为github action参考java的用这个 所以用这个
|
||||
# 还有microsoft(微软维护的openjdk发行版) oracle(商用SDK)等
|
||||
distribution: 'temurin'
|
||||
java-version: '8'
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x' # Node.js版本 20系列的最新稳定版
|
||||
|
||||
- name: Compile backend
|
||||
run: |
|
||||
mvn package
|
||||
mvn package -P war
|
||||
|
||||
- name: Compile frontend
|
||||
run: |
|
||||
cd ./web
|
||||
npm install
|
||||
npm run build:prod
|
||||
cd ../
|
||||
|
||||
- name: Package Files
|
||||
run: |
|
||||
cp -r ./src/main/resources/static release/ # 复制前端文件
|
||||
cp ./target/*.jar release/ # 复制 JAR 文件
|
||||
cp ./src/main/resources/application-dev.yml release/application.yml
|
||||
|
||||
BRANCH=${{ github.event.base_ref }}
|
||||
BRANCH_NAME=$(echo "$BRANCH" | grep -oP 'refs/heads/\K.*')
|
||||
echo "BRANCH_NAME= ${BRANCH_NAME}"
|
||||
# 如果无法获取,使用默认分支
|
||||
if [[ -z "BRANCH_NAME" ]]; then
|
||||
BRANCH_NAME="${{ github.event.repository.default_branch }}"
|
||||
fi
|
||||
|
||||
TAG_NAME="${GITHUB_REF#refs/tags/}"
|
||||
ZIP_FILE_NAME="${BRANCH_NAME}-${TAG_NAME}.zip"
|
||||
zip -r "$ZIP_FILE_NAME" release
|
||||
echo "ZIP_FILE_NAME=$ZIP_FILE_NAME" >> $GITHUB_ENV
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: ${{ env.ZIP_FILE_NAME }}
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -28,3 +28,5 @@ hs_err_pid*
|
||||
|
||||
/src/main/resources/static/
|
||||
certificates
|
||||
/.vs
|
||||
/docker/volumes
|
||||
|
||||
57
README.md
57
README.md
@@ -1,5 +1,5 @@
|
||||

|
||||
# 开箱即用的28181协议视频平台
|
||||
# 开箱即用的国标28181和部标808+1078协议视频平台
|
||||
|
||||
[](https://travis-ci.org/xia-chu/ZLMediaKit)
|
||||
[](https://github.com/xia-chu/ZLMediaKit/blob/master/LICENSE)
|
||||
@@ -8,7 +8,7 @@
|
||||
[](https://github.com/xia-chu/ZLMediaKit/pulls)
|
||||
|
||||
|
||||
WEB VIDEO PLATFORM是一个基于GB28181-2016标准实现的开箱即用的网络视频平台,负责实现核心信令与设备管理后台部分,支持NAT穿透,支持海康、大华、宇视等品牌的IPC、NVR接入。支持国标级联,支持将不带国标功能的摄像机/直播流/直播推流转发到其他国标平台。
|
||||
WEB VIDEO PLATFORM是一个基于GB28181-2016、部标808、部标1078标准实现的开箱即用的网络视频平台,负责实现核心信令与设备管理后台部分,支持NAT穿透,支持海康、大华、宇视等品牌的IPC、NVR接入。支持国标级联,支持将不带国标功能的摄像机/直播流/直播推流转发到其他国标平台。
|
||||
|
||||
流媒体服务基于@夏楚 ZLMediaKit [https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit)
|
||||
播放器使用@dexter jessibuca [https://github.com/langhuihui/jessibuca/tree/v3](https://github.com/langhuihui/jessibuca/tree/v3)
|
||||
@@ -27,15 +27,6 @@ WEB VIDEO PLATFORM是一个基于GB28181-2016标准实现的开箱即用的网
|
||||
wvp使用文档 [https://doc.wvp-pro.cn](https://doc.wvp-pro.cn)
|
||||
ZLM使用文档 [https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit/ZLMediaKit)
|
||||
|
||||
# 付费社群
|
||||
[](https://t.zsxq.com/0d8VAD3Dm)
|
||||
> 收费是为了提供更好的服务,也是对作者更大的激励。加入星球的用户三天后可以私信我留下微信号,我会拉大家入群。
|
||||
> 加入三天内不满意可以直接自行推出,星球会直接退款给大家。需要发票可以在星球app中直接咨询星球客服获取。
|
||||
|
||||
> 星球还提供了包括闭源的全功能试用包, 会随时更新。
|
||||
|
||||
> 付费社群即可以对作者提供支持,也可以为大家更加快速的解决问题。如果暂时无法加入,给项目点个星也是极大的鼓励。
|
||||
|
||||
# gitee仓库
|
||||
https://gitee.com/pan648540858/wvp-GB28181-pro.git
|
||||
|
||||
@@ -129,13 +120,38 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
|
||||
- [X] 支持Mysql,Postgresql,金仓等数据库
|
||||
- [X] 支持录制计划, 根据设定的时间对通道进行录制. 暂不支持将录制的内容转发到国标上级
|
||||
- [X] 支持国标信令集群
|
||||
- [X] 新增支持部标808和部标1078,大量新特性不一一列表了。支持作为网关被国标上级调用部标设备
|
||||
|
||||
|
||||
# 闭源内容
|
||||
- [X] 支持ONVIF协议,设备检索,支持点播,云台控制,国标级联点播,自动点播等。
|
||||
- [X] 支持部标1078+808协议,支持点播,云台控制,录像回放,位置上报,自动点播等。
|
||||
- [X] 支持国标28181-2022协议,支持巡航轨迹查询,PTZ精准控制,存储卡格式化,设备软件升级,OSD配置,h265+aac,支持辅码流,录像倒放等。
|
||||
- [X] 支持国网B接口协议。支持注册,获取资源,预览, 云台控制,预置位控制等,可免费定制支持语音对讲、录像回放和抓拍图像。
|
||||
- [X] 国标增强版: 支持国标28181-2022协议,支持巡航轨迹查询,PTZ精准控制,存储卡格式化,设备软件升级,OSD配置,h265+aac,支持辅码流,录像倒放等。
|
||||
- [X] 全功能版:
|
||||
- [X] 支持开源所有功能
|
||||
- [X] ONVIF协议
|
||||
- 设备检索
|
||||
- 实时图像预览
|
||||
- 录像回放、回放倍速控制
|
||||
- 云台控制、预置位控制、云台绝对定位、看守位
|
||||
- 聚焦控制
|
||||
- 设备重启
|
||||
- 设备时间设置以及跟系统时间的差值比较
|
||||
- 恢复出厂设置
|
||||
- 自动获取设备品牌等信息、支持展示DNS信息、支持协议的展示
|
||||
- 国标级联点播、自动点播等。
|
||||
- [X] 国网B接口协议
|
||||
- 设备注册
|
||||
- 资源获取
|
||||
- 预览
|
||||
- 云台控制
|
||||
- 预置位控制等,
|
||||
- 可免费定制支持语音对讲、录像回放和抓拍图像。
|
||||
- [X] 支持按权限分配可以使用的通道
|
||||
- [X] 支持电子地图。支持展示通道位置,支持在地图上修改通道位置。可扩展接入高德地图API,支持搜索位置,附近设备。
|
||||
- [X] 支持表格导出
|
||||
- [X] 拉流代理支持按照品牌拼接url。
|
||||
- [X] 播放鉴权,更加安全。
|
||||
- [X] 此版本后续开发功能支持直接更新提供,无需二次付费。
|
||||
- [X] 提供源码不限制部署次数和支持路数。
|
||||
|
||||
|
||||
# 授权协议
|
||||
@@ -143,6 +159,17 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
|
||||
|
||||
# 技术支持
|
||||
|
||||
# 付费社群
|
||||
<img src="doc/_media/shequ.png" width="50%" height="50%">
|
||||
|
||||
> 收费是为了提供更好的服务,也是对作者更大的激励。加入星球的用户三天后可以私信我留下微信号,我会拉大家入群。
|
||||
> 加入三天内不满意可以直接自行推出,星球会直接退款给大家。需要发票可以在星球app中直接咨询星球客服获取。
|
||||
|
||||
> 星球还提供了包括闭源的全功能试用包, 会随时更新。
|
||||
|
||||
> 付费社群即可以对作者提供支持,也可以为大家更加快速的解决问题。如果暂时无法加入,给项目点个星也是极大的鼓励。
|
||||
|
||||
|
||||
[知识星球](https://t.zsxq.com/0d8VAD3Dm)专栏列表:,
|
||||
- [使用入门系列一:WVP-PRO能做什么](https://t.zsxq.com/0dLguVoSp)
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@ WVP支持三种图像输入方式,直播,[拉流代理](_content/ability/pro
|
||||
1. 默认情况下WVP收到推流信息后,列表中出现这条推流信息,如果你需要共享推流信息到其他国标平台,那么你需要编辑/国标通道配置,配置国标编码.
|
||||
2. WVP也支持推流前导入大量通道直接推送给上级,点击“下载模板”按钮,根据示例修改模板后,点击“通道导入”按钮导入通道数据.
|
||||
|
||||
## 生成推流地址
|
||||
可以在推流列表里点击‘生成推流地址’按钮,得到新地址后直接复制到推流设备。
|
||||
|
||||
## 推拉流鉴权规则
|
||||
|
||||
为了保护服务器的WVP默认开启推流鉴权(目前不支持关闭此功能)
|
||||
|
||||
19
docker/.env
Normal file
19
docker/.env
Normal file
@@ -0,0 +1,19 @@
|
||||
MediaRtmp=10001
|
||||
MediaRtsp=10002
|
||||
MediaRtp=10003
|
||||
|
||||
WebHttp=8080
|
||||
WebHttps=8081
|
||||
|
||||
Stream_IP=127.0.0.1
|
||||
SDP_IP=127.0.0.1
|
||||
|
||||
SIP_ShowIP=127.0.0.1
|
||||
SIP_Port=8160
|
||||
SIP_Domain=3502000000
|
||||
SIP_Id=35020000002000000001
|
||||
SIP_Password=wvp_sip_password
|
||||
|
||||
|
||||
RecordSip=true
|
||||
RecordPushLive=
|
||||
10
docker/README.md
Normal file
10
docker/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
可以在当前目录下:
|
||||
使用`docker compose up -d`直接运行。
|
||||
使用`docker compose up -d -build -force-recreate`强制重新构建所有服务的镜像并删除旧容器重新运行
|
||||
|
||||
`.env`用来配置环境变量,在这里配好之后,其它的配置会自动联动的。
|
||||
|
||||
`build.sh`用来以日期为tag构建镜像,推送到指定的容器注册表内(Windows下可以使用`Git Bash`运行)
|
||||
|
||||
|
||||
其它的文件的作用暂不明确
|
||||
106
docker/build.sh
106
docker/build.sh
@@ -1,45 +1,79 @@
|
||||
#/bin/bash
|
||||
set -e
|
||||
#!/bin/bash
|
||||
|
||||
version=2.7.3
|
||||
# 获取当前日期作为标签(格式:YYYYMMDD)
|
||||
date_tag=$(date +%Y%m%d)
|
||||
|
||||
git clone https://gitee.com/pan648540858/wvp-GB28181-pro.git
|
||||
cd wvp-GB28181-pro/web_src && \
|
||||
npm install && \
|
||||
npm run build
|
||||
# 切换到脚本所在目录的上一级目录作为工作目录
|
||||
cd "$(dirname "$0")/.." || {
|
||||
echo "错误:无法切换到上级目录"
|
||||
exit 1
|
||||
}
|
||||
echo "已切换工作目录到:$(pwd)"
|
||||
|
||||
cd ../../
|
||||
mkdir -p ./nginx/dist
|
||||
cp -r wvp-GB28181-pro/src/main/resources/static/* ./nginx/dist
|
||||
# 检查私有仓库环境变量
|
||||
if [ -z "$DOCKER_REGISTRY" ]; then
|
||||
echo "未设置DOCKER_REGISTRY环境变量"
|
||||
read -p "请输入私有Docker注册库地址(如不推送请留空): " input_registry
|
||||
docker_registry="$input_registry"
|
||||
else
|
||||
docker_registry="$DOCKER_REGISTRY"
|
||||
fi
|
||||
|
||||
echo "构建ZLM容器"
|
||||
cd ./media/
|
||||
chmod +x ./build.sh
|
||||
./build.sh
|
||||
cd ../
|
||||
# 定义要构建的镜像和对应的Dockerfile路径(相对当前工作目录)
|
||||
images=(
|
||||
"wvp-service:docker/wvp/Dockerfile"
|
||||
"wvp-nginx:docker/nginx/Dockerfile"
|
||||
)
|
||||
|
||||
echo "构建数据库容器"
|
||||
cd ./mysql/
|
||||
chmod +x ./build.sh
|
||||
./build.sh
|
||||
cd ../
|
||||
# 构建镜像的函数
|
||||
build_image() {
|
||||
local image_name="$1"
|
||||
local dockerfile_path="$2"
|
||||
|
||||
echo "构建Redis容器"
|
||||
cd ./redis/
|
||||
chmod +x ./build.sh
|
||||
./build.sh
|
||||
cd ../
|
||||
# 检查Dockerfile是否存在
|
||||
if [ ! -f "$dockerfile_path" ]; then
|
||||
echo "错误:未找到Dockerfile - \"$dockerfile_path\",跳过构建"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "构建WVP容器"
|
||||
cd ./wvp/
|
||||
chmod +x ./build.sh
|
||||
./build.sh
|
||||
cd ../
|
||||
# 构建镜像
|
||||
local full_image_name="${image_name}:${date_tag}"
|
||||
echo
|
||||
echo "=============================================="
|
||||
echo "开始构建镜像:${full_image_name}"
|
||||
echo "Dockerfile路径:${dockerfile_path}"
|
||||
|
||||
echo "构建Nginx容器"
|
||||
cd ./nginx/
|
||||
chmod +x ./build.sh
|
||||
./build.sh
|
||||
cd ../
|
||||
docker build -t "${full_image_name}" -f "${dockerfile_path}" .
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "镜像${full_image_name}构建失败"
|
||||
return 1
|
||||
fi
|
||||
|
||||
./push.sh
|
||||
# 推送镜像(如果设置了仓库地址)
|
||||
if [ -n "$docker_registry" ]; then
|
||||
local registry_image="${docker_registry}/${full_image_name}"
|
||||
echo "给镜像打标签:${registry_image}"
|
||||
docker tag "${full_image_name}" "${registry_image}"
|
||||
|
||||
echo "推送镜像到注册库"
|
||||
docker push "${registry_image}"
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "镜像${registry_image}推送成功"
|
||||
else
|
||||
echo "镜像${registry_image}推送失败"
|
||||
fi
|
||||
else
|
||||
echo "未提供注册库地址,不执行推送"
|
||||
fi
|
||||
echo "=============================================="
|
||||
echo
|
||||
}
|
||||
|
||||
# 循环构建所有镜像
|
||||
for item in "${images[@]}"; do
|
||||
IFS=':' read -r image_name dockerfile_path <<< "$item"
|
||||
build_image "$image_name" "$dockerfile_path"
|
||||
done
|
||||
|
||||
echo "所有镜像处理完成"
|
||||
exit 0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: '3'
|
||||
services:
|
||||
polaris-redis:
|
||||
image: polaris-tian-docker.pkg.coding.net/qt/polaris/polaris-redis:latest
|
||||
image: redis:latest # 使用官方Redis镜像
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
|
||||
@@ -11,8 +11,8 @@ services:
|
||||
start_period: 10s
|
||||
networks:
|
||||
- media-net
|
||||
ports:
|
||||
- 6379:6379
|
||||
# ports:
|
||||
# - 6379:6379
|
||||
volumes:
|
||||
- ./redis/conf/redis.conf:/opt/polaris/redis/redis.conf
|
||||
- ./volumes/redis/data/:/data
|
||||
@@ -21,7 +21,7 @@ services:
|
||||
command: redis-server /opt/polaris/redis/redis.conf --appendonly yes
|
||||
|
||||
polaris-mysql:
|
||||
image: polaris-tian-docker.pkg.coding.net/qt/polaris/polaris-mysql:latest
|
||||
image: mysql:8 # 使用官方MySQL 8镜像
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/3306" ]
|
||||
@@ -34,18 +34,18 @@ services:
|
||||
environment:
|
||||
MYSQL_DATABASE: wvp
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_USER: root
|
||||
MYSQL_PASSWORD: root
|
||||
MYSQL_USER: wvp_user
|
||||
MYSQL_PASSWORD: wvp_password
|
||||
TZ: Asia/Shanghai
|
||||
ports:
|
||||
- 3306:3306
|
||||
# ports:
|
||||
# - 3306:3306
|
||||
volumes:
|
||||
- ./mysql/conf:/etc/mysql/conf.d
|
||||
- ./logs/mysql:/logs
|
||||
- ./volumes/mysql/data:/var/lib/mysql
|
||||
- ../数据库/2.7.4/初始化-mysql-2.7.4.sql:/docker-entrypoint-initdb.d/init.sql # 初始化SQL脚本目录
|
||||
command: [
|
||||
'mysqld',
|
||||
'--default-authentication-plugin=mysql_native_password',
|
||||
# '--default-authentication-plugin=mysql_native_password',
|
||||
'--innodb-buffer-pool-size=80M',
|
||||
'--character-set-server=utf8mb4',
|
||||
'--collation-server=utf8mb4_general_ci',
|
||||
@@ -54,69 +54,99 @@ services:
|
||||
]
|
||||
|
||||
polaris-media:
|
||||
image: polaris-tian-docker.pkg.coding.net/qt/polaris/polaris-media:latest
|
||||
image: zlmediakit/zlmediakit:master # 替换为官方镜像
|
||||
restart: always
|
||||
networks:
|
||||
- media-net
|
||||
ports:
|
||||
- "10935:10935"
|
||||
- "5540:5540"
|
||||
- "6080:6080"
|
||||
#- "6080:80/tcp" # [播流]HTTP 安全考虑-非测试阶段需要注释掉,改为由nginx代理播流地址
|
||||
#- "4443:443/tcp" # [播流]HTTPS 安全考虑-非测试阶段需要注释掉,改为由nginx代理播流地址
|
||||
- "${MediaRtmp:-10935}:${MediaRtmp:-10935}/tcp" # [收流]RTMP
|
||||
- "${MediaRtmp:-10935}:${MediaRtmp:-10935}/udp" # [收流]RTMP
|
||||
#- "41935:41935/tcp" # [收流]RTMPS 无效
|
||||
- "${MediaRtsp:-5540}:${MediaRtsp:-5540}/tcp" # [收流]RTSP
|
||||
- "${MediaRtsp:-5540}:${MediaRtsp:-5540}/udp" # [收流]RTSP
|
||||
#- "45540:45540/tcp" # [收流]RTSPS 无效
|
||||
- "${MediaRtp:-10000}:${MediaRtp:-10000}/tcp" # [收流]RTP
|
||||
- "${MediaRtp:-10000}:${MediaRtp:-10000}/udp" # [收流]RTP
|
||||
volumes:
|
||||
- ./volumes/video:/opt/media/www/record/
|
||||
- ./volumes/video:/opt/media/bin/www/record/
|
||||
- ./logs/media:/opt/media/log/
|
||||
- ./media/config.ini:/conf/config.ini
|
||||
command: [
|
||||
'MediaServer',
|
||||
'-c', '/conf/config.ini',
|
||||
'-l', '0'
|
||||
]
|
||||
|
||||
polaris-wvp:
|
||||
image: polaris-tian-docker.pkg.coding.net/qt/polaris/polaris-wvp:latest
|
||||
# 显式指定构建上下文和Dockerfile路径
|
||||
build:
|
||||
context: .. # 构建上下文的根路径
|
||||
dockerfile: ./docker/wvp/Dockerfile # 相对于上下文路径的Dockerfile位置
|
||||
restart: always
|
||||
networks:
|
||||
- media-net
|
||||
ports:
|
||||
- "18978:18978"
|
||||
- "8116:8116/udp"
|
||||
- "8116:8116/tcp"
|
||||
- "${SIP_Port:-8116}:${SIP_Port:-8116}/udp"
|
||||
- "${SIP_Port:-8116}:${SIP_Port:-8116}/tcp"
|
||||
depends_on:
|
||||
- polaris-redis
|
||||
- polaris-mysql
|
||||
- polaris-media
|
||||
links:
|
||||
- polaris-redis
|
||||
- polaris-mysql
|
||||
- polaris-media
|
||||
volumes:
|
||||
- ./wvp/wvp/:/opt/wvp/wvp/
|
||||
- ./wvp/wvp/:/opt/ylcx/wvp/
|
||||
- ./logs/wvp:/opt/wvp/logs/
|
||||
environment:
|
||||
TZ: "Asia/Shanghai"
|
||||
# 本机的IP
|
||||
SIP_HOST: 127.0.0.1
|
||||
STREAM_HOST: 127.0.0.1
|
||||
# 流链接的IP
|
||||
Stream_IP: ${Stream_IP}
|
||||
# SDP里的IP
|
||||
SDP_IP: ${SDP_IP}
|
||||
# [可选] zlm服务器访问WVP所使用的IP, 默认使用127.0.0.1,zlm和wvp没有部署在同一台服务器时必须配置
|
||||
ZLM_HOOK_HOST: polaris-wvp
|
||||
ZLM_HOST: polaris-media
|
||||
ZLM_PORT: 6080
|
||||
ZLM_SERCERT: su6TiedN2rVAmBbIDX0aa0QTiBJLBdcf
|
||||
|
||||
MediaHttp: ${WebHttp:-8080}
|
||||
#MediaHttps: ${WebHttps:-8081}
|
||||
MediaRtmp: ${MediaRtmp:-10935}
|
||||
MediaRtsp: ${MediaRtsp:-5540}
|
||||
MediaRtp: ${MediaRtp:-10000}
|
||||
|
||||
REDIS_HOST: polaris-redis
|
||||
REDIS_PORT: 6379
|
||||
|
||||
DATABASE_HOST: polaris-mysql
|
||||
DATABASE_PORT: 3306
|
||||
DATABASE_USER: wvp
|
||||
DATABASE_PASSWORD: wvp
|
||||
# 前端跨域配置,nginx容器所在物理机IP
|
||||
NGINX_HOST: http://127.0.0.1:8080
|
||||
DATABASE_USER: wvp_user
|
||||
DATABASE_PASSWORD: wvp_password
|
||||
|
||||
SIP_ShowIP: ${SIP_ShowIP}
|
||||
SIP_Port: ${SIP_Port:-8116}
|
||||
SIP_Domain: ${SIP_Domain}
|
||||
SIP_Id: ${SIP_Id}
|
||||
SIP_Password: ${SIP_Password}
|
||||
|
||||
RecordSip: ${RecordSip}
|
||||
RecordPushLive: ${RecordPushLive}
|
||||
|
||||
polaris-nginx:
|
||||
image: polaris-tian-docker.pkg.coding.net/qt/polaris/polaris-nginx:latest
|
||||
# 显式指定构建上下文和Dockerfile路径
|
||||
build:
|
||||
context: .. # 构建上下文的根路径
|
||||
dockerfile: ./docker/nginx/Dockerfile # 相对于上下文路径的Dockerfile位置
|
||||
ports:
|
||||
- "8080:8080"
|
||||
- "${WebHttp:-8080}:8080"
|
||||
depends_on:
|
||||
- polaris-wvp
|
||||
links:
|
||||
- polaris-wvp
|
||||
environment:
|
||||
WVP_HOST: polaris-wvp
|
||||
WVP_PORT: 18978
|
||||
volumes:
|
||||
- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf
|
||||
- ./nginx/templates/:/etc/nginx/templates
|
||||
- ./logs/nginx:/var/log/nginx
|
||||
environment:
|
||||
# 流链接的IP
|
||||
Stream_IP: ${Stream_IP}
|
||||
networks:
|
||||
- media-net
|
||||
|
||||
|
||||
@@ -52,21 +52,21 @@ alive_interval=10.0
|
||||
enable=1
|
||||
on_flow_report=
|
||||
on_http_access=
|
||||
on_play=
|
||||
on_publish=
|
||||
on_record_mp4=
|
||||
on_play=http://polaris-wvp:18978/index/hook/on_play
|
||||
on_publish=http://polaris-wvp:18978/index/hook/on_publish
|
||||
on_record_mp4=http://polaris-wvp:18978/index/hook/on_record_mp4
|
||||
on_record_ts=
|
||||
on_rtp_server_timeout=
|
||||
on_rtp_server_timeout=http://polaris-wvp:18978/index/hook/on_rtp_server_timeout
|
||||
on_rtsp_auth=
|
||||
on_rtsp_realm=
|
||||
on_send_rtp_stopped=
|
||||
on_send_rtp_stopped=http://polaris-wvp:18978/index/hook/on_send_rtp_stopped
|
||||
on_server_exited=
|
||||
on_server_keepalive=
|
||||
on_server_started=
|
||||
on_server_keepalive=http://polaris-wvp:18978/index/hook/on_server_keepalive
|
||||
on_server_started=http://polaris-wvp:18978/index/hook/on_server_started
|
||||
on_shell_login=
|
||||
on_stream_changed=
|
||||
on_stream_none_reader=
|
||||
on_stream_not_found=
|
||||
on_stream_changed=http://polaris-wvp:18978/index/hook/on_stream_changed
|
||||
on_stream_none_reader=http://polaris-wvp:18978/index/hook/on_stream_none_reader
|
||||
on_stream_not_found=http://polaris-wvp:18978/index/hook/on_stream_not_found
|
||||
retry=1
|
||||
retry_delay=3.0
|
||||
stream_changed_schemas=rtsp/rtmp/fmp4/ts/hls/hls.fmp4
|
||||
@@ -82,10 +82,10 @@ forwarded_ip_header=
|
||||
keepAliveSecond=30
|
||||
maxReqSize=40960
|
||||
notFound=<html><head><title>404 Not Found</title></head><body bgcolor="white"><center><h1>您访问的资源不存在!</h1></center><hr><center>ZLMediaKit(git hash:8ccb4e9/%aI,branch:master,build time:2024-11-07T10:34:19)</center></body></html>
|
||||
port=6080
|
||||
port=80
|
||||
rootPath=./www
|
||||
sendBufSize=65536
|
||||
sslport=4443
|
||||
sslport=443
|
||||
virtualPath=
|
||||
|
||||
[multicast]
|
||||
@@ -99,7 +99,7 @@ auto_close=0
|
||||
continue_push_ms=3000
|
||||
enable_audio=1
|
||||
enable_fmp4=1
|
||||
enable_hls=1
|
||||
enable_hls=0
|
||||
enable_hls_fmp4=0
|
||||
enable_mp4=0
|
||||
enable_rtmp=1
|
||||
@@ -111,7 +111,7 @@ hls_save_path=./www
|
||||
modify_stamp=2
|
||||
mp4_as_player=0
|
||||
mp4_max_second=3600
|
||||
mp4_save_path=/home
|
||||
mp4_save_path=/opt/media/bin/www
|
||||
paced_sender_ms=0
|
||||
rtmp_demand=0
|
||||
rtsp_demand=0
|
||||
@@ -119,13 +119,14 @@ ts_demand=0
|
||||
|
||||
[record]
|
||||
appName=record
|
||||
enableFmp4=0
|
||||
enableFmp4=1
|
||||
fastStart=0
|
||||
fileBufSize=65536
|
||||
fileRepeat=0
|
||||
sampleMS=500
|
||||
|
||||
[rtc]
|
||||
bfilter=0
|
||||
datachannel_echo=0
|
||||
externIP=
|
||||
maxRtpCacheMS=5000
|
||||
@@ -150,7 +151,7 @@ directProxy=1
|
||||
enhanced=0
|
||||
handshakeSecond=15
|
||||
keepAliveSecond=15
|
||||
port=10935
|
||||
port=10001
|
||||
sslport=0
|
||||
|
||||
[rtp]
|
||||
@@ -165,8 +166,9 @@ dumpDir=
|
||||
gop_cache=1
|
||||
h264_pt=98
|
||||
h265_pt=99
|
||||
merge_frame=1
|
||||
opus_pt=100
|
||||
port=10000
|
||||
port=10003
|
||||
port_range=30000-30500
|
||||
ps_pt=96
|
||||
rtp_g711_dur_ms=100
|
||||
@@ -179,7 +181,7 @@ directProxy=1
|
||||
handshakeSecond=15
|
||||
keepAliveSecond=15
|
||||
lowLatency=0
|
||||
port=5540
|
||||
port=10002
|
||||
rtpTransportType=-1
|
||||
sslport=0
|
||||
|
||||
@@ -189,6 +191,7 @@ port=0
|
||||
|
||||
[srt]
|
||||
latencyMul=4
|
||||
passPhrase=
|
||||
pktBufSize=8192
|
||||
port=9000
|
||||
timeoutSec=5
|
||||
|
||||
@@ -1,19 +1,28 @@
|
||||
FROM ubuntu:24.04 AS builder
|
||||
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y nodejs npm && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY ./web /build
|
||||
WORKDIR /build
|
||||
|
||||
RUN npm --registry=https://registry.npmmirror.com install
|
||||
RUN npm run build:prod
|
||||
|
||||
WORKDIR /src/main/resources
|
||||
RUN ls
|
||||
|
||||
WORKDIR /src/main/resources/static
|
||||
RUN ls
|
||||
|
||||
FROM nginx:alpine
|
||||
|
||||
RUN apk add --no-cache bash
|
||||
|
||||
ARG TZ=Asia/Shanghai
|
||||
RUN \
|
||||
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
|
||||
apk update && \
|
||||
apk add tzdata
|
||||
RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \
|
||||
echo '${TZ}' > /etc/timezone
|
||||
|
||||
RUN rm -rf /etc/nginx/conf.d/*
|
||||
RUN mkdir /opt/dist
|
||||
COPY ./dist /opt/dist
|
||||
COPY ./conf/nginx.conf /etc/nginx/conf.d
|
||||
|
||||
COPY --from=builder /src/main/resources/static /opt/dist
|
||||
|
||||
CMD ["nginx","-g","daemon off;"]
|
||||
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#user nobody;
|
||||
worker_processes 1;
|
||||
|
||||
#error_log logs/error.log;
|
||||
#error_log logs/error.log notice;
|
||||
#error_log logs/error.log info;
|
||||
|
||||
#pid logs/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
#keepalive_timeout 0;
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;
|
||||
|
||||
server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
root /opt/dist;
|
||||
index index.html index.htm;
|
||||
}
|
||||
location /record_proxy/{
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header REMOTE-HOST $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass http://polaris-wvp:18978/;
|
||||
}
|
||||
location /api/ {
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header REMOTE-HOST $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass http://polaris-wvp:18978;
|
||||
}
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root html;
|
||||
}
|
||||
}
|
||||
}
|
||||
110
docker/nginx/templates/nginx.conf.template
Normal file
110
docker/nginx/templates/nginx.conf.template
Normal file
@@ -0,0 +1,110 @@
|
||||
server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
root /opt/dist;
|
||||
index index.html index.htm;
|
||||
}
|
||||
location /record_proxy/{
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header REMOTE-HOST $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass http://polaris-wvp:18978/;
|
||||
}
|
||||
location /api/ {
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header REMOTE-HOST $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_pass http://polaris-wvp:18978;
|
||||
|
||||
|
||||
# 从环境变量获取原始主机地址(x.x.x.x)
|
||||
set $original_host ${Stream_IP};
|
||||
|
||||
# 执行字符串替换
|
||||
# 将媒体资源文件替换为Nginx输出的相对地址
|
||||
sub_filter "http://$original_host/index/api/downloadFile" "mediaserver/api/downloadFile";
|
||||
sub_filter "http://$original_host:80/index/api/downloadFile" "mediaserver/api/downloadFile";
|
||||
sub_filter "https://$original_host/index/api/downloadFile" "mediaserver/api/downloadFile";
|
||||
sub_filter "https://$original_host:443/index/api/downloadFile" "mediaserver/api/downloadFile";
|
||||
sub_filter "http://$original_host/mp4_record" "mp4_record";
|
||||
sub_filter "http://$original_host:80/mp4_record" "mp4_record";
|
||||
sub_filter "https://$original_host/mp4_record" "mp4_record";
|
||||
sub_filter "https://$original_host:443/mp4_record" "mp4_record";
|
||||
|
||||
# 设置为off表示替换所有匹配项,而不仅仅是第一个
|
||||
sub_filter_once off;
|
||||
|
||||
# 确保响应被正确处理
|
||||
sub_filter_types application/json; # 只对JSON响应进行处理
|
||||
}
|
||||
|
||||
# 将mediaserver/record转发到目标地址
|
||||
location /mediaserver/api/downloadFile {
|
||||
# 目标服务器地址
|
||||
proxy_pass http://polaris-media:80/index/api/downloadFile;
|
||||
|
||||
# 以下是常用的反向代理设置
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# 超时设置,根据需要调整
|
||||
proxy_connect_timeout 300s;
|
||||
proxy_send_timeout 300s;
|
||||
proxy_read_timeout 300s;
|
||||
}
|
||||
|
||||
# 仅允许代理/rtp/开头的路径
|
||||
location ^~ /rtp/ {
|
||||
# 代理到ZLMediakit服务
|
||||
proxy_pass http://polaris-media:80;
|
||||
|
||||
# 基础HTTP代理配置
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# WebSocket支持配置
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
# 超时设置,根据实际需求调整
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_read_timeout 3600s;
|
||||
proxy_send_timeout 60s;
|
||||
}
|
||||
|
||||
# 仅允许代理/rtp/开头的路径
|
||||
location ^~ /mp4_record/ {
|
||||
# 代理到ZLMediakit服务
|
||||
proxy_pass http://polaris-media:80;
|
||||
|
||||
# 基础HTTP代理配置
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# WebSocket支持配置
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
# 超时设置,根据实际需求调整
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_read_timeout 3600s;
|
||||
proxy_send_timeout 60s;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root html;
|
||||
}
|
||||
}
|
||||
@@ -1,64 +1,84 @@
|
||||
FROM ubuntu:20.04 AS build
|
||||
ARG Platfrom=amd64
|
||||
ARG JDK_NAME
|
||||
FROM ringcentral/jdk:11 AS builder
|
||||
|
||||
EXPOSE 18978/tcp
|
||||
EXPOSE 8116/tcp
|
||||
EXPOSE 8116/udp
|
||||
EXPOSE 8080/tcp
|
||||
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND="noninteractive" \
|
||||
apt-get install -y --no-install-recommends \
|
||||
wget \
|
||||
cmake \
|
||||
maven \
|
||||
git \
|
||||
ca-certificates \
|
||||
tzdata \
|
||||
curl \
|
||||
libpcre3 \
|
||||
libpcre3-dev \
|
||||
zlib1g-dev \
|
||||
openssl \
|
||||
libssl-dev \
|
||||
gdb && \
|
||||
apt-get autoremove -y && \
|
||||
apt-get clean -y && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
#RUN apt-get update && \
|
||||
#DEBIAN_FRONTEND="noninteractive" \
|
||||
#apt-get install -y --no-install-recommends \
|
||||
#wget \
|
||||
#cmake \
|
||||
#maven \
|
||||
#git \
|
||||
#ca-certificates \
|
||||
#tzdata \
|
||||
#curl \
|
||||
#libpcre3 \
|
||||
#libpcre3-dev \
|
||||
#zlib1g-dev \
|
||||
#openssl \
|
||||
#libssl-dev \
|
||||
#gdb && \
|
||||
#apt-get autoremove -y && \
|
||||
#apt-get clean -y && \
|
||||
#rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# install jdk1.8
|
||||
RUN mkdir -p /opt/download
|
||||
WORKDIR /opt/download
|
||||
RUN if [ "$Platfrom" = "arm64" ]; \
|
||||
then \
|
||||
wget https://polaris-tian-generic.pkg.coding.net/qt/autopliot/jdk-8u411-linux-aarch64.tar.gz?version=latest --no-check-certificate -O jdk-8.tar.gz && \
|
||||
tar -zxvf /opt/download/jdk-8.tar.gz -C /usr/local/ --transform 's/jdk1.8.0_411/java/' && \
|
||||
rm /opt/download/jdk-8.tar.gz; \
|
||||
else \
|
||||
wget https://polaris-tian-generic.pkg.coding.net/qt/autopliot/jdk-8u202-linux-x64.tar.gz?version=latest --no-check-certificate -O jdk-8.tar.gz && \
|
||||
tar -zxvf /opt/download/jdk-8.tar.gz -C /usr/local/ --transform 's/jdk1.8.0_202/java/' && \
|
||||
rm /opt/download/jdk-8.tar.gz; \
|
||||
fi
|
||||
## install jdk1.8
|
||||
#RUN mkdir -p /opt/download
|
||||
#WORKDIR /opt/download
|
||||
#RUN if [ "$Platfrom" = "arm64" ]; \
|
||||
#then \
|
||||
#wget https://polaris-tian-generic.pkg.coding.net/qt/autopliot/jdk-8u411-linux-aarch64.tar.gz?version=latest --no-check-certificate -O jdk-8.tar.gz && \
|
||||
#tar -zxvf /opt/download/jdk-8.tar.gz -C /usr/local/ --transform 's/jdk1.8.0_411/java/' && \
|
||||
#rm /opt/download/jdk-8.tar.gz; \
|
||||
#else \
|
||||
#wget https://polaris-tian-generic.pkg.coding.net/qt/autopliot/jdk-8u202-linux-x64.tar.gz?version=latest --no-check-certificate -O jdk-8.tar.gz && \
|
||||
#tar -zxvf /opt/download/jdk-8.tar.gz -C /usr/local/ --transform 's/jdk1.8.0_202/java/' && \
|
||||
#rm /opt/download/jdk-8.tar.gz; \
|
||||
#fi
|
||||
|
||||
ENV JAVA_HOME /usr/local/java/
|
||||
ENV JRE_HOME ${JAVA_HOME}/jre
|
||||
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
|
||||
ENV PATH ${JAVA_HOME}/bin:$PATH
|
||||
#ENV JAVA_HOME /usr/local/java/
|
||||
#ENV JRE_HOME ${JAVA_HOME}/jre
|
||||
#ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
|
||||
#ENV PATH ${JAVA_HOME}/bin:$PATH
|
||||
|
||||
RUN java -version && javac -version
|
||||
|
||||
#RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list.d/debian.sources && \
|
||||
RUN apt-get update && \
|
||||
apt-get install -y maven && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
COPY . /build
|
||||
WORKDIR /build
|
||||
RUN ls && mvn clean package -Dmaven.test.skip=true
|
||||
WORKDIR /build/target
|
||||
RUN mv wvp-pro-*.jar wvp.jar
|
||||
|
||||
|
||||
FROM ringcentral/jdk:11
|
||||
RUN mkdir -p /opt/wvp
|
||||
WORKDIR /opt/wvp
|
||||
COPY ./wvp /opt/wvp
|
||||
|
||||
WORKDIR /home
|
||||
RUN cd /home && \
|
||||
git clone https://gitee.com/pan648540858/wvp-GB28181-pro.git
|
||||
|
||||
RUN cd /home/wvp-GB28181-pro && \
|
||||
mvn clean package -Dmaven.test.skip=true && \
|
||||
cp /home/wvp-GB28181-pro/target/*.jar /opt/wvp/wvp.jar
|
||||
|
||||
WORKDIR /opt/wvp
|
||||
COPY --from=builder /build/target /opt/wvp
|
||||
COPY ./docker/wvp/wvp /opt/wvp
|
||||
ENTRYPOINT ["java", "-Xms512m", "-Xmx1024m", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/opt/ylcx/", "-jar", "wvp.jar", "--spring.config.location=/opt/ylcx/wvp/application.yml"]
|
||||
|
||||
|
||||
|
||||
#RUN mkdir -p /opt/wvp
|
||||
#WORKDIR /opt/wvp
|
||||
#COPY ./wvp /opt/wvp
|
||||
#
|
||||
#WORKDIR /home
|
||||
#RUN cd /home && \
|
||||
#git clone https://gitee.com/pan648540858/wvp-GB28181-pro.git
|
||||
#
|
||||
#RUN cd /home/wvp-GB28181-pro && \
|
||||
#mvn clean package -Dmaven.test.skip=true && \
|
||||
#cp /home/wvp-GB28181-pro/target/*.jar /opt/wvp/wvp.jar
|
||||
#
|
||||
#WORKDIR /opt/wvp
|
||||
#ENTRYPOINT ["java", "-Xms512m", "-Xmx1024m", "-XX:+HeapDumpOnOutOfMemoryError", "-XX:HeapDumpPath=/opt/ylcx/", "-jar", "wvp.jar", "--spring.config.location=/opt/ylcx/wvp/application.yml"]
|
||||
@@ -1,73 +1,107 @@
|
||||
spring:
|
||||
# 设置接口超时时间
|
||||
mvc:
|
||||
async:
|
||||
request-timeout: 20000
|
||||
thymeleaf:
|
||||
cache: false
|
||||
# [可选]上传文件大小限制
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 10MB
|
||||
max-request-size: 100MB
|
||||
# REDIS数据库配置
|
||||
redis:
|
||||
# [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
|
||||
host: ${REDIS_HOST:127.0.0.1}
|
||||
# [必须修改] 端口号
|
||||
port: ${REDIS_PORT:6379}
|
||||
# [可选] 数据库 DB
|
||||
database: 1
|
||||
# [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
|
||||
password:
|
||||
# [可选] 超时时间
|
||||
timeout: 30000
|
||||
# mysql数据源
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://${DATABASE_HOST:127.0.0.1}:${DATABASE_PORT:3306}/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true&allowPublicKeyRetrieval=true
|
||||
username: ${DATABASE_USER:root}
|
||||
password: ${DATABASE_PASSWORD:root}
|
||||
cache:
|
||||
type: redis
|
||||
thymeleaf:
|
||||
cache: false
|
||||
# 设置接口超时时间
|
||||
mvc:
|
||||
async:
|
||||
request-timeout: 20000
|
||||
# [可选]上传文件大小限制
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 10MB
|
||||
max-request-size: 100MB
|
||||
# REDIS数据库配置
|
||||
redis:
|
||||
# [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
|
||||
host: ${REDIS_HOST:127.0.0.1}
|
||||
# [必须修改] 端口号
|
||||
port: ${REDIS_PORT:6379}
|
||||
# [可选] 数据库 DB
|
||||
database: 1
|
||||
# [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
|
||||
password:
|
||||
# [可选] 超时时间
|
||||
timeout: 10000
|
||||
## [可选] 一个pool最多可分配多少个jedis实例
|
||||
#poolMaxTotal: 1000
|
||||
## [可选] 一个pool最多有多少个状态为idle(空闲)的jedis实例
|
||||
#poolMaxIdle: 500
|
||||
## [可选] 最大的等待时间(秒)
|
||||
#poolMaxWait: 5
|
||||
# [必选] jdbc数据库配置
|
||||
datasource:
|
||||
# mysql数据源
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://${DATABASE_HOST:127.0.0.1}:${DATABASE_PORT:3306}/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true&allowPublicKeyRetrieval=true
|
||||
username: ${DATABASE_USER:root}
|
||||
password: ${DATABASE_PASSWORD:root}
|
||||
|
||||
#[可选] 监听的HTTP端口, 网页和接口调用都是这个端口
|
||||
server:
|
||||
port: 18978
|
||||
ssl:
|
||||
# [可选] 是否开启HTTPS访问
|
||||
enabled: false
|
||||
port: 18978
|
||||
ssl:
|
||||
# [可选] 是否开启HTTPS访问
|
||||
# docker里运行,内部不需要HTTPS
|
||||
enabled: false
|
||||
# 作为28181服务器的配置
|
||||
sip:
|
||||
# [必须修改] 本机的IP
|
||||
ip: ${SIP_HOST:127.0.0.1}
|
||||
# [可选]
|
||||
port: 8116
|
||||
# [可选]
|
||||
domain: 3402000000
|
||||
# [可选]
|
||||
id: 34020000002000000001
|
||||
password:
|
||||
alarm: true
|
||||
# [必须修改] 本机的IP,对应你的网卡,监听什么ip就是使用什么网卡,
|
||||
# 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
|
||||
# 如果不明白,就使用0.0.0.0,大部分情况都是可以的
|
||||
# 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
|
||||
ip: 0.0.0.0
|
||||
# [可选] 没有任何业务需求,仅仅是在前端展示的时候用
|
||||
show-ip: ${SIP_ShowIP}
|
||||
# [可选]
|
||||
port: ${SIP_Port:8116}
|
||||
# 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
|
||||
# 后两位为行业编码,定义参照附录D.3
|
||||
# 3701020049标识山东济南历下区 信息行业接入
|
||||
# [可选]
|
||||
domain: ${SIP_Domain:3402000000}
|
||||
# [可选]
|
||||
id: ${SIP_Id:34020000002000000001}
|
||||
# [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验
|
||||
password: ${SIP_Password}
|
||||
# [可选] 国标级联注册失败,再次发起注册的时间间隔。 默认60秒
|
||||
register-time-interval: 60
|
||||
# [可选] 云台控制速度
|
||||
ptz-speed: 50
|
||||
# TODO [可选] 收到心跳后自动上线, 重启服务后会将所有设备置为离线,默认false,等待注册后上线。设置为true则收到心跳设置为上线。
|
||||
# keepalliveToOnline: false
|
||||
# 是否存储alarm信息
|
||||
alarm: true
|
||||
# 命令发送等待回复的超时时间, 单位:毫秒
|
||||
timeout: 1000
|
||||
|
||||
# 默认服务器配置
|
||||
media:
|
||||
id: polaris
|
||||
# [必须修改] ZLM 内网IP与端口
|
||||
ip: ${ZLM_HOST:127.0.0.1}
|
||||
http-port: ${ZLM_PORT:6080}
|
||||
http-port: 80
|
||||
# [可选] 返回流地址时的ip,置空使用 media.ip
|
||||
stream-ip: ${STREAM_HOST:127.0.0.1}
|
||||
stream-ip: ${Stream_IP}
|
||||
# [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
|
||||
sdp-ip: ${SIP_HOST:127.0.0.1}
|
||||
# [可选] Hook IP, 默认使用sip.ip
|
||||
hook-ip: ${SIP_HOST:127.0.0.1}
|
||||
sdp-ip: ${SDP_IP}
|
||||
# [可选] zlm服务器访问WVP所使用的IP, 默认使用127.0.0.1,zlm和wvp没有部署在同一台服务器时必须配置
|
||||
hook-ip: ${ZLM_HOOK_HOST}
|
||||
# [可选] sslport
|
||||
http-ssl-port: 4443
|
||||
rtp-proxy-port: 10000
|
||||
rtmp-port: 10935
|
||||
rtmp-ssl-port: 41935
|
||||
rtsp-port: 5540
|
||||
rtsp-ssl-port: 45540
|
||||
http-ssl-port: 0
|
||||
flv-port: ${MediaHttp:}
|
||||
flv-ssl-port: ${MediaHttps:}
|
||||
ws-flv-port: ${MediaHttp:}
|
||||
ws-flv-ssl-port: ${MediaHttps:}
|
||||
rtp-proxy-port: ${MediaRtp:}
|
||||
rtmp-port: ${MediaRtmp:}
|
||||
rtmp-ssl-port: 0
|
||||
rtsp-port: ${MediaRtsp:}
|
||||
rtsp-ssl-port: 0
|
||||
# [可选] 是否自动配置ZLM, 如果希望手动配置ZLM, 可以设为false, 不建议新接触的用户修改
|
||||
auto-config: true
|
||||
# [可选]
|
||||
secret: ${ZLM_SERCERT}
|
||||
# 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
|
||||
@@ -79,28 +113,28 @@ media:
|
||||
# [可选]
|
||||
send-port-range: 50502,50506
|
||||
|
||||
record-path: /opt/media/record
|
||||
record-path: /opt/media/bin/www/record/
|
||||
record-day: 7
|
||||
record-assist-port: 0
|
||||
user-settings:
|
||||
auto-apply-play: true
|
||||
play-timeout: 30000
|
||||
wait-track: false
|
||||
record-push-live: false
|
||||
record-sip: false
|
||||
record-push-live: ${RecordPushLive:false}
|
||||
record-sip: ${RecordSip:false}
|
||||
stream-on-demand: true
|
||||
interface-authentication: false
|
||||
interface-authentication: true
|
||||
broadcast-for-platform: TCP-PASSIVE
|
||||
push-stream-after-ack: true
|
||||
send-to-platforms-when-id-lost: true
|
||||
interface-authentication-excludes:
|
||||
- /api/**
|
||||
push-authority: false
|
||||
allowed-origins:
|
||||
- http://localhost:8080
|
||||
- http://127.0.0.1:8080
|
||||
- http://0.0.0.0:8080
|
||||
- ${NGINX_HOST}
|
||||
# - /api/**
|
||||
push-authority: true
|
||||
# allowed-origins:
|
||||
# - http://localhost:8080
|
||||
# - http://127.0.0.1:8080
|
||||
# - http://0.0.0.0:8080
|
||||
# - ${NGINX_HOST}
|
||||
logging:
|
||||
config: classpath:logback-spring.xml
|
||||
|
||||
|
||||
22
pom.xml
22
pom.xml
@@ -364,6 +364,27 @@
|
||||
<version>32.1.3-jre</version>
|
||||
</dependency>
|
||||
|
||||
<!--ftp server-->
|
||||
<dependency>
|
||||
<groupId>org.apache.ftpserver</groupId>
|
||||
<artifactId>ftpserver-core</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.ftpserver</groupId>
|
||||
<artifactId>ftplet-api</artifactId>
|
||||
<version>1.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 自动化生成代码工具 -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 自动化生成代码工具 -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
@@ -383,6 +404,7 @@
|
||||
<artifactId>log-viewer-spring-boot</artifactId>
|
||||
<version>1.0.10</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
||||
@@ -79,6 +79,8 @@ public class StreamInfo implements Serializable, Cloneable{
|
||||
private String startTime;
|
||||
@Schema(description = "结束时间")
|
||||
private String endTime;
|
||||
@Schema(description = "时长(回放时使用)")
|
||||
private Double duration;
|
||||
@Schema(description = "进度(录像下载使用)")
|
||||
private double progress;
|
||||
@Schema(description = "文件下载地址(录像下载使用)")
|
||||
@@ -101,87 +103,112 @@ public class StreamInfo implements Serializable, Cloneable{
|
||||
@Schema(description = "使用的WVP ID")
|
||||
private String serverId;
|
||||
|
||||
public void setRtmp(String host, int port, int sslPort, String app, String stream, String callIdParam) {
|
||||
@Schema(description = "流绑定的流媒体操作key")
|
||||
private String key;
|
||||
|
||||
public void setRtmp(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam) {
|
||||
String file = String.format("%s/%s%s", app, stream, callIdParam);
|
||||
if (port > 0) {
|
||||
if (port != null && port > 0) {
|
||||
this.rtmp = new StreamURL("rtmp", host, port, file);
|
||||
}
|
||||
if (sslPort > 0) {
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.rtmps = new StreamURL("rtmps", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setRtsp(String host, int port, int sslPort, String app, String stream, String callIdParam) {
|
||||
public void setRtsp(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam) {
|
||||
String file = String.format("%s/%s%s", app, stream, callIdParam);
|
||||
if (port > 0) {
|
||||
if (port != null && port > 0) {
|
||||
this.rtsp = new StreamURL("rtsp", host, port, file);
|
||||
}
|
||||
if (sslPort > 0) {
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.rtsps = new StreamURL("rtsps", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFlv(String host, int port, int sslPort, String file) {
|
||||
if (port > 0) {
|
||||
public void setFlv(String host, Integer port, Integer sslPort, String file) {
|
||||
if (port != null && port > 0) {
|
||||
this.flv = new StreamURL("http", host, port, file);
|
||||
}
|
||||
this.ws_flv = new StreamURL("ws", host, port, file);
|
||||
if (sslPort > 0) {
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.https_flv = new StreamURL("https", host, sslPort, file);
|
||||
this.wss_flv = new StreamURL("wss", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setWsFlv(String host, int port, int sslPort, String file) {
|
||||
if (port > 0) {
|
||||
public void setWsFlv(String host, Integer port, Integer sslPort, String file) {
|
||||
if (port != null && port > 0) {
|
||||
this.ws_flv = new StreamURL("ws", host, port, file);
|
||||
}
|
||||
if (sslPort > 0) {
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.wss_flv = new StreamURL("wss", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setFmp4(String host, int port, int sslPort, String app, String stream, String callIdParam) {
|
||||
String file = String.format("%s/%s.live.mp4%s", app, stream, callIdParam);
|
||||
if (port > 0) {
|
||||
public void setFmp4(String host, Integer port, Integer sslPort, String file) {
|
||||
if (port != null && port > 0) {
|
||||
this.fmp4 = new StreamURL("http", host, port, file);
|
||||
}
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.https_fmp4 = new StreamURL("https", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setWsMp4(String host, Integer port, Integer sslPort, String file) {
|
||||
if (port != null && port > 0) {
|
||||
this.ws_fmp4 = new StreamURL("ws", host, port, file);
|
||||
}
|
||||
if (sslPort > 0) {
|
||||
this.https_fmp4 = new StreamURL("https", host, sslPort, file);
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.wss_fmp4 = new StreamURL("wss", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setHls(String host, int port, int sslPort, String app, String stream, String callIdParam) {
|
||||
public void setHls(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam) {
|
||||
String file = String.format("%s/%s/hls.m3u8%s", app, stream, callIdParam);
|
||||
if (port > 0) {
|
||||
if (port != null && port > 0) {
|
||||
this.hls = new StreamURL("http", host, port, file);
|
||||
}
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.https_hls = new StreamURL("https", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setWsHls(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam) {
|
||||
String file = String.format("%s/%s/hls.m3u8%s", app, stream, callIdParam);
|
||||
if (port != null && port > 0) {
|
||||
this.ws_hls = new StreamURL("ws", host, port, file);
|
||||
}
|
||||
if (sslPort > 0) {
|
||||
this.https_hls = new StreamURL("https", host, sslPort, file);
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.wss_hls = new StreamURL("wss", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setTs(String host, int port, int sslPort, String app, String stream, String callIdParam) {
|
||||
public void setTs(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam) {
|
||||
String file = String.format("%s/%s.live.ts%s", app, stream, callIdParam);
|
||||
|
||||
if (port > 0) {
|
||||
if (port != null && port > 0) {
|
||||
this.ts = new StreamURL("http", host, port, file);
|
||||
}
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.https_ts = new StreamURL("https", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setWsTs(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam) {
|
||||
String file = String.format("%s/%s.live.ts%s", app, stream, callIdParam);
|
||||
|
||||
if (port != null && port > 0) {
|
||||
this.ws_ts = new StreamURL("ws", host, port, file);
|
||||
}
|
||||
if (sslPort > 0) {
|
||||
this.https_ts = new StreamURL("https", host, sslPort, file);
|
||||
if (sslPort != null && sslPort > 0) {
|
||||
this.wss_ts = new StreamURL("wss", host, sslPort, file);
|
||||
}
|
||||
}
|
||||
|
||||
public void setRtc(String host, int port, int sslPort, String app, String stream, String callIdParam, boolean isPlay) {
|
||||
public void setRtc(String host, Integer port, Integer sslPort, String app, String stream, String callIdParam, boolean isPlay) {
|
||||
if (callIdParam != null) {
|
||||
callIdParam = Objects.equals(callIdParam, "") ? callIdParam : callIdParam.replace("?", "&");
|
||||
}
|
||||
// String file = String.format("%s/%s?type=%s%s", app, stream, isPlay?"play":"push", callIdParam);
|
||||
String file = String.format("index/api/webrtc?app=%s&stream=%s&type=%s%s", app, stream, isPlay?"play":"push", callIdParam);
|
||||
if (port > 0) {
|
||||
this.rtc = new StreamURL("http", host, port, file);
|
||||
|
||||
@@ -153,4 +153,15 @@ public class VideoManagerConstants {
|
||||
*/
|
||||
public static final String REDIS_RECORD_INFO_RES_COUNT_PRE = "GB_RECORD_INFO_RES_COUNT:";
|
||||
|
||||
//************************** 1078 ****************************************
|
||||
|
||||
|
||||
public static final String INVITE_INFO_1078_POSITION = "INVITE_INFO_1078_POSITION:";
|
||||
public static final String INVITE_INFO_1078_PLAY = "INVITE_INFO_1078_PLAY:";
|
||||
public static final String INVITE_INFO_1078_PLAYBACK = "INVITE_INFO_1078_PLAYBACK:";
|
||||
public static final String INVITE_INFO_1078_TALK = "INVITE_INFO_1078_TALK:";
|
||||
|
||||
|
||||
public static final String RECORD_LIST_1078 = "RECORD_LIST_1078:";
|
||||
|
||||
}
|
||||
|
||||
@@ -4,18 +4,18 @@ package com.genersoft.iot.vmp.common.enums;
|
||||
* 支持的通道数据类型
|
||||
*/
|
||||
|
||||
public enum ChannelDataType {
|
||||
public class ChannelDataType {
|
||||
|
||||
GB28181(1,"国标28181"),
|
||||
STREAM_PUSH(2,"推流设备"),
|
||||
STREAM_PROXY(3,"拉流代理");
|
||||
public final static int GB28181 = 1;
|
||||
public final static int STREAM_PUSH = 2;
|
||||
public final static int STREAM_PROXY = 3;
|
||||
public final static int JT_1078 = 200;
|
||||
|
||||
public final static String PLAY_SERVICE = "sourceChannelPlayService";
|
||||
public final static String PLAYBACK_SERVICE = "sourceChannelPlaybackService";
|
||||
public final static String DOWNLOAD_SERVICE = "sourceChannelDownloadService";
|
||||
public final static String PTZ_SERVICE = "sourceChannelPTZService";
|
||||
|
||||
public final int value;
|
||||
|
||||
public final String desc;
|
||||
|
||||
ChannelDataType(Integer value, String desc) {
|
||||
this.value = value;
|
||||
this.desc = desc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import com.genersoft.iot.vmp.media.bean.MediaServer;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -15,6 +16,7 @@ import java.util.regex.Pattern;
|
||||
@Slf4j
|
||||
@Configuration("mediaConfig")
|
||||
@Order(0)
|
||||
@Data
|
||||
public class MediaConfig{
|
||||
|
||||
// 修改必须配置,不再支持自动获取
|
||||
@@ -45,6 +47,9 @@ public class MediaConfig{
|
||||
@Value("${media.flv-port:0}")
|
||||
private Integer flvPort = 0;
|
||||
|
||||
@Value("${media.mp4-port:0}")
|
||||
private Integer mp4Port = 0;
|
||||
|
||||
@Value("${media.ws-flv-port:0}")
|
||||
private Integer wsFlvPort = 0;
|
||||
|
||||
@@ -66,6 +71,9 @@ public class MediaConfig{
|
||||
@Value("${media.rtp-proxy-port:0}")
|
||||
private Integer rtpProxyPort = 0;
|
||||
|
||||
@Value("${media.jtt-proxy-port:0}")
|
||||
private Integer jttProxyPort = 0;
|
||||
|
||||
@Value("${media.rtsp-port:0}")
|
||||
private Integer rtspPort = 0;
|
||||
|
||||
@@ -99,33 +107,7 @@ public class MediaConfig{
|
||||
@Value("${media.type:zlm}")
|
||||
private String type;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public String getHookIp() {
|
||||
return hookIp;
|
||||
}
|
||||
|
||||
public int getHttpPort() {
|
||||
return httpPort;
|
||||
}
|
||||
|
||||
public int getHttpSSlPort() {
|
||||
return httpSSlPort;
|
||||
}
|
||||
|
||||
public int getRtmpPort() {
|
||||
return rtmpPort;
|
||||
}
|
||||
|
||||
public int getRtmpSSlPort() {
|
||||
return rtmpSSlPort;
|
||||
}
|
||||
|
||||
public int getRtpProxyPort() {
|
||||
if (rtpProxyPort == null) {
|
||||
@@ -136,32 +118,12 @@ public class MediaConfig{
|
||||
|
||||
}
|
||||
|
||||
public int getRtspPort() {
|
||||
return rtspPort;
|
||||
}
|
||||
|
||||
public int getRtspSSLPort() {
|
||||
return rtspSSLPort;
|
||||
}
|
||||
|
||||
public boolean isAutoConfig() {
|
||||
return autoConfig;
|
||||
}
|
||||
|
||||
public String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
public boolean isRtpEnable() {
|
||||
return rtpEnable;
|
||||
}
|
||||
|
||||
public String getRtpPortRange() {
|
||||
return rtpPortRange;
|
||||
}
|
||||
|
||||
public int getRecordAssistPort() {
|
||||
return recordAssistPort;
|
||||
public Integer getJttProxyPort() {
|
||||
if (jttProxyPort == null) {
|
||||
return 0;
|
||||
}else {
|
||||
return jttProxyPort;
|
||||
}
|
||||
}
|
||||
|
||||
public String getSdpIp() {
|
||||
@@ -191,10 +153,6 @@ public class MediaConfig{
|
||||
}
|
||||
}
|
||||
|
||||
public String getSipDomain() {
|
||||
return sipDomain;
|
||||
}
|
||||
|
||||
public MediaServer getMediaSerItem(){
|
||||
MediaServer mediaServer = new MediaServer();
|
||||
mediaServer.setId(id);
|
||||
@@ -204,31 +162,17 @@ public class MediaConfig{
|
||||
mediaServer.setSdpIp(getSdpIp());
|
||||
mediaServer.setStreamIp(getStreamIp());
|
||||
mediaServer.setHttpPort(httpPort);
|
||||
if (flvPort == 0) {
|
||||
mediaServer.setFlvPort(httpPort);
|
||||
}else {
|
||||
mediaServer.setFlvPort(flvPort);
|
||||
}
|
||||
if (wsFlvPort == 0) {
|
||||
mediaServer.setWsFlvPort(httpPort);
|
||||
}else {
|
||||
mediaServer.setWsFlvPort(wsFlvPort);
|
||||
}
|
||||
if (flvSSlPort == 0) {
|
||||
mediaServer.setFlvSSLPort(httpSSlPort);
|
||||
}else {
|
||||
mediaServer.setFlvSSLPort(flvSSlPort);
|
||||
}
|
||||
if (wsFlvSSlPort == 0) {
|
||||
mediaServer.setWsFlvSSLPort(httpSSlPort);
|
||||
}else {
|
||||
mediaServer.setWsFlvSSLPort(wsFlvSSlPort);
|
||||
}
|
||||
mediaServer.setFlvPort(flvPort);
|
||||
mediaServer.setMp4Port(mp4Port);
|
||||
mediaServer.setWsFlvPort(wsFlvPort);
|
||||
mediaServer.setFlvSSLPort(flvSSlPort);
|
||||
mediaServer.setWsFlvSSLPort(wsFlvSSlPort);
|
||||
|
||||
mediaServer.setHttpSSlPort(httpSSlPort);
|
||||
mediaServer.setRtmpPort(rtmpPort);
|
||||
mediaServer.setRtmpSSlPort(rtmpSSlPort);
|
||||
mediaServer.setRtpProxyPort(getRtpProxyPort());
|
||||
mediaServer.setJttProxyPort(getJttProxyPort());
|
||||
mediaServer.setRtspPort(rtspPort);
|
||||
mediaServer.setRtspSSLPort(rtspSSLPort);
|
||||
mediaServer.setAutoConfig(autoConfig);
|
||||
@@ -250,42 +194,10 @@ public class MediaConfig{
|
||||
return mediaServer;
|
||||
}
|
||||
|
||||
public Integer getRecordDay() {
|
||||
return recordDay;
|
||||
}
|
||||
|
||||
public void setRecordDay(Integer recordDay) {
|
||||
this.recordDay = recordDay;
|
||||
}
|
||||
|
||||
public String getRecordPath() {
|
||||
return recordPath;
|
||||
}
|
||||
|
||||
public void setRecordPath(String recordPath) {
|
||||
this.recordPath = recordPath;
|
||||
}
|
||||
|
||||
public String getRtpSendPortRange() {
|
||||
return rtpSendPortRange;
|
||||
}
|
||||
|
||||
public void setRtpSendPortRange(String rtpSendPortRange) {
|
||||
this.rtpSendPortRange = rtpSendPortRange;
|
||||
}
|
||||
|
||||
private boolean isValidIPAddress(String ipAddress) {
|
||||
if ((ipAddress != null) && (!ipAddress.isEmpty())) {
|
||||
return Pattern.matches("^([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$", ipAddress);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getWanIp() {
|
||||
return wanIp;
|
||||
}
|
||||
|
||||
public void setWanIp(String wanIp) {
|
||||
this.wanIp = wanIp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.web.context.WebServerInitializedEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
@@ -9,17 +10,14 @@ import org.springframework.stereotype.Component;
|
||||
@Component
|
||||
public class ServiceInfo implements ApplicationListener<WebServerInitializedEvent> {
|
||||
|
||||
@Getter
|
||||
private static int serverPort;
|
||||
|
||||
public static int getServerPort() {
|
||||
return serverPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(WebServerInitializedEvent event) {
|
||||
// 项目启动获取启动的端口号
|
||||
ServiceInfo.serverPort = event.getWebServer().getPort();
|
||||
log.info("项目启动获取启动的端口号: " + ServiceInfo.serverPort);
|
||||
log.info("项目启动获取启动的端口号: {}", ServiceInfo.serverPort);
|
||||
}
|
||||
|
||||
public void setServerPort(int serverPort) {
|
||||
|
||||
@@ -98,4 +98,12 @@ public class SpringDocConfig {
|
||||
.packagesToScan("com.genersoft.iot.vmp.user")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi publicApi7() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("6. 部标设备")
|
||||
.packagesToScan("com.genersoft.iot.vmp.jt1078.controller")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,6 +204,9 @@ public class UserSetting {
|
||||
*/
|
||||
private boolean sipCacheServerConnections = true;
|
||||
|
||||
|
||||
/**
|
||||
* 禁用date头,变相禁用了校时
|
||||
*/
|
||||
private boolean disableDateHeader = false;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
public interface FileCallback {
|
||||
|
||||
OutputStream run(String path);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import org.apache.ftpserver.ftplet.Authority;
|
||||
import org.apache.ftpserver.ftplet.AuthorizationRequest;
|
||||
|
||||
public class FtpAuthority implements Authority {
|
||||
|
||||
@Override
|
||||
public boolean canAuthorize(AuthorizationRequest authorizationRequest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthorizationRequest authorize(AuthorizationRequest authorizationRequest) {
|
||||
return authorizationRequest;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import org.apache.ftpserver.ftplet.FileSystemFactory;
|
||||
import org.apache.ftpserver.ftplet.FileSystemView;
|
||||
import org.apache.ftpserver.ftplet.FtpException;
|
||||
import org.apache.ftpserver.ftplet.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Component
|
||||
public class FtpFileSystemFactory implements FileSystemFactory {
|
||||
|
||||
private final Map<String, OutputStream> outputStreamMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public FileSystemView createFileSystemView(User user) throws FtpException {
|
||||
return new FtpFileSystemView(user, path -> {
|
||||
return outputStreamMap.get(path);
|
||||
});
|
||||
}
|
||||
|
||||
public void addOutputStream(String filePath, OutputStream outputStream) {
|
||||
outputStreamMap.put(filePath, outputStream);
|
||||
}
|
||||
|
||||
public void removeOutputStream(String filePath) {
|
||||
outputStreamMap.remove(filePath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import org.apache.ftpserver.ftplet.FileSystemView;
|
||||
import org.apache.ftpserver.ftplet.FtpException;
|
||||
import org.apache.ftpserver.ftplet.FtpFile;
|
||||
import org.apache.ftpserver.ftplet.User;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class FtpFileSystemView implements FileSystemView {
|
||||
|
||||
private User user;
|
||||
|
||||
private FileCallback fileCallback;
|
||||
|
||||
public FtpFileSystemView(User user, FileCallback fileCallback) {
|
||||
this.user = user;
|
||||
this.fileCallback = fileCallback;
|
||||
}
|
||||
|
||||
public static String HOME_PATH = "root";
|
||||
|
||||
public FtpFile workDir = VirtualFtpFile.getDir(HOME_PATH);
|
||||
|
||||
@Override
|
||||
public FtpFile getHomeDirectory() throws FtpException {
|
||||
return VirtualFtpFile.getDir(HOME_PATH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FtpFile getWorkingDirectory() throws FtpException {
|
||||
return workDir;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean changeWorkingDirectory(String dir) throws FtpException {
|
||||
workDir = VirtualFtpFile.getDir(dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FtpFile getFile(String file) throws FtpException {
|
||||
VirtualFtpFile ftpFile = VirtualFtpFile.getFile(file);
|
||||
if (fileCallback != null) {
|
||||
OutputStream outputStream = fileCallback.run(workDir.getName());
|
||||
if (outputStream != null) {
|
||||
ftpFile.setOutputStream(outputStream);
|
||||
}
|
||||
}
|
||||
return ftpFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRandomAccessible() throws FtpException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ftpserver.*;
|
||||
import org.apache.ftpserver.ftplet.FtpException;
|
||||
import org.apache.ftpserver.listener.Listener;
|
||||
import org.apache.ftpserver.listener.ListenerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "ftp.enable", havingValue = "true")
|
||||
@Slf4j
|
||||
public class FtpServerConfig {
|
||||
|
||||
@Autowired
|
||||
private UserManager userManager;
|
||||
|
||||
@Autowired
|
||||
private FtpFileSystemFactory fileSystemFactory;
|
||||
|
||||
@Autowired
|
||||
private Ftplet ftplet;
|
||||
|
||||
@Autowired
|
||||
private FtpSetting ftpSetting;
|
||||
|
||||
/**
|
||||
* ftp server init
|
||||
*/
|
||||
@Bean
|
||||
public FtpServer ftpServer() {
|
||||
FtpServerFactory serverFactory = new FtpServerFactory();
|
||||
ListenerFactory listenerFactory = new ListenerFactory();
|
||||
// 1、设置服务端口
|
||||
listenerFactory.setPort(ftpSetting.getPort());
|
||||
// 2、设置被动模式数据上传的接口范围,云服务器需要开放对应区间的端口给客户端
|
||||
DataConnectionConfigurationFactory dataConnectionConfFactory = new DataConnectionConfigurationFactory();
|
||||
dataConnectionConfFactory.setPassivePorts(ftpSetting.getPassivePorts());
|
||||
listenerFactory.setDataConnectionConfiguration(dataConnectionConfFactory.createDataConnectionConfiguration());
|
||||
// 4、替换默认的监听器
|
||||
Listener listener = listenerFactory.createListener();
|
||||
serverFactory.addListener("default", listener);
|
||||
// 5、配置自定义用户事件
|
||||
Map<String, org.apache.ftpserver.ftplet.Ftplet> ftpLets = new HashMap<>();
|
||||
ftpLets.put("ftpService", ftplet);
|
||||
serverFactory.setFtplets(ftpLets);
|
||||
// 6、读取用户的配置信息
|
||||
// 6.2、设置用信息
|
||||
serverFactory.setUserManager(userManager);
|
||||
serverFactory.setFileSystem(fileSystemFactory);
|
||||
// 7、实例化FTP Server
|
||||
FtpServer server = serverFactory.createServer();
|
||||
try {
|
||||
server.start();
|
||||
if (!server.isStopped()) {
|
||||
log.info("[FTP服务] 已启动, 端口: {}", ftpSetting.getPort());
|
||||
}
|
||||
} catch (FtpException e) {
|
||||
log.info("[FTP服务] 启动失败 ", e);
|
||||
}
|
||||
return server;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 配置文件 user-settings 映射的配置信息
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "ftp", ignoreInvalidFields = true)
|
||||
@Order(0)
|
||||
@Data
|
||||
public class FtpSetting {
|
||||
|
||||
private Boolean enable = Boolean.FALSE;
|
||||
|
||||
private int port = 21;
|
||||
private String passivePorts = "10000-10500";
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import com.genersoft.iot.vmp.jt1078.event.FtpUploadEvent;
|
||||
import org.apache.ftpserver.ftplet.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
@Component
|
||||
public class Ftplet extends DefaultFtplet {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(Ftplet.class);
|
||||
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
@Override
|
||||
public FtpletResult onUploadEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
|
||||
FtpFile file = session.getFileSystemView().getFile(request.getArgument());
|
||||
if (file == null) {
|
||||
return super.onUploadEnd(session, request);
|
||||
}
|
||||
sendEvent(file.getAbsolutePath());
|
||||
return super.onUploadUniqueEnd(session, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FtpletResult onAppendEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
|
||||
FtpFile file = session.getFileSystemView().getFile(request.getArgument());
|
||||
if (file == null) {
|
||||
return super.onUploadEnd(session, request);
|
||||
}
|
||||
sendEvent(file.getAbsolutePath());
|
||||
return super.onUploadUniqueEnd(session, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FtpletResult onUploadUniqueEnd(FtpSession session, FtpRequest request) throws FtpException, IOException {
|
||||
FtpFile file = session.getFileSystemView().getFile(request.getArgument());
|
||||
if (file == null) {
|
||||
return super.onUploadEnd(session, request);
|
||||
}
|
||||
sendEvent(file.getAbsolutePath());
|
||||
return super.onUploadUniqueEnd(session, request);
|
||||
}
|
||||
|
||||
private void sendEvent(String filePath){
|
||||
FtpUploadEvent event = new FtpUploadEvent(this);
|
||||
logger.info("[文件已上传]: {}", filePath);
|
||||
event.setFileName(filePath);
|
||||
applicationEventPublisher.publishEvent(event);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.ftpserver.ftplet.*;
|
||||
import org.apache.ftpserver.usermanager.UsernamePasswordAuthentication;
|
||||
import org.apache.ftpserver.usermanager.impl.BaseUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class UserManager implements org.apache.ftpserver.ftplet.UserManager {
|
||||
|
||||
private static final String PREFIX = "VMP_FTP_USER_";
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<Object, Object> redisTemplate;
|
||||
|
||||
|
||||
@Override
|
||||
public User getUserByName(String username) throws FtpException {
|
||||
return (BaseUser)redisTemplate.opsForValue().get(PREFIX + username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAllUserNames() throws FtpException {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String username) throws FtpException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(User user) throws FtpException {}
|
||||
|
||||
@Override
|
||||
public boolean doesExist(String username) throws FtpException {
|
||||
return redisTemplate.opsForValue().get(PREFIX + username) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User authenticate(Authentication authentication) throws AuthenticationFailedException {
|
||||
UsernamePasswordAuthentication usernamePasswordAuthentication = (UsernamePasswordAuthentication) authentication;
|
||||
BaseUser user = (BaseUser)redisTemplate.opsForValue().get(PREFIX + usernamePasswordAuthentication.getUsername());
|
||||
if (user != null && usernamePasswordAuthentication.getPassword().equals(user.getPassword())) {
|
||||
return user;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAdminName() throws FtpException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdmin(String username) throws FtpException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public BaseUser getRandomUser(){
|
||||
BaseUser use = new BaseUser();
|
||||
use.setName(RandomStringUtils.randomAlphabetic(6).toLowerCase());
|
||||
use.setPassword(RandomStringUtils.randomAlphabetic(6).toLowerCase());
|
||||
use.setEnabled(true);
|
||||
use.setHomeDirectory("/");
|
||||
List<Authority> authorities = new ArrayList<>();
|
||||
authorities.add(new FtpAuthority());
|
||||
use.setAuthorities(authorities);
|
||||
String key = PREFIX + use.getName();
|
||||
|
||||
// 随机用户信息十分钟自动失效
|
||||
Duration duration = Duration.ofMinutes(10);
|
||||
redisTemplate.opsForValue().set(key, use, duration);
|
||||
return use;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package com.genersoft.iot.vmp.conf.ftpServer;
|
||||
|
||||
import lombok.Setter;
|
||||
import org.apache.ftpserver.ftplet.FtpFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class VirtualFtpFile implements FtpFile {
|
||||
|
||||
@Setter
|
||||
private String name;
|
||||
|
||||
@Setter
|
||||
private boolean hidden = false;
|
||||
|
||||
@Setter
|
||||
private boolean directory = false;
|
||||
|
||||
@Setter
|
||||
private String ownerName;
|
||||
|
||||
private Long lastModified = null;
|
||||
|
||||
@Setter
|
||||
private long size = 0;
|
||||
|
||||
@Setter
|
||||
private OutputStream outputStream;
|
||||
|
||||
public static VirtualFtpFile getFile(String name) {
|
||||
VirtualFtpFile virtualFtpFile = new VirtualFtpFile();
|
||||
virtualFtpFile.setName(name);
|
||||
return virtualFtpFile;
|
||||
}
|
||||
|
||||
public static VirtualFtpFile getDir(String name) {
|
||||
if (name.endsWith("/")) {
|
||||
name = name.replaceAll("/", "");
|
||||
}
|
||||
VirtualFtpFile virtualFtpFile = new VirtualFtpFile();
|
||||
virtualFtpFile.setName(name);
|
||||
virtualFtpFile.setDirectory(true);
|
||||
return virtualFtpFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAbsolutePath() {
|
||||
return FtpFileSystemView.HOME_PATH + "/" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden() {
|
||||
return hidden;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFile() {
|
||||
return !directory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesExist() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWritable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRemovable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOwnerName() {
|
||||
return ownerName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupName() {
|
||||
return "root";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLinkCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastModified() {
|
||||
if (lastModified == null) {
|
||||
lastModified = System.currentTimeMillis();
|
||||
}
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setLastModified(long time) {
|
||||
lastModified = time;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getPhysicalFile() {
|
||||
System.err.println("getPhysicalFile");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mkdir() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean move(FtpFile destination) {
|
||||
this.name = destination.getName();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<? extends FtpFile> listFiles() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream createOutputStream(long offset) throws IOException {
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream createInputStream(long offset) throws IOException {
|
||||
System.out.println("createInputStream----");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -236,7 +236,7 @@ public class JwtUtils implements InitializingBean {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON);
|
||||
} else {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
|
||||
}
|
||||
|
||||
@@ -99,6 +99,8 @@ public class WebSecurityConfig {
|
||||
defaultExcludes.add("/index/hook/**");
|
||||
defaultExcludes.add("/api/device/query/snap/**");
|
||||
defaultExcludes.add("/index/hook/abl/**");
|
||||
defaultExcludes.add("/api/jt1078/playback/download");
|
||||
defaultExcludes.add("/api/jt1078/snap");
|
||||
|
||||
if (userSetting.getInterfaceAuthentication() && !userSetting.getInterfaceAuthenticationExcludes().isEmpty()) {
|
||||
defaultExcludes.addAll(userSetting.getInterfaceAuthenticationExcludes());
|
||||
|
||||
@@ -150,6 +150,9 @@ public class CommonGBChannel {
|
||||
@Schema(description = "更新时间")
|
||||
private String updateTime;
|
||||
|
||||
@Schema(description = "流唯一编号,存在表示正在直播")
|
||||
private String streamId;
|
||||
|
||||
public String encode(String serverDeviceId) {
|
||||
return encode(null, serverDeviceId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class CommonRecordInfo {
|
||||
|
||||
// 开始时间
|
||||
private String startTime;
|
||||
|
||||
// 结束时间
|
||||
private String endTime;
|
||||
|
||||
// 文件大小 单位byte
|
||||
private String fileSize;
|
||||
|
||||
}
|
||||
@@ -21,6 +21,12 @@ public class DeviceChannel extends CommonGBChannel {
|
||||
@Schema(description = "数据库自增ID")
|
||||
private int id;
|
||||
|
||||
@Schema(description = "父设备编码")
|
||||
private String parentDeviceId;
|
||||
|
||||
@Schema(description = "父设备名称")
|
||||
private String parentName;
|
||||
|
||||
@MessageElementForCatalog("DeviceID")
|
||||
@Schema(description = "编码")
|
||||
private String deviceId;
|
||||
@@ -173,9 +179,6 @@ public class DeviceChannel extends CommonGBChannel {
|
||||
@Schema(description = "子设备数")
|
||||
private int subCount;
|
||||
|
||||
@Schema(description = "流唯一编号,存在表示正在直播")
|
||||
private String streamId;
|
||||
|
||||
@Schema(description = "是否含有音频")
|
||||
private boolean hasAudio;
|
||||
|
||||
@@ -189,7 +192,7 @@ public class DeviceChannel extends CommonGBChannel {
|
||||
@Schema(description = "通道类型, 默认0, 0: 普通通道,1 行政区划 2 业务分组/虚拟组织")
|
||||
private int channelType;
|
||||
|
||||
private Integer dataType = ChannelDataType.GB28181.value;
|
||||
private Integer dataType = ChannelDataType.GB28181;
|
||||
|
||||
public void setPtzType(int ptzType) {
|
||||
this.ptzType = ptzType;
|
||||
@@ -249,7 +252,7 @@ public class DeviceChannel extends CommonGBChannel {
|
||||
commonGBChannel.setGbId(id);
|
||||
commonGBChannel.setGbDeviceId(deviceId);
|
||||
commonGBChannel.setGbName(name);
|
||||
commonGBChannel.setDataType(ChannelDataType.GB28181.value);
|
||||
commonGBChannel.setDataType(ChannelDataType.GB28181);
|
||||
commonGBChannel.setDataDeviceId(getDataDeviceId());
|
||||
return commonGBChannel;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ public class FrontEndControlCodeForAuxiliary implements IFrontEndControlCode {
|
||||
}
|
||||
|
||||
/**
|
||||
* 辅助开关控制指令: 1为开, 2为关, 3为设置自动扫描右边界, 4为设置自动扫描速度
|
||||
* 辅助开关控制指令: 1为开, 2为关
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
|
||||
@@ -27,6 +27,13 @@ public class FrontEndControlCodeForPreset implements IFrontEndControlCode {
|
||||
@Setter
|
||||
private Integer presetId;
|
||||
|
||||
/**
|
||||
* 预置位名称
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private String presetName;
|
||||
|
||||
|
||||
@Override
|
||||
public String encode() {
|
||||
|
||||
@@ -14,7 +14,7 @@ public class FrontEndControlCodeForScan implements IFrontEndControlCode {
|
||||
}
|
||||
|
||||
/**
|
||||
* 预置位指令: 1为开始自动扫描, 2为设置自动扫描左边界, 3为设置自动扫描右边界, 4为设置自动扫描速度
|
||||
* 预置位指令: 1为开始自动扫描, 2为设置自动扫描左边界, 3为设置自动扫描右边界, 4为设置自动扫描速度, 5为停止自动扫描
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
|
||||
@@ -14,7 +14,7 @@ public class FrontEndControlCodeForTour implements IFrontEndControlCode {
|
||||
}
|
||||
|
||||
/**
|
||||
* 巡航指令: 1为加入巡航点, 2为删除一个巡航点, 3为设置巡航速度, 4为设置巡航停留时间, 5为开始巡航
|
||||
* 巡航指令: 1为加入巡航点, 2为删除一个巡航点, 3为设置巡航速度, 4为设置巡航停留时间, 5为开始巡航, 6为停止巡航
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
public class FrontEndControlCodeForWiper implements IFrontEndControlCode {
|
||||
|
||||
private final FrontEndControlType type = FrontEndControlType.AUXILIARY;
|
||||
|
||||
@Override
|
||||
public FrontEndControlType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 辅助开关控制指令: 1为开, 2为关
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private Integer code;
|
||||
|
||||
@Override
|
||||
public String encode() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.dom4j.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Delayed;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class MessageResponseTask<T> implements Delayed {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private Element element;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private List<T> data;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String key;
|
||||
|
||||
|
||||
/**
|
||||
* 超时时间(单位: 毫秒)
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
private long delayTime;
|
||||
|
||||
@Override
|
||||
public long getDelay(@NotNull TimeUnit unit) {
|
||||
return unit.convert(delayTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull Delayed o) {
|
||||
return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
@@ -11,6 +13,8 @@ import java.util.List;
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月8日 下午2:05:56
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@Schema(description = "设备录像查询结果信息")
|
||||
public class RecordInfo {
|
||||
|
||||
@@ -36,67 +40,4 @@ public class RecordInfo {
|
||||
@Schema(description = "")
|
||||
private List<RecordItem> recordList;
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getSumNum() {
|
||||
return sumNum;
|
||||
}
|
||||
|
||||
public void setSumNum(int sumNum) {
|
||||
this.sumNum = sumNum;
|
||||
}
|
||||
|
||||
public List<RecordItem> getRecordList() {
|
||||
return recordList;
|
||||
}
|
||||
|
||||
public void setRecordList(List<RecordItem> recordList) {
|
||||
this.recordList = recordList;
|
||||
}
|
||||
|
||||
public String getChannelId() {
|
||||
return channelId;
|
||||
}
|
||||
|
||||
public void setChannelId(String channelId) {
|
||||
this.channelId = channelId;
|
||||
}
|
||||
|
||||
public String getSn() {
|
||||
return sn;
|
||||
}
|
||||
|
||||
public void setSn(String sn) {
|
||||
this.sn = sn;
|
||||
}
|
||||
|
||||
public Instant getLastTime() {
|
||||
return lastTime;
|
||||
}
|
||||
|
||||
public void setLastTime(Instant lastTime) {
|
||||
this.lastTime = lastTime;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -13,6 +15,8 @@ import java.time.temporal.TemporalAccessor;
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月8日 下午2:06:54
|
||||
*/
|
||||
@Setter
|
||||
@Getter
|
||||
@Schema(description = "设备录像详情")
|
||||
public class RecordItem implements Comparable<RecordItem>{
|
||||
|
||||
@@ -40,93 +44,13 @@ public class RecordItem implements Comparable<RecordItem>{
|
||||
@Schema(description = "保密属性(必选)缺省为0;0:不涉密,1:涉密")
|
||||
private int secrecy;
|
||||
|
||||
@Schema(description = "录像产生类型(可选)time或alarm 或 manua")
|
||||
@Schema(description = "录像产生类型(可选)time或alarm 或 manual")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "录像触发者ID(可选)")
|
||||
private String recorderId;
|
||||
|
||||
public String getDeviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
public void setDeviceId(String deviceId) {
|
||||
this.deviceId = deviceId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getFilePath() {
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public void setFilePath(String filePath) {
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public String getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setStartTime(String startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public String getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public void setEndTime(String endTime) {
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public int getSecrecy() {
|
||||
return secrecy;
|
||||
}
|
||||
|
||||
public void setSecrecy(int secrecy) {
|
||||
this.secrecy = secrecy;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getRecorderId() {
|
||||
return recorderId;
|
||||
}
|
||||
|
||||
public void setRecorderId(String recorderId) {
|
||||
this.recorderId = recorderId;
|
||||
}
|
||||
|
||||
public String getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public void setFileSize(String fileSize) {
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Override
|
||||
public int compareTo(@NotNull RecordItem recordItem) {
|
||||
TemporalAccessor startTimeNow = DateUtil.formatter.parse(startTime);
|
||||
TemporalAccessor startTimeParam = DateUtil.formatter.parse(recordItem.getStartTime());
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SipSendFailEvent extends SipSubscribe.EventResult<String> {
|
||||
|
||||
private String callId;
|
||||
|
||||
private String msg;
|
||||
|
||||
public static SipSendFailEvent getInstance(String callId, String msg){
|
||||
SipSendFailEvent sipSendFailEvent = new SipSendFailEvent();
|
||||
sipSendFailEvent.setMsg(msg);
|
||||
sipSendFailEvent.setCallId(callId);
|
||||
return sipSendFailEvent;
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,9 @@ package com.genersoft.iot.vmp.gb28181.controller;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.conf.security.JwtUtils;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceType;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.IndustryCodeType;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.NetworkIdentificationType;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelToGroupByGbDeviceParam;
|
||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelToGroupParam;
|
||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelToRegionByGbDeviceParam;
|
||||
@@ -17,6 +15,8 @@ import com.genersoft.iot.vmp.media.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
@@ -35,13 +35,14 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
@Tag(name = "全局通道管理")
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping(value = "/api/common/channel")
|
||||
public class CommonChannelController {
|
||||
public class ChannelController {
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
@@ -276,7 +277,94 @@ public class CommonChannelController {
|
||||
|
||||
@Operation(summary = "播放通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@GetMapping("/play")
|
||||
public DeferredResult<WVPResult<StreamContent>> deleteChannelToGroupByGbDevice(HttpServletRequest request, Integer channelId){
|
||||
public DeferredResult<WVPResult<StreamContent>> play(HttpServletRequest request, Integer channelId){
|
||||
Assert.notNull(channelId,"参数异常");
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
|
||||
DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
|
||||
|
||||
ErrorCallback<StreamInfo> callback = (code, msg, streamInfo) -> {
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()) {
|
||||
WVPResult<StreamContent> wvpResult = WVPResult.success();
|
||||
if (streamInfo != null) {
|
||||
if (userSetting.getUseSourceIpAsStreamIp()) {
|
||||
streamInfo=streamInfo.clone();//深拷贝
|
||||
String host;
|
||||
try {
|
||||
URL url=new URL(request.getRequestURL().toString());
|
||||
host=url.getHost();
|
||||
} catch (MalformedURLException e) {
|
||||
host=request.getLocalAddr();
|
||||
}
|
||||
streamInfo.changeStreamIp(host);
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(streamInfo.getMediaServer().getTranscodeSuffix())
|
||||
&& !"null".equalsIgnoreCase(streamInfo.getMediaServer().getTranscodeSuffix())) {
|
||||
streamInfo.setStream(streamInfo.getStream() + "_" + streamInfo.getMediaServer().getTranscodeSuffix());
|
||||
}
|
||||
wvpResult.setData(new StreamContent(streamInfo));
|
||||
}else {
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
}
|
||||
result.setResult(wvpResult);
|
||||
}else {
|
||||
result.setResult(WVPResult.fail(code, msg));
|
||||
}
|
||||
};
|
||||
channelPlayService.play(channel, null, userSetting.getRecordSip(), callback);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Operation(summary = "停止播放通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@GetMapping("/play/stop")
|
||||
public void stopPlay(Integer channelId){
|
||||
Assert.notNull(channelId,"参数异常");
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
channelPlayService.stopPlay(channel, channel.getStreamId());
|
||||
}
|
||||
|
||||
@Operation(summary = "录像查询", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||
@Parameter(name = "startTime", description = "开始时间", required = true)
|
||||
@Parameter(name = "endTime", description = "结束时间", required = true)
|
||||
@GetMapping("/playback/query")
|
||||
public DeferredResult<WVPResult<List<CommonRecordInfo>>> queryRecord(Integer channelId, String startTime, String endTime){
|
||||
|
||||
DeferredResult<WVPResult<List<CommonRecordInfo>>> result = new DeferredResult<>(Long.valueOf(userSetting.getRecordInfoTimeout()), TimeUnit.MILLISECONDS);
|
||||
if (!DateUtil.verification(startTime, DateUtil.formatter)){
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "startTime格式为" + DateUtil.PATTERN);
|
||||
}
|
||||
if (!DateUtil.verification(endTime, DateUtil.formatter)){
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "endTime格式为" + DateUtil.PATTERN);
|
||||
}
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
|
||||
channelPlayService.queryRecord(channel, startTime, endTime, (code, msg, data) -> {
|
||||
WVPResult<List<CommonRecordInfo>> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
wvpResult.setData(data);
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
result.onTimeout(()->{
|
||||
WVPResult<List<CommonRecordInfo>> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(ErrorCode.ERROR100.getCode());
|
||||
wvpResult.setMsg("timeout");
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@Operation(summary = "录像回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||
@Parameter(name = "startTime", description = "开始时间", required = true)
|
||||
@Parameter(name = "endTime", description = "结束时间", required = true)
|
||||
@GetMapping("/playback")
|
||||
public DeferredResult<WVPResult<StreamContent>> playback(HttpServletRequest request, Integer channelId, String startTime, String endTime){
|
||||
Assert.notNull(channelId,"参数异常");
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
@@ -313,7 +401,67 @@ public class CommonChannelController {
|
||||
result.setResult(WVPResult.fail(code, msg));
|
||||
}
|
||||
};
|
||||
channelPlayService.play(channel, null, userSetting.getRecordSip(), callback);
|
||||
channelPlayService.playback(channel, DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime),
|
||||
DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime), callback);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Operation(summary = "停止录像回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||
@Parameter(name = "stream", description = "流ID", required = true)
|
||||
@GetMapping("/playback/stop")
|
||||
public void stopPlayback(Integer channelId, String stream){
|
||||
Assert.notNull(channelId,"参数异常");
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
channelPlayService.stopPlayback(channel, stream);
|
||||
}
|
||||
|
||||
@Operation(summary = "暂停录像回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||
@Parameter(name = "stream", description = "流ID", required = true)
|
||||
@GetMapping("/playback/pause")
|
||||
public void pausePlayback(Integer channelId, String stream){
|
||||
Assert.notNull(channelId,"参数异常");
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
channelPlayService.playbackPause(channel, stream);
|
||||
}
|
||||
|
||||
@Operation(summary = "恢复录像回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||
@Parameter(name = "stream", description = "流ID", required = true)
|
||||
@GetMapping("/playback/resume")
|
||||
public void resumePlayback(Integer channelId, String stream){
|
||||
Assert.notNull(channelId,"参数异常");
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
channelPlayService.playbackResume(channel, stream);
|
||||
}
|
||||
|
||||
@Operation(summary = "拖动录像回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||
@Parameter(name = "stream", description = "流ID", required = true)
|
||||
@Parameter(name = "seekTime", description = "将要播放的时间", required = true)
|
||||
@GetMapping("/playback/seek")
|
||||
public void seekPlayback(Integer channelId, String stream, Long seekTime){
|
||||
Assert.notNull(channelId,"参数异常");
|
||||
Assert.notNull(seekTime,"参数异常");
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
channelPlayService.playbackSeek(channel, stream, seekTime);
|
||||
}
|
||||
|
||||
@Operation(summary = "拖动录像回放", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||
@Parameter(name = "stream", description = "流ID", required = true)
|
||||
@Parameter(name = "speed", description = "倍速", required = true)
|
||||
@GetMapping("/playback/speed")
|
||||
public void seekPlayback(Integer channelId, String stream, Double speed){
|
||||
Assert.notNull(channelId,"参数异常");
|
||||
Assert.notNull(speed,"参数异常");
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
channelPlayService.playbackSpeed(channel, stream, speed);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,601 @@
|
||||
package com.genersoft.iot.vmp.gb28181.controller;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.conf.security.JwtUtils;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelControlService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Tag(name = "全局通道前端控制")
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping(value = "/api/common/channel/front-end")
|
||||
public class ChannelFrontEndController {
|
||||
|
||||
@Autowired
|
||||
private IGbChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private IGbChannelControlService channelControlService;
|
||||
|
||||
|
||||
@Operation(summary = "云台控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||
@Parameter(name = "command", description = "控制指令,允许值: left, right, up, down, upleft, upright, downleft, downright, zoomin, zoomout, stop", required = true)
|
||||
@Parameter(name = "panSpeed", description = "水平速度(0-100)", required = true)
|
||||
@Parameter(name = "tiltSpeed", description = "垂直速度(0-100)", required = true)
|
||||
@Parameter(name = "zoomSpeed", description = "缩放速度(0-100)", required = true)
|
||||
@GetMapping("/ptz")
|
||||
public DeferredResult<WVPResult<String>> ptz(Integer channelId, String command, Integer panSpeed, Integer tiltSpeed, Integer zoomSpeed){
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[通用通道]云台控制 API调用,channelId:{} ,command:{} ,panSpeed:{} ,tiltSpeed:{} ,zoomSpeed:{}",channelId, command, panSpeed, tiltSpeed, zoomSpeed);
|
||||
}
|
||||
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
|
||||
if (panSpeed == null) {
|
||||
panSpeed = 50;
|
||||
}else if (panSpeed < 0 || panSpeed > 100) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "panSpeed 为 0-100的数字");
|
||||
}
|
||||
if (tiltSpeed == null) {
|
||||
tiltSpeed = 50;
|
||||
}else if (tiltSpeed < 0 || tiltSpeed > 100) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "tiltSpeed 为 0-100的数字");
|
||||
}
|
||||
if (zoomSpeed == null) {
|
||||
zoomSpeed = 50;
|
||||
}else if (zoomSpeed < 0 || zoomSpeed > 100) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "zoomSpeed 为 0-100的数字");
|
||||
}
|
||||
|
||||
FrontEndControlCodeForPTZ controlCode = new FrontEndControlCodeForPTZ();
|
||||
controlCode.setPanSpeed(panSpeed);
|
||||
controlCode.setTiltSpeed(tiltSpeed);
|
||||
controlCode.setZoomSpeed(zoomSpeed);
|
||||
switch (command){
|
||||
case "left":
|
||||
controlCode.setPan(0);
|
||||
break;
|
||||
case "right":
|
||||
controlCode.setPan(1);
|
||||
break;
|
||||
case "up":
|
||||
controlCode.setTilt(0);
|
||||
break;
|
||||
case "down":
|
||||
controlCode.setTilt(1);
|
||||
break;
|
||||
case "upleft":
|
||||
controlCode.setPan(0);
|
||||
controlCode.setTilt(0);
|
||||
break;
|
||||
case "upright":
|
||||
controlCode.setTilt(0);
|
||||
controlCode.setPan(1);
|
||||
break;
|
||||
case "downleft":
|
||||
controlCode.setPan(0);
|
||||
controlCode.setTilt(1);
|
||||
break;
|
||||
case "downright":
|
||||
controlCode.setTilt(1);
|
||||
controlCode.setPan(1);
|
||||
break;
|
||||
case "zoomin":
|
||||
controlCode.setZoom(1);
|
||||
break;
|
||||
case "zoomout":
|
||||
controlCode.setZoom(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DeferredResult<WVPResult<String>> result = new DeferredResult<>();
|
||||
|
||||
result.onTimeout(()->{
|
||||
WVPResult<String> wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "请求超时");
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
|
||||
channelControlService.ptz(channel, controlCode, (code, msg, data) -> {
|
||||
WVPResult<String> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
wvpResult.setData(data);
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "光圈控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "command", description = "控制指令,允许值: in, out, stop", required = true)
|
||||
@Parameter(name = "speed", description = "光圈速度(0-100)", required = true)
|
||||
@GetMapping("/fi/iris")
|
||||
public DeferredResult<WVPResult<String>> iris(Integer channelId, String command, Integer speed){
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[通用通道]光圈控制 API调用,channelId:{} ,command:{} ,speed:{} ",channelId, command, speed);
|
||||
}
|
||||
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
|
||||
if (speed == null) {
|
||||
speed = 50;
|
||||
}else if (speed < 0 || speed > 100) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "speed 为 0-100的数字");
|
||||
}
|
||||
|
||||
FrontEndControlCodeForFI controlCode = new FrontEndControlCodeForFI();
|
||||
controlCode.setIrisSpeed(speed);
|
||||
|
||||
switch (command){
|
||||
case "in":
|
||||
controlCode.setIris(1);
|
||||
break;
|
||||
case "out":
|
||||
controlCode.setIris(0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DeferredResult<WVPResult<String>> result = new DeferredResult<>();
|
||||
|
||||
result.onTimeout(()->{
|
||||
WVPResult<String> wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "请求超时");
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
|
||||
ErrorCallback<String> callback = (code, msg, data) -> {
|
||||
WVPResult<String> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
wvpResult.setData(data);
|
||||
result.setResult(wvpResult);
|
||||
};
|
||||
|
||||
channelControlService.fi(channel, controlCode, callback);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Operation(summary = "聚焦控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "command", description = "控制指令,允许值: near, far, stop", required = true)
|
||||
@Parameter(name = "speed", description = "聚焦速度(0-100)", required = true)
|
||||
@GetMapping("/fi/focus")
|
||||
public DeferredResult<WVPResult<String>> focus(Integer channelId, String command, Integer speed){
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[通用通道]聚焦控制 API调用,channelId:{} ,command:{} ,speed:{} ", channelId, command, speed);
|
||||
}
|
||||
|
||||
if (speed == null) {
|
||||
speed = 50;
|
||||
}else if (speed < 0 || speed > 100) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "speed 为 0-100的数字");
|
||||
}
|
||||
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
|
||||
FrontEndControlCodeForFI controlCode = new FrontEndControlCodeForFI();
|
||||
controlCode.setFocusSpeed(speed);
|
||||
switch (command){
|
||||
case "near":
|
||||
controlCode.setFocus(0);
|
||||
break;
|
||||
case "far":
|
||||
controlCode.setFocus(1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DeferredResult<WVPResult<String>> result = new DeferredResult<>();
|
||||
|
||||
result.onTimeout(()->{
|
||||
WVPResult<String> wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "请求超时");
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
|
||||
ErrorCallback<String> callback = (code, msg, data) -> {
|
||||
WVPResult<String> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
wvpResult.setData(data);
|
||||
result.setResult(wvpResult);
|
||||
};
|
||||
|
||||
channelControlService.fi(channel, controlCode, callback);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Operation(summary = "查询预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@GetMapping("/preset/query")
|
||||
public DeferredResult<WVPResult<List<Preset>>> queryPreset(Integer channelId) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[通用通道] 预置位查询API调用, {}", channelId);
|
||||
}
|
||||
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
|
||||
DeferredResult<WVPResult<List<Preset>>> result = new DeferredResult<>();
|
||||
|
||||
result.onTimeout(()->{
|
||||
WVPResult<List<Preset>> wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "请求超时");
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
|
||||
ErrorCallback<List<Preset>> callback = (code, msg, data) -> {
|
||||
WVPResult<List<Preset>> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
wvpResult.setData(data);
|
||||
result.setResult(wvpResult);
|
||||
};
|
||||
|
||||
channelControlService.queryPreset(channel, callback);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private DeferredResult<WVPResult<String>> controlPreset(Integer channelId, FrontEndControlCodeForPreset controlCode) {
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
|
||||
|
||||
DeferredResult<WVPResult<String>> result = new DeferredResult<>();
|
||||
|
||||
result.onTimeout(()->{
|
||||
WVPResult<String> wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "请求超时");
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
|
||||
ErrorCallback<String> callback = (code, msg, data) -> {
|
||||
WVPResult<String> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
wvpResult.setData(data);
|
||||
result.setResult(wvpResult);
|
||||
};
|
||||
|
||||
channelControlService.preset(channel, controlCode, callback);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Operation(summary = "预置位指令-设置预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "presetId", description = "预置位编号", required = true)
|
||||
@Parameter(name = "presetName", description = "预置位名称", required = true)
|
||||
@GetMapping("/preset/add")
|
||||
public DeferredResult<WVPResult<String>> addPreset(Integer channelId, Integer presetId, String presetName) {
|
||||
FrontEndControlCodeForPreset controlCode = new FrontEndControlCodeForPreset();
|
||||
controlCode.setCode(1);
|
||||
controlCode.setPresetId(presetId);
|
||||
controlCode.setPresetName(presetName);
|
||||
|
||||
return controlPreset(channelId, controlCode);
|
||||
}
|
||||
|
||||
@Operation(summary = "预置位指令-调用预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "presetId", description = "预置位编号(1-100)", required = true)
|
||||
@GetMapping("/preset/call")
|
||||
public DeferredResult<WVPResult<String>> callPreset(Integer channelId, Integer presetId) {
|
||||
FrontEndControlCodeForPreset controlCode = new FrontEndControlCodeForPreset();
|
||||
controlCode.setCode(2);
|
||||
controlCode.setPresetId(presetId);
|
||||
|
||||
return controlPreset(channelId, controlCode);
|
||||
}
|
||||
|
||||
@Operation(summary = "预置位指令-删除预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "presetId", description = "预置位编号(1-100)", required = true)
|
||||
@GetMapping("/preset/delete")
|
||||
public DeferredResult<WVPResult<String>> deletePreset(Integer channelId, Integer presetId) {
|
||||
|
||||
FrontEndControlCodeForPreset controlCode = new FrontEndControlCodeForPreset();
|
||||
controlCode.setCode(3);
|
||||
controlCode.setPresetId(presetId);
|
||||
|
||||
return controlPreset(channelId, controlCode);
|
||||
}
|
||||
|
||||
private DeferredResult<WVPResult<String>> tourControl(Integer channelId, FrontEndControlCodeForTour controlCode) {
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
|
||||
DeferredResult<WVPResult<String>> result = new DeferredResult<>();
|
||||
|
||||
result.onTimeout(()->{
|
||||
WVPResult<String> wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "请求超时");
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
|
||||
ErrorCallback<String> callback = (code, msg, data) -> {
|
||||
WVPResult<String> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
wvpResult.setData(data);
|
||||
result.setResult(wvpResult);
|
||||
};
|
||||
|
||||
channelControlService.tour(channel, controlCode, callback);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Operation(summary = "巡航指令-加入巡航点", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "tourId", description = "巡航组号", required = true)
|
||||
@Parameter(name = "presetId", description = "预置位编号", required = true)
|
||||
@GetMapping("/tour/point/add")
|
||||
public DeferredResult<WVPResult<String>> addTourPoint(Integer channelId, Integer tourId, Integer presetId) {
|
||||
|
||||
FrontEndControlCodeForTour controlCode = new FrontEndControlCodeForTour();
|
||||
controlCode.setCode(1);
|
||||
controlCode.setPresetId(presetId);
|
||||
controlCode.setTourId(tourId);
|
||||
|
||||
return tourControl(channelId, controlCode);
|
||||
}
|
||||
|
||||
@Operation(summary = "巡航指令-删除一个巡航点", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "tourId", description = "巡航组号(1-100)", required = true)
|
||||
@Parameter(name = "presetId", description = "预置位编号(0-100, 为0时删除整个巡航)", required = true)
|
||||
@GetMapping("/tour/point/delete")
|
||||
public DeferredResult<WVPResult<String>> deleteCruisePoint(Integer channelId, Integer tourId, Integer presetId) {
|
||||
FrontEndControlCodeForTour controlCode = new FrontEndControlCodeForTour();
|
||||
controlCode.setCode(2);
|
||||
controlCode.setPresetId(presetId);
|
||||
controlCode.setTourId(tourId);
|
||||
|
||||
return tourControl(channelId, controlCode);
|
||||
}
|
||||
|
||||
@Operation(summary = "巡航指令-设置巡航速度", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "tourId", description = "巡航组号(0-100)", required = true)
|
||||
@Parameter(name = "speed", description = "巡航速度(1-4095)", required = true)
|
||||
@Parameter(name = "presetId", description = "预置位编号", required = true)
|
||||
@GetMapping("/tour/speed")
|
||||
public DeferredResult<WVPResult<String>> setCruiseSpeed(Integer channelId, Integer tourId, Integer speed, Integer presetId) {
|
||||
FrontEndControlCodeForTour controlCode = new FrontEndControlCodeForTour();
|
||||
controlCode.setCode(3);
|
||||
controlCode.setTourSpeed(speed);
|
||||
controlCode.setTourId(tourId);
|
||||
controlCode.setPresetId(presetId);
|
||||
return tourControl(channelId, controlCode);
|
||||
}
|
||||
|
||||
@Operation(summary = "巡航指令-设置巡航停留时间", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "tourId", description = "巡航组号", required = true)
|
||||
@Parameter(name = "time", description = "巡航停留时间(1-4095)", required = true)
|
||||
@Parameter(name = "presetId", description = "预置位编号", required = true)
|
||||
@GetMapping("/tour/time")
|
||||
public DeferredResult<WVPResult<String>> setCruiseTime(Integer channelId, Integer tourId, Integer time, Integer presetId) {
|
||||
FrontEndControlCodeForTour controlCode = new FrontEndControlCodeForTour();
|
||||
controlCode.setCode(4);
|
||||
controlCode.setTourTime(time);
|
||||
controlCode.setTourId(tourId);
|
||||
controlCode.setPresetId(presetId);
|
||||
return tourControl(channelId, controlCode);
|
||||
}
|
||||
|
||||
@Operation(summary = "巡航指令-开始巡航", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "tourId", description = "巡航组号)", required = true)
|
||||
@GetMapping("/tour/start")
|
||||
public DeferredResult<WVPResult<String>> startCruise(Integer channelId, Integer tourId) {
|
||||
FrontEndControlCodeForTour controlCode = new FrontEndControlCodeForTour();
|
||||
controlCode.setCode(5);
|
||||
controlCode.setTourId(tourId);
|
||||
return tourControl(channelId, controlCode);
|
||||
}
|
||||
|
||||
@Operation(summary = "巡航指令-停止巡航", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "tourId", description = "巡航组号", required = true)
|
||||
@GetMapping("/tour/stop")
|
||||
public DeferredResult<WVPResult<String>> stopCruise(Integer channelId, Integer tourId) {
|
||||
FrontEndControlCodeForTour controlCode = new FrontEndControlCodeForTour();
|
||||
controlCode.setCode(6);
|
||||
controlCode.setTourId(tourId);
|
||||
return tourControl(channelId, controlCode);
|
||||
}
|
||||
|
||||
private DeferredResult<WVPResult<String>> scanControl(Integer channelId, FrontEndControlCodeForScan controlCode) {
|
||||
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
DeferredResult<WVPResult<String>> result = new DeferredResult<>();
|
||||
|
||||
result.onTimeout(()->{
|
||||
WVPResult<String> wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "请求超时");
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
|
||||
ErrorCallback<String> callback = (code, msg, data) -> {
|
||||
WVPResult<String> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
wvpResult.setData(data);
|
||||
result.setResult(wvpResult);
|
||||
};
|
||||
channelControlService.scan(channel, controlCode, callback);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
@Operation(summary = "扫描指令-开始自动扫描", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "scanId", description = "扫描组号(0-100)", required = true)
|
||||
@GetMapping("/scan/start")
|
||||
public DeferredResult<WVPResult<String>> startScan(Integer channelId, Integer scanId) {
|
||||
FrontEndControlCodeForScan controlCode = new FrontEndControlCodeForScan();
|
||||
controlCode.setCode(1);
|
||||
controlCode.setScanId(scanId);
|
||||
return scanControl(channelId, controlCode);
|
||||
|
||||
}
|
||||
|
||||
@Operation(summary = "扫描指令-停止自动扫描", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "scanId", description = "扫描组号(0-100)", required = true)
|
||||
@GetMapping("/scan/stop")
|
||||
public DeferredResult<WVPResult<String>> stopScan(Integer channelId, Integer scanId) {
|
||||
FrontEndControlCodeForScan controlCode = new FrontEndControlCodeForScan();
|
||||
controlCode.setCode(5);
|
||||
controlCode.setScanId(scanId);
|
||||
return scanControl(channelId, controlCode);
|
||||
}
|
||||
|
||||
@Operation(summary = "扫描指令-设置自动扫描左边界", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "scanId", description = "扫描组号(0-100)", required = true)
|
||||
@GetMapping("/scan/set/left")
|
||||
public DeferredResult<WVPResult<String>> setScanLeft(Integer channelId, Integer scanId) {
|
||||
FrontEndControlCodeForScan controlCode = new FrontEndControlCodeForScan();
|
||||
controlCode.setCode(2);
|
||||
controlCode.setScanId(scanId);
|
||||
return scanControl(channelId, controlCode);
|
||||
}
|
||||
|
||||
@Operation(summary = "扫描指令-设置自动扫描右边界", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "scanId", description = "扫描组号(0-100)", required = true)
|
||||
@GetMapping("/scan/set/right")
|
||||
public DeferredResult<WVPResult<String>> setScanRight(Integer channelId, Integer scanId) {
|
||||
FrontEndControlCodeForScan controlCode = new FrontEndControlCodeForScan();
|
||||
controlCode.setCode(3);
|
||||
controlCode.setScanId(scanId);
|
||||
return scanControl(channelId, controlCode);
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "扫描指令-设置自动扫描速度", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "scanId", description = "扫描组号(0-100)", required = true)
|
||||
@Parameter(name = "speed", description = "自动扫描速度(1-4095)", required = true)
|
||||
@GetMapping("/scan/set/speed")
|
||||
public DeferredResult<WVPResult<String>> setScanSpeed(Integer channelId, Integer scanId, Integer speed) {
|
||||
FrontEndControlCodeForScan controlCode = new FrontEndControlCodeForScan();
|
||||
controlCode.setCode(4);
|
||||
controlCode.setScanId(scanId);
|
||||
controlCode.setScanSpeed(speed);
|
||||
return scanControl(channelId, controlCode);
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "辅助开关控制指令-雨刷控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "command", description = "控制指令,允许值: on, off", required = true)
|
||||
@GetMapping("/wiper")
|
||||
public DeferredResult<WVPResult<String>> wiper(Integer channelId, String command){
|
||||
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
|
||||
FrontEndControlCodeForWiper controlCode = new FrontEndControlCodeForWiper();
|
||||
|
||||
switch (command){
|
||||
case "on":
|
||||
controlCode.setCode(1);
|
||||
break;
|
||||
case "off":
|
||||
controlCode.setCode(2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DeferredResult<WVPResult<String>> result = new DeferredResult<>();
|
||||
|
||||
result.onTimeout(()->{
|
||||
WVPResult<String> wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "请求超时");
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
|
||||
ErrorCallback<String> callback = (code, msg, data) -> {
|
||||
WVPResult<String> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
wvpResult.setData(data);
|
||||
result.setResult(wvpResult);
|
||||
};
|
||||
|
||||
channelControlService.wiper(channel, controlCode, callback);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Operation(summary = "辅助开关控制指令", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "command", description = "控制指令,允许值: on, off", required = true)
|
||||
@Parameter(name = "auxiliaryId", description = "开关编号", required = true)
|
||||
@GetMapping("/auxiliary")
|
||||
public DeferredResult<WVPResult<String>> auxiliarySwitch(Integer channelId, String command, Integer auxiliaryId){
|
||||
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
|
||||
FrontEndControlCodeForAuxiliary controlCode = new FrontEndControlCodeForAuxiliary();
|
||||
controlCode.setAuxiliaryId(auxiliaryId);
|
||||
switch (command){
|
||||
case "on":
|
||||
controlCode.setCode(1);
|
||||
break;
|
||||
case "off":
|
||||
controlCode.setCode(2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DeferredResult<WVPResult<String>> result = new DeferredResult<>();
|
||||
|
||||
result.onTimeout(()->{
|
||||
WVPResult<String> wvpResult = WVPResult.fail(ErrorCode.ERROR100.getCode(), "请求超时");
|
||||
result.setResult(wvpResult);
|
||||
});
|
||||
|
||||
ErrorCallback<String> callback = (code, msg, data) -> {
|
||||
WVPResult<String> wvpResult = new WVPResult<>();
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
wvpResult.setData(data);
|
||||
result.setResult(wvpResult);
|
||||
};
|
||||
channelControlService.auxiliary(channel, controlCode, callback);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -70,16 +70,16 @@ public class DeviceControl {
|
||||
|
||||
@Operation(summary = "布防/撤防", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "guardCmdStr", description = "命令, 可选值:SetGuard(布防),ResetGuard(撤防)", required = true)
|
||||
@Parameter(name = "guardCmd", description = "命令, 可选值:SetGuard(布防),ResetGuard(撤防)", required = true)
|
||||
@GetMapping("/guard")
|
||||
public DeferredResult<WVPResult<String>> guardApi(String deviceId, String guardCmdStr) {
|
||||
public DeferredResult<WVPResult<String>> guardApi(String deviceId, String guardCmd) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("布防/撤防API调用");
|
||||
}
|
||||
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
||||
Assert.notNull(device, "设备不存在");
|
||||
DeferredResult<WVPResult<String>> result = new DeferredResult<>();
|
||||
deviceService.guard(device, guardCmdStr, (code, msg, data) -> {
|
||||
deviceService.guard(device, guardCmd, (code, msg, data) -> {
|
||||
result.setResult(new WVPResult<>(code, msg, data));
|
||||
});
|
||||
result.onTimeout(() -> {
|
||||
|
||||
@@ -113,6 +113,19 @@ public class DeviceQuery {
|
||||
return deviceChannelService.queryChannelsByDeviceId(deviceId, query, channelType, online, page, count);
|
||||
}
|
||||
|
||||
@GetMapping("/streams")
|
||||
@Operation(summary = "分页查询存在流的通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "page", description = "当前页", required = true)
|
||||
@Parameter(name = "count", description = "每页查询数量", required = true)
|
||||
@Parameter(name = "query", description = "查询内容")
|
||||
public PageInfo<DeviceChannel> streamChannels(int page, int count,
|
||||
@RequestParam(required = false) String query) {
|
||||
if (ObjectUtils.isEmpty(query)) {
|
||||
query = null;
|
||||
}
|
||||
|
||||
return deviceChannelService.queryChannels(query, true, null, null, true, page, count);
|
||||
}
|
||||
|
||||
@Operation(summary = "同步设备通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Group;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.GroupTree;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IGroupService;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -33,7 +34,7 @@ public class GroupController {
|
||||
groupService.add(group);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询分组")
|
||||
@Operation(summary = "查询分组节点")
|
||||
@Parameter(name = "query", description = "要搜索的内容", required = true)
|
||||
@Parameter(name = "parent", description = "所属分组编号", required = true)
|
||||
@ResponseBody
|
||||
@@ -49,6 +50,17 @@ public class GroupController {
|
||||
return groupService.queryForTree(query, parent, hasChannel);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询分组")
|
||||
@Parameter(name = "query", description = "要搜索的内容", required = true)
|
||||
@Parameter(name = "channel", description = "true为查询通道,false为查询节点", required = true)
|
||||
@ResponseBody
|
||||
@GetMapping("/tree/query")
|
||||
public PageInfo<Group> queryTree(Integer page, Integer count,
|
||||
@RequestParam(required = true) String query
|
||||
){
|
||||
return groupService.queryList(page, count, query);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新分组")
|
||||
@Parameter(name = "group", description = "Group", required = true)
|
||||
@ResponseBody
|
||||
|
||||
@@ -7,19 +7,26 @@ import com.genersoft.iot.vmp.conf.security.SecurityUtils;
|
||||
import com.genersoft.iot.vmp.conf.security.dto.LoginUser;
|
||||
import com.genersoft.iot.vmp.media.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.streamProxy.service.IStreamProxyService;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
|
||||
@Tag(name = "媒体流相关")
|
||||
@@ -52,11 +59,12 @@ public class MediaController {
|
||||
@Parameter(name = "useSourceIpAsStreamIp", description = "是否使用请求IP作为返回的地址IP")
|
||||
@GetMapping(value = "/stream_info_by_app_and_stream")
|
||||
@ResponseBody
|
||||
public StreamContent getStreamInfoByAppAndStream(HttpServletRequest request, @RequestParam String app,
|
||||
@RequestParam String stream,
|
||||
@RequestParam(required = false) String mediaServerId,
|
||||
@RequestParam(required = false) String callId,
|
||||
@RequestParam(required = false) Boolean useSourceIpAsStreamIp){
|
||||
public DeferredResult<WVPResult<StreamContent>> getStreamInfoByAppAndStream(HttpServletRequest request, @RequestParam String app,
|
||||
@RequestParam String stream,
|
||||
@RequestParam(required = false) String mediaServerId,
|
||||
@RequestParam(required = false) String callId,
|
||||
@RequestParam(required = false) Boolean useSourceIpAsStreamIp){
|
||||
DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>();
|
||||
boolean authority = false;
|
||||
if (callId != null) {
|
||||
// 权限校验
|
||||
@@ -75,9 +83,7 @@ public class MediaController {
|
||||
authority = true;
|
||||
}
|
||||
}
|
||||
|
||||
StreamInfo streamInfo;
|
||||
|
||||
if (useSourceIpAsStreamIp != null && useSourceIpAsStreamIp) {
|
||||
String host = request.getHeader("Host");
|
||||
String localAddr = host.split(":")[0];
|
||||
@@ -88,30 +94,37 @@ public class MediaController {
|
||||
}
|
||||
|
||||
if (streamInfo != null){
|
||||
return new StreamContent(streamInfo);
|
||||
WVPResult<StreamContent> wvpResult = WVPResult.success();
|
||||
wvpResult.setData(new StreamContent(streamInfo));
|
||||
result.setResult(wvpResult);
|
||||
}else {
|
||||
ErrorCallback<StreamInfo> callback = (code, msg, streamInfoStoStart) -> {
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()) {
|
||||
WVPResult<StreamContent> wvpResult = WVPResult.success();
|
||||
if (useSourceIpAsStreamIp != null && useSourceIpAsStreamIp) {
|
||||
String host;
|
||||
try {
|
||||
URL url=new URL(request.getRequestURL().toString());
|
||||
host=url.getHost();
|
||||
} catch (MalformedURLException e) {
|
||||
host=request.getLocalAddr();
|
||||
}
|
||||
streamInfoStoStart.changeStreamIp(host);
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(streamInfoStoStart.getMediaServer().getTranscodeSuffix())
|
||||
&& !"null".equalsIgnoreCase(streamInfoStoStart.getMediaServer().getTranscodeSuffix())) {
|
||||
streamInfoStoStart.setStream(streamInfoStoStart.getStream() + "_" + streamInfoStoStart.getMediaServer().getTranscodeSuffix());
|
||||
}
|
||||
wvpResult.setData(new StreamContent(streamInfoStoStart));
|
||||
result.setResult(wvpResult);
|
||||
}else {
|
||||
result.setResult(WVPResult.fail(code, msg));
|
||||
}
|
||||
};
|
||||
//获取流失败,重启拉流后重试一次
|
||||
streamProxyService.stopByAppAndStream(app,stream);
|
||||
boolean start = streamProxyService.startByAppAndStream(app, stream);
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
log.error("[线程休眠失败], {}", e.getMessage());
|
||||
}
|
||||
if (useSourceIpAsStreamIp != null && useSourceIpAsStreamIp) {
|
||||
String host = request.getHeader("Host");
|
||||
String localAddr = host.split(":")[0];
|
||||
log.info("使用{}作为返回流的ip", localAddr);
|
||||
streamInfo = mediaServerService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, localAddr, authority);
|
||||
}else {
|
||||
streamInfo = mediaServerService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority);
|
||||
}
|
||||
if (streamInfo != null){
|
||||
return new StreamContent(streamInfo);
|
||||
}else {
|
||||
throw new ControllerException(ErrorCode.ERROR100);
|
||||
}
|
||||
streamProxyService.startByAppAndStream(app, stream, callback);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* 获取推流播放地址
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.genersoft.iot.vmp.gb28181.controller;
|
||||
|
||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
@@ -26,6 +25,7 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
@@ -165,10 +165,10 @@ public class PlaybackController {
|
||||
@Operation(summary = "回放暂停", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "streamId", description = "回放流ID", required = true)
|
||||
@GetMapping("/pause/{streamId}")
|
||||
public void playPause(@PathVariable String streamId) {
|
||||
public void playbackPause(@PathVariable String streamId) {
|
||||
log.info("[回放暂停] streamId: {}", streamId);
|
||||
try {
|
||||
playService.pauseRtp(streamId);
|
||||
playService.playbackPause(streamId);
|
||||
} catch (ServiceException e) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), e.getMessage());
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
@@ -183,7 +183,7 @@ public class PlaybackController {
|
||||
public void playResume(@PathVariable String streamId) {
|
||||
log.info("playResume: "+streamId);
|
||||
try {
|
||||
playService.resumeRtp(streamId);
|
||||
playService.playbackResume(streamId);
|
||||
} catch (ServiceException e) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), e.getMessage());
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
@@ -191,23 +191,14 @@ public class PlaybackController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "回放拖动播放", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "streamId", description = "回放流ID", required = true)
|
||||
@Parameter(name = "seekTime", description = "拖动偏移量,单位s", required = true)
|
||||
@GetMapping("/seek/{streamId}/{seekTime}")
|
||||
public void playSeek(@PathVariable String streamId, @PathVariable long seekTime) {
|
||||
public void playbackSeek(@PathVariable String streamId, @PathVariable long seekTime) {
|
||||
log.info("playSeek: "+streamId+", "+seekTime);
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
|
||||
|
||||
if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
|
||||
log.warn("streamId不存在!");
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
|
||||
}
|
||||
Device device = deviceService.getDeviceByDeviceId(inviteInfo.getDeviceId());
|
||||
DeviceChannel channel = channelService.getOneById(inviteInfo.getChannelId());
|
||||
try {
|
||||
cmder.playSeekCmd(device, channel, inviteInfo.getStreamInfo(), seekTime);
|
||||
playService.playbackSeek(streamId, seekTime);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
|
||||
}
|
||||
@@ -218,17 +209,10 @@ public class PlaybackController {
|
||||
@Parameter(name = "speed", description = "倍速0.25 0.5 1、2、4、8", required = true)
|
||||
@GetMapping("/speed/{streamId}/{speed}")
|
||||
public void playSpeed(@PathVariable String streamId, @PathVariable Double speed) {
|
||||
Assert.notNull(speed, "倍速不存在");
|
||||
log.info("playSpeed: "+streamId+", "+speed);
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
|
||||
|
||||
if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
|
||||
log.warn("streamId不存在!");
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
|
||||
}
|
||||
Device device = deviceService.getDeviceByDeviceId(inviteInfo.getDeviceId());
|
||||
DeviceChannel channel = channelService.getOneById(inviteInfo.getChannelId());
|
||||
try {
|
||||
cmder.playSpeedCmd(device, channel, inviteInfo.getStreamInfo(), speed);
|
||||
playService.playbackSpeed(streamId, speed);
|
||||
} catch (InvalidArgumentException | ParseException | SipException e) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
|
||||
}
|
||||
|
||||
@@ -50,20 +50,29 @@ public class RegionController {
|
||||
return regionService.query(query, page, count);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询区域")
|
||||
@Operation(summary = "查询区域节点")
|
||||
@Parameter(name = "query", description = "要搜索的内容", required = true)
|
||||
@Parameter(name = "parent", description = "所属行政区划编号", required = true)
|
||||
@Parameter(name = "hasChannel", description = "是否查询通道", required = true)
|
||||
@ResponseBody
|
||||
@GetMapping("/tree/list")
|
||||
public List<RegionTree> queryForTree(
|
||||
@RequestParam(required = false) String query,
|
||||
@RequestParam(required = false) Integer parent,
|
||||
@RequestParam(required = false) Boolean hasChannel
|
||||
){
|
||||
if (ObjectUtils.isEmpty(query)) {
|
||||
query = null;
|
||||
}
|
||||
return regionService.queryForTree(query, parent, hasChannel);
|
||||
return regionService.queryForTree(parent, hasChannel);
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "查询区域")
|
||||
@Parameter(name = "query", description = "要搜索的内容", required = true)
|
||||
@Parameter(name = "channel", description = "true为查询通道,false为查询节点", required = true)
|
||||
@ResponseBody
|
||||
@GetMapping("/tree/query")
|
||||
public PageInfo<Region> queryTree(Integer page, Integer count,
|
||||
@RequestParam(required = true) String query
|
||||
){
|
||||
return regionService.queryList(page, count, query);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新区域")
|
||||
|
||||
@@ -275,10 +275,8 @@ public interface CommonGBChannelMapper {
|
||||
" true as is_leaf " +
|
||||
" from wvp_device_channel " +
|
||||
" where coalesce(gb_civil_code, civil_code) = #{parentDeviceId} " +
|
||||
" <if test='query != null'> AND (coalesce(gb_device_id, device_id) LIKE concat('%',#{query},'%') " +
|
||||
" OR coalesce(gb_name, name) LIKE concat('%',#{query},'%'))</if> " +
|
||||
" </script>")
|
||||
List<RegionTree> queryForRegionTreeByCivilCode(@Param("query") String query, @Param("parentDeviceId") String parentDeviceId);
|
||||
List<RegionTree> queryForRegionTreeByCivilCode(@Param("parentDeviceId") String parentDeviceId);
|
||||
|
||||
@Update(value = {" <script>" +
|
||||
" UPDATE wvp_device_channel " +
|
||||
@@ -582,4 +580,21 @@ public interface CommonGBChannelMapper {
|
||||
|
||||
@SelectProvider(type = ChannelProvider.class, method = "queryOnlineListsByGbDeviceId")
|
||||
List<CommonGBChannel> queryOnlineListsByGbDeviceId(@Param("deviceId") int deviceId);
|
||||
|
||||
@Update("UPDATE wvp_device_channel SET stream_id = #{stream} where id = #{gbId}")
|
||||
void updateStream(int gbId, String stream);
|
||||
|
||||
@Update("<script> " +
|
||||
"<foreach collection='commonGBChannels' index='index' item='item' separator=';'> " +
|
||||
"UPDATE wvp_device_channel " +
|
||||
" SET gb_longitude=#{item.gbLongitude}" +
|
||||
", gb_latitude=#{item.gbLatitude} " +
|
||||
", gps_speed=#{item.gpsSpeed} " +
|
||||
", gps_altitude=#{item.gpsAltitude} " +
|
||||
", gps_direction=#{item.gpsDirection} " +
|
||||
", gps_time=#{item.gpsTime} " +
|
||||
"WHERE id = #{item.gbId}" +
|
||||
"</foreach> " +
|
||||
"</script>")
|
||||
void updateGps(List<CommonGBChannel> commonGBChannels);
|
||||
}
|
||||
|
||||
@@ -86,10 +86,11 @@ public interface DeviceChannelMapper {
|
||||
int update(DeviceChannel channel);
|
||||
|
||||
@SelectProvider(type = DeviceChannelProvider.class, method = "queryChannels")
|
||||
List<DeviceChannel> queryChannels(@Param("dataDeviceId") int dataDeviceId, @Param("civilCode") String civilCode,
|
||||
List<DeviceChannel> queryChannels(@Param("dataDeviceId") Integer dataDeviceId, @Param("civilCode") String civilCode,
|
||||
@Param("businessGroupId") String businessGroupId, @Param("parentChannelId") String parentChannelId,
|
||||
@Param("query") String query, @Param("hasSubChannel") Boolean hasSubChannel,
|
||||
@Param("online") Boolean online, @Param("channelIds") List<String> channelIds);
|
||||
@Param("query") String query, @Param("queryParent") Boolean queryParent,
|
||||
@Param("hasSubChannel") Boolean hasSubChannel, @Param("online") Boolean online,
|
||||
@Param("channelIds") List<String> channelIds, @Param("hasStream") Boolean hasStream);
|
||||
|
||||
@SelectProvider(type = DeviceChannelProvider.class, method = "queryChannelsByDeviceDbId")
|
||||
List<DeviceChannel> queryChannelsByDeviceDbId(@Param("dataDeviceId") int dataDeviceId);
|
||||
|
||||
@@ -252,6 +252,7 @@ public interface DeviceMapper {
|
||||
"mobile_position_submission_interval,"+
|
||||
"subscribe_cycle_for_alarm,"+
|
||||
"ssrc_check,"+
|
||||
"media_server_id,"+
|
||||
"as_message_channel,"+
|
||||
"broadcast_push_after_ack,"+
|
||||
"geo_coord_sys,"+
|
||||
|
||||
@@ -156,7 +156,8 @@ public interface GroupMapper {
|
||||
" wcg.name as gb_name," +
|
||||
" wcg.business_group as gb_business_group_id," +
|
||||
" 1 as gb_parental," +
|
||||
" wcg.parent_device_id as gb_parent_id" +
|
||||
" wcg.parent_device_id as gb_parent_id," +
|
||||
" wcg.civil_code as gb_civil_code" +
|
||||
" from wvp_common_group wcg" +
|
||||
" left join wvp_platform_group wpg on wpg.group_id = wcg.id" +
|
||||
" where wpg.platform_id = #{platformId} " +
|
||||
|
||||
@@ -80,9 +80,8 @@ public interface RegionMapper {
|
||||
" where " +
|
||||
" <if test='parentId != null'> parent_id = #{parentId} </if> " +
|
||||
" <if test='parentId == null'> parent_id is null </if> " +
|
||||
" <if test='query != null'> AND (device_id LIKE concat('%',#{query},'%') escape '/' OR name LIKE concat('%',#{query},'%') escape '/')</if> " +
|
||||
" </script>")
|
||||
List<RegionTree> queryForTree(@Param("query") String query, @Param("parentId") Integer parentId);
|
||||
List<RegionTree> queryForTree(@Param("parentId") Integer parentId);
|
||||
|
||||
@Delete("<script>" +
|
||||
" DELETE FROM wvp_common_region WHERE id in " +
|
||||
|
||||
@@ -16,6 +16,7 @@ public class ChannelProvider {
|
||||
" data_device_id,\n" +
|
||||
" create_time,\n" +
|
||||
" update_time,\n" +
|
||||
" stream_id,\n" +
|
||||
" record_plan_id,\n" +
|
||||
" coalesce(gb_device_id, device_id) as gb_device_id,\n" +
|
||||
" coalesce(gb_name, name) as gb_name,\n" +
|
||||
@@ -60,6 +61,7 @@ public class ChannelProvider {
|
||||
" wdc.data_device_id,\n" +
|
||||
" wdc.create_time,\n" +
|
||||
" wdc.update_time,\n" +
|
||||
" wdc.stream_id,\n" +
|
||||
" wdc.record_plan_id,\n" +
|
||||
" coalesce(wdc.gb_device_id, wdc.device_id) as gb_device_id,\n" +
|
||||
" coalesce(wdc.gb_name, wdc.name) as gb_name,\n" +
|
||||
|
||||
@@ -20,6 +20,8 @@ public class DeviceChannelProvider {
|
||||
" dc.gps_time,\n" +
|
||||
" dc.stream_identification,\n" +
|
||||
" dc.channel_type,\n" +
|
||||
" d.device_id as parent_device_id,\n" +
|
||||
" coalesce(d.custom_name, d.name) as parent_name,\n" +
|
||||
" coalesce(dc.gb_device_id, dc.device_id) as device_id,\n" +
|
||||
" coalesce(dc.gb_name, dc.name) as name,\n" +
|
||||
" coalesce(dc.gb_manufacturer, dc.manufacturer) as manufacturer,\n" +
|
||||
@@ -55,13 +57,17 @@ public class DeviceChannelProvider {
|
||||
" coalesce(dc.gb_svc_space_support_mod, dc.svc_space_support_mod) as svc_space_support_mod,\n" +
|
||||
" coalesce(dc.gb_svc_time_support_mode,dc.svc_time_support_mode) as svc_time_support_mode\n" +
|
||||
" from " +
|
||||
" wvp_device_channel dc "
|
||||
" wvp_device_channel dc " +
|
||||
" left join wvp_device d on d.id = dc.data_device_id "
|
||||
;
|
||||
}
|
||||
public String queryChannels(Map<String, Object> params ){
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append(getBaseSelectSql());
|
||||
sqlBuild.append(" where data_type = " + ChannelDataType.GB28181.value + " and dc.data_device_id = #{dataDeviceId} ");
|
||||
sqlBuild.append(" where data_type = " + ChannelDataType.GB28181);
|
||||
if (params.get("dataDeviceId") != null) {
|
||||
sqlBuild.append(" AND dc.data_device_id = #{dataDeviceId} ");
|
||||
}
|
||||
if (params.get("businessGroupId") != null ) {
|
||||
sqlBuild.append(" AND coalesce(dc.gb_business_group_id, dc.business_group_id)=#{businessGroupId} AND coalesce(dc.gb_parent_id, dc.parent_id) is null");
|
||||
}else if (params.get("parentChannelId") != null ) {
|
||||
@@ -73,8 +79,15 @@ public class DeviceChannelProvider {
|
||||
}
|
||||
if (params.get("query") != null && !ObjectUtils.isEmpty(params.get("query"))) {
|
||||
sqlBuild.append(" AND (coalesce(dc.gb_device_id, dc.device_id) LIKE concat('%',#{query},'%') escape '/'" +
|
||||
" OR coalesce(dc.gb_name, dc.name) LIKE concat('%',#{query},'%') escape '/')")
|
||||
;
|
||||
" OR coalesce(dc.gb_name, dc.name) LIKE concat('%',#{query},'%') escape '/'");
|
||||
if (params.get("queryParent") != null && (Boolean) params.get("queryParent")) {
|
||||
sqlBuild.append(" OR d.device_id LIKE concat('%',#{query},'%') escape '/'");
|
||||
sqlBuild.append(" OR coalesce(d.custom_name, d.name) LIKE concat('%',#{query},'%') escape '/'");
|
||||
}
|
||||
sqlBuild.append(")");
|
||||
}
|
||||
if (params.get("hasStream") != null && (Boolean) params.get("hasStream")) {
|
||||
sqlBuild.append(" AND dc.stream_id IS NOT NULL");
|
||||
}
|
||||
if (params.get("online") != null && (Boolean)params.get("online")) {
|
||||
sqlBuild.append(" AND coalesce(gb_status, status) = 'ON'");
|
||||
@@ -101,7 +114,7 @@ public class DeviceChannelProvider {
|
||||
}
|
||||
sqlBuild.append(" )");
|
||||
}
|
||||
sqlBuild.append(" ORDER BY device_id");
|
||||
sqlBuild.append(" ORDER BY d.device_id, dc.device_id");
|
||||
return sqlBuild.toString();
|
||||
}
|
||||
|
||||
@@ -109,14 +122,14 @@ public class DeviceChannelProvider {
|
||||
public String queryChannelsByDeviceDbId(Map<String, Object> params ){
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append(getBaseSelectSql());
|
||||
sqlBuild.append(" where data_type = " + ChannelDataType.GB28181.value + " and dc.data_device_id = #{dataDeviceId}");
|
||||
sqlBuild.append(" where data_type = " + ChannelDataType.GB28181 + " and dc.data_device_id = #{dataDeviceId}");
|
||||
return sqlBuild.toString();
|
||||
}
|
||||
|
||||
public String queryAllChannels(Map<String, Object> params ){
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append(getBaseSelectSql());
|
||||
sqlBuild.append(" where data_type = " + ChannelDataType.GB28181.value + " and dc.data_device_id = #{dataDeviceId}");
|
||||
sqlBuild.append(" where data_type = " + ChannelDataType.GB28181 + " and dc.data_device_id = #{dataDeviceId}");
|
||||
return sqlBuild.toString();
|
||||
}
|
||||
|
||||
@@ -130,25 +143,25 @@ public class DeviceChannelProvider {
|
||||
public String getOneByDeviceId(Map<String, Object> params ){
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append(getBaseSelectSql());
|
||||
sqlBuild.append(" where data_type = " + ChannelDataType.GB28181.value + " and dc.data_device_id=#{dataDeviceId} and coalesce(dc.gb_device_id, dc.device_id) = #{channelId}");
|
||||
sqlBuild.append(" where data_type = " + ChannelDataType.GB28181 + " and dc.data_device_id=#{dataDeviceId} and coalesce(dc.gb_device_id, dc.device_id) = #{channelId}");
|
||||
return sqlBuild.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String queryByDeviceId(Map<String, Object> params ){
|
||||
return getBaseSelectSql() + " where data_type = " + ChannelDataType.GB28181.value + " and channel_type = 0 and coalesce(gb_device_id, device_id) = #{gbDeviceId}";
|
||||
return getBaseSelectSql() + " where data_type = " + ChannelDataType.GB28181 + " and channel_type = 0 and coalesce(gb_device_id, device_id) = #{gbDeviceId}";
|
||||
}
|
||||
|
||||
public String queryById(Map<String, Object> params ){
|
||||
return getBaseSelectSql() + " where data_type = " + ChannelDataType.GB28181.value + " and channel_type = 0 and id = #{gbId}";
|
||||
return getBaseSelectSql() + " where data_type = " + ChannelDataType.GB28181 + " and channel_type = 0 and id = #{gbId}";
|
||||
}
|
||||
|
||||
|
||||
public String queryList(Map<String, Object> params ){
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append(getBaseSelectSql());
|
||||
sqlBuild.append(" where channel_type = 0 and data_type = " + ChannelDataType.GB28181.value);
|
||||
sqlBuild.append(" where channel_type = 0 and data_type = " + ChannelDataType.GB28181);
|
||||
if (params.get("query") != null) {
|
||||
sqlBuild.append(" AND (coalesce(gb_device_id, device_id) LIKE concat('%',#{query},'%')" +
|
||||
" OR coalesce(gb_name, name) LIKE concat('%',#{query},'%') )")
|
||||
|
||||
@@ -50,14 +50,6 @@ public class SipSubscribe {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTimeout(String callId) {
|
||||
SipEvent sipEvent = subscribes.get(callId);
|
||||
if (sipEvent != null) {
|
||||
delayQueue.remove(sipEvent);
|
||||
delayQueue.offer(sipEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public interface Event { void response(EventResult eventResult);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.common.enums.DeviceControlType;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.MobilePosition;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelReduce;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
|
||||
@@ -104,6 +101,7 @@ public interface IDeviceChannelService {
|
||||
|
||||
PageInfo<DeviceChannel> queryChannelsByDeviceId(String deviceId, String query, Boolean channelType, Boolean online, int page, int count);
|
||||
|
||||
PageInfo<DeviceChannel> queryChannels(String query, Boolean queryParent, Boolean channelType, Boolean online, Boolean hasStream, int page, int count);
|
||||
|
||||
List<Device> queryDeviceWithAsMessageChannel();
|
||||
|
||||
|
||||
@@ -200,5 +200,6 @@ public interface IDeviceService {
|
||||
|
||||
void deviceInfo(Device device, ErrorCallback<Object> callback);
|
||||
|
||||
void queryPreset(Device device, String channelId, ErrorCallback<Object> callback);
|
||||
void queryPreset(Device device, String channelId, ErrorCallback<List<Preset>> callback);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.FrontEndControlCodeForPTZ;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IGbChannelControlService {
|
||||
|
||||
|
||||
void ptz(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback);
|
||||
void fi(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback);
|
||||
void preset(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback);
|
||||
void tour(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback);
|
||||
void scan(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback);
|
||||
void auxiliary(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback);
|
||||
void fi(CommonGBChannel channel, FrontEndControlCodeForFI frontEndControlCode, ErrorCallback<String> callback);
|
||||
void preset(CommonGBChannel channel, FrontEndControlCodeForPreset frontEndControlCode, ErrorCallback<String> callback);
|
||||
void tour(CommonGBChannel channel, FrontEndControlCodeForTour frontEndControlCode, ErrorCallback<String> callback);
|
||||
void scan(CommonGBChannel channel, FrontEndControlCodeForScan frontEndControlCode, ErrorCallback<String> callback);
|
||||
void wiper(CommonGBChannel channel, FrontEndControlCodeForWiper controlCode, ErrorCallback<String> callback);
|
||||
void auxiliary(CommonGBChannel channel, FrontEndControlCodeForAuxiliary frontEndControlCode, ErrorCallback<String> callback);
|
||||
void queryPreset(CommonGBChannel channel, ErrorCallback<List<Preset>> callback);
|
||||
}
|
||||
|
||||
@@ -3,31 +3,39 @@ package com.genersoft.iot.vmp.gb28181.service;
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonRecordInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.InviteMessageInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IGbChannelPlayService {
|
||||
|
||||
void start(CommonGBChannel channel, InviteMessageInfo inviteInfo, Platform platform, ErrorCallback<StreamInfo> callback);
|
||||
void startInvite(CommonGBChannel channel, InviteMessageInfo inviteInfo, Platform platform, ErrorCallback<StreamInfo> callback);
|
||||
|
||||
void stopPlay(InviteSessionType type, CommonGBChannel channel, String stream);
|
||||
void stopInvite(InviteSessionType type, CommonGBChannel channel, String stream);
|
||||
|
||||
void playback(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback);
|
||||
|
||||
void download(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed,
|
||||
ErrorCallback<StreamInfo> callback);
|
||||
|
||||
void stopPlay(CommonGBChannel channel, String stream);
|
||||
|
||||
void play(CommonGBChannel channel, Platform platform, Boolean record, ErrorCallback<StreamInfo> callback);
|
||||
|
||||
void playGbDeviceChannel(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback);
|
||||
void stopPlayback(CommonGBChannel channel, String stream);
|
||||
|
||||
void stopPlayDeviceChannel(InviteSessionType type, CommonGBChannel channel, String stream);
|
||||
void stopDownload(CommonGBChannel channel, String stream);
|
||||
|
||||
void playProxy(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback);
|
||||
void playbackPause(CommonGBChannel channel, String streamId);
|
||||
|
||||
void stopPlayProxy(CommonGBChannel channel);
|
||||
void playbackResume(CommonGBChannel channel, String streamId);
|
||||
|
||||
void playPush(CommonGBChannel channel, String platformDeviceId, String platformName, ErrorCallback<StreamInfo> callback);
|
||||
void playbackSeek(CommonGBChannel channel, String stream, long seekTime);
|
||||
|
||||
void stopPlayPush(CommonGBChannel channel);
|
||||
void playbackSpeed(CommonGBChannel channel, String stream, Double speed);
|
||||
|
||||
void pauseRtp(String streamId);
|
||||
|
||||
void resumeRtp(String streamId);
|
||||
void queryRecord(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<List<CommonRecordInfo>> callback);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||
import com.genersoft.iot.vmp.streamPush.bean.StreamPush;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
@@ -87,8 +86,6 @@ public interface IGbChannelService {
|
||||
|
||||
PageInfo<CommonGBChannel> queryList(int page, int count, String query, Boolean online, Boolean hasRecordPlan, Integer channelType);
|
||||
|
||||
void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> callback);
|
||||
|
||||
PageInfo<CommonGBChannel> queryListByCivilCodeForUnusual(int page, int count, String query, Boolean online, Integer channelType);
|
||||
|
||||
void clearChannelCivilCode(Boolean all, List<Integer> channelIds);
|
||||
@@ -99,4 +96,5 @@ public interface IGbChannelService {
|
||||
|
||||
void updateGPSFromGPSMsgInfo(List<GPSMsgInfo> gpsMsgInfoList);
|
||||
|
||||
void updateGPS(List<CommonGBChannel> channelList);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.service;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Group;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.GroupTree;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -23,4 +24,6 @@ public interface IGroupService {
|
||||
boolean batchAdd(List<Group> groupList);
|
||||
|
||||
List<Group> getPath(String deviceId, String businessGroup);
|
||||
|
||||
PageInfo<Group> queryList(Integer page, Integer count, String query);
|
||||
}
|
||||
|
||||
@@ -4,21 +4,18 @@ package com.genersoft.iot.vmp.gb28181.service;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Preset;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IPTZService {
|
||||
|
||||
|
||||
List<Preset> queryPresetList(String deviceId, String channelDeviceId);
|
||||
|
||||
void addPreset(Preset preset);
|
||||
|
||||
void deletePreset(Integer qq);
|
||||
|
||||
void ptz(Device device, String channelId, int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed);
|
||||
|
||||
void frontEndCommand(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combindCode2);
|
||||
|
||||
void frontEndCommand(CommonGBChannel channel, Integer cmdCode, Integer parameter1, Integer parameter2, Integer combindCode2);
|
||||
|
||||
void queryPresetList(CommonGBChannel channel, ErrorCallback<List<Preset>> callback);
|
||||
|
||||
}
|
||||
|
||||
@@ -48,9 +48,13 @@ public interface IPlayService {
|
||||
|
||||
void stopAudioBroadcast(Device device, DeviceChannel channel);
|
||||
|
||||
void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException;
|
||||
void playbackPause(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException;
|
||||
void playbackResume(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
void playbackSeek(String streamId, long seekTime) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
void playbackSpeed(String streamId, double speed) throws InvalidArgumentException, ParseException, SipException;
|
||||
|
||||
void startPushStream(SendRtpInfo sendRtpItem, DeviceChannel channel, SIPResponse sipResponse, Platform platform, CallIdHeader callIdHeader);
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ public interface IRegionService {
|
||||
|
||||
Region queryRegionByDeviceId(String regionDeviceId);
|
||||
|
||||
List<RegionTree> queryForTree(String query, Integer parent, Boolean hasChannel);
|
||||
List<RegionTree> queryForTree(Integer parent, Boolean hasChannel);
|
||||
|
||||
void syncFromChannel();
|
||||
|
||||
@@ -40,4 +40,6 @@ public interface IRegionService {
|
||||
String getDescription(String civilCode);
|
||||
|
||||
void addByCivilCode(String civilCode);
|
||||
|
||||
PageInfo<Region> queryList(int page, int count, String query);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
|
||||
/**
|
||||
* 资源能力接入-录像下载
|
||||
*/
|
||||
public interface ISourceDownloadService {
|
||||
|
||||
void download(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed, ErrorCallback<StreamInfo> callback);
|
||||
|
||||
void stopDownload(CommonGBChannel channel, String stream);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 资源能力接入-云台控制
|
||||
*/
|
||||
public interface ISourcePTZService {
|
||||
|
||||
void ptz(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback);
|
||||
|
||||
void preset(CommonGBChannel channel, FrontEndControlCodeForPreset frontEndControlCode, ErrorCallback<String> callback);
|
||||
|
||||
void fi(CommonGBChannel channel, FrontEndControlCodeForFI frontEndControlCode, ErrorCallback<String> callback);
|
||||
|
||||
void tour(CommonGBChannel channel, FrontEndControlCodeForTour frontEndControlCode, ErrorCallback<String> callback);
|
||||
|
||||
void scan(CommonGBChannel channel, FrontEndControlCodeForScan frontEndControlCode, ErrorCallback<String> callback);
|
||||
|
||||
void auxiliary(CommonGBChannel channel, FrontEndControlCodeForAuxiliary frontEndControlCode, ErrorCallback<String> callback);
|
||||
|
||||
void wiper(CommonGBChannel channel, FrontEndControlCodeForWiper frontEndControlCode, ErrorCallback<String> callback);
|
||||
|
||||
void queryPreset(CommonGBChannel channel, ErrorCallback<List<Preset>> callback);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
|
||||
/**
|
||||
* 资源能力接入-实时录像
|
||||
*/
|
||||
public interface ISourcePlayService {
|
||||
|
||||
void play(CommonGBChannel channel, Platform platform, Boolean record, ErrorCallback<StreamInfo> callback);
|
||||
|
||||
void stopPlay(CommonGBChannel channel, String stream);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service;
|
||||
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonRecordInfo;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 资源能力接入-录像回放
|
||||
*/
|
||||
public interface ISourcePlaybackService {
|
||||
|
||||
void playback(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback);
|
||||
|
||||
void stopPlayback(CommonGBChannel channel, String stream);
|
||||
|
||||
void playbackPause(CommonGBChannel channel, String stream);
|
||||
|
||||
void playbackResume(CommonGBChannel channel, String stream);
|
||||
|
||||
void playbackSeek(CommonGBChannel channel, String stream, long seekTime);
|
||||
|
||||
void playbackSpeed(CommonGBChannel channel, String stream, Double speed);
|
||||
|
||||
void queryRecord(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<List<CommonRecordInfo>> callback);
|
||||
}
|
||||
@@ -696,7 +696,7 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<DeviceChannel> all = channelMapper.queryChannels(deviceDbId, civilCode, businessGroupId, parentId, query, channelType, online,null);
|
||||
List<DeviceChannel> all = channelMapper.queryChannels(deviceDbId, civilCode, businessGroupId, parentId, query, false, channelType, online, null, null);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
|
||||
@@ -717,7 +717,19 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
PageHelper.startPage(page, count);
|
||||
List<DeviceChannel> all = channelMapper.queryChannels(device.getId(), null,null, null, query, hasSubChannel, online,null);
|
||||
List<DeviceChannel> all = channelMapper.queryChannels(device.getId(), null, null, null, query, false, hasSubChannel, online, null, null);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<DeviceChannel> queryChannels(String query, Boolean queryParent, Boolean hasSubChannel, Boolean online, Boolean hasStream, int page, int count) {
|
||||
PageHelper.startPage(page, count);
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<DeviceChannel> all = channelMapper.queryChannels(null, null, null, null, query, queryParent, hasSubChannel, online, null, hasStream);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
|
||||
@@ -768,7 +780,7 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
|
||||
@Override
|
||||
public void addChannel(DeviceChannel channel) {
|
||||
channel.setDataType(ChannelDataType.GB28181.value);
|
||||
channel.setDataType(ChannelDataType.GB28181);
|
||||
channel.setDataDeviceId(channel.getDataDeviceId());
|
||||
channelMapper.add(channel);
|
||||
}
|
||||
@@ -814,7 +826,7 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
|
||||
@Override
|
||||
public void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> callback) {
|
||||
if (channel.getDataType() != ChannelDataType.GB28181.value){
|
||||
if (channel.getDataType() != ChannelDataType.GB28181){
|
||||
// 只支持国标的语音喊话
|
||||
log.warn("[INFO 消息] 非国标设备, 通道ID: {}", channel.getGbId());
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "非国标设备", null);
|
||||
|
||||
@@ -691,7 +691,7 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
|
||||
|
||||
@Override
|
||||
public List<Device> getAllByStatus(Boolean status) {
|
||||
return deviceMapper.getDevices(ChannelDataType.GB28181.value, status);
|
||||
return deviceMapper.getDevices(ChannelDataType.GB28181, status);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -852,7 +852,7 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<Device> all = deviceMapper.getDeviceList(ChannelDataType.GB28181.value, query, status);
|
||||
List<Device> all = deviceMapper.getDeviceList(ChannelDataType.GB28181, query, status);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
|
||||
@@ -863,12 +863,12 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
|
||||
|
||||
@Override
|
||||
public Device getDeviceByChannelId(Integer channelId) {
|
||||
return deviceMapper.queryByChannelId(ChannelDataType.GB28181.value,channelId);
|
||||
return deviceMapper.queryByChannelId(ChannelDataType.GB28181,channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Device getDeviceBySourceChannelDeviceId(String channelId) {
|
||||
return deviceMapper.getDeviceBySourceChannelDeviceId(ChannelDataType.GB28181.value,channelId);
|
||||
return deviceMapper.getDeviceBySourceChannelDeviceId(ChannelDataType.GB28181,channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1252,9 +1252,9 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryPreset(Device device, String channelId, ErrorCallback<Object> callback) {
|
||||
public void queryPreset(Device device, String channelId, ErrorCallback<List<Preset>> callback) {
|
||||
if (!userSetting.getServerId().equals(device.getServerId())) {
|
||||
WVPResult<Object> result = redisRpcService.queryPreset(device.getServerId(), device, channelId);
|
||||
WVPResult<List<Preset>> result = redisRpcService.queryPreset(device.getServerId(), device, channelId);
|
||||
callback.run(result.getCode(), result.getMsg(), result.getData());
|
||||
return;
|
||||
}
|
||||
@@ -1267,4 +1267,6 @@ public class DeviceServiceImpl implements IDeviceService, CommandLineRunner {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,43 +1,128 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.FrontEndControlCodeForPTZ;
|
||||
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelControlService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.ISourcePTZService;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.sip.message.Response;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class GbChannelControlServiceImpl implements IGbChannelControlService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private Map<String, ISourcePTZService> sourcePTZServiceMap;
|
||||
|
||||
|
||||
@Override
|
||||
public void ptz(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback) {
|
||||
log.info("[通用通道] 云台控制, 通道: {}", channel.getGbId());
|
||||
log.info("[通用通道] 云台控制, 类型: {}, 编号:{}", channel.getDataType(), channel.getGbDeviceId());
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePTZService sourcePTZService = sourcePTZServiceMap.get(ChannelDataType.PTZ_SERVICE + dataType);
|
||||
if (sourcePTZService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型: {} 不支持云台控制", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
sourcePTZService.ptz(channel, frontEndControlCode, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preset(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback) {
|
||||
log.info("[通用通道] 预置位, 通道: {}", channel.getGbId());
|
||||
public void preset(CommonGBChannel channel, FrontEndControlCodeForPreset frontEndControlCode, ErrorCallback<String> callback) {
|
||||
log.info("[通用通道] 预置位控制, 类型: {}, 编号:{}", channel.getDataType(), channel.getGbDeviceId());
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePTZService sourcePTZService = sourcePTZServiceMap.get(ChannelDataType.PTZ_SERVICE + dataType);
|
||||
if (sourcePTZService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型: {} 不支持预置位控制", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
sourcePTZService.preset(channel, frontEndControlCode, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fi(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback) {
|
||||
log.info("[通用通道] FI指令, 通道: {}", channel.getGbId());
|
||||
public void fi(CommonGBChannel channel, FrontEndControlCodeForFI frontEndControlCode, ErrorCallback<String> callback) {
|
||||
log.info("[通用通道] FI指令, 类型: {}, 编号:{}", channel.getDataType(), channel.getGbDeviceId());
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePTZService sourcePTZService = sourcePTZServiceMap.get(ChannelDataType.PTZ_SERVICE + dataType);
|
||||
if (sourcePTZService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型: {} 不支持FI指令", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
sourcePTZService.fi(channel, frontEndControlCode, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tour(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback) {
|
||||
|
||||
public void tour(CommonGBChannel channel, FrontEndControlCodeForTour frontEndControlCode, ErrorCallback<String> callback) {
|
||||
log.info("[通用通道] 巡航指令, 类型: {}, 编号:{}", channel.getDataType(), channel.getGbDeviceId());
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePTZService sourcePTZService = sourcePTZServiceMap.get(ChannelDataType.PTZ_SERVICE + dataType);
|
||||
if (sourcePTZService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型: {} 不支持巡航指令", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
sourcePTZService.tour(channel, frontEndControlCode, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scan(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback) {
|
||||
|
||||
public void scan(CommonGBChannel channel, FrontEndControlCodeForScan frontEndControlCode, ErrorCallback<String> callback) {
|
||||
log.info("[通用通道] 扫描指令, 类型: {}, 编号:{}", channel.getDataType(), channel.getGbDeviceId());
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePTZService sourcePTZService = sourcePTZServiceMap.get(ChannelDataType.PTZ_SERVICE + dataType);
|
||||
if (sourcePTZService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型: {} 不支持扫描指令", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
sourcePTZService.scan(channel, frontEndControlCode, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void auxiliary(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback) {
|
||||
public void auxiliary(CommonGBChannel channel, FrontEndControlCodeForAuxiliary frontEndControlCode, ErrorCallback<String> callback) {
|
||||
log.info("[通用通道] 辅助开关控制指令, 类型: {}, 编号:{}", channel.getDataType(), channel.getGbDeviceId());
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePTZService sourcePTZService = sourcePTZServiceMap.get(ChannelDataType.PTZ_SERVICE + dataType);
|
||||
if (sourcePTZService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型: {} 不支持辅助开关控制指令", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
sourcePTZService.auxiliary(channel, frontEndControlCode, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wiper(CommonGBChannel channel, FrontEndControlCodeForWiper frontEndControlCode, ErrorCallback<String> callback) {
|
||||
log.info("[通用通道] 雨刷控制, 类型: {}, 编号:{}", channel.getDataType(), channel.getGbDeviceId());
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePTZService sourcePTZService = sourcePTZServiceMap.get(ChannelDataType.PTZ_SERVICE + dataType);
|
||||
if (sourcePTZService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型: {} 不支持雨刷控制", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
sourcePTZService.wiper(channel, frontEndControlCode, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryPreset(CommonGBChannel channel, ErrorCallback<List<Preset>> callback) {
|
||||
log.info("[通用通道] 预置位查询, 类型: {}, 编号:{}", channel.getDataType(), channel.getGbDeviceId());
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePTZService sourcePTZService = sourcePTZServiceMap.get(ChannelDataType.PTZ_SERVICE + dataType);
|
||||
if (sourcePTZService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型: {} 不支持预置位查询", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
sourcePTZService.queryPreset(channel, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,95 +2,63 @@ package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.conf.exception.ServiceException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.PlayException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.dao.CommonGBChannelMapper;
|
||||
import com.genersoft.iot.vmp.gb28181.service.*;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IPlayService;
|
||||
import com.genersoft.iot.vmp.jt1078.service.Ijt1078PlayService;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.streamProxy.service.IStreamProxyPlayService;
|
||||
import com.genersoft.iot.vmp.streamPush.service.IStreamPushPlayService;
|
||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.message.Response;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
|
||||
|
||||
@Autowired
|
||||
private IPlayService deviceChannelPlayService;
|
||||
|
||||
@Autowired
|
||||
private IStreamProxyPlayService streamProxyPlayService;
|
||||
|
||||
@Autowired
|
||||
private IStreamPushPlayService streamPushPlayService;
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
||||
@Autowired
|
||||
private CommonGBChannelMapper channelMapper;
|
||||
|
||||
@Autowired
|
||||
private Map<String, ISourcePlayService> sourcePlayServiceMap;
|
||||
|
||||
@Autowired
|
||||
private Ijt1078PlayService jt1078PlayService;
|
||||
|
||||
@Autowired
|
||||
private Map<String, ISourcePlaybackService> sourcePlaybackServiceMap;
|
||||
|
||||
@Autowired
|
||||
private Map<String, ISourceDownloadService> sourceDownloadServiceMap;
|
||||
|
||||
|
||||
@Override
|
||||
public void start(CommonGBChannel channel, InviteMessageInfo inviteInfo, Platform platform, ErrorCallback<StreamInfo> callback) {
|
||||
public void startInvite(CommonGBChannel channel, InviteMessageInfo inviteInfo, Platform platform, ErrorCallback<StreamInfo> callback) {
|
||||
if (channel == null || inviteInfo == null || callback == null || channel.getDataType() == null) {
|
||||
log.warn("[通用通道点播] 参数异常, channel: {}, inviteInfo: {}, callback: {}", channel != null, inviteInfo != null, callback != null);
|
||||
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||
}
|
||||
log.info("[点播通用通道] 类型:{}, 通道: {}({})", inviteInfo.getSessionName(), channel.getGbName(), channel.getGbDeviceId());
|
||||
|
||||
if ("Play".equalsIgnoreCase(inviteInfo.getSessionName())) {
|
||||
play(channel, platform, userSetting.getRecordSip(), callback);
|
||||
}else if ("Playback".equals(inviteInfo.getSessionName())) {
|
||||
if (channel.getDataType() == ChannelDataType.GB28181.value) {
|
||||
// 国标通道
|
||||
playbackGbDeviceChannel(channel, inviteInfo.getStartTime(), inviteInfo.getStopTime(), callback);
|
||||
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY.value) {
|
||||
// 拉流代理
|
||||
log.warn("[回放通用通道] 不支持回放拉流代理的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||
throw new PlayException(Response.FORBIDDEN, "forbidden");
|
||||
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH.value) {
|
||||
// 推流
|
||||
log.warn("[回放通用通道] 不支持回放推流的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||
throw new PlayException(Response.FORBIDDEN, "forbidden");
|
||||
} else {
|
||||
// 通道数据异常
|
||||
log.error("[回放通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||
}
|
||||
playback(channel, inviteInfo.getStartTime(), inviteInfo.getStopTime(), callback);
|
||||
}else if ("Download".equals(inviteInfo.getSessionName())) {
|
||||
if (channel.getDataType() == ChannelDataType.GB28181.value) {
|
||||
int downloadSpeed = 4;
|
||||
try {
|
||||
if (inviteInfo.getDownloadSpeed() != null){
|
||||
downloadSpeed = Integer.parseInt(inviteInfo.getDownloadSpeed());
|
||||
}
|
||||
}catch (Exception ignored) {}
|
||||
|
||||
// 国标通道
|
||||
downloadGbDeviceChannel(channel, inviteInfo.getStartTime(), inviteInfo.getStopTime(), downloadSpeed, callback);
|
||||
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY.value) {
|
||||
// 拉流代理
|
||||
log.warn("[下载通用通道录像] 不支持下载拉流代理的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||
throw new PlayException(Response.FORBIDDEN, "forbidden");
|
||||
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH.value) {
|
||||
// 推流
|
||||
log.warn("[下载通用通道录像] 不支持下载推流的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||
throw new PlayException(Response.FORBIDDEN, "forbidden");
|
||||
} else {
|
||||
// 通道数据异常
|
||||
log.error("[回放通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||
}
|
||||
Integer downloadSpeed = Integer.parseInt(inviteInfo.getDownloadSpeed());
|
||||
// 国标通道
|
||||
download(channel, inviteInfo.getStartTime(), inviteInfo.getStopTime(), downloadSpeed, callback);
|
||||
}else {
|
||||
// 不支持的点播方式
|
||||
log.error("[点播通用通道] 不支持的点播方式:{}, {}({})", inviteInfo.getSessionName(), channel.getGbName(), channel.getGbDeviceId());
|
||||
@@ -99,149 +67,173 @@ public class GbChannelPlayServiceImpl implements IGbChannelPlayService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopPlay(InviteSessionType type, CommonGBChannel channel, String stream) {
|
||||
if (channel.getDataType() == ChannelDataType.GB28181.value) {
|
||||
// 国标通道
|
||||
stopPlayDeviceChannel(type, channel, stream);
|
||||
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY.value) {
|
||||
// 拉流代理
|
||||
stopPlayProxy(channel);
|
||||
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH.value) {
|
||||
// 推流
|
||||
stopPlayPush(channel);
|
||||
} else {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||
public void stopInvite(InviteSessionType type, CommonGBChannel channel, String stream) {
|
||||
switch (type) {
|
||||
case PLAY:
|
||||
stopPlay(channel, stream);
|
||||
break;
|
||||
case PLAYBACK:
|
||||
stopPlayback(channel, stream);
|
||||
break;
|
||||
case DOWNLOAD:
|
||||
stopDownload(channel, stream);
|
||||
break;
|
||||
default:
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型编号: {} 不支持此类型请求", type);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void play(CommonGBChannel channel, Platform platform, Boolean record, ErrorCallback<StreamInfo> callback) {
|
||||
if (channel.getDataType() == ChannelDataType.GB28181.value) {
|
||||
// 国标通道
|
||||
playGbDeviceChannel(channel, record, callback);
|
||||
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY.value) {
|
||||
// 拉流代理
|
||||
playProxy(channel, record, callback);
|
||||
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH.value) {
|
||||
if (platform != null) {
|
||||
// 推流
|
||||
playPush(channel, platform.getServerGBId(), platform.getName(), callback);
|
||||
}else {
|
||||
// 推流
|
||||
playPush(channel, null, null, callback);
|
||||
}
|
||||
} else {
|
||||
log.info("[通用通道] 播放, 类型: {}, 编号:{}", channel.getDataType(), channel.getGbDeviceId());
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePlayService sourceChannelPlayService = sourcePlayServiceMap.get(ChannelDataType.PLAY_SERVICE + dataType);
|
||||
if (sourceChannelPlayService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||
log.error("[点播通用通道] 类型编号: {} 不支持实时流预览", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
sourceChannelPlayService.play(channel, platform, record, (code, msg, data) -> {
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()) {
|
||||
// 将流ID记录到数据库
|
||||
if (channel.getDataType() != ChannelDataType.GB28181) {
|
||||
channelMapper.updateStream(channel.getGbId(), data.getStream());
|
||||
}
|
||||
}
|
||||
callback.run(code, msg, data);
|
||||
});
|
||||
}
|
||||
@Override
|
||||
public void playback(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback) {
|
||||
log.info("[通用通道] 回放, 类型: {}, 编号:{}", channel.getDataType(), channel.getGbDeviceId());
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePlaybackService playbackService = sourcePlaybackServiceMap.get(ChannelDataType.PLAYBACK_SERVICE + dataType);
|
||||
if (playbackService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型编号: {} 不支持回放", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
playbackService.playback(channel, startTime, stopTime, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playGbDeviceChannel(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback){
|
||||
// 国标通道
|
||||
try {
|
||||
deviceChannelPlayService.play(channel, record, callback);
|
||||
} catch (PlayException e) {
|
||||
callback.run(e.getCode(), e.getMsg(), null);
|
||||
} catch (ControllerException e) {
|
||||
log.error("[点播失败] {}({}), {}", channel.getGbName(), channel.getGbDeviceId(), e.getMsg());
|
||||
callback.run(Response.BUSY_HERE, "busy here", null);
|
||||
} catch (Exception e) {
|
||||
log.error("[点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
|
||||
callback.run(Response.BUSY_HERE, "busy here", null);
|
||||
public void download(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed,
|
||||
ErrorCallback<StreamInfo> callback){
|
||||
log.info("[通用通道] 录像下载, 类型: {}, 编号:{}", channel.getDataType(), channel.getGbDeviceId());
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourceDownloadService downloadService = sourceDownloadServiceMap.get(ChannelDataType.DOWNLOAD_SERVICE + dataType);
|
||||
if (downloadService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型编号: {} 不支持录像下载", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
downloadService.download(channel, startTime, stopTime, downloadSpeed, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopPlayDeviceChannel(InviteSessionType type, CommonGBChannel channel, String stream) {
|
||||
// 国标通道
|
||||
try {
|
||||
deviceChannelPlayService.stop(type, channel, stream);
|
||||
} catch (Exception e) {
|
||||
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
|
||||
public void stopPlay(CommonGBChannel channel, String stream) {
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePlayService sourceChannelPlayService = sourcePlayServiceMap.get(ChannelDataType.PLAY_SERVICE + dataType);
|
||||
if (sourceChannelPlayService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型编号: {} 不支持停止实时流", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
sourceChannelPlayService.stopPlay(channel, stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playProxy(CommonGBChannel channel, Boolean record, ErrorCallback<StreamInfo> callback){
|
||||
// 拉流代理通道
|
||||
try {
|
||||
streamProxyPlayService.start(channel.getDataDeviceId(), record, callback);
|
||||
}catch (Exception e) {
|
||||
callback.run(Response.BUSY_HERE, "busy here", null);
|
||||
public void stopPlayback(CommonGBChannel channel, String stream) {
|
||||
log.info("[通用通道] 停止回放, 类型: {}, 编号:{}", channel.getDataType(), channel.getGbDeviceId());
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePlaybackService playbackService = sourcePlaybackServiceMap.get(ChannelDataType.PLAYBACK_SERVICE + dataType);
|
||||
if (playbackService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型编号: {} 不支持回放", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
playbackService.stopPlayback(channel, stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopPlayProxy(CommonGBChannel channel) {
|
||||
// 拉流代理通道
|
||||
try {
|
||||
streamProxyPlayService.stop(channel.getDataDeviceId());
|
||||
}catch (Exception e) {
|
||||
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
|
||||
public void stopDownload(CommonGBChannel channel, String stream) {
|
||||
log.info("[通用通道] 停止录像下载, 类型: {}, 编号:{} stream: {}", channel.getDataType(), channel.getGbDeviceId(), stream);
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourceDownloadService downloadService = sourceDownloadServiceMap.get(ChannelDataType.DOWNLOAD_SERVICE + dataType);
|
||||
if (downloadService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型编号: {} 不支持录像下载", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
downloadService.stopDownload(channel, stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playPush(CommonGBChannel channel, String platformDeviceId, String platformName, ErrorCallback<StreamInfo> callback){
|
||||
// 推流
|
||||
try {
|
||||
streamPushPlayService.start(channel.getDataDeviceId(), callback, platformDeviceId, platformName);
|
||||
}catch (PlayException e) {
|
||||
callback.run(e.getCode(), e.getMsg(), null);
|
||||
}catch (Exception e) {
|
||||
log.error("[点播推流通道失败] 通道: {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
|
||||
callback.run(Response.BUSY_HERE, "busy here", null);
|
||||
public void playbackPause(CommonGBChannel channel, String stream) {
|
||||
log.info("[通用通道] 回放暂停, 类型: {}, 编号:{} stream:{}", channel.getDataType(), channel.getGbDeviceId(), stream);
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePlaybackService playbackService = sourcePlaybackServiceMap.get(ChannelDataType.PLAYBACK_SERVICE + dataType);
|
||||
if (playbackService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型编号: {} 不支持回放暂停", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
playbackService.playbackPause(channel, stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopPlayPush(CommonGBChannel channel) {
|
||||
// 推流
|
||||
try {
|
||||
streamPushPlayService.stop(channel.getDataDeviceId());
|
||||
}catch (Exception e) {
|
||||
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void playbackGbDeviceChannel(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback){
|
||||
try {
|
||||
deviceChannelPlayService.playBack(channel, startTime, stopTime, callback);
|
||||
} catch (PlayException e) {
|
||||
callback.run(e.getCode(), e.getMsg(), null);
|
||||
} catch (Exception e) {
|
||||
callback.run(Response.BUSY_HERE, "busy here", null);
|
||||
public void playbackResume(CommonGBChannel channel, String stream) {
|
||||
log.info("[通用通道] 回放暂停恢复, 类型: {}, 编号:{} stream:{}", channel.getDataType(), channel.getGbDeviceId(), stream);
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePlaybackService playbackService = sourcePlaybackServiceMap.get(ChannelDataType.PLAYBACK_SERVICE + dataType);
|
||||
if (playbackService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型编号: {} 不支持回放暂停恢复", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
playbackService.playbackResume(channel, stream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pauseRtp(String streamId) {
|
||||
try {
|
||||
deviceChannelPlayService.pauseRtp(streamId);
|
||||
} catch (ServiceException | InvalidArgumentException | ParseException | SipException ignore) {}
|
||||
public void playbackSeek(CommonGBChannel channel, String stream, long seekTime) {
|
||||
log.info("[通用通道] 回放拖动播放, 类型: {}, 编号:{} stream:{}", channel.getDataType(), channel.getGbDeviceId(), stream);
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePlaybackService playbackService = sourcePlaybackServiceMap.get(ChannelDataType.PLAYBACK_SERVICE + dataType);
|
||||
if (playbackService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型编号: {} 不支持回放暂停恢复", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
playbackService.playbackSeek(channel, stream, seekTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeRtp(String streamId) {
|
||||
try {
|
||||
deviceChannelPlayService.resumeRtp(streamId);
|
||||
} catch (ServiceException | InvalidArgumentException | ParseException | SipException ignore) {}
|
||||
}
|
||||
|
||||
private void downloadGbDeviceChannel(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed,
|
||||
ErrorCallback<StreamInfo> callback){
|
||||
try {
|
||||
deviceChannelPlayService.download(channel, startTime, stopTime, downloadSpeed, callback);
|
||||
} catch (PlayException e) {
|
||||
callback.run(e.getCode(), e.getMsg(), null);
|
||||
} catch (Exception e) {
|
||||
callback.run(Response.BUSY_HERE, "busy here", null);
|
||||
public void playbackSpeed(CommonGBChannel channel, String stream, Double speed) {
|
||||
log.info("[通用通道] 回放倍速播放, 类型: {}, 编号:{} stream:{}", channel.getDataType(), channel.getGbDeviceId(), stream);
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePlaybackService playbackService = sourcePlaybackServiceMap.get(ChannelDataType.PLAYBACK_SERVICE + dataType);
|
||||
if (playbackService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型编号: {} 不支持回放暂停恢复", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
playbackService.playbackSpeed(channel, stream, speed);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void queryRecord(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<List<CommonRecordInfo>> callback) {
|
||||
log.info("[通用通道] 录像查询, 类型: {}, 编号:{}", channel.getDataType(), channel.getGbDeviceId());
|
||||
Integer dataType = channel.getDataType();
|
||||
ISourcePlaybackService playbackService = sourcePlaybackServiceMap.get(ChannelDataType.PLAYBACK_SERVICE + dataType);
|
||||
if (playbackService == null) {
|
||||
// 通道数据异常
|
||||
log.error("[点播通用通道] 类型编号: {} 不支持回放暂停恢复", dataType);
|
||||
throw new PlayException(Response.BUSY_HERE, "channel not support");
|
||||
}
|
||||
playbackService.queryRecord(channel, startTime, endTime, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,12 +366,12 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
log.warn("[重置国标通道] 未找到对应Id的通道: id: {}", id);
|
||||
throw new ControllerException(ErrorCode.ERROR400);
|
||||
}
|
||||
if (channel.getDataType() != ChannelDataType.GB28181.value) {
|
||||
if (channel.getDataType() != ChannelDataType.GB28181) {
|
||||
log.warn("[重置国标通道] 非国标下级通道无法重置: id: {}", id);
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "非国标下级通道无法重置");
|
||||
}
|
||||
// 这个多加一个参数,为了防止将非国标的通道通过此方法清空内容,导致意外发生
|
||||
commonGBChannelMapper.reset(id, ChannelDataType.GB28181.value, channel.getDataDeviceId(), DateUtil.getNow());
|
||||
commonGBChannelMapper.reset(id, ChannelDataType.GB28181, channel.getDataDeviceId(), DateUtil.getNow());
|
||||
CommonGBChannel channelNew = getOne(id);
|
||||
// 发送通过更新通知
|
||||
try {
|
||||
@@ -494,7 +494,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
|
||||
@Override
|
||||
public void addChannelToRegionByGbDevice(String civilCode, List<Integer> deviceIds) {
|
||||
List<CommonGBChannel> channelList = commonGBChannelMapper.queryByGbDeviceIds(ChannelDataType.GB28181.value, deviceIds);
|
||||
List<CommonGBChannel> channelList = commonGBChannelMapper.queryByGbDeviceIds(ChannelDataType.GB28181, deviceIds);
|
||||
if (channelList.isEmpty()) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "所有通道Id不存在");
|
||||
}
|
||||
@@ -515,7 +515,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
|
||||
@Override
|
||||
public void deleteChannelToRegionByGbDevice(List<Integer> deviceIds) {
|
||||
List<CommonGBChannel> channelList = commonGBChannelMapper.queryByGbDeviceIds(ChannelDataType.GB28181.value, deviceIds);
|
||||
List<CommonGBChannel> channelList = commonGBChannelMapper.queryByGbDeviceIds(ChannelDataType.GB28181, deviceIds);
|
||||
if (channelList.isEmpty()) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "所有通道Id不存在");
|
||||
}
|
||||
@@ -632,7 +632,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
@Override
|
||||
@Transactional
|
||||
public void addChannelToGroupByGbDevice(String parentId, String businessGroup, List<Integer> deviceIds) {
|
||||
List<CommonGBChannel> channelList = commonGBChannelMapper.queryByGbDeviceIds(ChannelDataType.GB28181.value, deviceIds);
|
||||
List<CommonGBChannel> channelList = commonGBChannelMapper.queryByGbDeviceIds(ChannelDataType.GB28181, deviceIds);
|
||||
if (channelList.isEmpty()) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "所有通道Id不存在");
|
||||
}
|
||||
@@ -660,7 +660,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
|
||||
@Override
|
||||
public void deleteChannelToGroupByGbDevice(List<Integer> deviceIds) {
|
||||
List<CommonGBChannel> channelList = commonGBChannelMapper.queryByGbDeviceIds(ChannelDataType.GB28181.value, deviceIds);
|
||||
List<CommonGBChannel> channelList = commonGBChannelMapper.queryByGbDeviceIds(ChannelDataType.GB28181, deviceIds);
|
||||
if (channelList.isEmpty()) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "所有通道Id不存在");
|
||||
}
|
||||
@@ -702,7 +702,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
|
||||
@Override
|
||||
public List<CommonGBChannel> queryListByStreamPushList(List<StreamPush> streamPushList) {
|
||||
return commonGBChannelMapper.queryListByStreamPushList(ChannelDataType.STREAM_PUSH.value, streamPushList);
|
||||
return commonGBChannelMapper.queryListByStreamPushList(ChannelDataType.STREAM_PUSH, streamPushList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -717,25 +717,6 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryRecordInfo(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<RecordInfo> callback) {
|
||||
if (channel.getDataType() == ChannelDataType.GB28181.value) {
|
||||
deviceChannelService.queryRecordInfo(channel, startTime, endTime, callback);
|
||||
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY.value) {
|
||||
// 拉流代理
|
||||
log.warn("[下载通用通道录像] 不支持下载拉流代理的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||
throw new PlayException(Response.FORBIDDEN, "forbidden");
|
||||
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH.value) {
|
||||
// 推流
|
||||
log.warn("[下载通用通道录像] 不支持下载推流的录像: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||
throw new PlayException(Response.FORBIDDEN, "forbidden");
|
||||
} else {
|
||||
// 通道数据异常
|
||||
log.error("[回放通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<CommonGBChannel> queryListByCivilCodeForUnusual(int page, int count, String query, Boolean online, Integer channelType) {
|
||||
PageHelper.startPage(page, count);
|
||||
@@ -790,4 +771,21 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
}
|
||||
commonGBChannelMapper.updateGpsByDeviceId(gpsMsgInfoList);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void updateGPS(List<CommonGBChannel> commonGBChannels) {
|
||||
int limitCount = 1000;
|
||||
if (commonGBChannels.size() > limitCount) {
|
||||
for (int i = 0; i < commonGBChannels.size(); i += limitCount) {
|
||||
int toIndex = i + limitCount;
|
||||
if (i + limitCount > commonGBChannels.size()) {
|
||||
toIndex = commonGBChannels.size();
|
||||
}
|
||||
commonGBChannelMapper.updateGps(commonGBChannels.subList(i, toIndex));
|
||||
}
|
||||
} else {
|
||||
commonGBChannelMapper.updateGps(commonGBChannels);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IGroupService;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -293,4 +295,16 @@ public class GroupServiceImpl implements IGroupService {
|
||||
allParent.add(parent);
|
||||
return allParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<Group> queryList(Integer page, Integer count, String query) {
|
||||
PageHelper.startPage(page, count);
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<Group> all = groupManager.query(query, null, null);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IPTZService;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcPlayService;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -21,7 +22,6 @@ import org.springframework.util.Assert;
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@@ -78,7 +78,7 @@ public class PTZServiceImpl implements IPTZService {
|
||||
|
||||
@Override
|
||||
public void frontEndCommand(CommonGBChannel channel, Integer cmdCode, Integer parameter1, Integer parameter2, Integer combindCode2) {
|
||||
if (channel.getDataType() != ChannelDataType.GB28181.value) {
|
||||
if (channel.getDataType() != ChannelDataType.GB28181) {
|
||||
// 只有国标通道的支持云台控制
|
||||
log.warn("[INFO 消息] 只有国标通道的支持云台控制, 通道ID: {}", channel.getGbId());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持");
|
||||
@@ -92,17 +92,20 @@ public class PTZServiceImpl implements IPTZService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Preset> queryPresetList(String deviceId, String channelDeviceId) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPreset(Preset preset) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePreset(Integer qq) {
|
||||
|
||||
public void queryPresetList(CommonGBChannel channel, ErrorCallback<List<Preset>> callback) {
|
||||
if (channel.getDataType() != ChannelDataType.GB28181) {
|
||||
// 只有国标通道的支持云台控制
|
||||
log.warn("[INFO 消息] 只有国标通道的支持云台控制, 通道ID: {}", channel.getGbId());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持");
|
||||
}
|
||||
Device device = deviceService.getDevice(channel.getDataDeviceId());
|
||||
if (device == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到设备");
|
||||
}
|
||||
DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId());
|
||||
if (deviceChannel == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到通道");
|
||||
}
|
||||
deviceService.queryPreset(device, deviceChannel.getDeviceId(), callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,14 +296,14 @@ public class PlatformChannelServiceImpl implements IPlatformChannelService {
|
||||
@Override
|
||||
@Transactional
|
||||
public void addChannelByDevice(Integer platformId, List<Integer> deviceIds) {
|
||||
List<Integer> channelList = commonGBChannelMapper.queryByGbDeviceIdsForIds(ChannelDataType.GB28181.value, deviceIds);
|
||||
List<Integer> channelList = commonGBChannelMapper.queryByGbDeviceIdsForIds(ChannelDataType.GB28181, deviceIds);
|
||||
addChannels(platformId, channelList);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void removeChannelByDevice(Integer platformId, List<Integer> deviceIds) {
|
||||
List<Integer> channelList = commonGBChannelMapper.queryByGbDeviceIdsForIds(ChannelDataType.GB28181.value, deviceIds);
|
||||
List<Integer> channelList = commonGBChannelMapper.queryByGbDeviceIdsForIds(ChannelDataType.GB28181, deviceIds);
|
||||
removeChannels(platformId, channelList);
|
||||
}
|
||||
|
||||
|
||||
@@ -398,6 +398,8 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
|
||||
SipTransactionInfo transactionInfo = statusTaskRunner.getRegisterTransactionInfo(platformInDb.getServerGBId());
|
||||
// 注销后出发平台离线, 如果是启用的平台,那么下次丢失检测会检测到并重新注册上线
|
||||
sendUnRegister(platformInDb, transactionInfo);
|
||||
}else if (platform.isEnable()) {
|
||||
sendRegister(platform, null);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -889,6 +891,9 @@ public class PlatformServiceImpl implements IPlatformService, CommandLineRunner
|
||||
|
||||
subscribeHolder.removeCatalogSubscribe(platform.getServerGBId());
|
||||
subscribeHolder.removeMobilePositionSubscribe(platform.getServerGBId());
|
||||
if (callback != null) {
|
||||
callback.run(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.common.InviteInfo;
|
||||
import com.genersoft.iot.vmp.common.*;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
@@ -34,7 +33,6 @@ import com.genersoft.iot.vmp.service.ISendRtpServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.*;
|
||||
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcPlayService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.utils.CloudRecordUtils;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
@@ -684,17 +682,11 @@ public class PlayServiceImpl implements IPlayService {
|
||||
* @param stream ssrc
|
||||
*/
|
||||
private void snapOnPlay(MediaServer mediaServerItemInuse, String deviceId, String channelId, String stream) {
|
||||
String streamUrl;
|
||||
if (mediaServerItemInuse.getRtspPort() != 0) {
|
||||
streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", stream);
|
||||
} else {
|
||||
streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.mp4", mediaServerItemInuse.getHttpPort(), "rtp", stream);
|
||||
}
|
||||
String path = "snap";
|
||||
String fileName = deviceId + "_" + channelId + ".jpg";
|
||||
// 请求截图
|
||||
log.info("[请求截图]: " + fileName);
|
||||
mediaServerService.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName);
|
||||
mediaServerService.getSnap(mediaServerItemInuse, "rtp", stream, 15, 1, path, fileName);
|
||||
}
|
||||
|
||||
public StreamInfo onPublishHandlerForPlay(MediaServer mediaServerItem, MediaInfo mediaInfo, Device device, DeviceChannel channel) {
|
||||
@@ -987,8 +979,8 @@ public class PlayServiceImpl implements IPlayService {
|
||||
}
|
||||
|
||||
|
||||
private void download(MediaServer mediaServerItem, Device device, DeviceChannel channel, String startTime, String endTime, int downloadSpeed, ErrorCallback<StreamInfo> callback) {
|
||||
if (mediaServerItem == null ) {
|
||||
private void download(MediaServer mediaServer, Device device, DeviceChannel channel, String startTime, String endTime, int downloadSpeed, ErrorCallback<StreamInfo> callback) {
|
||||
if (mediaServer == null ) {
|
||||
callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(),
|
||||
InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(),
|
||||
null);
|
||||
@@ -998,7 +990,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
int tcpMode = device.getStreamMode().equals("TCP-ACTIVE")? 2: (device.getStreamMode().equals("TCP-PASSIVE")? 1:0);
|
||||
// 录像下载不使用固定流地址,固定流地址会导致如果开始时间与结束时间一致时文件错误的叠加在一起
|
||||
RTPServerParam rtpServerParam = new RTPServerParam();
|
||||
rtpServerParam.setMediaServerItem(mediaServerItem);
|
||||
rtpServerParam.setMediaServerItem(mediaServer);
|
||||
rtpServerParam.setSsrcCheck(device.isSsrcCheck());
|
||||
rtpServerParam.setPlayback(true);
|
||||
rtpServerParam.setPort(0);
|
||||
@@ -1008,7 +1000,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
SSRCInfo ssrcInfo = receiveRtpServerService.openRTPServer(rtpServerParam, (code, msg, result) -> {
|
||||
if (code == InviteErrorCode.SUCCESS.getCode() && result != null && result.getHookData() != null) {
|
||||
// hook响应
|
||||
StreamInfo streamInfo = onPublishHandlerForDownload(mediaServerItem, result.getHookData().getMediaInfo(), device, channel, startTime, endTime);
|
||||
StreamInfo streamInfo = onPublishHandlerForDownload(mediaServer, result.getHookData().getMediaInfo(), device, channel, startTime, endTime);
|
||||
if (streamInfo == null) {
|
||||
log.warn("[录像下载] 获取流地址信息失败");
|
||||
callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
|
||||
@@ -1016,7 +1008,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
return;
|
||||
}
|
||||
callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
|
||||
log.info("[录像下载] 调用成功 deviceId: {}, channelId: {}, 开始时间: {}, 结束时间: {}", device.getDeviceId(), channel, startTime, endTime);
|
||||
log.info("[录像下载] 调用成功 deviceId: {}, channelId: {}, 开始时间: {}, 结束时间: {}", device.getDeviceId(), channel.getDeviceId(), startTime, endTime);
|
||||
}else {
|
||||
if (callback != null) {
|
||||
callback.run(code, msg, null);
|
||||
@@ -1054,24 +1046,24 @@ public class PlayServiceImpl implements IPlayService {
|
||||
device.isSsrcCheck());
|
||||
|
||||
// 初始化redis中的invite消息状态
|
||||
InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channel.getId(), ssrcInfo.getStream(), ssrcInfo, mediaServerItem.getId(),
|
||||
mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.DOWNLOAD,
|
||||
InviteInfo inviteInfo = InviteInfo.getInviteInfo(device.getDeviceId(), channel.getId(), ssrcInfo.getStream(), ssrcInfo, mediaServer.getId(),
|
||||
mediaServer.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.DOWNLOAD,
|
||||
InviteSessionStatus.ready, true);
|
||||
inviteInfo.setStartTime(startTime);
|
||||
inviteInfo.setEndTime(endTime);
|
||||
|
||||
inviteStreamService.updateInviteInfo(inviteInfo);
|
||||
try {
|
||||
cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channel, startTime, endTime, downloadSpeed,
|
||||
cmder.downloadStreamCmd(mediaServer, ssrcInfo, device, channel, startTime, endTime, downloadSpeed,
|
||||
eventResult -> {
|
||||
// 对方返回错误
|
||||
callback.run(InviteErrorCode.FAIL.getCode(), String.format("录像下载失败, 错误码: %s, %s", eventResult.statusCode, eventResult.msg), null);
|
||||
receiveRtpServerService.closeRTPServer(mediaServerItem, ssrcInfo);
|
||||
receiveRtpServerService.closeRTPServer(mediaServer, ssrcInfo);
|
||||
sessionManager.removeByStream(ssrcInfo.getApp(), ssrcInfo.getStream());
|
||||
inviteStreamService.removeInviteInfo(inviteInfo);
|
||||
}, eventResult ->{
|
||||
// 处理收到200ok后的TCP主动连接以及SSRC不一致的问题
|
||||
InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channel,
|
||||
InviteOKHandler(eventResult, ssrcInfo, mediaServer, device, channel,
|
||||
callback, inviteInfo, InviteSessionType.DOWNLOAD);
|
||||
|
||||
// 注册录像回调事件,录像下载结束后写入下载地址
|
||||
@@ -1080,8 +1072,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
inviteInfo.getDeviceId(), inviteInfo.getChannelId(), ssrcInfo.getStream());
|
||||
log.info("[录像下载] 收到录像写入磁盘消息内容: " + hookData);
|
||||
RecordInfo recordInfo = hookData.getRecordInfo();
|
||||
String filePath = recordInfo.getFilePath();
|
||||
DownloadFileInfo downloadFileInfo = CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath);
|
||||
DownloadFileInfo downloadFileInfo = mediaServerService.getDownloadFilePath(mediaServer, recordInfo);
|
||||
InviteInfo inviteInfoForNew = inviteStreamService.getInviteInfo(inviteInfo.getType()
|
||||
, inviteInfo.getChannelId(), inviteInfo.getStream());
|
||||
if (inviteInfoForNew != null && inviteInfoForNew.getStreamInfo() != null) {
|
||||
@@ -1090,7 +1081,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
inviteStreamService.updateInviteInfo(inviteInfoForNew, 60*15L);
|
||||
}
|
||||
};
|
||||
Hook hook = Hook.getInstance(HookType.on_record_mp4, "rtp", ssrcInfo.getStream(), mediaServerItem.getId());
|
||||
Hook hook = Hook.getInstance(HookType.on_record_mp4, "rtp", ssrcInfo.getStream(), mediaServer.getId());
|
||||
// 设置过期时间,下载失败时自动处理订阅数据
|
||||
hook.setExpireTime(System.currentTimeMillis() + 24 * 60 * 60 * 1000);
|
||||
subscribe.addSubscribe(hook, hookEventForRecord);
|
||||
@@ -1098,7 +1089,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
log.error("[命令发送失败] 录像下载: {}", e.getMessage());
|
||||
callback.run(InviteErrorCode.FAIL.getCode(),e.getMessage(), null);
|
||||
receiveRtpServerService.closeRTPServer(mediaServerItem, ssrcInfo);
|
||||
receiveRtpServerService.closeRTPServer(mediaServer, ssrcInfo);
|
||||
sessionManager.removeByStream(ssrcInfo.getApp(), ssrcInfo.getStream());
|
||||
inviteStreamService.removeInviteInfo(inviteInfo);
|
||||
}
|
||||
@@ -1118,11 +1109,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
log.warn("[获取下载进度] 未查询到录像下载的信息 {}/{}-{}", device.getDeviceId(), channel.getDeviceId(), stream);
|
||||
return null;
|
||||
}
|
||||
String filePath = allList.get(0).getFilePath();
|
||||
if (filePath == null) {
|
||||
log.warn("[获取下载进度] 未查询到录像下载的文件路径 {}/{}-{}", device.getDeviceId(), channel.getDeviceId(), stream);
|
||||
return null;
|
||||
}
|
||||
|
||||
String mediaServerId = allList.get(0).getMediaServerId();
|
||||
MediaServer mediaServer = mediaServerService.getOne(mediaServerId);
|
||||
if (mediaServer == null) {
|
||||
@@ -1130,7 +1117,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
return null;
|
||||
}
|
||||
log.warn("[获取下载进度] 发现下载已经结束,直接从数据库获取到文件 {}/{}-{}", device.getDeviceId(), channel.getDeviceId(), stream);
|
||||
DownloadFileInfo downloadFileInfo = CloudRecordUtils.getDownloadFilePath(mediaServer, filePath);
|
||||
DownloadFileInfo downloadFileInfo = mediaServerService.getDownloadFilePath(mediaServer, RecordInfo.getInstance(allList.get(0)));
|
||||
StreamInfo streamInfo = new StreamInfo();
|
||||
streamInfo.setDownLoadFilePath(downloadFileInfo);
|
||||
streamInfo.setApp(app);
|
||||
@@ -1392,7 +1379,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException {
|
||||
public void playbackPause(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException {
|
||||
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
|
||||
if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
|
||||
@@ -1403,7 +1390,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备不存在");
|
||||
}
|
||||
if (!userSetting.getServerId().equals(device.getServerId())) {
|
||||
redisRpcPlayService.pauseRtp(device.getServerId(), streamId);
|
||||
redisRpcPlayService.playbackPause(device.getServerId(), streamId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1430,7 +1417,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException {
|
||||
public void playbackResume(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException {
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
|
||||
if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "streamId不存在");
|
||||
@@ -1440,7 +1427,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备不存在");
|
||||
}
|
||||
if (!userSetting.getServerId().equals(device.getServerId())) {
|
||||
redisRpcPlayService.resumeRtp(device.getServerId(), streamId);
|
||||
redisRpcPlayService.playbackResume(device.getServerId(), streamId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1464,6 +1451,32 @@ public class PlayServiceImpl implements IPlayService {
|
||||
cmder.playResumeCmd(device, channel, inviteInfo.getStreamInfo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSeek(String streamId, long seekTime) throws InvalidArgumentException, ParseException, SipException {
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
|
||||
|
||||
if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
|
||||
log.warn("streamId不存在!");
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
|
||||
}
|
||||
Device device = deviceService.getDeviceByDeviceId(inviteInfo.getDeviceId());
|
||||
DeviceChannel channel = deviceChannelService.getOneById(inviteInfo.getChannelId());
|
||||
cmder.playSeekCmd(device, channel, inviteInfo.getStreamInfo(), seekTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeed(String streamId, double speed) throws InvalidArgumentException, ParseException, SipException {
|
||||
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
|
||||
|
||||
if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
|
||||
log.warn("streamId不存在!");
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
|
||||
}
|
||||
Device device = deviceService.getDeviceByDeviceId(inviteInfo.getDeviceId());
|
||||
DeviceChannel channel = deviceChannelService.getOneById(inviteInfo.getChannelId());
|
||||
cmder.playSpeedCmd(device, channel, inviteInfo.getStreamInfo(), speed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startPushStream(SendRtpInfo sendRtpInfo, DeviceChannel channel, SIPResponse sipResponse, Platform platform, CallIdHeader callIdHeader) {
|
||||
// 开始发流
|
||||
@@ -1617,17 +1630,11 @@ public class PlayServiceImpl implements IPlayService {
|
||||
if (inviteInfo != null) {
|
||||
if (inviteInfo.getStreamInfo() != null) {
|
||||
// 已存在线直接截图
|
||||
MediaServer mediaServerItemInuse = inviteInfo.getStreamInfo().getMediaServer();
|
||||
String streamUrl;
|
||||
if (mediaServerItemInuse.getRtspPort() != 0) {
|
||||
streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", inviteInfo.getStreamInfo().getStream());
|
||||
}else {
|
||||
streamUrl = String.format("http://127.0.0.1:%s/%s/%s.live.mp4", mediaServerItemInuse.getHttpPort(), "rtp", inviteInfo.getStreamInfo().getStream());
|
||||
}
|
||||
MediaServer mediaServer = inviteInfo.getStreamInfo().getMediaServer();
|
||||
String path = "snap";
|
||||
// 请求截图
|
||||
log.info("[请求截图]: " + fileName);
|
||||
mediaServerService.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName);
|
||||
mediaServerService.getSnap(mediaServer, "rtp", inviteInfo.getStreamInfo().getStream(), 15, 1, path, fileName);
|
||||
File snapFile = new File(path + File.separator + fileName);
|
||||
if (snapFile.exists()) {
|
||||
errorCallback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), snapFile.getAbsoluteFile());
|
||||
|
||||
@@ -144,17 +144,12 @@ public class RegionServiceImpl implements IRegionService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RegionTree> queryForTree(String query, Integer parent, Boolean hasChannel) {
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<RegionTree> regionList = regionMapper.queryForTree(query, parent);
|
||||
public List<RegionTree> queryForTree(Integer parent, Boolean hasChannel) {
|
||||
List<RegionTree> regionList = regionMapper.queryForTree(parent);
|
||||
if (parent != null && hasChannel != null && hasChannel) {
|
||||
Region parentRegion = regionMapper.queryOne(parent);
|
||||
if (parentRegion != null) {
|
||||
List<RegionTree> channelList = commonGBChannelMapper.queryForRegionTreeByCivilCode(query, parentRegion.getDeviceId());
|
||||
List<RegionTree> channelList = commonGBChannelMapper.queryForRegionTreeByCivilCode(parentRegion.getDeviceId());
|
||||
regionList.addAll(channelList);
|
||||
}
|
||||
}
|
||||
@@ -324,4 +319,16 @@ public class RegionServiceImpl implements IRegionService {
|
||||
parentId = region.getId();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<Region> queryList(int page, int count, String query) {
|
||||
PageHelper.startPage(page, count);
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<Region> all = regionMapper.query(query, null);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IPlayService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.ISourceDownloadService;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service(ChannelDataType.DOWNLOAD_SERVICE + ChannelDataType.GB28181)
|
||||
public class SourceDownloadServiceForGbImpl implements ISourceDownloadService {
|
||||
|
||||
@Autowired
|
||||
private IPlayService deviceChannelPlayService;
|
||||
|
||||
@Override
|
||||
public void download(CommonGBChannel channel, Long startTime, Long stopTime, Integer downloadSpeed, ErrorCallback<StreamInfo> callback) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopDownload(CommonGBChannel channel, String stream) {
|
||||
// 国标通道
|
||||
try {
|
||||
deviceChannelPlayService.stop(InviteSessionType.DOWNLOAD, channel, stream);
|
||||
} catch (Exception e) {
|
||||
log.error("[停止下载失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IPTZService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.ISourcePTZService;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service(ChannelDataType.PTZ_SERVICE + ChannelDataType.GB28181)
|
||||
public class SourcePTZServiceForGbImpl implements ISourcePTZService {
|
||||
|
||||
@Autowired
|
||||
private IPTZService ptzService;
|
||||
|
||||
@Override
|
||||
public void ptz(CommonGBChannel channel, FrontEndControlCodeForPTZ frontEndControlCode, ErrorCallback<String> callback) {
|
||||
try {
|
||||
int cmdCode = 0;
|
||||
int panSpeed = 0;
|
||||
int titleSpeed = 0;
|
||||
int zoomSpeed = 0;
|
||||
if (frontEndControlCode != null) {
|
||||
if (frontEndControlCode.getPan() != null) {
|
||||
if (frontEndControlCode.getPan() == 0) {
|
||||
cmdCode = cmdCode | 1 << 1;
|
||||
} else if (frontEndControlCode.getPan() == 1) {
|
||||
cmdCode = cmdCode | 1;
|
||||
}
|
||||
}
|
||||
if (frontEndControlCode.getTilt() != null) {
|
||||
if (frontEndControlCode.getTilt() == 0) {
|
||||
cmdCode = cmdCode | 1 << 3;
|
||||
} else if (frontEndControlCode.getTilt() == 1) {
|
||||
cmdCode = cmdCode | 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (frontEndControlCode.getZoom() != null) {
|
||||
if (frontEndControlCode.getZoom() == 0) {
|
||||
cmdCode = cmdCode | 1 << 5;
|
||||
} else if (frontEndControlCode.getZoom() == 1) {
|
||||
cmdCode = cmdCode | 1 << 4;
|
||||
}
|
||||
}
|
||||
if (frontEndControlCode.getPanSpeed() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
if (frontEndControlCode.getTiltSpeed() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
if (frontEndControlCode.getZoomSpeed() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
panSpeed = (int)(frontEndControlCode.getPanSpeed()/100D* 255);
|
||||
titleSpeed = (int)(frontEndControlCode.getTiltSpeed()/100D* 255);;
|
||||
zoomSpeed = (int)(frontEndControlCode.getZoomSpeed()/100D* 16);
|
||||
}
|
||||
ptzService.frontEndCommand(channel, cmdCode, panSpeed, titleSpeed, zoomSpeed);
|
||||
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
|
||||
}catch (Exception e) {
|
||||
log.error("[云台控制失败] ", e);
|
||||
callback.run(ErrorCode.ERROR100.getCode(), e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preset(CommonGBChannel channel, FrontEndControlCodeForPreset frontEndControlCode, ErrorCallback<String> callback) {
|
||||
try {
|
||||
int cmdCode = 0;
|
||||
int parameter1 = 0;
|
||||
int parameter2 = 0;
|
||||
int parameter3 = 0;
|
||||
if (frontEndControlCode != null) {
|
||||
if (frontEndControlCode.getCode() != null) {
|
||||
if (frontEndControlCode.getCode() == 1) {
|
||||
cmdCode = 0x81;
|
||||
} else if (frontEndControlCode.getCode() == 2) {
|
||||
cmdCode = 0x82;
|
||||
}else if (frontEndControlCode.getCode() == 3) {
|
||||
cmdCode = 0x83;
|
||||
}
|
||||
}
|
||||
if (frontEndControlCode.getPresetId() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter2 = frontEndControlCode.getPresetId();
|
||||
}
|
||||
ptzService.frontEndCommand(channel, cmdCode, parameter1, parameter2, parameter3);
|
||||
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
|
||||
}catch (Exception e) {
|
||||
log.error("[预置位控制失败] ", e);
|
||||
callback.run(ErrorCode.ERROR100.getCode(), e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fi(CommonGBChannel channel, FrontEndControlCodeForFI frontEndControlCode, ErrorCallback<String> callback) {
|
||||
try {
|
||||
int cmdCode = 1 << 6;
|
||||
int focusSpeed = 0;
|
||||
int irisSpeed = 0;
|
||||
int parameter3 = 0;
|
||||
if (frontEndControlCode != null) {
|
||||
if (frontEndControlCode.getFocus() != null) {
|
||||
if (frontEndControlCode.getFocus() == 0) {
|
||||
cmdCode = cmdCode | 1 << 1;
|
||||
} else if (frontEndControlCode.getFocus() == 1) {
|
||||
cmdCode = cmdCode | 1;
|
||||
}else {
|
||||
log.error("[FI失败] 未知的聚焦指令 {}", frontEndControlCode.getFocus());
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "未知的指令", null);
|
||||
}
|
||||
}
|
||||
if (frontEndControlCode.getIris() != null) {
|
||||
if (frontEndControlCode.getIris() == 0) {
|
||||
cmdCode = cmdCode | 1 << 3;
|
||||
} else if (frontEndControlCode.getIris() == 1) {
|
||||
cmdCode = cmdCode | 1 << 2;
|
||||
}else {
|
||||
log.error("[FI失败] 未知的光圈指令 {}", frontEndControlCode.getIris());
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "未知的指令", null);
|
||||
}
|
||||
}
|
||||
if (frontEndControlCode.getFocusSpeed() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
if (frontEndControlCode.getIrisSpeed() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
focusSpeed = frontEndControlCode.getFocusSpeed();
|
||||
irisSpeed = frontEndControlCode.getIrisSpeed();
|
||||
}
|
||||
ptzService.frontEndCommand(channel, cmdCode, focusSpeed, irisSpeed, parameter3);
|
||||
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
|
||||
}catch (Exception e) {
|
||||
log.error("[云台控制失败] ", e);
|
||||
callback.run(ErrorCode.ERROR100.getCode(), e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tour(CommonGBChannel channel, FrontEndControlCodeForTour frontEndControlCode, ErrorCallback<String> callback) {
|
||||
try {
|
||||
int cmdCode = 0;
|
||||
int parameter1 = 0;
|
||||
int parameter2 = 0;
|
||||
int parameter3 = 0;
|
||||
if (frontEndControlCode != null) {
|
||||
if (frontEndControlCode.getCode() != null) {
|
||||
if (frontEndControlCode.getCode() == 1) {
|
||||
cmdCode = 0x84;
|
||||
if (frontEndControlCode.getPresetId() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter2 = frontEndControlCode.getPresetId();
|
||||
} else if (frontEndControlCode.getCode() == 2) {
|
||||
cmdCode = 0x85;
|
||||
if (frontEndControlCode.getPresetId() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter2 = frontEndControlCode.getPresetId();
|
||||
}else if (frontEndControlCode.getCode() == 3) {
|
||||
cmdCode = 0x86;
|
||||
if (frontEndControlCode.getPresetId() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter2 = frontEndControlCode.getPresetId();
|
||||
if (frontEndControlCode.getTourSpeed() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter3 = frontEndControlCode.getTourSpeed();
|
||||
}else if (frontEndControlCode.getCode() == 4) {
|
||||
cmdCode = 0x87;
|
||||
if (frontEndControlCode.getPresetId() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter2 = frontEndControlCode.getPresetId();
|
||||
if (frontEndControlCode.getTourTime() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter3 = frontEndControlCode.getTourTime();
|
||||
}else if (frontEndControlCode.getCode() == 5) {
|
||||
cmdCode = 0x88;
|
||||
}else if (frontEndControlCode.getCode() == 6) {
|
||||
}else {
|
||||
log.error("[巡航控制失败] 未知的指令 {}", frontEndControlCode.getCode());
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "未知的指令", null);
|
||||
}
|
||||
if (frontEndControlCode.getTourId() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter1 = frontEndControlCode.getTourId();
|
||||
}
|
||||
|
||||
}
|
||||
ptzService.frontEndCommand(channel, cmdCode, parameter1, parameter2, parameter3);
|
||||
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
|
||||
}catch (Exception e) {
|
||||
log.error("[巡航控制失败] ", e);
|
||||
callback.run(ErrorCode.ERROR100.getCode(), e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scan(CommonGBChannel channel, FrontEndControlCodeForScan frontEndControlCode, ErrorCallback<String> callback) {
|
||||
try {
|
||||
int cmdCode = 0;
|
||||
int parameter1 = 0;
|
||||
int parameter2 = 0;
|
||||
int parameter3 = 0;
|
||||
if (frontEndControlCode != null) {
|
||||
if (frontEndControlCode.getCode() != null) {
|
||||
if (frontEndControlCode.getCode() == 1) {
|
||||
cmdCode = 0x89;
|
||||
if (frontEndControlCode.getScanId() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter1 = frontEndControlCode.getScanId();
|
||||
} else if (frontEndControlCode.getCode() == 2) {
|
||||
cmdCode = 0x89;
|
||||
if (frontEndControlCode.getScanId() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter1 = frontEndControlCode.getScanId();
|
||||
parameter2 = 1;
|
||||
}else if (frontEndControlCode.getCode() == 3) {
|
||||
cmdCode = 0x89;
|
||||
if (frontEndControlCode.getScanId() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter1 = frontEndControlCode.getScanId();
|
||||
parameter2 = 2;
|
||||
}else if (frontEndControlCode.getCode() == 4) {
|
||||
cmdCode = 0x8A;
|
||||
if (frontEndControlCode.getScanId() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
if (frontEndControlCode.getScanSpeed() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter1 = frontEndControlCode.getScanId();
|
||||
parameter2 = frontEndControlCode.getScanSpeed();
|
||||
}else if (frontEndControlCode.getCode() == 5) {
|
||||
}else {
|
||||
log.error("[巡航控制失败] 未知的指令 {}", frontEndControlCode.getCode());
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "未知的指令", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
ptzService.frontEndCommand(channel, cmdCode, parameter1, parameter2, parameter3);
|
||||
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
|
||||
}catch (Exception e) {
|
||||
log.error("[巡航控制失败] ", e);
|
||||
callback.run(ErrorCode.ERROR100.getCode(), e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void auxiliary(CommonGBChannel channel, FrontEndControlCodeForAuxiliary frontEndControlCode, ErrorCallback<String> callback) {
|
||||
try {
|
||||
int cmdCode = 0;
|
||||
int parameter1 = 0;
|
||||
int parameter2 = 0;
|
||||
int parameter3 = 0;
|
||||
if (frontEndControlCode != null) {
|
||||
if (frontEndControlCode.getCode() != null) {
|
||||
if (frontEndControlCode.getCode() == 1) {
|
||||
cmdCode = 0x8C;
|
||||
if (frontEndControlCode.getAuxiliaryId() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter1 = frontEndControlCode.getAuxiliaryId();
|
||||
} else if (frontEndControlCode.getCode() == 2) {
|
||||
cmdCode = 0x8D;
|
||||
if (frontEndControlCode.getAuxiliaryId() == null) {
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "参数异常", null);
|
||||
return;
|
||||
}
|
||||
parameter1 = frontEndControlCode.getAuxiliaryId();
|
||||
}else {
|
||||
log.error("[辅助开关失败] 未知的指令 {}", frontEndControlCode.getCode());
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "未知的指令", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
ptzService.frontEndCommand(channel, cmdCode, parameter1, parameter2, parameter3);
|
||||
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
|
||||
}catch (Exception e) {
|
||||
log.error("[辅助开关失败] ", e);
|
||||
callback.run(ErrorCode.ERROR100.getCode(), e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wiper(CommonGBChannel channel, FrontEndControlCodeForWiper frontEndControlCode, ErrorCallback<String> callback) {
|
||||
try {
|
||||
int cmdCode = 0;
|
||||
int parameter1 = 1;
|
||||
int parameter2 = 0;
|
||||
int parameter3 = 0;
|
||||
if (frontEndControlCode != null) {
|
||||
if (frontEndControlCode.getCode() != null) {
|
||||
if (frontEndControlCode.getCode() == 1) {
|
||||
cmdCode = 0x8C;
|
||||
} else if (frontEndControlCode.getCode() == 2) {
|
||||
cmdCode = 0x8D;
|
||||
}else {
|
||||
log.error("[雨刷开关失败] 未知的指令 {}", frontEndControlCode.getCode());
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "未知的指令", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
ptzService.frontEndCommand(channel, cmdCode, parameter1, parameter2, parameter3);
|
||||
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), null);
|
||||
}catch (Exception e) {
|
||||
log.error("[雨刷开关失败] ", e);
|
||||
callback.run(ErrorCode.ERROR100.getCode(), e.getMessage(), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryPreset(CommonGBChannel channel, ErrorCallback<List<Preset>> callback) {
|
||||
ptzService.queryPresetList(channel, callback);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.PlayException;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IPlayService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.ISourcePlayService;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.sip.message.Response;
|
||||
|
||||
@Slf4j
|
||||
@Service(ChannelDataType.PLAY_SERVICE + ChannelDataType.GB28181)
|
||||
public class SourcePlayServiceForGbImpl implements ISourcePlayService {
|
||||
|
||||
@Autowired
|
||||
private IPlayService deviceChannelPlayService;
|
||||
|
||||
@Override
|
||||
public void play(CommonGBChannel channel, Platform platform, Boolean record, ErrorCallback<StreamInfo> callback) {
|
||||
// 国标通道
|
||||
try {
|
||||
deviceChannelPlayService.play(channel, record, callback);
|
||||
} catch (PlayException e) {
|
||||
callback.run(e.getCode(), e.getMsg(), null);
|
||||
} catch (ControllerException e) {
|
||||
log.error("[点播失败] {}({}), {}", channel.getGbName(), channel.getGbDeviceId(), e.getMsg());
|
||||
callback.run(Response.BUSY_HERE, "busy here", null);
|
||||
} catch (Exception e) {
|
||||
log.error("[点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
|
||||
callback.run(Response.BUSY_HERE, "busy here", null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopPlay(CommonGBChannel channel, String stream) {
|
||||
// 国标通道
|
||||
try {
|
||||
deviceChannelPlayService.stop(InviteSessionType.PLAY, channel, stream);
|
||||
} catch (Exception e) {
|
||||
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.common.InviteSessionType;
|
||||
import com.genersoft.iot.vmp.common.StreamInfo;
|
||||
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonRecordInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.PlayException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.RecordItem;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IPlayService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.ISourcePlaybackService;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.sip.message.Response;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service(ChannelDataType.PLAYBACK_SERVICE + ChannelDataType.GB28181)
|
||||
public class SourcePlaybackServiceForGbImpl implements ISourcePlaybackService {
|
||||
|
||||
@Autowired
|
||||
private IPlayService playService;
|
||||
|
||||
@Autowired
|
||||
private IDeviceChannelService channelService;
|
||||
|
||||
@Override
|
||||
public void playback(CommonGBChannel channel, Long startTime, Long stopTime, ErrorCallback<StreamInfo> callback) {
|
||||
try {
|
||||
playService.playBack(channel, startTime, stopTime, callback);
|
||||
} catch (PlayException e) {
|
||||
callback.run(e.getCode(), e.getMsg(), null);
|
||||
} catch (Exception e) {
|
||||
callback.run(Response.BUSY_HERE, "busy here", null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopPlayback(CommonGBChannel channel, String stream) {
|
||||
// 国标通道
|
||||
try {
|
||||
playService.stop(InviteSessionType.PLAYBACK, channel, stream);
|
||||
} catch (Exception e) {
|
||||
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackPause(CommonGBChannel channel, String stream) {
|
||||
// 国标通道
|
||||
try {
|
||||
playService.playbackPause(stream);
|
||||
} catch (Exception e) {
|
||||
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackResume(CommonGBChannel channel, String stream) {
|
||||
// 国标通道
|
||||
try {
|
||||
playService.playbackPause(stream);
|
||||
} catch (Exception e) {
|
||||
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSeek(CommonGBChannel channel, String stream, long seekTime) {
|
||||
// 国标通道
|
||||
try {
|
||||
playService.playbackPause(stream);
|
||||
} catch (Exception e) {
|
||||
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playbackSpeed(CommonGBChannel channel, String stream, Double speed) {
|
||||
// 国标通道
|
||||
try {
|
||||
playService.playbackSpeed(stream, speed);
|
||||
} catch (Exception e) {
|
||||
log.error("[停止点播失败] {}({})", channel.getGbName(), channel.getGbDeviceId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryRecord(CommonGBChannel channel, String startTime, String endTime, ErrorCallback<List<CommonRecordInfo>> callback) {
|
||||
channelService.queryRecordInfo(channel, startTime, endTime, (code, msg, data) -> {
|
||||
if (code == ErrorCode.SUCCESS.getCode()) {
|
||||
List<RecordItem> recordList = data.getRecordList();
|
||||
List<CommonRecordInfo> recordInfoList = new ArrayList<>();
|
||||
for (RecordItem recordItem : recordList) {
|
||||
CommonRecordInfo recordInfo = new CommonRecordInfo();
|
||||
recordInfo.setStartTime(recordItem.getStartTime());
|
||||
recordInfo.setEndTime(recordItem.getEndTime());
|
||||
recordInfo.setFileSize(recordItem.getFileSize());
|
||||
recordInfoList.add(recordInfo);
|
||||
}
|
||||
callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), recordInfoList);
|
||||
}else {
|
||||
callback.run(code, msg, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ public class DeviceStatusTaskInfo{
|
||||
private SipTransactionInfo transactionInfo;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
* 过期时间,单位毫秒
|
||||
*/
|
||||
private long expireTime;
|
||||
}
|
||||
|
||||
@@ -94,7 +94,10 @@ public class DeviceStatusTaskRunner {
|
||||
return false;
|
||||
}
|
||||
log.debug("[更新状态任务时间] 编号: {}", key);
|
||||
// 如果值更改时间,如果队列中有多个元素时 超时无法出发。目前采用移除再加入的方法
|
||||
delayQueue.remove(task);
|
||||
task.setDelayTime(expirationTime);
|
||||
delayQueue.offer(task);
|
||||
String redisKey = String.format("%s_%s_%s", prefix, userSetting.getServerId(), task.getDeviceId());
|
||||
Duration duration = Duration.ofSeconds((expirationTime - System.currentTimeMillis())/1000);
|
||||
redisTemplate.expire(redisKey, duration);
|
||||
@@ -118,7 +121,7 @@ public class DeviceStatusTaskRunner {
|
||||
if (taskInfo == null) {
|
||||
continue;
|
||||
}
|
||||
Long expire = redisTemplate.getExpire(redisKey);
|
||||
Long expire = redisTemplate.getExpire(redisKey, TimeUnit.MILLISECONDS);
|
||||
taskInfo.setExpireTime(expire);
|
||||
result.add(taskInfo);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public class SubscribeTaskInfo {
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
* 过期时间,单位: 秒
|
||||
*/
|
||||
private long expireTime;
|
||||
|
||||
|
||||
@@ -94,7 +94,9 @@ public class SubscribeTaskRunner{
|
||||
return false;
|
||||
}
|
||||
log.info("[更新订阅任务时间] {}, 编号: {}", task.getName(), key);
|
||||
delayQueue.remove(task);
|
||||
task.setDelayTime(expirationTime);
|
||||
delayQueue.offer(task);
|
||||
String redisKey = String.format("%s_%s_%s", prefix, userSetting.getServerId(), task.getKey());
|
||||
Duration duration = Duration.ofSeconds((expirationTime - System.currentTimeMillis())/1000);
|
||||
redisTemplate.expire(redisKey, duration);
|
||||
@@ -118,7 +120,7 @@ public class SubscribeTaskRunner{
|
||||
if (taskInfo == null) {
|
||||
continue;
|
||||
}
|
||||
Long expire = redisTemplate.getExpire(redisKey);
|
||||
Long expire = redisTemplate.getExpire(redisKey, TimeUnit.SECONDS);
|
||||
taskInfo.setExpireTime(expire);
|
||||
result.add(taskInfo);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
package com.genersoft.iot.vmp.gb28181.task.platformStatus;
|
||||
|
||||
import com.genersoft.iot.vmp.common.CommonCallback;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.Delayed;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 平台注册任务可序列化的信息
|
||||
@@ -23,7 +16,7 @@ public class PlatformRegisterTaskInfo{
|
||||
private SipTransactionInfo sipTransactionInfo;
|
||||
|
||||
/**
|
||||
* 过期时间
|
||||
* 过期时间,单位: 毫秒
|
||||
*/
|
||||
private long expireTime;
|
||||
}
|
||||
|
||||
@@ -108,19 +108,6 @@ public class PlatformStatusTaskRunner {
|
||||
return task.getSipTransactionInfo();
|
||||
}
|
||||
|
||||
public boolean updateRegisterDelay(String platformServerId, long expirationTime) {
|
||||
PlatformRegisterTask task = registerSubscribes.get(platformServerId);
|
||||
if (task == null) {
|
||||
return false;
|
||||
}
|
||||
log.info("[更新平台注册任务时间] 平台上级编号: {}", platformServerId);
|
||||
task.setDelayTime(expirationTime);
|
||||
String redisKey = String.format("%s_%s_%s", prefix, userSetting.getServerId(), platformServerId);
|
||||
Duration duration = Duration.ofSeconds((expirationTime - System.currentTimeMillis())/1000);
|
||||
redisTemplate.expire(redisKey, duration);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean containsRegister(String platformServerId) {
|
||||
return registerSubscribes.containsKey(platformServerId);
|
||||
}
|
||||
@@ -152,16 +139,6 @@ public class PlatformStatusTaskRunner {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean updateKeepAliveDelay(String platformServerId, long expirationTime) {
|
||||
PlatformKeepaliveTask task = keepaliveSubscribes.get(platformServerId);
|
||||
if (task == null) {
|
||||
return false;
|
||||
}
|
||||
log.info("[更新平台心跳任务时间] 平台上级编号: {}", platformServerId);
|
||||
task.setDelayTime(expirationTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean containsKeepAlive(String platformServerId) {
|
||||
return keepaliveSubscribes.containsKey(platformServerId);
|
||||
}
|
||||
@@ -179,7 +156,7 @@ public class PlatformStatusTaskRunner {
|
||||
if (taskInfo == null) {
|
||||
continue;
|
||||
}
|
||||
Long expire = redisTemplate.getExpire(redisKey);
|
||||
Long expire = redisTemplate.getExpire(redisKey, TimeUnit.MILLISECONDS);
|
||||
taskInfo.setExpireTime(expire);
|
||||
result.add(taskInfo);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import gov.nist.javax.sip.message.SIPRequest;
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:设备能力接口,用于定义设备的控制、查询能力
|
||||
@@ -256,7 +257,7 @@ public interface ISIPCommander {
|
||||
*
|
||||
* @param device 视频设备
|
||||
*/
|
||||
void presetQuery(Device device, String channelId, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException;
|
||||
void presetQuery(Device device, String channelId, ErrorCallback<List<Preset>> callback) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 查询移动设备位置数据
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||
import com.genersoft.iot.vmp.utils.IpPortUtil;
|
||||
import gov.nist.javax.sip.message.MessageFactoryImpl;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -90,7 +91,7 @@ public class SIPRequestHeaderPlarformProvider {
|
||||
|
||||
|
||||
Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(), fromTag, toTag, callIdHeader, expires);
|
||||
SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIp() + ":" + parentPlatform.getServerPort());
|
||||
SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), IpPortUtil.concatenateIpAndPort(parentPlatform.getServerIp(), String.valueOf(parentPlatform.getServerPort())));
|
||||
if (www == null) {
|
||||
AuthorizationHeader authorizationHeader = SipFactory.getInstance().createHeaderFactory().createAuthorizationHeader("Digest");
|
||||
String username = parentPlatform.getUsername();
|
||||
@@ -214,7 +215,7 @@ public class SIPRequestHeaderPlarformProvider {
|
||||
public SIPRequest createNotifyRequest(Platform parentPlatform, String content, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException {
|
||||
SIPRequest request = null;
|
||||
// sipuri
|
||||
SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIp()+ ":" + parentPlatform.getServerPort());
|
||||
SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(parentPlatform.getServerGBId(), IpPortUtil.concatenateIpAndPort(parentPlatform.getServerIp(), String.valueOf(parentPlatform.getServerPort())));
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), parentPlatform.getDevicePort(),
|
||||
@@ -274,7 +275,7 @@ public class SIPRequestHeaderPlarformProvider {
|
||||
|
||||
SIPRequest request = null;
|
||||
// sipuri
|
||||
SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIp()+ ":" + platform.getServerPort());
|
||||
SipURI requestURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getServerGBId(), IpPortUtil.concatenateIpAndPort(platform.getServerIp(), String.valueOf(platform.getServerPort())));
|
||||
// via
|
||||
ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
|
||||
ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(platform.getDeviceIp(), platform.getDevicePort(),
|
||||
@@ -380,7 +381,7 @@ public class SIPRequestHeaderPlarformProvider {
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(platform.getDeviceIp())+":"+ platform.getDevicePort()));
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), IpPortUtil.concatenateIpAndPort(sipLayer.getLocalIp(platform.getDeviceIp()), String.valueOf(platform.getDevicePort()))));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.utils.GitUtil;
|
||||
import com.genersoft.iot.vmp.utils.IpPortUtil;
|
||||
import gov.nist.javax.sip.message.SIPRequest;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -106,7 +107,7 @@ public class SIPRequestHeaderProvider {
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), IpPortUtil.concatenateIpAndPort(sipLayer.getLocalIp(device.getLocalIp()), String.valueOf(sipConfig.getPort()))));
|
||||
// Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
// Subject
|
||||
@@ -142,7 +143,7 @@ public class SIPRequestHeaderProvider {
|
||||
CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.INVITE);
|
||||
request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader,fromHeader, toHeader, viaHeaders, maxForwards);
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), IpPortUtil.concatenateIpAndPort(sipLayer.getLocalIp(device.getLocalIp()), String.valueOf(sipConfig.getPort()))));
|
||||
// Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), device.getHost().getIp()+":"+device.getHost().getPort()));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
@@ -170,7 +171,7 @@ public class SIPRequestHeaderProvider {
|
||||
viaHeaders.add(viaHeader);
|
||||
//from
|
||||
// SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(),sipConfig.getDomain());
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp()) + ":" + sipConfig.getPort());
|
||||
SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), IpPortUtil.concatenateIpAndPort(sipLayer.getLocalIp(device.getLocalIp()), String.valueOf(sipConfig.getPort())));
|
||||
Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
|
||||
FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, transactionInfo.getFromTag());
|
||||
//to
|
||||
@@ -189,7 +190,7 @@ public class SIPRequestHeaderProvider {
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), IpPortUtil.concatenateIpAndPort(sipLayer.getLocalIp(device.getLocalIp()), String.valueOf(sipConfig.getPort()))));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
@@ -224,7 +225,7 @@ public class SIPRequestHeaderProvider {
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), IpPortUtil.concatenateIpAndPort(sipLayer.getLocalIp(device.getLocalIp()), String.valueOf(sipConfig.getPort()))));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
@@ -261,7 +262,7 @@ public class SIPRequestHeaderProvider {
|
||||
toHeader, viaHeaders, maxForwards);
|
||||
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), IpPortUtil.concatenateIpAndPort(sipLayer.getLocalIp(device.getLocalIp()), String.valueOf(sipConfig.getPort()))));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
// Expires
|
||||
@@ -314,7 +315,7 @@ public class SIPRequestHeaderProvider {
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipLayer.getLocalIp(device.getLocalIp())+":"+sipConfig.getPort()));
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), IpPortUtil.concatenateIpAndPort(sipLayer.getLocalIp(device.getLocalIp()), String.valueOf(sipConfig.getPort()))));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
@@ -345,7 +346,7 @@ public class SIPRequestHeaderProvider {
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), localIp + ":"+sipConfig.getPort()));
|
||||
Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), IpPortUtil.concatenateIpAndPort(localIp, String.valueOf(sipConfig.getPort()))));
|
||||
request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
|
||||
|
||||
request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
|
||||
|
||||
@@ -40,6 +40,7 @@ import javax.sip.SipFactory;
|
||||
import javax.sip.header.CallIdHeader;
|
||||
import javax.sip.message.Request;
|
||||
import java.text.ParseException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:设备能力接口,用于定义设备的控制、查询能力
|
||||
@@ -1118,7 +1119,7 @@ public class SIPCommander implements ISIPCommander {
|
||||
* @param device 视频设备
|
||||
*/
|
||||
@Override
|
||||
public void presetQuery(Device device, String channelId, ErrorCallback<Object> callback) throws InvalidArgumentException, SipException, ParseException {
|
||||
public void presetQuery(Device device, String channelId, ErrorCallback<List<Preset>> callback) throws InvalidArgumentException, SipException, ParseException {
|
||||
|
||||
String cmdType = "PresetQuery";
|
||||
int sn = (int) ((Math.random() * 9 + 1) * 100000);
|
||||
@@ -1136,10 +1137,10 @@ public class SIPCommander implements ISIPCommander {
|
||||
}
|
||||
cmdXml.append("</Query>\r\n");
|
||||
|
||||
MessageEvent<Object> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 1000L, callback);
|
||||
MessageEvent<List<Preset>> messageEvent = MessageEvent.getInstance(cmdType, sn + "", channelId, 4000L, callback);
|
||||
messageSubscribe.addSubscribe(messageEvent);
|
||||
|
||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
||||
log.info("[预置位查询] 设备编号: {}, 通道编号: {}, SN: {}", device.getDeviceId(), channelId, sn);
|
||||
Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
|
||||
sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, eventResult -> {
|
||||
messageSubscribe.removeSubscribe(messageEvent.getKey());
|
||||
callback.run(ErrorCode.ERROR100.getCode(), "失败," + eventResult.msg, null);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user