|
@@ -28,7 +28,7 @@
|
|
|
|
|
|
UA_NodeId counterNodePublisher = {1, UA_NODEIDTYPE_NUMERIC, {1234}};
|
|
UA_NodeId counterNodePublisher = {1, UA_NODEIDTYPE_NUMERIC, {1234}};
|
|
UA_Int64 pubIntervalNs;
|
|
UA_Int64 pubIntervalNs;
|
|
-UA_ServerCallback pubCallback = NULL;
|
|
|
|
|
|
+UA_ServerCallback pubCallback = NULL; /* Sentinel if a timer is active */
|
|
UA_Server *pubServer;
|
|
UA_Server *pubServer;
|
|
UA_Boolean running = true;
|
|
UA_Boolean running = true;
|
|
void *pubData;
|
|
void *pubData;
|
|
@@ -43,6 +43,22 @@ struct timespec cycleStartDelay[MAX_MEASUREMENTS+1];
|
|
struct timespec cycleDuration[MAX_MEASUREMENTS+1];
|
|
struct timespec cycleDuration[MAX_MEASUREMENTS+1];
|
|
size_t publisherMeasurementsCounter = 0;
|
|
size_t publisherMeasurementsCounter = 0;
|
|
|
|
|
|
|
|
+/* The value to published */
|
|
|
|
+#define UA_ENABLE_STATICVALUESOURCE
|
|
|
|
+static UA_UInt64 publishValue = 62541;
|
|
|
|
+
|
|
|
|
+static UA_StatusCode
|
|
|
|
+readPublishValue(UA_Server *server,
|
|
|
|
+ const UA_NodeId *sessionId, void *sessionContext,
|
|
|
|
+ const UA_NodeId *nodeId, void *nodeContext,
|
|
|
|
+ UA_Boolean sourceTimeStamp, const UA_NumericRange *range,
|
|
|
|
+ UA_DataValue *dataValue) {
|
|
|
|
+ UA_Variant_setScalarCopy(&dataValue->value, &publishValue,
|
|
|
|
+ &UA_TYPES[UA_TYPES_UINT64]);
|
|
|
|
+ dataValue->hasValue = true;
|
|
|
|
+ return UA_STATUSCODE_GOOD;
|
|
|
|
+}
|
|
|
|
+
|
|
static void
|
|
static void
|
|
timespec_diff(struct timespec *start, struct timespec *stop,
|
|
timespec_diff(struct timespec *start, struct timespec *stop,
|
|
struct timespec *result) {
|
|
struct timespec *result) {
|
|
@@ -144,9 +160,6 @@ UA_PubSubManager_addRepeatedCallback(UA_Server *server,
|
|
|
|
|
|
/* Set global values for the publish callback */
|
|
/* Set global values for the publish callback */
|
|
int resultTimerCreate = 0;
|
|
int resultTimerCreate = 0;
|
|
- pubServer = server;
|
|
|
|
- pubCallback = callback;
|
|
|
|
- pubData = data;
|
|
|
|
pubIntervalNs = (UA_Int64) (interval_ms * MILLI_AS_NANO_SECONDS);
|
|
pubIntervalNs = (UA_Int64) (interval_ms * MILLI_AS_NANO_SECONDS);
|
|
|
|
|
|
/* Handle the signal */
|
|
/* Handle the signal */
|
|
@@ -164,7 +177,7 @@ UA_PubSubManager_addRepeatedCallback(UA_Server *server,
|
|
resultTimerCreate = timer_create(CLOCKID, &pubEvent, &pubEventTimer);
|
|
resultTimerCreate = timer_create(CLOCKID, &pubEvent, &pubEventTimer);
|
|
if(resultTimerCreate != 0) {
|
|
if(resultTimerCreate != 0) {
|
|
UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
|
|
UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
|
|
- "Failed to create a system event");
|
|
|
|
|
|
+ "Failed to create a system event with code %i", resultTimerCreate);
|
|
return UA_STATUSCODE_BADINTERNALERROR;
|
|
return UA_STATUSCODE_BADINTERNALERROR;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -177,7 +190,7 @@ UA_PubSubManager_addRepeatedCallback(UA_Server *server,
|
|
resultTimerCreate = timer_settime(pubEventTimer, 0, &timerspec, NULL);
|
|
resultTimerCreate = timer_settime(pubEventTimer, 0, &timerspec, NULL);
|
|
if(resultTimerCreate != 0) {
|
|
if(resultTimerCreate != 0) {
|
|
UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
|
|
UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
|
|
- "Failed to arm the system timer");
|
|
|
|
|
|
+ "Failed to arm the system timer with code %i", resultTimerCreate);
|
|
timer_delete(pubEventTimer);
|
|
timer_delete(pubEventTimer);
|
|
return UA_STATUSCODE_BADINTERNALERROR;
|
|
return UA_STATUSCODE_BADINTERNALERROR;
|
|
}
|
|
}
|
|
@@ -188,6 +201,11 @@ UA_PubSubManager_addRepeatedCallback(UA_Server *server,
|
|
calculatedCycleStartTime[0].tv_nsec += pubIntervalNs;
|
|
calculatedCycleStartTime[0].tv_nsec += pubIntervalNs;
|
|
nanoSecondFieldConversion(&calculatedCycleStartTime[0]);
|
|
nanoSecondFieldConversion(&calculatedCycleStartTime[0]);
|
|
|
|
|
|
|
|
+ /* Set the callback -- used as a sentinel to detect an operational publisher */
|
|
|
|
+ pubServer = server;
|
|
|
|
+ pubCallback = callback;
|
|
|
|
+ pubData = data;
|
|
|
|
+
|
|
return UA_STATUSCODE_GOOD;
|
|
return UA_STATUSCODE_GOOD;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -222,6 +240,8 @@ UA_PubSubManager_changeRepeatedCallbackInterval(UA_Server *server,
|
|
|
|
|
|
void
|
|
void
|
|
UA_PubSubManager_removeRepeatedPubSubCallback(UA_Server *server, UA_UInt64 callbackId) {
|
|
UA_PubSubManager_removeRepeatedPubSubCallback(UA_Server *server, UA_UInt64 callbackId) {
|
|
|
|
+ if(!pubCallback)
|
|
|
|
+ return;
|
|
timer_delete(pubEventTimer);
|
|
timer_delete(pubEventTimer);
|
|
pubCallback = NULL; /* So that a new callback can be registered */
|
|
pubCallback = NULL; /* So that a new callback can be registered */
|
|
}
|
|
}
|
|
@@ -260,6 +280,13 @@ addPubSubConfiguration(UA_Server* server) {
|
|
counterValue.field.variable.promotedField = UA_FALSE;
|
|
counterValue.field.variable.promotedField = UA_FALSE;
|
|
counterValue.field.variable.publishParameters.publishedVariable = counterNodePublisher;
|
|
counterValue.field.variable.publishParameters.publishedVariable = counterNodePublisher;
|
|
counterValue.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
|
|
counterValue.field.variable.publishParameters.attributeId = UA_ATTRIBUTEID_VALUE;
|
|
|
|
+#ifdef UA_ENABLE_STATICVALUESOURCE
|
|
|
|
+ counterValue.field.variable.staticValueSourceEnabled = true;
|
|
|
|
+ UA_DataValue_init(&counterValue.field.variable.staticValueSource);
|
|
|
|
+ UA_Variant_setScalar(&counterValue.field.variable.staticValueSource.value,
|
|
|
|
+ &publishValue, &UA_TYPES[UA_TYPES_UINT64]);
|
|
|
|
+ counterValue.field.variable.staticValueSource.value.storageType = UA_VARIANT_DATA_NODELETE;
|
|
|
|
+#endif
|
|
UA_Server_addDataSetField(server, publishedDataSetIdent, &counterValue,
|
|
UA_Server_addDataSetField(server, publishedDataSetIdent, &counterValue,
|
|
&dataSetFieldIdentCounter);
|
|
&dataSetFieldIdentCounter);
|
|
|
|
|
|
@@ -280,6 +307,9 @@ addPubSubConfiguration(UA_Server* server) {
|
|
dataSetWriterConfig.keyFrameCount = 10;
|
|
dataSetWriterConfig.keyFrameCount = 10;
|
|
UA_Server_addDataSetWriter(server, writerGroupIdent, publishedDataSetIdent,
|
|
UA_Server_addDataSetWriter(server, writerGroupIdent, publishedDataSetIdent,
|
|
&dataSetWriterConfig, &dataSetWriterIdent);
|
|
&dataSetWriterConfig, &dataSetWriterIdent);
|
|
|
|
+
|
|
|
|
+ UA_Server_freezeWriterGroupConfiguration(server, writerGroupIdent);
|
|
|
|
+ UA_Server_setWriterGroupOperational(server, writerGroupIdent);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
static void
|
|
@@ -289,12 +319,15 @@ addServerNodes(UA_Server* server) {
|
|
UA_Variant_setScalar(&publisherAttr.value, &publishValue, &UA_TYPES[UA_TYPES_UINT64]);
|
|
UA_Variant_setScalar(&publisherAttr.value, &publishValue, &UA_TYPES[UA_TYPES_UINT64]);
|
|
publisherAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Publisher Counter");
|
|
publisherAttr.displayName = UA_LOCALIZEDTEXT("en-US", "Publisher Counter");
|
|
publisherAttr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
|
|
publisherAttr.accessLevel = UA_ACCESSLEVELMASK_READ | UA_ACCESSLEVELMASK_WRITE;
|
|
- UA_Server_addVariableNode(server, counterNodePublisher,
|
|
|
|
- UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
|
|
|
|
- UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
|
|
|
|
- UA_QUALIFIEDNAME(1, "Publisher Counter"),
|
|
|
|
- UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
|
|
|
|
- publisherAttr, NULL, NULL);
|
|
|
|
|
|
+ UA_DataSource dataSource;
|
|
|
|
+ dataSource.read = readPublishValue;
|
|
|
|
+ dataSource.write = NULL;
|
|
|
|
+ UA_Server_addDataSourceVariableNode(server, counterNodePublisher,
|
|
|
|
+ UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
|
|
|
|
+ UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
|
|
|
|
+ UA_QUALIFIEDNAME(1, "Publisher Counter"),
|
|
|
|
+ UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
|
|
|
|
+ publisherAttr, dataSource, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
/* Stop signal */
|
|
/* Stop signal */
|
|
@@ -322,7 +355,6 @@ int main(void) {
|
|
/* Run the server */
|
|
/* Run the server */
|
|
UA_StatusCode retval = UA_Server_run(server, &running);
|
|
UA_StatusCode retval = UA_Server_run(server, &running);
|
|
UA_Server_delete(server);
|
|
UA_Server_delete(server);
|
|
- UA_ServerConfig_delete(config);
|
|
|
|
|
|
|
|
return (int)retval;
|
|
return (int)retval;
|
|
}
|
|
}
|