概述
PubSub在OPC UA应用程序中分为Publishers(发布者)和Subscribers(订阅者)。发布者是数据的来源,订阅者使用这些数据。PubSub中的通信是基于消息的,Publishers将消息发送给面向消息的中间件,PubSub支持两种不同的消息中间件变体,broker-less和broker-based两种形式。broker-less面向消息的中间件是能够路由基于数据报的消息的网络基础设备,Publishers和Subscribers使用数据报协议,如UDP;broker-based面向消息的中间件是一个消息代理,Publishers和Subscribers使用标准的消息传递协议,如AMQP或MQTT代理。
基于UDP的发布订阅
-
编译open62541
CMake中勾选对应的UA_ENABLE_ALALGAMATION和UA_ENABLE_PUBSUB选项,如图所示

编译生成的工程后能够得到对应的.h和.c文件

将其添加进我们工程中能正常使用了。本例程用的是没有勾选UA_ENABLE_AMALGAMATION选项,即使用.h和.lib的方式去进行使用的。 -
Publish端
这里以tutorial_pubsub_publish.c中内容来讲述如何进行发布,代码如下,有部分修改。
#include <open62541/plugin/log_stdout.h>
#include <open62541/plugin/pubsub_ethernet.h>
#include <open62541/plugin/pubsub_udp.h>
#include <open62541/server.h>
#include <open62541/server_config_default.h>
UA_NodeId connectionIdent, publishedDataSetIdent, writerGroupIdent;
UA_NodeId connectionIdentEx, publishedDataSetIdentEx, writerGroupIdentEx;
UA_NodeId myIntegerNodeId, myIntegerNodeIdEx;
static void
addPubSubConnection(UA_Server *server, UA_String *transportProfile,
UA_NetworkAddressUrlDataType *networkAddressUrl){
/* Details about the connection configuration and handling are located
* in the pubsub connection tutorial */
UA_PubSubConnectionConfig connectionConfig;
memset(&connectionConfig, 0, sizeof(connectionConfig));
connectionConfig.name = UA_STRING("UADP Connection 1");
connectionConfig.transportProfileUri = *transportProfile;
connectionConfig.enabled = UA_TRUE;
UA_Variant_setScalar(&connectionConfig.address, networkAddressUrl,
&UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
/* Changed to static publisherId from random generation to identify
* the publisher on Subscriber side */
connectionConfig.publisherId.numeric = 2234;
UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdent);
}
static void
addPubSubConnectionEx(UA_Server *server, UA_String *transportProfile,
UA_NetworkAddressUrlDataType *networkAddressUrl){
/* Details about the connection configuration and handling are located
* in the pubsub connection tutorial */
UA_PubSubConnectionConfig connectionConfig;
memset(&connectionConfig, 0, sizeof(connectionConfig));
connectionConfig.name = UA_STRING("UADP Connection 2");
connectionConfig.transportProfileUri = *transportProfile;
connectionConfig.enabled = UA_TRUE;
UA_Variant_setScalar(&connectionConfig.address, networkAddressUrl,
&UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
/* Changed to static publisherId from random generation to identify
* the publisher on Subscriber side */
connectionConfig.publisherId.numeric = 2234;
UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdentEx);
}
static void
addPublishedDataSet(UA_Server *server) {
/* The PublishedDataSetConfig contains all necessary public
* information for the creation of a new PublishedDataSet */
UA_PublishedDataSetConfig publishedDataSetConfig;
memset(&publishedDataSetConfig, 0, sizeof(UA_PublishedDataSetConfig));
publishedDataSetConfig.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
publishedDataSetConfig.name = UA_STRING("Demo PDS");
/* Create new PublishedDataSet based on the PublishedDataSetConfig. */
UA_Server_addPublishedDataSet(server, &publishedDataSetConfig, &publishedDataSetIdent);
}
static void
addPublishedDataSetEx(UA_Server *server) {
/* The PublishedDataSetConfig contains all necessary public
* information for the creation of a new PublishedDataSet */
UA_PublishedDataSetConfig publishedDataSetConfig;
memset(&publishedDataSetConfig, 0, sizeof(UA_PublishedDataSetConfig));
publishedDataSetConfig.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
publishedDataSetConfig.name = UA_STRING("Demo PDS Ex");
/* Create new PublishedDataSet based on the PublishedDataSetConfig. */
UA_Server_addPublishedDataSet(server, &publishedDataSetConfig, &publishedDataSetIdentEx);
}
static void
addDataSetField(UA_Server *server) {
/* Add a field to the previous created PublishedDataSet */
UA_NodeId dataSetFieldIdent;
UA_DataSetFieldConfig dataSetFieldConfig;
memset(&dataSetFieldConfig, 0, sizeof(UA_DataSetFieldConfig));
dataSetFieldConfig.dataSetFieldType = UA_PUBSUB_DATASETFIELD_VARIABLE;
dataSetFieldConfig.field.variable.fieldNameAlias = UA_STRING("Server localtime");
dataSetFieldConfig.field.variable.promotedField = UA_FALSE;
dataSetFieldConfig.field.variable.publishParameters.publishedVariable =
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
dataSetFieldConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
UA_Server_addDataSetField(server, publishedDataSetIdent,
&dataSetFieldConfig, &dataSetFieldIdent);
}
static void
addDataSetFieldEx(UA_Server *server) {
/* Add a field to the previous created PublishedDataSet */
UA_NodeId dataSetFieldIdent;
UA_DataSetFieldConfig dataSetFieldConfig;
memset(&dataSetFieldConfig, 0, sizeof(UA_DataSetFieldConfig));
dataSetFieldConfig.dataSetFieldType = UA_PUBSUB_DATASETFIELD_VARIABLE;
dataSetFieldConfig.field.variable.fieldNameAlias = UA_STRING("Server localtime");
dataSetFieldConfig.field.variable.promotedField = UA_FALSE;
dataSetFieldConfig.field.variable.publishParameters.publishedVariable =
UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
dataSetFieldConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
UA_Server_addDataSetField(server, publishedDataSetIdentEx,
&dataSetFieldConfig, &dataSetFieldIdent);
/***********添加节点****************/
UA_NodeId myFieldIdent;
UA_DataSetFieldConfig myFieldConfig;
memset(&myFieldConfig, 0, sizeof(UA_DataSetFieldConfig));
myFieldConfig.dataSetFieldType = UA_PUBSUB_DATASETFIELD_VARIABLE;
myFieldConfig.field.variable.fieldNameAlias = UA_STRING("Myself node");
myFieldConfig.field.variable.promotedField = UA_FALSE;
myFieldConfig.field.variable.publishParameters.publishedVariable = myIntegerNodeId;
myFieldConfig.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
UA_Server_addDataSetField(server, publishedDataSetIdentEx,
&myFieldConfig, &

本文详细介绍了如何在OPCUA应用程序中使用open62541库实现Publishers和Subscribers之间的PubSub通信,包括配置、发布、订阅过程,以及解决跨平台地址解析问题的方法。
&spm=1001.2101.3001.5002&articleId=123787686&d=1&t=3&u=6434080da8384592837228ff3a686e51)
3314

被折叠的 条评论
为什么被折叠?



