mirror of
https://gitee.com/pan648540858/wvp-GB28181-pro.git
synced 2026-05-27 07:27:49 +08:00
Compare commits
429 Commits
3a5513a2e6
...
9941608207
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9941608207 | ||
|
|
77594dae3d | ||
|
|
4280a1d08e | ||
|
|
8d6fe0c9d8 | ||
|
|
6469aefe22 | ||
|
|
bee911fa09 | ||
|
|
554a11ead6 | ||
|
|
c0ef35c3a0 | ||
|
|
602cd390e0 | ||
|
|
842647674a | ||
|
|
1156880194 | ||
|
|
dd2f99487d | ||
|
|
3009951e45 | ||
|
|
0ed37d58ec | ||
|
|
e7d26b34b3 | ||
|
|
f7eea28951 | ||
|
|
a706069e97 | ||
|
|
3a594f7bee | ||
|
|
15ff87a323 | ||
|
|
9edbcd9768 | ||
|
|
a2ac65dc70 | ||
|
|
ff0d54968d | ||
|
|
af3a283b3d | ||
|
|
fd306d8ede | ||
|
|
a064f27bf8 | ||
|
|
fb9ff67701 | ||
|
|
403e7648f9 | ||
|
|
c1672728d3 | ||
|
|
576feec514 | ||
|
|
5c83bf2a41 | ||
|
|
d96faa2459 | ||
|
|
27c7969b8f | ||
|
|
784c94cce8 | ||
|
|
6ae7bdc8e0 | ||
|
|
752ee1c290 | ||
|
|
18be8aff6c | ||
|
|
f0f62fa675 | ||
|
|
6ebeef33ae | ||
|
|
021e7a908f | ||
|
|
fed14aded4 | ||
|
|
dc5a66753c | ||
|
|
04742531fc | ||
|
|
5db66b0f40 | ||
|
|
416dac382e | ||
|
|
dfba1840e3 | ||
|
|
6f577268ee | ||
|
|
93724bac98 | ||
|
|
83662f4210 | ||
|
|
c11da964e2 | ||
|
|
2877d67e92 | ||
|
|
56d4e1ebd9 | ||
|
|
e7d1a24f3e | ||
|
|
ed00a2a75a | ||
|
|
1702907573 | ||
|
|
fad9f2954a | ||
|
|
45509372bd | ||
|
|
5c25385d29 | ||
|
|
1da487f02a | ||
|
|
e555df52d3 | ||
|
|
c90836261a | ||
|
|
d7f5e7d771 | ||
|
|
0a19ce4f34 | ||
|
|
efbd302260 | ||
|
|
09f1ef20a7 | ||
|
|
c75122008c | ||
|
|
e272d25939 | ||
|
|
2ee9a3fa71 | ||
|
|
333965255f | ||
|
|
3f6264cad9 | ||
|
|
8ec950d515 | ||
|
|
9614584219 | ||
|
|
19b873ba5c | ||
|
|
edeb8d6b3f | ||
|
|
61a761e288 | ||
|
|
867b26b9a8 | ||
|
|
24417203f0 | ||
|
|
f3bd58acfe | ||
|
|
9e880786b3 | ||
|
|
d51de48923 | ||
|
|
0ed395ff2e | ||
|
|
3cec9d2bd1 | ||
|
|
ed2f104529 | ||
|
|
4c97022c78 | ||
|
|
1693d904c4 | ||
|
|
c2d42d67c0 | ||
|
|
4fb04776f2 | ||
|
|
65553e966e | ||
|
|
e9eeeeefd7 | ||
|
|
49578e884f | ||
|
|
e9c227a3cf | ||
|
|
3b1a6b4903 | ||
|
|
f9f9d03502 | ||
|
|
47571962e6 | ||
|
|
a79429115f | ||
|
|
34fb79093e | ||
|
|
305c8ec8d7 | ||
|
|
43ef080f55 | ||
|
|
ee52b43c99 | ||
|
|
4cc399ce39 | ||
|
|
a69e3d5dde | ||
|
|
c0ab010475 | ||
|
|
79ee116174 | ||
|
|
045c14da0d | ||
|
|
0c78a9460b | ||
|
|
6e5cadd32b | ||
|
|
fb150da97a | ||
|
|
a4e20f0f50 | ||
|
|
9388c279e7 | ||
|
|
03b5c0241f | ||
|
|
a60eb082fe | ||
|
|
9d0678f765 | ||
|
|
9b0d091e4e | ||
|
|
ebd95250c0 | ||
|
|
47e4f2343b | ||
|
|
f7b35e8e14 | ||
|
|
8b17e97682 | ||
|
|
e730bf2d15 | ||
|
|
ca07935232 | ||
|
|
56b70d335a | ||
|
|
29802ccded | ||
|
|
3f2089f584 | ||
|
|
45af124eb0 | ||
|
|
5874d4d1fa | ||
|
|
d40bc5a034 | ||
|
|
44ed06bcbe | ||
|
|
be04660de8 | ||
|
|
e28141da6e | ||
|
|
04bcb6dcb8 | ||
|
|
9d47fe30f5 | ||
|
|
cefc87ad47 | ||
|
|
8c3e9320fa | ||
|
|
b7a2b6816b | ||
|
|
569b361a43 | ||
|
|
16fd1db833 | ||
|
|
9c2c727c8c | ||
|
|
42635592c6 | ||
|
|
1655e5903b | ||
|
|
055bbc2dca | ||
|
|
3c6b715ce1 | ||
|
|
3d9e718f26 | ||
|
|
67ef8ed8f0 | ||
|
|
48eff320fd | ||
|
|
8f2b107eab | ||
|
|
3c88f86a73 | ||
|
|
4765d0efa6 | ||
|
|
17c967ed4e | ||
|
|
fae839af05 | ||
|
|
70356c08d2 | ||
|
|
93c24a74e6 | ||
|
|
51759535fc | ||
|
|
51cd14e02e | ||
|
|
eddf20e62a | ||
|
|
a424f270e8 | ||
|
|
1bfb51c90e | ||
|
|
5bcdf5dfb6 | ||
|
|
bab5534134 | ||
|
|
537d86ca89 | ||
|
|
465e03d15d | ||
|
|
c79b7a9743 | ||
|
|
8d488b33e9 | ||
|
|
e194c027cb | ||
|
|
f8e5e8f057 | ||
|
|
9e8fbea73b | ||
|
|
0d6ed0a71e | ||
|
|
54f6ff9f81 | ||
|
|
5f4d78fe8f | ||
|
|
2b66404a2a | ||
|
|
380c42040f | ||
|
|
1c25f2f190 | ||
|
|
d9b750dc50 | ||
|
|
d507d075b1 | ||
|
|
592b1799e7 | ||
|
|
8c7b8eaeba | ||
|
|
6659779d91 | ||
|
|
b2000cba9a | ||
|
|
b5ca5feeea | ||
|
|
1c55bc3fd1 | ||
|
|
50df430831 | ||
|
|
371511f836 | ||
|
|
eada4a64dc | ||
|
|
196ecad3a3 | ||
|
|
d9b7be4814 | ||
|
|
1b35fbd0e0 | ||
|
|
2657d61c08 | ||
|
|
5aaa1c016b | ||
|
|
a948b78629 | ||
|
|
f4ba4ef159 | ||
|
|
8848de9d15 | ||
|
|
44bd521446 | ||
|
|
14c85838f4 | ||
|
|
d15307533a | ||
|
|
1420fcfcd0 | ||
|
|
0c29c90d3b | ||
|
|
420b3889c5 | ||
|
|
7c5cee5d87 | ||
|
|
27d7f3cc6e | ||
|
|
592c1c2b71 | ||
|
|
5b89145337 | ||
|
|
6a2ecd937d | ||
|
|
98e6cfcc4c | ||
|
|
081a146f2a | ||
|
|
68f7d3ef74 | ||
|
|
1a7f517c5a | ||
|
|
e4a0a37f0b | ||
|
|
c4ab55a456 | ||
|
|
10c75036f5 | ||
|
|
3b7ba3eb46 | ||
|
|
e754d0d804 | ||
|
|
e284c3857c | ||
|
|
f0eb101130 | ||
|
|
fd5079a652 | ||
|
|
20135726eb | ||
|
|
242062bda3 | ||
|
|
0329c8f5d1 | ||
|
|
51f126e571 | ||
|
|
4e48eb6cab | ||
|
|
1323d081e8 | ||
|
|
f528735119 | ||
|
|
d3d7ea8fbb | ||
|
|
991dd0ea41 | ||
|
|
1dfbb875b2 | ||
|
|
a4ca333abb | ||
|
|
e5fd66ef96 | ||
|
|
556f0ebf2f | ||
|
|
13b896ce23 | ||
|
|
f62b655602 | ||
|
|
46fa390387 | ||
|
|
277f2db137 | ||
|
|
601daa1092 | ||
|
|
03497c55f0 | ||
|
|
a5b48e5b19 | ||
|
|
b22e894e94 | ||
|
|
282e0db96e | ||
|
|
5db39a2265 | ||
|
|
edeea61318 | ||
|
|
a94b18bde9 | ||
|
|
5846a4ed5b | ||
|
|
358799a391 | ||
|
|
4ba04661ab | ||
|
|
36e15c80b0 | ||
|
|
449b215367 | ||
|
|
b034faad62 | ||
|
|
261945ca62 | ||
|
|
ff975b47ba | ||
|
|
93532a6b3b | ||
|
|
e0adc7306b | ||
|
|
291a87e1f7 | ||
|
|
46bf5b7a39 | ||
|
|
824690a37f | ||
|
|
3410fae879 | ||
|
|
c0dea69839 | ||
|
|
f564ff0aba | ||
|
|
a030c15c8f | ||
|
|
4b90298c99 | ||
|
|
b4dddb0b08 | ||
|
|
9c2c4a92b1 | ||
|
|
18cfba612b | ||
|
|
6074638f5b | ||
|
|
dbb2492640 | ||
|
|
7ffe773175 | ||
|
|
942a41c630 | ||
|
|
595d9be283 | ||
|
|
6ae623d639 | ||
|
|
0103d5819b | ||
|
|
972ef30f8d | ||
|
|
913d358a11 | ||
|
|
5d5d654410 | ||
|
|
f7d811a299 | ||
|
|
5c826ef449 | ||
|
|
0de2bb54cd | ||
|
|
83875a5905 | ||
|
|
3728219177 | ||
|
|
62ae1ee978 | ||
|
|
e8d832d0a5 | ||
|
|
89101b2731 | ||
|
|
56fdbd34f4 | ||
|
|
6efff9daf9 | ||
|
|
74c98c8636 | ||
|
|
15a551d983 | ||
|
|
2b1645729b | ||
|
|
84ef932964 | ||
|
|
2aef6ab6f1 | ||
|
|
de6a3ceb76 | ||
|
|
87ecf68332 | ||
|
|
01fbf102c2 | ||
|
|
3e9def7aac | ||
|
|
a945078788 | ||
|
|
9ece77d54a | ||
|
|
37b79633f0 | ||
|
|
98c62b93f7 | ||
|
|
bae9b2571a | ||
|
|
2c0c576d93 | ||
|
|
5011a6b74a | ||
|
|
271bb19c99 | ||
|
|
adfce4464d | ||
|
|
c8ddee905f | ||
|
|
8be6979911 | ||
|
|
1e9cdfe87f | ||
|
|
9817bf3fb7 | ||
|
|
82ab524fc4 | ||
|
|
e085258d74 | ||
|
|
2f1ebca335 | ||
|
|
b626a583f4 | ||
|
|
dcc20d0d15 | ||
|
|
6af9b8da1f | ||
|
|
e9562d7d31 | ||
|
|
b0e25ef784 | ||
|
|
7ddf066878 | ||
|
|
9161a090f6 | ||
|
|
7bf548492a | ||
|
|
e02a047eb2 | ||
|
|
aaa1d3a46f | ||
|
|
db4ba4035f | ||
|
|
cc71b7d9ca | ||
|
|
c6e3df685a | ||
|
|
ad67155d73 | ||
|
|
2112fffc26 | ||
|
|
364d613ccb | ||
|
|
c53e4f6fbc | ||
|
|
cc91db30c5 | ||
|
|
00749619da | ||
|
|
9280b57974 | ||
|
|
a3149139e2 | ||
|
|
58401b1444 | ||
|
|
4a5de5a2db | ||
|
|
faa0a01b9f | ||
|
|
5dd49b3d44 | ||
|
|
4011e54dd8 | ||
|
|
738b3b6a8e | ||
|
|
a5bfe5049d | ||
|
|
c946b97514 | ||
|
|
0fc0cd6e41 | ||
|
|
734f0c7e04 | ||
|
|
16bc3dabd6 | ||
|
|
7c833f3d12 | ||
|
|
e5acf7f1e4 | ||
|
|
eb43ffd98f | ||
|
|
e45b2479d3 | ||
|
|
7bdde6907a | ||
|
|
5be7c7636e | ||
|
|
76580d8fdc | ||
|
|
5b489d7c26 | ||
|
|
5a392372cb | ||
|
|
8aa97ba695 | ||
|
|
516c5ce3d1 | ||
|
|
9facff13b1 | ||
|
|
91b81ceb7a | ||
|
|
06b27beedc | ||
|
|
bc356849c7 | ||
|
|
225940825b | ||
|
|
62122f95f0 | ||
|
|
67b846fe2f | ||
|
|
714e1ff62c | ||
|
|
0058f1b0a9 | ||
|
|
34b6b516ab | ||
|
|
f9c22fcb3d | ||
|
|
c5ac7e218a | ||
|
|
975e94eee1 | ||
|
|
50e2565643 | ||
|
|
dd5ab573f2 | ||
|
|
a6236a2c13 | ||
|
|
16143a3fff | ||
|
|
fce96def9f | ||
|
|
570307669e | ||
|
|
205e529660 | ||
|
|
21e7ca0e46 | ||
|
|
6729df4992 | ||
|
|
c6bd4ac352 | ||
|
|
9f3cab6486 | ||
|
|
be787d1a14 | ||
|
|
8716160d96 | ||
|
|
9800fd6e7b | ||
|
|
4005a12403 | ||
|
|
59c91bdaf8 | ||
|
|
7d08b56267 | ||
|
|
05c83cf6ef | ||
|
|
1d36382986 | ||
|
|
bb350e847d | ||
|
|
d410a3ca18 | ||
|
|
b08f00104e | ||
|
|
2dc7eecb47 | ||
|
|
48a0e88b95 | ||
|
|
0077df29d4 | ||
|
|
5457407601 | ||
|
|
ae239c8848 | ||
|
|
9badf1c7fe | ||
|
|
d54787f323 | ||
|
|
8a2dc6031e | ||
|
|
9255ea802f | ||
|
|
349b0442d6 | ||
|
|
403eb4499d | ||
|
|
6757f4b719 | ||
|
|
8ba30e83ef | ||
|
|
98d9eb5314 | ||
|
|
a8a4aecc15 | ||
|
|
b649464753 | ||
|
|
ebdd9ab534 | ||
|
|
a1ab834875 | ||
|
|
4ec4d618d6 | ||
|
|
5fc1000fcc | ||
|
|
302eb98d51 | ||
|
|
984d8743be | ||
|
|
26bbeac6c7 | ||
|
|
81c2b5715c | ||
|
|
3e5da98539 | ||
|
|
a7b7371e74 | ||
|
|
0f420c43ac | ||
|
|
abc3766556 | ||
|
|
603ce18573 | ||
|
|
6acc395ad2 | ||
|
|
da33471dfd | ||
|
|
98199ec657 | ||
|
|
3e672ca38c | ||
|
|
9bc9dbe43b | ||
|
|
60d51cf23a | ||
|
|
93946407e8 | ||
|
|
23a72e94e6 | ||
|
|
d4c531dc12 | ||
|
|
dff7b8e31f | ||
|
|
e400c92f53 | ||
|
|
4eb0163e43 | ||
|
|
d78f76e58b | ||
|
|
44f17c723b | ||
|
|
18bd959541 | ||
|
|
dc38df6288 | ||
|
|
613452b3fc | ||
|
|
9494b6dc85 | ||
|
|
79dc7e79d2 | ||
|
|
6275372455 |
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`运行)
|
||||
|
||||
|
||||
其它的文件的作用暂不明确
|
||||
114
docker/build.sh
114
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)"
|
||||
|
||||
# 检查私有仓库环境变量
|
||||
if [ -z "$DOCKER_REGISTRY" ]; then
|
||||
echo "未设置DOCKER_REGISTRY环境变量"
|
||||
read -p "请输入私有Docker注册库地址(如不推送请留空): " input_registry
|
||||
docker_registry="$input_registry"
|
||||
else
|
||||
docker_registry="$DOCKER_REGISTRY"
|
||||
fi
|
||||
|
||||
# 定义要构建的镜像和对应的Dockerfile路径(相对当前工作目录)
|
||||
images=(
|
||||
"wvp-service:docker/wvp/Dockerfile"
|
||||
"wvp-nginx:docker/nginx/Dockerfile"
|
||||
)
|
||||
|
||||
# 构建镜像的函数
|
||||
build_image() {
|
||||
local image_name="$1"
|
||||
local dockerfile_path="$2"
|
||||
|
||||
cd ../../
|
||||
mkdir -p ./nginx/dist
|
||||
cp -r wvp-GB28181-pro/src/main/resources/static/* ./nginx/dist
|
||||
# 检查Dockerfile是否存在
|
||||
if [ ! -f "$dockerfile_path" ]; then
|
||||
echo "错误:未找到Dockerfile - \"$dockerfile_path\",跳过构建"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 构建镜像
|
||||
local full_image_name="${image_name}:${date_tag}"
|
||||
echo
|
||||
echo "=============================================="
|
||||
echo "开始构建镜像:${full_image_name}"
|
||||
echo "Dockerfile路径:${dockerfile_path}"
|
||||
|
||||
docker build -t "${full_image_name}" -f "${dockerfile_path}" .
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "镜像${full_image_name}构建失败"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 推送镜像(如果设置了仓库地址)
|
||||
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
|
||||
}
|
||||
|
||||
echo "构建ZLM容器"
|
||||
cd ./media/
|
||||
chmod +x ./build.sh
|
||||
./build.sh
|
||||
cd ../
|
||||
# 循环构建所有镜像
|
||||
for item in "${images[@]}"; do
|
||||
IFS=':' read -r image_name dockerfile_path <<< "$item"
|
||||
build_image "$image_name" "$dockerfile_path"
|
||||
done
|
||||
|
||||
echo "构建数据库容器"
|
||||
cd ./mysql/
|
||||
chmod +x ./build.sh
|
||||
./build.sh
|
||||
cd ../
|
||||
|
||||
echo "构建Redis容器"
|
||||
cd ./redis/
|
||||
chmod +x ./build.sh
|
||||
./build.sh
|
||||
cd ../
|
||||
|
||||
echo "构建WVP容器"
|
||||
cd ./wvp/
|
||||
chmod +x ./build.sh
|
||||
./build.sh
|
||||
cd ../
|
||||
|
||||
echo "构建Nginx容器"
|
||||
cd ./nginx/
|
||||
chmod +x ./build.sh
|
||||
./build.sh
|
||||
cd ../
|
||||
|
||||
./push.sh
|
||||
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
|
||||
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"]
|
||||
|
||||
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"]
|
||||
#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
|
||||
|
||||
|
||||
BIN
libs/smiley-http-proxy-servlet-2.0.jar
Normal file
BIN
libs/smiley-http-proxy-servlet-2.0.jar
Normal file
Binary file not shown.
137
pom.xml
137
pom.xml
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.7.18</version>
|
||||
<version>3.4.4</version>
|
||||
</parent>
|
||||
|
||||
<groupId>com.genersoft</groupId>
|
||||
@ -48,7 +48,6 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.build.timestamp.format>MMddHHmm</maven.build.timestamp.format>
|
||||
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
|
||||
|
||||
<!-- 依赖版本 -->
|
||||
<snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
|
||||
@ -56,6 +55,9 @@
|
||||
<generated.asciidoc.directory>${project.build.directory}/asciidoc</generated.asciidoc.directory>
|
||||
<asciidoctor.html.output.directory>${project.build.directory}/asciidoc/html</asciidoctor.html.output.directory>
|
||||
<asciidoctor.pdf.output.directory>${project.build.directory}/asciidoc/pdf</asciidoctor.pdf.output.directory>
|
||||
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<profiles>
|
||||
@ -113,6 +115,17 @@
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 日志相关 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
@ -121,7 +134,7 @@
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>2.2.2</version>
|
||||
<version>3.0.4</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
@ -139,14 +152,13 @@
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 数据库监控页面 -->
|
||||
<!-- h2 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>1.2.23</version>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>2.3.232</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- mysql数据库 -->
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
@ -180,42 +192,48 @@
|
||||
<systemPath>${basedir}/libs/jdbc-x86/kingbase8-8.6.0.jar</systemPath>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>cn.com.kingbase</groupId>-->
|
||||
<!-- <artifactId>kingbase8</artifactId>-->
|
||||
<!-- <version>8.6.0</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!--Mybatis分页插件 -->
|
||||
<dependency>
|
||||
<groupId>com.github.pagehelper</groupId>
|
||||
<artifactId>pagehelper-spring-boot-starter</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>2.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<!--在线文档 -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-ui</artifactId>
|
||||
<version>1.6.10</version>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>2.8.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
|
||||
<version>2.8.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-security</artifactId>
|
||||
<version>1.6.10</version>
|
||||
<version>1.8.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-springdoc-ui</artifactId>
|
||||
<version>3.0.3</version>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
<version>4.5.0</version>
|
||||
</dependency>
|
||||
|
||||
<!--参数校验 -->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 日志相关 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>javax.validation</groupId>-->
|
||||
<!-- <artifactId>validation-api</artifactId>-->
|
||||
<!-- <version>3.0.2</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!-- sip协议栈 -->
|
||||
<dependency>
|
||||
@ -228,14 +246,14 @@
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
<version>1.7.36</version>
|
||||
<version>2.0.17</version>
|
||||
</dependency>
|
||||
|
||||
<!-- xml解析库 -->
|
||||
<dependency>
|
||||
<groupId>org.dom4j</groupId>
|
||||
<artifactId>dom4j</artifactId>
|
||||
<version>2.1.3</version>
|
||||
<version>2.1.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- json解析库fastjson2 -->
|
||||
@ -259,21 +277,21 @@
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.10.0</version>
|
||||
<version>4.12.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- okhttp 调试日志 -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>logging-interceptor</artifactId>
|
||||
<version>4.10.0</version>
|
||||
<version>4.12.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- okhttp-digest -->
|
||||
<dependency>
|
||||
<groupId>io.github.rburgst</groupId>
|
||||
<artifactId>okhttp-digest</artifactId>
|
||||
<version>2.7</version>
|
||||
<version>3.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 -->
|
||||
@ -287,21 +305,20 @@
|
||||
<dependency>
|
||||
<groupId>org.bitbucket.b_c</groupId>
|
||||
<artifactId>jose4j</artifactId>
|
||||
<version>0.9.3</version>
|
||||
<version>0.9.6</version>
|
||||
</dependency>
|
||||
|
||||
<!--反向代理-->
|
||||
<dependency>
|
||||
<groupId>org.mitre.dsmiley.httpproxy</groupId>
|
||||
<artifactId>smiley-http-proxy-servlet</artifactId>
|
||||
<version>1.12.1</version>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.14</version>
|
||||
</dependency>
|
||||
|
||||
<!--excel解析库-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel</artifactId>
|
||||
<version>3.3.2</version>
|
||||
<version>4.0.3</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
@ -312,43 +329,44 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>1.24.0</version>
|
||||
<version>1.27.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 获取系统信息 -->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>6.2.2</version>
|
||||
<version>6.6.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 检测文件编码 -->
|
||||
<!-- https://mvnrepository.com/artifact/cpdetector/cpdetector -->
|
||||
<!--<dependency>-->
|
||||
<!-- <groupId>cpdetector</groupId>-->
|
||||
<!-- <artifactId>cpdetector</artifactId>-->
|
||||
<!-- <version>1.0.8</version>-->
|
||||
<!--</dependency>-->
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>32.1.3-jre</version>
|
||||
<version>33.4.8-jre</version>
|
||||
</dependency>
|
||||
|
||||
<!--ftp server-->
|
||||
<dependency>
|
||||
<groupId>org.apache.ftpserver</groupId>
|
||||
<artifactId>ftpserver-core</artifactId>
|
||||
<version>1.2.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.ftpserver</groupId>
|
||||
<artifactId>ftplet-api</artifactId>
|
||||
<version>1.2.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 自动化生成代码工具 -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<version>1.18.38</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!--LogViewer-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>io.github.sevdokimov.logviewer</groupId>-->
|
||||
@ -361,6 +379,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>
|
||||
@ -374,7 +393,7 @@
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.7.2</version>
|
||||
<version>3.4.10</version>
|
||||
<configuration>
|
||||
<includeSystemScope>true</includeSystemScope>
|
||||
<executable>true</executable>
|
||||
@ -384,10 +403,10 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<version>3.14.0</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<source>21</source>
|
||||
<target>21</target>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
@ -401,7 +420,7 @@
|
||||
<plugin>
|
||||
<groupId>pl.project13.maven</groupId>
|
||||
<artifactId>git-commit-id-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<version>4.9.10</version>
|
||||
<configuration>
|
||||
<offline>true</offline>
|
||||
<failOnNoGitDirectory>false</failOnNoGitDirectory>
|
||||
@ -412,7 +431,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
<version>3.2.5</version>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
@ -421,7 +440,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.4.2</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/配置详情.yml</exclude>
|
||||
|
||||
@ -13,10 +13,10 @@ import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.SessionCookieConfig;
|
||||
import javax.servlet.SessionTrackingMode;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.SessionCookieConfig;
|
||||
import jakarta.servlet.SessionTrackingMode;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -75,6 +75,21 @@ public class VideoManagerConstants {
|
||||
*/
|
||||
public static final String VM_MSG_PUSH_STREAM_LIST_CHANGE = "VM_MSG_PUSH_STREAM_LIST_CHANGE";
|
||||
|
||||
/**
|
||||
* 请求同步三方组织结构
|
||||
*/
|
||||
public static final String VM_MSG_GROUP_LIST_REQUEST = "VM_MSG_GROUP_LIST_REQUEST";
|
||||
|
||||
/**
|
||||
* 同步三方组织结构回复
|
||||
*/
|
||||
public static final String VM_MSG_GROUP_LIST_RESPONSE = "VM_MSG_GROUP_LIST_RESPONSE";
|
||||
|
||||
/**
|
||||
* 同步三方组织结构回复
|
||||
*/
|
||||
public static final String VM_MSG_GROUP_LIST_CHANGE = "VM_MSG_GROUP_LIST_CHANGE";
|
||||
|
||||
/**
|
||||
* redis 消息通知设备推流到平台
|
||||
*/
|
||||
@ -153,4 +168,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
@ -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,301 +0,0 @@
|
||||
package com.genersoft.iot.vmp.conf;
|
||||
|
||||
import com.genersoft.iot.vmp.media.bean.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.service.IMediaServerService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.mitre.dsmiley.httpproxy.ProxyServlet;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
|
||||
/**
|
||||
* @author lin
|
||||
*/
|
||||
@SuppressWarnings(value = {"rawtypes", "unchecked"})
|
||||
@Configuration
|
||||
@Order(1)
|
||||
@Slf4j
|
||||
public class ProxyServletConfig {
|
||||
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@Value("${server.port}")
|
||||
private int serverPort;
|
||||
|
||||
@Bean
|
||||
public ServletRegistrationBean zlmServletRegistrationBean(){
|
||||
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new ZlmProxyServlet(),"/zlm/*");
|
||||
servletRegistrationBean.setName("zlm_Proxy");
|
||||
servletRegistrationBean.addInitParameter("targetUri", "http://127.0.0.1:6080");
|
||||
servletRegistrationBean.addUrlMappings();
|
||||
if (log.isDebugEnabled()) {
|
||||
servletRegistrationBean.addInitParameter("log", "true");
|
||||
}
|
||||
return servletRegistrationBean;
|
||||
}
|
||||
|
||||
class ZlmProxyServlet extends ProxyServlet{
|
||||
@Override
|
||||
protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
|
||||
String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
|
||||
MediaServer mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
|
||||
if (mediaInfo != null) {
|
||||
if (!ObjectUtils.isEmpty(queryStr)) {
|
||||
queryStr += "&secret=" + mediaInfo.getSecret();
|
||||
}else {
|
||||
queryStr = "secret=" + mediaInfo.getSecret();
|
||||
}
|
||||
}
|
||||
return queryStr;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected HttpResponse doExecute(HttpServletRequest servletRequest, HttpServletResponse servletResponse,
|
||||
HttpRequest proxyRequest) throws IOException {
|
||||
HttpResponse response = super.doExecute(servletRequest, servletResponse, proxyRequest);
|
||||
response.removeHeaders("Access-Control-Allow-Origin");
|
||||
response.setHeader("Access-Control-Allow-Credentials","true");
|
||||
response.removeHeaders("Access-Control-Allow-Credentials");
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异常处理
|
||||
*/
|
||||
@Override
|
||||
protected void handleRequestException(HttpRequest proxyRequest, HttpResponse proxyResonse, Exception e){
|
||||
try {
|
||||
super.handleRequestException(proxyRequest, proxyResonse, e);
|
||||
} catch (ServletException servletException) {
|
||||
log.error("zlm 代理失败: ", e);
|
||||
} catch (IOException ioException) {
|
||||
if (ioException instanceof ConnectException) {
|
||||
log.error("zlm 连接失败");
|
||||
} else {
|
||||
log.error("zlm 代理失败: ", e);
|
||||
}
|
||||
} catch (RuntimeException exception){
|
||||
log.error("zlm 代理失败: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对于为按照格式请求的可以直接返回404
|
||||
*/
|
||||
@Override
|
||||
protected String getTargetUri(HttpServletRequest servletRequest) {
|
||||
String requestURI = servletRequest.getRequestURI();
|
||||
MediaServer mediaInfo = getMediaInfoByUri(requestURI);
|
||||
|
||||
String uri = null;
|
||||
if (mediaInfo != null) {
|
||||
// String realRequestURI = requestURI.substring(requestURI.indexOf(mediaInfo.getId())+ mediaInfo.getId().length());
|
||||
uri = String.format("http://%s:%s", mediaInfo.getIp(), mediaInfo.getHttpPort());
|
||||
}else {
|
||||
uri = "http://127.0.0.1:" + serverPort +"/index/hook/null"; // 只是一个能返回404的请求而已, 其他的也可以
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态替换请求目标
|
||||
*/
|
||||
@Override
|
||||
protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
|
||||
String requestURI = servletRequest.getRequestURI();
|
||||
MediaServer mediaInfo = getMediaInfoByUri(requestURI);
|
||||
HttpHost host;
|
||||
if (mediaInfo != null) {
|
||||
host = new HttpHost(mediaInfo.getIp(), mediaInfo.getHttpPort());
|
||||
}else {
|
||||
host = new HttpHost("127.0.0.1", serverPort);
|
||||
}
|
||||
return host;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据uri获取流媒体信息
|
||||
*/
|
||||
MediaServer getMediaInfoByUri(String uri){
|
||||
String[] split = uri.split("/");
|
||||
String mediaServerId = split[2];
|
||||
if ("default".equalsIgnoreCase(mediaServerId)) {
|
||||
return mediaServerService.getDefaultMediaServer();
|
||||
}else {
|
||||
return mediaServerService.getOne(mediaServerId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 去掉url中的标志信息
|
||||
*/
|
||||
@Override
|
||||
protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
|
||||
String requestURI = servletRequest.getRequestURI();
|
||||
MediaServer mediaInfo = getMediaInfoByUri(requestURI);
|
||||
String url = super.rewriteUrlFromRequest(servletRequest);
|
||||
if (mediaInfo == null) {
|
||||
log.error("[ZLM服务访问代理],错误:处理url信息时未找到流媒体信息=>{}", requestURI);
|
||||
return url;
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(mediaInfo.getId())) {
|
||||
url = url.replace(mediaInfo.getId() + "/", "");
|
||||
}
|
||||
return url.replace("default/", "");
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServletRegistrationBean recordServletRegistrationBean(){
|
||||
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new RecordProxyServlet(),"/record_proxy/*");
|
||||
servletRegistrationBean.setName("record_proxy");
|
||||
servletRegistrationBean.addInitParameter("targetUri", "http://127.0.0.1:18081");
|
||||
servletRegistrationBean.addUrlMappings();
|
||||
if (log.isDebugEnabled()) {
|
||||
servletRegistrationBean.addInitParameter("log", "true");
|
||||
}
|
||||
return servletRegistrationBean;
|
||||
}
|
||||
|
||||
class RecordProxyServlet extends ProxyServlet{
|
||||
|
||||
@Override
|
||||
protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
|
||||
String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);
|
||||
MediaServer mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI());
|
||||
if (mediaInfo == null) {
|
||||
return null;
|
||||
}
|
||||
String remoteHost = String.format("http://%s:%s", mediaInfo.getStreamIp(), mediaInfo.getRecordAssistPort());
|
||||
if (!ObjectUtils.isEmpty(queryStr)) {
|
||||
queryStr += "&remoteHost=" + remoteHost;
|
||||
}else {
|
||||
queryStr = "remoteHost=" + remoteHost;
|
||||
}
|
||||
return queryStr;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected HttpResponse doExecute(HttpServletRequest servletRequest, HttpServletResponse servletResponse,
|
||||
HttpRequest proxyRequest) throws IOException {
|
||||
HttpResponse response = super.doExecute(servletRequest, servletResponse, proxyRequest);
|
||||
String origin = servletRequest.getHeader("origin");
|
||||
response.setHeader("Access-Control-Allow-Origin",origin);
|
||||
response.setHeader("Access-Control-Allow-Credentials","true");
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 异常处理
|
||||
*/
|
||||
@Override
|
||||
protected void handleRequestException(HttpRequest proxyRequest, HttpResponse proxyResponse, Exception e){
|
||||
try {
|
||||
super.handleRequestException(proxyRequest, proxyResponse, e);
|
||||
} catch (ServletException servletException) {
|
||||
log.error("录像服务 代理失败: ", e);
|
||||
} catch (IOException ioException) {
|
||||
if (ioException instanceof ConnectException) {
|
||||
log.error("录像服务 连接失败");
|
||||
// }else if (ioException instanceof ClientAbortException) {
|
||||
// /**
|
||||
// * TODO 使用这个代理库实现代理在遇到代理视频文件时,如果是206结果,会遇到报错蛋市目前功能正常,
|
||||
// * TODO 暂时去除异常处理。后续使用其他代理框架修改测试
|
||||
// */
|
||||
|
||||
}else {
|
||||
log.error("录像服务 代理失败: ", e);
|
||||
}
|
||||
} catch (RuntimeException exception){
|
||||
log.error("录像服务 代理失败: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对于为按照格式请求的可以直接返回404
|
||||
*/
|
||||
@Override
|
||||
protected String getTargetUri(HttpServletRequest servletRequest) {
|
||||
String requestURI = servletRequest.getRequestURI();
|
||||
MediaServer mediaInfo = getMediaInfoByUri(requestURI);
|
||||
|
||||
String uri = null;
|
||||
if (mediaInfo != null) {
|
||||
// String realRequestURI = requestURI.substring(requestURI.indexOf(mediaInfo.getId())+ mediaInfo.getId().length());
|
||||
uri = String.format("http://%s:%s", mediaInfo.getIp(), mediaInfo.getRecordAssistPort());
|
||||
}else {
|
||||
uri = "http://127.0.0.1:" + serverPort +"/index/hook/null"; // 只是一个能返回404的请求而已, 其他的也可以
|
||||
}
|
||||
return uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* 动态替换请求目标
|
||||
*/
|
||||
@Override
|
||||
protected HttpHost getTargetHost(HttpServletRequest servletRequest) {
|
||||
String requestURI = servletRequest.getRequestURI();
|
||||
MediaServer mediaInfo = getMediaInfoByUri(requestURI);
|
||||
HttpHost host;
|
||||
if (mediaInfo != null) {
|
||||
host = new HttpHost(mediaInfo.getIp(), mediaInfo.getRecordAssistPort());
|
||||
}else {
|
||||
host = new HttpHost("127.0.0.1", serverPort);
|
||||
}
|
||||
return host;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据uri获取流媒体信息
|
||||
*/
|
||||
MediaServer getMediaInfoByUri(String uri){
|
||||
String[] split = uri.split("/");
|
||||
String mediaServerId = split[2];
|
||||
if ("default".equalsIgnoreCase(mediaServerId)) {
|
||||
return mediaServerService.getDefaultMediaServer();
|
||||
}else {
|
||||
return mediaServerService.getOne(mediaServerId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 去掉url中的标志信息
|
||||
*/
|
||||
@Override
|
||||
protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) {
|
||||
String requestURI = servletRequest.getRequestURI();
|
||||
MediaServer mediaInfo = getMediaInfoByUri(requestURI);
|
||||
String url = super.rewriteUrlFromRequest(servletRequest);
|
||||
if (mediaInfo == null) {
|
||||
log.error("[录像服务访问代理],错误:处理url信息时未找到流媒体信息=>{}", requestURI);
|
||||
return url;
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(mediaInfo.getId())) {
|
||||
url = url.replace(mediaInfo.getId() + "/", "");
|
||||
}
|
||||
return url.replace("default/", "");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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,19 @@ public class UserSetting {
|
||||
*/
|
||||
private boolean sipCacheServerConnections = true;
|
||||
|
||||
/**
|
||||
* 禁用date头,变相禁用了校时
|
||||
*/
|
||||
private boolean disableDateHeader = false;
|
||||
|
||||
/**
|
||||
* 同步业务分组时自动生成分组国标编号的模板,不配置则默认参考当前的sip域信息生成
|
||||
*/
|
||||
private String groupSyncDeviceTemplate;
|
||||
|
||||
/**
|
||||
* 与第三方进行分组同步时使用别名而不是分组ID, 如果没有设置此项为true,那么分组编号就是必须传递的。如果是设置为true则,自动为别名的分组生成新的编号
|
||||
*/
|
||||
private boolean useAliasForGroupSync = 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;
|
||||
}
|
||||
}
|
||||
@ -34,6 +34,11 @@ public class RedisMsgListenConfig {
|
||||
@Autowired
|
||||
private RedisPushStreamListMsgListener pushStreamListMsgListener;
|
||||
|
||||
@Autowired
|
||||
private RedisGroupMsgListener groupMsgListener;
|
||||
|
||||
@Autowired
|
||||
private RedisGroupChangeListener groupChangeListener;
|
||||
|
||||
@Autowired
|
||||
private RedisCloseStreamMsgListener redisCloseStreamMsgListener;
|
||||
@ -64,6 +69,8 @@ public class RedisMsgListenConfig {
|
||||
container.addMessageListener(redisCloseStreamMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_CLOSE));
|
||||
container.addMessageListener(redisRpcConfig, new PatternTopic(RedisRpcConfig.REDIS_REQUEST_CHANNEL_KEY));
|
||||
container.addMessageListener(redisPushStreamCloseResponseListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_RESPONSE));
|
||||
container.addMessageListener(groupMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_GROUP_LIST_RESPONSE));
|
||||
container.addMessageListener(groupChangeListener, new PatternTopic(VideoManagerConstants.VM_MSG_GROUP_LIST_CHANGE));
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,4 +42,5 @@ public class RedisTemplateConfig {
|
||||
redisTemplate.setConnectionFactory(redisConnectionFactory);
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -10,8 +10,8 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
|
||||
@ -11,10 +11,10 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@ -83,7 +83,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||
// TODO 处理各个状态
|
||||
switch (jwtUser.getStatus()){
|
||||
case EXPIRED:
|
||||
response.setStatus(400);
|
||||
response.setStatus(401);
|
||||
chain.doFilter(request, response);
|
||||
// 异常
|
||||
return;
|
||||
|
||||
@ -24,7 +24,7 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import jakarta.annotation.Resource;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
@ -58,7 +58,7 @@ public class JwtUtils implements InitializingBean {
|
||||
private static IUserService userService;
|
||||
|
||||
private static IUserApiKeyService userApiKeyService;
|
||||
|
||||
|
||||
private static UserSetting userSetting;
|
||||
|
||||
public static String getApiKeyHeader() {
|
||||
@ -231,12 +231,12 @@ public class JwtUtils implements InitializingBean {
|
||||
if (expirationTime != null) {
|
||||
// 判断是否即将过期, 默认剩余时间小于5分钟未即将过期
|
||||
// 剩余时间 (秒)
|
||||
long timeRemaining = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8)) - expirationTime.getValue();
|
||||
long timeRemaining = expirationTime.getValue() - LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8));
|
||||
if (timeRemaining < 5 * 60) {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON);
|
||||
} else {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
|
||||
}
|
||||
|
||||
@ -5,9 +5,9 @@ import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
||||
@ -7,14 +7,15 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
@ -35,7 +36,7 @@ import java.util.List;
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
@Order(1)
|
||||
@Slf4j
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
public class WebSecurityConfig {
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
@ -55,15 +56,13 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
@Autowired
|
||||
private JwtAuthenticationFilter jwtAuthenticationFilter;
|
||||
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
|
||||
return config.getAuthenticationManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置认证方式
|
||||
*
|
||||
* @param auth
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
@Bean
|
||||
public AuthenticationProvider authProvider() {
|
||||
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
|
||||
// 设置不隐藏 未找到用户异常
|
||||
provider.setHideUserNotFoundExceptions(true);
|
||||
@ -71,11 +70,11 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
provider.setUserDetailsService(userDetailsService);
|
||||
// 设置密码加密算法
|
||||
provider.setPasswordEncoder(passwordEncoder());
|
||||
auth.authenticationProvider(provider);
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
List<String> defaultExcludes = new ArrayList<>();
|
||||
defaultExcludes.add("/");
|
||||
defaultExcludes.add("/#/**");
|
||||
@ -100,34 +99,32 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
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());
|
||||
}
|
||||
|
||||
http.headers().contentTypeOptions().disable()
|
||||
.and().cors().configurationSource(configurationSource())
|
||||
.and().csrf().disable()
|
||||
.sessionManagement()
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
|
||||
http
|
||||
.headers(headers -> headers.contentTypeOptions(contentType -> contentType.disable()))
|
||||
.cors(cors -> cors.configurationSource(configurationSource()))
|
||||
.csrf(csrf -> csrf.disable())
|
||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.ALWAYS))
|
||||
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
// 配置拦截规则
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
|
||||
.antMatchers(defaultExcludes.toArray(new String[0])).permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
|
||||
.requestMatchers(defaultExcludes.toArray(new String[0])).permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
// 异常处理器
|
||||
.and()
|
||||
.exceptionHandling()
|
||||
.authenticationEntryPoint(anonymousAuthenticationEntryPoint)
|
||||
.and().logout().logoutUrl("/api/user/logout").permitAll()
|
||||
.logoutSuccessHandler(logoutHandler)
|
||||
;
|
||||
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
.exceptionHandling(exception -> exception.authenticationEntryPoint(anonymousAuthenticationEntryPoint))
|
||||
.logout(logout -> logout.logoutUrl("/api/user/logout")
|
||||
.permitAll()
|
||||
.logoutSuccessHandler(logoutHandler));
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
CorsConfigurationSource configurationSource() {
|
||||
@ -139,7 +136,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
if (userSetting.getAllowedOrigins() != null && !userSetting.getAllowedOrigins().isEmpty()) {
|
||||
corsConfiguration.setAllowCredentials(true);
|
||||
corsConfiguration.setAllowedOrigins(userSetting.getAllowedOrigins());
|
||||
}else {
|
||||
} else {
|
||||
// 在SpringBoot 2.4及以上版本处理跨域时,遇到错误提示:当allowCredentials为true时,allowedOrigins不能包含特殊值"*"。
|
||||
// 解决方法是明确指定allowedOrigins或使用allowedOriginPatterns。
|
||||
corsConfiguration.setAllowCredentials(true);
|
||||
@ -156,17 +153,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
/**
|
||||
* 描述: 密码加密算法 BCrypt 推荐使用
|
||||
**/
|
||||
@Bean
|
||||
public BCryptPasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 描述: 注入AuthenticationManager管理器
|
||||
**/
|
||||
@Override
|
||||
@Bean
|
||||
public AuthenticationManager authenticationManager() throws Exception {
|
||||
return super.authenticationManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,13 +2,13 @@ package com.genersoft.iot.vmp.conf.webLog;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.websocket.*;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import jakarta.websocket.*;
|
||||
import jakarta.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
@ServerEndpoint(value = "/channel/log")
|
||||
@ServerEndpoint(value = "/channel/log")
|
||||
@Slf4j
|
||||
public class LogChannel {
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@ import java.util.Random;
|
||||
@Slf4j
|
||||
public class DigestServerAuthenticationHelper {
|
||||
|
||||
private MessageDigest messageDigest;
|
||||
private final MessageDigest messageDigest;
|
||||
|
||||
public static final String DEFAULT_ALGORITHM = "MD5";
|
||||
public static final String DEFAULT_SCHEME = "Digest";
|
||||
@ -59,19 +59,18 @@ public class DigestServerAuthenticationHelper {
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
public DigestServerAuthenticationHelper()
|
||||
throws NoSuchAlgorithmException {
|
||||
messageDigest = MessageDigest.getInstance(DEFAULT_ALGORITHM);
|
||||
}
|
||||
|
||||
public static String toHexString(byte b[]) {
|
||||
public static String toHexString(byte[] b) {
|
||||
int pos = 0;
|
||||
char[] c = new char[b.length * 2];
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
c[pos++] = toHex[(b[i] >> 4) & 0x0F];
|
||||
c[pos++] = toHex[b[i] & 0x0f];
|
||||
for (byte value : b) {
|
||||
c[pos++] = toHex[(value >> 4) & 0x0F];
|
||||
c[pos++] = toHex[value & 0x0f];
|
||||
}
|
||||
return new String(c);
|
||||
}
|
||||
@ -87,8 +86,8 @@ public class DigestServerAuthenticationHelper {
|
||||
long pad = rand.nextLong();
|
||||
String nonceString = Long.valueOf(time).toString()
|
||||
+ Long.valueOf(pad).toString();
|
||||
byte mdbytes[] = messageDigest.digest(nonceString.getBytes());
|
||||
return toHexString(mdbytes);
|
||||
byte[] mdBytes = messageDigest.digest(nonceString.getBytes());
|
||||
return toHexString(mdBytes);
|
||||
}
|
||||
|
||||
public Response generateChallenge(HeaderFactory headerFactory, Response response, String realm) {
|
||||
@ -132,8 +131,6 @@ public class DigestServerAuthenticationHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
String A2 = request.getMethod().toUpperCase() + ":" + uri.toString();
|
||||
String HA1 = hashedPassword;
|
||||
|
||||
@ -177,12 +174,11 @@ public class DigestServerAuthenticationHelper {
|
||||
if ( authHeader == null || authHeader.getRealm() == null) {
|
||||
return false;
|
||||
}
|
||||
String realm = authHeader.getRealm().trim();
|
||||
String username = authHeader.getUsername().trim();
|
||||
|
||||
if ( username == null || realm == null ) {
|
||||
if ( authHeader.getUsername() == null || authHeader.getRealm() == null ) {
|
||||
return false;
|
||||
}
|
||||
String realm = authHeader.getRealm().trim();
|
||||
String username = authHeader.getUsername().trim();
|
||||
|
||||
String nonce = authHeader.getNonce();
|
||||
URI uri = authHeader.getURI();
|
||||
@ -199,26 +195,24 @@ public class DigestServerAuthenticationHelper {
|
||||
// nonce计数器,是一个16进制的数值,表示同一nonce下客户端发送出请求的数量
|
||||
int nc = authHeader.getNonceCount();
|
||||
String ncStr = String.format("%08x", nc).toUpperCase();
|
||||
// String ncStr = new DecimalFormat("00000000").format(nc);
|
||||
// String ncStr = new DecimalFormat("00000000").format(Integer.parseInt(nc + "", 16));
|
||||
|
||||
String A1 = username + ":" + realm + ":" + pass;
|
||||
|
||||
String A2 = request.getMethod().toUpperCase() + ":" + uri.toString();
|
||||
|
||||
byte mdbytes[] = messageDigest.digest(A1.getBytes());
|
||||
byte[] mdbytes = messageDigest.digest(A1.getBytes());
|
||||
String HA1 = toHexString(mdbytes);
|
||||
log.debug("A1: " + A1);
|
||||
log.debug("A2: " + A2);
|
||||
log.debug("A1: {}", A1);
|
||||
log.debug("A2: {}", A2);
|
||||
mdbytes = messageDigest.digest(A2.getBytes());
|
||||
String HA2 = toHexString(mdbytes);
|
||||
log.debug("HA1: " + HA1);
|
||||
log.debug("HA2: " + HA2);
|
||||
log.debug("HA1: {}", HA1);
|
||||
log.debug("HA2: {}", HA2);
|
||||
// String cnonce = authHeader.getCNonce();
|
||||
log.debug("nonce: " + nonce);
|
||||
log.debug("nc: " + ncStr);
|
||||
log.debug("cnonce: " + cnonce);
|
||||
log.debug("qop: " + qop);
|
||||
log.debug("nonce: {}", nonce);
|
||||
log.debug("nc: {}", ncStr);
|
||||
log.debug("cnonce: {}", cnonce);
|
||||
log.debug("qop: {}", qop);
|
||||
String KD = HA1 + ":" + nonce;
|
||||
|
||||
if (qop != null && qop.equalsIgnoreCase("auth") ) {
|
||||
@ -231,12 +225,12 @@ public class DigestServerAuthenticationHelper {
|
||||
KD += ":" + qop;
|
||||
}
|
||||
KD += ":" + HA2;
|
||||
log.debug("KD: " + KD);
|
||||
log.debug("KD: {}", KD);
|
||||
mdbytes = messageDigest.digest(KD.getBytes());
|
||||
String mdString = toHexString(mdbytes);
|
||||
log.debug("mdString: " + mdString);
|
||||
log.debug("mdString: {}", mdString);
|
||||
String response = authHeader.getResponse();
|
||||
log.debug("response: " + response);
|
||||
log.debug("response: {}", response);
|
||||
return mdString.equals(response);
|
||||
|
||||
}
|
||||
|
||||
@ -150,6 +150,12 @@ public class CommonGBChannel {
|
||||
@Schema(description = "更新时间")
|
||||
private String updateTime;
|
||||
|
||||
@Schema(description = "流唯一编号,存在表示正在直播")
|
||||
private String streamId;
|
||||
|
||||
@Schema(description = "是否支持对讲 1支持,0不支持")
|
||||
private Integer enableBroadcast;
|
||||
|
||||
public String encode(String serverDeviceId) {
|
||||
return encode(null, serverDeviceId);
|
||||
}
|
||||
@ -337,6 +343,9 @@ public class CommonGBChannel {
|
||||
if (this.getGbSvcTimeSupportMode() != null) {
|
||||
content.append(" <SVCTimeSupportMode>" + this.getGbSvcTimeSupportMode() + "</SVCTimeSupportMode>\n");
|
||||
}
|
||||
if (this.getEnableBroadcast() != null) {
|
||||
content.append(" <EnableBroadcast>" + this.getEnableBroadcast() + "</EnableBroadcast>\n");
|
||||
}
|
||||
content.append("</Info>\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
}
|
||||
@ -212,4 +212,8 @@ public class Device {
|
||||
|
||||
@Schema(description = "所属服务Id")
|
||||
private String serverId;
|
||||
|
||||
public boolean isWgs84() {
|
||||
return geoCoordSys.equalsIgnoreCase("WGS84");
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -116,7 +122,6 @@ public class DeviceChannel extends CommonGBChannel {
|
||||
@Schema(description = "经度 WGS-84坐标系")
|
||||
private Double longitude;
|
||||
|
||||
|
||||
@MessageElementForCatalog("Latitude")
|
||||
@Schema(description = ",纬度 WGS-84坐标系")
|
||||
private Double latitude;
|
||||
@ -173,9 +178,6 @@ public class DeviceChannel extends CommonGBChannel {
|
||||
@Schema(description = "子设备数")
|
||||
private int subCount;
|
||||
|
||||
@Schema(description = "流唯一编号,存在表示正在直播")
|
||||
private String streamId;
|
||||
|
||||
@Schema(description = "是否含有音频")
|
||||
private boolean hasAudio;
|
||||
|
||||
@ -189,7 +191,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;
|
||||
@ -233,7 +235,11 @@ public class DeviceChannel extends CommonGBChannel {
|
||||
GbCode gbCode = GbCode.decode(deviceChannel.getDeviceId());
|
||||
if (gbCode != null && "138".equals(gbCode.getTypeCode())) {
|
||||
deviceChannel.setHasAudio(true);
|
||||
if (deviceChannel.getEnableBroadcast() == null && "138".equals(gbCode.getTypeCode())) {
|
||||
deviceChannel.setEnableBroadcast(1);
|
||||
}
|
||||
}
|
||||
|
||||
return deviceChannel;
|
||||
}
|
||||
|
||||
@ -249,7 +255,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;
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 解析收到的前端控制指令
|
||||
|
||||
@ -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 "";
|
||||
}
|
||||
}
|
||||
@ -58,12 +58,19 @@ public class Group implements Comparable<Group>{
|
||||
*/
|
||||
@Schema(description = "更新时间")
|
||||
private String updateTime;
|
||||
|
||||
/**
|
||||
* 行政区划
|
||||
*/
|
||||
@Schema(description = "行政区划")
|
||||
private String civilCode;
|
||||
|
||||
/**
|
||||
* 别名
|
||||
*/
|
||||
@Schema(description = "别名, 此别名为唯一值,可以对接第三方是存储对方的ID")
|
||||
private String alias;
|
||||
|
||||
public static Group getInstance(DeviceChannel channel) {
|
||||
GbCode gbCode = GbCode.decode(channel.getDeviceId());
|
||||
if (gbCode == null || (!gbCode.getTypeCode().equals("215") && !gbCode.getTypeCode().equals("216"))) {
|
||||
|
||||
@ -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,15 +2,19 @@ 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;
|
||||
|
||||
/**
|
||||
* @description:设备录像信息bean
|
||||
/**
|
||||
* @description:设备录像信息bean
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月8日 下午2:05:56
|
||||
* @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,16 +3,20 @@ 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;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
|
||||
/**
|
||||
* @description:设备录像bean
|
||||
* @description:设备录像bean
|
||||
* @author: swwheihei
|
||||
* @date: 2020年5月8日 下午2:06:54
|
||||
* @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,67 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RedisGroupMessage {
|
||||
|
||||
/**
|
||||
* 分组国标ID
|
||||
*/
|
||||
private String groupGbId;
|
||||
|
||||
/**
|
||||
* 分组别名
|
||||
*/
|
||||
private String groupAlias;
|
||||
|
||||
/**
|
||||
* 分组名称
|
||||
*/
|
||||
private String groupName;
|
||||
|
||||
/**
|
||||
* 分组所属的行政区划
|
||||
*/
|
||||
private String groupCivilCode;
|
||||
|
||||
/**
|
||||
* 分组所属父分组国标ID
|
||||
*/
|
||||
private String parentGroupGbId;
|
||||
|
||||
/**
|
||||
* 分组所属父分组别名
|
||||
*/
|
||||
private String parentGAlias;
|
||||
|
||||
/**
|
||||
* 分组所属业务分组国标ID
|
||||
*/
|
||||
private String topGroupGbId;
|
||||
|
||||
/**
|
||||
* 分组所属业务分组别名
|
||||
*/
|
||||
private String topGroupGAlias;
|
||||
|
||||
/**
|
||||
* 分组变化消息中的消息类型,取值为 add update delete
|
||||
*/
|
||||
private String messageType;
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RedisGroupMessage{" +
|
||||
"groupGbId='" + groupGbId + '\'' +
|
||||
", groupAlias='" + groupAlias + '\'' +
|
||||
", groupName='" + groupName + '\'' +
|
||||
", groupCivilCode='" + groupCivilCode + '\'' +
|
||||
", parentGroupGbId='" + parentGroupGbId + '\'' +
|
||||
", parentGAlias='" + parentGAlias + '\'' +
|
||||
", topGroupGbId='" + topGroupGbId + '\'' +
|
||||
", topGroupGAlias='" + topGroupGAlias + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -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,21 +2,20 @@ 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;
|
||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelToRegionParam;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
||||
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;
|
||||
@ -24,6 +23,7 @@ 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 jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.Assert;
|
||||
@ -31,17 +31,17 @@ import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.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;
|
||||
@ -49,9 +49,6 @@ public class CommonChannelController {
|
||||
@Autowired
|
||||
private IGbChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private IMediaServerService mediaServerService;
|
||||
|
||||
@Autowired
|
||||
private IGbChannelPlayService channelPlayService;
|
||||
|
||||
@ -276,7 +273,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 +397,85 @@ 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);
|
||||
}
|
||||
|
||||
@Operation(summary = "为地图获取通道列表", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "query", description = "查询内容")
|
||||
@Parameter(name = "online", description = "是否在线")
|
||||
@Parameter(name = "hasRecordPlan", description = "是否已设置录制计划")
|
||||
@Parameter(name = "channelType", description = "通道类型, 0:国标设备,1:推流设备,2:拉流代理")
|
||||
@Parameter(name = "geoCoordSys", description = "地理坐标系, WGS84/GCJ02")
|
||||
@GetMapping("/map/list")
|
||||
public List<CommonGBChannel> queryListForMap(
|
||||
@RequestParam(required = false) String query,
|
||||
@RequestParam(required = false) Boolean online,
|
||||
@RequestParam(required = false) Boolean hasRecordPlan,
|
||||
@RequestParam(required = false) Integer channelType){
|
||||
if (ObjectUtils.isEmpty(query)){
|
||||
query = null;
|
||||
}
|
||||
return channelService.queryListForMap(query, online, hasRecordPlan, channelType);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 设备控制命令API接口
|
||||
*
|
||||
*
|
||||
* @author lawrencehj
|
||||
* @date 2021年2月1日
|
||||
*/
|
||||
@ -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(() -> {
|
||||
|
||||
@ -31,8 +31,8 @@ import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.ServletOutputStream;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -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)
|
||||
|
||||
@ -31,7 +31,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
||||
@ -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 jakarta.servlet.http.HttpServletRequest;
|
||||
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 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;
|
||||
}
|
||||
/**
|
||||
* 获取推流播放地址
|
||||
|
||||
@ -93,9 +93,6 @@ public class PlatformController {
|
||||
@ResponseBody
|
||||
public void add(@RequestBody Platform platform) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("保存上级平台信息API调用");
|
||||
}
|
||||
Assert.notNull(platform.getName(), "平台名称不可为空");
|
||||
Assert.notNull(platform.getServerGBId(), "上级平台国标编号不可为空");
|
||||
Assert.notNull(platform.getServerIp(), "上级平台IP不可为空");
|
||||
@ -140,9 +137,6 @@ public class PlatformController {
|
||||
@ResponseBody
|
||||
public void updatePlatform(@RequestBody Platform parentPlatform) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("保存上级平台信息API调用");
|
||||
}
|
||||
if (ObjectUtils.isEmpty(parentPlatform.getName())
|
||||
|| ObjectUtils.isEmpty(parentPlatform.getServerGBId())
|
||||
|| ObjectUtils.isEmpty(parentPlatform.getServerGBDomain())
|
||||
@ -163,16 +157,14 @@ public class PlatformController {
|
||||
@Parameter(name = "id", description = "上级平台ID")
|
||||
@DeleteMapping("/delete")
|
||||
@ResponseBody
|
||||
public DeferredResult<Object> deletePlatform(Integer id) {
|
||||
public DeferredResult<WVPResult<?>> deletePlatform(Integer id) {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("删除上级平台API调用");
|
||||
}
|
||||
DeferredResult<Object> deferredResult = new DeferredResult<>();
|
||||
DeferredResult<WVPResult<?>> deferredResult = new DeferredResult<>();
|
||||
|
||||
platformService.delete(id, (object)->{
|
||||
deferredResult.setResult(WVPResult.success());
|
||||
});
|
||||
platformService.delete(id, (object)-> deferredResult.setResult(WVPResult.success()));
|
||||
return deferredResult;
|
||||
}
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
@ -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;
|
||||
@ -33,7 +33,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.net.MalformedURLException;
|
||||
@ -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 = "更新区域")
|
||||
|
||||
@ -8,8 +8,8 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
|
||||
@ -57,7 +57,8 @@ public interface CommonGBChannelMapper {
|
||||
"gb_business_group_id," +
|
||||
"gb_download_speed," +
|
||||
"gb_svc_space_support_mod," +
|
||||
"gb_svc_time_support_mode ) " +
|
||||
"gb_svc_time_support_mode," +
|
||||
"enable_broadcast ) " +
|
||||
"VALUES (" +
|
||||
"#{gbDeviceId}, " +
|
||||
"#{dataType}, " +
|
||||
@ -96,7 +97,8 @@ public interface CommonGBChannelMapper {
|
||||
"#{gbBusinessGroupId},"+
|
||||
"#{gbDownloadSpeed},"+
|
||||
"#{gbSvcSpaceSupportMod},"+
|
||||
"#{gbSvcTimeSupportMode}"+
|
||||
"#{gbSvcTimeSupportMode},"+
|
||||
"#{enableBroadcast}"+
|
||||
")" +
|
||||
" </script>")
|
||||
@Options(useGeneratedKeys = true, keyProperty = "gbId", keyColumn = "id")
|
||||
@ -144,6 +146,7 @@ public interface CommonGBChannelMapper {
|
||||
", gb_download_speed = #{gbDownloadSpeed}" +
|
||||
", gb_svc_space_support_mod = #{gbSvcSpaceSupportMod}" +
|
||||
", gb_svc_time_support_mode = #{gbSvcTimeSupportMode}" +
|
||||
", enable_broadcast = #{enableBroadcast}" +
|
||||
" WHERE id = #{gbId}"+
|
||||
" </script>"})
|
||||
int update(CommonGBChannel commonGBChannel);
|
||||
@ -205,7 +208,8 @@ public interface CommonGBChannelMapper {
|
||||
"gb_business_group_id," +
|
||||
"gb_download_speed," +
|
||||
"gb_svc_space_support_mod," +
|
||||
"gb_svc_time_support_mode ) " +
|
||||
"gb_svc_time_support_mode," +
|
||||
"enable_broadcast ) " +
|
||||
"VALUES" +
|
||||
"<foreach collection='commonGBChannels' index='index' item='item' separator=','> " +
|
||||
"(#{item.gbDeviceId}, #{item.dataType}, #{item.dataDeviceId},#{item.createTime},#{item.updateTime}," +
|
||||
@ -214,7 +218,7 @@ public interface CommonGBChannelMapper {
|
||||
"#{item.gbRegisterWay},#{item.gbCertNum},#{item.gbCertifiable},#{item.gbErrCode},#{item.gbEndTime}, #{item.gbSecrecy},#{item.gbIpAddress}," +
|
||||
"#{item.gbPort},#{item.gbPassword},#{item.gbStatus},#{item.gbLongitude}, #{item.gbLatitude},#{item.gbPtzType},#{item.gbPositionType},#{item.gbRoomType}," +
|
||||
"#{item.gbUseType},#{item.gbSupplyLightType},#{item.gbDirectionType},#{item.gbResolution},#{item.gbBusinessGroupId},#{item.gbDownloadSpeed}," +
|
||||
"#{item.gbSvcSpaceSupportMod},#{item.gbSvcTimeSupportMode})" +
|
||||
"#{item.gbSvcSpaceSupportMod},#{item.gbSvcTimeSupportMode},#{item.enableBroadcast})" +
|
||||
"</foreach> " +
|
||||
" </script>")
|
||||
int batchAdd(List<CommonGBChannel> commonGBChannels);
|
||||
@ -275,10 +279,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 " +
|
||||
@ -426,6 +428,7 @@ public interface CommonGBChannelMapper {
|
||||
", gb_download_speed=#{item.gbDownloadSpeed}" +
|
||||
", gb_svc_space_support_mod=#{item.gbSvcSpaceSupportMod}" +
|
||||
", gb_svc_time_support_mode=#{item.gbSvcTimeSupportMode}" +
|
||||
", enable_broadcast = #{enableBroadcast}" +
|
||||
" WHERE id=#{item.gbId}" +
|
||||
"</foreach>" +
|
||||
"</script>"})
|
||||
@ -507,6 +510,7 @@ public interface CommonGBChannelMapper {
|
||||
" wdc.create_time,\n" +
|
||||
" wdc.update_time,\n" +
|
||||
" wdc.record_plan_id,\n" +
|
||||
" wdc.enable_broadcast,\n" +
|
||||
" coalesce( wdc.gb_device_id, wdc.device_id) as gb_device_id,\n" +
|
||||
" coalesce( wdc.gb_name, wdc.name) as gb_name,\n" +
|
||||
" coalesce( wdc.gb_manufacturer, wdc.manufacturer) as gb_manufacturer,\n" +
|
||||
@ -582,4 +586,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);
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelReduce;
|
||||
import com.genersoft.iot.vmp.gb28181.dao.provider.DeviceChannelProvider;
|
||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||
import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend;
|
||||
import org.apache.ibatis.annotations.*;
|
||||
import org.springframework.stereotype.Repository;
|
||||
@ -23,13 +22,13 @@ public interface DeviceChannelMapper {
|
||||
"insert into wvp_device_channel " +
|
||||
"(device_id, data_type, data_device_id, name, manufacturer, model, owner, civil_code, block, " +
|
||||
"address, parental, parent_id, safety_way, register_way, cert_num, certifiable, err_code, end_time, secrecy, " +
|
||||
"ip_address, port, password, status, longitude, latitude, ptz_type, position_type, room_type, use_type, " +
|
||||
"ip_address, port, password, status, longitude, latitude, gb_longitude, gb_latitude, ptz_type, position_type, room_type, use_type, " +
|
||||
"supply_light_type, direction_type, resolution, business_group_id, download_speed, svc_space_support_mod, " +
|
||||
"svc_time_support_mode, create_time, update_time, sub_count, stream_id, has_audio, gps_time, stream_identification, channel_type) " +
|
||||
"values " +
|
||||
"(#{deviceId}, #{dataType}, #{dataDeviceId}, #{name}, #{manufacturer}, #{model}, #{owner}, #{civilCode}, #{block}, " +
|
||||
"#{address}, #{parental}, #{parentId}, #{safetyWay}, #{registerWay}, #{certNum}, #{certifiable}, #{errCode}, #{endTime}, #{secrecy}, " +
|
||||
"#{ipAddress}, #{port}, #{password}, #{status}, #{longitude}, #{latitude}, #{ptzType}, #{positionType}, #{roomType}, #{useType}, " +
|
||||
"#{ipAddress}, #{port}, #{password}, #{status}, #{longitude}, #{latitude}, #{gbLongitude}, #{gbLatitude}, #{ptzType}, #{positionType}, #{roomType}, #{useType}, " +
|
||||
"#{supplyLightType}, #{directionType}, #{resolution}, #{businessGroupId}, #{downloadSpeed}, #{svcSpaceSupportMod}," +
|
||||
" #{svcTimeSupportMode}, #{createTime}, #{updateTime}, #{subCount}, #{streamId}, #{hasAudio}, #{gpsTime}, #{streamIdentification}, #{channelType}) " +
|
||||
"</script>")
|
||||
@ -64,6 +63,8 @@ public interface DeviceChannelMapper {
|
||||
", status=#{status}" +
|
||||
", longitude=#{longitude}" +
|
||||
", latitude=#{latitude}" +
|
||||
", gb_longitude=#{gbLongitude}" +
|
||||
", gb_latitude=#{gbLatitude}" +
|
||||
", ptz_type=#{ptzType}" +
|
||||
", position_type=#{positionType}" +
|
||||
", room_type=#{roomType}" +
|
||||
@ -86,10 +87,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);
|
||||
@ -198,14 +200,14 @@ public interface DeviceChannelMapper {
|
||||
"insert into wvp_device_channel " +
|
||||
"(device_id, data_type, data_device_id, name, manufacturer, model, owner, civil_code, block, " +
|
||||
"address, parental, parent_id, safety_way, register_way, cert_num, certifiable, err_code, end_time, secrecy, " +
|
||||
"ip_address, port, password, status, longitude, latitude, ptz_type, position_type, room_type, use_type, " +
|
||||
"ip_address, port, password, status, longitude, latitude, gb_longitude, gb_latitude, ptz_type, position_type, room_type, use_type, " +
|
||||
"supply_light_type, direction_type, resolution, business_group_id, download_speed, svc_space_support_mod, " +
|
||||
"svc_time_support_mode, create_time, update_time, sub_count, stream_id, has_audio, gps_time, stream_identification, channel_type) " +
|
||||
"values " +
|
||||
"<foreach collection='addChannels' index='index' item='item' separator=','> " +
|
||||
"(#{item.deviceId}, #{item.dataType}, #{item.dataDeviceId}, #{item.name}, #{item.manufacturer}, #{item.model}, #{item.owner}, #{item.civilCode}, #{item.block}, " +
|
||||
"#{item.address}, #{item.parental}, #{item.parentId}, #{item.safetyWay}, #{item.registerWay}, #{item.certNum}, #{item.certifiable}, #{item.errCode}, #{item.endTime}, #{item.secrecy}, " +
|
||||
"#{item.ipAddress}, #{item.port}, #{item.password}, #{item.status}, #{item.longitude}, #{item.latitude}, #{item.ptzType}, #{item.positionType}, #{item.roomType}, #{item.useType}, " +
|
||||
"#{item.ipAddress}, #{item.port}, #{item.password}, #{item.status}, #{item.longitude}, #{item.latitude}, #{item.gbLongitude}, #{item.gbLatitude}, #{item.ptzType}, #{item.positionType}, #{item.roomType}, #{item.useType}, " +
|
||||
"#{item.supplyLightType}, #{item.directionType}, #{item.resolution}, #{item.businessGroupId}, #{item.downloadSpeed}, #{item.svcSpaceSupportMod}," +
|
||||
" #{item.svcTimeSupportMode}, #{item.createTime}, #{item.updateTime}, #{item.subCount}, #{item.streamId}, #{item.hasAudio}, #{item.gpsTime}, #{item.streamIdentification}, #{item.channelType}) " +
|
||||
"</foreach> " +
|
||||
@ -246,6 +248,8 @@ public interface DeviceChannelMapper {
|
||||
", status=#{item.status}" +
|
||||
", longitude=#{item.longitude}" +
|
||||
", latitude=#{item.latitude}" +
|
||||
", gb_longitude=#{gbLongitude}" +
|
||||
", gb_latitude=#{gbLatitude}" +
|
||||
", ptz_type=#{item.ptzType}" +
|
||||
", position_type=#{item.positionType}" +
|
||||
", room_type=#{item.roomType}" +
|
||||
@ -268,72 +272,13 @@ public interface DeviceChannelMapper {
|
||||
"</script>"})
|
||||
int batchUpdate(List<DeviceChannel> updateChannels);
|
||||
|
||||
|
||||
@Update({"<script>" +
|
||||
"<foreach collection='updateChannels' item='item' separator=';'>" +
|
||||
" UPDATE" +
|
||||
" wvp_device_channel" +
|
||||
" SET update_time=#{item.updateTime}" +
|
||||
", device_id=#{item.deviceId}" +
|
||||
", data_type=#{item.dataType}" +
|
||||
", data_device_id=#{item.dataDeviceId}" +
|
||||
", name=#{item.name}" +
|
||||
", manufacturer=#{item.manufacturer}" +
|
||||
", model=#{item.model}" +
|
||||
", owner=#{item.owner}" +
|
||||
", civil_code=#{item.civilCode}" +
|
||||
", block=#{item.block}" +
|
||||
", address=#{item.address}" +
|
||||
", parental=#{item.parental}" +
|
||||
", parent_id=#{item.parentId}" +
|
||||
", safety_way=#{item.safetyWay}" +
|
||||
", register_way=#{item.registerWay}" +
|
||||
", cert_num=#{item.certNum}" +
|
||||
", certifiable=#{item.certifiable}" +
|
||||
", err_code=#{item.errCode}" +
|
||||
", end_time=#{item.endTime}" +
|
||||
", secrecy=#{item.secrecy}" +
|
||||
", ip_address=#{item.ipAddress}" +
|
||||
", port=#{item.port}" +
|
||||
", password=#{item.password}" +
|
||||
", status=#{item.status}" +
|
||||
", longitude=#{item.longitude}" +
|
||||
", latitude=#{item.latitude}" +
|
||||
", ptz_type=#{item.ptzType}" +
|
||||
", position_type=#{item.positionType}" +
|
||||
", room_type=#{item.roomType}" +
|
||||
", use_type=#{item.useType}" +
|
||||
", supply_light_type=#{item.supplyLightType}" +
|
||||
", direction_type=#{item.directionType}" +
|
||||
", resolution=#{item.resolution}" +
|
||||
", business_group_id=#{item.businessGroupId}" +
|
||||
", download_speed=#{item.downloadSpeed}" +
|
||||
", svc_space_support_mod=#{item.svcSpaceSupportMod}" +
|
||||
", svc_time_support_mode=#{item.svcTimeSupportMode}" +
|
||||
", sub_count=#{item.subCount}" +
|
||||
", stream_id=#{item.streamId}" +
|
||||
", has_audio=#{item.hasAudio}" +
|
||||
", gps_time=#{item.gpsTime}" +
|
||||
", stream_identification=#{item.streamIdentification}" +
|
||||
", channel_type=#{item.channelType}" +
|
||||
" WHERE data_type = #{item.dataType} and data_device_id = #{item.dataDeviceId} and device_id=#{item.deviceId}" +
|
||||
"</foreach>" +
|
||||
"</script>"})
|
||||
int batchUpdateForNotify(List<DeviceChannel> updateChannels);
|
||||
|
||||
@Update(" update wvp_device_channel" +
|
||||
" set sub_count = (select *" +
|
||||
" from (select count(0)" +
|
||||
" from wvp_device_channel" +
|
||||
" where data_type = 1 and data_device_id = #{dataDeviceId} and parent_id = #{channelId}) as temp)" +
|
||||
" where data_type = 1 and data_device_id = #{dataDeviceId} and device_id = #{channelId}")
|
||||
int updateChannelSubCount(@Param("dataDeviceId") int dataDeviceId, @Param("channelId") String channelId);
|
||||
|
||||
@Update(value = {" <script>" +
|
||||
" UPDATE wvp_device_channel " +
|
||||
" SET " +
|
||||
" latitude=#{latitude}, " +
|
||||
" longitude=#{longitude}, " +
|
||||
" gb_longitude=#{gbLongitude}, " +
|
||||
" gb_latitude=#{gbLatitude}, " +
|
||||
" gps_time=#{gpsTime} " +
|
||||
" WHERE id=#{id} " +
|
||||
" </script>"})
|
||||
@ -373,6 +318,8 @@ public interface DeviceChannelMapper {
|
||||
" status,\n" +
|
||||
" longitude,\n" +
|
||||
" latitude,\n" +
|
||||
" gb_longitude,\n" +
|
||||
" gb_latitude,\n" +
|
||||
" ptz_type,\n" +
|
||||
" position_type,\n" +
|
||||
" room_type,\n" +
|
||||
@ -428,6 +375,8 @@ public interface DeviceChannelMapper {
|
||||
" SET update_time=#{item.updateTime}" +
|
||||
"<if test='item.longitude != null'>, longitude=#{item.longitude}</if>" +
|
||||
"<if test='item.latitude != null'>, latitude=#{item.latitude}</if>" +
|
||||
"<if test='item.gbLongitude != null'>, gb_longitude=#{item.gbLongitude}</if>" +
|
||||
"<if test='item.gbLatitude != null'>, gb_latitude=#{item.gbLatitude}</if>" +
|
||||
"<if test='item.gpsTime != null'>, gps_time=#{item.gpsTime}</if>" +
|
||||
"<if test='item.id > 0'>WHERE id=#{item.id}</if>" +
|
||||
"<if test='item.id == 0'>WHERE data_type = #{item.dataType} and data_device_id=#{item.dataDeviceId} AND device_id=#{item.deviceId}</if>" +
|
||||
@ -473,6 +422,8 @@ public interface DeviceChannelMapper {
|
||||
" status,\n" +
|
||||
" longitude,\n" +
|
||||
" latitude,\n" +
|
||||
" gb_longitude,\n" +
|
||||
" gb_latitude,\n" +
|
||||
" ptz_type,\n" +
|
||||
" position_type,\n" +
|
||||
" room_type,\n" +
|
||||
@ -528,6 +479,8 @@ public interface DeviceChannelMapper {
|
||||
" status,\n" +
|
||||
" longitude,\n" +
|
||||
" latitude,\n" +
|
||||
" gb_longitude,\n" +
|
||||
" gb_latitude,\n" +
|
||||
" ptz_type,\n" +
|
||||
" position_type,\n" +
|
||||
" room_type,\n" +
|
||||
@ -555,13 +508,6 @@ public interface DeviceChannelMapper {
|
||||
" </script>"})
|
||||
void changeAudio(@Param("channelId") int channelId, @Param("audio") boolean audio);
|
||||
|
||||
@Update("<script> " +
|
||||
"<foreach collection='gpsMsgInfoList' index='index' item='item' separator=';'> " +
|
||||
"UPDATE wvp_device_channel SET gb_longitude = #{item.lng}, gb_latitude=#{item.lat} WHERE id = #{item.channelId}" +
|
||||
"</foreach> " +
|
||||
"</script>")
|
||||
void updateStreamGPS(List<GPSMsgInfo> gpsMsgInfoList);
|
||||
|
||||
@Update("UPDATE wvp_device_channel SET status=#{status} WHERE data_type=#{dataType} and data_device_id=#{dataDeviceId} AND device_id=#{deviceId}")
|
||||
void updateStatus(DeviceChannel channel);
|
||||
|
||||
@ -594,6 +540,8 @@ public interface DeviceChannelMapper {
|
||||
", status=#{status}" +
|
||||
", longitude=#{longitude}" +
|
||||
", latitude=#{latitude}" +
|
||||
", gb_longitude=#{gbLongitude}" +
|
||||
", gb_latitude=#{gbLatitude}" +
|
||||
", ptz_type=#{ptzType}" +
|
||||
", position_type=#{positionType}" +
|
||||
", room_type=#{roomType}" +
|
||||
@ -651,6 +599,8 @@ public interface DeviceChannelMapper {
|
||||
" status,\n" +
|
||||
" longitude,\n" +
|
||||
" latitude,\n" +
|
||||
" gb_longitude,\n" +
|
||||
" gb_latitude,\n" +
|
||||
" ptz_type,\n" +
|
||||
" position_type,\n" +
|
||||
" room_type,\n" +
|
||||
|
||||
@ -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,"+
|
||||
|
||||
@ -12,13 +12,13 @@ import java.util.Set;
|
||||
@Mapper
|
||||
public interface GroupMapper {
|
||||
|
||||
@Insert("INSERT INTO wvp_common_group (device_id, name, parent_id, parent_device_id, business_group, create_time, update_time, civil_code) " +
|
||||
"VALUES (#{deviceId}, #{name}, #{parentId}, #{parentDeviceId}, #{businessGroup}, #{createTime}, #{updateTime}, #{civilCode})")
|
||||
@Insert("INSERT INTO wvp_common_group (device_id, name, parent_id, parent_device_id, business_group, create_time, update_time, civil_code, alias) " +
|
||||
"VALUES (#{deviceId}, #{name}, #{parentId}, #{parentDeviceId}, #{businessGroup}, #{createTime}, #{updateTime}, #{civilCode}, #{alias})")
|
||||
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
|
||||
int add(Group group);
|
||||
|
||||
@Insert("INSERT INTO wvp_common_group (device_id, name, business_group, create_time, update_time, civil_code) " +
|
||||
"VALUES (#{deviceId}, #{name}, #{businessGroup}, #{createTime}, #{updateTime}, #{civilCode})")
|
||||
@Insert("INSERT INTO wvp_common_group (device_id, name, business_group, create_time, update_time, civil_code, alias) " +
|
||||
"VALUES (#{deviceId}, #{name}, #{businessGroup}, #{createTime}, #{updateTime}, #{civilCode}, #{alias})")
|
||||
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
|
||||
int addBusinessGroup(Group group);
|
||||
|
||||
@ -27,7 +27,8 @@ public interface GroupMapper {
|
||||
|
||||
@Update(" UPDATE wvp_common_group " +
|
||||
" SET update_time=#{updateTime}, device_id=#{deviceId}, name=#{name}, parent_id=#{parentId}, " +
|
||||
" parent_device_id=#{parentDeviceId}, business_group=#{businessGroup}, civil_code=#{civilCode}" +
|
||||
" parent_device_id=#{parentDeviceId}, business_group=#{businessGroup}, civil_code=#{civilCode}, " +
|
||||
" alias=#{alias}" +
|
||||
" WHERE id = #{id}")
|
||||
int update(Group group);
|
||||
|
||||
@ -55,10 +56,12 @@ public interface GroupMapper {
|
||||
" business_group," +
|
||||
" create_time," +
|
||||
" civil_code," +
|
||||
" alias," +
|
||||
" update_time) " +
|
||||
" VALUES " +
|
||||
" <foreach collection='groupList' index='index' item='item' separator=','> " +
|
||||
" (#{item.deviceId}, #{item.name}, #{item.parentDeviceId}, #{item.parentId}, #{item.businessGroup},#{item.createTime},#{item.civilCode},#{item.updateTime})" +
|
||||
" (#{item.deviceId}, #{item.name}, #{item.parentDeviceId}, #{item.parentId}, #{item.businessGroup}," +
|
||||
"#{item.createTime},#{item.civilCode},#{item.alias},#{item.updateTime})" +
|
||||
" </foreach> " +
|
||||
" </script>")
|
||||
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
|
||||
@ -156,7 +159,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} " +
|
||||
@ -199,6 +203,13 @@ public interface GroupMapper {
|
||||
" where w1.id in " +
|
||||
" <foreach collection='groupListForAdd' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
|
||||
" </script>", databaseId = "mysql")
|
||||
@Update(value = " <script>" +
|
||||
" update wvp_common_group w1 " +
|
||||
" inner join (select * from wvp_common_group ) w2 on w1.parent_device_id = w2.device_id " +
|
||||
" set w1.parent_id = w2.id" +
|
||||
" where w1.id in " +
|
||||
" <foreach collection='groupListForAdd' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
|
||||
" </script>", databaseId = "h2")
|
||||
@Update( value = " <script>" +
|
||||
" update wvp_common_group w1\n" +
|
||||
" set parent_id = w2.id\n" +
|
||||
@ -229,6 +240,18 @@ public interface GroupMapper {
|
||||
" where w1.id in " +
|
||||
" <foreach collection='groupListForAdd' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
|
||||
" </script>", databaseId = "mysql")
|
||||
@Update(value = " <script>" +
|
||||
" update wvp_common_group w1 " +
|
||||
" inner join (select * from wvp_common_group ) w2" +
|
||||
" on w1.parent_device_id is null" +
|
||||
" and w2.parent_device_id is null" +
|
||||
" and w2.device_id = w2.business_group " +
|
||||
" and w1.business_group = w2.device_id " +
|
||||
" and w1.device_id != w1.business_group " +
|
||||
" set w1.parent_id = w2.id" +
|
||||
" where w1.id in " +
|
||||
" <foreach collection='groupListForAdd' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
|
||||
" </script>", databaseId = "h2")
|
||||
@Update( value = " <script>" +
|
||||
" update wvp_common_group w1 " +
|
||||
" set parent_id = w2.id " +
|
||||
@ -266,4 +289,7 @@ public interface GroupMapper {
|
||||
|
||||
@Delete("DELETE FROM wvp_platform_group WHERE group_id = #{groupId}")
|
||||
void deletePlatformGroup(@Param("groupId") int groupId);
|
||||
|
||||
@Select("SELECT * from wvp_common_group WHERE alias = #{alias} ")
|
||||
Group queryGroupByAlias(@Param("alias") String alias);
|
||||
}
|
||||
|
||||
@ -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 " +
|
||||
@ -115,6 +114,13 @@ public interface RegionMapper {
|
||||
" where w1.id in " +
|
||||
" <foreach collection='regionListForAdd' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
|
||||
" </script>", databaseId = "mysql")
|
||||
@Update(value = " <script>" +
|
||||
" update wvp_common_region w1 " +
|
||||
" inner join (select * from wvp_common_region ) w2 on w1.parent_device_id = w2.device_id " +
|
||||
" set w1.parent_id = w2.id" +
|
||||
" where w1.id in " +
|
||||
" <foreach collection='regionListForAdd' item='item' open='(' separator=',' close=')' > #{item.id}</foreach>" +
|
||||
" </script>", databaseId = "h2")
|
||||
@Update( value = " <script>" +
|
||||
" update wvp_common_region w1\n" +
|
||||
" set parent_id = w2.id\n" +
|
||||
|
||||
@ -16,7 +16,9 @@ public class ChannelProvider {
|
||||
" data_device_id,\n" +
|
||||
" create_time,\n" +
|
||||
" update_time,\n" +
|
||||
" stream_id,\n" +
|
||||
" record_plan_id,\n" +
|
||||
" enable_broadcast,\n" +
|
||||
" coalesce(gb_device_id, device_id) as gb_device_id,\n" +
|
||||
" coalesce(gb_name, name) as gb_name,\n" +
|
||||
" coalesce(gb_manufacturer, manufacturer) as gb_manufacturer,\n" +
|
||||
@ -60,7 +62,9 @@ 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" +
|
||||
" wdc.enable_broadcast,\n" +
|
||||
" coalesce(wdc.gb_device_id, wdc.device_id) as gb_device_id,\n" +
|
||||
" coalesce(wdc.gb_name, wdc.name) as gb_name,\n" +
|
||||
" coalesce(wdc.gb_manufacturer, wdc.manufacturer) as gb_manufacturer,\n" +
|
||||
@ -105,6 +109,7 @@ public class ChannelProvider {
|
||||
" wdc.data_device_id,\n" +
|
||||
" wdc.create_time,\n" +
|
||||
" wdc.update_time,\n" +
|
||||
" wdc.enable_broadcast,\n" +
|
||||
" coalesce(wpgc.custom_device_id, wdc.gb_device_id, wdc.device_id) as gb_device_id,\n" +
|
||||
" coalesce(wpgc.custom_name, wdc.gb_name, wdc.name) as gb_name,\n" +
|
||||
" coalesce(wpgc.custom_manufacturer, wdc.gb_manufacturer, wdc.manufacturer) as gb_manufacturer,\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);
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
/**
|
||||
* 报警事件监听器.
|
||||
|
||||
@ -1,18 +1,14 @@
|
||||
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.controller.bean.ChannelReduce;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
|
||||
import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import org.dom4j.Element;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -32,28 +28,6 @@ public interface IDeviceChannelService {
|
||||
*/
|
||||
ResourceBaseInfo getOverview();
|
||||
|
||||
/**
|
||||
* 查询所有未分配的通道
|
||||
* @param platformId
|
||||
* @return
|
||||
*/
|
||||
List<ChannelReduce> queryAllChannelList(String platformId);
|
||||
|
||||
PageInfo<ChannelReduce> queryAllChannelList(int page, int count, String query, Boolean online, Boolean channelType, String platformId, String catalogId);
|
||||
|
||||
/**
|
||||
* 查询通道所属的设备
|
||||
*/
|
||||
List<Device> getDeviceByChannelId(String channelId);
|
||||
|
||||
/**
|
||||
* 批量删除通道
|
||||
* @param deleteChannelList 待删除的通道列表
|
||||
*/
|
||||
int deleteChannelsForNotify(List<DeviceChannel> deleteChannelList);
|
||||
|
||||
int updateChannelsStatus(List<DeviceChannel> channels);
|
||||
|
||||
/**
|
||||
* 获取一个通道
|
||||
*/
|
||||
@ -61,16 +35,6 @@ public interface IDeviceChannelService {
|
||||
|
||||
DeviceChannel getOneForSource(String deviceId, String channelId);
|
||||
|
||||
/**
|
||||
* 直接批量更新通道
|
||||
*/
|
||||
void batchUpdateChannelForNotify(List<DeviceChannel> channels);
|
||||
|
||||
/**
|
||||
* 直接批量添加
|
||||
*/
|
||||
void batchAddChannel(List<DeviceChannel> deviceChannels);
|
||||
|
||||
/**
|
||||
* 修改通道的码流类型
|
||||
*/
|
||||
@ -84,10 +48,6 @@ public interface IDeviceChannelService {
|
||||
|
||||
void stopPlay(Integer channelId);
|
||||
|
||||
void batchUpdateChannelGPS(List<DeviceChannel> channelList);
|
||||
|
||||
void batchAddMobilePosition(List<MobilePosition> addMobilePositionList);
|
||||
|
||||
void online(DeviceChannel channel);
|
||||
|
||||
void offline(DeviceChannel channel);
|
||||
@ -104,6 +64,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();
|
||||
|
||||
@ -127,8 +88,6 @@ public interface IDeviceChannelService {
|
||||
|
||||
DeviceChannel getOneBySourceId(int deviceDbId, String channelId);
|
||||
|
||||
List<DeviceChannel> queryChaneListByDeviceDbId(Integer deviceDbId);
|
||||
|
||||
List<Integer> queryChaneIdListByDeviceDbIds(List<Integer> deviceDbId);
|
||||
|
||||
void handlePtzCmd(@NotNull Integer dataDeviceId, @NotNull Integer gbId, Element rootElement, DeviceControlType type, ErrorCallback<String> callback);
|
||||
|
||||
@ -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,7 @@ public interface IGbChannelService {
|
||||
|
||||
void updateGPSFromGPSMsgInfo(List<GPSMsgInfo> gpsMsgInfoList);
|
||||
|
||||
void updateGPS(List<CommonGBChannel> channelList);
|
||||
|
||||
List<CommonGBChannel> queryListForMap(String query, Boolean online, Boolean hasRecordPlan, Integer channelType);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -16,11 +17,13 @@ public interface IGroupService {
|
||||
|
||||
List<GroupTree> queryForTree(String query, Integer parent, Boolean hasChannel);
|
||||
|
||||
void syncFromChannel();
|
||||
|
||||
boolean delete(int id);
|
||||
|
||||
boolean batchAdd(List<Group> groupList);
|
||||
|
||||
List<Group> getPath(String deviceId, String businessGroup);
|
||||
|
||||
PageInfo<Group> queryList(Integer page, Integer count, String query);
|
||||
|
||||
Group queryGroupByAlias(String groupAlias);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -8,7 +8,6 @@ import com.genersoft.iot.vmp.common.enums.DeviceControlType;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelReduce;
|
||||
import com.genersoft.iot.vmp.gb28181.dao.DeviceChannelMapper;
|
||||
import com.genersoft.iot.vmp.gb28181.dao.DeviceMapper;
|
||||
import com.genersoft.iot.vmp.gb28181.dao.DeviceMobilePositionMapper;
|
||||
@ -24,12 +23,14 @@ import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
|
||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||
import com.genersoft.iot.vmp.service.redisMsg.IRedisRpcPlayService;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
import com.genersoft.iot.vmp.utils.Coordtransform;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo;
|
||||
import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dom4j.Element;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -43,7 +44,6 @@ import org.springframework.util.ObjectUtils;
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import javax.sip.message.Response;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -209,66 +209,6 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
return new ResourceBaseInfo(total, online);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<ChannelReduce> queryAllChannelList(String platformId) {
|
||||
return channelMapper.queryChannelListInAll(null, null, null, platformId, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<ChannelReduce> queryAllChannelList(int page, int count, String query, Boolean online, Boolean channelType, String platformId, String catalogId) {
|
||||
PageHelper.startPage(page, count);
|
||||
List<ChannelReduce> all = channelMapper.queryChannelListInAll(query, online, channelType, platformId, catalogId);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Device> getDeviceByChannelId(String channelId) {
|
||||
return channelMapper.getDeviceByChannelDeviceId(channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public int deleteChannelsForNotify(List<DeviceChannel> channels) {
|
||||
int limitCount = 1000;
|
||||
int result = 0;
|
||||
if (!channels.isEmpty()) {
|
||||
if (channels.size() > limitCount) {
|
||||
for (int i = 0; i < channels.size(); i += limitCount) {
|
||||
int toIndex = i + limitCount;
|
||||
if (i + limitCount > channels.size()) {
|
||||
toIndex = channels.size();
|
||||
}
|
||||
result += channelMapper.batchDel(channels.subList(i, toIndex));
|
||||
}
|
||||
}else {
|
||||
result += channelMapper.batchDel(channels);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public int updateChannelsStatus(List<DeviceChannel> channels) {
|
||||
int limitCount = 1000;
|
||||
int result = 0;
|
||||
if (!channels.isEmpty()) {
|
||||
if (channels.size() > limitCount) {
|
||||
for (int i = 0; i < channels.size(); i += limitCount) {
|
||||
int toIndex = i + limitCount;
|
||||
if (i + limitCount > channels.size()) {
|
||||
toIndex = channels.size();
|
||||
}
|
||||
result += channelMapper.batchUpdateStatus(channels.subList(i, toIndex));
|
||||
}
|
||||
}else {
|
||||
result += channelMapper.batchUpdateStatus(channels);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void online(DeviceChannel channel) {
|
||||
channelMapper.online(channel.getId());
|
||||
@ -312,58 +252,6 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
return channelMapper.getOneBySourceChannelId(deviceDbId, channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public synchronized void batchUpdateChannelForNotify(List<DeviceChannel> channels) {
|
||||
String now = DateUtil.getNow();
|
||||
for (DeviceChannel channel : channels) {
|
||||
channel.setUpdateTime(now);
|
||||
}
|
||||
int limitCount = 1000;
|
||||
if (!channels.isEmpty()) {
|
||||
if (channels.size() > limitCount) {
|
||||
for (int i = 0; i < channels.size(); i += limitCount) {
|
||||
int toIndex = i + limitCount;
|
||||
if (i + limitCount > channels.size()) {
|
||||
toIndex = channels.size();
|
||||
}
|
||||
channelMapper.batchUpdateForNotify(channels.subList(i, toIndex));
|
||||
}
|
||||
}else {
|
||||
channelMapper.batchUpdateForNotify(channels);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void batchAddChannel(List<DeviceChannel> channels) {
|
||||
String now = DateUtil.getNow();
|
||||
for (DeviceChannel channel : channels) {
|
||||
channel.setUpdateTime(now);
|
||||
channel.setCreateTime(now);
|
||||
}
|
||||
int limitCount = 1000;
|
||||
if (!channels.isEmpty()) {
|
||||
if (channels.size() > limitCount) {
|
||||
for (int i = 0; i < channels.size(); i += limitCount) {
|
||||
int toIndex = i + limitCount;
|
||||
if (i + limitCount > channels.size()) {
|
||||
toIndex = channels.size();
|
||||
}
|
||||
channelMapper.batchAdd(channels.subList(i, toIndex));
|
||||
}
|
||||
}else {
|
||||
channelMapper.batchAdd(channels);
|
||||
}
|
||||
}
|
||||
for (DeviceChannel channel : channels) {
|
||||
if (channel.getParentId() != null) {
|
||||
channelMapper.updateChannelSubCount(channel.getDataDeviceId(), channel.getParentId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateChannelStreamIdentification(DeviceChannel channel) {
|
||||
Assert.hasLength(channel.getStreamIdentification(), "码流标识必须存在");
|
||||
@ -389,11 +277,6 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
return channelMapper.queryChannelsByDeviceDbId(device.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DeviceChannel> queryChaneListByDeviceDbId(Integer deviceDbId) {
|
||||
return channelMapper.queryChannelsByDeviceDbId(deviceDbId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Integer> queryChaneIdListByDeviceDbIds(List<Integer> deviceDbIds) {
|
||||
return channelMapper.queryChaneIdListByDeviceDbIds(deviceDbIds);
|
||||
@ -434,6 +317,17 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
|
||||
@Override
|
||||
public void updateChannelGPS(Device device, DeviceChannel deviceChannel, MobilePosition mobilePosition) {
|
||||
|
||||
if (device.getGeoCoordSys().equalsIgnoreCase("GCJ02")) {
|
||||
Double[] wgs84Position = Coordtransform.GCJ02ToWGS84(mobilePosition.getLongitude(), mobilePosition.getLatitude());
|
||||
mobilePosition.setLongitude(wgs84Position[0]);
|
||||
mobilePosition.setLatitude(wgs84Position[1]);
|
||||
|
||||
Double[] wgs84PositionForChannel = Coordtransform.GCJ02ToWGS84(deviceChannel.getLongitude(), deviceChannel.getLatitude());
|
||||
deviceChannel.setGbLongitude(wgs84PositionForChannel[0]);
|
||||
deviceChannel.setGbLatitude(wgs84PositionForChannel[1]);
|
||||
}
|
||||
|
||||
if (userSetting.getSavePositionHistory()) {
|
||||
deviceMobilePositionMapper.insertNewPosition(mobilePosition);
|
||||
}
|
||||
@ -497,49 +391,6 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
channelMapper.stopPlayById(channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void batchUpdateChannelGPS(List<DeviceChannel> channelList) {
|
||||
for (DeviceChannel deviceChannel : channelList) {
|
||||
deviceChannel.setUpdateTime(DateUtil.getNow());
|
||||
if (deviceChannel.getGpsTime() == null) {
|
||||
deviceChannel.setGpsTime(DateUtil.getNow());
|
||||
}
|
||||
}
|
||||
int count = 1000;
|
||||
if (channelList.size() > count) {
|
||||
for (int i = 0; i < channelList.size(); i+=count) {
|
||||
int toIndex = i+count;
|
||||
if ( i + count > channelList.size()) {
|
||||
toIndex = channelList.size();
|
||||
}
|
||||
List<DeviceChannel> channels = channelList.subList(i, toIndex);
|
||||
channelMapper.batchUpdatePosition(channels);
|
||||
}
|
||||
}else {
|
||||
channelMapper.batchUpdatePosition(channelList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void batchAddMobilePosition(List<MobilePosition> mobilePositions) {
|
||||
// int count = 500;
|
||||
// if (mobilePositions.size() > count) {
|
||||
// for (int i = 0; i < mobilePositions.size(); i+=count) {
|
||||
// int toIndex = i+count;
|
||||
// if ( i + count > mobilePositions.size()) {
|
||||
// toIndex = mobilePositions.size();
|
||||
// }
|
||||
// List<MobilePosition> mobilePositionsSub = mobilePositions.subList(i, toIndex);
|
||||
// deviceMobilePositionMapper.batchadd(mobilePositionsSub);
|
||||
// }
|
||||
// }else {
|
||||
// deviceMobilePositionMapper.batchadd(mobilePositions);
|
||||
// }
|
||||
deviceMobilePositionMapper.batchadd(mobilePositions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanChannelsForDevice(int deviceId) {
|
||||
channelMapper.cleanChannelsByDeviceId(deviceId);
|
||||
@ -696,7 +547,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 +568,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 +631,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 +677,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);
|
||||
|
||||
@ -39,6 +39,7 @@ import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import gov.nist.javax.sip.message.SIPResponse;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
@ -51,7 +52,6 @@ import org.springframework.util.Assert;
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.ResponseEvent;
|
||||
import javax.sip.SipException;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.text.ParseException;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,6 @@ import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
|
||||
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.genersoft.iot.vmp.utils.DateUtil;
|
||||
@ -26,7 +25,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.sip.message.Response;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@ -366,12 +364,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 +492,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 +513,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 +630,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 +658,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 +700,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 +715,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 +769,26 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CommonGBChannel> queryListForMap(String query, Boolean online, Boolean hasRecordPlan, Integer channelType) {
|
||||
return commonGBChannelMapper.queryList(query, online, hasRecordPlan, channelType);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user