ChimeraTK-ControlSystemAdapter-OPCUAAdapter 04.00.05
Loading...
Searching...
No Matches
csa_processvariable.h
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-2021 Andreas Ebner <Andreas.Ebner@iosb.fraunhofer.de>
20 */
21
22#pragma once
23
24#include "ChimeraTK/ControlSystemAdapter/ControlSystemPVManager.h"
25#include "ChimeraTK/SupportedUserTypes.h"
26#include "ua_mapped_class.h"
27
28#include <boost/fusion/container/map.hpp>
29
30#include <string>
31using namespace std;
32namespace fusion = boost::fusion;
33
34namespace ChimeraTK {
35
36 typedef fusion::map<fusion::pair<int8_t, uint>, fusion::pair<uint8_t, uint>, fusion::pair<int16_t, uint>,
37 fusion::pair<uint16_t, uint>, fusion::pair<int32_t, uint>, fusion::pair<uint32_t, uint>,
38 fusion::pair<int64_t, uint>, fusion::pair<uint64_t, uint>, fusion::pair<float, uint>, fusion::pair<double, uint>,
39 fusion::pair<string, uint>, fusion::pair<Boolean, uint>>
41
50 private:
51 string namePV;
52 string nameNew;
53 string nodeStringIdOverwrite;
54 string engineeringUnit;
55 string description;
56 UA_NodeId ownNodeId = UA_NODEID_NULL;
57
58 TypesMap typesMap{fusion::make_pair<int8_t>(UA_TYPES_SBYTE), fusion::make_pair<uint8_t>(UA_TYPES_BYTE),
59 fusion::make_pair<int16_t>(UA_TYPES_INT16), fusion::make_pair<uint16_t>(UA_TYPES_UINT16),
60 fusion::make_pair<int32_t>(UA_TYPES_INT32), fusion::make_pair<uint32_t>(UA_TYPES_UINT32),
61 fusion::make_pair<int64_t>(UA_TYPES_INT64), fusion::make_pair<uint64_t>(UA_TYPES_UINT64),
62 fusion::make_pair<float>(UA_TYPES_FLOAT), fusion::make_pair<double>(UA_TYPES_DOUBLE),
63 fusion::make_pair<string>(UA_TYPES_STRING), fusion::make_pair<Boolean>(UA_TYPES_BOOLEAN)};
64
65 private:
66 bool array;
67 boost::shared_ptr<ControlSystemPVManager> csManager;
68 UA_StatusCode addPVChildNodes(UA_NodeId pvNodeId, const string& baseNodePath, UA_DataSource_Map& map);
69
74 UA_StatusCode mapSelfToNamespace(const UA_Logger* logger);
75
76 public:
86 ua_processvariable(UA_Server* server, UA_NodeId basenodeid, const string& namePV,
87 boost::shared_ptr<ControlSystemPVManager> csManager, const UA_Logger* logger, string overwriteNodeString = "");
88
93
97 UA_DateTime getSourceTimeStamp();
98
99 static UA_StatusCode ua_readproxy_ua_processvariable_getName(UA_Server* server, const UA_NodeId* sessionId,
100 void* sessionContext, const UA_NodeId* nodeId, void* nodeContext, UA_Boolean includeSourceTimeStamp,
101 const UA_NumericRange* range, UA_DataValue* value);
102
107 string getName();
108
109 static UA_StatusCode ua_readproxy_ua_processvariable_getType(UA_Server* server, const UA_NodeId* sessionId,
110 void* sessionContext, const UA_NodeId* nodeId, void* nodeContext, UA_Boolean includeSourceTimeStamp,
111 const UA_NumericRange* range, UA_DataValue* value);
112
117 string getType();
118
119 static UA_StatusCode ua_readproxy_ua_processvariable_getEngineeringUnit(UA_Server* server,
120 const UA_NodeId* sessionId, void* sessionContext, const UA_NodeId* nodeId, void* nodeContext,
121 UA_Boolean includeSourceTimeStamp, const UA_NumericRange* range, UA_DataValue* value);
122
123 static UA_StatusCode ua_writeproxy_ua_processvariable_setEngineeringUnit(UA_Server* server,
124 const UA_NodeId* sessionId, void* sessionContext, const UA_NodeId* nodeId, void* nodeContext,
125 const UA_NumericRange* range, const UA_DataValue* value);
126
131 void setEngineeringUnit(string engineeringUnit);
136 string getEngineeringUnit();
137
138 static UA_StatusCode ua_writeproxy_ua_processvariable_setDescription(UA_Server* server, const UA_NodeId* sessionId,
139 void* sessionContext, const UA_NodeId* nodeId, void* nodeContext, const UA_NumericRange* range,
140 const UA_DataValue* value);
141
142 static UA_StatusCode ua_readproxy_ua_processvariable_getDescription(UA_Server* server, const UA_NodeId* sessionId,
143 void* sessionContext, const UA_NodeId* nodeId, void* nodeContext, UA_Boolean includeSourceTimeStamp,
144 const UA_NumericRange* range, UA_DataValue* value);
145
147 static UA_StatusCode ua_readproxy_ua_processvariable_getValidity(UA_Server* server, const UA_NodeId* sessionId,
148 void* sessionContext, const UA_NodeId* nodeId, void* nodeContext, UA_Boolean includeSourceTimeStamp,
149 const UA_NumericRange* range, UA_DataValue* value);
150
155 void setDescription(string description);
160 string getDescription();
161
166 UA_NodeId getOwnNodeId();
167
168 template<typename T>
169 static UA_StatusCode ua_readproxy_ua_processvariable_getValue(UA_Server* server, const UA_NodeId* sessionId,
170 void* sessionContext, const UA_NodeId* nodeId, void* nodeContext, UA_Boolean includeSourceTimeStamp,
171 const UA_NumericRange* range, UA_DataValue* value);
172
173 template<typename T>
174 UA_StatusCode getValue(UA_Variant* v, const UA_NumericRange* range);
175
176 template<typename T>
177 static UA_StatusCode ua_writeproxy_ua_processvariable_setValue(UA_Server* server, const UA_NodeId* sessionId,
178 void* sessionContext, const UA_NodeId* nodeId, void* nodeContext, const UA_NumericRange* range,
179 const UA_DataValue* value);
180
181 template<typename T>
182 UA_StatusCode setValue(const UA_Variant* data);
183
184 template<typename T>
185 UA_UInt32 typeSpecificSetup(UA_DataSource_Map_Element& mapElem, const UA_NodeId nodeId);
186 };
187
188 template<typename T>
190 const UA_NodeId* /*sessionId*/, void* /*sessionContext*/, const UA_NodeId* /*nodeId*/, void* nodeContext,
191 UA_Boolean includeSourceTimeStamp, const UA_NumericRange* range, UA_DataValue* value) {
192 auto* thisObj = static_cast<ua_processvariable*>(nodeContext);
193 UA_StatusCode rv = UA_STATUSCODE_GOOD;
194 rv = thisObj->getValue<T>(&value->value, range);
195 if(rv == UA_STATUSCODE_GOOD) {
196 value->hasValue = true;
197 if(includeSourceTimeStamp) {
198 value->sourceTimestamp = thisObj->getSourceTimeStamp();
199 value->hasSourceTimestamp = true;
200 }
201 }
202 return rv;
203 }
204
205 template<typename T>
207 const UA_NodeId* /*sessionId*/, void* /*sessionContext*/, const UA_NodeId* /*nodeId*/, void* nodeContext,
208 const UA_NumericRange* /*range*/, const UA_DataValue* value) {
209 UA_StatusCode retval = UA_STATUSCODE_BADINTERNALERROR;
210 auto* theClass = static_cast<ua_processvariable*>(nodeContext);
211 retval = theClass->setValue<T>(&value->value);
212 return retval;
213 }
214
215 template<typename T>
216 UA_StatusCode ua_processvariable::getValue(UA_Variant* v, const UA_NumericRange* range) {
217 UA_StatusCode rv = UA_STATUSCODE_BADINTERNALERROR;
218 if(this->csManager->getProcessVariable(this->namePV)->isReadable()) {
219 this->csManager->getProcessArray<T>(this->namePV)->readLatest();
220 }
221 if(this->csManager->getProcessArray<T>(this->namePV)->accessChannel(0).size() == 1) {
222 T ival = this->csManager->getProcessArray<T>(this->namePV)->accessChannel(0).at(0);
223 rv = UA_Variant_setScalarCopy(v, &ival, &UA_TYPES[fusion::at_key<T>(typesMap)]);
224 }
225 else {
226 std::vector<T> iarr = this->csManager->getProcessArray<T>(this->namePV)->accessChannel(0);
227 v->type = &UA_TYPES[fusion::at_key<T>(typesMap)];
228 if(range != nullptr) {
229 // v->type = &UA_TYPES[fusion::at_key<T>(typesMap)];
230 // rv = UA_Variant_setRangeCopy(v, iarr.data(), iarr.size(), *range);
231 UA_Variant tmpVariant;
232 UA_Variant_setArray(&tmpVariant, iarr.data(), iarr.size(), &UA_TYPES[fusion::at_key<T>(typesMap)]);
233 rv = UA_Variant_copyRange(&tmpVariant, v, *range);
234 }
235 else {
236 rv = UA_Variant_setArrayCopy(v, iarr.data(), iarr.size(), &UA_TYPES[fusion::at_key<T>(typesMap)]);
237 }
238 }
239 return rv;
240 }
241
242 template<>
243 inline UA_StatusCode ua_processvariable::getValue<string>(UA_Variant* v, const UA_NumericRange* /*range*/) {
244 UA_StatusCode rv = UA_STATUSCODE_BADINTERNALERROR;
245 if(this->csManager->getProcessVariable(this->namePV)->isReadable()) {
246 this->csManager->getProcessArray<string>(this->namePV)->readLatest();
247 }
248 if(this->csManager->getProcessArray<string>(this->namePV)->accessChannel(0).size() == 1) {
249 string sval = this->csManager->getProcessArray<string>(this->namePV)->accessChannel(0).at(0);
250 UA_String ua_val = UA_String_fromChars((char*)sval.c_str());
251 rv = UA_Variant_setScalarCopy(v, &ua_val, &UA_TYPES[UA_TYPES_STRING]);
252 UA_String_clear(&ua_val);
253 }
254 else {
255 std::vector<string> sarr = this->csManager->getProcessArray<string>(this->namePV)->accessChannel(0);
256 auto* sarrayval = new UA_String[sarr.size()];
257 for(size_t i = 0; i < sarr.size(); i++) {
258 sarrayval[i] = UA_String_fromChars((char*)sarr[i].c_str());
259 }
260 rv = UA_Variant_setArrayCopy(v, sarrayval, sarr.size(), &UA_TYPES[UA_TYPES_STRING]);
261 delete[] sarrayval;
262 }
263 return rv;
264 }
265
266 template<typename T>
267 UA_StatusCode ua_processvariable::setValue(const UA_Variant* data) {
268 UA_StatusCode retval = UA_STATUSCODE_BADINTERNALERROR;
269
270 if(this->csManager->getProcessVariable(this->namePV)->isWriteable()) {
271 vector<T> valueArray;
272 if(UA_Variant_isScalar(data) && (!array)) {
273 T value = *((T*)data->data);
274 valueArray.push_back(value);
275 }
276 else if((!UA_Variant_isScalar(data)) && array) {
277 auto* v = (T*)data->data;
278 valueArray.resize(data->arrayLength);
279 for(size_t i = 0; i < valueArray.size(); i++) {
280 valueArray.at(i) = v[i];
281 }
282 if(this->csManager->getProcessArray<T>(this->namePV)->accessChannel(0).size() != data->arrayLength) {
283 return UA_STATUSCODE_BADINVALIDARGUMENT;
284 }
285 }
286 this->csManager->getProcessArray<T>(this->namePV)->accessChannel(0) = valueArray;
287 this->csManager->getProcessArray<T>(this->namePV)->write();
288 retval = UA_STATUSCODE_GOOD;
289 }
290 else {
291 retval = UA_STATUSCODE_BADNOTWRITABLE;
292 }
293
294 return retval;
295 }
296
297 template<>
298 inline UA_StatusCode ua_processvariable::setValue<std::string>(const UA_Variant* data) {
299 UA_StatusCode retval = UA_STATUSCODE_BADINTERNALERROR;
300
301 if(this->csManager->getProcessVariable(this->namePV)->isWriteable()) {
302 vector<string> valueArray;
303 if(UA_Variant_isScalar(data) && (!array)) {
304 string cpps;
305 UASTRING_TO_CPPSTRING(((UA_String) * ((UA_String*)data->data)), cpps)
306 // string value = *((string *)data->data);
307 valueArray.push_back(cpps);
308 }
309 else if((!UA_Variant_isScalar(data)) && array) {
310 // Array
311 auto* vdata = (UA_String*)data->data;
312 valueArray.resize(data->arrayLength);
313 for(uint32_t i = 0; i < valueArray.size(); i++) {
314 string cpps;
315 UASTRING_TO_CPPSTRING(vdata[i], cpps)
316 valueArray.at(i) = cpps;
317 }
318 if(this->csManager->getProcessArray<string>(this->namePV)->accessChannel(0).size() != data->arrayLength) {
319 return UA_STATUSCODE_BADINVALIDARGUMENT;
320 }
321 }
322 this->csManager->getProcessArray<string>(this->namePV)->accessChannel(0) = valueArray;
323 this->csManager->getProcessArray<string>(this->namePV)->write();
324 retval = UA_STATUSCODE_GOOD;
325 }
326 else {
327 retval = UA_STATUSCODE_BADNOTWRITABLE;
328 }
329
330 return retval;
331 }
332
333 template<typename T>
334 UA_UInt32 ua_processvariable::typeSpecificSetup(UA_DataSource_Map_Element& mapElem, const UA_NodeId nodeId) {
335 UA_Int32 arrayDims;
336 mapElem.dataSource.read = ua_processvariable::ua_readproxy_ua_processvariable_getValue<T>;
337 if(this->csManager->getProcessVariable(this->namePV)->isWriteable()) {
338 mapElem.dataSource.write = ua_processvariable::ua_writeproxy_ua_processvariable_setValue<T>;
339 }
340 if(this->csManager->getProcessArray<T>(this->namePV)->accessChannel(0).size() == 1) {
341 this->array = false;
342 }
343 else {
344 this->array = true;
345 arrayDims = this->csManager->getProcessArray<T>(this->namePV)->accessChannel(0).size();
346 }
347 UA_Server_writeDataType(this->mappedServer, nodeId, UA_TYPES[fusion::at_key<T>(typesMap)].typeId);
348 return arrayDims;
349 }
350
351} // namespace ChimeraTK
This class mapped all inforamtion into the opca server.
This class represent a processvariable of the controlsystemadapter in the information model of a OPC ...
static UA_StatusCode ua_readproxy_ua_processvariable_getDescription(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)
static UA_StatusCode ua_writeproxy_ua_processvariable_setDescription(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *nodeId, void *nodeContext, const UA_NumericRange *range, const UA_DataValue *value)
void setEngineeringUnit(string engineeringUnit)
Set engineering unit of processvariable.
string getName()
Get name of processvariable.
static UA_StatusCode ua_writeproxy_ua_processvariable_setValue(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *nodeId, void *nodeContext, const UA_NumericRange *range, const UA_DataValue *value)
string getType()
Get type of processvariable.
UA_DateTime getSourceTimeStamp()
Reimplement the sourcetimestamp for every processvariable.
~ua_processvariable()
Destructor for ua_processvariable.
UA_UInt32 typeSpecificSetup(UA_DataSource_Map_Element &mapElem, const UA_NodeId nodeId)
static UA_StatusCode ua_readproxy_ua_processvariable_getEngineeringUnit(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_NodeId getOwnNodeId()
Get node id of this processvariable instance.
static UA_StatusCode ua_readproxy_ua_processvariable_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)
string getEngineeringUnit()
Get engineering unit of processvariable.
static UA_StatusCode ua_readproxy_ua_processvariable_getType(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)
static UA_StatusCode ua_readproxy_ua_processvariable_getValidity(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)
Get vadility of processvariable.
void setDescription(string description)
Get description unit of processvariable.
static UA_StatusCode ua_writeproxy_ua_processvariable_setEngineeringUnit(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *nodeId, void *nodeContext, const UA_NumericRange *range, const UA_DataValue *value)
UA_StatusCode setValue(const UA_Variant *data)
UA_StatusCode getValue(UA_Variant *v, const UA_NumericRange *range)
static UA_StatusCode ua_readproxy_ua_processvariable_getName(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)
string getDescription()
Get description unit of processvariable.
boost::shared_ptr< ChimeraTK::ControlSystemPVManager > csManager
std::list< UA_DataSource_Map_Element > UA_DataSource_Map
fusion::map< fusion::pair< int8_t, uint >, fusion::pair< uint8_t, uint >, fusion::pair< int16_t, uint >, fusion::pair< uint16_t, uint >, fusion::pair< int32_t, uint >, fusion::pair< uint32_t, uint >, fusion::pair< int64_t, uint >, fusion::pair< uint64_t, uint >, fusion::pair< float, uint >, fusion::pair< double, uint >, fusion::pair< string, uint >, fusion::pair< Boolean, uint > > TypesMap
For generic callback use, this sturct contains the methode pointer and a NodeId of the model.
#define UASTRING_TO_CPPSTRING(_p_uastring, _p_cppstring)