|
@@ -9,31 +9,28 @@ static void stopHandler(int sig) {
|
|
running = false;
|
|
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;
|
|
UA_ObjectTypeAttributes otAttr = UA_ObjectTypeAttributes_default;
|
|
otAttr.description = UA_LOCALIZEDTEXT("en-US", "A mamal");
|
|
otAttr.description = UA_LOCALIZEDTEXT("en-US", "A mamal");
|
|
otAttr.displayName = UA_LOCALIZEDTEXT("en-US", "MamalType");
|
|
otAttr.displayName = UA_LOCALIZEDTEXT("en-US", "MamalType");
|
|
@@ -126,8 +123,138 @@ int main(void) {
|
|
UA_QUALIFIEDNAME(1, "Mamal1"), UA_NODEID_NUMERIC(1, 10000),
|
|
UA_QUALIFIEDNAME(1, "Mamal1"), UA_NODEID_NUMERIC(1, 10000),
|
|
oAttr, NULL, NULL);
|
|
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 */
|
|
/* Run the server */
|
|
- 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);
|
|
UA_ServerConfig_delete(config);
|
|
return (int)retval;
|
|
return (int)retval;
|