Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4263600
  • 博文数量: 776
  • 博客积分: 13014
  • 博客等级: 上将
  • 技术积分: 10391
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-22 17:00
文章分类

全部博文(776)

文章存档

2015年(55)

2014年(43)

2013年(147)

2012年(20)

2011年(82)

2010年(429)

分类: LINUX

2013-07-11 13:51:58

 

onvif实现功能和经验

 

1) 设备匹配probe消息

SOAP_FMAC5 int SOAP_FMAC6 soap_serve___dndl__Probe(struct soap *soap)

{    

….

soap_put_d__ProbeMatchesType(soap, &dn__ProbeResponse, "dn:ProbeResponse", NULL) 改成soap_put_d__ProbeMatchesType(soap, &dn__ProbeResponse, "d:ProbeMatches", NULL)

….

}

2) analytics.wsdl ptz.wsdl devicemgmt.wsdl media.wsdl event.wsdl 生成头文件,在头文件中要加#import "import/wsse.h" ,为了实现安全接口

 

3) 安全验证用户

SOAP_FMAC3 int SOAP_FMAC4 soap_out_SOAP_ENV__Header(struct soap *soap, const char *tag, int id, const struct SOAP_ENV__Header *a, const char *type)

{

….

soap->mustUnderstand = 1;

       if (soap_out_PointerTo_wsse__Security(soap, "wsse:Security", -1, &a->wsse__Security, ""))

              return soap->error;

改为soap->mustUnderstand = 0;

       if (soap_out_PointerTo_wsse__Security(soap, "wsse:Security", -1, &a->wsse__Security, ""))

              return soap->error;

….

}

 

4) 生成.c文件

D:\onvif>soapcpp2 -2 -c -x -L -pws -I D:\gsoap-2.8\gsoap;d:\gsoap-2.8/gsoap/import/ ws.h

 

其中-2参数是选择onvif 1.2 版本, 如果选择-1消息通知就无法被onvif测试工具识别

5) 生成.c后缀名的文件全部改成.cpp文件

6) onvif要生成客户和服务端, 客户端主要是用来发送hello消息和消息通知接口

7) 生成头文件

D:\onvif>wsdl2h.exe c -o ws.h -t typemap.dat -s analytics.wsdl ptz.wsdl devicemgmt.wsdl media.wsdl event.wsdl remotediscovery.wsdl imaging.wsdl

要在ws.h文件中增加 #import "import/wsse.h" 这表明是安全接口

8) soapcpp2生成数个.nsmp命名空间文件,只需要用其中一个就可以(我们使用的EventBinding.nsmap)

9) 开发人员只需关注wsClient.c, wsServer.c这两个文件,可对他进行修改

10) 通过wsdl2h.exe c -o ws.h -t typemap.dat -s analytics.wsdl ptz.wsdl devicemgmt.wsdl media.wsdl event.wsdl remotediscovery.wsdl imaging.wsdl 会报错误,不影响开发.

 

 11) 设备发现的soap初试化必为 下列代码

   
soap_init1(&m_soap_entry, SOAP_IO_UDP | SOAP_XML_IGNORENS);

    struct ip_mreqn imreq;

    imreq.imr_multiaddr.s_addr =inet_addr(MULTI_GROUPID);

    imreq.imr_address.s_addr = htonl(INADDR_ANY);

    imreq.imr_ifindex= 2;

 

    m_soap_entry.version = 2;

    m_soap_entry.send_timeout = 3; // 1s timeout

    m_soap_entry.recv_timeout = 3; // 1s timeout

 

    if (!soap_valid_socket(soap_bind(&m_soap_entry, NULL, 3702, 100)))

    {

        DEBUG_OUTPUT4("CDiscovery::Init soap_valid_socket error");

    }

    DEBUG_OUTPUT4("CDiscovery::Init soap_valid_socket success");

 

    if (setsockopt(m_soap_entry.master, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imreq, sizeof(imreq))<0)

    {

        DEBUG_OUTPUT4("CDiscovery::Init setsockopt IP_ADD_MEMBERSHIP Error");

}

 

12) hello 消息发送必须为

        struct soap *tsoap;

        tsoap = soap_copy(&m_soap_entry);

        Hello(tsoap, endpointReference);

if (soap_connect(soap, soap_endpoint, soap_action)

        || soap_envelope_begin_out(soap)

        || soap_putheader(soap)

        || soap_body_begin_out(soap)

        || soap_put___dnrd__Hello(soap, &soap_tmp___dnrd__Hello, "-dnrd:Hello", NULL)

        || soap_body_end_out(soap)

        || soap_envelope_end_out(soap)

        || soap_end_send(soap))

              return soap_closesock(soap);

改为

   if (soap_connect(soap, NULL, soap_action))

        {

            return soap_closesock(soap);

        }                  

        soap_set_endpoint(soap, soap_endpoint);

        soap->error = SOAP_OK;

        struct sockaddr_in peer;

        peer.sin_family=AF_INET;

        peer.sin_port=htons(soap->port);

        peer.sin_addr.s_addr=inet_addr(soap->host);

        memcpy(&soap->peer, &peer, sizeof(sockaddr_in));

        soap->peerlen = sizeof(peer);

 

        if(soap_envelope_begin_out(soap)

                || soap_putheader(soap)

                || soap_body_begin_out(soap)

                || soap_put___dnrd__Hello(soap, &soap_tmp___dnrd__Hello, "-dnrd:Hello", NULL)

                || soap_body_end_out(soap)

                || soap_envelope_end_out(soap)

                || soap_end_send(soap))

            return soap_closesock(soap);

 

13) 开发人员要实现服务端所有接口,下面是部分接口(请参考wsClient.cpp 文件

 

SOAP_FMAC5 int SOAP_FMAC6 __dndl__Probe(struct soap*, struct d__ProbeType *dn__Probe, struct d__ProbeMatchesType *dn__ProbeResponse);

 

SOAP_FMAC5 int SOAP_FMAC6 __dnrd__Hello(struct soap*, struct d__HelloType *dn__Hello, struct d__ResolveType *dn__HelloResponse);

 

SOAP_FMAC5 int SOAP_FMAC6 __dnrd__Bye(struct soap*, struct d__ByeType *dn__Bye, struct d__ResolveType *dn__ByeResponse);

  

14) 安全用户名和密码是采用openssl库和gsoap的自带的控件, 采用下列接口

soap_wsse_verify_Password

soap_wsse_verify_Timestamp

soap_wsse_get_Username

 

15) openssl 编译

tar zxvf openssl-0.9.8.tar.gz

cd openssl-0.9.8

./config no-asm --prefix=/opt/openssl os/compiler: /ToolChain/bin/

arm-none-linux-gnueabi-g++

make

make install

之后进入到/opt/openssl 拷贝头文件和库

 

16) 通过80端口发送流


首先要判断消息是onvif消息还是请求流消息, 通过MSG_PEEK来区分

如果是onvif消息就走onvif信令,否则走播流通道

 

 Onvif已经实现功能

设备发送hello消息

设备接收hello消息

设备发现匹配相应

获取设备信息

设置系统时间

获取系统时间

软件出厂默认值恢复

系统重新启动

获取wsdlurl

获取所有能力集

获取设备能力集

获取事件能力集

获取图象能力集

获取媒体能力集

获取主机名字

设置主机名

获取网络接口信息

设置网络接口信息

获取网络协议

获取网关

设置网关 

阅读(23682) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

nananxiao2014-01-13 22:41:01

hello消息的修改不明白,不是UDP报文吗?为什么改成这个样子?另外想问下,我现在hello包可以发出,但是test工具测试的时候总是报收包失败,我抓包看过了3702端口的组播包发出来了,请问楼主有遇到这种情况吗?谢谢