当前位置:   article > 正文

实现OPC UA publish/subscribe单次发送_ua_server_createevent

ua_server_createevent

     最近一直在写OPC UA publish/subscribe 模式的程序,发现程序设置好之后,数据就源源不断地发出来了。但是令人困惑的是变量值明明没有改变,数据会连续不断地重复发送,根本停不下来 。网络上也有人在抓狂,我只要一个数据就够了,不要没完没了。

      其实,OPC UA publish/subscribe 的机制与传统IT 领域的MQTT 发布/订阅机制不完全相同。MQTT 发布的信息是非周期性的消息。比如开/关灯,·某个数据的当前值等等。程序每次发送消息只能发送一个消息包。如果你需要周期性地发送数据,需要使用定时器来重复发送。

    OPC UA publish/subscribe是为了发送周期性数据而建立的通信机制。传统OT为实现如温度闭环、运动控制、机器人等控制,需要周期性的数据采集,OPC UA publish/subscribe用来解决“周期性”数据的传输问题。

       在OPC UA 协议栈中维护了一个周期性时钟,一旦这个时钟产生中断,服务器将会根据DatasetWrite 的配置,读取相关变量和事件的值,准备好Publish 的消息,从网络上发布出去。而周期是在PublishGroup 中配置的。它们以毫秒为单位。所有这些都不需要应用程序干预。这种异步周期发送的机制非常适合需要连续性采样数据的场合,比如过程控制,机器人动作控制等。

只发送一个消息的方法

        对于许多控制数据而言,多次连续发送会带来麻烦,比如开关灯的操作。虽然我们可以在订阅端做判断,过滤掉重复的数据,但是那样会增加网络的带宽。

       是否能够实现数据不连续发送呢?网络上的例子几乎都是连续发送的。我不信邪,尝试了很长一段时间,终于成功了,在此处分享给大家。

    这里的关键是Publish端要将变量值的状态改为“UA_STATUSCODE_BADNOTCONNECTED“。下面是写变量程序。

  1. void writeVariableNode( UA_Server * server ,const UA_NodeId nodeId,UA_Int32 value)
  2. {
  3. //Write a different integer value
  4. UA_Int32 val=value;
  5. UA_Variant Var;
  6. UA_Variant_init(&Var);
  7. UA_Variant_setScalar(&Var, &val, &UA_TYPES[UA_TYPES_INT32]);
  8. UA_Server_writeValue(server, nodeId, Var);
  9. // Set the status code of the value to an error code. The function
  10. //UA_Server_write provides access to the raw service. The above
  11. //UA_Server_writeValue is syntactic sugar for writing a specific node
  12. //attribute with the write service.
  13. UA_WriteValue wv;
  14. UA_WriteValue_init(&wv);
  15. wv.nodeId = nodeId;
  16. wv.attributeId = UA_ATTRIBUTEID_VALUE;
  17. wv.value.status = UA_STATUSCODE_BADNOTCONNECTED;
  18. wv.value.value = Var;
  19. wv.value.value.type=&UA_TYPES[UA_TYPES_INT32];
  20. wv.value.hasValue = true;
  21. wv.value.hasStatus = true;
  22. UA_Server_write(server, &wv);
  23. }

 另外,addDataSetWriter程序中,keyFrameCounter 改为0。否则会出现message 丢弃, 只接受keyFrame  消息 。

  1. static void
  2. addDataSetWriter(UA_Server *server) {
  3. /* We need now a DataSetWriter within the WriterGroup. This means we must
  4. * create a new DataSetWriterConfig and add call the addWriterGroup function. */
  5. UA_NodeId dataSetWriterIdent;
  6. UA_DataSetWriterConfig dataSetWriterConfig;
  7. memset(&dataSetWriterConfig, 0, sizeof(UA_DataSetWriterConfig));
  8. dataSetWriterConfig.name = UA_STRING("Demo DataSetWriter");
  9. dataSetWriterConfig.dataSetWriterId = 62542;
  10. dataSetWriterConfig.keyFrameCount = 0;//fixed by yao
  11. UA_Server_addDataSetWriter(server, writerGroupIdent, publishedDataSetIdent,
  12. &dataSetWriterConfig, &dataSetWriterIdent);
  13. }

在Publisher 端,我添加了一个线程定时发送两个变量的值。

  1. void* threadFunction(void* server)
  2. { UA_Int32 variable1=0;
  3. UA_Int32 variable2=0;
  4. UA_Variant value;
  5. UA_Variant_init(&value);
  6. while(1)
  7. {
  8. variable2=100-variable1;
  9. writeVariableNode(server,UA_NODEID_NUMERIC(1,52525),variable1);
  10. writeVariableNode(server,UA_NODEID_NUMERIC(1,52510),variable2);
  11. printf("variable1 value%d\n",variable1);
  12. variable1++;
  13. if(variable1>100) variable1=0;
  14. UA_sleep_ms(100);
  15. }
  16. }

   OPC UA 现场总线

            在这里,我们也联想到了最近提出来的OPC UA FX 现场交换总线。目前它是基于了OPC UA pub/sub 和tsn 构建的。pub/sub 模式简单,而且能够通过时间窗口实现定时发送。与tsn 完美结合在一起。

      笔者认为,只有同时实现了连续发送和单独发送两种模式,才有可能成为现场总线协议。毕竟许多的场合需要确定的单个消息传递。本次测试,为以后进一步实现OPC UA Over tsn 打下了基础。

OPC UA 的心比较大,希望未来一统天下!

    

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/80702
推荐阅读
相关标签
  

闽ICP备14008679号