address_space_internal.cpp
Go to the documentation of this file.
1 
11 #include "address_space_internal.h"
12 
13 
14 namespace OpcUa
15 {
16 namespace Internal
17 {
18 typedef std::map <IntegerId, std::shared_ptr<InternalSubscription>> SubscriptionsIdMap; // Map SubscptioinId, SubscriptionData
19 
20 //store subscription for one attribute
22 {
26 };
27 
28 AddressSpaceInMemory::AddressSpaceInMemory(const Common::Logger::SharedPtr & logger)
29  : Logger(logger)
30  , DataChangeCallbackHandle(0)
31 {
32  /*
33  ObjectAttributes attrs;
34  attrs.Description = LocalizedText(OpcUa::Names::Root);
35  attrs.DisplayName = LocalizedText(OpcUa::Names::Root);
36 
37  AddNodesItem rootNode;
38  rootNode.BrowseName = QualifiedName(0, OpcUa::Names::Root);
39  rootNode.Class = NodeClass::Object;
40  rootNode.RequestedNewNodeId = ObjectId::RootFolder;
41  rootNode.TypeDefinition = ObjectId::FolderType;
42  rootNode.Attributes = attrs;
43  AddNode(rootNode);
44  */
45 }
46 
48 {
49 }
50 
51 std::vector<AddNodesResult> AddressSpaceInMemory::AddNodes(const std::vector<AddNodesItem> & items)
52 {
53  boost::unique_lock<boost::shared_mutex> lock(DbMutex);
54 
55  std::vector<AddNodesResult> results;
56 
57  for (const AddNodesItem & item : items)
58  {
59  results.push_back(AddNode(item));
60  }
61 
62  return results;
63 }
64 
65 std::vector<StatusCode> AddressSpaceInMemory::AddReferences(const std::vector<AddReferencesItem> & items)
66 {
67  boost::unique_lock<boost::shared_mutex> lock(DbMutex);
68 
69  std::vector<StatusCode> results;
70 
71  for (const auto & item : items)
72  {
73  results.push_back(AddReference(item));
74  }
75 
76  return results;
77 }
78 
80 {
81  boost::shared_lock<boost::shared_mutex> lock(DbMutex);
82 
83  std::vector<BrowsePathResult> results;
84 
85  for (BrowsePath browsepath : params.BrowsePaths)
86  {
87  BrowsePathResult result = TranslateBrowsePath(browsepath);
88  results.push_back(result);
89  }
90 
91  return results;
92 }
93 
94 std::vector<BrowseResult> AddressSpaceInMemory::Browse(const OpcUa::NodesQuery & query) const
95 {
96  boost::shared_lock<boost::shared_mutex> lock(DbMutex);
97 
98  LOG_TRACE(Logger, "address_space_internal| browse");
99 
100  std::vector<BrowseResult> results;
101 
102  for (BrowseDescription browseDescription : query.NodesToBrowse)
103  {
104  BrowseResult result;
105 
106  if (Logger && Logger->should_log(spdlog::level::trace))
107  {
108  Logger->trace("address_space_internal| browsing");
109  Logger->trace(" NodeId: '{}'", browseDescription.NodeToBrowse);
110  Logger->trace(" ReferenceId: '{}'", browseDescription.ReferenceTypeId);
111  Logger->trace(" Direction: {}", browseDescription.Direction);
112  Logger->trace(" NodeClasses: {:#x}", (unsigned)browseDescription.NodeClasses);
113  Logger->trace(" ResultMask: {:#x}", (unsigned)browseDescription.ResultMask);
114  }
115 
116  NodesMap::const_iterator node_it = Nodes.find(browseDescription.NodeToBrowse);
117 
118  if (node_it == Nodes.end())
119  {
120  LOG_WARN(Logger, "address_space_internal| Node '{}' not found in the address space", OpcUa::ToString(browseDescription.NodeToBrowse));
121 
122  continue;
123  }
124 
125  std::copy_if(node_it->second.References.begin(), node_it->second.References.end(), std::back_inserter(result.Referencies),
126  std::bind(&AddressSpaceInMemory::IsSuitableReference, this, std::cref(browseDescription), std::placeholders::_1)
127  );
128  results.push_back(result);
129  }
130 
131  return results;
132 }
133 
134 std::vector<BrowseResult> AddressSpaceInMemory::BrowseNext() const
135 {
136  boost::shared_lock<boost::shared_mutex> lock(DbMutex);
137 
138  return std::vector<BrowseResult>();
139 }
140 
141 std::vector<NodeId> AddressSpaceInMemory::RegisterNodes(const std::vector<NodeId> & params) const
142 {
143  boost::unique_lock<boost::shared_mutex> lock(DbMutex);
144 
145  return params;
146 }
147 
148 void AddressSpaceInMemory::UnregisterNodes(const std::vector<NodeId> & params) const
149 {
150  boost::unique_lock<boost::shared_mutex> lock(DbMutex);
151 
152  return;
153 }
154 
155 std::vector<DataValue> AddressSpaceInMemory::Read(const ReadParameters & params) const
156 {
157  boost::shared_lock<boost::shared_mutex> lock(DbMutex);
158 
159  std::vector<DataValue> values;
160 
161  for (const ReadValueId & attribute : params.AttributesToRead)
162  {
163  values.push_back(GetValue(attribute.NodeId, attribute.AttributeId));
164  }
165 
166  return values;
167 }
168 
169 std::vector<StatusCode> AddressSpaceInMemory::Write(const std::vector<OpcUa::WriteValue> & values)
170 {
171  boost::unique_lock<boost::shared_mutex> lock(DbMutex);
172 
173  std::vector<StatusCode> statuses;
174 
175  for (WriteValue value : values)
176  {
177  if (value.Value.Encoding & DATA_VALUE)
178  {
179  statuses.push_back(SetValue(value.NodeId, value.AttributeId, value.Value));
180  continue;
181  }
182 
183  statuses.push_back(StatusCode::BadNotWritable);
184  }
185 
186  return statuses;
187 }
188 
189 std::tuple<bool, NodeId> AddressSpaceInMemory::FindElementInNode(const NodeId & nodeid, const RelativePathElement & element) const
190 {
191  NodesMap::const_iterator nodeit = Nodes.find(nodeid);
192 
193  if (nodeit != Nodes.end())
194  {
195  for (auto reference : nodeit->second.References)
196  {
197  //if (reference.first == current) { std::cout << reference.second.BrowseName.NamespaceIndex << reference.second.BrowseName.Name << " to " << element.TargetName.NamespaceIndex << element.TargetName.Name <<std::endl; }
198  if (reference.BrowseName == element.TargetName)
199  {
200  return std::make_tuple(true, reference.TargetNodeId);
201  }
202  }
203  }
204 
205  return std::make_tuple(false, NodeId());
206 }
207 
209 {
210  NodeId current = browsepath.StartingNode;
211  BrowsePathResult result;
212 
213  for (RelativePathElement element : browsepath.Path.Elements)
214  {
215  auto res = FindElementInNode(current, element);
216 
217  if (std::get<0>(res) == false)
218  {
220  return result;
221  }
222 
223  current = std::get<1>(res);
224  }
225 
227  std::vector<BrowsePathTarget> targets;
229  target.Node = current;
230  target.RemainingPathIndex = std::numeric_limits<uint32_t>::max();
231  targets.push_back(target);
232  result.Targets = targets;
233  return result;
234 }
235 
237 {
238  NodesMap::const_iterator nodeit = Nodes.find(node);
239 
240  if (nodeit == Nodes.end())
241  {
242 // LOG_DEBUG(Logger, "address_space_internal| node not found: {}", node);
243  }
244 
245  else
246  {
247  AttributesMap::const_iterator attrit = nodeit->second.Attributes.find(attribute);
248 
249  if (attrit == nodeit->second.Attributes.end())
250  {
251 // LOG_DEBUG(Logger, "address_space_internal| node: {} has no attribute: {}", node, ToString(attribute));
252  }
253 
254  else
255  {
256  if (attrit->second.GetValueCallback)
257  {
258  LOG_DEBUG(Logger, "address_space_internal| invoke registered callback");
259 
260  return attrit->second.GetValueCallback();
261  }
262 
263 // LOG_TRACE(Logger, "address_space_internal| no callback registered, returning stored value");
264 
265  return attrit->second.Value;
266  }
267  }
268 
269  DataValue value;
272  return value;
273 }
274 
275 uint32_t AddressSpaceInMemory::AddDataChangeCallback(const NodeId & node, AttributeId attribute, std::function<Server::DataChangeCallback> callback)
276 {
277  boost::unique_lock<boost::shared_mutex> lock(DbMutex);
278 
279  LOG_DEBUG(Logger, "address_space_internal| set data changes callback for node {} and attribute {}", node, (unsigned)attribute);
280 
281  NodesMap::iterator it = Nodes.find(node);
282 
283  if (it == Nodes.end())
284  {
285  LOG_ERROR(Logger, "address_space_internal| Node: '{}' not found", node);
286  throw std::runtime_error("address_space_internal| NodeId not found");
287  }
288 
289  AttributesMap::iterator ait = it->second.Attributes.find(attribute);
290 
291  if (ait == it->second.Attributes.end())
292  {
293  LOG_ERROR(Logger, "address_space_internal| Attribute: {} of node: ‘{}‘ not found", (unsigned)attribute, node);
294  throw std::runtime_error("Attribute not found");
295  }
296 
297  uint32_t handle = ++DataChangeCallbackHandle;
299  data.Callback = callback;
300  ait->second.DataChangeCallbacks[handle] = data;
301  ClientIdToAttributeMap[handle] = NodeAttribute(node, attribute);
302  return handle;
303 }
304 
306 {
307  boost::unique_lock<boost::shared_mutex> lock(DbMutex);
308 
309  LOG_DEBUG(Logger, "address_space_internal| deleting callback with client id: {}", serverhandle);
310 
311  ClientIdToAttributeMapType::iterator it = ClientIdToAttributeMap.find(serverhandle);
312 
313  if (it == ClientIdToAttributeMap.end())
314  {
315  LOG_WARN(Logger, "address_space_internal| request to delete a callback using unknown handle: {1}", serverhandle);
316  return;
317  }
318 
319  NodesMap::iterator nodeit = Nodes.find(it->second.Node);
320 
321  if (nodeit != Nodes.end())
322  {
323  AttributesMap::iterator ait = nodeit->second.Attributes.find(it->second.Attribute);
324 
325  if (ait != nodeit->second.Attributes.end())
326  {
327  size_t nb = ait->second.DataChangeCallbacks.erase(serverhandle);
328 
329  LOG_DEBUG(Logger, "address_space_internal| deleted {} callbacks", nb);
330 
331  ClientIdToAttributeMap.erase(serverhandle);
332  return;
333  }
334  }
335 
336  throw std::runtime_error("address_space_internal| NodeId or attribute nor found");
337 }
338 
339 StatusCode AddressSpaceInMemory::SetValueCallback(const NodeId & node, AttributeId attribute, std::function<DataValue(void)> callback)
340 {
341  boost::unique_lock<boost::shared_mutex> lock(DbMutex);
342 
343  NodesMap::iterator it = Nodes.find(node);
344 
345  if (it != Nodes.end())
346  {
347  AttributesMap::iterator ait = it->second.Attributes.find(attribute);
348 
349  if (ait != it->second.Attributes.end())
350  {
351  ait->second.GetValueCallback = callback;
352  return StatusCode::Good;
353  }
354  }
355 
357 }
358 
359 void AddressSpaceInMemory::SetMethod(const NodeId & node, std::function<std::vector<OpcUa::Variant> (NodeId context, std::vector<OpcUa::Variant> arguments)> callback)
360 {
361  boost::unique_lock<boost::shared_mutex> lock(DbMutex);
362 
363  NodesMap::iterator it = Nodes.find(node);
364 
365  if (it != Nodes.end())
366  {
367  it->second.Method = callback;
368  }
369 
370  else
371  {
372  throw std::runtime_error("address_space_internal| while setting node callback: node does not exist.");
373  }
374 }
375 
376 std::vector<OpcUa::CallMethodResult> AddressSpaceInMemory::Call(const std::vector<OpcUa::CallMethodRequest> & methodsToCall)
377 {
378  boost::shared_lock<boost::shared_mutex> lock(DbMutex);
379 
380  std::vector<OpcUa::CallMethodResult> results;
381 
382  for (auto method : methodsToCall)
383  {
384  results.push_back(CallMethod(method));
385  }
386 
387  return results;
388 }
389 
391 {
392  CallMethodResult result;
393  NodesMap::iterator node_it = Nodes.find(request.ObjectId);
394 
395  if (node_it == Nodes.end())
396  {
398  return result;
399  }
400 
401  NodesMap::iterator method_it = Nodes.find(request.MethodId);
402 
403  if (method_it == Nodes.end())
404  {
406  return result;
407  }
408 
409  if (! method_it->second.Method)
410  {
412  return result;
413  }
414 
415  //FIXME: find a way to return more information about failure to client
416  try
417  {
418  result.OutputArguments = method_it->second.Method(node_it->first, request.InputArguments);
419  }
420 
421  catch (std::exception & ex)
422  {
423  LOG_ERROR(Logger, "address_space_internal| exception while calling method: {}: {}", request.MethodId, ex.what());
425  return result;
426  }
427 
428  for (auto var : request.InputArguments)
429  {
430  result.InputArgumentResults.push_back(StatusCode::Good);
431  }
432 
433  result.Status = StatusCode::Good;
434  return result;
435 }
436 
438 {
439  NodesMap::iterator it = Nodes.find(node);
440 
441  if (it != Nodes.end())
442  {
443  AttributesMap::iterator ait = it->second.Attributes.find(attribute);
444 
445  if (ait != it->second.Attributes.end())
446  {
447  DataValue value(data);
449  ait->second.Value = value;
450 
451  //call registered callback
452  for (auto pair : ait->second.DataChangeCallbacks)
453  {
454  pair.second.Callback(it->first, ait->first, ait->second.Value);
455  }
456 
457  return StatusCode::Good;
458  }
459  }
460 
462 }
463 
465 {
466 // LOG_TRACE(Logger, "address_space_internal| checking reference: '{}' to node: '{}' ({}) which must fit ref: '{}' with IncludeSubtypes: '{}'", reference.ReferenceTypeId, reference.TargetNodeId, reference.BrowseName, desc.ReferenceTypeId, desc.IncludeSubtypes);
467 
468  if ((desc.Direction == BrowseDirection::Forward && !reference.IsForward) || (desc.Direction == BrowseDirection::Inverse && reference.IsForward))
469  {
470 // LOG_TRACE(Logger, "address_space_internal| reference in wrong direction");
471  return false;
472  }
473 
475  {
476 // LOG_TRACE(Logger, "address_space_internal| reference has wrong type");
477  return false;
478  }
479 
481  {
482 // LOG_TRACE(Logger, "address_space_internal| reference has wrong class");
483  return false;
484  }
485 
486 // LOG_TRACE(Logger, "address_space_internal| reference suitable");
487  return true;
488 }
489 
490 bool AddressSpaceInMemory::IsSuitableReferenceType(const ReferenceDescription & reference, const NodeId & typeId, bool includeSubtypes) const
491 {
492  if (!includeSubtypes)
493  {
494  return reference.ReferenceTypeId == typeId;
495  }
496 
497  const std::vector<NodeId> suitableTypes = SelectNodesHierarchy(std::vector<NodeId>(1, typeId));
498  const auto resultIt = std::find(suitableTypes.begin(), suitableTypes.end(), reference.ReferenceTypeId);
499  \
500  return resultIt != suitableTypes.end();
501 }
502 
503 std::vector<NodeId> AddressSpaceInMemory::SelectNodesHierarchy(std::vector<NodeId> sourceNodes) const
504 {
505  std::vector<NodeId> subNodes;
506 
507  for (NodeId nodeid : sourceNodes)
508  {
509  NodesMap::const_iterator node_it = Nodes.find(nodeid);
510 
511  if (node_it != Nodes.end())
512  {
513  for (auto & ref : node_it->second.References)
514  {
515  if (ref.IsForward)
516  {
517  subNodes.push_back(ref.TargetNodeId);
518  }
519  }
520  }
521  }
522 
523  if (subNodes.empty())
524  {
525  return sourceNodes;
526  }
527 
528  const std::vector<NodeId> allChilds = SelectNodesHierarchy(subNodes);
529  sourceNodes.insert(sourceNodes.end(), allChilds.begin(), allChilds.end());
530  return sourceNodes;
531 }
532 
534 {
535  AddNodesResult result;
536 
537  LOG_TRACE(Logger, "address_space_internal| adding new node id: '{}' name: '{}'", item.RequestedNewNodeId, item.BrowseName.Name);
538 
539  const NodeId resultId = GetNewNodeId(item.RequestedNewNodeId);
540 
541  if (!Nodes.empty() && resultId != ObjectId::Null && Nodes.find(resultId) != Nodes.end())
542  {
543  LOG_ERROR(Logger, "address_space_internal| NodeId: '{}' already exists", resultId);
545  return result;
546  }
547 
548  NodesMap::iterator parent_node_it = Nodes.end();
549 
550  if (item.ParentNodeId != NodeId())
551  {
552  parent_node_it = Nodes.find(item.ParentNodeId);
553 
554  if (parent_node_it == Nodes.end())
555  {
556  LOG_ERROR(Logger, "address_space_internal| parent node '{}' does not exists", item.ParentNodeId);
558  return result;
559  }
560  }
561 
562  NodeStruct nodestruct;
563  //Add Common attributes
564  nodestruct.Attributes[AttributeId::NodeId].Value = resultId;
565  nodestruct.Attributes[AttributeId::BrowseName].Value = item.BrowseName;
566  nodestruct.Attributes[AttributeId::NodeClass].Value = static_cast<int32_t>(item.Class);
567 
568  // Add requested attributes
569  for (const auto & attr : item.Attributes.Attributes)
570  {
571  AttributeValue attval;
572  attval.Value = attr.second;
573 
574  nodestruct.Attributes.insert(std::make_pair(attr.first, attval));
575  }
576 
577  Nodes.insert(std::make_pair(resultId, nodestruct));
578 
579  if (parent_node_it != Nodes.end())
580  {
581  // Link from parent to child
582  NodeStruct& parent = parent_node_it->second;
583 
585  desc.ReferenceTypeId = item.ReferenceTypeId;
586  desc.TargetNodeId = resultId;
587  desc.TargetNodeClass = item.Class;
588  desc.BrowseName = item.BrowseName;
591  desc.IsForward = true; // should this be in constructor?
592 
593  parent.References.push_back(desc);
594 
595  // Link to parent
596  AddReferencesItem typeRef;
597  typeRef.ReferenceTypeId = item.ReferenceTypeId;
598  typeRef.SourceNodeId = resultId;
599  typeRef.TargetNodeId = item.ParentNodeId;
600  typeRef.TargetNodeClass = static_cast<NodeClass>(parent.Attributes[AttributeId::NodeClass].Value.Value.As<int32_t>());
601  typeRef.IsForward = false;
602  AddReference(typeRef);
603  }
604 
605  if (item.TypeDefinition != ObjectId::Null)
606  {
607  // Link to parent
608  AddReferencesItem typeRef;
609  typeRef.SourceNodeId = resultId;
610  typeRef.IsForward = true;
612  typeRef.TargetNodeId = item.TypeDefinition;
614  AddReference(typeRef);
615  }
616 
617  result.Status = StatusCode::Good;
618  result.AddedNodeId = resultId;
619 
620  LOG_TRACE(Logger, "address_space_internal| node added");
621 
622  return result;
623 }
624 
626 {
627  NodesMap::iterator node_it = Nodes.find(item.SourceNodeId);
628 
629  if (node_it == Nodes.end())
630  {
632  }
633 
634  NodesMap::iterator targetnode_it = Nodes.find(item.TargetNodeId);
635 
636  if (targetnode_it == Nodes.end())
637  {
639  }
640 
642  desc.ReferenceTypeId = item.ReferenceTypeId;
643  desc.IsForward = item.IsForward;
644  desc.TargetNodeId = item.TargetNodeId;
645  desc.TargetNodeClass = item.TargetNodeClass;
647 
648  if (dv.Status == StatusCode::Good)
649  {
650  desc.BrowseName = dv.Value.As<QualifiedName>();
651  }
652 
653  else
654  {
655  desc.BrowseName = QualifiedName("NONAME", 0);
656  }
657 
659 
660  if (dv.Status == StatusCode::Good)
661  {
662  desc.DisplayName = dv.Value.As<LocalizedText>();
663  }
664 
665  else
666  {
668  }
669 
670  node_it->second.References.push_back(desc);
671  return StatusCode::Good;
672 }
673 
675 {
676  uint32_t idx;
677 
678  if (id == ObjectId::Null || id.IsNull())
679  {
680  idx = DefaultIdx;
681  }
682 
683  else
684  {
685  if (id.HasNullIdentifier())
686  {
687  idx = id.GetNamespaceIndex();
688  }
689 
690  else
691  {
692  return id;
693  }
694  }
695 
696  // skip over already assigned node id's
697  // this should be a very seldom operation - it only happens when
698  // we actively assign static node id's to some nodes and after that
699  // create nodes using automatic id allocation and even then it
700  // only happens once. So we don't care about optimiziation here.
701  for (;;)
702  {
703  NodeId result = OpcUa::NumericNodeId(++MaxNodeIdNum, idx);
704 
705  if (Nodes.find(result) == Nodes.end())
706  {
707  return result;
708  }
709 
710  // completly unlikly - we would have to allocate 4gig nodes to
711  // fullfill this condition
712  if (MaxNodeIdNum == std::numeric_limits<uint32_t>::max())
713  {
714  throw std::runtime_error("address_space_internal| unable to assign new NodeId: range exceeded");
715  }
716  }
717 }
718 }
719 
720 namespace Server
721 {
722 AddressSpace::UniquePtr CreateAddressSpace(const Common::Logger::SharedPtr & logger)
723 {
724  return AddressSpace::UniquePtr(new Internal::AddressSpaceInMemory(logger));
725 }
726 }
727 }
virtual std::vector< DataValue > Read(const ReadParameters &params) const
std::vector< OpcUa::ReadValueId > AttributesToRead
#define LOG_TRACE(__logger__,...)
Definition: common/logger.h:23
AddressSpaceInMemory(const Common::Logger::SharedPtr &logger)
#define LOG_WARN(__logger__,...)
Definition: common/logger.h:26
virtual std::vector< StatusCode > Write(const std::vector< OpcUa::WriteValue > &values)
std::vector< OpcUa::Variant > OutputArguments
StatusCode AddReference(const AddReferencesItem &item)
bool IsSuitableReferenceType(const ReferenceDescription &reference, const NodeId &typeId, bool includeSubtypes) const
std::vector< BrowseDescription > NodesToBrowse
Definition: protocol/view.h:50
const uint8_t DATA_VALUE_STATUS_CODE
Definition: data_value.h:19
std::vector< OpcUa::StatusCode > InputArgumentResults
std::map< AttributeId, Variant > Attributes
std::vector< BrowsePath > BrowsePaths
std::vector< OpcUa::Variant > InputArguments
#define LOG_ERROR(__logger__,...)
Definition: common/logger.h:27
#define LOG_DEBUG(__logger__,...)
Definition: common/logger.h:24
ClientIdToAttributeMapType ClientIdToAttributeMap
std::tuple< bool, NodeId > FindElementInNode(const NodeId &nodeid, const RelativePathElement &element) const
void DeleteDataChangeCallback(uint32_t serverhandle)
Delete data change callback assosioated with handle.
StatusCode SetValue(const NodeId &node, AttributeId attribute, const DataValue &data)
virtual std::vector< StatusCode > AddReferences(const std::vector< AddReferencesItem > &items)
virtual std::vector< AddNodesResult > AddNodes(const std::vector< AddNodesItem > &items)
std::vector< NodeId > SelectNodesHierarchy(std::vector< NodeId > sourceNodes) const
std::vector< ReferenceDescription > References
DataValue GetValue(const NodeId &node, AttributeId attribute) const
BrowsePathResult TranslateBrowsePath(const BrowsePath &browsepath) const
std::function< Server::DataChangeCallback > Callback
virtual std::vector< BrowsePathResult > TranslateBrowsePathsToNodeIds(const TranslateBrowsePathsParameters &params) const
std::vector< RelativePathElement > Elements
Definition: types.h:125
handle
Definition: client.py:58
CallMethodResult CallMethod(CallMethodRequest method)
RelativePath Path
virtual std::vector< BrowseResult > BrowseNext() const
virtual void UnregisterNodes(const std::vector< NodeId > &params) const
uint32_t AddDataChangeCallback(const NodeId &node, AttributeId attribute, std::function< Server::DataChangeCallback > callback)
Add callback which will be called when values of attribute is changed.
OPC UA Address space part. GNU LGPL.
BrowseResultMask ResultMask
Definition: protocol/view.h:41
NodeClass
Definition: enums.h:39
std::string Name
Definition: types.h:74
void SetMethod(const NodeId &node, std::function< std::vector< OpcUa::Variant >(NodeId context, std::vector< OpcUa::Variant > arguments)> callback)
Set method function for a method node.
std::map< IntegerId, std::shared_ptr< InternalSubscription > > SubscriptionsIdMap
virtual std::vector< BrowseResult > Browse(const OpcUa::NodesQuery &query) const
std::string ToString(const AttributeId &value)
static DateTime Current()
virtual std::vector< OpcUa::CallMethodResult > Call(const std::vector< OpcUa::CallMethodRequest > &methodsToCall)
void SetServerTimestamp(const DateTime &t)
Definition: data_value.h:116
BrowseDirection Direction
Definition: protocol/view.h:37
OpcUa::AttributeId AttributeId
const uint8_t DATA_VALUE
Definition: data_value.h:18
virtual std::vector< NodeId > RegisterNodes(const std::vector< NodeId > &params) const
std::vector< ReferenceDescription > Referencies
Definition: protocol/view.h:82
AddressSpace::UniquePtr CreateAddressSpace(const Common::Logger::SharedPtr &logger)
uint8_t Encoding
Definition: data_value.h:28
T As() const
Definition: variant.h:271
std::vector< BrowsePathTarget > Targets
NodeId NumericNodeId(uint32_t value, uint16_t namespaceIndex=0)
Definition: nodeid.h:218
OpcUa::StatusCode Status
StatusCode Status
Definition: data_value.h:30
AddNodesResult AddNode(const AddNodesItem &item)
OpcUa::NodeId NodeId
idx
Definition: client.py:32
const char Server[]
Definition: strings.h:121
bool IsSuitableReference(const BrowseDescription &desc, const ReferenceDescription &reference) const
QualifiedName TargetName
Definition: types.h:120
StatusCode SetValueCallback(const NodeId &node, AttributeId attribute, std::function< DataValue(void)> callback)
Set callback which will be called to read new value of the attribue.


ros_opcua_impl_freeopcua
Author(s): Denis Štogl
autogenerated on Tue Jan 19 2021 03:06:03