Onvif协议客户端开发(4)--Onvif客户端设备搜索

Onvif设备客户端搜索功能

实现原理:
在Onvif协议中规定,客户端以多播的形式往多播组发送一个Probe(探测:soap_send___wsdd__Probe函数)的消息去搜索目标设备,在该探测消息中包含了客户端中规定的搜寻条件;而服务端则在指定的端口监测是否有广播消息请求,并对比对应搜寻的条件,如果符合则回复该条广播消息,回复的消息内容中即包含了服务端的IP和服务端Onvif的端口。
客户端发送完探测消息之后则进入下一步循环的被动接收服务端返回的广播响应消息(soap_recv___wsdd__ProbeMatches接收函数),如果有消息返回则获取到Onvif的设备信息。

// 宏值定义
const char *SOAP_ENDPOINT = "soap.udp://239.255.255.250:3702"; // 组播IP:239.255.255.250,Onvif服务端监听的端口为3702
const char *WAS_TO = "urn:schemas-xmlsoap-org:ws:2005:04:discovery";
const char *WAS_ACTIONS = "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";
const char *SOAP_ITEM = "";                                                    // 寻找的设备范围
const char *SOAP_TYPES = "dn:NetworkVideoTransmitter";                            // 寻找的设备类型

// 初始化变量信息
wsdd__ProbeType resProbeType;			// probe请求的结构体
struct __wsdd__ProbeMatches resProbe;   // probe响应的结构体
wsdd__ScopesType sScope;
struct SOAP_ENV__Header *header;
struct soap *stSoapNew = soap_new();
soap_set_namespaces(stSoapNew, namespaces);               // 设置soap的namespaces
stSoapNew->recv_timeout = 10;                                           // 设置超时(超过指定时间没有数据就退出)
stSoapNew->send_timeout = 10;
stSoapNew->connect_timeout = 10;
soap_set_mode(stSoapNew, SOAP_C_UTFSTRING);		// 设置编码格式为UTF-8

// 初始化头数据
struct SOAP_ENV__Header *header = soap_new_SOAP_ENV__Header(stSoapNew ,1);
soap_default_SOAP_ENV__Header(stSoapNew , header);
header->wsa__MessageID = (char*)soap_wsa_rand_uuid(stSoapNew );
header->wsa__To = (char*)onvifSoapMalloc(stSoapNew , strlen(WAS_TO) + 1);
header->wsa__Action = (char*)onvifSoapMalloc(stSoapNew , strlen(WAS_ACTIONS) + 1);
strcpy(header->wsa__To, WAS_TO);
strcpy(header->wsa__Action, WAS_ACTIONS);
stSoapNew ->header = header;

// 初始化Probe的结构体数据
struct wsdd__ScopesType *scope = NULL;                                      // 用于描述查找哪类的Web服务
scope = soap_new_wsdd__ScopesType(stSoapNew, 1);
soap_default_wsdd__ScopesType(stSoapNew, scope);                                 // 设置寻找设备的范围
scope->__item = (char*)onvifSoapMalloc(stSoapNew, strlen(SOAP_ITEM) + 1);
strcpy(scope->__item, SOAP_ITEM);
memset(resProbeType, 0x00, sizeof(struct wsdd__ProbeType));
soap_default_wsdd__ProbeType(stSoapNew, probe);
resProbeType->Scopes = scope;
resProbeType->Types = (char*)onvifSoapMalloc(soap, strlen(SOAP_TYPES) + 1);     // 设置寻找设备的类型
strcpy(resProbeType->Types, SOAP_TYPES);

// 开始搜索Onvif设备
int nRet = soap_send___wsdd__Probe(stSoapNew, SOAP_ENDPOINT, NULL, &resProbeType);
	while (SOAP_OK == nRet)
	{
		memset(&resProbe, 0x00, sizeof(resProbe));
		nRet = soap_recv___wsdd__ProbeMatches(stSoapNew, &resProbe);// 接受服务端返回的信息
		if (SOAP_OK == nRet || SOAP_OK == stSoapNew->error)
		{
			for (int i=0;i__sizeProbeMatch;i++)
			{
				char sDeviceIp[32] = {0};
				char sDevicePort[12]  = {0};
				if (2 == sscanf((respond.wsdd__ProbeMatches->ProbeMatch + i)->XAddrs, "http://%31[^:]:%31[^/]", sDeviceIp, sDevicePort))
				{
					printf("Onvif Ip is %s, Port is %d\n",sDeviceIp,atoi(sDevicePort));
				}
				else if (1 == sscanf((respond.wsdd__ProbeMatches->ProbeMatch + i)->XAddrs, "http://%31[^/]", deviceInfo.sDeviceIp))
				{
					printf("Onvif Ip is %s, Port is %d\n",sDeviceIp,80);
				}
				else
				{
					continue;
				}
			}
		}
	}

你可能感兴趣的:(Onvif协议)