123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- /* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
- *
- * Copyright (c) 2019 Kalycito Infotech Private Limited
- */
- /**
- * IMPORTANT ANNOUNCEMENT
- * The PubSub Subscriber API is currently not finished. This example can be used
- * to receive and display values that are published by tutorial_pubsub_publish
- * example in the TargetVariables of Subscriber Information Model .
- */
- #include <open62541/plugin/log_stdout.h>
- #include <open62541/plugin/pubsub_udp.h>
- #include <open62541/server.h>
- #include <open62541/server_config_default.h>
- #include <open62541/types_generated.h>
- #include "ua_pubsub.h"
- #ifdef UA_ENABLE_PUBSUB_ETH_UADP
- #include <open62541/plugin/pubsub_ethernet.h>
- #endif
- #include <stdio.h>
- #include <signal.h>
- #include <stdlib.h>
- UA_NodeId connectionIdentifier;
- UA_NodeId readerGroupIdentifier;
- UA_NodeId readerIdentifier;
- UA_DataSetReaderConfig readerConfig;
- static void fillTestDataSetMetaData(UA_DataSetMetaDataType *pMetaData);
- /* Add new connection to the server */
- static UA_StatusCode
- addPubSubConnection(UA_Server *server, UA_String *transportProfile,
- UA_NetworkAddressUrlDataType *networkAddressUrl) {
- if((server == NULL) || (transportProfile == NULL) ||
- (networkAddressUrl == NULL)) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- /* Configuration creation for the connection */
- UA_PubSubConnectionConfig connectionConfig;
- memset (&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig));
- connectionConfig.name = UA_STRING("UDPMC Connection 1");
- connectionConfig.transportProfileUri = *transportProfile;
- connectionConfig.enabled = UA_TRUE;
- UA_Variant_setScalar(&connectionConfig.address, networkAddressUrl,
- &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
- connectionConfig.publisherId.numeric = UA_UInt32_random ();
- retval |= UA_Server_addPubSubConnection (server, &connectionConfig, &connectionIdentifier);
- if (retval != UA_STATUSCODE_GOOD) {
- return retval;
- }
- retval |= UA_PubSubConnection_regist(server, &connectionIdentifier);
- return retval;
- }
- /* Add ReaderGroup to the created connection */
- static UA_StatusCode
- addReaderGroup(UA_Server *server) {
- if(server == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- UA_ReaderGroupConfig readerGroupConfig;
- memset (&readerGroupConfig, 0, sizeof(UA_ReaderGroupConfig));
- readerGroupConfig.name = UA_STRING("ReaderGroup1");
- retval |= UA_Server_addReaderGroup(server, connectionIdentifier, &readerGroupConfig,
- &readerGroupIdentifier);
- return retval;
- }
- /* Add DataSetReader to the ReaderGroup */
- static UA_StatusCode
- addDataSetReader(UA_Server *server) {
- if(server == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- memset (&readerConfig, 0, sizeof(UA_DataSetReaderConfig));
- readerConfig.name = UA_STRING("DataSet Reader 1");
- /* Parameters to filter which DataSetMessage has to be processed
- * by the DataSetReader */
- /* The following parameters are used to show that the data published by
- * tutorial_pubsub_publish.c is being subscribed and is being updated in
- * the information model */
- UA_UInt16 publisherIdentifier = 2234;
- readerConfig.publisherId.type = &UA_TYPES[UA_TYPES_UINT16];
- readerConfig.publisherId.data = &publisherIdentifier;
- readerConfig.writerGroupId = 100;
- readerConfig.dataSetWriterId = 62541;
- /* Setting up Meta data configuration in DataSetReader */
- fillTestDataSetMetaData(&readerConfig.dataSetMetaData);
- retval |= UA_Server_addDataSetReader(server, readerGroupIdentifier, &readerConfig,
- &readerIdentifier);
- return retval;
- }
- /* Set SubscribedDataSet type to TargetVariables data type
- * Add subscribedvariables to the DataSetReader */
- static UA_StatusCode
- addSubscribedVariables (UA_Server *server, UA_NodeId dataSetReaderId) {
- if(server == NULL) {
- return UA_STATUSCODE_BADINTERNALERROR;
- }
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- UA_NodeId folderId;
- UA_String folderName = readerConfig.dataSetMetaData.name;
- UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
- UA_QualifiedName folderBrowseName;
- if(folderName.length > 0) {
- oAttr.displayName.locale = UA_STRING ("en-US");
- oAttr.displayName.text = folderName;
- folderBrowseName.namespaceIndex = 1;
- folderBrowseName.name = folderName;
- }
- else {
- oAttr.displayName = UA_LOCALIZEDTEXT ("en-US", "Subscribed Variables");
- folderBrowseName = UA_QUALIFIEDNAME (1, "Subscribed Variables");
- }
- UA_Server_addObjectNode (server, UA_NODEID_NULL,
- UA_NODEID_NUMERIC (0, UA_NS0ID_OBJECTSFOLDER),
- UA_NODEID_NUMERIC (0, UA_NS0ID_ORGANIZES),
- folderBrowseName, UA_NODEID_NUMERIC (0,
- UA_NS0ID_BASEOBJECTTYPE), oAttr, NULL, &folderId);
- retval |= UA_Server_DataSetReader_addTargetVariables (server, &folderId,
- dataSetReaderId,
- UA_PUBSUB_SDS_TARGET);
- UA_free(readerConfig.dataSetMetaData.fields);
- return retval;
- }
- /* Define MetaData for TargetVariables */
- static void fillTestDataSetMetaData(UA_DataSetMetaDataType *pMetaData) {
- if(pMetaData == NULL) {
- return;
- }
- UA_DataSetMetaDataType_init (pMetaData);
- pMetaData->name = UA_STRING ("DataSet 1");
- /* Static definition of number of fields size to 4 to create four different
- * targetVariables of distinct datatype
- * Currently the publisher sends only DateTime data type */
- pMetaData->fieldsSize = 4;
- pMetaData->fields = (UA_FieldMetaData*)UA_Array_new (pMetaData->fieldsSize,
- &UA_TYPES[UA_TYPES_FIELDMETADATA]);
- /* DateTime DataType */
- UA_FieldMetaData_init (&pMetaData->fields[0]);
- UA_NodeId_copy (&UA_TYPES[UA_TYPES_DATETIME].typeId,
- &pMetaData->fields[0].dataType);
- pMetaData->fields[0].builtInType = UA_NS0ID_DATETIME;
- pMetaData->fields[0].name = UA_STRING ("DateTime");
- pMetaData->fields[0].valueRank = -1; /* scalar */
- /* Int32 DataType */
- UA_FieldMetaData_init (&pMetaData->fields[1]);
- UA_NodeId_copy(&UA_TYPES[UA_TYPES_INT32].typeId,
- &pMetaData->fields[1].dataType);
- pMetaData->fields[1].builtInType = UA_NS0ID_INT32;
- pMetaData->fields[1].name = UA_STRING ("Int32");
- pMetaData->fields[1].valueRank = -1; /* scalar */
- /* Int64 DataType */
- UA_FieldMetaData_init (&pMetaData->fields[2]);
- UA_NodeId_copy(&UA_TYPES[UA_TYPES_INT64].typeId,
- &pMetaData->fields[2].dataType);
- pMetaData->fields[2].builtInType = UA_NS0ID_INT64;
- pMetaData->fields[2].name = UA_STRING ("Int64");
- pMetaData->fields[2].valueRank = -1; /* scalar */
- /* Boolean DataType */
- UA_FieldMetaData_init (&pMetaData->fields[3]);
- UA_NodeId_copy (&UA_TYPES[UA_TYPES_BOOLEAN].typeId,
- &pMetaData->fields[3].dataType);
- pMetaData->fields[3].builtInType = UA_NS0ID_BOOLEAN;
- pMetaData->fields[3].name = UA_STRING ("BoolToggle");
- pMetaData->fields[3].valueRank = -1; /* scalar */
- }
- UA_Boolean running = true;
- static void stopHandler(int sign) {
- UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
- running = false;
- }
- static int
- run(UA_String *transportProfile, UA_NetworkAddressUrlDataType *networkAddressUrl) {
- signal(SIGINT, stopHandler);
- signal(SIGTERM, stopHandler);
- /* Return value initialized to Status Good */
- UA_StatusCode retval = UA_STATUSCODE_GOOD;
- UA_Server *server = UA_Server_new();
- UA_ServerConfig *config = UA_Server_getConfig(server);
- UA_ServerConfig_setMinimal(config, 4801, NULL);
- /* Add the PubSub network layer implementation to the server config.
- * The TransportLayer is acting as factory to create new connections
- * on runtime. Details about the PubSubTransportLayer can be found inside the
- * tutorial_pubsub_connection */
- config->pubsubTransportLayers = (UA_PubSubTransportLayer *)
- UA_calloc(2, sizeof(UA_PubSubTransportLayer));
- if(!config->pubsubTransportLayers) {
- UA_Server_delete(server);
- return EXIT_FAILURE;
- }
- config->pubsubTransportLayers[0] = UA_PubSubTransportLayerUDPMP();
- config->pubsubTransportLayersSize++;
- #ifdef UA_ENABLE_PUBSUB_ETH_UADP
- config->pubsubTransportLayers[1] = UA_PubSubTransportLayerEthernet();
- config->pubsubTransportLayersSize++;
- #endif
- /* API calls */
- /* Add PubSubConnection */
- retval |= addPubSubConnection(server, transportProfile, networkAddressUrl);
- if (retval != UA_STATUSCODE_GOOD)
- return EXIT_FAILURE;
- /* Add ReaderGroup to the created PubSubConnection */
- retval |= addReaderGroup(server);
- if (retval != UA_STATUSCODE_GOOD)
- return EXIT_FAILURE;
- /* Add DataSetReader to the created ReaderGroup */
- retval |= addDataSetReader(server);
- if (retval != UA_STATUSCODE_GOOD)
- return EXIT_FAILURE;
- /* Add SubscribedVariables to the created DataSetReader */
- retval |= addSubscribedVariables(server, readerIdentifier);
- if (retval != UA_STATUSCODE_GOOD)
- return EXIT_FAILURE;
- retval = UA_Server_run(server, &running);
- UA_Server_delete(server);
- return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
- }
- static void
- usage(char *progname) {
- printf("usage: %s <uri> [device]\n", progname);
- }
- int main(int argc, char **argv) {
- UA_String transportProfile = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp");
- UA_NetworkAddressUrlDataType networkAddressUrl = {UA_STRING_NULL , UA_STRING("opc.udp://224.0.0.22:4840/")};
- if(argc > 1) {
- if(strcmp(argv[1], "-h") == 0) {
- usage(argv[0]);
- return EXIT_SUCCESS;
- } else if(strncmp(argv[1], "opc.udp://", 10) == 0) {
- networkAddressUrl.url = UA_STRING(argv[1]);
- } else if(strncmp(argv[1], "opc.eth://", 10) == 0) {
- transportProfile =
- UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-eth-uadp");
- if(argc < 3) {
- printf("Error: UADP/ETH needs an interface name\n");
- return EXIT_FAILURE;
- }
- networkAddressUrl.networkInterface = UA_STRING(argv[2]);
- networkAddressUrl.url = UA_STRING(argv[1]);
- } else {
- printf ("Error: unknown URI\n");
- return EXIT_FAILURE;
- }
- }
- return run(&transportProfile, &networkAddressUrl);
- }
|