如何在gSoap中实现ONVIF CreatePullPointSubscription事件过滤器?
问题
我们基于Yocto Kirkstone提供的gSoap 2.8.106,实现符合ONVIF S和T Profile标准的服务,其中T Profile要求支持事件过滤(例如测试项EVENT-2-1-26-v17.06中"PULLMESSAGES过滤器主题子树"的要求)。
在EventBindingService::CreatePullPointSubscription方法中,会收到_tev__CreatePullPointSubscription类型指针,其Filter成员指向wsnt__FilterType:
/* complex XML schema type 'tev:CreatePullPointSubscription': */ class SOAP_CMAC _tev__CreatePullPointSubscription { public: /// Optional element 'tev:Filter' of XML schema type 'wsnt:FilterType' wsnt__FilterType *Filter; };
但默认生成的wsnt__FilterType仅包含__any成员:
/* complex XML schema type 'wsnt:FilterType': */ class SOAP_CMAC wsnt__FilterType : public soap_dom_element { public: /// XML DOM element node graph std::vector<struct soap_dom_element> __any; };
根据gSOAP官方文档,我们尝试修改typemap.dat添加扩展成员:
wsnt__FilterType = $ wsnt__TopicExpressionType *wsnt__TopicExpression;
修改后wsnt__FilterType新增了wsnt__TopicExpression成员,但仅能读取Dialect属性,无法获取完整过滤细节。
需解决两个问题:
- 如何读取过滤器的完整细节?
- 读取过滤规则后,是否有现成过滤逻辑可复用,还是需从零开发?
回答
一、读取过滤器完整细节的方法
完善typemap.dat的结构映射
仅添加wsnt__TopicExpression不足以覆盖所有过滤元素,需将wsnt:FilterType包含的所有子元素都映射到结构体成员中。ONVIF标准中wsnt:FilterType包含wsnt:TopicExpression、wsnt:MessageContent、wsnt:ProducerReference等子元素,正确的typemap规则如下:wsnt__FilterType = struct { wsnt__TopicExpressionType *TopicExpression; wsnt__MessageContentExpressionType *MessageContent; wsnt__ProducerReferenceExpressionType *ProducerReference; };同时,默认生成的
wsnt__TopicExpressionType通常只有Dialect属性,需补充文本内容字段的映射:wsnt__TopicExpressionType = $ xsd__string *__value; xsd__anyURI Dialect;重新生成代码后,
wsnt__FilterType的成员就能同时获取过滤规则的属性和文本内容。直接解析__any成员的DOM节点
若不想修改typemap,可直接遍历wsnt__FilterType中的__any向量,利用gSOAP提供的DOM操作API(如soap_element_tag、soap_element_attr、soap_element_value等),手动解析每个节点的标签、属性和文本内容,提取完整过滤细节。
二、过滤逻辑的实现
ONVIF事件过滤没有通用的现成实现可直接复用,因为不同设备的事件主题结构、内容格式差异较大,需结合自身设备的事件体系开发:
- 先明确自身设备支持的事件主题树结构(例如ONVIF定义的
tns1:Device/System/Event这类主题路径); - 根据
TopicExpression中的Dialect类型实现匹配逻辑:- 若为
http://docs.oasis-open.org/wsn/t-1/TopicExpression/Concrete方言,需匹配完全一致的主题路径; - 若为
http://docs.oasis-open.org/wsn/t-1/TopicExpression/Full方言,需支持*、//等通配符的路径匹配;
- 若为
- 若涉及
MessageContent过滤,还要解析事件消息的内容字段,实现字段级的条件匹配。
开发完成后,可参考ONVIF官方的EVENT-2系列测试项验证过滤逻辑,确保符合T Profile的要求。
内容的提问来源于stack exchange,提问作者parsley72

