#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=). * * Supported types (scalar and 1D array via "type[]" suffix): * bool, int16, uint16, int32, uint32, int64, uint64, float, double, string * * Access levels: read, readwrite. */ #include #include /* ======================================================================== * 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 */