Onvif协议客户端开发【3.问题篇】

自己在开发的过程中也遇到了很多问题,这里记录下来。

1.平台问题。

一开始自己是在windows下面开发的,但是一者windows下面的make跟linux下的有些差异,二者在windows下面如果用VS来做开发的话在交叉编译的过程中可能也会碰到很多问题。大多数的资料上大家基本都采用在linux上进行开发,虽然官方的测试工具是C#写的所以估计是用vs开发的,但是既然linux平台上的资料多一点,那么自己也就在linux上开发好了。

2.在搜索篇中碰到的问题。

主要参考下面这篇文章:

Onvif开发之客户端搜索篇

注意文章中代码96行:

1
req.Types = ""; //"dn:NetworkVideoTransmitter";

必须填写,我自己因为没有填写这个字段,导致出现了segment fault错误。应该是没有初始化结构体导致指针访问了错误的地址。

/*设置所需设备的类型,ns1为命名空间前缀,为wsdd.nsmap文件中

{“tdn”,”http://www.onvif.org/ver10/network/wsdl”}的tdn,如果不是tdn,而是其它,

例如ns1这里也要随之改为ns1 */

而到底改成什么可以查看自己的wedd.h(有wsdd.nsmap修改名称后得到)文件。

3.在鉴权篇中遇到的问题

鉴权篇主要参考下面两个博客:

Onvif开发之客户端鉴权获取参数篇

Linux设备上的Onvif实现16:实现Onvif鉴权

我采用的是第二篇博客中的方法,也就是使用soap_wsse_add_UsernameTokenDigest这个函数。

当时为了使用这个函数,可是费了自己很大周折。需要的注意点很多:

  1. 必须写makefile。由于soapC.c有11M,编译它在我的电脑上要花2分钟左右的时间,所以为了不必每次修改代码后都重新编译它,最好编写makefile。这也是我第一次认识到makefile如此重要的一个原因。
  2. 仔细阅读第二篇文章里面的编译细节,2 实现一节好好看,一个细节出问题就会编译不了的,具体来说:
  3. 修改onvif.h #include”wsse.h”
  4. 鉴权需要的那些文件:dom.c wsseapi.c smdevp.c mecevp.c threads.c wsaapi.c还有对应的头文件,一个都不能少!
  5. makefile中必须添加编译开关-DWITH_DOM -DWITH_OPENSSL
  6. wsse系列函数必须链接标准的openssl库 我们先去openssl官网中下载源代码来编译,源代码里面有我们需要的头文件。在gcc编译的时候需要在gcc全局搜索路径 C_INCLUDE_PATH 里面加上头文件所在路径。
  7. 由于编译的时候需要 -lcrypto -lssl 链接openssl的这两个库,为了简单起见我们直接在linux里面安装openssl好了,这样应该就可以成功链接了。

最后即使编译成功了,在运行的时候会出现soap->error 4的情况。仍然是不知道原因,但是找到如下的解决方法:

http://blog.csdn.net/bing87496988/article/details/38707829

该方案注释了半行代码就好了。具体原因不明。

至此如果能够成功使用鉴权函数soap_wsse_add_UsernameTokenDigest

下面的事情就好办啦~~~~

 

4.鉴权成功之后我基本上全程按照精华篇那份代码copy下来测试每一个步骤,包括能力获取,媒体配置文件获取和uri获取。

这里需要注意两个问题:

第一个是内存初始化的问题。比如我们有结构体E,我们做如下的初始化:

struct E e;

这样初始化不会出错。因为是在栈里面分配内存,系统自己会帮你做好初始化工作

但是下面这个样子就有问题了:

struct E *e;

这个时候如果我们访问e的成员变量比如e->a就可能会出现由于没有初始化而造成segment fault错误。

所以在开发的时候我们应该时刻记得初始化,加上:

e = (E *)malloc(sizeof(struct E));

这样我们再访问就不会出现错误了。

这是个很基本的问题,但是自己还是犯错了,希望谨记。

第二个问题是在读取媒体配置文件的时候,通过官方提供的工具发现media profile文件存在多个,那么如何读取多个媒体文件呢?

一开始以为要调用soap_call_trtGetProfiles多次,后来看了官方文档,发现其实调用这个函数之后,在trt__GetProfilesResponse里面已经包含了多个profiles的信息了。也就是是这个结构体里面包含的是profile list。

我们可以通过使用打印出trt_GetProfilesResponse.__sizeProfiles的值来印证我们的观点。

而有多个media profiles并不妨碍我们后面获取media uri。

 

基本上在直到获取uri的过程中碰到的大问题就是这个几个了。如果大家碰到了其他问题可以再看看资料篇里面的其他资料。