Commit 5ba0fba03d9fcb09eea0c1e703a4f050378d7992

Authored by panlinlin
1 parent d551c82d

添加部分onvif代码

.gitmodules 0 → 100644
  1 +[submodule "be.teletask.onvif-java"]
  2 + path = be.teletask.onvif-java
  3 + url = https://gitee.com/18010473990/be.teletask.onvif-java.git
... ...
libs/onvif-java-1.0.2.jar 0 → 100644
No preview for this file type
... ... @@ -10,7 +10,7 @@
10 10 </parent>
11 11  
12 12 <groupId>com.genersoft</groupId>
13   - <artifactId>wvp</artifactId>
  13 + <artifactId>wvp-gb28181</artifactId>
14 14 <version>2.0.0</version>
15 15 <name>web video platform</name>
16 16  
... ... @@ -44,6 +44,7 @@
44 44  
45 45 <properties>
46 46 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  47 + <maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
47 48  
48 49 <!-- 依赖版本 -->
49 50 <pagehelper.version>5.2.0</pagehelper.version>
... ... @@ -167,10 +168,36 @@
167 168 <artifactId>okhttp</artifactId>
168 169 <version>4.9.0</version>
169 170 </dependency>
170   - </dependencies>
  171 +
  172 + <!-- okhttp-digest -->
  173 + <dependency>
  174 + <groupId>com.burgstaller</groupId>
  175 + <artifactId>okhttp-digest</artifactId>
  176 + <version>2.1</version>
  177 + </dependency>
  178 +
  179 + <!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 -->
  180 + <dependency>
  181 + <groupId>net.sf.kxml</groupId>
  182 + <artifactId>kxml2</artifactId>
  183 + <version>2.3.0</version>
  184 + </dependency>
  185 +
  186 +
  187 + <!-- onvif协议栈 -->
  188 + <dependency>
  189 + <groupId>be.teletask</groupId>
  190 + <artifactId>onvif-java</artifactId>
  191 + <version>1.0.2</version>
  192 + <scope>system</scope>
  193 + <systemPath>${project.basedir}/libs/onvif-java-1.0.2.jar</systemPath>
  194 + </dependency>
  195 + </dependencies>
  196 +
  197 +
171 198  
172 199 <build>
173   - <finalName>wvp-2.0</finalName>
  200 + <finalName>${project.artifactId}-${project.version}-${maven.build.timestamp}</finalName>
174 201 <plugins>
175 202 <plugin>
176 203 <groupId>org.springframework.boot</groupId>
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
... ... @@ -35,6 +35,8 @@ public class DeferredResultHolder {
35 35  
36 36 public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP";
37 37  
  38 + public static final String CALLBACK_ONVIF = "CALLBACK_ONVIF";
  39 +
38 40 public static final String CALLBACK_CMD_MOBILEPOSITION = "CALLBACK_MOBILEPOSITION";
39 41  
40 42 public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY";
... ...
src/main/java/com/genersoft/iot/vmp/onvif/IONVIFServer.java 0 → 100644
  1 +package com.genersoft.iot.vmp.onvif;
  2 +
  3 +import be.teletask.onvif.models.OnvifDevice;
  4 +import com.genersoft.iot.vmp.onvif.dto.ONVIFCallBack;
  5 +
  6 +import java.util.List;
  7 +
  8 +public interface IONVIFServer {
  9 +
  10 + void search(int timeout, ONVIFCallBack<List<String>> callBack);
  11 +
  12 + void getRTSPUrl(int timeout, OnvifDevice device, ONVIFCallBack<String> callBack);
  13 +}
... ...
src/main/java/com/genersoft/iot/vmp/onvif/dto/ONVIFCallBack.java 0 → 100644
  1 +package com.genersoft.iot.vmp.onvif.dto;
  2 +
  3 +public interface ONVIFCallBack<T> {
  4 + void run(int errorCode, T t);
  5 +}
... ...
src/main/java/com/genersoft/iot/vmp/onvif/impl/ONVIFServerIMpl.java 0 → 100644
  1 +package com.genersoft.iot.vmp.onvif.impl;
  2 +
  3 +
  4 +import be.teletask.onvif.DiscoveryManager;
  5 +import be.teletask.onvif.OnvifManager;
  6 +import be.teletask.onvif.listeners.*;
  7 +import be.teletask.onvif.models.*;
  8 +import be.teletask.onvif.responses.OnvifResponse;
  9 +import com.genersoft.iot.vmp.onvif.IONVIFServer;
  10 +import com.genersoft.iot.vmp.onvif.dto.ONVIFCallBack;
  11 +import org.slf4j.Logger;
  12 +import org.slf4j.LoggerFactory;
  13 +import org.springframework.stereotype.Service;
  14 +
  15 +import java.net.URI;
  16 +import java.net.URISyntaxException;
  17 +import java.util.ArrayList;
  18 +import java.util.HashMap;
  19 +import java.util.List;
  20 +import java.util.Map;
  21 +
  22 +/**
  23 + * 处理onvif的各种操作
  24 + */
  25 +@Service
  26 +public class ONVIFServerIMpl implements IONVIFServer {
  27 +
  28 + private final static Logger logger = LoggerFactory.getLogger(ONVIFServerIMpl.class);
  29 +
  30 + @Override
  31 + public void search(int timeout, ONVIFCallBack<List<String>> callBack) {
  32 + DiscoveryManager manager = new DiscoveryManager();
  33 + manager.setDiscoveryTimeout(timeout);
  34 + Map<String, Device> deviceMap = new HashMap<>();
  35 + // 搜索设备
  36 + manager.discover(new DiscoveryListener() {
  37 + @Override
  38 + public void onDiscoveryStarted() {
  39 + logger.info("Discovery started");
  40 + }
  41 +
  42 + @Override
  43 + public void onDevicesFound(List<Device> devices) {
  44 + if (devices == null || devices.size() == 0) return;
  45 + for (Device device : devices){
  46 + System.out.println(device.getHostName());
  47 + deviceMap.put(device.getHostName(), device);
  48 + }
  49 + }
  50 +
  51 + // 搜索结束
  52 + @Override
  53 + public void onDiscoveryFinished() {
  54 + ArrayList<String> result = new ArrayList<>();
  55 + for (Device device : deviceMap.values()) {
  56 + System.out.println(device.getHostName());
  57 + result.add(device.getHostName());
  58 + }
  59 + callBack.run(0, result);
  60 + }
  61 + });
  62 + }
  63 +
  64 + @Override
  65 + public void getRTSPUrl(int timeout, OnvifDevice device, ONVIFCallBack<String> callBack) {
  66 + if (device.getHostName() == null ){
  67 + callBack.run(400, null);
  68 + }
  69 + OnvifManager onvifManager = new OnvifManager();
  70 + onvifManager.setOnvifResponseListener(new OnvifResponseListener(){
  71 +
  72 + @Override
  73 + public void onResponse(OnvifDevice onvifDevice, OnvifResponse response) {
  74 + System.out.println("[RESPONSE] " + onvifDevice.getHostName()
  75 + + "======" + response.getErrorCode()
  76 + + "======" + response.getErrorMessage());
  77 + }
  78 +
  79 + @Override
  80 + public void onError(OnvifDevice onvifDevice, int errorCode, String errorMessage) {
  81 + System.out.println("[ERROR] " + onvifDevice.getHostName() + "======" + errorCode + "=======" + errorMessage);
  82 + callBack.run(errorCode, errorMessage);
  83 + }
  84 + });
  85 +
  86 + try {
  87 + onvifManager.getServices(device, (OnvifDevice onvifDevice, OnvifServices services) -> {
  88 + if (services.getProfilesPath().equals("/onvif/Media")) {
  89 + onvifDevice.setPath(services);
  90 + onvifManager.getMediaProfiles(onvifDevice, new OnvifMediaProfilesListener() {
  91 + @Override
  92 + public void onMediaProfilesReceived(OnvifDevice device, List<OnvifMediaProfile> mediaProfiles) {
  93 + for (OnvifMediaProfile mediaProfile : mediaProfiles) {
  94 + System.out.println(mediaProfile.getName());
  95 + System.out.println(mediaProfile.getToken());
  96 + if (mediaProfile.getName().equals("mainStream")) {
  97 + onvifManager.getMediaStreamURI(device, mediaProfile, (OnvifDevice onvifDevice,
  98 + OnvifMediaProfile profile, String uri) -> {
  99 +
  100 + uri = uri.replace("rtsp://", "rtsp://"+ device.getUsername() + ":"+ device.getPassword() + "@");
  101 + logger.info(onvifDevice.getHostName() + "的地址" + uri);
  102 + callBack.run(0, uri);
  103 + });
  104 + }
  105 + }
  106 + }
  107 + });
  108 + }
  109 + });
  110 + }catch (Exception e) {
  111 + callBack.run(400, e.getMessage());
  112 + }
  113 +
  114 +
  115 + }
  116 +}
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/onvif/ONVIFController.java 0 → 100644
  1 +package com.genersoft.iot.vmp.vmanager.onvif;
  2 +
  3 +import be.teletask.onvif.models.OnvifDevice;
  4 +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
  5 +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  6 +import com.genersoft.iot.vmp.onvif.IONVIFServer;
  7 +import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
  8 +import io.swagger.annotations.Api;
  9 +import io.swagger.annotations.ApiImplicitParam;
  10 +import io.swagger.annotations.ApiImplicitParams;
  11 +import io.swagger.annotations.ApiOperation;
  12 +import org.springframework.beans.factory.annotation.Autowired;
  13 +import org.springframework.http.ResponseEntity;
  14 +import org.springframework.web.bind.annotation.*;
  15 +import org.springframework.web.context.request.async.DeferredResult;
  16 +
  17 +import java.util.List;
  18 +import java.util.UUID;
  19 +
  20 +@Api(tags = "onvif设备")
  21 +@CrossOrigin
  22 +@RestController
  23 +@RequestMapping("/api/onvif")
  24 +public class ONVIFController {
  25 +
  26 +
  27 + @Autowired
  28 + private DeferredResultHolder resultHolder;
  29 +
  30 + @Autowired
  31 + private IONVIFServer onvifServer;
  32 +
  33 +
  34 + @ApiOperation("搜索")
  35 + @ApiImplicitParams({
  36 + @ApiImplicitParam(name="timeout", value = "超时时间", required = true, dataTypeClass = Integer.class),
  37 + })
  38 + @GetMapping(value = "/search")
  39 + @ResponseBody
  40 + public DeferredResult<ResponseEntity<WVPResult>> search(@RequestParam(required = false)Integer timeout){
  41 + DeferredResult<ResponseEntity<WVPResult>> result = new DeferredResult<>(timeout + 10L);
  42 + UUID uuid = UUID.randomUUID();
  43 + result.onTimeout(()->{
  44 + RequestMessage msg = new RequestMessage();
  45 + msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
  46 + WVPResult<String> wvpResult = new WVPResult();
  47 + wvpResult.setCode(0);
  48 + wvpResult.setMsg("搜索超时");
  49 + msg.setData(wvpResult);
  50 + resultHolder.invokeResult(msg);
  51 + });
  52 + resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF + uuid, result);
  53 +
  54 + onvifServer.search(timeout, (errorCode, onvifDevices) ->{
  55 + RequestMessage msg = new RequestMessage();
  56 + msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
  57 + WVPResult<List<String>> resultData = new WVPResult();
  58 + resultData.setCode(errorCode);
  59 + if (errorCode == 0) {
  60 + resultData.setMsg("success");
  61 + resultData.setData(onvifDevices);
  62 + }else {
  63 + resultData.setMsg("fail");
  64 + }
  65 + msg.setData(resultData);
  66 + msg.setData(resultData);
  67 + resultHolder.invokeResult(msg);
  68 + });
  69 +
  70 + return result;
  71 + }
  72 +
  73 + @ApiOperation("获取onvif的rtsp地址")
  74 + @ApiImplicitParams({
  75 + @ApiImplicitParam(name="timeout", value = "超时时间", required = true, dataTypeClass = Integer.class),
  76 + @ApiImplicitParam(name="hostname", value = "onvif地址", required = true, dataTypeClass = String.class),
  77 + @ApiImplicitParam(name="username", value = "用户名", required = true, dataTypeClass = String.class),
  78 + @ApiImplicitParam(name="password", value = "密码", required = true, dataTypeClass = String.class),
  79 + })
  80 + @GetMapping(value = "/rtsp")
  81 + @ResponseBody
  82 + public DeferredResult<ResponseEntity<WVPResult>> getRTSPUrl(@RequestParam(value="timeout", required=false, defaultValue="3000") Integer timeout,
  83 + @RequestParam(required = true) String hostname,
  84 + @RequestParam(required = false) String username,
  85 + @RequestParam(required = false) String password
  86 + ){
  87 +
  88 + DeferredResult<ResponseEntity<WVPResult>> result = new DeferredResult<>(timeout + 10L);
  89 + UUID uuid = UUID.randomUUID();
  90 + result.onTimeout(()->{
  91 + RequestMessage msg = new RequestMessage();
  92 + msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
  93 + WVPResult<String> wvpResult = new WVPResult();
  94 + wvpResult.setCode(0);
  95 + wvpResult.setMsg("获取onvif的rtsp地址超时");
  96 + msg.setData(wvpResult);
  97 + resultHolder.invokeResult(msg);
  98 + });
  99 + resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF + uuid, result);
  100 + OnvifDevice onvifDevice = new OnvifDevice(hostname, username, password);
  101 + onvifServer.getRTSPUrl(timeout, onvifDevice, (errorCode, url) ->{
  102 + RequestMessage msg = new RequestMessage();
  103 + msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
  104 + WVPResult<String> resultData = new WVPResult();
  105 + resultData.setCode(errorCode);
  106 + if (errorCode == 0) {
  107 + resultData.setMsg("success");
  108 + resultData.setData(url);
  109 + }else {
  110 + resultData.setMsg(url);
  111 + }
  112 + msg.setData(resultData);
  113 +
  114 + resultHolder.invokeResult(msg);
  115 + });
  116 +
  117 + return result;
  118 + }
  119 +
  120 +}
... ...
web_src/src/components/StreamProxyList.vue
... ... @@ -10,6 +10,7 @@
10 10 </div>
11 11 <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
12 12 <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">添加代理</el-button>
  13 + <el-button v-if="false" icon="el-icon-search" size="mini" style="margin-right: 1rem;" type="primary" @click="addOnvif">搜索ONVIF</el-button>
13 14 </div>
14 15 <devicePlayer ref="devicePlayer"></devicePlayer>
15 16 <el-table :data="streamProxyList" border style="width: 100%" :height="winHeight">
... ... @@ -79,6 +80,7 @@
79 80 :total="total">
80 81 </el-pagination>
81 82 <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit>
  83 + <onvifEdit ref="onvifEdit" ></onvifEdit>
82 84 </el-main>
83 85 </el-container>
84 86 </div>
... ... @@ -86,6 +88,7 @@
86 88  
87 89 <script>
88 90 import streamProxyEdit from './dialog/StreamProxyEdit.vue'
  91 + import onvifEdit from './dialog/onvifEdit.vue'
89 92 import devicePlayer from './dialog/devicePlayer.vue'
90 93 import uiHeader from './UiHeader.vue'
91 94 export default {
... ... @@ -93,6 +96,7 @@
93 96 components: {
94 97 devicePlayer,
95 98 streamProxyEdit,
  99 + onvifEdit,
96 100 uiHeader
97 101 },
98 102 data() {
... ... @@ -113,7 +117,7 @@
113 117 },
114 118 mounted() {
115 119 this.initData();
116   - // this.updateLooper = setInterval(this.initData, 10000);
  120 + this.updateLooper = setInterval(this.initData, 1000);
117 121 },
118 122 destroyed() {
119 123 this.$destroy('videojs');
... ... @@ -155,6 +159,36 @@
155 159 addStreamProxy: function(){
156 160 this.$refs.streamProxyEdit.openDialog(null, this.initData)
157 161 },
  162 + addOnvif: function(){
  163 + this.getListLoading = true;
  164 + this.getListLoading = true;
  165 + this.$axios({
  166 + method: 'get',
  167 + url:`/api/onvif/search?timeout=3000`,
  168 + }).then((res) =>{
  169 + this.getListLoading = false;
  170 + if (res.data.code == 0 ){
  171 + if (res.data.data.length > 0) {
  172 + console.log(res.data.data)
  173 + this.$refs.onvifEdit.openDialog(res.data.data, (url)=>{
  174 + if (url != null) {
  175 + this.$refs.onvifEdit.close();
  176 + this.$refs.streamProxyEdit.openDialog({type: "default", url: url, src_url: url}, this.initData())
  177 + }
  178 + })
  179 + }else {
  180 + this.$message.success("未找到可用设备");
  181 + }
  182 + }else {
  183 + this.$message.error(res.data.msg);
  184 + }
  185 +
  186 + }).catch((error)=> {
  187 + this.getListLoading = false;
  188 + this.$message.error(error.response.data.msg);
  189 + });
  190 +
  191 + },
158 192 saveStreamProxy: function(){
159 193 },
160 194 play: function(row){
... ...
web_src/src/components/dialog/StreamProxyEdit.vue
... ... @@ -139,9 +139,6 @@ export default {
139 139 this.listChangeCallback = callback;
140 140 if (proxyParam != null) {
141 141 this.proxyParam = proxyParam;
142   - this.onSubmit_text = "保存";
143   - } else {
144   - this.onSubmit_text = "立即创建";
145 142 }
146 143 },
147 144 onSubmit: function () {
... ... @@ -163,6 +160,7 @@ export default {
163 160 that.showDialog = false;
164 161 if (that.listChangeCallback != null) {
165 162 that.listChangeCallback();
  163 + that.dialogLoading = false;
166 164 }
167 165 }
168 166 }).catch(function (error) {
... ...
web_src/src/components/dialog/onvifEdit.vue 0 → 100644
  1 +<template>
  2 + <div id="onvif搜索" v-loading="isLoging">
  3 + <el-dialog
  4 + title="onvif搜索"
  5 + width="40%"
  6 + top="2rem"
  7 + :close-on-click-modal="false"
  8 + :visible.sync="showDialog"
  9 + :destroy-on-close="true"
  10 + @close="close()"
  11 + >
  12 + <div id="shared" style="margin-top: 1rem;margin-right: 100px;">
  13 + <el-form ref="form" :rules="rules" :model="form" label-width="140px" >
  14 + <el-form-item label="地址" prop="hostName" >
  15 + <el-select v-model="form.hostName" style="float: left; width: 100%" >
  16 + <el-option
  17 + v-for="item in hostNames"
  18 + :key="item"
  19 + :label="item.replace('http://', '')"
  20 + :value="item">
  21 + </el-option>
  22 + </el-select>
  23 +
  24 + </el-form-item>
  25 + <el-form-item label="用户名" prop="username">
  26 + <el-input v-model="form.username" clearable></el-input>
  27 + </el-form-item>
  28 + <el-form-item label="密码" prop="password">
  29 + <el-input v-model="form.password" clearable></el-input>
  30 + </el-form-item>
  31 + <el-form-item>
  32 + <div style="float: right;">
  33 + <el-button type="primary" @click="onSubmit" >确认</el-button>
  34 + <el-button @click="close">取消</el-button>
  35 + </div>
  36 +
  37 + </el-form-item>
  38 + </el-form>
  39 + </div>
  40 + </el-dialog>
  41 + </div>
  42 +</template>
  43 +
  44 +<script>
  45 +export default {
  46 + name: "onvifEdit",
  47 + props: {},
  48 + computed: {},
  49 + created() {},
  50 + data() {
  51 + return {
  52 + listChangeCallback: null,
  53 + showDialog: false,
  54 + isLoging: false,
  55 + hostNames:[],
  56 + form: {
  57 + hostName: null,
  58 + username: "admin",
  59 + password: "admin123",
  60 + },
  61 +
  62 + rules: {
  63 + hostName: [{ required: true, message: "请选择", trigger: "blur" }],
  64 + username: [{ required: true, message: "请输入用户名", trigger: "blur" }],
  65 + password: [{ required: true, message: "请输入密码", trigger: "blur" }],
  66 + },
  67 + };
  68 + },
  69 + methods: {
  70 + openDialog: function (hostNamesParam, callback) {
  71 + console.log(hostNamesParam)
  72 + this.showDialog = true;
  73 + this.listChangeCallback = callback;
  74 + if (hostNamesParam != null) {
  75 + this.hostNames = hostNamesParam;
  76 + }
  77 +
  78 + },
  79 + onSubmit: function () {
  80 + console.log("onSubmit");
  81 + console.log(this.form);
  82 + this.$axios({
  83 + method: 'get',
  84 + url:`api/onvif/rtsp`,
  85 + params: {
  86 + hostname: this.form.hostName,
  87 + timeout: 3000,
  88 + username: this.form.username,
  89 + password: this.form.password,
  90 + }
  91 + }).then((res) => {
  92 + console.log(res.data)
  93 + if (res.data.code == 0) {
  94 + if (res.data.data != null) {
  95 + this.listChangeCallback(res.data.data)
  96 + }else {
  97 + this.$message({
  98 + showClose: true,
  99 + message: res.data.msg,
  100 + type: "error",
  101 + });
  102 + }
  103 +
  104 + }else {
  105 + this.$message({
  106 + showClose: true,
  107 + message: res.data.msg,
  108 + type: "error",
  109 + });
  110 + }
  111 + }).catch(function (error) {
  112 + console.log(error);
  113 + });
  114 + },
  115 + close: function () {
  116 + this.showDialog = false;
  117 + this.$refs.form.resetFields();
  118 + },
  119 + },
  120 +};
  121 +</script>
... ...