open62541:发布温度值

Posted

技术标签:

【中文标题】open62541:发布温度值【英文标题】:open62541: publish temperature val 【发布时间】:2019-08-11 05:00:08 【问题描述】:

我目前正在尝试使用名为 open62541 的 OPC UA 实现发布日期时间值和温度值。

为此,我一直在使用 open62541 github 存储库中的测试示例,因为它已经发布了当前日期时间。 我试图为温度值添加另一个 DSF(DataSetField),就像它与日期时间一起显示的那样。但它不会发布它。

以下代码 sn-p 显示了我如何定义添加 DataSetFields 的方法:

/**
 * **DataSetField handling**
 *
 * The DataSetField (DSF) is part of the PDS and describes exactly one published
 * field. */
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
addDataSetFieldTemperature(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("Temperature");
    dataSetFieldConfig.field.variable.promotedField = UA_FALSE;
    dataSetFieldConfig.field.variable.publishParameters.publishedVariable =
                                      UA_NODEID_NUMERIC(0, 50);
    dataSetFieldConfig.field.variable.publishParameters.attributeId =
                                      UA_ATTRIBUTEID_VALUE;
    UA_Server_addDataSetField(server, publishedDataSetIdent, 
                                      &dataSetFieldConfig,
                                      &dataSetFieldIdent);

在主函数中,然后我调用这两个方法将它们添加到 PDS(PublishedDataSet)中:

addPubSubConnection(server, transportProfile, networkAddressUrl);
addPublishedDataSet(server);
addDataSetFieldTemperature(server);
addDataSetField(server);
addWriterGroup(server);
addDataSetWriter(server);

温度值是一个简单的双精度值,那么我在这里做错了什么? 也许错误在订阅的客户端应用程序中?

为了订阅已发布的值,我还使用了 github 上的示例(文件名为 tutorial_pubsub_subscribe.c),我正在尝试按如下方式解析值:

/* Loop over the fields and print well-known content types */
for(int i = 0; i < dsm->data.keyFrameData.fieldCount; i++) 
    const UA_DataType *currentType = dsm->data.keyFrameData.dataSetFields[i].value.type;
    if(currentType == &UA_TYPES[UA_TYPES_BYTE]) 
        UA_Byte value = *(UA_Byte *)dsm->data.keyFrameData.dataSetFields[i].value.data;
        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
                    "Message content: [Byte] \tReceived data: %i", value);
     else if (currentType == &UA_TYPES[UA_TYPES_DATETIME]) 
        UA_DateTime value = *(UA_DateTime *)dsm->data.keyFrameData.dataSetFields[i].value.data;
        UA_DateTimeStruct receivedTime = UA_DateTime_toStruct(value);
        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
                    "Message content: [DateTime] \t"
                    "Received date: %02i-%02i-%02i Received time: %02i:%02i:%02i",
                    receivedTime.year, receivedTime.month, receivedTime.day,
                    receivedTime.hour, receivedTime.min, receivedTime.sec);
     else if(currentType == &UA_TYPES[UA_TYPES_UINT16]) 
        UA_UInt16 receivedTemp =
            *(UA_UInt16 *)dsm->data.keyFrameData.dataSetFields[i].value.data;

        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
                    "Message content: [UA_UInt16] \t"
                    "Received temperature: %i",
                    receivedTemp);
    

有什么建议吗?非常感谢您,如果您需要有关此问题的更多详细信息,请告诉我,我将进一步编辑问题!

编辑:如果您想查看整个示例代码,请查看以下链接: 对于发布应用程序: https://github.com/open62541/open62541/blob/master/examples/pubsub/tutorial_pubsub_publish.c

订阅申请:https://github.com/open62541/open62541/blob/master/examples/pubsub/tutorial_pubsub_subscribe.c

【问题讨论】:

也许您可以链接您作为代码基础的文件。如果它是正确的,我已经找到了这个:github.com/open62541/open62541/blob/master/examples/pubsub/… 谢谢@David,我编辑了我的问题并添加了两个链接。一个用于发布代码,一个用于订阅代码。 你能调试循环上方的温度值(作为所有值集合的一部分)吗?数据中有温度值吗?如果是这样,也许循环中的某些条件是错误的。 你好@David,我可以看到fieldCount = 2。所以循环重复了2次。第一次,currentType 是 NULL,所以没有任何 if/if else 被执行。第二次,currentType 是 Datetime,所以 datetime-if 被执行并解析时间戳 我不知道你从哪里得到数据以及它们存储在哪里,但是 pubsub 示例是针对多播网络的,所以也许你最好定位于数据源:github.com/open62541/open62541/blob/master/examples/… 【参考方案1】:

您需要在addPubSubConnection之前致电addDataSetFieldTemperature 有关如何更新变量的更多详细信息,请参阅此处https://***.com/questions/58855146/opcua-open62541-pubsub-how-to-publish-value-change/58882085#58882085

【讨论】:

以上是关于open62541:发布温度值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 uaexpert 中查看添加的 open62541 参数?

open62541:构建 PubSub 示例时出错

在 Windows 中使用 open62541 构建一个简单的服务器

open62541 浏览节点和使用它的方法

open62541:同时获取订阅的所有变更监控项

基于open62541的OPC UA服务器建立