Commit 1b893278 authored by Léo-Paul Géneau's avatar Léo-Paul Géneau 👾

Add Drone class

parent 0db1ae2c
...@@ -2,7 +2,26 @@ ...@@ -2,7 +2,26 @@
#define __PUBSUB_COMMON_H__ #define __PUBSUB_COMMON_H__
#include <open62541/server.h> #include <open62541/server.h>
#include <open62541/plugin/log_stdout.h>
#define countof(x) (sizeof(x) / sizeof((x)[0])) #define countof(x) (sizeof(x) / sizeof((x)[0]))
typedef struct {
int id;
UA_Double latitude;
UA_UInt32 latitudeId;
UA_Double longitude;
UA_UInt32 longitudeId;
UA_Float altitude;
UA_UInt32 altitudeId;
} JSDroneData;
typedef struct {
char *name;
char *description;
void * UA_RESTRICT pdefaultValue;
int type;
UA_Byte builtInType;
} VariableData;
#endif /* __PUBSUB_COMMON_H__ */ #endif /* __PUBSUB_COMMON_H__ */
\ No newline at end of file
...@@ -3,10 +3,11 @@ ...@@ -3,10 +3,11 @@
#include "pubsub_common.h" #include "pubsub_common.h"
void writeFloat(char *name, float value); UA_StatusCode writeVariable(char *name, void * UA_RESTRICT pvalue,
void writeDouble(char *name, double value); UA_DataType type);
int publish(UA_String *transportProfile, int publish(UA_String *transportProfile,
UA_NetworkAddressUrlDataType *networkAddressUrl, UA_NetworkAddressUrlDataType *networkAddressUrl,
UA_Boolean *running); VariableData const *variableArray, int nbVariable,
int id, UA_Boolean *running);
#endif /* __PUBSUB_PUBLISH_H__ */ #endif /* __PUBSUB_PUBLISH_H__ */
...@@ -5,6 +5,10 @@ ...@@ -5,6 +5,10 @@
int subscribe(UA_String *transportProfile, int subscribe(UA_String *transportProfile,
UA_NetworkAddressUrlDataType *networkAddressUrl, UA_NetworkAddressUrlDataType *networkAddressUrl,
VariableData const *variableArray, int nbVariable, int nbReader,
void (*init_node_id)(UA_UInt32 id, int nb, int magic),
int (*get_reader_id)(int nb),
void (*update)(UA_UInt32 id, const UA_DataValue*),
UA_Boolean *running); UA_Boolean *running);
#endif /* __PUBSUB_SUBSCRIBE_H__ */ #endif /* __PUBSUB_SUBSCRIBE_H__ */
...@@ -4,32 +4,24 @@ ...@@ -4,32 +4,24 @@
#include "pubsub_publish.h" #include "pubsub_publish.h"
typedef struct PublishedVariable {
char *name;
char *description;
void * UA_RESTRICT pdefaultValue;
UA_DataType type;
} PublishedVariable;
static UA_Server *server; static UA_Server *server;
UA_NodeId connectionIdent, publishedDataSetIdent, writerGroupIdent; UA_NodeId connectionIdent, publishedDataSetIdent, writerGroupIdent;
static void static UA_StatusCode
addPubSubConnection(UA_Server *server, UA_String *transportProfile, addPubSubConnection(UA_Server *server, UA_String *transportProfile,
UA_NetworkAddressUrlDataType *networkAddressUrl){ UA_NetworkAddressUrlDataType *networkAddressUrl,
/* Details about the connection configuration and handling are located int id){
* in the pubsub connection tutorial */ char name[20];
UA_snprintf(name, sizeof(name - 1), "UADP Connection %d", id);
UA_PubSubConnectionConfig connectionConfig; UA_PubSubConnectionConfig connectionConfig;
memset(&connectionConfig, 0, sizeof(connectionConfig)); memset(&connectionConfig, 0, sizeof(connectionConfig));
connectionConfig.name = UA_STRING("UADP Connection 1"); connectionConfig.name = UA_STRING(name);
connectionConfig.transportProfileUri = *transportProfile; connectionConfig.transportProfileUri = *transportProfile;
connectionConfig.enabled = UA_TRUE; connectionConfig.enabled = UA_TRUE;
UA_Variant_setScalar(&connectionConfig.address, networkAddressUrl, UA_Variant_setScalar(&connectionConfig.address, networkAddressUrl,
&UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
/* Changed to static publisherId from random generation to identify connectionConfig.publisherId.numeric = id;
* the publisher on Subscriber side */ return UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdent);
connectionConfig.publisherId.numeric = 2234;
UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdent);
} }
/** /**
...@@ -40,27 +32,29 @@ addPubSubConnection(UA_Server *server, UA_String *transportProfile, ...@@ -40,27 +32,29 @@ addPubSubConnection(UA_Server *server, UA_String *transportProfile,
* other PubSub elements are directly or indirectly linked with the PDS or * other PubSub elements are directly or indirectly linked with the PDS or
* connection. */ * connection. */
static void static void
addPublishedDataSet(UA_Server *server) { addPublishedDataSet(UA_Server *server, int id) {
/* The PublishedDataSetConfig contains all necessary public /* The PublishedDataSetConfig contains all necessary public
* information for the creation of a new PublishedDataSet */ * information for the creation of a new PublishedDataSet */
char name[8];
UA_snprintf(name, sizeof(name - 1), "PDS %d", id);
UA_PublishedDataSetConfig publishedDataSetConfig; UA_PublishedDataSetConfig publishedDataSetConfig;
memset(&publishedDataSetConfig, 0, sizeof(UA_PublishedDataSetConfig)); memset(&publishedDataSetConfig, 0, sizeof(UA_PublishedDataSetConfig));
publishedDataSetConfig.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS; publishedDataSetConfig.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
publishedDataSetConfig.name = UA_STRING("Demo PDS"); publishedDataSetConfig.name = UA_STRING(name);
/* Create new PublishedDataSet based on the PublishedDataSetConfig. */ /* Create new PublishedDataSet based on the PublishedDataSetConfig. */
UA_Server_addPublishedDataSet(server, &publishedDataSetConfig, &publishedDataSetIdent); UA_Server_addPublishedDataSet(server, &publishedDataSetConfig, &publishedDataSetIdent);
} }
static void static UA_StatusCode
addVariable(UA_Server *server, PublishedVariable varDetails) { addVariable(UA_Server *server, VariableData varDetails) {
UA_VariableAttributes attr = UA_VariableAttributes_default; UA_VariableAttributes attr = UA_VariableAttributes_default;
UA_Variant_setScalar(&attr.value, varDetails.pdefaultValue, &varDetails.type); UA_Variant_setScalar(&attr.value, varDetails.pdefaultValue, &UA_TYPES[varDetails.type]);
attr.description = UA_LOCALIZEDTEXT("en-US", varDetails.description); attr.description = UA_LOCALIZEDTEXT("en-US", varDetails.description);
attr.displayName = UA_LOCALIZEDTEXT("en-US", varDetails.description); attr.displayName = UA_LOCALIZEDTEXT("en-US", varDetails.description);
attr.dataType = varDetails.type.typeId; attr.dataType = UA_TYPES[varDetails.type].typeId;
attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE; attr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
UA_Server_addVariableNode(server, UA_NODEID_STRING(1, varDetails.name), return UA_Server_addVariableNode(server, UA_NODEID_STRING(1, varDetails.name),
UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
UA_QUALIFIEDNAME(1, varDetails.description), UA_QUALIFIEDNAME(1, varDetails.description),
...@@ -68,29 +62,17 @@ addVariable(UA_Server *server, PublishedVariable varDetails) { ...@@ -68,29 +62,17 @@ addVariable(UA_Server *server, PublishedVariable varDetails) {
attr, NULL, NULL); attr, NULL, NULL);
} }
static void UA_StatusCode writeVariable(char *name, void * UA_RESTRICT pvalue, UA_DataType type)
writeVariable(char *name, void * UA_RESTRICT pvalue,
UA_DataType type)
{ {
UA_NodeId integerNodeId = UA_NODEID_STRING(1, name); UA_NodeId integerNodeId = UA_NODEID_STRING(1, name);
UA_Variant var; UA_Variant var;
UA_Variant_init(&var); UA_Variant_init(&var);
UA_Variant_setScalar(&var, pvalue, &type); UA_Variant_setScalar(&var, pvalue, &type);
UA_Server_writeValue(server, integerNodeId, var); return UA_Server_writeValue(server, integerNodeId, var);
}
void writeFloat(char *name, float externValue) {
float localValue = externValue;
writeVariable(name, &localValue, UA_TYPES[UA_TYPES_FLOAT]);
}
void writeDouble(char *name, double externValue) {
double localValue = externValue;
writeVariable(name, &localValue, UA_TYPES[UA_TYPES_DOUBLE]);
} }
static void static void
addDataSetField(UA_Server *server, PublishedVariable varDetails) { addDataSetField(UA_Server *server, VariableData varDetails) {
UA_NodeId dataSetFieldIdent; UA_NodeId dataSetFieldIdent;
UA_DataSetFieldConfig dataSetFieldConfig; UA_DataSetFieldConfig dataSetFieldConfig;
memset(&dataSetFieldConfig, 0, sizeof(UA_DataSetFieldConfig)); memset(&dataSetFieldConfig, 0, sizeof(UA_DataSetFieldConfig));
...@@ -146,7 +128,7 @@ addWriterGroup(UA_Server *server) { ...@@ -146,7 +128,7 @@ addWriterGroup(UA_Server *server) {
* A DataSetWriter (DSW) is the glue between the WG and the PDS. The DSW is * A DataSetWriter (DSW) is the glue between the WG and the PDS. The DSW is
* linked to exactly one PDS and contains additional information for the * linked to exactly one PDS and contains additional information for the
* message generation. */ * message generation. */
static void static UA_StatusCode
addDataSetWriter(UA_Server *server) { addDataSetWriter(UA_Server *server) {
/* We need now a DataSetWriter within the WriterGroup. This means we must /* We need now a DataSetWriter within the WriterGroup. This means we must
* create a new DataSetWriterConfig and add call the addWriterGroup function. */ * create a new DataSetWriterConfig and add call the addWriterGroup function. */
...@@ -156,54 +138,40 @@ addDataSetWriter(UA_Server *server) { ...@@ -156,54 +138,40 @@ addDataSetWriter(UA_Server *server) {
dataSetWriterConfig.name = UA_STRING("Demo DataSetWriter"); dataSetWriterConfig.name = UA_STRING("Demo DataSetWriter");
dataSetWriterConfig.dataSetWriterId = 62541; dataSetWriterConfig.dataSetWriterId = 62541;
dataSetWriterConfig.keyFrameCount = 10; dataSetWriterConfig.keyFrameCount = 10;
UA_Server_addDataSetWriter(server, writerGroupIdent, publishedDataSetIdent, return UA_Server_addDataSetWriter(server, writerGroupIdent, publishedDataSetIdent,
&dataSetWriterConfig, &dataSetWriterIdent); &dataSetWriterConfig, &dataSetWriterIdent);
} }
int publish(UA_String *transportProfile, int publish(UA_String *transportProfile,
UA_NetworkAddressUrlDataType *networkAddressUrl, UA_NetworkAddressUrlDataType *networkAddressUrl,
UA_Boolean *running) { VariableData const *variableArray, int nbVariable,
int id, UA_Boolean *running) {
int i; int i;
UA_Float defaultFloat = 0; UA_StatusCode retval = UA_STATUSCODE_GOOD;
UA_Double defaultDouble = 0;
const PublishedVariable publishedVariableArray[] = {
{
.name = "lattitude",
.description = "Lattitude",
.pdefaultValue = &defaultDouble,
.type = UA_TYPES[UA_TYPES_DOUBLE],
},
{
.name = "longitude",
.description = "Longitude",
.pdefaultValue = &defaultDouble,
.type = UA_TYPES[UA_TYPES_DOUBLE],
},
{
.name = "altitude",
.description = "Altitude",
.pdefaultValue = &defaultFloat,
.type = UA_TYPES[UA_TYPES_FLOAT],
},
};
server = UA_Server_new(); server = UA_Server_new();
UA_ServerConfig *config = UA_Server_getConfig(server); UA_ServerConfig *config = UA_Server_getConfig(server);
UA_ServerConfig_setDefault(config); UA_ServerConfig_setDefault(config);
UA_ServerConfig_addPubSubTransportLayer(config, UA_PubSubTransportLayerUDPMP()); UA_ServerConfig_addPubSubTransportLayer(config, UA_PubSubTransportLayerUDPMP());
addPubSubConnection(server, transportProfile, networkAddressUrl); retval |= addPubSubConnection(server, transportProfile, networkAddressUrl, id);
addPublishedDataSet(server); if (retval != UA_STATUSCODE_GOOD)
for(i = 0; i < countof(publishedVariableArray); i++) { return EXIT_FAILURE;
addVariable(server, publishedVariableArray[i]);
addDataSetField(server, publishedVariableArray[i]); addPublishedDataSet(server, id);
for(i = 0; i < nbVariable; i++) {
retval |= addVariable(server, variableArray[i]);
if (retval != UA_STATUSCODE_GOOD)
return EXIT_FAILURE;
addDataSetField(server, variableArray[i]);
} }
addWriterGroup(server);
addDataSetWriter(server);
UA_StatusCode retval = UA_Server_run(server, running); addWriterGroup(server);
retval |= addDataSetWriter(server);
if (retval != UA_STATUSCODE_GOOD)
return EXIT_FAILURE;
retval |= UA_Server_run(server, running);
UA_Server_delete(server); UA_Server_delete(server);
return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE; return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
} }
#include <open62541/client_subscriptions.h> #include <open62541/client_subscriptions.h>
#include <open62541/plugin/log_stdout.h>
#include <open62541/plugin/pubsub_udp.h> #include <open62541/plugin/pubsub_udp.h>
#include <open62541/server_config_default.h> #include <open62541/server_config_default.h>
#include <open62541/types_generated.h> #include <open62541/types_generated.h>
...@@ -7,21 +6,17 @@ ...@@ -7,21 +6,17 @@
#include "ua_pubsub.h" #include "ua_pubsub.h"
#include "pubsub_subscribe.h" #include "pubsub_subscribe.h"
typedef struct SubscribedVariable {
UA_Byte builtInType;
UA_String name;
UA_NodeId dataType;
} SubscribedVariable;
UA_NodeId connectionIdentifier; UA_NodeId connectionIdentifier;
UA_NodeId readerGroupIdentifier; UA_NodeId readerGroupIdentifier;
UA_NodeId readerIdentifier; UA_NodeId readerIdentifier;
UA_DataSetReaderConfig readerConfig; UA_DataSetReaderConfig readerConfig;
static void (*callbackUpdate)(UA_UInt32, const UA_DataValue*);
static void fillDataSetMetaData(UA_DataSetMetaDataType *pMetaData, static void fillDataSetMetaData(UA_DataSetMetaDataType *pMetaData,
SubscribedVariable *subscribedVariableArray, VariableData const *variableArray,
int variableNb); int nbVariable, int id);
/* Add new connection to the server */ /* Add new connection to the server */
static UA_StatusCode static UA_StatusCode
...@@ -83,32 +78,20 @@ addReaderGroup(UA_Server *server) { ...@@ -83,32 +78,20 @@ addReaderGroup(UA_Server *server) {
* SubscribedDataSet and be contained within a ReaderGroup. */ * SubscribedDataSet and be contained within a ReaderGroup. */
/* Add DataSetReader to the ReaderGroup */ /* Add DataSetReader to the ReaderGroup */
static UA_StatusCode static UA_StatusCode
addDataSetReader(UA_Server *server, addDataSetReader(UA_Server *server, VariableData const *variableArray,
SubscribedVariable *subscribedVariableArray, int nbVariable, int id) {
int variableNb) {
if(server == NULL) { if(server == NULL) {
return UA_STATUSCODE_BADINTERNALERROR; return UA_STATUSCODE_BADINTERNALERROR;
} }
UA_StatusCode retval = UA_STATUSCODE_GOOD; 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 */ /* Setting up Meta data configuration in DataSetReader */
fillDataSetMetaData(&readerConfig.dataSetMetaData, subscribedVariableArray, variableNb); fillDataSetMetaData(&readerConfig.dataSetMetaData, variableArray,
nbVariable, id);
retval |= UA_Server_addDataSetReader(server, readerGroupIdentifier, &readerConfig, retval |= UA_Server_addDataSetReader(server, readerGroupIdentifier,
&readerIdentifier); &readerConfig, &readerIdentifier);
return retval; return retval;
} }
...@@ -117,11 +100,7 @@ dataChangeNotificationCallback(UA_Server *server, UA_UInt32 monitoredItemId, ...@@ -117,11 +100,7 @@ dataChangeNotificationCallback(UA_Server *server, UA_UInt32 monitoredItemId,
void *monitoredItemContext, const UA_NodeId *nodeId, void *monitoredItemContext, const UA_NodeId *nodeId,
void *nodeContext, UA_UInt32 attributeId, void *nodeContext, UA_UInt32 attributeId,
const UA_DataValue *var) { const UA_DataValue *var) {
if(UA_Variant_hasScalarType(&var->value, &UA_TYPES[UA_TYPES_DOUBLE])) { callbackUpdate(nodeId->identifier.numeric, var);
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
"Received Notification with value %f",
*(UA_Double*) var->value.data);
}
} }
/** /**
...@@ -130,7 +109,8 @@ dataChangeNotificationCallback(UA_Server *server, UA_UInt32 monitoredItemId, ...@@ -130,7 +109,8 @@ dataChangeNotificationCallback(UA_Server *server, UA_UInt32 monitoredItemId,
* Set SubscribedDataSet type to TargetVariables data type. * Set SubscribedDataSet type to TargetVariables data type.
* Add subscribedvariables to the DataSetReader */ * Add subscribedvariables to the DataSetReader */
static UA_StatusCode static UA_StatusCode
addSubscribedVariables (UA_Server *server, UA_NodeId dataSetReaderId) { addSubscribedVariables (UA_Server *server, UA_NodeId dataSetReaderId, int nb,
void (*init_node_id)(UA_UInt32 id, int nb, int magic)) {
if(server == NULL) if(server == NULL)
return UA_STATUSCODE_BADINTERNALERROR; return UA_STATUSCODE_BADINTERNALERROR;
...@@ -183,8 +163,8 @@ addSubscribedVariables (UA_Server *server, UA_NodeId dataSetReaderId) { ...@@ -183,8 +163,8 @@ addSubscribedVariables (UA_Server *server, UA_NodeId dataSetReaderId) {
vAttr, NULL, &newNode); vAttr, NULL, &newNode);
/*monitor variable*/ /*monitor variable*/
UA_MonitoredItemCreateRequest monRequest = UA_MonitoredItemCreateRequest monRequest = UA_MonitoredItemCreateRequest_default(newNode);
UA_MonitoredItemCreateRequest_default(newNode); init_node_id(newNode.identifier.numeric, nb, i);
UA_Server_createDataChangeMonitoredItem(server, UA_TIMESTAMPSTORETURN_SOURCE, UA_Server_createDataChangeMonitoredItem(server, UA_TIMESTAMPSTORETURN_SOURCE,
monRequest, NULL, dataChangeNotificationCallback); monRequest, NULL, dataChangeNotificationCallback);
...@@ -213,60 +193,53 @@ addSubscribedVariables (UA_Server *server, UA_NodeId dataSetReaderId) { ...@@ -213,60 +193,53 @@ addSubscribedVariables (UA_Server *server, UA_NodeId dataSetReaderId) {
* and PublishedDataSetFields of Publisher */ * and PublishedDataSetFields of Publisher */
/* Define MetaData for TargetVariables */ /* Define MetaData for TargetVariables */
static void fillDataSetMetaData(UA_DataSetMetaDataType *pMetaData, static void fillDataSetMetaData(UA_DataSetMetaDataType *pMetaData,
SubscribedVariable *subscribedVariableArray, VariableData const *variableArray,
int variableNb) { int nbVariable, int id) {
char name[12];
UA_snprintf(name, sizeof(name - 1), "DataSet %d", id);
if(pMetaData == NULL) { if(pMetaData == NULL) {
return; return;
} }
UA_DataSetMetaDataType_init (pMetaData); UA_DataSetMetaDataType_init (pMetaData);
pMetaData->name = UA_STRING ("DataSet 1"); pMetaData->name = UA_STRING (name);
/* Definition of number of fields sizeto create different /* Definition of number of fields sizeto create different
* targetVariables of distinct datatype */ * targetVariables of distinct datatype */
pMetaData->fieldsSize = variableNb; pMetaData->fieldsSize = nbVariable;
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "filedsSize %d", pMetaData->fieldsSize); UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "fieldsSize %d", (int) pMetaData->fieldsSize);
pMetaData->fields = (UA_FieldMetaData*)UA_Array_new (pMetaData->fieldsSize, pMetaData->fields = (UA_FieldMetaData*)UA_Array_new (pMetaData->fieldsSize,
&UA_TYPES[UA_TYPES_FIELDMETADATA]); &UA_TYPES[UA_TYPES_FIELDMETADATA]);
for(size_t i = 0; i < pMetaData->fieldsSize; i++) { for(size_t i = 0; i < pMetaData->fieldsSize; i++) {
UA_FieldMetaData_init (&pMetaData->fields[i]); UA_FieldMetaData_init (&pMetaData->fields[i]);
UA_NodeId_copy(&subscribedVariableArray[i].dataType,
&pMetaData->fields[i].dataType); UA_NodeId_copy(&UA_TYPES[variableArray[i].type].typeId, &pMetaData->fields[i].dataType);
pMetaData->fields[i].builtInType = subscribedVariableArray[i].builtInType; pMetaData->fields[i].builtInType = variableArray[i].builtInType;
pMetaData->fields[i].name = subscribedVariableArray[i].name; pMetaData->fields[i].name = UA_STRING (variableArray[i].name);
pMetaData->fields[i].valueRank = -1; /* scalar */ pMetaData->fields[i].valueRank = -1; /* scalar */
} }
} }
int subscribe(UA_String *transportProfile, int subscribe(UA_String *transportProfile,
UA_NetworkAddressUrlDataType *networkAddressUrl, UA_NetworkAddressUrlDataType *networkAddressUrl,
VariableData const *variableArray, int nbVariable, int nbReader,
void (*init_node_id)(UA_UInt32 id, int nb, int magic),
int (*get_reader_id)(int nb),
void (*update)(UA_UInt32 id, const UA_DataValue*),
UA_Boolean *running) { UA_Boolean *running) {
const SubscribedVariable subscribedVariableArray[] = {
{
.builtInType = UA_NS0ID_DOUBLE,
.name = UA_STRING ("lattitude"),
.dataType = UA_TYPES[UA_TYPES_DOUBLE].typeId,
},
{
.builtInType = UA_NS0ID_DOUBLE,
.name = UA_STRING ("longitude"),
.dataType = UA_TYPES[UA_TYPES_DOUBLE].typeId,
},
{
.builtInType = UA_NS0ID_FLOAT,
.name = UA_STRING ("altitude"),
.dataType = UA_TYPES[UA_TYPES_FLOAT].typeId,
},
};
/* Return value initialized to Status Good */ /* Return value initialized to Status Good */
UA_StatusCode retval = UA_STATUSCODE_GOOD; UA_StatusCode retval = UA_STATUSCODE_GOOD;
UA_Server *server = UA_Server_new(); UA_Server *server = UA_Server_new();
UA_ServerConfig *config = UA_Server_getConfig(server); UA_ServerConfig *config = UA_Server_getConfig(server);
UA_ServerConfig_setMinimal(config, 4801, NULL); UA_ServerConfig_setMinimal(config, 4801, NULL);
UA_UInt16 publisherIdentifier;
char readerName[19];
callbackUpdate = update;
/* Add the PubSub network layer implementation to the server config. /* Add the PubSub network layer implementation to the server config.
* The TransportLayer is acting as factory to create new connections * The TransportLayer is acting as factory to create new connections
* on runtime. Details about the PubSubTransportLayer can be found inside the * on runtime. Details about the PubSubTransportLayer can be found inside the
...@@ -278,21 +251,35 @@ int subscribe(UA_String *transportProfile, ...@@ -278,21 +251,35 @@ int subscribe(UA_String *transportProfile,
retval |= addPubSubConnection(server, transportProfile, networkAddressUrl); retval |= addPubSubConnection(server, transportProfile, networkAddressUrl);
if (retval != UA_STATUSCODE_GOOD) if (retval != UA_STATUSCODE_GOOD)
return EXIT_FAILURE; return EXIT_FAILURE;
/*UA_PubSubConnection *currentConnectionContext =
UA_PubSubConnection_findConnectionbyId(server, connectionIdentifier);
printf("connected %d\n", currentConnectionContext->isRegistered);*/
/* Add ReaderGroup to the created PubSubConnection */ /* Add ReaderGroup to the created PubSubConnection */
retval |= addReaderGroup(server); retval |= addReaderGroup(server);
if (retval != UA_STATUSCODE_GOOD) if (retval != UA_STATUSCODE_GOOD)
return EXIT_FAILURE; return EXIT_FAILURE;
//printf("connected %d\n", currentConnectionContext->isRegistered);
/* Add DataSetReader to the created ReaderGroup */ memset (&readerConfig, 0, sizeof(UA_DataSetReaderConfig));
retval |= addDataSetReader(server, subscribedVariableArray, countof(subscribedVariableArray)); readerConfig.publisherId.type = &UA_TYPES[UA_TYPES_UINT16];
readerConfig.writerGroupId = 100;
readerConfig.dataSetWriterId = 62541;
for (size_t i = 0; i < nbReader; i++) {
publisherIdentifier = get_reader_id(i);
UA_snprintf(readerName, sizeof(readerName - 1), "DataSet Reader %d", publisherIdentifier);
readerConfig.name = UA_STRING(readerName);
readerConfig.publisherId.data = &publisherIdentifier;
retval |= addDataSetReader(server, variableArray, nbVariable, publisherIdentifier);
if (retval != UA_STATUSCODE_GOOD) if (retval != UA_STATUSCODE_GOOD)
return EXIT_FAILURE; return EXIT_FAILURE;
/* Add SubscribedVariables to the created DataSetReader */ /* Add SubscribedVariables to the created DataSetReader */
retval |= addSubscribedVariables(server, readerIdentifier); retval |= addSubscribedVariables(server, readerIdentifier, i, init_node_id);
if (retval != UA_STATUSCODE_GOOD) if (retval != UA_STATUSCODE_GOOD)
return EXIT_FAILURE; return EXIT_FAILURE;
}
retval = UA_Server_run(server, running); retval = UA_Server_run(server, running);
UA_Server_delete(server); UA_Server_delete(server);
......
...@@ -4,15 +4,142 @@ ...@@ -4,15 +4,142 @@
#include "pubsub_publish.h" #include "pubsub_publish.h"
#include "pubsub_subscribe.h" #include "pubsub_subscribe.h"
static JSClassID js_drone_class_id;
UA_Float defaultFloat = 0;
UA_Double defaultDouble = 0;
const VariableData droneVariableArray[] = {
{
.name = "latitude",
.description = "Latitude",
.pdefaultValue = &defaultDouble,
.type = UA_TYPES_DOUBLE,
.builtInType = UA_NS0ID_DOUBLE,
},
{
.name = "longitude",
.description = "Longitude",
.pdefaultValue = &defaultDouble,
.type = UA_TYPES_DOUBLE,
.builtInType = UA_NS0ID_DOUBLE,
},
{
.name = "altitude",
.description = "Altitude",
.pdefaultValue = &defaultFloat,
.type = UA_TYPES_FLOAT,
.builtInType = UA_NS0ID_FLOAT,
},
};
static UA_Boolean publishing = true; static UA_Boolean publishing = true;
static UA_Boolean subscribing = true; static UA_Boolean subscribing = true;
int nbDrone;
static JSValueConst *drone_object_id_list;
static void js_drone_finalizer(JSRuntime *rt, JSValue val)
{
JSDroneData *s = JS_GetOpaque(val, js_drone_class_id);
js_free_rt(rt, s);
}
static JSValue js_drone_ctor(JSContext *ctx, JSValueConst new_target,
int argc, JSValueConst *argv)
{
JSDroneData *s;
JSValue obj = JS_UNDEFINED;
JSValue proto;
s = js_mallocz(ctx, sizeof(*s));
if (!s)
return JS_EXCEPTION;
if (JS_ToInt32(ctx, &s->id, argv[0]))
goto fail;
proto = JS_GetPropertyStr(ctx, new_target, "prototype");
if (JS_IsException(proto))
goto fail;
obj = JS_NewObjectProtoClass(ctx, proto, js_drone_class_id);
JS_FreeValue(ctx, proto);
if (JS_IsException(obj))
goto fail;
JS_SetOpaque(obj, s);
return obj;
fail:
js_free(ctx, s);
JS_FreeValue(ctx, obj);
return JS_EXCEPTION;
}
static JSValue js_drone_init(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
int nb;
JSDroneData *s = JS_GetOpaque2(ctx, this_val, js_drone_class_id);
if (!s)
return JS_EXCEPTION;
if (JS_ToInt32(ctx, &nb, argv[0]))
return JS_EXCEPTION;
drone_object_id_list[nb] = this_val;
return JS_UNDEFINED;
}
static JSValue js_drone_get(JSContext *ctx, JSValueConst this_val, int magic)
{
JSDroneData *s = JS_GetOpaque2(ctx, this_val, js_drone_class_id);
if (!s)
return JS_EXCEPTION;
switch(magic) {
case 0:
return JS_NewInt32(ctx, s->id);
case 1:
return JS_NewFloat64(ctx, s->latitude);
case 2:
return JS_NewFloat64(ctx, s->longitude);
case 3:
return JS_NewFloat64(ctx, s->altitude);
default:
return JS_EXCEPTION;
}
}
static JSClassDef js_drone_class = {
"Drone",
.finalizer = js_drone_finalizer,
};
static const JSCFunctionListEntry js_drone_proto_funcs[] = {
JS_CGETSET_MAGIC_DEF("id", js_drone_get, NULL, 0),
JS_CGETSET_MAGIC_DEF("latitude", js_drone_get, NULL, 1),
JS_CGETSET_MAGIC_DEF("longitude", js_drone_get, NULL, 2),
JS_CGETSET_MAGIC_DEF("altitude", js_drone_get, NULL, 3),
JS_CFUNC_DEF("init", 1, js_drone_init),
};
void pubsub_publish_coordinates(double latitude, double longitude, float altitude)
{
UA_StatusCode res = UA_STATUSCODE_GOOD;
res |= writeVariable(droneVariableArray[0].name, &latitude,
UA_TYPES[droneVariableArray[0].type]);
res |= writeVariable(droneVariableArray[1].name, &longitude,
UA_TYPES[droneVariableArray[1].type]);
res |= writeVariable(droneVariableArray[2].name, &altitude,
UA_TYPES[droneVariableArray[2].type]);
if (res != UA_STATUSCODE_GOOD)
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
"Writing variable returned value %x", res);
}
static JSValue js_pubsub_publish(JSContext *ctx, JSValueConst this_val, static JSValue js_pubsub_publish(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv) int argc, JSValueConst *argv)
{ {
const char *ipv6; const char *ipv6;
const char *port; const char *port;
char urlBuffer[44]; char urlBuffer[44];
int id;
int res; int res;
ipv6 = JS_ToCString(ctx, argv[0]); ipv6 = JS_ToCString(ctx, argv[0]);
...@@ -24,13 +151,85 @@ static JSValue js_pubsub_publish(JSContext *ctx, JSValueConst this_val, ...@@ -24,13 +151,85 @@ static JSValue js_pubsub_publish(JSContext *ctx, JSValueConst this_val,
UA_NetworkAddressUrlDataType networkAddressUrl = UA_NetworkAddressUrlDataType networkAddressUrl =
{UA_STRING_NULL , UA_STRING(urlBuffer)}; {UA_STRING_NULL , UA_STRING(urlBuffer)};
res = publish(&transportProfile, &networkAddressUrl, &publishing); if (JS_ToInt32(ctx, &id, argv[2]))
return JS_EXCEPTION;
res = publish(&transportProfile, &networkAddressUrl, droneVariableArray,
countof(droneVariableArray), id, &publishing);
JS_FreeCString(ctx, ipv6); JS_FreeCString(ctx, ipv6);
JS_FreeCString(ctx, port); JS_FreeCString(ctx, port);
return JS_NewInt32(ctx, res); return JS_NewInt32(ctx, res);
} }
static JSValue js_init_subscription(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
if (JS_ToInt32(ctx, &nbDrone, argv[0]))
return JS_EXCEPTION;
drone_object_id_list = malloc(nbDrone * sizeof(JSValueConst));
return JS_NewInt32(ctx, 0);
}
int get_drone_id(int nb) {
JSDroneData *s = JS_GetOpaque(drone_object_id_list[nb], js_drone_class_id);
return s->id;
}
void init_node_id(UA_UInt32 id, int nb, int magic) {
JSDroneData *s = JS_GetOpaque(drone_object_id_list[nb], js_drone_class_id);
switch(magic) {
case 0:
s->latitudeId = id;
break;
case 1:
s->longitudeId = id;
break;
case 2:
s->altitudeId = id;
break;
default:
break;
}
}
void pubsub_update_coordinates(UA_UInt32 id, const UA_DataValue *var)
{
JSDroneData *s;
for(size_t i = 0; i < nbDrone; i++) {
s = JS_GetOpaque(drone_object_id_list[i], js_drone_class_id);
if (s->latitudeId == id) {
s->latitude = *(UA_Double*) var->value.data;
return;
} else if (s->longitudeId == id) {
s->longitude = *(UA_Double*) var->value.data;
return;
} else if (s->altitudeId == id) {
s->altitude = *(UA_Float*) var->value.data;
return;
}
}
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT, "NodeId not found");
}
static JSValue js_pubsub_write(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
double latitude;
double longitude;
double altitude;
if (JS_ToFloat64(ctx, &latitude, argv[0]))
return JS_EXCEPTION;
if (JS_ToFloat64(ctx, &longitude, argv[1]))
return JS_EXCEPTION;
if (JS_ToFloat64(ctx, &altitude, argv[2]))
return JS_EXCEPTION;
pubsub_publish_coordinates(latitude, longitude, altitude);
return JS_NewInt32(ctx, 0);
}
static JSValue js_pubsub_subscribe(JSContext *ctx, JSValueConst this_val, static JSValue js_pubsub_subscribe(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv) int argc, JSValueConst *argv)
{ {
...@@ -48,20 +247,14 @@ static JSValue js_pubsub_subscribe(JSContext *ctx, JSValueConst this_val, ...@@ -48,20 +247,14 @@ static JSValue js_pubsub_subscribe(JSContext *ctx, JSValueConst this_val,
UA_NetworkAddressUrlDataType networkAddressUrl = UA_NetworkAddressUrlDataType networkAddressUrl =
{UA_STRING_NULL , UA_STRING(urlBuffer)}; {UA_STRING_NULL , UA_STRING(urlBuffer)};
res = subscribe(&transportProfile, &networkAddressUrl, &subscribing); res = subscribe(&transportProfile, &networkAddressUrl, droneVariableArray,
countof(droneVariableArray), nbDrone, init_node_id,
get_drone_id, pubsub_update_coordinates, &subscribing);
JS_FreeCString(ctx, ipv6); JS_FreeCString(ctx, ipv6);
JS_FreeCString(ctx, port); JS_FreeCString(ctx, port);
return JS_NewInt32(ctx, res); return JS_NewInt32(ctx, res);
} }
void pubsub_set_coordinates(double lattitude, double longitude, float altitude)
{
writeDouble("lattitude", lattitude);
writeDouble("longitude", longitude);
writeFloat("altitude", altitude);
}
static JSValue js_stop_publishing(JSContext *ctx, JSValueConst this_val, static JSValue js_stop_publishing(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv) int argc, JSValueConst *argv)
{ {
...@@ -73,6 +266,7 @@ static JSValue js_stop_subscribing(JSContext *ctx, JSValueConst this_val, ...@@ -73,6 +266,7 @@ static JSValue js_stop_subscribing(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv) int argc, JSValueConst *argv)
{ {
subscribing = false; subscribing = false;
free(drone_object_id_list);
return JS_NewInt32(ctx, 0); return JS_NewInt32(ctx, 0);
} }
...@@ -89,7 +283,7 @@ static JSValue js_mavsdk_start(JSContext *ctx, JSValueConst this_val, ...@@ -89,7 +283,7 @@ static JSValue js_mavsdk_start(JSContext *ctx, JSValueConst this_val,
if (JS_ToInt32(ctx, &timeout, argv[2])) if (JS_ToInt32(ctx, &timeout, argv[2]))
return JS_EXCEPTION; return JS_EXCEPTION;
res = mavsdk_start(url, log_file, timeout, pubsub_set_coordinates); res = mavsdk_start(url, log_file, timeout, pubsub_publish_coordinates);
JS_FreeCString(ctx, url); JS_FreeCString(ctx, url);
JS_FreeCString(ctx, log_file); JS_FreeCString(ctx, log_file);
...@@ -361,10 +555,28 @@ static const JSCFunctionListEntry js_mavsdk_funcs[] = { ...@@ -361,10 +555,28 @@ static const JSCFunctionListEntry js_mavsdk_funcs[] = {
JS_CFUNC_DEF("subscribe", 2, js_pubsub_subscribe ), JS_CFUNC_DEF("subscribe", 2, js_pubsub_subscribe ),
JS_CFUNC_DEF("stopPublishing", 0, js_stop_publishing ), JS_CFUNC_DEF("stopPublishing", 0, js_stop_publishing ),
JS_CFUNC_DEF("stopSubscribing", 0, js_stop_subscribing ), JS_CFUNC_DEF("stopSubscribing", 0, js_stop_subscribing ),
JS_CFUNC_DEF("initSubscription", 1, js_init_subscription ),
JS_CFUNC_DEF("pubsubWrite", 3, js_pubsub_write ),
}; };
static int js_mavsdk_init(JSContext *ctx, JSModuleDef *m) static int js_mavsdk_init(JSContext *ctx, JSModuleDef *m)
{ {
JSValue drone_proto, drone_class;
JS_NewClassID(&js_drone_class_id);
JS_NewClass(JS_GetRuntime(ctx), js_drone_class_id, &js_drone_class);
drone_proto = JS_NewObject(ctx);
JS_SetPropertyFunctionList(ctx, drone_proto, js_drone_proto_funcs,
countof(js_drone_proto_funcs));
drone_class = JS_NewCFunction2(ctx, js_drone_ctor, "Drone", 1,
JS_CFUNC_constructor, 0);
JS_SetConstructor(ctx, drone_class, drone_proto);
JS_SetClassProto(ctx, js_drone_class_id, drone_proto);
JS_SetModuleExport(ctx, m, "Drone", drone_class);
return JS_SetModuleExportList(ctx, m, js_mavsdk_funcs, return JS_SetModuleExportList(ctx, m, js_mavsdk_funcs,
countof(js_mavsdk_funcs)); countof(js_mavsdk_funcs));
} }
...@@ -376,5 +588,6 @@ JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) ...@@ -376,5 +588,6 @@ JSModuleDef *js_init_module(JSContext *ctx, const char *module_name)
if (!m) if (!m)
return NULL; return NULL;
JS_AddModuleExportList(ctx, m, js_mavsdk_funcs, countof(js_mavsdk_funcs)); JS_AddModuleExportList(ctx, m, js_mavsdk_funcs, countof(js_mavsdk_funcs));
JS_AddModuleExport(ctx, m, "Drone");
return m; return m;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment