Explorar el Código

Merge pull request #1608 from open62541/hotfix/examples_variable_type

Set variable types in examples and add example for _begin and _finish
Stefan Profanter hace 7 años
padre
commit
aa257fc013

+ 155 - 28
examples/server_inheritance.c

@@ -9,31 +9,28 @@ static void stopHandler(int sig) {
     running = false;
 }
 
-int main(void) {
-    signal(SIGINT,  stopHandler);
-    signal(SIGTERM, stopHandler);
+/**
+ * This will create a type structure and some instances of the types:
+ *
+ * Create a rudimentary objectType
+ *
+ * Type:
+ * + MamalType
+ *  v- Class  = "mamalia"
+ *  v- Species
+ *  o- Abilities
+ *      v- MakeSound
+ *      v- Breathe = True
+ *  + DogType
+ *      v- Species = "Canis"
+ *      v- Name
+ *      o- Abilities
+ *          v- MakeSound = "Wuff"
+ *           v- FetchNewPaper
+ */
+static void createMamals(UA_Server *server) {
 
-    UA_ServerConfig *config = UA_ServerConfig_new_default();
-    UA_Server *server = UA_Server_new(config);
-
-    /* Create a rudimentary objectType
-     *
-     * Type:
-     * + MamalType
-     *  v- Class  = "mamalia"
-     *  v- Species
-     *  o- Abilities
-     *      v- MakeSound
-     *      v- Breathe = True
-     *  + DogType
-     *      v- Species = "Canis"
-     *      v- Name
-     *      o- Abilities
-     *          v- MakeSound = "Wuff"
-     *           v- FetchNewPaper
-     */
 
-    UA_StatusCode retval;
     UA_ObjectTypeAttributes otAttr = UA_ObjectTypeAttributes_default;
     otAttr.description = UA_LOCALIZEDTEXT("en-US", "A mamal");
     otAttr.displayName = UA_LOCALIZEDTEXT("en-US", "MamalType");
@@ -50,7 +47,7 @@ int main(void) {
     UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, 10001),
                               UA_NODEID_NUMERIC(1, 10000),
                               UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
-                              UA_QUALIFIEDNAME(1, "Class"), UA_NODEID_NULL,
+                              UA_QUALIFIEDNAME(1, "Class"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
                               vAttr, NULL, NULL);
 
     vAttr = UA_VariableAttributes_default;
@@ -59,7 +56,7 @@ int main(void) {
     UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, 10002),
                               UA_NODEID_NUMERIC(1, 10000),
                               UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
-                              UA_QUALIFIEDNAME(1, "Species"), UA_NODEID_NULL,
+                              UA_QUALIFIEDNAME(1, "Species"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
                               vAttr, NULL, NULL);
 
     otAttr = UA_ObjectTypeAttributes_default;
@@ -78,7 +75,7 @@ int main(void) {
     UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, 20001),
                               UA_NODEID_NUMERIC(1, 20000),
                               UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
-                              UA_QUALIFIEDNAME(1, "Species"), UA_NODEID_NULL,
+                              UA_QUALIFIEDNAME(1, "Species"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
                               vAttr, NULL, NULL);
 
     vAttr = UA_VariableAttributes_default;
@@ -89,7 +86,7 @@ int main(void) {
     UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, 20002),
                               UA_NODEID_NUMERIC(1, 20000),
                               UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
-                              UA_QUALIFIEDNAME(1, "Name"), UA_NODEID_NULL,
+                              UA_QUALIFIEDNAME(1, "Name"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
                               vAttr, NULL, NULL);
 
     /* Instatiate a dog named bello:
@@ -126,8 +123,138 @@ int main(void) {
                             UA_QUALIFIEDNAME(1, "Mamal1"), UA_NODEID_NUMERIC(1, 10000),
                             oAttr, NULL, NULL);
 
+}
+
+/**
+ * This method shows the usage of _begin and _finish methods.
+ * Normally, if you create an instance of an object type, all its
+ * mandatory children are inherited and created.
+ * It could be the case that you first need to create a node,
+ * add some children with specific IDs and then all the remaining
+ * inherited children should be created.
+ * For this use-case you can use first the _begin method,
+ * which creates the node, including its parent references.
+ * Then you can add any children, and then you should
+ * call _finish on that node, which then adds all the inherited children.
+ *
+ * For further details check the example below or the corresponding
+ * method documentation.
+ *
+ * To demonstrate this, we use the following example:
+ *
+ * + ObjectType
+ *      + LampType (Object)
+ *          + IsOn (Variable, Boolean, Mandatory)
+ *          + Brightness (Variable, UInt16, Mandatory)
+ * + Objects
+ *      + LampGreen
+ *          Should inherit the mandatory IsOn and Brightness with a generated node ID
+ *      + LampRed
+ *          IsOn should have the node ID 30101, Brightness will be inherited with a generated node ID
+ *
+ */
+static void createCustomInheritance(UA_Server *server) {
+
+    /* Add LampType object type node */
+
+    UA_ObjectTypeAttributes otAttr = UA_ObjectTypeAttributes_default;
+    otAttr.description = UA_LOCALIZEDTEXT("en-US", "A Lamp");
+    otAttr.displayName = UA_LOCALIZEDTEXT("en-US", "LampType");
+    UA_Server_addObjectTypeNode(server, UA_NODEID_NUMERIC(1, 30000),
+                                UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
+                                UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE),
+                                UA_QUALIFIEDNAME(1, "LampType"), otAttr, NULL, NULL);
+
+
+    /* Add the two mandatory children, IsOn and Brightness */
+    UA_VariableAttributes vAttr = UA_VariableAttributes_default;
+    vAttr.description =  UA_LOCALIZEDTEXT("en-US", "Switch lamp on/off");
+    vAttr.displayName =  UA_LOCALIZEDTEXT("en-US", "IsOn");
+    UA_Boolean isOn = UA_FALSE;
+    UA_Variant_setScalar(&vAttr.value, &isOn, &UA_TYPES[UA_TYPES_BOOLEAN]);
+    UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, 30001),
+                              UA_NODEID_NUMERIC(1, 30000),
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
+                              UA_QUALIFIEDNAME(1, "IsOn"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
+                              vAttr, NULL, NULL);
+    UA_Server_addReference(server, UA_NODEID_NUMERIC(1, 30001),
+                           UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),
+                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY), true);
+
+    vAttr = UA_VariableAttributes_default;
+    vAttr.description =  UA_LOCALIZEDTEXT("en-US", "Lamp brightness");
+    vAttr.displayName =  UA_LOCALIZEDTEXT("en-US", "Brightness");
+    UA_UInt16 brightness = 142;
+    UA_Variant_setScalar(&vAttr.value, &brightness, &UA_TYPES[UA_TYPES_UINT16]);
+    UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, 30002),
+                              UA_NODEID_NUMERIC(1, 30000),
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
+                              UA_QUALIFIEDNAME(1, "Brightness"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
+                              vAttr, NULL, NULL);
+    UA_Server_addReference(server, UA_NODEID_NUMERIC(1, 30002),
+                           UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),
+                           UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY), true);
+    
+    /* Now we want to inherit all the mandatory children for LampGreen and don't care about the node ids.
+     * These will be automatically generated. This will internally call the _begin and _finish methods */
+
+    UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
+    oAttr.description = UA_LOCALIZEDTEXT("en-US", "A green lamp");
+    oAttr.displayName = UA_LOCALIZEDTEXT("en-US", "LampGreen");
+    UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0),
+                            UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
+                            UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+                            UA_QUALIFIEDNAME(1, "LampGreen"), UA_NODEID_NUMERIC(1, 30000),
+                            oAttr, NULL, NULL);
+
+    /* For the red lamp we want to set the node ID of the IsOn child manually, thus we need to use
+     * the _begin method, add the child and then _finish: */
+
+    /* The call to UA_Server_addNode_begin will create the node and its parent references,
+     * but it will not instantiate the mandatory children */
+    oAttr = UA_ObjectAttributes_default;
+    oAttr.description = UA_LOCALIZEDTEXT("en-US", "A red lamp");
+    oAttr.displayName = UA_LOCALIZEDTEXT("en-US", "LampRed");
+    UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
+                            UA_NODEID_NUMERIC(1, 30100),
+                            UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
+                            UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
+                            UA_QUALIFIEDNAME(1, "LampRed"),
+                            UA_NODEID_NUMERIC(1, 30000),
+                            (const UA_NodeAttributes*)&oAttr, &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],
+                            NULL, NULL);
+
+    /* Now we can add the IsOn with our own node ID */
+    vAttr = UA_VariableAttributes_default;
+    vAttr.description =  UA_LOCALIZEDTEXT("en-US", "Switch lamp on/off");
+    vAttr.displayName =  UA_LOCALIZEDTEXT("en-US", "IsOn");
+    isOn = UA_FALSE;
+    UA_Variant_setScalar(&vAttr.value, &isOn, &UA_TYPES[UA_TYPES_BOOLEAN]);
+    UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, 30101),
+                              UA_NODEID_NUMERIC(1, 30100),
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
+                              UA_QUALIFIEDNAME(1, "IsOn"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
+                              vAttr, NULL, NULL);
+
+    /* And then we need to call the UA_Server_addNode_finish which adds all the remaining
+     * children and does some further initialization. It will not add the IsNode child,
+     * since a child with the same browse name already exists */
+    UA_Server_addNode_finish(server, UA_NODEID_NUMERIC(1, 30100));
+}
+
+int main(void) {
+    signal(SIGINT,  stopHandler);
+    signal(SIGTERM, stopHandler);
+
+    UA_ServerConfig *config = UA_ServerConfig_new_default();
+    UA_Server *server = UA_Server_new(config);
+
+    createMamals(server);
+
+    createCustomInheritance(server);
+
     /* Run the server */
-    retval = UA_Server_run(server, &running);
+    UA_StatusCode retval = UA_Server_run(server, &running);
     UA_Server_delete(server);
     UA_ServerConfig_delete(config);
     return (int)retval;

+ 2 - 2
examples/server_instantiation.c

@@ -42,7 +42,7 @@ int main(void) {
     UA_Variant_setScalar(&vAttr.value, &ageVar, &UA_TYPES[UA_TYPES_UINT32]);
     UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, 10001),
                               UA_NODEID_NUMERIC(1, 10000), UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
-                              UA_QUALIFIEDNAME(1, "Age"), UA_NODEID_NULL, vAttr, NULL, NULL);
+                              UA_QUALIFIEDNAME(1, "Age"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), vAttr, NULL, NULL);
 
     otAttr = UA_ObjectTypeAttributes_default;
     otAttr.description = UA_LOCALIZEDTEXT("en-US", "A dog, subtype of mamal");
@@ -58,7 +58,7 @@ int main(void) {
     UA_Variant_setScalar(&vAttr.value, &defaultName, &UA_TYPES[UA_TYPES_STRING]);
     UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(1, 10003),
                               UA_NODEID_NUMERIC(1, 10002), UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
-                              UA_QUALIFIEDNAME(1, "Name"), UA_NODEID_NULL, vAttr, NULL, NULL);
+                              UA_QUALIFIEDNAME(1, "Name"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), vAttr, NULL, NULL);
 
     /* Instatiate a dog named bello:
      * (O) Objects

+ 2 - 2
examples/tutorial_server_datasource.c

@@ -49,7 +49,7 @@ addCurrentTimeVariable(UA_Server *server) {
     UA_QualifiedName currentName = UA_QUALIFIEDNAME(1, "current-time");
     UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
     UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
-    UA_NodeId variableTypeNodeId = UA_NODEID_NULL;
+    UA_NodeId variableTypeNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
     UA_Server_addVariableNode(server, currentNodeId, parentNodeId,
                               parentReferenceNodeId, currentName,
                               variableTypeNodeId, attr, NULL, NULL);
@@ -140,7 +140,7 @@ addCurrentTimeDataSourceVariable(UA_Server *server) {
     UA_QualifiedName currentName = UA_QUALIFIEDNAME(1, "current-time-datasource");
     UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
     UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
-    UA_NodeId variableTypeNodeId = UA_NODEID_NULL;
+    UA_NodeId variableTypeNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE);
 
     UA_DataSource timeDataSource;
     timeDataSource.read = readCurrentTime;

+ 9 - 9
examples/tutorial_server_object.c

@@ -66,7 +66,7 @@ manuallyDefinePump(UA_Server *server) {
     UA_Server_addObjectNode(server, UA_NODEID_NULL,
                             UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
                             UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES),
-                            UA_QUALIFIEDNAME(1, "Pump (Manual)"), UA_NODEID_NULL,
+                            UA_QUALIFIEDNAME(1, "Pump (Manual)"), UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE),
                             oAttr, NULL, &pumpId);
 
     UA_VariableAttributes mnAttr = UA_VariableAttributes_default;
@@ -76,7 +76,7 @@ manuallyDefinePump(UA_Server *server) {
     UA_Server_addVariableNode(server, UA_NODEID_NULL, pumpId,
                               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
                               UA_QUALIFIEDNAME(1, "ManufacturerName"),
-                              UA_NODEID_NULL, mnAttr, NULL, NULL);
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), mnAttr, NULL, NULL);
 
     UA_VariableAttributes modelAttr = UA_VariableAttributes_default;
     UA_String modelName = UA_STRING("Mega Pump 3000");
@@ -85,7 +85,7 @@ manuallyDefinePump(UA_Server *server) {
     UA_Server_addVariableNode(server, UA_NODEID_NULL, pumpId,
                               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
                               UA_QUALIFIEDNAME(1, "ModelName"),
-                              UA_NODEID_NULL, modelAttr, NULL, NULL);
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), modelAttr, NULL, NULL);
 
     UA_VariableAttributes statusAttr = UA_VariableAttributes_default;
     UA_Boolean status = true;
@@ -94,7 +94,7 @@ manuallyDefinePump(UA_Server *server) {
     UA_Server_addVariableNode(server, UA_NODEID_NULL, pumpId,
                               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
                               UA_QUALIFIEDNAME(1, "Status"),
-                              UA_NODEID_NULL, statusAttr, NULL, NULL);
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), statusAttr, NULL, NULL);
 
     UA_VariableAttributes rpmAttr = UA_VariableAttributes_default;
     UA_Double rpm = 50.0;
@@ -103,7 +103,7 @@ manuallyDefinePump(UA_Server *server) {
     UA_Server_addVariableNode(server, UA_NODEID_NULL, pumpId,
                               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
                               UA_QUALIFIEDNAME(1, "MotorRPMs"),
-                              UA_NODEID_NULL, rpmAttr, NULL, NULL);
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), rpmAttr, NULL, NULL);
 }
 
 /**
@@ -183,7 +183,7 @@ defineObjectTypes(UA_Server *server) {
     UA_Server_addVariableNode(server, UA_NODEID_NULL, deviceTypeId,
                               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
                               UA_QUALIFIEDNAME(1, "ManufacturerName"),
-                              UA_NODEID_NULL, mnAttr, NULL, &manufacturerNameId);
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), mnAttr, NULL, &manufacturerNameId);
     /* Make the manufacturer name mandatory */
     UA_Server_addReference(server, manufacturerNameId,
                            UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),
@@ -195,7 +195,7 @@ defineObjectTypes(UA_Server *server) {
     UA_Server_addVariableNode(server, UA_NODEID_NULL, deviceTypeId,
                               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
                               UA_QUALIFIEDNAME(1, "ModelName"),
-                              UA_NODEID_NULL, modelAttr, NULL, NULL);
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), modelAttr, NULL, NULL);
 
     /* Define the object type for "Pump" */
     UA_ObjectTypeAttributes ptAttr = UA_ObjectTypeAttributes_default;
@@ -212,7 +212,7 @@ defineObjectTypes(UA_Server *server) {
     UA_Server_addVariableNode(server, UA_NODEID_NULL, pumpTypeId,
                               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
                               UA_QUALIFIEDNAME(1, "Status"),
-                              UA_NODEID_NULL, statusAttr, NULL, &statusId);
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), statusAttr, NULL, &statusId);
     /* Make the status variable mandatory */
     UA_Server_addReference(server, statusId,
                            UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE),
@@ -224,7 +224,7 @@ defineObjectTypes(UA_Server *server) {
     UA_Server_addVariableNode(server, UA_NODEID_NULL, pumpTypeId,
                               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
                               UA_QUALIFIEDNAME(1, "MotorRPMs"),
-                              UA_NODEID_NULL, rpmAttr, NULL, NULL);
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), rpmAttr, NULL, NULL);
 }
 
 /**

+ 1 - 1
examples/tutorial_server_variable.c

@@ -36,7 +36,7 @@ addVariable(UA_Server *server) {
     UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
     UA_Server_addVariableNode(server, myIntegerNodeId, parentNodeId,
                               parentReferenceNodeId, myIntegerName,
-                              UA_NODEID_NULL, attr, NULL, NULL);
+                              UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), attr, NULL, NULL);
 }
 
 /**

+ 1 - 1
examples/tutorial_server_variabletype.c

@@ -89,7 +89,7 @@ addVariableFail(UA_Server *server) {
     UA_String s = UA_STRING("2dpoint?");
     UA_Variant_setScalar(&vAttr.value, &s, &UA_TYPES[UA_TYPES_STRING]);
 
-    /* Add the node */
+    /* Add the node will return UA_STATUSCODE_BADTYPEMISMATCH*/
     UA_Server_addVariableNode(server, UA_NODEID_NULL,
                               UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
                               UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),