算下來,斷斷續續的接觸Onvif有近兩個多星期了,剛開始實在不好懂,尤其它基于soap協定而來,之前對這個協定也沒怎麼了解,讓我進度緩慢。 不過幸好有google大神在,幫助良多。閑扯了,由于項目需要,需要對攝像頭模組(符合ONVIF的)的一些屬性進行修改,比如網絡配置、視訊參數配置等。 OK,剛接到這個需求,就開始無窮的google,發現網上多是搜尋裝置的例子,涉及修改裝置屬性的文章不多。 還好讓我找到些類似的,再配合官方白皮書說明,終于把這個東西解決了。
/*
* endpoint: 操作ONVIF裝置位址 如"http://192.168.1.100/onvif/device_service"
* ip_dst: 這是我用的全局變量,就是ip位址了
*/
int onvif_DeviceSetNetworkInterfaces(char *endpoint)
{
int result = SOAP_ERR;
if( endpoint == NULL || == strlen(endpoint) )
{
printf("[%s][%d]\n", __func__, __LINE__);
return result;
}
if( endpoint != NULL && != strlen(endpoint) )
{
struct soap soap;
soap_init(&soap);
struct _tds__SetNetworkInterfaces req;
struct _tds__SetNetworkInterfacesResponse rsp;
rsp.RebootNeeded = ;//設定後重新開機
char interface[] = "NetworkInterfaceToken_1";
req.InterfaceToken = interface;//要設定的裝置網絡接口
//char ipaddr[16] = "10.0.0.232";
//xsd__boolean dhcp = xsd__boolean__true_;
struct tt__NetworkInterfaceSetConfiguration network;
soap_default_tt__NetworkInterfaceSetConfiguration(&soap, &network);
//network.Enabled = 1;
enum xsd__boolean netEnable = xsd__boolean__true_;
enum xsd__boolean ipv4Enable = xsd__boolean__true_;
enum xsd__boolean DHCP = xsd__boolean__false_;
network.Enabled = &netEnable;
struct tt__IPv4NetworkInterfaceSetConfiguration tt_ipv4;
soap_default_tt__IPv4NetworkInterfaceSetConfiguration(&soap, &tt_ipv4);
struct tt__PrefixedIPv4Address tt_prefAddr;
soap_default_tt__PrefixedIPv4Address(&soap, &tt_prefAddr);
tt_prefAddr.Address = ip_dst;//modify ipaddr
tt_prefAddr.PrefixLength = ;
tt_ipv4.Manual = &tt_prefAddr;
tt_ipv4.__sizeManual = ;//must understand 這裡坑我最久,後面會說
tt_ipv4.DHCP = &DHCP;
tt_ipv4.Enabled = &ipv4Enable;
network.IPv4 = &tt_ipv4;
int mtuLen = ;
network.MTU = &mtuLen;
printf("%d\n", network.IPv4->Manual->PrefixLength);
printf("%s\n", network.IPv4->Manual->Address);
req.NetworkInterface = &network;
result = soap_call___tds__SetNetworkInterfaces(&soap,endpoint, NULL, &req, &rsp);
if(result == SOAP_OK)
{
printf("====================setNetworkInterfaces successful============================\n");
}
soap_destroy(&soap);
soap_end(&soap);
soap_done(&soap);
}
return result;
}
下面回顧一下我的調試經過:
1、 代碼一開始一直報段錯誤,原因是有些結構體的成員指派類型不對。 舉個例子:tt__NetworkInterfaceSetConfiguration結構體裡Enabled成員為xsd__boolean *, 那麼就必須用這個類型來給值,不能直接用1或0。
2、soap_call___tds__SetNetworkInterfaces一直設定失敗,後來通過wireshark去抓包發現别人工具(Onvif device Manager)發出的SetNetworkInterfaces指令,裡面的InterfaceToken為”NetworkInterfaceToken_1”, 我之前一直用的是”lo”或“eth0”,後來修改好後,發現就能設定部分資訊了,比如DHCP、MTU那些資訊, 并且設定後模組能夠自行重新開機。 但IP仍無法正常修改。
抓包如下:

3、後來在網上找尋答案無果,回來看看DEBUG資訊,發現我的SENT.log如下
再對比一下Onvif device Manager設定OK的指令,抓包下來可以看到:
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SetNetworkInterfaces xmlns="http://www.onvif.org/ver10/device/wsdl">
<InterfaceToken>NetworkInterfaceToken_1</InterfaceToken>
<NetworkInterface>
<Enabled xmlns="http://www.onvif.org/ver10/schema">true</Enabled>
<MTU xmlns="http://www.onvif.org/ver10/schema">16436</MTU>
<IPv4 xmlns="http://www.onvif.org/ver10/schema">
<Enabled>true</Enabled>
<Manual><Address>10.0.0.231</Address><PrefixLength>24</PrefixLength></Manual>
<DHCP>false</DHCP>
</IPv4>
</NetworkInterface>
</SetNetworkInterfaces>
</s:Body>
難怪我的IP修改設定總不成功,soap都沒把我的修改ip資訊加上,裡面沒有找到Manual段,Manual段包括了位址資訊的修改。
最後的最後,發現是自己沒有設定tt__IPv4NetworkInterfaceSetConfiguration結構體的__sizeManual成員,少了設定Manual的size,soap不知道這個大小,是以沒有将資訊發送上。 是以我設定成1後,就全部work了,哈哈。 下面為成功後的SENT.log資訊
最後說明一下,我操作的裝置是攝像頭模組,可能代碼裡面有些跟你們用的裝置資訊不一樣,這個需要根據實際情況進行修改。
需要工程的話,見下載下傳連結: http://download.csdn.net/download/nszjh/8618129
參考