Onvif开发之客户端搜索篇

关于ONVIF的广播,有客户端搜索和服务端发现的区别:客户端向固定的网段和固定的端口发送广播消息,服务端在对应的端口回复广播请求消息
本文首先介绍客户端如何进行广播的已经对广播回复的信息的基本处理。

客户端这里处理相对服务端比较复杂一点,需要注意几个地方:

1 广播的ip和端口号(注意这个端口号和通信的端口是不一样的,通信端口号可以自己随意定一个,但是这个广播的是ONVIF协议定好公用的)

  ip:239:255:255:250   port:3702

2 MessageID ,此ID每次都需要不同,不然每次只有第一次能搜索到设备,第二次就不行了!一般情况下都是区uuid的随机值的,但是我在开发的过程是去的一个随机值加上自己设备的mac地址组合的

3 soap_send___wsdd__Probe函数,发送广播信息,通过它来判断是否发送成功,确认是否继续下一步操作进行接收消息

4 soap_recv___wsdd__ProbeMatches函数,此函数是通过广播后,设备通过onvif协议回复了设备的一些基本信息,客户端通过循 环调用此函数来接多个设备回复的各个设备的一些基本信息包括设备ip以及通信的prot

知道了这几个基本的注意点和前篇介绍的代码生成框架,接下来就是敲代码了。该main函数登场了

[cpp] view plain copy

 

 

  1. <span style="font-size:14px;">/* 
  2.  * ===================================================================================== 
  3.  * 
  4.  *       Filename:  main.c 
  5.  *    Description:  简单例程测试:客户端通过ONVIF协议搜索前端设备, 
  6.  *        Created:  2013年12月26日 12时17分48秒 
  7.  *       Compiler:  gcc 
  8.  *         Author:  max_min_,  
  9.  * 
  10.  * ===================================================================================== 
  11.  */  
  12. #include "wsdd.h"  
  13. #include <stdio.h>  
  14.   
  15. static struct soap* ONVIF_Initsoap(struct SOAP_ENV__Header *header, const char *was_To, const char *was_Action, int timeout)  
  16. {  
  17.     struct soap *soap = NULL;   
  18.     unsigned char macaddr[6];  
  19.     char _HwId[1024];  
  20.     unsigned int Flagrand;  
  21.     soap = soap_new();  
  22.     if(soap == NULL)  
  23.     {     
  24.         printf("[%d]soap = NULL\n", __LINE__);  
  25.         return NULL;  
  26.     }     
  27.      soap_set_namespaces( soap, namespaces);  
  28.     //超过5秒钟没有数据就退出  
  29.     if (timeout > 0)  
  30.     {     
  31.         soap->recv_timeout = timeout;  
  32.         soap->send_timeout = timeout;  
  33.         soap->connect_timeout = timeout;  
  34.     }     
  35.     else  
  36.     {     
  37.         //如果外部接口没有设备默认超时时间的话,我这里给了一个默认值10s  
  38.         soap->recv_timeout    = 10;   
  39.         soap->send_timeout    = 10;   
  40.         soap->connect_timeout = 10;   
  41.     }     
  42.    soap_default_SOAP_ENV__Header(soap, header);  
  43.   
  44.     // 为了保证每次搜索的时候MessageID都是不相同的!因为简单,直接取了随机值  
  45.     srand((int)time(0));  
  46.     Flagrand = rand()%9000 + 1000; //保证四位整数  
  47.     macaddr[0] = 0x1; macaddr[1] = 0x2; macaddr[2] = 0x3; macaddr[3] = 0x4; macaddr[4] = 0x5; macaddr[5] = 0x6;  
  48.     sprintf(_HwId,"urn:uuid:%ud68a-1dd2-11b2-a105-%02X%02X%02X%02X%02X%02X",  
  49.             Flagrand, macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);  
  50.     header->wsa__MessageID =(char *)malloc( 100);  
  51.     memset(header->wsa__MessageID, 0, 100);  
  52.     strncpy(header->wsa__MessageID, _HwId, strlen(_HwId));  
  53.   
  54.     if (was_Action != NULL)  
  55.     {  
  56.         header->wsa__Action =(char *)malloc(1024);  
  57.         memset(header->wsa__Action, '\0', 1024);  
  58.         strncpy(header->wsa__Action, was_Action, 1024);//"http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";  
  59.     }  
  60.     if (was_To != NULL)  
  61.     {  
  62.         header->wsa__To =(char *)malloc(1024);  
  63.         memset(header->wsa__To, '\0', 1024);  
  64.         strncpy(header->wsa__To,  was_To, 1024);//"urn:schemas-xmlsoap-org:ws:2005:04:discovery";     
  65.     }  
  66.     soap->header = header;  
  67.     return soap;  
  68. }  
  69. int ONVIF_ClientDiscovery( )  
  70. {  
  71.     int HasDev = 0;  
  72.     int retval = SOAP_OK;  
  73.     wsdd__ProbeType req;  
  74.     struct __wsdd__ProbeMatches resp;  
  75.     wsdd__ScopesType sScope;  
  76.     struct SOAP_ENV__Header header;  
  77.     struct soap* soap;  
  78.   
  79.   
  80.     const char *was_To = "urn:schemas-xmlsoap-org:ws:2005:04:discovery";  
  81.     const char *was_Action = "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";  
  82.     //这个就是传递过去的组播的ip地址和对应的端口发送广播信息      
  83.     const char *soap_endpoint = "soap.udp://239.255.255.250:3702/";  
  84.   
  85.     //这个接口填充一些信息并new返回一个soap对象,本来可以不用额外接口,  
  86.     // 但是后期会作其他操作,此部分剔除出来后面的操作就相对简单了,只是调用接口就好  
  87.     soap = ONVIF_Initsoap(&header, was_To, was_Action, 5);  
  88.   
  89.     soap_default_SOAP_ENV__Header(soap, &header);  
  90.     soap->header = &header;  
  91.   
  92.     soap_default_wsdd__ScopesType(soap, &sScope);  
  93.     sScope.__item = "";  
  94.     soap_default_wsdd__ProbeType(soap, &req);  
  95.     req.Scopes = &sScope;  
  96.     req.Types = ""; //"dn:NetworkVideoTransmitter";  
  97.   
  98.     retval = soap_send___wsdd__Probe(soap, soap_endpoint, NULL, &req);  
  99.     //发送组播消息成功后,开始循环接收各位设备发送过来的消息  
  100.     while (retval == SOAP_OK)  
  101.     {  
  102.         retval = soap_recv___wsdd__ProbeMatches(soap, &resp);  
  103.         if (retval == SOAP_OK)  
  104.         {  
  105.             if (soap->error)  
  106.             {  
  107.                 printf("[%d]: recv error:%d,%s,%s\n", __LINE__, soap->error, *soap_faultcode(soap), *soap_faultstring(soap));  
  108.                 retval = soap->error;  
  109.             }  
  110.             else //成功接收某一个设备的消息  
  111.             {  
  112.                 HasDev ++;  
  113.                 if (resp.wsdd__ProbeMatches->ProbeMatch != NULL && resp.wsdd__ProbeMatches->ProbeMatch->XAddrs != NULL)  
  114.                 {  
  115.                     printf(" ################  recv  %d devices info #### \n", HasDev );  
  116.                     printf("Target Service Address  : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->XAddrs);  
  117.                     printf("Target EP Address       : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->wsa__EndpointReference.Address);  
  118.                     printf("Target Type             : %s\r\n", resp.wsdd__ProbeMatches->ProbeMatch->Types);  
  119.                     printf("Target Metadata Version : %d\r\n", resp.wsdd__ProbeMatches->ProbeMatch->MetadataVersion);  
  120.                     sleep(1);  
  121.                 }  
  122.             }  
  123.         }  
  124.         else if (soap->error)  
  125.         {  
  126.             if (HasDev == 0)  
  127.             {  
  128.                 printf("[%s][%d] Thers Device discovery or soap error: %d, %s, %s \n", __func__, __LINE__, soap->error, *soap_faultcode(soap), *soap_faultstrin  
  129.                 retval = soap->error;  
  130.             }  
  131.             else  
  132.             {  
  133.                 printf(" [%s]-[%d] Search end! It has Searched %d devices! \n", __func__, __LINE__, HasDev);  
  134.                 retval = 0;  
  135.             }  
  136.             break;  
  137.         }  
  138.     }  
  139.   
  140.     soap_destroy(soap);  
  141.     soap_end(soap);  
  142.     soap_free(soap);  
  143.   
  144.     return retval;  
  145. }  
  146. int main(void )  
  147. {  
  148.     //组播接口   
  149.     if (ONVIF_ClientDiscovery() != 0 )  
  150.     {  
  151.         printf("discovery failed!\n");  
  152.         return -1;  
  153.     }  
  154.   
  155.     return 0;  
  156. }  
  157. </span>  

运行测试结果如下图

              

 

可以看到注意信息就是http://172.18.13.127:9000/onvif/device_service这句了!设备的IP地址以及通信端口都有了,第三个没有端口,也就是使用默认的端口80了,海康和大华的貌似都是用80端口
到这里差不多客户端的搜索就完成了,剩下只是把搜索到的设备信息解析出来,然后保存起来!提供给客户端使用了,我在实际开发的过程中是通过调用外层接口传递一个回调函数指针进去,然后匹配信息出来,给客户端!

搜索使用的源码下载地址:onvif客户端搜索

时间: 2024-10-29 02:17:44

Onvif开发之客户端搜索篇的相关文章

Onvif开发之客户端鉴权获取参数篇

前面一篇已经介绍了客户端如何发些设备,下面这篇简单介绍下在发现设备后,如何通过ONVIF协议来获取设备的相关参数 ONVIF中不管是客户端还是设备端,最先实现的接口都是关于能力的那个接口,在客户端实现的函数名也就是[soap_call___tds__GetServiceCapabilities]通过获取的接口才知道设备具有那些能力,能够进行那些操作,服务端最基本的也需要实现这接口,让客户端知道设备支持那些基本操作.但是当设备端作了加密处理的话,即使你实现了这些接口,也不能正常获取到参数的,所以需

Onvif开发之基础介绍篇

什么是Onvif协议,谁开启了Onvif时代?                                                                 ONVIF:原意为 开放型网络视频接口论坛,即 Open Network Video Interface Forum ,是安讯士.博世.索尼等三家公司在2008年共同成立的一个国际性 开放型 网络视频产品 标准网络接口 的开发论坛,后来由这个技术开发论坛共同制定的开放性行业标准,就用该论坛的大写字母命名,即ONVIF 网络

ONVIF客户端搜索设备获取rtsp地址开发笔记(精华篇)

原文  http://blog.csdn.net/gubenpeiyuan/article/details/25618177   概要: 目前ONVIF协议家族设备已占据数字监控行业半壁江山以上,亲,作为开发者的你还在犹豫是否了解下吗?本文介绍了ONVIF客户端从设备搜索,鉴权,能力获取,媒体信息获取,URI地址获取的整套流程.文章只讲述了比较重要或其他博文没有讲述的开发点,详细可以参考文末参考文章.最后,能获得rtsp地址之后,然后去做其他功能比如录像,ptz这些就非常得心应手了.本文出自CS

onvif开发之设备发现功能的实现--转

忙了一个多月,onvif总算告一段落了.这几个星期忙着其他的项目,也没有好好整理一下onvif的东西.接下来得好好整理一下自己的项目思路和项目经验,同时将自己的一些心得写出来,希望对人有所帮助.         相信大多数兄弟和我一样,onvif开发,最开始做的就是发现功能.这两天登录onvif的官网看才发现,onvif版本在八月份有更新,已经更新到V2.4了,于是下载最新的版本来进行.代码的生成可以详见我的前一篇文章.V2.4版本新增了一个wsdl文件,现在用于生成源码的文件一共有18个.为了

FlexPaper二次开发问题及搜索高亮显示

原文:FlexPaper二次开发问题及搜索高亮显示 最近有个需求,做一个IT知识库,类似于文库,说到文库肯定会用到在线浏览文档了,所有在网上翻阅了一下类似豆丁的在线浏览器插件的资料,将其进行了二次开发,在这跟需要用到的朋友分享一下,下面部分内容用到有些前辈的博客内容,首次写博,写的不好之处请见谅...高手勿喷,O(∩_∩)O谢谢 1.前期准备工作 1.首先二次开发,当然前提是需要一份FlexPaper的源码.源码下载地址: http://files.cnblogs.com/yimiao/Flex

【Windows10&amp;nbsp;IoT开发系列】配置篇

原文:[Windows10 IoT开发系列]配置篇 Windows10 For IoT是Windows 10家族的一个新星,其针对不同平台拥有不同的版本.而其最重要的一个版本是运行在Raspberry Pi.MinnowBoard和Galileo平台上的核心版.本文重点针对Raspberry Pi平台的Windwos10 IoT配置做介绍. Windows 10 IoT Editions ​一:设置你的电脑. 注:​开发Windows10 IoT的电脑需要Visual Studio 2015.

Android多功能时钟开发案例(实战篇)_Android

上一篇为大家介绍的是Android多功能时钟开发基础内容,大家可以回顾一下,Android多功能时钟开发案例(基础篇) 接下来进入实战,快点来学习吧. 一.时钟在布局文件中我们看到,界面上只有一个TextView,这个TextView的作用就是显示一个系统的当前时间,同时这个时间还是一秒一秒跳的,要实现一秒一秒的跳就需要我们每隔一秒就要刷新一下,同时我们这里还考虑了切换到另一个Tab的时候,这个时间就不跳动了,这样就会减少这个对系统的占用,考虑到了这点我们在这里用到了Handler,通过hand

在android开发中如何搜索下载国外精美的图标资源

问题描述 在android开发中如何搜索下载国外精美的图标资源 在安卓开发中,图标是我们经常和必须用到的东西,但是自己设计图标又不在行,只能在网上搜索,但是国内很多网站的图标资源是收费的,如何找到国外的图标资源站,谢谢! 解决方案 https://www.iconfinder.com/

用WinInet开发Internet客户端应用指南(一)

一.概述 一个Internet客户端程序的目的是通过Internet协议如:HTTP.FTP等来存取网络数据源(服务器)的信息.客户端程序可以访问服务器获得象天气预报,股票价格.重要新闻数据,甚至是与服务器交换信息.Internet客户端程序可以通过外部网络(Internet)或内部网络(一般为Intranet)访问服务器. 为了开发Internet客户端程序.MFC类库提供了专门的 Win32 Internet 扩展接口,也就是WinInet.MFC将WinInet封装在一个标准的.易于使用的