1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
#ifndef DISCOVERY_NODES_CONFIG_H
#define DISCOVERY_NODES_CONFIG_H
/**
* @file nodes_config.h
* @brief Dot-indexed node configuration parser and server-side node creator.
*
* Reads a config file containing node.N.field entries, parses them into
* an array of node descriptors, and creates corresponding OPC UA variable
* nodes in the server address space. Each node gets a string NodeId in
* namespace 1 (ns=1;s=<name>).
*
* Supported types (scalar and 1D array via "type[]" suffix):
* bool, int16, uint16, int32, uint32, int64, uint64, float, double, string
*
* Access levels: read, readwrite.
*/
#include <open62541/server.h>
#include <stddef.h>
/* ========================================================================
* Types
* ======================================================================== */
/**
* @brief OPC UA data types supported by the nodes config parser.
*/
typedef enum
{
NODE_TYPE_BOOL,
NODE_TYPE_INT16,
NODE_TYPE_UINT16,
NODE_TYPE_INT32,
NODE_TYPE_UINT32,
NODE_TYPE_INT64,
NODE_TYPE_UINT64,
NODE_TYPE_FLOAT,
NODE_TYPE_DOUBLE,
NODE_TYPE_STRING
} node_type;
/**
* @brief Access level flags for a variable node.
*/
typedef enum
{
NODE_ACCESS_READ,
NODE_ACCESS_READWRITE
} node_access_level;
/**
* @brief Describes a single variable node to be created on the server.
*
* All string pointers are heap-allocated copies owned by this struct.
* Call nodes_config_free() to release them.
*/
typedef struct
{
char *name; /**< DisplayName, browseName, and string NodeId. */
char *description; /**< Optional description text (NULL when absent). */
node_type type; /**< OPC UA data type. */
UA_Boolean is_array; /**< true when the type name ended with "[]". */
char *value_str; /**< Raw value string (comma-separated for arrays). */
node_access_level access; /**< Read or read-write. */
} node_config;
/**
* @brief A parsed set of variable node definitions.
*/
typedef struct
{
node_config *nodes;
size_t count;
} nodes_config;
/* ========================================================================
* Public API
* ======================================================================== */
/**
* @brief Parses a nodes configuration file.
*
* Reads dot-indexed keys (node.N.name, node.N.type, etc.) from the
* file at @p path, groups them by index, validates required fields,
* and populates a nodes_config struct. The caller must free the
* result with nodes_config_free().
*
* When the file contains no node.* keys the function succeeds with
* out->count == 0 and out->nodes == NULL.
*
* @param path Path to the nodes configuration file.
* @param out Output: parsed nodes configuration.
* @return 0 on success, -1 on error (logged via UA_LOG_ERROR/FATAL).
*/
int nodes_config_load (const char *path, nodes_config *out);
/**
* @brief Adds all configured variable nodes to a server.
*
* For each node_config entry, parses the value string into the
* appropriate UA type, constructs a UA_VariableAttributes, and calls
* UA_Server_addVariableNode with a string NodeId in namespace 1
* under the Objects folder.
*
* Individual node failures are logged but do not stop processing of
* remaining nodes.
*
* @param server The UA_Server to add nodes to.
* @param nc The parsed nodes configuration.
* @return 0 when all nodes were added, -1 if any node failed.
*/
int nodes_config_add (UA_Server *server, const nodes_config *nc);
/**
* @brief Frees all memory owned by a nodes_config structure.
*
* After this call the structure is zeroed and must not be used
* unless nodes_config_load() is called again.
*
* @param nc The nodes configuration to free.
*/
void nodes_config_free (nodes_config *nc);
#endif /* DISCOVERY_NODES_CONFIG_H */
|