panlinlin
4 years ago
11 changed files with 446 additions and 7 deletions
@ -0,0 +1,3 @@ |
|||
[submodule "be.teletask.onvif-java"] |
|||
path = be.teletask.onvif-java |
|||
url = https://gitee.com/18010473990/be.teletask.onvif-java.git |
Binary file not shown.
@ -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); |
|||
} |
@ -0,0 +1,5 @@ |
|||
package com.genersoft.iot.vmp.onvif.dto; |
|||
|
|||
public interface ONVIFCallBack<T> { |
|||
void run(int errorCode, T t); |
|||
} |
@ -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()); |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
@ -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的rtsp地址") |
|||
@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的rtsp地址超时"); |
|||
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; |
|||
} |
|||
|
|||
} |
@ -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> |
Loading…
Reference in new issue