本文是Linux c++ onvif客户端开发系列文章之一:
- Linux c++ onvif客户端开发(1): 根据wsdl生成cpp源文件
- Linux c++ onvif客户端开发(2): 获取摄像头H264/H265 RTSP地址
- Linux c++ onvif客户端开发(3): 扫描设备
- Linux c++ onvif客户端开发(4): 扫描某个设备是否支持onvif
- Linux c++ onvif客户端开发(5):gsoap内存管理
-
Linux c++ onvif客户端开发(6):获取设备信息
-
Linux c++ onvif客户端开发(7):struct soap包装类
1. 接口作用
返回设备支持的服务和能力集合。
服务:就是这个设备支持什么功能。每个服务都有一个固定的命名空间namespace,这个命名空间是有规范定义的不可修改的;还有一个对应设备服务的url地址,这个是设备商可以自定义的。
能力:就是这个服务的功能细节,比如视频服务是否支持rtsp协议等等。
典型的数据格式
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<s:Envelope
xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:sc="http://www.w3.org/2003/05/soap-encoding"
xmlns:tt="http://www.onvif.org/ver10/schema"
xmlns:tds="http://www.onvif.org/ver10/device/wsdl"
xmlns:trt="http://www.onvif.org/ver10/media/wsdl"
xmlns:tr2="http://www.onvif.org/ver20/media/wsdl"
xmlns:tev="http://www.onvif.org/ver10/events/wsdl"
xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl"
xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl"
xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl">
<s:Body>
<tds:GetServicesResponse>
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver10/device/wsdl</tds:Namespace>
<tds:XAddr>http://10.10.10.13/onvif/device_service</tds:XAddr>
<tds:Version>
<tt:Major>1</tt:Major>
<tt:Minor>0</tt:Minor>
</tds:Version>
</tds:Service>
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver20/analytics/wsdl</tds:Namespace>
<tds:XAddr>http://10.10.10.13/onvif/Analytics_service</tds:XAddr>
<tds:Version>
<tt:Major>1</tt:Major>
<tt:Minor>0</tt:Minor>
</tds:Version>
</tds:Service>
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver20/imaging/wsdl</tds:Namespace>
<tds:XAddr>http://10.10.10.13/onvif/imaging_service</tds:XAddr>
<tds:Version>
<tt:Major>2</tt:Major>
<tt:Minor>0</tt:Minor>
</tds:Version>
</tds:Service>
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver10/media/wsdl</tds:Namespace>
<tds:XAddr>http://10.10.10.13/onvif/media_service</tds:XAddr>
<tds:Version>
<tt:Major>1</tt:Major>
<tt:Minor>0</tt:Minor>
</tds:Version>
</tds:Service>
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver20/media/wsdl</tds:Namespace>
<tds:XAddr>http://10.10.10.13/onvif/media2_service</tds:XAddr>
<tds:Version>
<tt:Major>2</tt:Major>
<tt:Minor>0</tt:Minor>
</tds:Version>
</tds:Service>
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver10/events/wsdl</tds:Namespace>
<tds:XAddr>http://10.10.10.103/onvif/event_service</tds:XAddr>
<tds:Version>
<tt:Major>1</tt:Major>
<tt:Minor>0</tt:Minor>
</tds:Version>
</tds:Service>
<tds:Service>
<tds:Namespace>http://www.onvif.org/ver10/deviceIO/wsdl</tds:Namespace>
<tds:XAddr>http://10.10.10.13/onvif/deviceIO_service</tds:XAddr>
<tds:Version>
<tt:Major>1</tt:Major>
<tt:Minor>0</tt:Minor>
</tds:Version>
</tds:Service>
</tds:GetServicesResponse>
</s:Body>
</s:Envelope>
2. 掏出ONVIF Device Test Tool测试一番
1.打开测试工具,选中网卡
2. Device IP填写好设备地址,probe获取服务地址
3. password填写密码,check 获取设备信息
获取信息是需要密码的。
4. 切换到debug-Device Management - Get Services
3. 查看文档接口
wsdl定义
https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl
ONVIF-Core-Specification
https://www.onvif.org/specs/core/ONVIF-Core-Specification.pdf
4. 代码实现
定义Service对象
struct Service {
std::string ns;
std::string xaddr;
};
Device对象
class Device {
public:
Device(const std::string &ip, const std::string &user,
const std::string &passwd, int default_timeout = 2);
~Device();
int Probe(int timeout = 1);
std::string xaddr() const { return xaddr_; }
int GetDeviceInformation(DeviceInformation &device_info,
Fault *fault = nullptr);
// 获取服务地址集
int GetServices(std::map<std::string, Service> &services,
Fault *fault = nullptr);
private:
std::string ip_;
std::string username_;
std::string password_;
int default_timeout_;
std::string xaddr_;
};
实现GetServices。
如果需要返回capabilities 数据,IncludeCapability 可以指定为true,默认不指定。
int Device::GetServices(std::map<std::string, Service> &services,
Fault *fault) {
std::unique_ptr<Soap> soap(new Soap(default_timeout_));
soap_wsse_add_UsernameTokenDigest(soap->soap(), nullptr, username_.data(),
password_.data());
struct _tds__GetServices devsrv_req;
struct _tds__GetServicesResponse devsrv_resp;
// devsrv_req.IncludeCapability = true;
int result = soap_call___tds__GetServices(soap->soap(), xaddr_.data(), NULL,
&devsrv_req, devsrv_resp);
if (SOAP_OK == result) {
for (auto &i : devsrv_resp.Service) {
Service ser{i->Namespace, i->XAddr};
services[i->Namespace] = ser;
}
} else {
soap->FillFault(fault);
}
return result;
}
Soap 和 Fault的定义参考第7篇文章