onvif客户端对接大华设备错误解决


前段时间调试onvif客户端的时候出现了一个奇怪的问题,手头有大华和海康的IPC各一个,海康的IPC使用onvif与待测试的onvif客户端完美测试通过。但是在用大华设备测试onvif客户端的时候出现了一些奇怪的问题。这两个奇怪的问题纠结了我2-3天,经过一段时间的努力终于解决了此bug,下面就此bug进行记录,希望给开发onvif客户端的coder们提供些许帮助。

错误1:客户端调用GetOSDOptions,GetOSDs的时候,大华设备也对此信令进行了完整的回复,但是在客户端使用返回参数trt__GetOSDOptionsResponse,trt__GetOSDsResponse的时候,发现这些参数都是NULL.但是通过抓包发现这些数据大华IPC已经进行了回复。

解决:通过打开-DDEBUG选项,查看onvif客户端的调试信息,发现在TEST.log中有如下Tags GetOSDs----------trt:GetOSDs match but namespaces differ;Tags GetOSDOptions----------trt:GetOSDOptions match but namespaces differ;在onvif框架代码中查找namespaces differ,在stdsoap2.c的soap_match_tag函数中找到了

  1. soap_match_tag(struct soap *soap, constchar *tag1, constchar *tag2)

  2. { registerconstchar *s, *t;

  3. registerint err;

  4. if (!tag1 || !tag2 || !*tag2)

  5. return SOAP_OK;

  6. s = strchr(tag1, ':');

  7. t = strchr(tag2, ':');

  8. if (t)

  9. { if (s)

  10. { if (t[1] && SOAP_STRCMP(s + 1, t + 1))

  11. return SOAP_TAG_MISMATCH;

  12. if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)))

  13. { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, t));

  14. if (err == SOAP_NAMESPACE)

  15. return SOAP_TAG_MISMATCH;

  16. return err;

  17. }

  18. }

  19. elseif (!t[1])

  20. { err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2);

  21. if (err == SOAP_NAMESPACE)

  22. return SOAP_TAG_MISMATCH;

  23. }

  24. elseif (SOAP_STRCMP(tag1, t + 1))

  25. { return SOAP_TAG_MISMATCH;

  26. }

  27. elseif (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2)))

  28. {

  29. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s'----------'%s' match but namespaces differ\n", tag1, tag2));

  30. if (err == SOAP_NAMESPACE)

  31. return SOAP_TAG_MISMATCH;

  32. return err;

  33. }

  34. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));

  35. return SOAP_OK;

  36. }

  37. if (s)

  38. { if (SOAP_STRCMP(s + 1, tag2))

  39. return SOAP_TAG_MISMATCH;

  40. }

  41. elseif (SOAP_STRCMP(tag1, tag2))

  42. return SOAP_TAG_MISMATCH;

  43. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));

  44. return SOAP_OK;

  45. }<pre name="code"class="cpp">soap_match_namespace(struct soap *soap, constchar *id1, constchar *id2, size_t n1, size_t n2)

  46. { registerstruct soap_nlist *np = soap->nlist;

  47. constchar *s;

  48. while (np && (strncmp(np->id, id1, n1) || np->id[n1]))

  49. {

  50. DBGLOG(TEST, SOAP_MESSAGE(fdebug, "np->id:%s id1:%s\n",np->id,id1));

  51. np = np->next;

  52. }

  53. if (np)

  54. { if (!(soap->mode & SOAP_XML_IGNORENS))

  55. if (np->index < 0

  56. || ((s = soap->local_namespaces[np->index].id) && (strncmp(s, id2, n2) || (s[n2] && s[n2] != '_'))))

  57. return SOAP_NAMESPACE;

  58. return SOAP_OK;

  59. }

  60. if (n1 == 0)

  61. return (SOAP_XML_IGNORENS) ? SOAP_OK : SOAP_NAMESPACE;//modfied by Gaoy---20171016 soap->mode & SOAP_XML_IGNORENS---->SOAP_XML_IGNORENS

  62. if ((n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3))

  63. || (soap->mode & SOAP_XML_IGNORENS))

  64. return SOAP_OK;

  65. return soap->error = SOAP_SYNTAX_ERROR;

  66. }

  1. 最终确定是由于soap_match_namespace返回出错导致的,故在soap_match_namespace将做如下修改return (SOAP_XML_IGNORENS) ? SOAP_OK : SOAP_NAMESPACE;//modfied by Gaoy---20171016 soap->mode & SOAP_XML_IGNORENS---->SOAP_XML_IGNORENS

  2. 经过此番修改,在获取osd的时候上述错误便不再出现了。但是对于在此修改对其他地方造成的影响目前还未看到,希望遇到过此种问题的Coder们给我一点你们的修改提示。互相学习…………

  1. 错误2:客户端可以获取到大华IPC的视频编码参数,但是在将获取到的参数重新设置下去就出现了错误

  2. [11:50:25, onvif_client.c, 2309]soap error(12): SOAP-ENV:Sender, Parameters can not be set<br>

  3. [11:50:25, onvif_client.c, 2309]soap error(12): SOAP-ENV:Sender, Parameters can not be set<br>

  1. 解决:经过在通过大华NVR去使用onvfi协议设置IPC参数的抓包信息进行比较发现,是由于我的onvif客户端代码在设置IPC参数的对于下面加粗的部分未进行赋值,估计大华对这些参数是不能进行修改的,但是由于我未赋值就传下去了错误的值导致出错。

    p_trt__SetVideoEncoderConfiguration->Configuration->Multicast->Address->IPv4Address = (char *)soap_malloc(soap, DEFAULT_LNGTH_SIZE);

    sprintf(p_trt__SetVideoEncoderConfiguration->Configuration->Multicast->Address->IPv4Address, "239.1.0.1");

    p_trt__SetVideoEncoderConfiguration->Configuration->Multicast->Address->IPv6Address = NULL;

    p_trt__SetVideoEncoderConfiguration->Configuration->Multicast->Port = 1001;

    p_trt__SetVideoEncoderConfiguration->Configuration->Multicast->AutoStart = xsd__boolean__false_;

    p_trt__SetVideoEncoderConfiguration->Configuration->Multicast->TTL = 64;

    p_trt__SetVideoEncoderConfiguration->Configuration->Multicast->__size = 0;

    p_trt__SetVideoEncoderConfiguration->Configuration->Multicast->__any = NULL;

  1. 客户端和服务器端的onvif版本:

  2. 大华IPC onvif版本:v2.4.1 onvif客户端版本:17.06