ChimeraTK-ControlSystemAdapter-OPCUAAdapter  04.00.01
csa_additionalvariable.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ChimeraTKs ControlSystem-OPC-UA-Adapter.
3  *
4  * ChimeraTKs ControlSystem-OPC-UA-Adapter is free software: you can
5  * redistribute it and/or modify it under the terms of the Lesser GNU
6  * General Public License as published by the Free Software Foundation,
7  * either version 3 of the License, or (at your option) any later version.
8  *
9  * ChimeraTKs ControlSystem-OPC-UA-Adapter is distributed in the hope
10  * that it will be useful, but WITHOUT ANY WARRANTY; without even the
11  * implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  * See the Lesser GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with Foobar. If not, see https://www.gnu.org/licenses/lgpl.html
16  *
17  * Copyright (c) 2016 Chris Iatrou <Chris_Paul.Iatrou@tu-dresden.de>
18  * Copyright (c) 2016 Julian Rahm <Julian.Rahm@tu-dresden.de>
19  * Copyright (c) 2019-2023 Andreas Ebner <Andreas.Ebner@iosb.fraunhofer.de>
20  */
21 
22 #include "csa_additionalvariable.h"
23 
24 #include "csa_config.h"
25 
26 extern "C" {
27 #include "csa_namespace.h"
28 }
29 
30 #include "ua_map_types.h"
31 
32 #include <iostream>
33 #include <utility>
34 
35 using namespace std;
36 namespace ChimeraTK {
37  ua_additionalvariable::ua_additionalvariable(
38  UA_Server* server, UA_NodeId basenodeid, string name, string value, string description)
39  : ua_mapped_class(server, basenodeid) {
40  this->name = std::move(name);
41  this->value = std::move(value);
42  this->description = std::move(description);
43  this->ownNodeId = UA_NODEID_NULL;
44 
45  this->mapSelfToNamespace();
46  }
47 
49  // Our ua_mapped_class destructor will take care of deleting our opcua footprint as long as all variables are mapped
50  // in this->ownedNodes
51  UA_NodeId_clear(&this->ownNodeId);
52  }
53 
54  // Value
56  const UA_NodeId* /*sessionId*/, void* /*sessionContext*/, const UA_NodeId* /*nodeId*/, void* nodeContext,
57  UA_Boolean includeSourceTimeStamp, const UA_NumericRange* /*range*/, UA_DataValue* value) {
58  auto thisObj = static_cast<ua_additionalvariable*>(nodeContext);
59  UA_String ua_val;
60  char* s = (char*)malloc(thisObj->getValue().length() + 1);
61  strncpy(s, (char*)thisObj->getValue().c_str(), thisObj->getValue().length());
62  ua_val.length = thisObj->getValue().length();
63  ua_val.data = (UA_Byte*)malloc(ua_val.length);
64  memcpy(ua_val.data, s, ua_val.length);
65  free(s);
66  UA_Variant_setScalarCopy(&value->value, &ua_val, &UA_TYPES[11]);
67  UA_String_clear(&ua_val);
68  value->hasValue = true;
69  if(includeSourceTimeStamp) {
70  value->sourceTimestamp = thisObj->getSourceTimeStamp();
71  value->hasSourceTimestamp = true;
72  }
73  return UA_STATUSCODE_GOOD;
74  }
75 
76  // UA_RDPROXY_STRING(ua_additionalvariable, getValue)
78  return this->value;
79  }
80 
81  UA_StatusCode ua_additionalvariable::mapSelfToNamespace() {
82  UA_StatusCode retval = UA_STATUSCODE_GOOD;
83  UA_NodeId createdNodeId = UA_NODEID_NULL;
84 
85  if(UA_NodeId_equal(&this->baseNodeId, &createdNodeId) == UA_TRUE) return UA_STATUSCODE_BADINVALIDARGUMENT;
86 
87  // Generate additional variable node id
88  UA_String baseNodeIdString = baseNodeId.identifier.string;
89  string baseNodeIdStringCPP;
90  UASTRING_TO_CPPSTRING(baseNodeIdString, baseNodeIdStringCPP)
91  if(!baseNodeIdStringCPP.empty()) {
92  baseNodeIdStringCPP.resize(baseNodeIdStringCPP.size() - 3);
93  }
94 
95  UA_String* opcua_node_variable_t_ns_2_variant_DataContents = UA_String_new();
96  *opcua_node_variable_t_ns_2_variant_DataContents = UA_STRING_ALLOC(this->value.c_str());
97  UA_VariableAttributes vAttr;
98  UA_VariableAttributes_init(&vAttr);
99  vAttr = UA_VariableAttributes_default;
100  vAttr.displayName = UA_LOCALIZEDTEXT_ALLOC(const_cast<char*>("en_US"), const_cast<char*>(this->name.c_str()));
101  vAttr.description =
102  UA_LOCALIZEDTEXT_ALLOC(const_cast<char*>("en_US"), const_cast<char*>(this->description.c_str()));
103  vAttr.dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_STRING);
104  vAttr.valueRank = UA_VALUERANK_SCALAR;
105  UA_Variant_setScalar(&vAttr.value, opcua_node_variable_t_ns_2_variant_DataContents, &UA_TYPES[UA_TYPES_STRING]);
106 
107  UA_QualifiedName qualName = UA_QUALIFIEDNAME_ALLOC(1, this->name.c_str());
108  retval |= UA_Server_addVariableNode(this->mappedServer,
109  UA_NODEID_STRING(1, const_cast<char*>((baseNodeIdStringCPP + "/" + name + "AdditionalVariable").c_str())),
110  this->baseNodeId, UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), qualName,
111  UA_NODEID_NUMERIC(CSA_NSID, UA_NS2ID_CTKADDITIONALVARIABLE), vAttr, (void*)this, &createdNodeId);
112  UA_NodeId_copy(&createdNodeId, &this->ownNodeId);
114  createdNodeId, UA_NODEID_NUMERIC(CSA_NSID, UA_NS2ID_CTKADDITIONALVARIABLE), &this->ownedNodes);
115 
116  UA_QualifiedName_clear(&qualName);
117  UA_VariableAttributes_clear(&vAttr);
118 
119  UA_VariableAttributes vAttr2;
120  UA_VariableAttributes_init(&vAttr2);
121  vAttr2 = UA_VariableAttributes_default;
122  vAttr2.displayName = UA_LOCALIZEDTEXT_ALLOC(const_cast<char*>("en_US"), const_cast<char*>("Description"));
123  vAttr2.description =
124  UA_LOCALIZEDTEXT_ALLOC(const_cast<char*>("en_US"), const_cast<char*>(this->description.c_str()));
125  vAttr2.dataType = UA_NODEID_NUMERIC(0, UA_NS0ID_STRING);
126  vAttr.valueRank = UA_VALUERANK_SCALAR;
127  UA_String addVarDescription = UA_STRING_ALLOC(description.c_str());
128  UA_Variant_setScalarCopy(&vAttr2.value, &addVarDescription, &UA_TYPES[UA_TYPES_STRING]);
129 
130  UA_QualifiedName qualName2 = UA_QUALIFIEDNAME_ALLOC(1, this->description.c_str());
131  string parentNodeStringDescription = baseNodeIdStringCPP + "/" + name + "/Description";
132  retval |= UA_Server_addVariableNode(this->mappedServer,
133  UA_NODEID_STRING(1, const_cast<char*>(parentNodeStringDescription.c_str())), this->ownNodeId,
134  UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), qualName2, UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
135  vAttr2, nullptr, nullptr);
136 
137  UA_QualifiedName_clear(&qualName2);
138 
139  /* Use a datasource map to map any local getter/setter functions to opcua variables nodes */
140  UA_DataSource_Map mapDs;
141  UA_DataSource_Map_Element mapElemValue;
142  mapElemValue.typeTemplateId = UA_NODEID_NUMERIC(CSA_NSID, CSA_NSID_ADDITIONAL_VARIABLE_VALUE);
143  mapElemValue.description = vAttr2.description;
144  mapElemValue.dataSource.read = ua_readproxy_ua_additionalvariable_getValue;
145  mapElemValue.dataSource.write = nullptr;
146  mapDs.push_back(mapElemValue);
147 
148  UA_Server_setVariableNode_dataSource(this->mappedServer, createdNodeId, mapElemValue.dataSource);
149 
150  UA_String_clear(&addVarDescription);
151  UA_VariableAttributes_clear(&vAttr2);
152  UA_NodeId_clear(&createdNodeId);
153 
154  return retval;
155  }
156 
158  return UA_DateTime_now();
159  }
160 } // namespace ChimeraTK
ChimeraTK::ua_additionalvariable::~ua_additionalvariable
~ua_additionalvariable()
Definition: csa_additionalvariable.cpp:48
ChimeraTK::ua_mapInstantiatedNodes
UA_StatusCode ua_mapInstantiatedNodes(UA_NodeId objectId, UA_NodeId definitionId, void *handle)
Node function and proxy mapping for new nodes.
Definition: ua_map_types.cpp:30
ChimeraTK::UA_DataSource_Map_Element_t::typeTemplateId
UA_NodeId typeTemplateId
Definition: ua_map_types.h:51
ChimeraTK::ua_mapped_class::mappedServer
UA_Server * mappedServer
Definition: ua_mapped_class.h:39
ChimeraTK::ua_additionalvariable::getSourceTimeStamp
UA_DateTime getSourceTimeStamp()
Get the SourceTimeStamp from node in the OPC UA server Virtual methode which returned Timestamp is se...
Definition: csa_additionalvariable.cpp:157
ChimeraTK::ua_mapped_class
This class mapped all inforamtion into the opca server.
Definition: ua_mapped_class.h:33
ChimeraTK::ua_mapped_class::baseNodeId
UA_NodeId baseNodeId
Definition: ua_mapped_class.h:36
csa_namespace.h
ChimeraTK::UA_DataSource_Map_Element
struct ChimeraTK::UA_DataSource_Map_Element_t UA_DataSource_Map_Element
ChimeraTK::ua_additionalvariable::ua_readproxy_ua_additionalvariable_getValue
static UA_StatusCode ua_readproxy_ua_additionalvariable_getValue(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *nodeId, void *nodeContext, UA_Boolean includeSourceTimeStamp, const UA_NumericRange *range, UA_DataValue *value)
Definition: csa_additionalvariable.cpp:55
ChimeraTK::UA_DataSource_Map
std::list< UA_DataSource_Map_Element > UA_DataSource_Map
Definition: ua_map_types.h:56
ChimeraTK::ua_additionalvariable::getValue
string getValue()
Definition: csa_additionalvariable.cpp:77
csa_additionalvariable.h
UASTRING_TO_CPPSTRING
#define UASTRING_TO_CPPSTRING(_p_uastring, _p_cppstring)
Definition: ua_typeconversion.h:53
ChimeraTK::ua_mapped_class::ownedNodes
nodePairList ownedNodes
Definition: ua_mapped_class.h:35
ChimeraTK::ua_additionalvariable
This class represent a additional variable from <variableMap.xml> in the information model of a OPC U...
Definition: csa_additionalvariable.h:36
ua_map_types.h
ChimeraTK
Definition: csa_additionalvariable.h:28