32 UA_StatusCode
get_child_variables(UA_NodeId childId, UA_Boolean isInverse, UA_NodeId referenceTypeId,
void* handle) {
33 if(isInverse)
return UA_STATUSCODE_GOOD;
35 UA_NodeId organizes = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
37 if(UA_NodeId_equal(&referenceTypeId, &organizes)) {
40 UA_NodeClass outNodeClass;
41 UA_NodeClass_init(&outNodeClass);
42 UA_Server_readNodeClass(handler->server, childId, &outNodeClass);
43 if(outNodeClass == UA_NODECLASS_VARIABLE) {
44 UA_NodeId* temp = UA_NodeId_new();
45 UA_NodeId_copy(&childId, temp);
46 handler->historizing_nodes->insert(handler->historizing_nodes->end(), *temp);
47 handler->historizing_setup->insert(handler->historizing_setup->end(), handler->history);
49 return UA_STATUSCODE_GOOD;
53 vector<AdapterFolderHistorySetup> historyfolders, UA_Server* mappedServer, UA_ServerConfig* server_config) {
54 for(
size_t i = 0; i < historyfolders.size(); i++) {
55 UA_NodeId* temp = UA_NodeId_new();
56 UA_StatusCode retval = UA_Server_readNodeId(mappedServer, historyfolders[i].folder_id, temp);
57 UA_NodeId_clear(temp);
58 if(retval == UA_STATUSCODE_GOOD) {
60 handle.
server = mappedServer;
61 handle.
history = historyfolders[i].folder_historizing;
64 UA_Server_forEachChildNodeCall(mappedServer, historyfolders[i].folder_id,
get_child_variables, &handle);
67 UA_LOG_WARNING(server_config->logging, UA_LOGCATEGORY_USERLAND,
68 "Warning! Folder is not mapped in the server. StatusCode: %s ", UA_StatusCode_name(retval));
74 vector<AdapterPVHistorySetup> historyvariables, UA_Server* mappedServer, UA_ServerConfig* server_config) {
75 for(
size_t i = 0; i < historyvariables.size(); i++) {
76 UA_NodeId* temp = UA_NodeId_new();
77 UA_NodeId
id = historyvariables[i].variable_id;
78 UA_StatusCode retval = UA_Server_readNodeId(mappedServer,
id, temp);
79 if(retval == UA_STATUSCODE_GOOD) {
80 UA_String out = UA_STRING_NULL;
81 UA_print(&
id, &UA_TYPES[UA_TYPES_NODEID], &out);
83 server_config->logging, UA_LOGCATEGORY_USERLAND,
"Add history for node %.*s ", (
int)out.length, out.data);
84 UA_String_clear(&out);
85 historizing_nodes->insert(historizing_nodes->end(), historyvariables[i].variable_id);
86 historizing_setup->insert(historizing_setup->end(), historyvariables[i].variable_historizing);
89 UA_String out = UA_STRING_NULL;
90 UA_print(&
id, &UA_TYPES[UA_TYPES_NODEID], &out);
91 UA_LOG_WARNING(server_config->logging, UA_LOGCATEGORY_USERLAND,
92 "Warning! Node %.*s has a history configuration but is not mapped to the server. StatusCode: %s ",
93 (
int)out.length, out.data, UA_StatusCode_name(retval));
94 UA_String_clear(&out);
96 UA_NodeId_clear(temp);
98 UA_LOG_INFO(server_config->logging, UA_LOGCATEGORY_USERLAND,
"Added %ld nodes to the historizing.",
99 historizing_nodes->size());
105 UA_Server_readAccessLevel(mappedServer,
id, &temp);
106 if(temp & UA_ACCESSLEVELMASK_READ) {
107 temp |= UA_ACCESSLEVELMASK_HISTORYREAD;
108 UA_Server_writeAccessLevel(mappedServer,
id, temp);
110 UA_Server_writeHistorizing(mappedServer,
id,
true);
111 UA_Byte_clear(&temp);
115 vector<UA_NodeId>& historizing_nodes, vector<string>& historizing_setup, UA_ServerConfig* server_config) {
120 for(
size_t i = 0; i < historizing_nodes.size(); i++) {
121 for(
size_t j = i + 1; j < historizing_nodes.size(); j++) {
122 if(UA_NodeId_equal(
reinterpret_cast<UA_NodeId*
>(&historizing_nodes[i]),
123 reinterpret_cast<UA_NodeId*
>(&historizing_nodes[j]))) {
124 UA_String out = UA_STRING_NULL;
125 UA_print(
reinterpret_cast<UA_NodeId*
>(&historizing_nodes[j]), &UA_TYPES[UA_TYPES_NODEID], &out);
126 UA_LOG_INFO(server_config->logging, UA_LOGCATEGORY_USERLAND,
127 "Node %.*s has multiple history settings. The first folder/process_variable setting in the mapping "
128 "file is considered if multiple exists/overlap. "
129 "process_variable settings are preferred over folder settings.",
130 (
int)out.length, out.data);
131 UA_String_clear(&out);
132 UA_NodeId_clear(
reinterpret_cast<UA_NodeId*
>(&historizing_nodes[j]));
133 historizing_nodes.erase(historizing_nodes.begin() + j);
134 historizing_setup.erase(historizing_setup.begin() + j);
145 vector<string>& historizing_setup, UA_ServerConfig* server_config, vector<AdapterHistorySetup> history) {
150 for(
size_t i = position; i < historizing_nodes.size(); i++) {
152 for(
auto& j : history) {
153 if(historizing_setup[i] == j.name) {
159 UA_String out = UA_STRING_NULL;
160 UA_print(
reinterpret_cast<UA_NodeId*
>(&historizing_nodes[i]), &UA_TYPES[UA_TYPES_NODEID], &out);
161 UA_LOG_WARNING(server_config->logging, UA_LOGCATEGORY_USERLAND,
162 "Warning! Remove node %.*s from historizing because the setup %s is missing.", (
int)out.length, out.data,
163 historizing_setup[i].c_str());
164 UA_String_clear(&out);
166 historizing_nodes.erase(historizing_nodes.begin() + i);
167 historizing_setup.erase(historizing_setup.begin() + i);
176 UA_HistoryDataGathering
add_historizing_nodes(vector<UA_NodeId>& historizing_nodes, vector<string>& historizing_setup,
177 UA_Server* mappedServer, UA_ServerConfig* server_config, vector<AdapterHistorySetup> history,
178 vector<AdapterFolderHistorySetup> historyfolders, vector<AdapterPVHistorySetup> historyvariables) {
180 add_folder_historizing(&historizing_nodes, &historizing_setup, historyfolders, mappedServer, server_config);
184 UA_HistoryDataGathering gathering = UA_HistoryDataGathering_Default(historizing_nodes.size());
185 server_config->historyDatabase = UA_HistoryDatabase_default(gathering);
186 for(
size_t i = 0; i < historizing_nodes.size(); i++) {
187 UA_HistorizingNodeIdSettings setting;
188 setting.historizingUpdateStrategy = UA_HISTORIZINGUPDATESTRATEGY_POLL;
190 for(
auto& j : history) {
191 if(historizing_setup[i] == j.name) {
196 setting.historizingBackend = UA_HistoryDataBackend_Memory_Circular(historizing_nodes.size(), hist.
buffer_length);
198 setting.pollingInterval = hist.
interval;
199 UA_StatusCode retval = gathering.registerNodeId(mappedServer, gathering.context, &historizing_nodes[i], setting);
200 if(retval != UA_STATUSCODE_GOOD) {
201 UA_String out = UA_STRING_NULL;
202 UA_print(&historizing_nodes[i], &UA_TYPES[UA_TYPES_NODEID], &out);
203 UA_LOG_WARNING(server_config->logging, UA_LOGCATEGORY_USERLAND,
204 "Failed to add historizing for Node %.*s with StatusCode %s", (
int)out.length, out.data,
205 UA_StatusCode_name(retval));
206 UA_String_clear(&out);
208 retval = gathering.startPoll(mappedServer, gathering.context, &historizing_nodes[i]);
209 if(retval != UA_STATUSCODE_GOOD) {
210 UA_String out = UA_STRING_NULL;
211 UA_print(&historizing_nodes[i], &UA_TYPES[UA_TYPES_NODEID], &out);
212 UA_LOG_WARNING(server_config->logging, UA_LOGCATEGORY_USERLAND,
213 "Failed to start the poll for Node %.*s with StatusCode %s", (
int)out.length, out.data,
214 UA_StatusCode_name(retval));
215 UA_String_clear(&out);
221 void clear_history(UA_HistoryDataGathering gathering, vector<UA_NodeId>& historizing_nodes,
222 vector<string>& historizing_setup, UA_Server* mappedServer, vector<AdapterFolderHistorySetup> historyfolders,
223 vector<AdapterPVHistorySetup> historyvariables, UA_ServerConfig* server_config) {
225 for(
auto& historizing_node : historizing_nodes) {
226 UA_StatusCode retval = gathering.stopPoll(mappedServer, gathering.context, &historizing_node);
227 UA_LOG_INFO(server_config->logging, UA_LOGCATEGORY_SERVER,
228 "Stopping polling thread used by the historizing -> %s", UA_StatusCode_name(retval));
231 historizing_nodes.clear();
232 historizing_setup.clear();
234 for(
auto& historyfolder : historyfolders) {
235 UA_NodeId_clear(&historyfolder.folder_id);
237 for(
auto& historyvariable : historyvariables) {
238 UA_NodeId_clear(&historyvariable.variable_id);
void clear_history(UA_HistoryDataGathering gathering, vector< UA_NodeId > &historizing_nodes, vector< string > &historizing_setup, UA_Server *mappedServer, vector< AdapterFolderHistorySetup > historyfolders, vector< AdapterPVHistorySetup > historyvariables, UA_ServerConfig *server_config)
UA_HistoryDataGathering add_historizing_nodes(vector< UA_NodeId > &historizing_nodes, vector< string > &historizing_setup, UA_Server *mappedServer, UA_ServerConfig *server_config, vector< AdapterHistorySetup > history, vector< AdapterFolderHistorySetup > historyfolders, vector< AdapterPVHistorySetup > historyvariables)
size_t entries_per_response