说明:
有一段时间被ONVIF弄的焦头烂额,特别是WS-Discovery。。。
ONVIF 采用这种全功能,SOAP而非REST模型,感觉没有那么好。。。
本文使用Gsoap 2.8.9 ,VS2010,win7
使用C++,以及命名空间将多个ONVIF service以dll/lib方式集成一起,所有代码可以
到这里下载点击打开链接
另外由于时间有限,整个VS2010 solution第一次编译可能不通过,大家再编译一次就好了
1. 参考“http://blog.csdn.net/ghostyu/article/details/8182516”,修改typemap.dat(注,修改前的typemap.dat位于
gsaop解压后目录)。修改后的typemap.dat在这里。
本文不同之处在于,使用C++,以及命名空间
2. 生成ws-discovery 服务server/client端代码,使用C++命名空间“WSDDiscovery”
如果用win7,最好用管理员权限打开"cmd",确保修改后的typemap.dat位于gsoap/bin/win32下面
cd gsoap/bin/win32
wsdl2h -o onvif.h -s -ttypemap.dat http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl
soapcpp2 onvif.h -x -qWSDDiscovery -I../../import -I../../
-qWSDDiscovery,指定命名空间。本文将ws-discovery,devicemgmt等service集成,使用命名空间,不用的兄弟可以不需要。
这一步将会生成“WSDDiscoveryStub.h”,“WSDDiscoveryServer.cpp”等文件
3.修改“WSDDiscoveryStub.h”
删除图中“WITH_NOGLOBAL”定义
4. 修改“WSDDiscoveryServer.cpp”,添加ws-discovery service端回调函数,注意将代码放置于命名空间内
SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Hello(struct soap*, struct wsdd__HelloType *wsdd__Hello)
{
return -1;
}
SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Bye(struct soap*, struct wsdd__ByeType *wsdd__Bye)
{
return -1;
}
SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Probe(struct soap* soap, struct wsdd__ProbeType *wsdd__Probe)
{
char _HwId[64]="urn:uuid:D149F919-4013-437E-B480-3707D96D27A4";
int interface_num = 0;
char ip_list[512]={0};
// Auto - get local ip address , return back this ip-address
GetIpList( ip_list , interface_num);
wsdd__ProbeMatchesType ProbeMatches;
ProbeMatches.__sizeProbeMatch = interface_num;
ProbeMatches.ProbeMatch = (struct wsdd__ProbeMatchType *)soap_malloc(soap, sizeof(struct wsdd__ProbeMatchType)*interface_num);
for(int i=0; i<interface_num; i++) {
ProbeMatches.ProbeMatch[i].MetadataVersion = 1;
// should be onvif device mgmt address
ProbeMatches.ProbeMatch[i].XAddrs = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);
sprintf(ProbeMatches.ProbeMatch[i].XAddrs, "http://%s:45678/", ip_list+i*20);
// probe type
ProbeMatches.ProbeMatch[i].Types = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);
strcpy( ProbeMatches.ProbeMatch[i].Types , "tdn:NetworkVideoTransmitter" );
// Scope
ProbeMatches.ProbeMatch[i].Scopes = (struct wsdd__ScopesType*)soap_malloc(soap,sizeof(struct wsdd__ScopesType));
ProbeMatches.ProbeMatch[i].Scopes->__item =(char *)soap_malloc(soap, 1024);
memset(ProbeMatches.ProbeMatch[i].Scopes->__item,0,sizeof(ProbeMatches.ProbeMatch->Scopes->__item));
strcat(ProbeMatches.ProbeMatch[i].Scopes->__item, "onvif://www.onvif.org/type/NetworkVideoTransmitter");
ProbeMatches.ProbeMatch[i].Scopes->MatchBy = NULL;
//ws-discovery¹æ¶¨ Ϊ¿ÉÑ¡Ïî , ReferenceProperties
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.ReferenceProperties = (struct wsa__ReferencePropertiesType*)soap_malloc(soap,sizeof(struct wsa__ReferencePropertiesType));
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.ReferenceProperties->__size = 0;
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.ReferenceProperties->__any = NULL;
//ws-discovery¹æ¶¨ Ϊ¿ÉÑ¡Ïî , ReferenceParameters
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.ReferenceParameters = (struct wsa__ReferenceParametersType*)soap_malloc(soap,sizeof(struct wsa__ReferenceParametersType));
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.ReferenceParameters->__size = 0;
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.ReferenceParameters->__any = NULL;
//ws-discovery¹æ¶¨ Ϊ¿ÉÑ¡Ïî , PortType
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.PortType = (char **)soap_malloc(soap, sizeof(char*) * SMALL_INFO_LENGTH);
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.PortType[0] = (char *)soap_malloc(soap, sizeof(char) * SMALL_INFO_LENGTH);
strcpy(ProbeMatches.ProbeMatch[i].wsa__EndpointReference.PortType[0], "ttl");
//ws-discovery¹æ¶¨ Ϊ¿ÉÑ¡Ïî , ServiceName
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.ServiceName = (struct wsa__ServiceNameType*)soap_malloc(soap,sizeof(struct wsa__ServiceNameType));
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.ServiceName->__item = NULL;
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.ServiceName->PortName = NULL;
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.ServiceName->__anyAttribute = NULL;
//ws-discovery¹æ¶¨ Ϊ¿ÉÑ¡Ïî , __any
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.__any = (char **)soap_malloc(soap, sizeof(char*) * SMALL_INFO_LENGTH);
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.__any[0] = (char *)soap_malloc(soap, sizeof(char) * SMALL_INFO_LENGTH);
strcpy(ProbeMatches.ProbeMatch[i].wsa__EndpointReference.__any[0], "Any");
//ws-discovery¹æ¶¨ Ϊ¿ÉÑ¡Ïî , __anyAttribute
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.__anyAttribute = (char *)soap_malloc(soap, sizeof(char) * SMALL_INFO_LENGTH);
strcpy(ProbeMatches.ProbeMatch[i].wsa__EndpointReference.__anyAttribute, "Attribute");
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.__size = 0;
//ws-discovery¹æ¶¨ Ϊ¿ÉÑ¡Ïî , Address
ProbeMatches.ProbeMatch[i].wsa__EndpointReference.Address = (char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);
strcpy(ProbeMatches.ProbeMatch[i].wsa__EndpointReference.Address, _HwId);
}
if( soap->header == 0 ) {
soap->header = (::SOAP_ENV__Header*)soap_malloc(soap, sizeof(struct SOAP_ENV__Header));
soap->header->wsa__RelatesTo = (::wsa__Relationship*)soap_malloc(soap, sizeof(struct wsa__Relationship));
//it's here
soap->header->wsa__MessageID =(char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);
strcpy(soap->header->wsa__MessageID,_HwId+4);
soap->header->wsa__RelatesTo->__item = soap->header->wsa__MessageID;
soap->header->wsa__RelatesTo->RelationshipType = NULL;
soap->header->wsa__RelatesTo->__anyAttribute = NULL;
}
else {
soap->header->wsa__RelatesTo = (::wsa__Relationship*)soap_malloc(soap, sizeof(struct wsa__Relationship));
//it's here
soap->header->wsa__RelatesTo->__item = soap->header->wsa__MessageID;
soap->header->wsa__RelatesTo->RelationshipType = NULL;
soap->header->wsa__RelatesTo->__anyAttribute = NULL;
soap->header->wsa__MessageID =(char *)soap_malloc(soap, sizeof(char) * INFO_LENGTH);
strcpy(soap->header->wsa__MessageID,_HwId+4);
}
soap->header->wsa__From = 0;
soap->header->wsa__ReplyTo = 0;
soap->header->wsa__FaultTo = 0;
soap->header->wsdd__AppSequence = 0;
soap->header->wsa__To = (char*)soap_malloc(soap, 128);
strcpy( soap->header->wsa__To , "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous");
soap->header->wsa__Action = (char*)soap_malloc(soap, 128);
strcpy(soap->header->wsa__Action , "http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches");
/* send over current socket as HTTP OK response: */
soap_send___wsdd__ProbeMatches(soap, "http://", NULL, &ProbeMatches);
return SOAP_OK;
}
SOAP_FMAC5 int SOAP_FMAC6 __wsdd__ProbeMatches(struct soap*, struct wsdd__ProbeMatchesType *wsdd__ProbeMatches)
{
return -1;
}
SOAP_FMAC5 int SOAP_FMAC6 __wsdd__Resolve(struct soap*, struct wsdd__ResolveType *wsdd__Resolve)
{
return -1;
}
SOAP_FMAC5 int SOAP_FMAC6 __wsdd__ResolveMatches(struct soap*, struct wsdd__ResolveMatchesType *wsdd__ResolveMatches)
{
return -1;
}
SOAP_FMAC5 int SOAP_FMAC6 __ns1__Hello(struct soap*, struct wsdd__HelloType tdn__Hello, struct wsdd__ResolveType &tdn__HelloResponse)
{
return -1;
}
SOAP_FMAC5 int SOAP_FMAC6 __ns1__Bye(struct soap*, struct wsdd__ByeType tdn__Bye, struct wsdd__ResolveType &tdn__ByeResponse)
{
return -1;
}
SOAP_FMAC5 int SOAP_FMAC6 __ns2__Probe(struct soap*, struct wsdd__ProbeType tdn__Probe, struct wsdd__ProbeMatchesType &tdn__ProbeResponse)
{
return -1;
}
5. 修改“WSDDiscoveryC.cpp”
6. 找到gsoap/stdsoap2.cpp,修改
1) gsoap源代码有一个小bug,暂时屏蔽
2) 由于每一个ONVIF serveice "namespace"可能不同,没有采用全局“namespace“
7. 生成envC.cpp,原因可参考gsoap帮助文档“soapdoc2.html” 19.35部分
1) “env.h",将下面内容保存为"env.h"
#import "header.h" // optional user-defined headers
#import "fault.h" // optional user-defined fault details
2) "header.h" ,将下面内容保存为"header.h"
struct wsa__Relationship
{
public:
char *__item;
char *RelationshipType; /* optional attribute of type xsd:QName */
char *__anyAttribute; /* optional attribute of type xsd:anyType */
};
typedef struct wsa__Relationship wsa__Relationship;
struct wsa__ReferencePropertiesType
{
public:
int __size; /* sequence of elements <-any> */
char **__any;
};
typedef struct wsa__ReferencePropertiesType wsa__ReferencePropertiesType;
struct wsa__ReferenceParametersType
{
public:
int __size; /* sequence of elements <-any> */
char **__any;
};
typedef struct wsa__ReferenceParametersType wsa__ReferenceParametersType;
struct wsa__ServiceNameType
{
public:
char *__item;
char *PortName; /* optional attribute of type xsd:string */
char *__anyAttribute; /* optional attribute of type xsd:anyType */
};
typedef struct wsa__ServiceNameType wsa__ServiceNameType;
struct wsa__EndpointReferenceType
{
public:
char *Address; /* required element of type xsd:string */
struct wsa__ReferencePropertiesType *ReferenceProperties; /* optional element of type wsa:ReferencePropertiesType */
struct wsa__ReferenceParametersType *ReferenceParameters; /* optional element of type wsa:ReferenceParametersType */
char **PortType; /* optional element of type xsd:QName */
struct wsa__ServiceNameType *ServiceName; /* optional element of type wsa:ServiceNameType */
int __size; /* sequence of elements <-any> */
char **__any;
char *__anyAttribute; /* optional attribute of type xsd:anyType */
};
typedef struct wsa__EndpointReferenceType wsa__EndpointReferenceType;
struct wsdd__AppSequenceType
{
public:
unsigned int InstanceId; /* required attribute of type xsd:unsignedInt */
char *SequenceId; /* optional attribute of type xsd:string */
unsigned int MessageNumber; /* required attribute of type xsd:unsignedInt */
};
typedef struct wsdd__AppSequenceType wsdd__AppSequenceType;
struct SOAP_ENV__Header
{
public:
char *wsa__MessageID; /* optional element of type wsa:MessageID */
struct wsa__Relationship *wsa__RelatesTo; /* optional element of type wsa:RelatesTo */
struct wsa__EndpointReferenceType *wsa__From; /* optional element of type wsa:From */
struct wsa__EndpointReferenceType *wsa__ReplyTo; /* mustUnderstand */
struct wsa__EndpointReferenceType *wsa__FaultTo; /* mustUnderstand */
char *wsa__To; /* mustUnderstand */
char *wsa__Action; /* mustUnderstand */
struct wsdd__AppSequenceType *wsdd__AppSequence; /* optional element of type wsdd:AppSequenceType */
};
3) fault.h,定义SOAP Fault,目前可以为空文件
4)将env.h , fault.h header.h 放置于"gsoap/bin/win32" ,执行:
soapcpp2 -penv env.h
将上面生成的文件“envC.cpp”,“WSDDiscoveryC.cpp”等文件组成
ws-discovery工程:
实例代码中“ONVIF-Services\WS-Discovery-service”