Browse Source

Attribute service delegates the writing of all attributes but ATTRIBUTE_VALUE to the userspace setAttribute function.

ichrispa 9 years ago
parent
commit
0b8f36f6ee
2 changed files with 84 additions and 15 deletions
  1. 7 1
      examples/client.c
  2. 77 14
      src/server/ua_services_attribute.c

+ 7 - 1
examples/client.c

@@ -249,12 +249,18 @@ int main(int argc, char *argv[]) {
     // Iterate over all nodes in 'Objects'
     UA_Client_forEachChildNodeCall(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), nodeIter);
     
-    // Get a copy of the node 'TheNewVariableNode'
+    // Get a copy of the node 'TheNewVariableNode' and delete it
     void *theCopy;
     UA_Client_getNodeCopy(client, retNodeId, (void*) &theCopy);
+    UA_Client_deleteNodeCopy(client, &theCopy);
     
+    // Delete a serverside node
     UA_Client_deleteMethodNode(client, UA_NODEID_NUMERIC(1,62541));
     
+    // Set a localized string version of "Objects"
+    UA_LocalizedText objectsLocale = UA_LOCALIZEDTEXT("de_DE", "Die Objekte");
+    UA_Client_setAttributeValue(client, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_ATTRIBUTEID_WRITEMASK, (void *) &objectsLocale);
+    
     UA_Client_disconnect(client);
     UA_Client_delete(client);
     return UA_STATUSCODE_GOOD;

+ 77 - 14
src/server/ua_services_attribute.c

@@ -426,6 +426,16 @@ void Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *
 #endif
 }
 
+#define SETATTRIBUTE_IF_DATATYPE_IS(EXP_DT)                                                                             \
+/* The Userspace setAttribute expects the value being passed being the correct type and has no own means for checking   \
+   We need to check for setAttribute if the dataType is correct                                                         \
+*/                                                                                                                      \
+expectType = UA_NODEID_NUMERIC(0, UA_NS0ID_##EXP_DT);                                                                   \
+if (! UA_NodeId_equal(&expectType, &wvalue->value.value.type->typeId))                                                  \
+  retval |= UA_STATUSCODE_BADTYPEMISMATCH;                                                                              \
+else                                                                                                                    \
+  retval = UA_Server_setAttributeValue(server, wvalue->nodeId, wvalue->attributeId, (void *) wvalue->value.value.data); \
+
 #ifndef BUILD_UNIT_TESTS
 static
 #endif
@@ -438,26 +448,87 @@ UA_StatusCode writeValue(UA_Server *server, UA_WriteValue *wvalue) {
 
     // we might repeat writing, e.g. when the node got replaced mid-work
     UA_Boolean done = UA_FALSE;
+    UA_NodeId expectType;
     while(!done) {
         const UA_Node *node = UA_NodeStore_get(server->nodestore, &wvalue->nodeId);
         if(!node)
             return UA_STATUSCODE_BADNODEIDUNKNOWN;
 
         switch(wvalue->attributeId) {
-        case UA_ATTRIBUTEID_NODEID:
-        case UA_ATTRIBUTEID_NODECLASS:
         case UA_ATTRIBUTEID_BROWSENAME:
+          SETATTRIBUTE_IF_DATATYPE_IS(QUALIFIEDNAME)
+          done = UA_TRUE;
+          break;
         case UA_ATTRIBUTEID_DISPLAYNAME:
+          SETATTRIBUTE_IF_DATATYPE_IS(UINT32)
+          done = UA_TRUE;
+          break;
         case UA_ATTRIBUTEID_DESCRIPTION:
+          SETATTRIBUTE_IF_DATATYPE_IS(UINT32)
+          done = UA_TRUE;
+          break;
         case UA_ATTRIBUTEID_WRITEMASK:
+          SETATTRIBUTE_IF_DATATYPE_IS(UINT32)
+          done = UA_TRUE;
+          break;
         case UA_ATTRIBUTEID_USERWRITEMASK:
+          SETATTRIBUTE_IF_DATATYPE_IS(UINT32)
+          done = UA_TRUE;
+          break;
         case UA_ATTRIBUTEID_ISABSTRACT:
+          SETATTRIBUTE_IF_DATATYPE_IS(BOOLEAN)
+          done = UA_TRUE;
+          break;
         case UA_ATTRIBUTEID_SYMMETRIC:
+          SETATTRIBUTE_IF_DATATYPE_IS(BOOLEAN)
+          done = UA_TRUE;
+          break;
         case UA_ATTRIBUTEID_INVERSENAME:
+          SETATTRIBUTE_IF_DATATYPE_IS(UINT32)
+          done = UA_TRUE;
+          break;
         case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
+          SETATTRIBUTE_IF_DATATYPE_IS(BOOLEAN)
+          done = UA_TRUE;
+          break;
         case UA_ATTRIBUTEID_EVENTNOTIFIER:
-            retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-            break;
+          SETATTRIBUTE_IF_DATATYPE_IS(BYTE)
+          done = UA_TRUE;
+          break;
+        case UA_ATTRIBUTEID_VALUERANK:
+          SETATTRIBUTE_IF_DATATYPE_IS(INT32)
+          done = UA_TRUE;
+          break;
+        case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
+          SETATTRIBUTE_IF_DATATYPE_IS(INT32)
+          done = UA_TRUE;
+          break;
+        case UA_ATTRIBUTEID_ACCESSLEVEL:
+          SETATTRIBUTE_IF_DATATYPE_IS(UINT32)
+          done = UA_TRUE;
+          break;
+        case UA_ATTRIBUTEID_USERACCESSLEVEL:
+          SETATTRIBUTE_IF_DATATYPE_IS(UINT32)
+          done = UA_TRUE;
+          break;
+        case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
+          SETATTRIBUTE_IF_DATATYPE_IS(DOUBLE)
+          done = UA_TRUE;
+          break;
+        case UA_ATTRIBUTEID_HISTORIZING:
+          SETATTRIBUTE_IF_DATATYPE_IS(BOOLEAN)
+          done = UA_TRUE;
+          break;
+        case UA_ATTRIBUTEID_EXECUTABLE:
+          SETATTRIBUTE_IF_DATATYPE_IS(BOOLEAN)
+          done = UA_TRUE;
+          break;
+        case UA_ATTRIBUTEID_USEREXECUTABLE:
+          SETATTRIBUTE_IF_DATATYPE_IS(LOCALIZEDTEXT)
+          done = UA_TRUE;
+          break;
+        // The value logic implemented by jpfr is far more advanced that that in the userspace, so we use that
+        // here
         case UA_ATTRIBUTEID_VALUE: {
             if(node->nodeClass != UA_NODECLASS_VARIABLE &&
                node->nodeClass != UA_NODECLASS_VARIABLETYPE) {
@@ -552,17 +623,9 @@ UA_StatusCode writeValue(UA_Server *server, UA_WriteValue *wvalue) {
                 UA_free(range.dimensions);
             }
             break;
+        case UA_ATTRIBUTEID_NODEID:
+        case UA_ATTRIBUTEID_NODECLASS:
         case UA_ATTRIBUTEID_DATATYPE:
-        case UA_ATTRIBUTEID_VALUERANK:
-        case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
-        case UA_ATTRIBUTEID_ACCESSLEVEL:
-        case UA_ATTRIBUTEID_USERACCESSLEVEL:
-        case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
-        case UA_ATTRIBUTEID_HISTORIZING:
-        case UA_ATTRIBUTEID_EXECUTABLE:
-        case UA_ATTRIBUTEID_USEREXECUTABLE:
-            retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
-            break;
         default:
             retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
             break;