Linux c++ onvif客户端开发(4): 扫描某个设备是否支持onvif

11 篇文章 0 订阅
10 篇文章 0 订阅

其实扫描单个设备和扫描多个设备用法都一样,只是将多播地址修改成某个IP地址即可。

参考https://blog.csdn.net/noevil/article/details/136175492

 定义常量

#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 (2) // socket超时时间(单秒秒)

 几个函数,没用上一篇文章的那个对象


static void *ONVIF_soap_malloc(struct soap *soap, unsigned int n) {
    void *p = NULL;

    if (n > 0) {
        p = soap_malloc(soap, n);
        memset(p, 0x00, n);
    }
    return p;
}

static struct soap *ONVIF_soap_new(int timeout) {
    struct soap *soap = soap_new(); // soap环境变量

    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;
}

static 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
}

static void ONVIF_init_header(struct soap *soap) {
    struct SOAP_ENV__Header *header = NULL;

    header = (struct SOAP_ENV__Header *)ONVIF_soap_malloc(
        soap, sizeof(struct SOAP_ENV__Header));
    soap_default_SOAP_ENV__Header(soap, header);
    header->wsa__MessageID = (char *)soap_wsa_rand_uuid(soap);
    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;

    return;
}


static void ONVIF_init_ProbeType(struct soap *soap,
                                 struct wsdd__ProbeType *probe) {
    struct wsdd__ScopesType *scope = NULL; // 用于描述查找哪类的Web服务

    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);

    return;
}

 发送消息到IP

注意这里不再使用多播地址239.255.255.250,而是替换成某个独立的IP地址。

也不需要循环去获取结果了。

timeout其实可以设置得足够小,1s都够了。

int OnvifDevice::Probe(int timeout) {
    int result = 0;
    struct soap *soap = NULL;        // soap环境变量
    struct wsdd__ProbeType req;      // 用于发送Probe消息
    struct __wsdd__ProbeMatches rep; // 用于接收Probe应答
    struct wsdd__ProbeMatchType *probeMatch;

    soap = ONVIF_soap_new(timeout);

    ONVIF_init_header(soap);          // 设置消息头描述
    ONVIF_init_ProbeType(soap, &req); // 设置寻找的设备的范围和类型

    std::string addr(std::string("soap.udp://") + ip_ + ":3702");

    // 向单播地址发送Probe消息
    result = soap_send___wsdd__Probe(soap, addr.data(), NULL, &req);
    // 开始循环接收设备发送过来的消息
    if (SOAP_OK == result) {
        memset(&rep, 0x00, sizeof(rep));
        result = soap_recv___wsdd__ProbeMatches(soap, &rep);
        if (SOAP_OK == result) {
            if (rep.wsdd__ProbeMatches) {
                for (int i = 0; i < rep.wsdd__ProbeMatches->__sizeProbeMatch;
                     i++) {
                    probeMatch = rep.wsdd__ProbeMatches->ProbeMatch + i;
                    xaddr_ = probeMatch->XAddrs;
                }
            }
        }
    }

    ONVIF_soap_delete(soap);

    return result;
}

  • 12
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值