天天看点

ONVIF系列——c++使用gsoap onvif编写onvif代码并控制海康摄像头1 环境要求编译链接

最近的工作需要对海康摄像头进行操作,同时环境是jetson nano的ubuntu18.04环境,海康sdk功能是比较多的,但是在类似于嵌入式的jetson nano板子上,海康sdk是不支持的,因此需要使用其他的库,比如说onvif,如果想了解onvif,请看ONVIF系列——Onvif协议介绍,如果想了解python控制onvif,请看ONVIF系列——python操控onvif.

对于c++的onvif库,我将在网上找的资料附在末尾,同时将我实现的gsoap-onvif附在文章末尾。

这篇文章将不会讲解gsoap代码是怎么来的,而是直接介绍onvif的c++代码如何实现,让你拿来就能用,直接编译运行。

1 环境要求

该代码是在jetson nano ubuntu 18.04,jetpack version为4.4.1上实现的,并成功运行。

  1. 一台jetson nano板子(或者ubuntu 18.04系统的linux主机)
  2. github库gsoap-onvif

请按照gsoap-onvif的readme指示的去操作。我也会在下面进行再次叙述。

安装openssl

gsoap-onvif需要用到openssl。当然,在Jetson 系列——jetson nano Ubuntu18.04安装Openssl-1.1.1中有详细的openssl介绍,虽然是1.1.1版本,但是大差不差。如果遇到安装的报错,或者安装完以后编译有报错,可以到这篇文章里找找看看有没有是我遇到的问题。

# download openssl from web 
wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2l.tar.gz
tar -xzvf openssl-1.0.2l.tar.gz
cd openssl-1.0.2l
sudo ./config
sudo make 
sudo make test # you can test it with this line 
sudo make install 
# check openssl version
openssl version
           

这里需要注意的是,openssl的版本是1.0.2l,最好按照要求得来,因为如果版本过高,可能有些代码在编译的过程中会报错。

我们首先从官网上下载openssl:

wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2l.tar.gz
           

然后解压,并进入到解压后的文件夹中,下载的路径和解压的路径请随意选择:

tar -xzvf openssl-1.0.2l.tar.gz
cd openssl-1.0.2l
           

下面是安装openssl的过程,请注意,在安装的过程中,最好使用sudo权限,因为需要在/usr/bin等地方创建文件或者文件夹。

sudo ./config
sudo make 
sudo make test # you can test it with this line 
sudo make install 
           

当安装完成以后,请输入

openssl version
           

查看openssl的版本。如果查看成功,并且版本号和我们安装到版本号相同,那么就安装成功了。

安装libssl1.0

sudo apt-get install libssl1.0-dev
           

当完成上面的步骤时,基本环境就算是安装好了,当然,我这里默认是安装时了opencv的,并且opencv的版本是4.1.1。

编译链接

一次封装

这个项目有两个可以编译链接的地方,你可以试试对gsoap-onvif进行一次封装的代码.

首先进入factory文件夹,并建立一个

build

文件夹

cd factory
mkdir build
           

然后进行编译链接

cmake ..
make 
           

你可以在

./factory/test/test_analyse.cpp

中找到测试的代码,类似的代码如下:

#include <chrono>
#include <iostream>
#include <sstream> 
#include "glog/logging.h"
#include "OnvifClientDevice.hpp"
#include "OnvifClientPTZ.hpp"
#include "OnvifClientMedia.hpp"

using namespace std;

int main(int argc, const char *argv[]) {
	
    std::string url = "192.168.66.64";
	std::string name = "admin";
	std::string password = "wst123456";
	OnvifClientPTZ *PTZ = new OnvifClientPTZ(url, name, password, true);
	OnvifClientMedia *Media = new OnvifClientMedia(url, name, password, true);
	std::vector<_ocp_Profile> get_profilesResponse;
	Media->getProfiles(get_profilesResponse);
	PTZ->gotoPreset(get_profilesResponse[0].profileToken,3,0.5);
	PTZ->getPresets(get_profilesResponse[0].profileToken);
    return 0;
}
           

可以看到,本项目调用了OnvifClientDevice,OnvifClientPTZ,OnvifClientMedia三个文件,这三个文件是对gsoap-onvif代码的一次封装,具体的封装方法,你可以到

./factory/3rdparty/ssigonvif/ssig/

中看到源代码。

那么本项目的使用风格就是这样。先声明实例化PTZ和Media

OnvifClientPTZ *PTZ = new OnvifClientPTZ(url, name, password, true);
OnvifClientMedia *Media = new OnvifClientMedia(url, name, password, true);
           

注意实例化的时候要输入该摄像头的url,name,passwd。

随后,便可以调用这个类的方法,目前日常所需要的onvif操纵摄像头的方法,都有实现,如果没有,你也可以仿照的已经实现的方法进行二次开发。

例如调用摄像头到某个预置位:

PTZ->gotoPreset(get_profilesResponse[0].profileToken,3,0.5);
           

注意这里第一个输入的来源,是需要从Media中获取配置的参数

std::vector<_ocp_Profile> get_profilesResponse;
Media->getProfiles(get_profilesResponse);
           

然后将参数的返回token传入到接口中,因为onvif要进行认证,只用这样才能正常调用和控制,否则会出现没有权限的情况。

又如stop,move等操作

PTZ->continuousMove(get_profilesResponse[0].profileToken, 0.5, 0, 0);
//sleep(2);
PTZ->stop(get_profilesResponse[0].profileToken, 0, 0);
PTZ->relativeMove(get_profilesResponse[0].profileToken, 0.0, 0.0, 0.0, 0.0, 0.5, 1);
           

对于ptz控制,media的config获取或者device的config获取,都可以看对应文件下的函数实现,然后直接调用即可。

比如打开OnvifClientPTZ.hpp,可以看到实现了下面的方法,setHomePosition的设置初始位置,goToHomePosition的复位,panLeft的向左多少度等操作,可以根据提示进行使用。

void setHomePosition(std::string profileToken);
void goToHomePosition(std::string profileToken);
// pan to the left n Degress
void panLeft(std::string profileToken, int nDegrees);
// pan to the right n Degrees
void panRight(std::string profileToken, int nDegrees);
void tiltDown(std::string profileToken, int nDegrees);
void tiltUp(std::string profileToken, int nDegrees);
           

二次封装

也有一个二次封装的代码,即

/src

文件夹下的

teacher.cpp

,将onvif中的ptz和media等封装成了一个类,需要用时实例化就好,这可以凭自己的喜好使用,并添加代码。

github代码:https://github.com/RichardoMrMu/gsoap-onvif

参考资料:

  1. ONVIF协议网络摄像机(IPC)客户端程序开发(1):专栏开篇
  2. 基于ONVIF协议的摄像头开发总结
  3. ONVIF协议开发之网络摄像头云台控制(C版)
  4. onvif专栏