Linux下onvif的编译

来源:互联网 发布:dmg文件怎么安装 mac 编辑:程序博客网 时间:2024/05/22 08:18

最先要申明的一点:onvif开发并不需要编译安装gsoap,gsoap只是用来获取onvif源代码的工具!

一、准备"onvif"源码

需要gsoap来帮助我们将.wdsl生成为.h,最后再生成.c文件。因为wdsl互相之间有相关性,离线安装会出现更多的麻烦(修改更多的配置信息),所以整个过程都在联网状态

完成,虽然比较耗时,但是强烈建议

gsoap项目地址(需要下载)

http://www.cs.fsu.edu/~engelen/soap.html

onvif项目的wdsl地址(不需要下载)

http://www.onvif.org/Documents/Specifications.aspx中的ONVIF WSDL and XML Schemas Specifications

二、生成源文件

1、准备生成环境(2.8.10以上版本应该不需要这个步骤,2.8.17r并不需要修改typemap.dat!)

解压gsoap到任意文件夹,修改gsoap目录下的typemap.dat文件,gsoap官网对onvif编译的说明如下:

How do I use gSOAP for the ONVIF specifications?

Use gSOAP 2.8.10 and up. In the typemap.dat file used by wsdl2h, add:

[plain] view plain copy
  1. #   ONVIF recommended prefixes  
  2. tds = "http://www.onvif.org/ver10/device/wsdl"  
  3. tev = "http://www.onvif.org/ver10/events/wsdl"  
  4. tls = "http://www.onvif.org/ver10/display/wsdl"  
  5. tmd = "http://www.onvif.org/ver10/deviceIO/wsdl"  
  6. timg    = "http://www.onvif.org/ver20/imaging/wsdl"  
  7. trt = "http://www.onvif.org/ver10/media/wsdl"  
  8. tptz    = "http://www.onvif.org/ver20/ptz/wsdl"  
  9. trv = "http://www.onvif.org/ver10/receiver/wsdl"  
  10. trc = "http://www.onvif.org/ver10/recording/wsdl"  
  11. tse = "http://www.onvif.org/ver10/search/wsdl"  
  12. trp = "http://www.onvif.org/ver10/replay/wsdl"  
  13. tan = "http://www.onvif.org/ver20/analytics/wsdl"  
  14. tad = "http://www.onvif.org/ver10/analyticsdevice/wsdl"  
  15. tdn = "http://www.onvif.org/ver10/network/wsdl"  
  16. tt  = "http://www.onvif.org/ver10/schema"  
  17. #   OASIS recommended prefixes  
  18. wsnt    = "http://docs.oasis-open.org/wsn/b-2"  
  19. wsntw   = "http://docs.oasis-open.org/wsn/bw-2"  
  20. wsrfbf  = "http://docs.oasis-open.org/wsrf/bf-2"  
  21. wsrfr   = "http://docs.oasis-open.org/wsrf/r-2"  
  22. wsrfrw  = "http://docs.oasis-open.org/wsrf/rw-2"  
  23. wstop   = "http://docs.oasis-open.org/wsn/t-1"  
  24. #   WS-Discovery 1.0 remapping  
  25. wsdd10__HelloType       = | wsdd__HelloType  
  26. wsdd10__ByeType         = | wsdd__ByeType  
  27. wsdd10__ProbeType       = | wsdd__ProbeType  
  28. wsdd10__ProbeMatchesType    = | wsdd__ProbeMatchesType  
  29. wsdd10__ProbeMatchType      = | wsdd__ProbeMatchType  
  30. wsdd10__ResolveType     = | wsdd__ResolveType  
  31. wsdd10__ResolveMatchesType  = | wsdd__ResolveMatchesType  
  32. wsdd10__ResolveMatchType    = | wsdd__ResolveMatchType  
  33. #   SOAP-ENV mapping  
  34. SOAP_ENV__Envelope  = struct SOAP_ENV__Envelope { struct SOAP_ENV__Header *SOAP_ENV__Header; _XML SOAP_ENV__Body; }; | struct SOAP_ENV__Envelope  
  35. SOAP_ENV__Header    = | struct SOAP_ENV__Header  
  36. SOAP_ENV__Fault     = | struct SOAP_ENV__Fault  
  37. SOAP_ENV__Detail    = | struct SOAP_ENV__Detail  
  38. SOAP_ENV__Code      = | struct SOAP_ENV__Code  
  39. SOAP_ENV__Subcode   = | struct SOAP_ENV__Subcode  
  40. SOAP_ENV__Reason    = | struct SOAP_ENV__Reason  

typemap.dat文件添加如上代码段,并复制到编译目录gsoap\bin\win32(win32对应windows,linux386对应linux,macosx对应macosx)。

2、生成.h文件

进入编译目录gsoap\bin\win32,这时目录下会有3个文件wsdl2h.exesoapcpp2.exe以及typemap.dat

运行命令行

[plain] view plain copy
  1. wsdl2h -P -x -c -s -t typemap.dat -o onvif.h <wsdl地址> <wsdl地址> ...  

其中<wsdl地址>为http://www.onvif.org/Documents/Specifications.aspx中的ONVIF WSDL and XML Schemas Specifications列表下各个wsdl文件网络位置,用空格分隔

<wsdl地址>举例

[plain] view plain copy
  1. http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl  
  2. http://www.onvif.org/onvif/ver10/events/wsdl/event.wsdl  
  3. http://www.onvif.org/onvif/ver10/display.wsdl  
  4. http://www.onvif.org/onvif/ver10/deviceio.wsdl  
  5. http://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdl  
  6. http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl  
  7. http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl  
  8. http://www.onvif.org/onvif/ver10/receiver.wsdl  
  9. http://www.onvif.org/onvif/ver10/recording.wsdl  
  10. http://www.onvif.org/onvif/ver10/search.wsdl  
  11. http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl  
  12. http://www.onvif.org/onvif/ver10/replay.wsdl  
  13. http://www.onvif.org/onvif/ver20/analytics/wsdl/analytics.wsdl  
  14. http://www.onvif.org/onvif/ver10/analyticsdevice.wsdl  
  15. http://www.onvif.org/ver10/actionengine.wsdl  
  16. http://www.onvif.org/ver10/pacs/accesscontrol.wsdl  
  17. http://www.onvif.org/ver10/pacs/doorcontrol.wsdl  
  18. http://www.onvif.org/ver10/advancedsecurity/wsdl/advancedsecurity.wsdl  
  19. http://www.onvif.org/onvif/ver10/schema/onvif.xsd  

等待完毕,会生成onvif.h文件在编译目录,大小在3~4m左右,失败的话大小为0k。

如果需要身份验证,修改生成的onvif.h,增加

[cpp] view plain copy
  1. #import "wsse.h"  

3、生成.c文件

进入编译目录gsoap\bin\win32,运行命令行

[plain] view plain copy
  1. soapcpp2 -c -x -L -I ../../import -I ../../../gsoap/ onvif.h  

使用gsoap版本gSOAP 2.8.17r stable (update) (20.7 MB)出现如下错误(这错误太低级了,完全没有宏保护)

wsa5.h(288): **ERROR**: remote method name clash: struct/class 'SOAP_ENV__Fault'

already declared at line 274

回到gsoap\import目录下修改wsa5.h,将重复申明的部分注释如下。

[cpp] view plain copy
  1. /*int SOAP_ENV__Fault 
  2. (       _QName           faultcode,     // SOAP 1.1 
  3.         char            *faultstring,       // SOAP 1.1 
  4.         char            *faultactor,        // SOAP 1.1 
  5.         struct SOAP_ENV__Detail *detail,        // SOAP 1.1 
  6.         struct SOAP_ENV__Code   *SOAP_ENV__Code,    // SOAP 1.2 
  7.         struct SOAP_ENV__Reason *SOAP_ENV__Reason,  // SOAP 1.2 
  8.         char            *SOAP_ENV__Node,    // SOAP 1.2 
  9.         char            *SOAP_ENV__Role,    // SOAP 1.2 
  10.         struct SOAP_ENV__Detail *SOAP_ENV__Detail,  // SOAP 1.2 
  11.     void 
  12. );*/  
重新运行上面的生成命令,生成成功。在目录下会生成很多文件,有用的文件如下:

soapC.c

soapClient.c

soapServer.c(与soapClient.c根据需要选择其一)

onvif.h

soapH.h

soapStub.h

wsdd.nsmap

除此之外,还需要gsoap-2.8\gsoap目录下的两个文件:

stdsoap2.c

stdsoap2.h

这些文件放在自己的代码目录下即可

四、onvif源码的使用

1、注释soapServer.c中SOAP_ENV__Fault部分代码

编译发生以下错误:

soapServer.c:259: undefined reference to `SOAP_ENV__Fault'

这里有两个解决办法,①如下注释soapServer.c中与这函数有关的代码,②自己实现这个函数。

[cpp] view plain copy
  1. SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap *soap)  
  2. {  
  3. soap_peek_element(soap);  
  4. /*if (!soap_match_tag(soap, soap->tag, "SOAP-ENV:Fault")) 
  5. return soap_serve_SOAP_ENV__Fault(soap);*/  
  6. if (!soap_match_tag(soap, soap->tag, "wsdd:Hello"))  
  7. return soap_serve___wsdd__Hello(soap);  
  8. if (!soap_match_tag(soap, soap->tag, "wsdd:Bye"))  
  9. return soap_serve___wsdd__Bye(soap);  
  10. if (!soap_match_tag(soap, soap->tag, "wsdd:Probe"))  
  11. return soap_serve___wsdd__Probe(soap);  
  12. if (!soap_match_tag(soap, soap->tag, "wsdd:ProbeMatches"))  
  13. return soap_serve___wsdd__ProbeMatches(soap);  
  14. if (!soap_match_tag(soap, soap->tag, "wsdd:Resolve"))  
  15. return soap_serve___wsdd__Resolve(soap);  
  16. if (!soap_match_tag(soap, soap->tag, "wsdd:ResolveMatches"))  
  17. return soap_serve___wsdd__ResolveMatches(soap);  
  18. return soap->error = SOAP_NO_METHOD;  
  19. }  

[cpp] view plain copy
  1. /*SOAP_FMAC5 int SOAP_FMAC6 soap_serve_SOAP_ENV__Fault(struct soap *soap) 
  2. {   struct SOAP_ENV__Fault soap_tmp_SOAP_ENV__Fault; 
  3.     soap_default_SOAP_ENV__Fault(soap, &soap_tmp_SOAP_ENV__Fault); 
  4.     if (!soap_get_SOAP_ENV__Fault(soap, &soap_tmp_SOAP_ENV__Fault, "SOAP-ENV:Fault", NULL)) 
  5.         return soap->error; 
  6.     if (soap_body_end_in(soap) 
  7.      || soap_envelope_end_in(soap) 
  8.      || soap_end_recv(soap)) 
  9.         return soap->error; 
  10.     soap->error = SOAP_ENV__Fault(soap, soap_tmp_SOAP_ENV__Fault.faultcode, soap_tmp_SOAP_ENV__Fault.faultstring, soap_tmp_SOAP_ENV__Fault.faultactor, soap_tmp_SOAP_ENV__Fault.detail, soap_tmp_SOAP_ENV__Fault.SOAP_ENV__Code, soap_tmp_SOAP_ENV__Fault.SOAP_ENV__Reason, soap_tmp_SOAP_ENV__Fault.SOAP_ENV__Node, soap_tmp_SOAP_ENV__Fault.SOAP_ENV__Role, soap_tmp_SOAP_ENV__Fault.SOAP_ENV__Detail); 
  11.     if (soap->error) 
  12.         return soap->error; 
  13.     return soap_closesock(soap); 
  14. }*/  

2、重定义soapH.h中soap_default_xsd_duration、soap_out_xsd__duration、soap_in_xsd__duration申明

编译发生很多类似以下的错误:
soapC.c:197: undefined reference to `soap_in_xsd__duration'

这里有两个解决办法,①如下修改soapH.h头文件,②项目包含gsoap/custom/duration.c文件(实现在此文件中)

[cpp] view plain copy
  1. //SOAP_FMAC1 void SOAP_FMAC2 soap_default_xsd__duration(struct soap*, LONG64 *);  
  2. #define soap_default_xsd__duration(soap, a) soap_default_unsignedLONG64(soap, (ULONG64 *)a)  
  3. //SOAP_FMAC1 int SOAP_FMAC2 soap_out_xsd__duration(struct soap*, const char*, int, const LONG64 *, const char*);  
  4. #define soap_out_xsd__duration(soap,a,b,c,d) soap_out_unsignedLONG64(soap, a, b, (ULONG64 *)c, d)  
  5. //SOAP_FMAC1 LONG64 * SOAP_FMAC2 soap_in_xsd__duration(struct soap*, const char*, LONG64 *, const char*);  
  6. #define soap_in_xsd__duration(soap, a, b, c) (LONG64*)soap_in_unsignedLONG64(soap,a,(ULONG64 *)b,c)  


3、实现功能函数

这时候编译我们的代码后会发生如下的错误(错误会有很多,做好思想准备,这里只列出一小部分)

[cpp] view plain copy
  1. /alex/discovery/soapServer.c:489: undefined reference to `__tds__GetServices'  
  2. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetServiceCapabilities':  
  3. /alex/discovery/soapServer.c:530: undefined reference to `__tds__GetServiceCapabilities'  
  4. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetDeviceInformation':  
  5. /alex/discovery/soapServer.c:571: undefined reference to `__tds__GetDeviceInformation'  
  6. /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetSystemDateAndTime':  
  7. /alex/discovery/soapServer.c:612: undefined reference to `__tds__SetSystemDateAndTime'  
  8. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetSystemDateAndTime':  
  9. /alex/discovery/soapServer.c:653: undefined reference to `__tds__GetSystemDateAndTime'  
  10. /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetSystemFactoryDefault':  
  11. /alex/discovery/soapServer.c:694: undefined reference to `__tds__SetSystemFactoryDefault'  
  12. /tmp/cc9R4RNL.o: In function `soap_serve___tds__UpgradeSystemFirmware':  
  13. /alex/discovery/soapServer.c:735: undefined reference to `__tds__UpgradeSystemFirmware'  
  14. /tmp/cc9R4RNL.o: In function `soap_serve___tds__SystemReboot':  
  15. /alex/discovery/soapServer.c:776: undefined reference to `__tds__SystemReboot'  
  16. /tmp/cc9R4RNL.o: In function `soap_serve___tds__RestoreSystem':  
  17. /alex/discovery/soapServer.c:817: undefined reference to `__tds__RestoreSystem'  
  18. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetSystemBackup':  
  19. /alex/discovery/soapServer.c:858: undefined reference to `__tds__GetSystemBackup'  
  20. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetSystemLog':  
  21. /alex/discovery/soapServer.c:899: undefined reference to `__tds__GetSystemLog'  
  22. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetSystemSupportInformation':  
  23. /alex/discovery/soapServer.c:940: undefined reference to `__tds__GetSystemSupportInformation'  
  24. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetScopes':  
  25. /alex/discovery/soapServer.c:981: undefined reference to `__tds__GetScopes'  
  26. /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetScopes':  
  27. /alex/discovery/soapServer.c:1022: undefined reference to `__tds__SetScopes'  
  28. /tmp/cc9R4RNL.o: In function `soap_serve___tds__AddScopes':  
  29. /alex/discovery/soapServer.c:1063: undefined reference to `__tds__AddScopes'  
  30. /tmp/cc9R4RNL.o: In function `soap_serve___tds__RemoveScopes':  
  31. /alex/discovery/soapServer.c:1104: undefined reference to `__tds__RemoveScopes'  
  32. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetDiscoveryMode':  
  33. /alex/discovery/soapServer.c:1145: undefined reference to `__tds__GetDiscoveryMode'  
  34. /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetDiscoveryMode':  
  35. /alex/discovery/soapServer.c:1186: undefined reference to `__tds__SetDiscoveryMode'  
  36. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetRemoteDiscoveryMode':  
  37. /alex/discovery/soapServer.c:1227: undefined reference to `__tds__GetRemoteDiscoveryMode'  
  38. /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetRemoteDiscoveryMode':  
  39. /alex/discovery/soapServer.c:1268: undefined reference to `__tds__SetRemoteDiscoveryMode'  
  40. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetDPAddresses':  
  41. /alex/discovery/soapServer.c:1309: undefined reference to `__tds__GetDPAddresses'  
  42. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetEndpointReference':  
  43. /alex/discovery/soapServer.c:1350: undefined reference to `__tds__GetEndpointReference'  
  44. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetRemoteUser':  
  45. /alex/discovery/soapServer.c:1391: undefined reference to `__tds__GetRemoteUser'  
  46. /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetRemoteUser':  
  47. /alex/discovery/soapServer.c:1432: undefined reference to `__tds__SetRemoteUser'  
  48. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetUsers':  
  49. /alex/discovery/soapServer.c:1473: undefined reference to `__tds__GetUsers'  
  50. /tmp/cc9R4RNL.o: In function `soap_serve___tds__CreateUsers':  
  51. /alex/discovery/soapServer.c:1514: undefined reference to `__tds__CreateUsers'  
  52. /tmp/cc9R4RNL.o: In function `soap_serve___tds__DeleteUsers':  
  53. /alex/discovery/soapServer.c:1555: undefined reference to `__tds__DeleteUsers'  
  54. /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetUser':  
  55. /alex/discovery/soapServer.c:1596: undefined reference to `__tds__SetUser'  
  56. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetWsdlUrl':  
  57. /alex/discovery/soapServer.c:1637: undefined reference to `__tds__GetWsdlUrl'  
  58. /tmp/cc9R4RNL.o: In function `soap_serve___tds__GetCapabilities':  
  59. /alex/discovery/soapServer.c:1678: undefined reference to `__tds__GetCapabilities'  
  60. /tmp/cc9R4RNL.o: In function `soap_serve___tds__SetDPAddresses':  
  61. /alex/discovery/soapServer.c:1719: undefined reference to `__tds__SetDPAddresses'  

这里便是我们会调用的功能函数,需要自己实现,每个函数都需要实现,但是对于我们不需要的功能函数,只做最简单的定义即可

[cpp] view plain copy
  1. int  __wsdd__ProbeMatches(struct soap* soap, struct wsdd__ProbeMatchesType *wsdd__ProbeMatches)  
  2. {  
  3.     fprintf(stderr,"__wsdd__ProbeMatches\n");  
  4. }  
  5. int  __wsdd__Resolve(struct soap* soap, struct wsdd__ResolveType *wsdd__Resolve)  
  6. {  
  7.     fprintf(stderr,"__wsdd__Resolve\n");  
  8. }  
  9. int  __wsdd__ResolveMatches(struct soap* soap, struct wsdd__ResolveMatchesType *wsdd__ResolveMatches)  
  10. {  
  11.     fprintf(stderr,"__wsdd__ResolveMatches\n");  
  12. }  
  13. int  __tdn__Hello(struct soap* soap, struct wsdd__HelloType tdn__Hello, struct wsdd__ResolveType *tdn__HelloResponse)  
  14. {  
  15.     fprintf(stderr,"__ns1__Hello\n");  
  16. }  
  17. int  __tdn__Bye(struct soap* soap, struct wsdd__ByeType tdn__Bye, struct wsdd__ResolveType *tdn__ByeResponse)  
  18. {  
  19.     fprintf(stderr,"__ns1__Bye\n");  
  20. }  
  21. int  __tdn__Probe(struct soap* soap, struct wsdd__ProbeType tdn__Probe, struct wsdd__ProbeMatchesType *tdn__ProbeResponse)  
  22. {  
  23.     fprintf(stderr,"__ns2__Probe\n");  
  24. }  


三、onvif开发手册

onvif开发手册

四、调试

1、打开onvif调试开关,以便让onvif打印一些可用的调试信息

在Makefile中添加调试宏定义如

[plain] view plain copy
  1. CC = gcc -DDEBUG  

2、打开调试宏后,程序运行目录会产生三个文件:

RECV.log:记录了onvif接收到的SOAP数据

SENT.log:记录了onvif发送出去的SOAP数据

TEST.log:记录了onvif的实时的工作状态

0 0