onvif开发摘要
对应onvif开发,步骤比较啰嗦。常规流程是:
1.下载gsoap工具
2.利用gsoap中wsdl2h在线生成头文件或者离线生成头文件。
1)在线生成头文件,但因为自带的wsdl2h.exe工具不支持https,需要自己编译一个windows版本工具,支持https还要移植openssl比较繁琐。
在Linux编译就方便多了安装openssl依赖,直接./configure make 即可生成新的wsdl2h
2)离线生成头文件,需要事先下载相关的wsdl文件以及依赖的xsd文件,相当的折腾,然后使用wsdl2h生成头文件
3 生成onvif.h头文件之后,即可根据soapcpp2命令生成C源文件或者CPP源文件。
注意:
1.因为鉴权的需要,在onvif.h头文件中加入#import "wsse.h"。
2.避免接下来产生框架发生错误,修改OnvifFramework(C++)\gsoap-2.8\gsoap\import路径下的wsa5.h,将SOAP_ENV__Fault结构体名字修改为SOAP_ENV__Fault_alex。
将生成的文件放到目录,后面即可调用。开发ONVIF客户端程序,使用XXXXProxy.h和XXXXProxy.scpervice.cpp,开发ONVIF服务器端程序,使用XXXXService.h和XXXXService.cpp
以上环境配置相当繁琐,运气不好可能会磕磕碰碰折腾一阵子。以上工作本质就将WSDL文档描述生成对应的C/C++代码,支持SOAP协议的发送和接收,以及onvif相关接口。
为了防止重复造轮子,笔者整理一套现成的SDK,以便后续快速进行二次开发。
目前提供了设备发现,获取媒体URL,云台控制,接收事件,录制管理等等,代码框架清楚直白,很容易二次开发
开发demo如下:
string GetMidaStreamUrl(OnvifClientDevice &onvifclientdevice,int channel)
{
_trt__GetProfilesResponse profiles;
_trt__GetStreamUriResponse StreamUriResponse;
tt__StreamSetup StreamSetup;
tt__Transport Transport;
Transport.Protocol = tt__TransportProtocol__UDP;
Transport.Tunnel = NULL;
StreamSetup.Stream = tt__StreamType__RTP_Unicast;
StreamSetup.Transport = &Transport;
#if 0
OnvifClientMedia* pmedia = new OnvifClientMedia(onvifclientdevice);
pmedia->GetProfiles(profiles);
//traverseVector(profiles.Profiles);
pmedia->GetStreamUri(StreamUriResponse, StreamSetup, profiles.Profiles[channel]->token);
#else
OnvifClientMedia media(onvifclientdevice);
media.GetProfiles(profiles);
//traverseVector(profiles.Profiles);
media.GetStreamUri(StreamUriResponse, StreamSetup, profiles.Profiles[channel]->token);
#endif
return StreamUriResponse.MediaUri->Uri;
}
typedef struct DeviceInfo
{
char uuid[64];
char deviceURL[64];
}DeviceInfo;
typedef struct DeviceList
{
int device_num;
DeviceInfo* pDeviceInfoList;
}DeviceList;
void ListDevideInfo(DeviceList DeviceList)
{
for (int i = 0; i < DeviceList.device_num; i++)
{
printf("uuid[%d]: %s\n", i,DeviceList.pDeviceInfoList[i].uuid);
printf("device[%d]: %s\n", i,DeviceList.pDeviceInfoList[i].deviceURL);
}
}
// SOAP_IO_UDP|SOAP_IO_FLUSH
int _tmain(int argc, _TCHAR* argv[])
{
if (argc < 3)
{
printf("usage: onvifclient.exe username password");
return 0;
}
int ret;
//发现设备
char* searchurl = "soap.udp://239.255.255.250:3702";
OnvifClientDiscovery tOnvifClientDiscovery(searchurl);
DeviceList DeviceList;
DeviceInfo* pDeviceInfo = NULL;
wsdd__ProbeMatchesType t_ProbeMatchesType;
tOnvifClientDiscovery.OnvifClientDeviceSearch(t_ProbeMatchesType);
DeviceList.device_num = t_ProbeMatchesType.__sizeProbeMatch;
if (t_ProbeMatchesType.__sizeProbeMatch > 0)
{
pDeviceInfo = (DeviceInfo*)malloc(sizeof(DeviceInfo) * (t_ProbeMatchesType.__sizeProbeMatch));
if (!pDeviceInfo)
{
printf("malloc DeviceList is failed ");
return 0;
}
DeviceList.pDeviceInfoList = pDeviceInfo;
}
for (int i = 0; i < t_ProbeMatchesType.__sizeProbeMatch; i++)
{
strcpy(pDeviceInfo[i].uuid, t_ProbeMatchesType.ProbeMatch[i].wsa__EndpointReference.Address);
strcpy(pDeviceInfo[i].deviceURL, t_ProbeMatchesType.ProbeMatch[i].XAddrs);
}
ListDevideInfo(DeviceList);
//查找媒体URL
string user(argv[1]);
string pass(argv[2]);
for (int i = 0; i < t_ProbeMatchesType.__sizeProbeMatch; i++)
{
string url(DeviceList.pDeviceInfoList[i].deviceURL);
OnvifClientDevice* ponvifDevice = new OnvifClientDevice(url, user, pass);
if (!ponvifDevice)
{
printf("malloc OnvifClientDevice is failed");
return 0;
}
_tds__GetCapabilitiesResponse pcapabilitiesResponse;
if (ponvifDevice)
{
ponvifDevice->GetCapabilities(pcapabilitiesResponse);
}
string MediaUri = GetMidaStreamUrl(*ponvifDevice, 0);
printf("url is %s\n", MediaUri.c_str());
}
return 0
}
编译后运行该程序
该demo地址如下:
https://download.csdn.net/download/fengliang191/12391306
该demo可以作为一个工具,可以用来发现支持onvif协议的IPC的IP地址,获取媒体RTSP的URL。因为不同厂家IPC的RTSP的URL不一样,该工具可以自动查找摄像头的RTSP的URL。目前SDK提供了设备发现,获取媒体URL,云台控制,接收事件,录制管理等等,代码框架清楚直白,支持Linux /windows ,很容易二次开发。SDK 下载地址请关注公众号:AV_Chat