研究Onvif终于告一个段落了,有些东西整理出来,供参考分享。
怎么利用gsoap生成onvif客户端代码,网上有很多介绍这里就不再说明了。 下面直接上代码:
int CONVIFClientDlg::ONVIF_Discovery(char *devType)
{
struct soap *soap = NULL; //soap环境变量
struct SOAP_ENV__Header header; //SOAP的头
struct wsdd__ScopesType sScope; //Probe里面的范围
struct wsdd__ProbeType req; //客户端发送的Probe
struct __wsdd__ProbeMatches resp; //服务端回的Probematchs
char strUUID[50];
char was_To[] = "urn:schemas-xmlsoap-org:ws:2005:04:discovery";
char was_Action[] = "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";
char cDev[] = "tds:Device";
char cNVT[] = "tdn:NetworkVideoTransmitter";
int result = 0;
int count = 0;
int iTimes = 0;
soap = soap_new();
if(NULL == soap )
{
printf("[%s][%d]new soap failed!\n", __FUNCTION__,__LINE__);
return 0;
}
soap_set_namespaces(soap, namespaces);
// soap_init(soap);
soap_init1(soap, SOAP_IO_UDP|SOAP_IO_FLUSH);
// soap_init2(soap, SOAP_IO_UDP|SOAP_IO_FLUSH|SOAP_IO_KEEPALIVE, SOAP_IO_UDP|SOAP_IO_FLUSH|SOAP_IO_KEEPALIVE);
// if(!soap_valid_socket(soap_bind(soap, NULL, 3702, 10)))
// {
// return NULL;
// }
soap->recv_timeout = 3;
soap->send_timeout = 3;
// soap->connect_timeout = 5;
soap_default_SOAP_ENV__Header(soap, &header);
soap_default_wsdd__ScopesType(soap, &sScope);
soap_default_wsdd__ProbeType(soap, &req);
//给头赋值
//获取guid(windows下叫guid,linux下叫uuid),格式为urn:uuid:8-4-4-4-12,由系统随机产生
memset(strUUID, 0, 50);
NewUUID(strUUID);
header.wsa__MessageID = strUUID; //(char *)soap_wsa_rand_uuid(soap);
header.wsa__To = was_To; //"urn:schemas-xmlsoap-org:ws:2005:04:discovery";
header.wsa__Action = was_Action; //"http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";
soap->header = &header;
//设置所需寻找设备的类型和范围,二者至少设定一个,否则可能收到非ONVIF设备,出现异常;
sScope.__item = ""; //设置所需设备的sScope, onvif://www.onvif.org
req.Scopes = &sScope;
if(devType == NULL)
{
req.Types = cNVT;
}
else
{
//tdn:NetworkVideoTransmitter, 设置所需设备的类型,tdn为命名空间前缀,
//为wsdd.nsmap文件中{"tdn","http://www.onvif.org/ver10/network/wsdl"}的tdn,
//如过不是tdn,而是其它,如ns1这里也要随之改为ns1
req.Types = devType; //tdn:NetworkVideoTransmitter
}
//以下用于UDP绑定IP发送消息
int iSelect = m_cbHostIP.GetCurSel();
if(iSelect != -1 && iSelect < m_iIpNum)
{
soap->ip = inet_addr(m_IpAddr[iSelect].ip);
}
#if 0
while(iTimes < MAX_SENDMSG_TIMES) //需要发送多次消息
{
printf("发送Probe!\n");
result = soap_send___wsdd__Probe(soap,"soap.udp://239.255.255.250:3702", NULL, &req);
if(result != SOAP_OK)
{
printf("Probe发送失败!\n");
}
iTimes++;
printf("已发送Probe次数:%d\n", iTimes);
req.Types = Dev;
//重新生成UUID
NewUUID(strUUID);
::Sleep(100);
}
do{
result = soap_recv___wsdd__ProbeMatches(soap,&resp);
//接收ProbeMatches,成功返回0,否则-1
if (result != SOAP_OK)
{
printf("Probe接收失败!\n");
break;
}
else
{
count++;
CString strIP;
strIP.Format(_T("%d.%d.%d.%d"), ((soap->ip)>>24)&0xFF, ((soap->ip)>>16)&0xFF, ((soap->ip)>>8)&0xFF,(soap->ip)&0xFF);
_tprintf(_T("\n%s\n"), strIP);
if(resp.wsdd__ProbeMatches != NULL)
{
cout<<"===============发现设备"<<count<<"================"<<endl;
cout<<"Type:"<<resp.wsdd__ProbeMatches->ProbeMatch->Types<<endl;
cout<<"Service Address:"<<resp.wsdd__ProbeMatches->ProbeMatch->XAddrs<<endl;
cout<<"UUID:"<<resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address<<endl;
cout<<"MetadataVersion:"<<resp.wsdd__ProbeMatches->ProbeMatch->MetadataVersion<<endl;
cout<<"Scopes:"<<resp.wsdd__ProbeMatches->ProbeMatch->Scopes->__item<<endl;
cout<<"========================================="<<endl;
//可能有多个服务地址
CString strServiceAddr(resp.wsdd__ProbeMatches->ProbeMatch->XAddrs);
CString strUUID(resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address);
int index = m_stDeviceList.InsertItem(0, _T("OnvifDevice"));
m_stDeviceList.SetItemText(index, 0, strIP);
m_stDeviceList.SetItemText(index, 1, strServiceAddr);
m_stDeviceList.SetItemText(index, 2, strUUID);
}
}
}while(1);
#else
//通过组播发送Probe探针,发送成功返回0,否则-1
BOOL bFind = FALSE;
while(iTimes < MAX_SENDMSG_TIMES) //需要发送多次消息
{
if(m_bExit)
{
break;
}
printf("发送Probe!\n");
result = soap_send___wsdd__Probe(soap,"soap.udp://239.255.255.250:3702", NULL, &req);
if(result != SOAP_OK)
{
printf("Probe发送失败!\n");
}
else
{
count = 0;
do{
result = soap_recv___wsdd__ProbeMatches(soap,&resp);
//接收ProbeMatches,成功返回0,否则-1
if (result != SOAP_OK)
{
printf("Probe接收失败!\n");
break;
}
else
{
count++;
CString strIP;
strIP.Format(_T("%d.%d.%d.%d"), ((soap->ip)>>24)&0xFF, ((soap->ip)>>16)&0xFF, ((soap->ip)>>8)&0xFF,(soap->ip)&0xFF);
_tprintf(_T("\n%s\n"), strIP);
if(resp.wsdd__ProbeMatches != NULL)
{
cout<<"===============发现设备"<<count<<"================"<<endl;
cout<<"Type:"<<resp.wsdd__ProbeMatches->ProbeMatch->Types<<endl;
cout<<"Service Address:"<<resp.wsdd__ProbeMatches->ProbeMatch->XAddrs<<endl;
if(resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address != NULL)
{
cout<<"UUID:"<<resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address<<endl;
}
cout<<"MetadataVersion:"<<resp.wsdd__ProbeMatches->ProbeMatch->MetadataVersion<<endl;
cout<<"Scopes:"<<resp.wsdd__ProbeMatches->ProbeMatch->Scopes->__item<<endl;
cout<<"========================================="<<endl;
//可能有多个服务地址
CString strServiceAddr(resp.wsdd__ProbeMatches->ProbeMatch->XAddrs);
CString strUUID(_T(""));
if(resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address != NULL)
{
strUUID = resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address;
}
CString strMetadataVersion;
strMetadataVersion.Format("%d", resp.wsdd__ProbeMatches->ProbeMatch->MetadataVersion);
int index = m_stDeviceList.InsertItem(0, _T("OnvifDevice"));
m_stDeviceList.SetItemText(index, 0, strIP);
m_stDeviceList.SetItemText(index, 1, strUUID);
m_stDeviceList.SetItemText(index, 2, strServiceAddr);
m_stDeviceList.SetItemText(index, 7, strMetadataVersion);
}
bFind = TRUE;
}
}while(1);
}
iTimes++;
printf("已发送Probe次数:%d\n", iTimes);
::Sleep(1);
if(bFind)
{
break;
}
memset(strUUID, 0, 50);
NewUUID(strUUID);
header.wsa__MessageID = strUUID; //(char *)soap_wsa_rand_uuid(soap);
header.wsa__To = was_To; //"urn:schemas-xmlsoap-org:ws:2005:04:discovery";
header.wsa__Action = was_Action; //"http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";
soap->header = &header;
}
#endif
printf("\n总共发现设备数:%d\n\n", count);
//清除变量
soap_destroy(soap); //removedeserialized class instances (C++ only)
soap_end(soap); //clean up and remove deserialized data
// soap_done(soap);
soap_free(soap);
::Sleep(1000);
return count;
}