onvif学习笔记8:最近写的一个ONVIF客户端的心得小结

本文分享了作者利用业余时间使用MFC开发ONVIF客户端的过程,涉及语言选择、环境搭建、鉴权实现等内容,并针对遇到的问题如中文乱码等提供了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近,利用业余时间编写一个简单的ONVIF客户端MFC程序,这里记录一下过程。

语言选择

在之前调查过,有用QT实现的,有用python实现的,虽然正在学python,无奈才看了3天的书,没自信去搞。最后还是使用自己熟悉了好多年的MFC,但没有找到MFC的代码,只好自己写一个了。

onvif客户端架构代码

从2013年首次接触onvif的恐惧,到去年对onvif熟知,都是服务端的代码。而客户端的代码却没接触过。不过用gsoap生成框架代码也简单。由于自己的求知欲较强,最后生成了面向对象的版本(即每种服务分别作为不同类)和不面向对象的版本(即所有接口均实现在一个文件),在两者难取舍情况下,不得已,做了2个版本。在Linux下使用面向对象的,而在MFC中使用C版本的。

VS2010搭建环境

onvif的鉴权,要使用到openssl,一开始我使用mingw编译openssl,但放到vs2010编译,出现很多未定义引用的错误,包括如_chkstk、___umoddi3这些没见过的函数,还搜索VS配置的/MD、/MDd、/MT、/MTd的资料,但还是一筹莫展。最后用vs编译器来编译openssl,结果一切正常了。
但是,gsoap生成的代码有部分是用linux的接口,如usleep,根据错误来修改,也不是十分困难的事。在MFC中使用,要将所有.c文件改为.cpp,还得在每个实现文件包含stdafx.h。

ONVIF鉴权

ONVIF的鉴权功能,网上资料比较少,大部分是基于WS-Username token的方式,而http digest较少。后来无意间搜索代码才找到使用方式。

ONVIF中文乱码

在实现OSD叠加功能时,发现中文有乱码,即使我将字符转换成UTF8但还是不行。后面跟踪soap结构体,发现xml协议中的内容是正常的UTF8(我使用hexdump同样的字符来对比二进制)。但到反序列化转换成结构体时,就出现乱码了,于是确认ONVIF代码本身编码存在问题。后来上网查了好久,发现可以将ONVIF设置为UTF编码,调用soap_set_mode(m_soap, SOAP_C_UTFSTRING); 即可。

下面简单描述从设备发现到叠加OSD的过程:
组播搜索设备(或者直接指定IP发probe);
获取设备提供的service——主要知道media的地址;
获取profile;
获取OSDOptions,知道设备OSD提供的特性及限制,不过我发现有个OSD选项被VS优化掉了,但在Linux下却没问题;
调用CreateOSD创建一个OSD,设备会返回一个OSD token,这个token就是下面要使用的;
使用SetOSD修改OSD内容、坐标;
调用DeleteOSD删除OSD。

ONVIF编码十分繁琐,需要一定的耐心和平常心对待。
建议参考gsoap生成的代码,比如soapstub.h头文件就定义了各种结构(类)。另外也要参考官网标准手册,里面对命令功能、返回值均有说明。至于每个结构体详细定义,可以参考官网提供的WSDL信息文档:http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl、http://www.onvif.org/onvif/ver10/media/wsdl/media.wsdl。
最后,抓包分析也是一个很好的方法,特别有且于了解未鉴权、鉴权的细节。

下一步计划:参考onvif测试工具界面、功能,做一个比较完善的ONVIF客户端(最好能集调试、视频查看为一体的程序)。以便深入学习ONVIF。


李迟 2016.6.7 周二 夜

### 使用 ONVIF 协议修改摄像头参数的方法 #### 创建 ONVIF 摄像头对象 为了使用 ONVIF 协议来修改摄像头参数,首先需要设置摄像头的连接信息,包括 IP 地址、端口号、用户名和密码。接着创建 `ONVIFCamera` 对象并更新其地址。 ```python from onvif import ONVIFCamera mycam = ONVIFCamera('192.168.0.1', 80, 'admin', 'password') ``` #### 获取设备管理服务 通过获取设备管理服务 (`DeviceManagement`) 来访问与配置相关的功能接口。 ```python device_mgmt = mycam.create_devicemgmt_service() ``` #### 修改图像设置 要调整摄像头的成像属性,比如亮度、对比度等,可以通过调用相应的 API 接口完成。下面是一个具体的例子展示如何更改这些参数[^4]: ```python # 定义新的图像设定结构体 new_image_setting = { "Brightness": 0.7, "ColorSaturation": 0.5, "Contrast": 0.6, } media_service = mycam.create_media_service() imaging_service = mycam.create_imaging_service() profiles = media_service.GetProfiles()[0] video_source_token = profiles.VideoSourceConfiguration.SourceToken request = imaging_service.create_type('SetImagingSettings') request.VideoSourceToken = video_source_token for key in new_image_setting.keys(): setattr(request.ImagingSettings, key, new_image_setting[key]) response = imaging_service.SetImagingSettings(request) print(response) ``` 此代码片段展示了如何利用 Python 中的 ONVIF 库去改变指定摄像头的图像质量选项。需要注意的是,在实际应用中可能还需要处理异常情况以及验证输入的有效性等问题。 #### 控制变焦和其他 PTZ 功能 对于想要控制摄像头的 Pan/Tilt/Zoom(PTZ),则需先获得 PTZ 服务实例,之后便能发送命令给目标设备执行特定动作[^1]。 ```python ptz_service = mycam.create_ptz_service() status = ptz_service.GetStatus({'ProfileToken': profile.token}) continuous_move_request = ptz_service.create_type('ContinuousMove') continuous_move_request.ProfileToken = status.Position token continuous_move_request.Velocity.Zoom.x = 1.0 # 放大操作 ptz_service.ContinuousMove(continuous_move_request) ``` 上述脚本实现了连续移动镜头至最大放大倍率的功能;同样地,也可以按照需求编其他类型的运动指令。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值