2012年12月28日 星期五

使用 gSoap 2.8.12 產生 ONVIF 程式碼


20121229 更新

1. gSOAP 最新版本為 2.8.12, 此版本在 FAQ 中註明了 ONVIF 程式產生時的 define namespace prefix and type bindings,如此在開發程式時可有一個統一的命名規則。如下:

tds = "http://www.onvif.org/ver10/device/wsdl" tev = "http://www.onvif.org/ver10/events/wsdl" tls = "http://www.onvif.org/ver10/display/wsdl" tmd = "http://www.onvif.org/ver10/deviceIO/wsdl" timg = "http://www.onvif.org/ver20/imaging/wsdl" trt = "http://www.onvif.org/ver10/media/wsdl" tptz = "http://www.onvif.org/ver20/ptz/wsdl" trv = "http://www.onvif.org/ver10/receiver/wsdl" trc = "http://www.onvif.org/ver10/recording/wsdl" tse = "http://www.onvif.org/ver10/search/wsdl" trp = "http://www.onvif.org/ver10/replay/wsdl" tan = "http://www.onvif.org/ver20/analytics/wsdl" tad = "http://www.onvif.org/ver10/analyticsdevice/wsdl" tdn = "http://www.onvif.org/ver10/network/wsdl" tt = "http://www.onvif.org/ver10/schema"



2. 這些常用定義已經內建在 d:\gsoap_2.8.12\gsoap-2.8\gsoap\typemap.dat 內。因此要編譯程式碼時直接使用即可。就一個支援 ONVIF 的 IPCAM, 其 wsdl2h 與 soapcpp2 的指令分別如下:

wsdl2h -cegxy -o onvif.h -t ..\..\typemap.dat http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl http://www.onvif.org/onvif/ver10/event/wsdl/event.wsdl http://www.onvif.org/onvif/ver10/deviceio.wsdl http://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdl http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl http://www.onvif.org/onvif/ver10/schema/onvif.xsd
   其中此處 wsdl2h 所用到的參數,其意義如下:
   -c      generate C source code
   -e      don't qualify enum names
   -g      generate global top-level element declarations
   -x      don't generate _XML any/anyAttribute extensibility elements
   -y      generate typedef synonyms for structs and enums

bin\win32\soapcpp2 -S -x -Iimport onvif.h    其中此處 soapcpp2 所用到的參數,其意義如下:
   -S      Generate server-side code only
   -x      Do not generate sample XML message files
   -I      Use (or paths separated with `:') for #import
 

3. 若需要支援舊版 ONVIF 規格
   例如: http://www.onvif.org/onvif/ver20/imaging/wsdl/imaging.wsdl
   那麼便需要手動更改 typemap.dat,
   例如加入 timg1 = "http://www.onvif.org/ver10/imaging/wsdl"


4. 使用上述 schema 此時產生的 onvif.h 會出現類似的 API。
   例如 __tev__Notify 與 __tev__Notify_ ,參考下圖,其實這兩個是相同的資料結構,
 
//gsoap tev service method-style: Notify_ document //gsoap tev service method-encoding: Notify_ literal //gsoap tev service method-action: Notify_ http://docs.oasis-open.org/wsn/bw-2/PullPoint/Notify int __tev__Notify_( struct _wsnt__Notify* wsnt__Notify, ///< Request parameter void ///< One-way message: no response parameter ); //gsoap tev service method-style: Notify document //gsoap tev service method-encoding: Notify literal //gsoap tev service method-action: Notify http://docs.oasis-open.org/wsn/bw-2/NotificationConsumer/Notify int __tev__Notify( struct _wsnt__Notify* wsnt__Notify, ///< Request parameter void ///< One-way message: no response parameter );

   後續產生的 stub function 也相同,因此實作時,其實可以將這兩個函數合併,舉例如下
SOAP_FMAC5 int SOAP_FMAC6 __tev__Notify(struct soap* tsoap, struct _wsnt__Notify *wsnt__Notify) { return 0; } SOAP_FMAC5 int SOAP_FMAC6 __tev__Notify_(struct soap* tsoap, struct _wsnt__Notify *wsnt__Notify) { __tev__Notify(tsoap, wsnt__Notify) return 0; }


問題分析
1. wsdl2h 使用時會產生下列warning messages. 問題待釐清..
Warning: attempt to include schema with mismatching elementFormDefault in schema 'http://www.onvif.org/ver10/device/wsdl' Warning: attempt to include schema with mismatching elementFormDefault in schema 'http://www.onvif.org/ver10/events/wsdl' Warning: attempt to include schema with mismatching elementFormDefault in schema 'http://www.onvif.org/ver10/deviceIO/wsdl' Warning: attempt to include schema with mismatching elementFormDefault in schema 'http://www.onvif.org/ver20/imaging/wsdl' Warning: attempt to include schema with mismatching elementFormDefault in schema 'http://www.onvif.org/ver10/media/wsdl' Warning: attempt to include schema with mismatching elementFormDefault in schema 'http://www.onvif.org/ver20/ptz/wsdl' Warning: attempt to include schema with mismatching elementFormDefault in schema 'http://www.onvif.org/ver10/schema' Warning: attempt to include schema with mismatching elementFormDefault in schema 'http://docs.oasis-open.org/wsrf/rw-2' Warning: attempt to include schema with mismatching elementFormDefault in schema 'http://www.onvif.org/ver10/media/wsdl' Warning: attempt to include schema with mismatching elementFormDefault in schema 'http://www.onvif.org/ver10/device/wsdl' Warning: WSDL "http://docs.oasis-open.org/wsn/bw-2" has no bindings to define operations

2. soapcpp2 所產生的程式碼與舊版不同處
參考下列程式碼
/// "http://docs.oasis-open.org/wsrf/r-2":ResourceUnknownFaultType is a complexType with complexContent extension of "http://docs.oasis-open.org/wsrf/bf-2":BaseFaultType. struct wsrfr__ResourceUnknownFaultType { /// INHERITED FROM wsrfbf__BaseFaultType: /// TODO: /// TODO: Schema extensibility is user-definable. /// Consult the protocol documentation to change or insert declarations. /// Use wsdl2h option -x to remove this element. /// Use wsdl2h option -d for xsd__anyType DOM (soap_dom_element). /// Element Timestamp of type xs:dateTime. time_t Timestamp 1; ///< Required element. /// Element Originator of type "http://www.w3.org/2005/08/addressing":EndpointReferenceType. wsa5__EndpointReferenceType* Originator 0; ///< Optional element. struct _wsrfr__ResourceUnknownFaultType_ErrorCode { /// Attribute dialect of type xs:anyURI. @xsd__anyURI dialect 1; ///< Required attribute. } *ErrorCode 0; ///< Optional element. /// Size of Description array is 0..unbounded $int __sizeDescription 0; struct _wsrfr__ResourceUnknownFaultType_Description { /// __item wraps 'xs:string' simpleContent. char* __item ; /// Imported attribute reference xml:lang. @_xml__lang xml__lang 0; ///< Optional attribute. } *Description 0; struct _wsrfr__ResourceUnknownFaultType_FaultCause { /// TODO: /// TODO: Schema extensibility is user-definable. /// Consult the protocol documentation to change or insert declarations. /// Use wsdl2h option -x to remove this element. /// Use wsdl2h option -d for xsd__anyType DOM (soap_dom_element). } *FaultCause 0; ///< Optional element. /// /// TODO: Schema extensibility is user-definable. /// Consult the protocol documentation to change or insert declarations. /// Use wsdl2h option -x to remove this attribute. /// Use wsdl2h option -d for xsd__anyAttribute DOM (soap_dom_attribute). // END OF INHERITED FROM wsrfbf__BaseFaultType };

比較 Timestamp,舊版的定義為 wsrf_bf2__Timestamp,因此產生的XML會有以下區別
<wsrf_bf2:Timestap>Time</wsrf_bf2:Timestap>
<wsrf_r2:Timestap>Time</wsrf_r2:Timestap>

參考 "http://docs.oasis-open.org/wsrf/bf-2.xsd 的定義,似乎新版gSoap此部分會造成問題的。使用 ONVIF Test Tool 12.06 測試,當回復的錯誤碼內為<wsrf_r2:Timestap>Time</wsrf_r2:Timestap>時,Test Tool會認為回復的內容無法正確辨識。