天天看點

Onvif修改裝置屬性

算下來,斷斷續續的接觸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仍無法正常修改。

抓包如下:

Onvif修改裝置屬性

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

參考

繼續閱讀