ONVIF客户端开发

时间:2021-11-10 08:30:55

在使用 gSoap 框架生成代码之后, 得到文件:

 soapC.c 
soapClient.c
stdsoap2.c stdsoap2.h
duration.c
wsdd.h

我们利用现有的soapClient, 调用API构建Onvif请求(包括XML, HTTP Client). 开发前需要了解一下Onvif官网文档指导: Onvif 2.0 Service Operation Index;该文档列举了ONVIF的各个模块下的各种方法. 再回到gSoap框架, 同样, 它的文档说明也比较详细.

gSoap 框架API

  • 创建初始化Soap对象
    在stdsoap2.h文件中,有如下定义
//创建各种soap
#define soap_new() soap_new1(SOAP_IO_DEFAULT)
#define soap_new1(mode) soap_new2(mode, mode)
#define soap_new2(imode, omode) soap_versioning(soap_new)(imode, omode)
//初始化各种soap
#define soap_init(soap) soap_init1(soap, SOAP_IO_DEFAULT)
#define soap_init1(soap, mode) soap_init2(soap, mode, mode)
#define soap_init2(soap, imode, omode) soap_versioning(soap_init)(soap, imode, omode)
  • 申请内存模块打Soap中
//该函数soap_done函数调用的时候释放, 无需调用free函数
soap_malloc(struct soap *soap, size_t n)
  • 结束释放Soap
//释放临时Cache
soap_end(struct soap *soap)

//释放所以内存模块和关闭socket
soap_done(struct soap *soap)

//销毁soap对象
#define soap_destroy(soap) soap_delete((soap), NULL)

另外,调试程序接口信息可以打开LOG Level, 如Cmake下

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -ggdb -DDEBUG")

使用宏DEBUG打开并输出调试信息到 recv.log, send.log, test.log .

设备发现

从官方文档上列举的这些方法,我们按照正常操作ONVIF设备客户端开始,那么第一步就必然是找到ONVIF在线的设备.

设备搜索步骤:

(1) 初始化客户端
初始化客户端, 包括uuid地址, 超时设置,头部信息等.

struct saop* onvif_init_soap(struct SOAP_ENV__Header *header,
const char *wsa_To,
const char *wsa_Action,
int timeout,
UserInfo_S *pUser){
struct soap *soap = NULL;
unsigned char macaddr[6] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; //设置MAC值
char _HwId[1024];
unsigned int Flagrand;
soap = soap_new();

if (soap == NULL) {
//LOGE("soap is NULL\n");
return NULL;
}

//设置命名空间
soap_set_namespaces(soap, namespaces);
if (timeout > 0){
soap->recv_timeout = timeout;
soap->send_timeout = timeout;
soap->connect_timeout = timeout;
}else{
//设置超时默认值 10s
soap->recv_timeout = 10;
soap->send_timeout = 10;
soap->connect_timeout = 10;
}

soap_default_SOAP_ENV__Header(soap, header);

srand((int)time(0));
Flagrand = rand() % 9000 + 1000; //取4位数

sprintf(_HwId, "urn:uuid:%ud68a-1dd2-11b2-a1025-%02X%02X%02X%02X%02X%02X",
Flagrand, macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
header->wsa__MessageID = (char *)soap_malloc(soap, 100);
memset(header->wsa__MessageID, 0, 100);
strncpy(header->wsa__MessageID, _HwId, strlen(_HwId));

if (pUser != NULL){
//TODO
}

if (wsa_Action != NULL){
//was_Action = "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";
header->wsa__Action = (char *)malloc(1024);
memset(header->wsa__Action, '\0', 1024);
strncpy(header->wsa__Action, wsa_Action, 1024);
}

if (wsa_To != NULL){
//wsa_To = "urn:schemas-xmlsoap-org:ws:2005:04:discovery";
header->wsa__To = (char *)malloc(1024);
memset(header->wsa__To, '\0', 1024);
strncpy(header->wsa__To, wsa_To, 1024);
}

soap->header = header;
return soap;
}

(2) 设置Probe搜索参数

wsdd__ProbeType req;
struct __wsdd__ProbeMatches resp;
wsdd__ScopesType sScope;
struct SOAP_ENV__Header header;
struct soap *soap = NULL;

const char *wsa_To = "urn:schemas-xmlsoap-org:ws:2005:04:discovery";
const char *wsa_Action = "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe";
const char *soap_endpoint = "soap.udp://239.255.255.250:3702/";

soap = onvif_init_soap(&header, wsa_To, wsa_Action, 5, NULL);

soap_default_SOAP_ENV__Header(soap, &header);
soap->header = &header;

soap_default_wsdd__ScopesType(soap, &sScope);
sScope.__item = "";
soap_default_wsdd__ProbeType(soap, &req);
req.Scopes = &sScope;
req.Types = "";

(3) 发送Probe Action

retval = soap_send___wsdd__Probe(soap, soap_endpoint, NULL, &req);

(4) 接收ProbeMatches


while(retval == SOAP_OK){
retval = soap_recv___wsdd__ProbeMatches(soap, &resp);
if (retval == SOAP_OK){
if (soap->error){
//LOGE("recv soap error:%s(%d)\n", *soap_faultstring(soap), *soap_faultcode(soap));
retval = soap->error;
}else{
if (resp.wsdd__ProbeMatches != NULL &&
resp.wsdd__ProbeMatches->ProbeMatch != NULL &&
resp.wsdd__ProbeMatches->ProbeMatch->XAddrs != NULL){
HasDev ++;

if (on_device_found(resp)){// 非0表示退出
break;
}

sleep(1);
}
}//else
}else if (soap->error){
if (HasDev == 0){
retval = soap->error;
}else{
retval = 0;
}
break;
}//else if
}//while

(5) 释放资源

soap_destroy(soap);
soap_end(soap);
soap_free(soap);