|
@@ -39,8 +39,7 @@ UA_Logger logger;
|
|
/*************************/
|
|
/*************************/
|
|
/* Read-only data source */
|
|
/* Read-only data source */
|
|
/*************************/
|
|
/*************************/
|
|
-static UA_StatusCode readTimeData(void *handle, UA_Boolean sourceTimeStamp,
|
|
|
|
- const UA_NumericRange *range, UA_DataValue *value) {
|
|
|
|
|
|
+static UA_StatusCode readTimeData(void *handle, UA_Boolean sourceTimeStamp, const UA_NumericRange *range, UA_DataValue *value) {
|
|
if(range) {
|
|
if(range) {
|
|
value->hasStatus = UA_TRUE;
|
|
value->hasStatus = UA_TRUE;
|
|
value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
|
|
value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
|
|
@@ -53,8 +52,6 @@ static UA_StatusCode readTimeData(void *handle, UA_Boolean sourceTimeStamp,
|
|
value->value.type = &UA_TYPES[UA_TYPES_DATETIME];
|
|
value->value.type = &UA_TYPES[UA_TYPES_DATETIME];
|
|
value->value.arrayLength = -1;
|
|
value->value.arrayLength = -1;
|
|
value->value.data = currentTime;
|
|
value->value.data = currentTime;
|
|
- value->value.arrayDimensionsSize = -1;
|
|
|
|
- value->value.arrayDimensions = NULL;
|
|
|
|
value->hasValue = UA_TRUE;
|
|
value->hasValue = UA_TRUE;
|
|
if(sourceTimeStamp) {
|
|
if(sourceTimeStamp) {
|
|
value->hasSourceTimestamp = UA_TRUE;
|
|
value->hasSourceTimestamp = UA_TRUE;
|
|
@@ -63,18 +60,12 @@ static UA_StatusCode readTimeData(void *handle, UA_Boolean sourceTimeStamp,
|
|
return UA_STATUSCODE_GOOD;
|
|
return UA_STATUSCODE_GOOD;
|
|
}
|
|
}
|
|
|
|
|
|
-static void releaseTimeData(void *handle, UA_DataValue *value) {
|
|
|
|
- if(value->hasValue)
|
|
|
|
- UA_DateTime_delete((UA_DateTime*)value->value.data);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/*****************************/
|
|
/*****************************/
|
|
/* Read-only CPU temperature */
|
|
/* Read-only CPU temperature */
|
|
/* Only on Linux */
|
|
/* Only on Linux */
|
|
/*****************************/
|
|
/*****************************/
|
|
FILE* temperatureFile = NULL;
|
|
FILE* temperatureFile = NULL;
|
|
-static UA_StatusCode readTemperature(void *handle, UA_Boolean sourceTimeStamp,
|
|
|
|
- const UA_NumericRange *range, UA_DataValue *value) {
|
|
|
|
|
|
+static UA_StatusCode readTemperature(void *handle, UA_Boolean sourceTimeStamp, const UA_NumericRange *range, UA_DataValue *value) {
|
|
if(range) {
|
|
if(range) {
|
|
value->hasStatus = UA_TRUE;
|
|
value->hasStatus = UA_TRUE;
|
|
value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
|
|
value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
|
|
@@ -104,11 +95,6 @@ static UA_StatusCode readTemperature(void *handle, UA_Boolean sourceTimeStamp,
|
|
return UA_STATUSCODE_GOOD;
|
|
return UA_STATUSCODE_GOOD;
|
|
}
|
|
}
|
|
|
|
|
|
-static void releaseTemperature(void *handle, UA_DataValue *value) {
|
|
|
|
- if(value->hasValue)
|
|
|
|
- UA_Double_delete((UA_Double*)value->value.data);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/*************************/
|
|
/*************************/
|
|
/* Read-write status led */
|
|
/* Read-write status led */
|
|
/*************************/
|
|
/*************************/
|
|
@@ -119,25 +105,13 @@ FILE* triggerFile = NULL;
|
|
FILE* ledFile = NULL;
|
|
FILE* ledFile = NULL;
|
|
UA_Boolean ledStatus = 0;
|
|
UA_Boolean ledStatus = 0;
|
|
|
|
|
|
-static UA_StatusCode readLedStatus(void *handle, UA_Boolean sourceTimeStamp,
|
|
|
|
- const UA_NumericRange *range, UA_DataValue *value) {
|
|
|
|
- if(range) {
|
|
|
|
- value->hasStatus = UA_TRUE;
|
|
|
|
- value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
|
|
|
|
- return UA_STATUSCODE_GOOD;
|
|
|
|
- }
|
|
|
|
|
|
+static UA_StatusCode readLedStatus(void *handle, UA_Boolean sourceTimeStamp, const UA_NumericRange *range, UA_DataValue *value) {
|
|
|
|
+ if(range)
|
|
|
|
+ return UA_STATUSCODE_BADINDEXRANGEINVALID;
|
|
|
|
|
|
- /* In order to reduce blocking time, we could alloc memory for every read
|
|
|
|
- and return a copy of the data. */
|
|
|
|
-#ifdef UA_MULTITHREADING
|
|
|
|
- pthread_rwlock_rdlock(&writeLock);
|
|
|
|
-#endif
|
|
|
|
- value->value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
|
|
|
|
- value->value.arrayLength = -1;
|
|
|
|
- value->value.data = &ledStatus;
|
|
|
|
- value->value.arrayDimensionsSize = -1;
|
|
|
|
- value->value.arrayDimensions = NULL;
|
|
|
|
- value->hasValue = UA_TRUE;
|
|
|
|
|
|
+ UA_StatusCode retval = UA_Variant_setScalarCopy(&value->value, &ledStatus, &UA_TYPES[UA_TYPES_BOOLEAN]);
|
|
|
|
+ if(retval != UA_STATUSCODE_GOOD)
|
|
|
|
+ return retval;
|
|
if(sourceTimeStamp) {
|
|
if(sourceTimeStamp) {
|
|
value->sourceTimestamp = UA_DateTime_now();
|
|
value->sourceTimestamp = UA_DateTime_now();
|
|
value->hasSourceTimestamp = UA_TRUE;
|
|
value->hasSourceTimestamp = UA_TRUE;
|
|
@@ -145,18 +119,6 @@ static UA_StatusCode readLedStatus(void *handle, UA_Boolean sourceTimeStamp,
|
|
return UA_STATUSCODE_GOOD;
|
|
return UA_STATUSCODE_GOOD;
|
|
}
|
|
}
|
|
|
|
|
|
-static void releaseLedStatus(void *handle, UA_DataValue *value) {
|
|
|
|
- if(!value->hasValue)
|
|
|
|
- return;
|
|
|
|
- /* If we allocated memory for a specific read, free the content of the
|
|
|
|
- variantdata. */
|
|
|
|
- value->value.arrayLength = -1;
|
|
|
|
- value->value.data = NULL;
|
|
|
|
-#ifdef UA_MULTITHREADING
|
|
|
|
- pthread_rwlock_unlock(&writeLock);
|
|
|
|
-#endif
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static UA_StatusCode writeLedStatus(void *handle, const UA_Variant *data, const UA_NumericRange *range) {
|
|
static UA_StatusCode writeLedStatus(void *handle, const UA_Variant *data, const UA_NumericRange *range) {
|
|
if(range)
|
|
if(range)
|
|
return UA_STATUSCODE_BADINDEXRANGEINVALID;
|
|
return UA_STATUSCODE_BADINDEXRANGEINVALID;
|
|
@@ -170,12 +132,11 @@ static UA_StatusCode writeLedStatus(void *handle, const UA_Variant *data, const
|
|
if(triggerFile)
|
|
if(triggerFile)
|
|
fseek(triggerFile, 0, SEEK_SET);
|
|
fseek(triggerFile, 0, SEEK_SET);
|
|
|
|
|
|
- if(ledFile){
|
|
|
|
- if(ledStatus == 1){
|
|
|
|
|
|
+ if(ledFile) {
|
|
|
|
+ if(ledStatus == 1)
|
|
fprintf(ledFile, "%s", "1");
|
|
fprintf(ledFile, "%s", "1");
|
|
- } else {
|
|
|
|
|
|
+ else
|
|
fprintf(ledFile, "%s", "0");
|
|
fprintf(ledFile, "%s", "0");
|
|
- }
|
|
|
|
fflush(ledFile);
|
|
fflush(ledFile);
|
|
}
|
|
}
|
|
#ifdef UA_MULTITHREADING
|
|
#ifdef UA_MULTITHREADING
|
|
@@ -192,10 +153,7 @@ static void stopHandler(int sign) {
|
|
static UA_ByteString loadCertificate(void) {
|
|
static UA_ByteString loadCertificate(void) {
|
|
UA_ByteString certificate = UA_STRING_NULL;
|
|
UA_ByteString certificate = UA_STRING_NULL;
|
|
FILE *fp = NULL;
|
|
FILE *fp = NULL;
|
|
- //FIXME: a potential bug of locating the certificate, we need to get the path from the server's config
|
|
|
|
- fp=fopen("server_cert.der", "rb");
|
|
|
|
-
|
|
|
|
- if(!fp) {
|
|
|
|
|
|
+ if(!(fp=fopen("server_cert.der", "rb"))) {
|
|
errno = 0; // we read errno also from the tcp layer...
|
|
errno = 0; // we read errno also from the tcp layer...
|
|
return certificate;
|
|
return certificate;
|
|
}
|
|
}
|
|
@@ -229,36 +187,24 @@ int main(int argc, char** argv) {
|
|
UA_Server_addNetworkLayer(server, ServerNetworkLayerTCP_new(UA_ConnectionConfig_standard, 16664));
|
|
UA_Server_addNetworkLayer(server, ServerNetworkLayerTCP_new(UA_ConnectionConfig_standard, 16664));
|
|
|
|
|
|
// add node with the datetime data source
|
|
// add node with the datetime data source
|
|
- UA_DataSource dateDataSource = (UA_DataSource)
|
|
|
|
- {.handle = NULL,
|
|
|
|
- .read = readTimeData,
|
|
|
|
- .release = releaseTimeData,
|
|
|
|
- .write = NULL};
|
|
|
|
|
|
+ UA_DataSource dateDataSource = (UA_DataSource) {.handle = NULL, .read = readTimeData, .write = NULL};
|
|
const UA_QualifiedName dateName = UA_QUALIFIEDNAME(1, "current time");
|
|
const UA_QualifiedName dateName = UA_QUALIFIEDNAME(1, "current time");
|
|
UA_Server_addDataSourceVariableNode(server, dateDataSource, dateName, UA_NODEID_NULL,
|
|
UA_Server_addDataSourceVariableNode(server, dateDataSource, dateName, UA_NODEID_NULL,
|
|
- UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
|
|
|
|
- UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
|
|
|
|
|
|
+ UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
|
|
|
|
|
|
#ifndef _WIN32
|
|
#ifndef _WIN32
|
|
//cpu temperature monitoring for linux machines
|
|
//cpu temperature monitoring for linux machines
|
|
- if((temperatureFile = fopen("/sys/class/thermal/thermal_zone0/temp", "r"))){
|
|
|
|
|
|
+ if((temperatureFile = fopen("/sys/class/thermal/thermal_zone0/temp", "r"))) {
|
|
// add node with the data source
|
|
// add node with the data source
|
|
- UA_DataSource temperatureDataSource = (UA_DataSource)
|
|
|
|
- {.handle = NULL,
|
|
|
|
- .read = readTemperature,
|
|
|
|
- .release = releaseTemperature,
|
|
|
|
- .write = NULL};
|
|
|
|
|
|
+ UA_DataSource temperatureDataSource = (UA_DataSource) {.handle = NULL, .read = readTemperature, .write = NULL};
|
|
const UA_QualifiedName tempName = UA_QUALIFIEDNAME(1, "cpu temperature");
|
|
const UA_QualifiedName tempName = UA_QUALIFIEDNAME(1, "cpu temperature");
|
|
UA_Server_addDataSourceVariableNode(server, temperatureDataSource, tempName, UA_NODEID_NULL,
|
|
UA_Server_addDataSourceVariableNode(server, temperatureDataSource, tempName, UA_NODEID_NULL,
|
|
- UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
|
|
|
|
- UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
|
|
|
|
|
|
+ UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES));
|
|
}
|
|
}
|
|
|
|
|
|
//LED control for rpi
|
|
//LED control for rpi
|
|
- if( access("/sys/class/leds/led0/trigger", F_OK ) != -1
|
|
|
|
- || access("/sys/class/leds/led0/brightness", F_OK ) != -1){
|
|
|
|
- if ( (triggerFile = fopen("/sys/class/leds/led0/trigger", "w"))
|
|
|
|
- && (ledFile = fopen("/sys/class/leds/led0/brightness", "w"))) {
|
|
|
|
|
|
+ if(access("/sys/class/leds/led0/trigger", F_OK ) != -1 || access("/sys/class/leds/led0/brightness", F_OK ) != -1) {
|
|
|
|
+ if((triggerFile = fopen("/sys/class/leds/led0/trigger", "w")) && (ledFile = fopen("/sys/class/leds/led0/brightness", "w"))) {
|
|
//setting led mode to manual
|
|
//setting led mode to manual
|
|
fprintf(triggerFile, "%s", "none");
|
|
fprintf(triggerFile, "%s", "none");
|
|
fflush(triggerFile);
|
|
fflush(triggerFile);
|
|
@@ -268,16 +214,12 @@ int main(int argc, char** argv) {
|
|
fflush(ledFile);
|
|
fflush(ledFile);
|
|
|
|
|
|
// add node with the LED status data source
|
|
// add node with the LED status data source
|
|
- UA_DataSource ledStatusDataSource = (UA_DataSource)
|
|
|
|
- {.handle = NULL,
|
|
|
|
- .read = readLedStatus,
|
|
|
|
- .release = releaseLedStatus,
|
|
|
|
- .write = writeLedStatus};
|
|
|
|
|
|
+ UA_DataSource ledStatusDataSource = (UA_DataSource) {.handle = NULL, .read = readLedStatus, .write = writeLedStatus};
|
|
const UA_QualifiedName statusName = UA_QUALIFIEDNAME(0, "status LED");
|
|
const UA_QualifiedName statusName = UA_QUALIFIEDNAME(0, "status LED");
|
|
UA_Server_addDataSourceVariableNode(server, ledStatusDataSource, statusName, UA_NODEID_NULL,
|
|
UA_Server_addDataSourceVariableNode(server, ledStatusDataSource, statusName, UA_NODEID_NULL,
|
|
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));
|
|
- }else{
|
|
|
|
|
|
+ } else {
|
|
UA_LOG_WARNING(logger, UA_LOGCATEGORY_USERLAND, "[Raspberry Pi] LED file exist, but I have no access (try to run server with sudo)");
|
|
UA_LOG_WARNING(logger, UA_LOGCATEGORY_USERLAND, "[Raspberry Pi] LED file exist, but I have no access (try to run server with sudo)");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -299,13 +241,16 @@ int main(int argc, char** argv) {
|
|
/**************/
|
|
/**************/
|
|
|
|
|
|
#define DEMOID 50000
|
|
#define DEMOID 50000
|
|
- UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Demo"), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
|
|
|
|
|
|
+ UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Demo"), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
|
|
|
|
+ UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
|
|
|
|
|
|
#define SCALARID 50001
|
|
#define SCALARID 50001
|
|
- UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Scalar"), UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
|
|
|
|
|
|
+ UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Scalar"), UA_NODEID_NUMERIC(1, SCALARID), UA_NODEID_NUMERIC(1, DEMOID),
|
|
|
|
+ UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
|
|
|
|
|
|
#define ARRAYID 50002
|
|
#define ARRAYID 50002
|
|
- UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Array"), UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(1, DEMOID), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
|
|
|
|
|
|
+ UA_Server_addObjectNode(server,UA_QUALIFIEDNAME(1, "Array"), UA_NODEID_NUMERIC(1, ARRAYID), UA_NODEID_NUMERIC(1, DEMOID),
|
|
|
|
+ UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), UA_NODEID_NUMERIC(0, UA_NS0ID_FOLDERTYPE));
|
|
|
|
|
|
UA_UInt32 id = 51000; //running id in namespace 0
|
|
UA_UInt32 id = 51000; //running id in namespace 0
|
|
for(UA_UInt32 type = 0; UA_IS_BUILTIN(type); type++) {
|
|
for(UA_UInt32 type = 0; UA_IS_BUILTIN(type); type++) {
|
|
@@ -337,16 +282,15 @@ int main(int argc, char** argv) {
|
|
if(temperatureFile)
|
|
if(temperatureFile)
|
|
fclose(temperatureFile);
|
|
fclose(temperatureFile);
|
|
|
|
|
|
- if(triggerFile){
|
|
|
|
|
|
+ if(triggerFile) {
|
|
fseek(triggerFile, 0, SEEK_SET);
|
|
fseek(triggerFile, 0, SEEK_SET);
|
|
//setting led mode to default
|
|
//setting led mode to default
|
|
fprintf(triggerFile, "%s", "mmc0");
|
|
fprintf(triggerFile, "%s", "mmc0");
|
|
fclose(triggerFile);
|
|
fclose(triggerFile);
|
|
}
|
|
}
|
|
|
|
|
|
- if(ledFile){
|
|
|
|
|
|
+ if(ledFile)
|
|
fclose(ledFile);
|
|
fclose(ledFile);
|
|
- }
|
|
|
|
|
|
|
|
#ifdef UA_MULTITHREADING
|
|
#ifdef UA_MULTITHREADING
|
|
pthread_rwlock_destroy(&writeLock);
|
|
pthread_rwlock_destroy(&writeLock);
|