Преглед изворни кода

Add example for _begin and _finish usage.

Fixes #857
Stefan Profanter пре 6 година
родитељ
комит
621a3236e6
1 измењених фајлова са 151 додато и 24 уклоњено
  1. 151 24
      examples/server_inheritance.c

+ 151 - 24
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");
@@ -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;