目前见过的错误码返回值为:-1,4,8,12,401,其实错误码的值并不重要,当我们发现有错误时,应该使用调试工具ONVIF Device test tool等去模拟发送和接收,并查看接收到的错误信息的打印,最为可靠;
soap_recv___wsdd__ProbeMatches(struct soap *soap, struct __wsdd__ProbeMatches *_param_1)
返回值 soap->error = -1;
解决方法:接收失败,多为IPC离线、网络问题、可以尝试查看设备是否在线,或者调大接收超时时间来调试。
SOAP_FMAC5 int SOAP_FMAC6 soap_call___tds__GetCapabilities(struct soap *soap, const char *soap_endpoint, const char *soap_action, struct _tds__GetCapabilities *tds__GetCapabilities, struct _tds__GetCapabilitiesResponse *tds__GetCapabilitiesResponse)
返回值 soap->error = 8;
解决方法:遇到IPC无法识别的命名空间,不使用初始化头文件函数1,使用初始化头文件函数2(平时用函数1,当判断到return == 8,就调用函数2,再重新获取能力即可);
初始化头文件函数1:bool OnvifInitHeader(struct soap* pSoap)
struct SOAP_ENV__Header *header = NULL;
if(NULL == pSoap) return false;
header = (struct SOAP_ENV__Header *)OnvifSoapMalloc(pSoap, sizeof(struct SOAP_ENV__Header));
soap_default_SOAP_ENV__Header(pSoap, header);
header->wsa__MessageID = (char*)soap_wsa_rand_uuid(pSoap);
header->wsa__To = (char*)OnvifSoapMalloc(pSoap, strlen(SOAP_TO) + 1);
header->wsa__Action = (char*)OnvifSoapMalloc(pSoap, strlen(SOAP_ACTION) + 1);
strcpy(header->wsa__To, SOAP_TO);
strcpy(header->wsa__Action, SOAP_ACTION);
pSoap->header = header;
return true;
初始化头文件函数2:bool OnvifInitHeader2(struct soap* pSoap)
struct SOAP_ENV__Header *header = NULL;
header = (struct SOAP_ENV__Header *)OnvifSoapMalloc(pSoap, sizeof(struct SOAP_ENV__Header));
soap_default_SOAP_ENV__Header(pSoap, header);
pSoap->header = header;
return true;
SOAP_FMAC5 int SOAP_FMAC6 soap_call___trt__GetProfiles(struct soap *soap, const char *soap_endpoint, const char *soap_action, struct _trt__GetProfiles *trt__GetProfiles, struct _trt__GetProfilesResponse *trt__GetProfilesResponse)
返回值 soap->error = 4;
***解决方法:遇到了两次返回值为4的情况,第一次是修改文件stdsoap2.cpp下函数soap_s2byte(struct soap soap, const char s, char p);注释掉代码中注释的部分,错误就消失了;第二次是因为IPC主码流或其他码流中含有gsoap不识别的音视频编码格式,例如H265,我使用的是第一版的onvif协议,gsoap也不能正确解析H265,所以报错,有兴趣的朋友可以参考这位大神的做法:Linux下onvif客户端获取h265 IPC摄像头的RTSP地址,或者直接修改摄像头视频编码格式为H264即可;
soap_s2byte(struct soap *soap, const char *s, char *p){
if (s){
long n;
char *r;
n = soap_strtol(s, &r, 10);
if (/*s == r || *r ||*/ n < -128 || n > 127)
soap->error = SOAP_TYPE;
*p = (char)n;
}
return soap->error;
}
返回值 soap->error = 401;
解决方法:摄像头用户名或者密码出错,输入正确的用户名密码就可以了。
返回值 soap->error = 12;
解决方法:摄像头设置了输入密码多次错误后,针对指定IP锁死禁止访问的机制,可以在程序里加密码判断来避免其多次错误的情况,或者修改IPC的安全配置中的选项,以下是海康摄像头的配置界面:
在我尝试组播搜索的时候只有同一网段的IPC能够返回信息值到我的程序,其他IPC即使在一个局域网内,但是不是同一网段的IPC,都不会返回消息;但是使用工具ONVIF Device test tool组播搜索的时候又能找到不同网段的IPC;这个问题尚未解决,希望有大神提供思路;
一开始我使用了一个单例模式,创建了一个soap* 的成员变量,就一直使用这个成员变量作为参数去调用各种功能;但是这样随着运行时间增加,调用功能函数次数增多会出现内存泄漏!!!。最后还是使用创建后就销毁的策略来解决了内存泄漏的问题;