11178
- 收藏
- 点赞
- 分享
- 举报
ONVIF协议实现3:整合Discovery和码流地址用ONVIF Device Manager测试
本帖最后由 goodman 于 2015-1-9 21:57 编辑
工作平台及工具:
Ubuntu:12.04 + gcc + OnvifTestTool12.12
gsoap下载:[url]http://www.cs.fsu.edu/~engelen/soap.html[/url]
PC:live555.exe + test.264
目前的最新版本为:gsoap2.8.21
经过前2编文章的的分析对于掌握ONVIF的实现应该没有什么问题了,本来是不想写这边文章的,但是我在整合Discovery和码流地址的时候还是遇到了不少问题
想想将来有某个小伙伴按照我的文章来学习ONVIF看到GC的部分突然没有了这是很不好的,做事情要有始有终,让我们把它结束吧。
1.生成源码
这次生成的代码需要3个WSDL了
./wsdl2h -o onvif.h -c -s -t ./typemap.dat [url]http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl[/url]
./soapcpp2 -c onvif.h -x -d ./ -I ${HOME}/workspace/source/gsoap-2.8/gsoap/import -I ${HOME}/workspace/source/gsoap-2.8/gsoap/
2.整理流程
整个程序的运行流程大概是这个样子,嗯,差不多就是这个样子。

3.整理代码
将设备发现和码流获取部分的代码分别整理到2个单独的文件里面去,接口函数如下:
/*初始化设备搜索的代码*/
[code]
int discoveryInit(struct DiscoveryApp *disApp);
void discoveryFini(struct DiscoveryApp *disApp);
int discoveryRun(struct DiscoveryApp *disApp);
/*初始化码流地址部分的代码*/
int gsoapAppInit(struct GsoapApp* app);
void gsoapAppFini(struct GsoapApp* app);
int gsoapAppRun(struct GsoapApp* app, int forked);
[/code]
那么整个主函数就比较干净了(当然我给的是示例代码,容错我想大家都知道怎么加)
[code]
struct GsoapApp* gApp = NULL;
struct DiscoveryApp* disApp = NULL;
int main(int argc, char* argv[])
{
gApp = (struct GsoapApp*)calloc(1, sizeof(*gApp));
disApp = (struct DiscoveryApp*)calloc(1, sizeof(*disApp));
discoveryInit(disApp);
discoveryRun(disApp);
gsoapAppInit(gApp);
gsoapAppRun(gApp, 1);
while(1) {
sleep(1);
}
discoveryFini(disApp);
gsoapAppFini(gApp);
free(gApp);
free(disApp);
return 0;
}
[/code]
4.错误处理
本以为到这里编译下就行了,因为我们在先前已经调通了Discovery和流地址的代码写好Makefile后一编译错误了
问题1链接错误:
[code]
wsddapi.c: In function ‘soap_wsdd_Hello’:
wsddapi.c:466:6: error: ‘struct wsdd__HelloType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘soap_wsdd_Bye’:
wsddapi.c:531:6: error: ‘struct wsdd__ByeType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘soap_wsdd_Resolve’:
wsddapi.c:688:6: error: ‘struct wsdd__ResolveType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘soap_wsdd_add_ProbeMatch’:
wsddapi.c:796:4: error: ‘struct wsdd__ProbeMatchType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘soap_wsdd_ResolveMatches’:
wsddapi.c:892:8: error: ‘struct wsdd__ResolveMatchType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘__wsdd__Hello’:
wsddapi.c:1132:13: error: ‘struct wsdd__HelloType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c:1140:1: error: ‘struct wsdd__HelloType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c:1162:10: error: ‘struct wsdd__HelloType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘__wsdd__Bye’:
wsddapi.c:1200:11: error: ‘struct wsdd__ByeType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c:1208:1: error: ‘struct wsdd__ByeType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c:1230:8: error: ‘struct wsdd__ByeType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘__wsdd__Resolve’:
wsddapi.c:1386:15: error: ‘struct wsdd__ResolveType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c:1402:12: error: ‘struct wsdd__ResolveType’ has no member named ‘wsa5__EndpointReference'
[/code]
一下子报了这么多错误,是链接找不到wsa5__EndpointReference,这个情况一般是只声明了,没有定义才会在链接的时候报错。
通过grep查找定义,发现是因为soapStub.h第15行定义了SOAP_WSA_2005宏导致的。
[code]
#ifndef soapStub_H
#define soapStub_H
#define SOAP_WSA_200408
#define SOAP_NAMESPACE_OF_wsdd "http://schemas.xmlsoap.org/ws/2005/04/discovery"
//#define SOAP_WSA_2005 注释这一行就可以了
#define SOAP_NAMESPACE_OF_tds "http://www.onvif.org/ver10/device/wsdl"
[/code]
再次make出现了错误
[code]
gsoapapp.o:(.data+0x0): multiple definition of `namespaces'
discovery.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status
[/code]
这是因为我们使用了2个soap服务,每个sopa服务都要设置自己的命名空间见discovery.c和gsoapapp.c
soap_set_namespaces(&app->soap, namespaces);
将其中的一个名字改掉就好了,我这里改的是gsoapapp.c
soap_set_namespaces(&app->soap, namespaces);-->soap_set_namespaces(&app->soap, namespaces1);
把MediaBinding.nsmap里面的namespaces改为namespaces1问题1就彻底解决了。
问题2无法搜索到设备:
使用ONVIF Device Manager死也搜索不到设备ONVIF Device Test Tool也不行设备端提示如下:

这个Discovery明明是调通的怎么就不行了呢?翻看log/test.log里面我们发现有这些日志
[code]
stdsoap2.c(7729): malloc(20) = 0xb6401b10
stdsoap2.c(7729): malloc(16) = 0xb6401b40
stdsoap2.c(7729): malloc(24) = 0xb6400b40
wsaapi.c(989): soap_wsa_fault_subcode(faultsubcode=wsa5:MessageAddressingHeaderRequired, faultstring=A required header representing a Message Addressing Property is not present.)
stdsoap2.c(7729): malloc(76) = 0xb6401b88
[/code]
经过和第一篇那个单独的Discovery工程里面的日志对比发现是命名空间的问题。打开wsdd.nsmap把命名空间修改为下面的
[code]
#include "soapH.h"
SOAP_NMAC struct Namespace namespaces[] =
{
{"SOAP-ENV", "http://www.w3.org/2003/05/soap-envelope", "http://schemas.xmlsoap.org/soap/envelope/", NULL},
{"SOAP-ENC", "http://www.w3.org/2003/05/soap-encoding", "http://schemas.xmlsoap.org/soap/encoding/", NULL},
{"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", NULL},
{"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema", NULL},
{"wsa", "http://schemas.xmlsoap.org/ws/2004/08/addressing", NULL, NULL},
{"wsdd", "http://schemas.xmlsoap.org/ws/2005/04/discovery", NULL, NULL},
{"tdn", "http://www.onvif.org/ver10/network/wsdl", NULL, NULL},
{"tds", "http://www.onvif.org/ver10/device/wsdl", NULL, NULL},
{NULL, NULL, NULL, NULL}
};
[/code]
重新编译代码(make clean && make)再执行发现可以发现设备了,这样我们就实现了自动发现设备,自动获取ONVIF的流地址了。
5.运行截图
直接运行ONVIF Device Manager程序,这次不需要再在右下角手工添加了。对于系统的标示我填了一部分。

播放视频:

6.总结
这样这个ONVIF系类的文章就算全部完成了,我们只要按照这个框架将其他的命令实现就能完整的做完ONVIF了。
这里大家看到了我们使用的ONVIF端口是8080,为什么要这个端口?这是因为我们的设备上需要用到WEB服务,而
WEB服务将80端口已经占了,不得不说这是个遗憾,目前使用gSOAP我还不清楚怎么把它和WEB整合在一起。当然
如果不借助gSOAP自己去实现ONVIF的话是可以解决的,但是那样要自己去解析xml数据那是比较繁琐的。
工作平台及工具:
Ubuntu:12.04 + gcc + OnvifTestTool12.12
gsoap下载:[url]http://www.cs.fsu.edu/~engelen/soap.html[/url]
PC:live555.exe + test.264
目前的最新版本为:gsoap2.8.21
经过前2编文章的的分析对于掌握ONVIF的实现应该没有什么问题了,本来是不想写这边文章的,但是我在整合Discovery和码流地址的时候还是遇到了不少问题
想想将来有某个小伙伴按照我的文章来学习ONVIF看到GC的部分突然没有了这是很不好的,做事情要有始有终,让我们把它结束吧。
1.生成源码
这次生成的代码需要3个WSDL了
./wsdl2h -o onvif.h -c -s -t ./typemap.dat [url]http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl[/url] [url]http://www.onvif.org/onvif/ver10/network/wsdl/remotediscovery.wsdl[/url]
./soapcpp2 -c onvif.h -x -d ./ -I ${HOME}/workspace/source/gsoap-2.8/gsoap/import -I ${HOME}/workspace/source/gsoap-2.8/gsoap/
2.整理流程
整个程序的运行流程大概是这个样子,嗯,差不多就是这个样子。

3.整理代码
将设备发现和码流获取部分的代码分别整理到2个单独的文件里面去,接口函数如下:
/*初始化设备搜索的代码*/
[code]
int discoveryInit(struct DiscoveryApp *disApp);
void discoveryFini(struct DiscoveryApp *disApp);
int discoveryRun(struct DiscoveryApp *disApp);
/*初始化码流地址部分的代码*/
int gsoapAppInit(struct GsoapApp* app);
void gsoapAppFini(struct GsoapApp* app);
int gsoapAppRun(struct GsoapApp* app, int forked);
[/code]
那么整个主函数就比较干净了(当然我给的是示例代码,容错我想大家都知道怎么加)
[code]
struct GsoapApp* gApp = NULL;
struct DiscoveryApp* disApp = NULL;
int main(int argc, char* argv[])
{
gApp = (struct GsoapApp*)calloc(1, sizeof(*gApp));
disApp = (struct DiscoveryApp*)calloc(1, sizeof(*disApp));
discoveryInit(disApp);
discoveryRun(disApp);
gsoapAppInit(gApp);
gsoapAppRun(gApp, 1);
while(1) {
sleep(1);
}
discoveryFini(disApp);
gsoapAppFini(gApp);
free(gApp);
free(disApp);
return 0;
}
[/code]
4.错误处理
本以为到这里编译下就行了,因为我们在先前已经调通了Discovery和流地址的代码写好Makefile后一编译错误了
问题1链接错误:
[code]
wsddapi.c: In function ‘soap_wsdd_Hello’:
wsddapi.c:466:6: error: ‘struct wsdd__HelloType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘soap_wsdd_Bye’:
wsddapi.c:531:6: error: ‘struct wsdd__ByeType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘soap_wsdd_Resolve’:
wsddapi.c:688:6: error: ‘struct wsdd__ResolveType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘soap_wsdd_add_ProbeMatch’:
wsddapi.c:796:4: error: ‘struct wsdd__ProbeMatchType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘soap_wsdd_ResolveMatches’:
wsddapi.c:892:8: error: ‘struct wsdd__ResolveMatchType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘__wsdd__Hello’:
wsddapi.c:1132:13: error: ‘struct wsdd__HelloType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c:1140:1: error: ‘struct wsdd__HelloType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c:1162:10: error: ‘struct wsdd__HelloType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘__wsdd__Bye’:
wsddapi.c:1200:11: error: ‘struct wsdd__ByeType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c:1208:1: error: ‘struct wsdd__ByeType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c:1230:8: error: ‘struct wsdd__ByeType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c: In function ‘__wsdd__Resolve’:
wsddapi.c:1386:15: error: ‘struct wsdd__ResolveType’ has no member named ‘wsa5__EndpointReference’
wsddapi.c:1402:12: error: ‘struct wsdd__ResolveType’ has no member named ‘wsa5__EndpointReference'
[/code]
一下子报了这么多错误,是链接找不到wsa5__EndpointReference,这个情况一般是只声明了,没有定义才会在链接的时候报错。
通过grep查找定义,发现是因为soapStub.h第15行定义了SOAP_WSA_2005宏导致的。
[code]
#ifndef soapStub_H
#define soapStub_H
#define SOAP_WSA_200408
#define SOAP_NAMESPACE_OF_wsdd "http://schemas.xmlsoap.org/ws/2005/04/discovery"
//#define SOAP_WSA_2005 注释这一行就可以了
#define SOAP_NAMESPACE_OF_tds "http://www.onvif.org/ver10/device/wsdl"
[/code]
再次make出现了错误
[code]
gsoapapp.o:(.data+0x0): multiple definition of `namespaces'
discovery.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status
[/code]
这是因为我们使用了2个soap服务,每个sopa服务都要设置自己的命名空间见discovery.c和gsoapapp.c
soap_set_namespaces(&app->soap, namespaces);
将其中的一个名字改掉就好了,我这里改的是gsoapapp.c
soap_set_namespaces(&app->soap, namespaces);-->soap_set_namespaces(&app->soap, namespaces1);
把MediaBinding.nsmap里面的namespaces改为namespaces1问题1就彻底解决了。
问题2无法搜索到设备:
使用ONVIF Device Manager死也搜索不到设备ONVIF Device Test Tool也不行设备端提示如下:

这个Discovery明明是调通的怎么就不行了呢?翻看log/test.log里面我们发现有这些日志
[code]
stdsoap2.c(7729): malloc(20) = 0xb6401b10
stdsoap2.c(7729): malloc(16) = 0xb6401b40
stdsoap2.c(7729): malloc(24) = 0xb6400b40
wsaapi.c(989): soap_wsa_fault_subcode(faultsubcode=wsa5:MessageAddressingHeaderRequired, faultstring=A required header representing a Message Addressing Property is not present.)
stdsoap2.c(7729): malloc(76) = 0xb6401b88
[/code]
经过和第一篇那个单独的Discovery工程里面的日志对比发现是命名空间的问题。打开wsdd.nsmap把命名空间修改为下面的
[code]
#include "soapH.h"
SOAP_NMAC struct Namespace namespaces[] =
{
{"SOAP-ENV", "http://www.w3.org/2003/05/soap-envelope", "http://schemas.xmlsoap.org/soap/envelope/", NULL},
{"SOAP-ENC", "http://www.w3.org/2003/05/soap-encoding", "http://schemas.xmlsoap.org/soap/encoding/", NULL},
{"xsi", "http://www.w3.org/2001/XMLSchema-instance", "http://www.w3.org/*/XMLSchema-instance", NULL},
{"xsd", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema", NULL},
{"wsa", "http://schemas.xmlsoap.org/ws/2004/08/addressing", NULL, NULL},
{"wsdd", "http://schemas.xmlsoap.org/ws/2005/04/discovery", NULL, NULL},
{"tdn", "http://www.onvif.org/ver10/network/wsdl", NULL, NULL},
{"tds", "http://www.onvif.org/ver10/device/wsdl", NULL, NULL},
{NULL, NULL, NULL, NULL}
};
[/code]
重新编译代码(make clean && make)再执行发现可以发现设备了,这样我们就实现了自动发现设备,自动获取ONVIF的流地址了。
5.运行截图
直接运行ONVIF Device Manager程序,这次不需要再在右下角手工添加了。对于系统的标示我填了一部分。

播放视频:

6.总结
这样这个ONVIF系类的文章就算全部完成了,我们只要按照这个框架将其他的命令实现就能完整的做完ONVIF了。
这里大家看到了我们使用的ONVIF端口是8080,为什么要这个端口?这是因为我们的设备上需要用到WEB服务,而
WEB服务将80端口已经占了,不得不说这是个遗憾,目前使用gSOAP我还不清楚怎么把它和WEB整合在一起。当然
如果不借助gSOAP自己去实现ONVIF的话是可以解决的,但是那样要自己去解析xml数据那是比较繁琐的。

下载
我来回答
回答12个
时间排序
认可量排序
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
认可0
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币
Markdown 语法
- 加粗**内容**
- 斜体*内容*
- 删除线~~内容~~
- 引用> 引用内容
- 代码`代码`
- 代码块```编程语言↵代码```
- 链接[链接标题](url)
- 无序列表- 内容
- 有序列表1. 内容
- 缩进内容
- 图片
相关问答
-
2015-01-05 21:26:10
-
2017-09-05 11:49:45
-
2014-12-31 21:32:49
-
2019-09-30 18:56:47
-
2016-04-08 19:03:38
-
2017-10-26 10:15:31
-
2018-12-11 10:20:04
-
2013-06-28 22:35:45
-
2018-08-28 13:24:28
-
2015-12-18 15:45:27
-
2013-07-11 12:48:42
-
2017-11-01 10:48:13
-
2013-01-27 14:45:58
-
2019-01-22 11:49:16
-
2016-01-07 10:53:12
-
2013-07-11 12:43:07
-
2016-07-03 18:18:39
-
2020-02-16 20:43:16
-
12013-07-11 12:08:27
无更多相似问答 去提问

点击登录
-- 积分
-- E币
提问
—
收益
—
被采纳
—
我要提问
切换马甲
上一页
下一页
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
提醒
你的问题还没有最佳答案,是否结题,结题后将扣除20%的悬赏金
取消
确认
提醒
你的问题还没有最佳答案,是否结题,结题后将根据回答情况扣除相应悬赏金(1回答=1E币)
取消
确认