ChimeraTK-ControlSystemAdapter-OPCUAAdapter 04.00.05
Loading...
Searching...
No Matches
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
23
24#include "csa_config.h"
25
26extern "C" {
27#include "csa_namespace.h"
28}
29
30#include "ua_map_types.h"
31
32#include <iostream>
33#include <utility>
34
35using namespace std;
36namespace ChimeraTK {
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
This class represent a additional variable from <variableMap.xml> in the information model of a OPC U...
ua_additionalvariable(UA_Server *server, UA_NodeId basenodeid, string name, string value, string description)
Constructor from <ua_additionalvariable> for generic creation.
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)
UA_DateTime getSourceTimeStamp()
Get the SourceTimeStamp from node in the OPC UA server Virtual methode which returned Timestamp is se...
This class mapped all inforamtion into the opca server.
std::list< UA_DataSource_Map_Element > UA_DataSource_Map
struct ChimeraTK::UA_DataSource_Map_Element_t UA_DataSource_Map_Element
UA_StatusCode ua_mapInstantiatedNodes(UA_NodeId objectId, UA_NodeId definitionId, void *handle)
Node function and proxy mapping for new nodes.
#define UASTRING_TO_CPPSTRING(_p_uastring, _p_cppstring)