基于Gsoap 集成多个ONVIF服务(ws-discovery)

说明:

有一段时间被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”




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值