From 5ba0fba03d9fcb09eea0c1e703a4f050378d7992 Mon Sep 17 00:00:00 2001 From: panlinlin <648540858@qq.com> Date: 星期一, 26 四月 2021 09:13:17 +0800 Subject: [PATCH] 添加部分onvif代码 --- libs/onvif-java-1.0.2.jar | 0 src/main/java/com/genersoft/iot/vmp/vmanager/onvif/ONVIFController.java | 120 +++++++++++++++ .gitmodules | 3 web_src/src/components/StreamProxyList.vue | 36 ++++ src/main/java/com/genersoft/iot/vmp/onvif/impl/ONVIFServerIMpl.java | 116 ++++++++++++++ src/main/java/com/genersoft/iot/vmp/onvif/IONVIFServer.java | 13 + web_src/src/components/dialog/onvifEdit.vue | 121 +++++++++++++++ web_src/src/components/dialog/StreamProxyEdit.vue | 4 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java | 2 pom.xml | 33 +++ src/main/java/com/genersoft/iot/vmp/onvif/dto/ONVIFCallBack.java | 5 11 files changed, 446 insertions(+), 7 deletions(-) diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..202b14c --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "be.teletask.onvif-java"] + path = be.teletask.onvif-java + url = https://gitee.com/18010473990/be.teletask.onvif-java.git diff --git a/libs/onvif-java-1.0.2.jar b/libs/onvif-java-1.0.2.jar new file mode 100644 index 0000000..dd62a23 --- /dev/null +++ b/libs/onvif-java-1.0.2.jar Binary files differ diff --git a/pom.xml b/pom.xml index 91b90e6..f8a8b53 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ </parent> <groupId>com.genersoft</groupId> - <artifactId>wvp</artifactId> + <artifactId>wvp-gb28181</artifactId> <version>2.0.0</version> <name>web video platform</name> @@ -44,6 +44,7 @@ <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format> <!-- 渚濊禆鐗堟湰 --> <pagehelper.version>5.2.0</pagehelper.version> @@ -167,10 +168,36 @@ <artifactId>okhttp</artifactId> <version>4.9.0</version> </dependency> - </dependencies> + + <!-- okhttp-digest --> + <dependency> + <groupId>com.burgstaller</groupId> + <artifactId>okhttp-digest</artifactId> + <version>2.1</version> + </dependency> + + <!-- https://mvnrepository.com/artifact/net.sf.kxml/kxml2 --> + <dependency> + <groupId>net.sf.kxml</groupId> + <artifactId>kxml2</artifactId> + <version>2.3.0</version> + </dependency> + + + <!-- onvif鍗忚鏍� --> + <dependency> + <groupId>be.teletask</groupId> + <artifactId>onvif-java</artifactId> + <version>1.0.2</version> + <scope>system</scope> + <systemPath>${project.basedir}/libs/onvif-java-1.0.2.jar</systemPath> + </dependency> + </dependencies> + + <build> - <finalName>wvp-2.0</finalName> + <finalName>${project.artifactId}-${project.version}-${maven.build.timestamp}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java index b7f592e..f21895c 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java @@ -35,6 +35,8 @@ public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP"; + public static final String CALLBACK_ONVIF = "CALLBACK_ONVIF"; + public static final String CALLBACK_CMD_MOBILEPOSITION = "CALLBACK_MOBILEPOSITION"; public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY"; diff --git a/src/main/java/com/genersoft/iot/vmp/onvif/IONVIFServer.java b/src/main/java/com/genersoft/iot/vmp/onvif/IONVIFServer.java new file mode 100644 index 0000000..eb81a36 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/onvif/IONVIFServer.java @@ -0,0 +1,13 @@ +package com.genersoft.iot.vmp.onvif; + +import be.teletask.onvif.models.OnvifDevice; +import com.genersoft.iot.vmp.onvif.dto.ONVIFCallBack; + +import java.util.List; + +public interface IONVIFServer { + + void search(int timeout, ONVIFCallBack<List<String>> callBack); + + void getRTSPUrl(int timeout, OnvifDevice device, ONVIFCallBack<String> callBack); +} diff --git a/src/main/java/com/genersoft/iot/vmp/onvif/dto/ONVIFCallBack.java b/src/main/java/com/genersoft/iot/vmp/onvif/dto/ONVIFCallBack.java new file mode 100644 index 0000000..3fdbde5 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/onvif/dto/ONVIFCallBack.java @@ -0,0 +1,5 @@ +package com.genersoft.iot.vmp.onvif.dto; + +public interface ONVIFCallBack<T> { + void run(int errorCode, T t); +} diff --git a/src/main/java/com/genersoft/iot/vmp/onvif/impl/ONVIFServerIMpl.java b/src/main/java/com/genersoft/iot/vmp/onvif/impl/ONVIFServerIMpl.java new file mode 100644 index 0000000..e747118 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/onvif/impl/ONVIFServerIMpl.java @@ -0,0 +1,116 @@ +package com.genersoft.iot.vmp.onvif.impl; + + +import be.teletask.onvif.DiscoveryManager; +import be.teletask.onvif.OnvifManager; +import be.teletask.onvif.listeners.*; +import be.teletask.onvif.models.*; +import be.teletask.onvif.responses.OnvifResponse; +import com.genersoft.iot.vmp.onvif.IONVIFServer; +import com.genersoft.iot.vmp.onvif.dto.ONVIFCallBack; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 澶勭悊onvif鐨勫悇绉嶆搷浣� + */ +@Service +public class ONVIFServerIMpl implements IONVIFServer { + + private final static Logger logger = LoggerFactory.getLogger(ONVIFServerIMpl.class); + + @Override + public void search(int timeout, ONVIFCallBack<List<String>> callBack) { + DiscoveryManager manager = new DiscoveryManager(); + manager.setDiscoveryTimeout(timeout); + Map<String, Device> deviceMap = new HashMap<>(); + // 鎼滅储璁惧 + manager.discover(new DiscoveryListener() { + @Override + public void onDiscoveryStarted() { + logger.info("Discovery started"); + } + + @Override + public void onDevicesFound(List<Device> devices) { + if (devices == null || devices.size() == 0) return; + for (Device device : devices){ + System.out.println(device.getHostName()); + deviceMap.put(device.getHostName(), device); + } + } + + // 鎼滅储缁撴潫 + @Override + public void onDiscoveryFinished() { + ArrayList<String> result = new ArrayList<>(); + for (Device device : deviceMap.values()) { + System.out.println(device.getHostName()); + result.add(device.getHostName()); + } + callBack.run(0, result); + } + }); + } + + @Override + public void getRTSPUrl(int timeout, OnvifDevice device, ONVIFCallBack<String> callBack) { + if (device.getHostName() == null ){ + callBack.run(400, null); + } + OnvifManager onvifManager = new OnvifManager(); + onvifManager.setOnvifResponseListener(new OnvifResponseListener(){ + + @Override + public void onResponse(OnvifDevice onvifDevice, OnvifResponse response) { + System.out.println("[RESPONSE] " + onvifDevice.getHostName() + + "======" + response.getErrorCode() + + "======" + response.getErrorMessage()); + } + + @Override + public void onError(OnvifDevice onvifDevice, int errorCode, String errorMessage) { + System.out.println("[ERROR] " + onvifDevice.getHostName() + "======" + errorCode + "=======" + errorMessage); + callBack.run(errorCode, errorMessage); + } + }); + + try { + onvifManager.getServices(device, (OnvifDevice onvifDevice, OnvifServices services) -> { + if (services.getProfilesPath().equals("/onvif/Media")) { + onvifDevice.setPath(services); + onvifManager.getMediaProfiles(onvifDevice, new OnvifMediaProfilesListener() { + @Override + public void onMediaProfilesReceived(OnvifDevice device, List<OnvifMediaProfile> mediaProfiles) { + for (OnvifMediaProfile mediaProfile : mediaProfiles) { + System.out.println(mediaProfile.getName()); + System.out.println(mediaProfile.getToken()); + if (mediaProfile.getName().equals("mainStream")) { + onvifManager.getMediaStreamURI(device, mediaProfile, (OnvifDevice onvifDevice, + OnvifMediaProfile profile, String uri) -> { + + uri = uri.replace("rtsp://", "rtsp://"+ device.getUsername() + ":"+ device.getPassword() + "@"); + logger.info(onvifDevice.getHostName() + "鐨勫湴鍧�" + uri); + callBack.run(0, uri); + }); + } + } + } + }); + } + }); + }catch (Exception e) { + callBack.run(400, e.getMessage()); + } + + + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/onvif/ONVIFController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/onvif/ONVIFController.java new file mode 100644 index 0000000..a484b51 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/onvif/ONVIFController.java @@ -0,0 +1,120 @@ +package com.genersoft.iot.vmp.vmanager.onvif; + +import be.teletask.onvif.models.OnvifDevice; +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; +import com.genersoft.iot.vmp.onvif.IONVIFServer; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.async.DeferredResult; + +import java.util.List; +import java.util.UUID; + +@Api(tags = "onvif璁惧") +@CrossOrigin +@RestController +@RequestMapping("/api/onvif") +public class ONVIFController { + + + @Autowired + private DeferredResultHolder resultHolder; + + @Autowired + private IONVIFServer onvifServer; + + + @ApiOperation("鎼滅储") + @ApiImplicitParams({ + @ApiImplicitParam(name="timeout", value = "瓒呮椂鏃堕棿", required = true, dataTypeClass = Integer.class), + }) + @GetMapping(value = "/search") + @ResponseBody + public DeferredResult<ResponseEntity<WVPResult>> search(@RequestParam(required = false)Integer timeout){ + DeferredResult<ResponseEntity<WVPResult>> result = new DeferredResult<>(timeout + 10L); + UUID uuid = UUID.randomUUID(); + result.onTimeout(()->{ + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid); + WVPResult<String> wvpResult = new WVPResult(); + wvpResult.setCode(0); + wvpResult.setMsg("鎼滅储瓒呮椂"); + msg.setData(wvpResult); + resultHolder.invokeResult(msg); + }); + resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF + uuid, result); + + onvifServer.search(timeout, (errorCode, onvifDevices) ->{ + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid); + WVPResult<List<String>> resultData = new WVPResult(); + resultData.setCode(errorCode); + if (errorCode == 0) { + resultData.setMsg("success"); + resultData.setData(onvifDevices); + }else { + resultData.setMsg("fail"); + } + msg.setData(resultData); + msg.setData(resultData); + resultHolder.invokeResult(msg); + }); + + return result; + } + + @ApiOperation("鑾峰彇onvif鐨剅tsp鍦板潃") + @ApiImplicitParams({ + @ApiImplicitParam(name="timeout", value = "瓒呮椂鏃堕棿", required = true, dataTypeClass = Integer.class), + @ApiImplicitParam(name="hostname", value = "onvif鍦板潃", required = true, dataTypeClass = String.class), + @ApiImplicitParam(name="username", value = "鐢ㄦ埛鍚�", required = true, dataTypeClass = String.class), + @ApiImplicitParam(name="password", value = "瀵嗙爜", required = true, dataTypeClass = String.class), + }) + @GetMapping(value = "/rtsp") + @ResponseBody + public DeferredResult<ResponseEntity<WVPResult>> getRTSPUrl(@RequestParam(value="timeout", required=false, defaultValue="3000") Integer timeout, + @RequestParam(required = true) String hostname, + @RequestParam(required = false) String username, + @RequestParam(required = false) String password + ){ + + DeferredResult<ResponseEntity<WVPResult>> result = new DeferredResult<>(timeout + 10L); + UUID uuid = UUID.randomUUID(); + result.onTimeout(()->{ + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid); + WVPResult<String> wvpResult = new WVPResult(); + wvpResult.setCode(0); + wvpResult.setMsg("鑾峰彇onvif鐨剅tsp鍦板潃瓒呮椂"); + msg.setData(wvpResult); + resultHolder.invokeResult(msg); + }); + resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF + uuid, result); + OnvifDevice onvifDevice = new OnvifDevice(hostname, username, password); + onvifServer.getRTSPUrl(timeout, onvifDevice, (errorCode, url) ->{ + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid); + WVPResult<String> resultData = new WVPResult(); + resultData.setCode(errorCode); + if (errorCode == 0) { + resultData.setMsg("success"); + resultData.setData(url); + }else { + resultData.setMsg(url); + } + msg.setData(resultData); + + resultHolder.invokeResult(msg); + }); + + return result; + } + +} diff --git a/web_src/src/components/StreamProxyList.vue b/web_src/src/components/StreamProxyList.vue index 0e0fcdd..d71de84 100644 --- a/web_src/src/components/StreamProxyList.vue +++ b/web_src/src/components/StreamProxyList.vue @@ -10,6 +10,7 @@ </div> <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;"> <el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addStreamProxy">娣诲姞浠g悊</el-button> + <el-button v-if="false" icon="el-icon-search" size="mini" style="margin-right: 1rem;" type="primary" @click="addOnvif">鎼滅储ONVIF</el-button> </div> <devicePlayer ref="devicePlayer"></devicePlayer> <el-table :data="streamProxyList" border style="width: 100%" :height="winHeight"> @@ -79,6 +80,7 @@ :total="total"> </el-pagination> <streamProxyEdit ref="streamProxyEdit" ></streamProxyEdit> + <onvifEdit ref="onvifEdit" ></onvifEdit> </el-main> </el-container> </div> @@ -86,6 +88,7 @@ <script> import streamProxyEdit from './dialog/StreamProxyEdit.vue' + import onvifEdit from './dialog/onvifEdit.vue' import devicePlayer from './dialog/devicePlayer.vue' import uiHeader from './UiHeader.vue' export default { @@ -93,6 +96,7 @@ components: { devicePlayer, streamProxyEdit, + onvifEdit, uiHeader }, data() { @@ -113,7 +117,7 @@ }, mounted() { this.initData(); - // this.updateLooper = setInterval(this.initData, 10000); + this.updateLooper = setInterval(this.initData, 1000); }, destroyed() { this.$destroy('videojs'); @@ -155,6 +159,36 @@ addStreamProxy: function(){ this.$refs.streamProxyEdit.openDialog(null, this.initData) }, + addOnvif: function(){ + this.getListLoading = true; + this.getListLoading = true; + this.$axios({ + method: 'get', + url:`/api/onvif/search?timeout=3000`, + }).then((res) =>{ + this.getListLoading = false; + if (res.data.code == 0 ){ + if (res.data.data.length > 0) { + console.log(res.data.data) + this.$refs.onvifEdit.openDialog(res.data.data, (url)=>{ + if (url != null) { + this.$refs.onvifEdit.close(); + this.$refs.streamProxyEdit.openDialog({type: "default", url: url, src_url: url}, this.initData()) + } + }) + }else { + this.$message.success("鏈壘鍒板彲鐢ㄨ澶�"); + } + }else { + this.$message.error(res.data.msg); + } + + }).catch((error)=> { + this.getListLoading = false; + this.$message.error(error.response.data.msg); + }); + + }, saveStreamProxy: function(){ }, play: function(row){ diff --git a/web_src/src/components/dialog/StreamProxyEdit.vue b/web_src/src/components/dialog/StreamProxyEdit.vue index 696379e..1c0d3b9 100644 --- a/web_src/src/components/dialog/StreamProxyEdit.vue +++ b/web_src/src/components/dialog/StreamProxyEdit.vue @@ -139,9 +139,6 @@ this.listChangeCallback = callback; if (proxyParam != null) { this.proxyParam = proxyParam; - this.onSubmit_text = "淇濆瓨"; - } else { - this.onSubmit_text = "绔嬪嵆鍒涘缓"; } }, onSubmit: function () { @@ -163,6 +160,7 @@ that.showDialog = false; if (that.listChangeCallback != null) { that.listChangeCallback(); + that.dialogLoading = false; } } }).catch(function (error) { diff --git a/web_src/src/components/dialog/onvifEdit.vue b/web_src/src/components/dialog/onvifEdit.vue new file mode 100644 index 0000000..c853294 --- /dev/null +++ b/web_src/src/components/dialog/onvifEdit.vue @@ -0,0 +1,121 @@ +<template> + <div id="onvif鎼滅储" v-loading="isLoging"> + <el-dialog + title="onvif鎼滅储" + width="40%" + top="2rem" + :close-on-click-modal="false" + :visible.sync="showDialog" + :destroy-on-close="true" + @close="close()" + > + <div id="shared" style="margin-top: 1rem;margin-right: 100px;"> + <el-form ref="form" :rules="rules" :model="form" label-width="140px" > + <el-form-item label="鍦板潃" prop="hostName" > + <el-select v-model="form.hostName" style="float: left; width: 100%" > + <el-option + v-for="item in hostNames" + :key="item" + :label="item.replace('http://', '')" + :value="item"> + </el-option> + </el-select> + + </el-form-item> + <el-form-item label="鐢ㄦ埛鍚�" prop="username"> + <el-input v-model="form.username" clearable></el-input> + </el-form-item> + <el-form-item label="瀵嗙爜" prop="password"> + <el-input v-model="form.password" clearable></el-input> + </el-form-item> + <el-form-item> + <div style="float: right;"> + <el-button type="primary" @click="onSubmit" >纭</el-button> + <el-button @click="close">鍙栨秷</el-button> + </div> + + </el-form-item> + </el-form> + </div> + </el-dialog> + </div> +</template> + +<script> +export default { + name: "onvifEdit", + props: {}, + computed: {}, + created() {}, + data() { + return { + listChangeCallback: null, + showDialog: false, + isLoging: false, + hostNames:[], + form: { + hostName: null, + username: "admin", + password: "admin123", + }, + + rules: { + hostName: [{ required: true, message: "璇烽�夋嫨", trigger: "blur" }], + username: [{ required: true, message: "璇疯緭鍏ョ敤鎴峰悕", trigger: "blur" }], + password: [{ required: true, message: "璇疯緭鍏ュ瘑鐮�", trigger: "blur" }], + }, + }; + }, + methods: { + openDialog: function (hostNamesParam, callback) { + console.log(hostNamesParam) + this.showDialog = true; + this.listChangeCallback = callback; + if (hostNamesParam != null) { + this.hostNames = hostNamesParam; + } + + }, + onSubmit: function () { + console.log("onSubmit"); + console.log(this.form); + this.$axios({ + method: 'get', + url:`api/onvif/rtsp`, + params: { + hostname: this.form.hostName, + timeout: 3000, + username: this.form.username, + password: this.form.password, + } + }).then((res) => { + console.log(res.data) + if (res.data.code == 0) { + if (res.data.data != null) { + this.listChangeCallback(res.data.data) + }else { + this.$message({ + showClose: true, + message: res.data.msg, + type: "error", + }); + } + + }else { + this.$message({ + showClose: true, + message: res.data.msg, + type: "error", + }); + } + }).catch(function (error) { + console.log(error); + }); + }, + close: function () { + this.showDialog = false; + this.$refs.form.resetFields(); + }, + }, +}; +</script> -- Gitblit v1.8.0