一、获取并编译gsoap
- 下载gsoap
- 环境准备
sudo apt-get install flex bison libssl-dev unzip zlib1g-dev ffmpeg
- 编译安装
unzip gsoap_2.8.*.zip
cd gsoap-2.8
./configure --prefix=PREFIX
make
sudo make install
二、编译生成onvif core lib 相关库
- 新建soap目录,从gsoap-2.8/gsoap拷贝相关文件到soap目录
stdsoap2.cpp - from "gsoap" folder
duration.c - from "gsoap/custom" folder
stlvector.h- from "gsoap" folder
stdsoap2.h- from "gsoap" folder
duration.h- from "gsoap/custom" folder
将duartion.c 改为 duartion.cpp c++编译需要
duration.cpp 改 #invlude<soapH.h> 为 #include "onvifH.h",如果你用了"soapcpp2 -p onvif"那头文件将是onvifH.h命名
- onvif core lib profile包含三个库 OnvifDeviceLib(设备信息) OnvifDiscoveryLib(设备发现) OnvifEventLib(事件)
- OnvifDeviceLib库生成
//生成web service 远程调用接口头文件
wsdl2h -t gsoap-2.8/gsoap/typemap.dat -o rcx.h http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl
//生成需要部署实现的c++代码接口
soapcpp2 -p onvifdevice -n -j -L -I gsoap-2.8/gsoap/import -x rcx.h
//生成文件如下
duration.cpp onvifdeviceC.cpp onvifdeviceDeviceBindingProxy.h onvifdeviceDeviceBindingService.h onvifdevice.nsmap stdsoap2.cpp stlvector.h
duration.h onvifdeviceDeviceBindingProxy.cpp onvifdeviceDeviceBindingService.cpp onvifdeviceH.h onvifdeviceStub.h stdsoap2.h
目录结构如下:
OnvifDeviceLib/
├── onvif
│ └── deviceserviceimplement.cpp
├── soap
│ ├── duration.cpp
│ ├── duration.h
│ ├── onvifdeviceC.cpp
│ ├── onvifdeviceDeviceBindingProxy.cpp
│ ├── onvifdeviceDeviceBindingProxy.h
│ ├── onvifdeviceDeviceBindingService.cpp
│ ├── onvifdeviceDeviceBindingService.h
│ ├── onvifdeviceH.h
│ ├── onvifdevice.nsmap
│ ├── onvifdeviceStub.h
│ ├── stdsoap2.cpp
│ ├── stdsoap2.h
│ └── stlvector.h
我们需要实现deviceserviceimplement.cpp,代码示例如下:
#include "soap/onvifdeviceDeviceBindingService.h" //这个是我们需要实现函数接口定义的头文件
/// Web service operation 'GetServices' (returns error code or SOAP_OK) 获取服务端信息接口
int DeviceBindingService::GetServices(_devicews__GetServices *devicews__GetServices, _devicews__GetServicesResponse &devicews__GetServicesResponse) {
//service Device 设备信息服务
devicews__Service * serviceDevice = new devicews__Service();
// service1->Capabilities = new _devicews__Service_Capabilities; //这个注释是因为这个是可选项
// service1->Capabilities->__any = "adsadadad";
serviceDevice->Namespace = "http://www.onvif.org/ver10/device/wsdl";
serviceDevice->Version = new tt__OnvifVersion();
serviceDevice->Version->Major = 2;
serviceDevice->Version->Minor = 42;
serviceDevice->XAddr = "192.168.1.10";
devicews__GetServicesResponse.Service.push_back(serviceDevice);
//service Media 媒体服务
devicews__Service * serviceMedia = new devicews__Service();
// service1->Capabilities = new _devicews__Service_Capabilities;
// service1->Capabilities->__any = "adsadadad";
serviceMedia->Namespace = "http://www.onvif.org/ver10/media/wsdl";
serviceMedia->Version = new tt__OnvifVersion();
serviceMedia->Version->Major = 2;
serviceMedia->Version->Minor = 42;
serviceMedia->XAddr = "192.168.1.10";
devicews__GetServicesResponse.Service.push_back(serviceMedia);
//service Event 事件服务
devicews__Service * serviceEvent = new devicews__Service();
// service1->Capabilities = new _devicews__Service_Capabilities;
// service1->Capabilities->__any = "adsadadad";
serviceEvent->Namespace = "http://www.onvif.org/ver10/events/wsdl";
serviceEvent->Version = new tt__OnvifVersion();
serviceEvent->Version->Major = 2;
serviceEvent->Version->Minor = 42;
serviceEvent->XAddr = "192.168.1.10";
devicews__GetServicesResponse.Service.push_back(serviceEvent);
//service PTZ ptz服务
devicews__Service * servicePTZ = new devicews__Service();
// service1->Capabilities = new _devicews__Service_Capabilities;
// service1->Capabilities->__any = "adsadadad";
servicePTZ->Namespace = "http://www.onvif.org/ver20/ptz/wsdl";
servicePTZ->Version = new tt__OnvifVersion();
servicePTZ->Version->Major = 2;
servicePTZ->Version->Minor = 42;
servicePTZ->XAddr = "192.168.1.10";
devicews__GetServicesResponse.Service.push_back(servicePTZ);
//service Imaging 图片服务
devicews__Service * serviceImaging = new devicews__Service();
// service1->Capabilities = new _devicews__Service_Capabilities;
// service1->Capabilities->__any = "adsadadad";
serviceImaging->Namespace = "http://www.onvif.org/ver20/imaging/wsdl";
serviceImaging->Version = new tt__OnvifVersion();
serviceImaging->Version->Major = 2;
serviceImaging->Version->Minor = 42;
serviceImaging->XAddr = "192.168.1.10";
devicews__GetServicesResponse.Service.push_back(serviceImaging);
return SOAP_OK;
}
/// Web service operation 'GetDeviceInformation' (returns error code or SOAP_OK) 获取设备信息接口
int DeviceBindingService::GetDeviceInformation(_devicews__GetDeviceInformation *devicews__GetDeviceInformation, _devicews__GetDeviceInformationResponse &devicews__GetDeviceInformationResponse) {
devicews__GetDeviceInformationResponse.FirmwareVersion = "0.1";
devicews__GetDeviceInformationResponse.HardwareId = "1";
devicews__GetDeviceInformationResponse.Manufacturer = "This is sample onvif server";
devicews__GetDeviceInformationResponse.Model = "2";
devicews__GetDeviceInformationResponse.SerialNumber = "100000";
return SOAP_OK;
}
测试的工具为ONVIF Device Test Tool 17.06
测试该项功能集成后的示例为:
三、接收协议请求后的应答过程
过程为:创建gsoap 实例,等待请求,匹配请求,做出应答
代码示例:
设备发现过程将在下一篇介绍,设备发现会将服务器ip和端口告知客户端。
故如下例子将监听改端口,后获取请求并匹配协议请求接口。
#include "soap/wsddapi.h"
int main()
{
//创建soap
struct soap *soap = soap_new();
//绑定监听端口和soap
soap_bind(soap, NULL, tcpPort, 100);
//创建设备信息服务
DeviceBindingService *sw;
sw = new DeviceBindingService(soap);
//监听并接收请求
while(true){
soap_accept(soap); //slect 等待请求
if (soap_begin_serve(soap)) //server未创建
//... error
soap_stream_fault(soap, std::cerr);
if(sw->dispatch() == SOAP_NO_METHOD)
{
//匹配不成功
printf("Method fault \n");
fflush(stdout);
soap_stream_fault(soap, std::cerr);
soap_closesock(soap);
}
printf("loop end \n");
fflush(stdout);
soap_destroy(soap); //断开连接,http为短连接,接着进行监听。
}
delete sw;
soap_end(soap);
soap_free(soap);
}
调用过程如下:
soap_accept(soap); //slect 等待请求 接收请求
sw->dispatch() //匹配请求
DeviceBindingService::dispatch(struct soap* soap)
if (!soap_match_tag(soap, soap->tag, "devicews:GetServices"))
return serve___devicews__GetServices(soap, this);
if (!soap_match_tag(soap, soap->tag, "devicews:GetDeviceInformation"))
return serve___devicews__GetDeviceInformation(soap, this);
service->GetDeviceInformation()
DeviceBindingService::GetDeviceInformation()//最终调用到这里,这个是由我们实现的函数。
有什么疑问可以提出,然后有想了解更多的请给我留言,后续可以更新大家较为关心的内容。