186 lines
7.6 KiB
C++
186 lines
7.6 KiB
C++
|
#include <assert.h>
|
|||
|
#include "soapH.h"
|
|||
|
#include "wsdd.nsmap"
|
|||
|
#include "soapStub.h"
|
|||
|
|
|||
|
#include <iostream>
|
|||
|
|
|||
|
#define SOAP_ASSERT assert
|
|||
|
#define SOAP_DBGLOG printf
|
|||
|
#define SOAP_DBGERR printf
|
|||
|
|
|||
|
#define SOAP_TO "urn:schemas-xmlsoap-org:ws:2005:04:discovery"
|
|||
|
#define SOAP_ACTION "http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe"
|
|||
|
|
|||
|
#define SOAP_MCAST_ADDR "soap.udp://239.255.255.250:3702" // onvif规定的组播地址
|
|||
|
|
|||
|
#define SOAP_ITEM "" // 寻找的设备范围
|
|||
|
#define SOAP_TYPES "dn:NetworkVideoTransmitter" // 寻找的设备类型
|
|||
|
|
|||
|
#define SOAP_SOCK_TIMEOUT (10) // socket超时时间(单秒秒)
|
|||
|
|
|||
|
void soap_perror(struct soap *soap, const char *str)
|
|||
|
{
|
|||
|
if (nullptr == str) {
|
|||
|
SOAP_DBGERR("[soap] error: %d, %s, %s\n", soap->error, *soap_faultcode(soap), *soap_faultstring(soap));
|
|||
|
} else {
|
|||
|
SOAP_DBGERR("[soap] %s error: %d, %s, %s\n", str, soap->error, *soap_faultcode(soap), *soap_faultstring(soap));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void* ONVIF_soap_malloc(struct soap *soap, unsigned int n)
|
|||
|
{
|
|||
|
void *p = nullptr;
|
|||
|
|
|||
|
if (n > 0) {
|
|||
|
p = soap_malloc(soap, n);
|
|||
|
SOAP_ASSERT(nullptr != p);
|
|||
|
memset(p, 0x00 ,n);
|
|||
|
}
|
|||
|
return p;
|
|||
|
}
|
|||
|
|
|||
|
struct soap *ONVIF_soap_new(int timeout)
|
|||
|
{
|
|||
|
struct soap *soap = nullptr; // soap环境变量
|
|||
|
|
|||
|
SOAP_ASSERT(nullptr != (soap = soap_new()));
|
|||
|
|
|||
|
soap_set_namespaces(soap, namespaces); // 设置soap的namespaces
|
|||
|
soap->recv_timeout = timeout; // 设置超时(超过指定时间没有数据就退出)
|
|||
|
soap->send_timeout = timeout;
|
|||
|
soap->connect_timeout = timeout;
|
|||
|
|
|||
|
#if defined(__linux__) || defined(__linux) // 参考https://www.genivia.com/dev.html#client-c的修改:
|
|||
|
soap->socket_flags = MSG_NOSIGNAL; // To prevent connection reset errors
|
|||
|
#endif
|
|||
|
|
|||
|
soap_set_mode(soap, SOAP_C_UTFSTRING); // 设置为UTF-8编码,否则叠加中文OSD会乱码
|
|||
|
|
|||
|
return soap;
|
|||
|
}
|
|||
|
|
|||
|
void ONVIF_soap_delete(struct soap *soap)
|
|||
|
{
|
|||
|
soap_destroy(soap); // remove deserialized class instances (C++ only)
|
|||
|
soap_end(soap); // Clean up deserialized data (except class instances) and temporary data
|
|||
|
soap_done(soap); // Reset, close communications, and remove callbacks
|
|||
|
soap_free(soap); // Reset and deallocate the context created with soap_new or soap_copy
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************
|
|||
|
**函数:ONVIF_init_header
|
|||
|
**功能:初始化soap描述消息头
|
|||
|
**参数:
|
|||
|
[in] soap - soap环境变量
|
|||
|
**返回:无
|
|||
|
**备注:
|
|||
|
1). 在本函数内部通过ONVIF_soap_malloc分配的内存,将在ONVIF_soap_delete中被释放
|
|||
|
************************************************************************/
|
|||
|
void ONVIF_init_header(struct soap *soap)
|
|||
|
{
|
|||
|
struct SOAP_ENV__Header *header = nullptr;
|
|||
|
|
|||
|
SOAP_ASSERT(nullptr != soap);
|
|||
|
|
|||
|
header = (struct SOAP_ENV__Header *)ONVIF_soap_malloc(soap, sizeof(struct SOAP_ENV__Header));
|
|||
|
soap_default_SOAP_ENV__Header(soap, header);
|
|||
|
header->wsa__MessageID = "shsuishsihsishsishsuisbjshsusisuisusi";
|
|||
|
header->wsa__To = (char*)ONVIF_soap_malloc(soap, strlen(SOAP_TO) + 1);
|
|||
|
header->wsa__Action = (char*)ONVIF_soap_malloc(soap, strlen(SOAP_ACTION) + 1);
|
|||
|
strcpy(header->wsa__To, SOAP_TO);
|
|||
|
strcpy(header->wsa__Action, SOAP_ACTION);
|
|||
|
soap->header = header;
|
|||
|
}
|
|||
|
|
|||
|
/************************************************************************
|
|||
|
**函数:ONVIF_init_ProbeType
|
|||
|
**功能:初始化探测设备的范围和类型
|
|||
|
**参数:
|
|||
|
[in] soap - soap环境变量
|
|||
|
[out] probe - 填充要探测的设备范围和类型
|
|||
|
**返回:
|
|||
|
0表明探测到,非0表明未探测到
|
|||
|
**备注:
|
|||
|
1). 在本函数内部通过ONVIF_soap_malloc分配的内存,将在ONVIF_soap_delete中被释放
|
|||
|
************************************************************************/
|
|||
|
void ONVIF_init_ProbeType(struct soap *soap, struct wsdd__ProbeType *probe)
|
|||
|
{
|
|||
|
struct wsdd__ScopesType *scope = nullptr; // 用于描述查找哪类的Web服务
|
|||
|
|
|||
|
SOAP_ASSERT(nullptr != soap);
|
|||
|
SOAP_ASSERT(nullptr != probe);
|
|||
|
|
|||
|
scope = (struct wsdd__ScopesType *)ONVIF_soap_malloc(soap, sizeof(struct wsdd__ScopesType));
|
|||
|
soap_default_wsdd__ScopesType(soap, scope); // 设置寻找设备的范围
|
|||
|
scope->__item = (char*)ONVIF_soap_malloc(soap, strlen(SOAP_ITEM) + 1);
|
|||
|
strcpy(scope->__item, SOAP_ITEM);
|
|||
|
|
|||
|
memset(probe, 0x00, sizeof(struct wsdd__ProbeType));
|
|||
|
soap_default_wsdd__ProbeType(soap, probe);
|
|||
|
probe->Scopes = scope;
|
|||
|
probe->Types = (char*)ONVIF_soap_malloc(soap, strlen(SOAP_TYPES) + 1); // 设置寻找设备的类型
|
|||
|
strcpy(probe->Types, SOAP_TYPES);
|
|||
|
}
|
|||
|
|
|||
|
void ONVIF_DetectDevice(void (*cb)(char *DeviceXAddr))
|
|||
|
{
|
|||
|
int i;
|
|||
|
int result = 0;
|
|||
|
unsigned int count = 0; // 搜索到的设备个数
|
|||
|
struct soap *soap = nullptr; // soap环境变量
|
|||
|
struct wsdd__ProbeType req; // 用于发送Probe消息
|
|||
|
struct __wsdd__ProbeMatches rep; // 用于接收Probe应答
|
|||
|
struct wsdd__ProbeMatchType *probeMatch;
|
|||
|
|
|||
|
SOAP_ASSERT(nullptr != (soap = ONVIF_soap_new(SOAP_SOCK_TIMEOUT)));
|
|||
|
|
|||
|
ONVIF_init_header(soap); // 设置消息头描述
|
|||
|
ONVIF_init_ProbeType(soap, &req); // 设置寻找的设备的范围和类型
|
|||
|
result = soap_send___wsdd__Probe(soap, SOAP_MCAST_ADDR, nullptr, &req); // 向组播地址广播Probe消息
|
|||
|
while (SOAP_OK == result) // 开始循环接收设备发送过来的消息
|
|||
|
{
|
|||
|
memset(&rep, 0x00, sizeof(rep));
|
|||
|
result = soap_recv___wsdd__ProbeMatches(soap, &rep);
|
|||
|
if (SOAP_OK == result) {
|
|||
|
if (soap->error) {
|
|||
|
soap_perror(soap, "ProbeMatches");
|
|||
|
} else { // 成功接收到设备的应答消息
|
|||
|
printf("__sizeProbeMatch:%d\n",rep.wsdd__ProbeMatches->__sizeProbeMatch);
|
|||
|
|
|||
|
if (nullptr != rep.wsdd__ProbeMatches) {
|
|||
|
count += rep.wsdd__ProbeMatches->__sizeProbeMatch;
|
|||
|
for(i = 0; i < rep.wsdd__ProbeMatches->__sizeProbeMatch; i++) {
|
|||
|
probeMatch = rep.wsdd__ProbeMatches->ProbeMatch + i;
|
|||
|
if (nullptr != cb) {
|
|||
|
cb(probeMatch->XAddrs); // 使用设备服务地址执行函数回调
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
} else if (soap->error) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
SOAP_DBGLOG("\ndetect end! It has detected %d devices!\n", count);
|
|||
|
|
|||
|
if (nullptr != soap) {
|
|||
|
ONVIF_soap_delete(soap);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
int main(int argc, char **argv)
|
|||
|
{
|
|||
|
printf("start\n");
|
|||
|
std::cout << "start " << std::endl;
|
|||
|
ONVIF_DetectDevice(nullptr);
|
|||
|
printf("end\n");
|
|||
|
std::cout << "end " << std::endl;
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|