00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <iostream>
00022
00023 #include <opc/ua/node.h>
00024
00025 #include <opc/ua/protocol/node_management.h>
00026 #include <opc/ua/protocol/strings.h>
00027 #include <opc/ua/protocol/string_utils.h>
00028 #include <opc/ua/protocol/variable_access_level.h>
00029
00030 namespace OpcUa
00031 {
00032
00033 Node::Node(Services::SharedPtr srv)
00034 : Node(srv, NumericNodeId(0, 0))
00035 {
00036 }
00037
00038 Node::Node(Services::SharedPtr srv, const NodeId& id)
00039 : Server(srv)
00040 , Id(id)
00041 {
00042 }
00043
00044 Node::Node(const Node& other)
00045 : Server(other.Server)
00046 , Id(other.Id)
00047 {
00048 }
00049
00050 NodeId Node::GetId() const
00051 {
00052 return Id;
00053 }
00054
00055 DataValue Node::GetAttribute(const AttributeId attr) const
00056 {
00057 ReadParameters params;
00058 ReadValueId attribute;
00059 attribute.NodeId = Id;
00060 attribute.AttributeId = attr;
00061 params.AttributesToRead.push_back(attribute);
00062 std::vector<DataValue> vec = Server->Attributes()-> Read(params);
00063 if ( vec.size() > 0 )
00064 {
00065 return vec.front();
00066 }
00067 else
00068 {
00069 return DataValue();
00070 }
00071 }
00072
00073 std::vector<Variant> Node::CallMethod(const NodeId methodId, const std::vector<Variant> inputArguments) const
00074 {
00075 std::vector<NodeId> vec_methodId;
00076 vec_methodId.push_back(methodId);
00077
00078 std::vector<std::vector<Variant>> vec_inputArguments;
00079 vec_inputArguments.push_back(inputArguments);
00080
00081 std::vector<std::vector<Variant>> results = CallMethods(vec_methodId, vec_inputArguments);
00082
00083 return results.front();
00084 }
00085
00086 std::vector<std::vector<Variant>> Node::CallMethods(const std::vector<NodeId> methodIds, const std::vector<std::vector<Variant>> inputArguments) const
00087 {
00088 std::vector<CallMethodRequest> methodsToCall;
00089
00090 std::vector<NodeId>::const_iterator it1;
00091 std::vector<std::vector<Variant>>::const_iterator it2;
00092 for (it1 = methodIds.begin(), it2 = inputArguments.begin();
00093 it1 != methodIds.end() && it2 != inputArguments.end();
00094 ++it1, ++it2)
00095 {
00096 CallMethodRequest callMethod;
00097 callMethod.ObjectId = Id;
00098 callMethod.MethodId = *it1;
00099 callMethod.InputArguments = *it2;
00100
00101 methodsToCall.push_back(callMethod);
00102 }
00103
00104 std::vector<CallMethodResult> results = Server->Method()->Call(methodsToCall);
00105
00106 std::vector<std::vector<Variant>> ret;
00107 for (std::vector<CallMethodResult>::iterator it = results.begin(); it != results.end(); ++it)
00108 {
00109 CheckStatusCode(it->Status);
00110 ret.push_back(it->OutputArguments);
00111 }
00112
00113 return ret;
00114 }
00115
00116 void Node::SetAttribute(AttributeId attr, const DataValue &dval) const
00117 {
00118 WriteValue attribute;
00119 attribute.NodeId = Id;
00120 attribute.AttributeId = attr;
00121 attribute.Value = dval;
00122 std::vector<StatusCode> codes = Server->Attributes()->Write(std::vector<WriteValue>(1, attribute));
00123 CheckStatusCode(codes.front());
00124 }
00125
00126 void Node::SetValue(const Variant& val) const
00127 {
00128 DataValue dval(val);
00129 SetAttribute(AttributeId::Value, dval);
00130 }
00131
00132 void Node::SetValue(const DataValue &dval) const
00133 {
00134 SetAttribute(AttributeId::Value, dval);
00135 }
00136
00137
00138 std::vector<Node> Node::GetChildren(const ReferenceId& refid) const
00139 {
00140 BrowseDescription description;
00141 description.NodeToBrowse = Id;
00142 description.Direction = BrowseDirection::Forward;
00143 description.IncludeSubtypes = true;
00144 description.NodeClasses = NodeClass::Unspecified;
00145 description.ResultMask = BrowseResultMask::All;
00146 description.ReferenceTypeId = refid;
00147
00148 NodesQuery query;
00149 query.NodesToBrowse.push_back(description);
00150 query.MaxReferenciesPerNode = 100;
00151 std::vector<Node> nodes;
00152 std::vector<BrowseResult> results = Server->Views()->Browse(query);
00153 if ( results.empty() )
00154 {
00155 return nodes;
00156 }
00157 while(!results[0].Referencies.empty())
00158 {
00159 for (auto refIt : results[0].Referencies)
00160 {
00161 Node node(Server, refIt.TargetNodeId);
00162 nodes.push_back(node);
00163 }
00164 results = Server->Views()->BrowseNext();
00165 if ( results.empty() )
00166 {
00167 return nodes;
00168 }
00169 }
00170 return nodes;
00171 }
00172
00173 std::vector<Node> Node::GetChildren() const
00174 {
00175 return GetChildren(ReferenceId::HierarchicalReferences);
00176 }
00177
00178 QualifiedName Node::GetBrowseName() const
00179 {
00180 Variant var = GetAttribute(AttributeId::BrowseName).Value;
00181 if (var.Type() != VariantType::QUALIFIED_NAME)
00182 {
00183 throw std::runtime_error("Could not retrieve browse name.");
00184 }
00185 return var.As<QualifiedName>();
00186 }
00187
00188 std::vector<AddNodesResult> Node::AddNodes(std::vector<AddNodesItem> items) const
00189 {
00190 return Server->NodeManagement()->AddNodes(items);
00191 }
00192
00193 std::vector<StatusCode> Node::AddReferences(std::vector<AddReferencesItem> items) const
00194 {
00195 return Server->NodeManagement()->AddReferences(items);
00196 }
00197
00198 Node Node::GetChild(const std::string& browsename) const
00199 {
00200 return GetChild(std::vector<std::string>({browsename}));
00201 }
00202
00203 Node Node::GetChild(const std::vector<std::string>& path) const
00204 {
00205 std::vector<QualifiedName> vec;
00206 uint16_t namespaceIdx = Id.GetNamespaceIndex();
00207 for (std::string str: path)
00208 {
00209 QualifiedName qname = ToQualifiedName(str, namespaceIdx);
00210 namespaceIdx = qname.NamespaceIndex;
00211 vec.push_back(qname);
00212 }
00213 return GetChild(vec);
00214 }
00215
00216
00217 Node Node::GetChild(const std::vector<QualifiedName>& path) const
00218 {
00219 std::vector<RelativePathElement> rpath;
00220 for (QualifiedName qname: path)
00221 {
00222 RelativePathElement el;
00223 el.TargetName = qname;
00224 rpath.push_back(el);
00225 }
00226 BrowsePath bpath;
00227 bpath.Path.Elements = rpath;
00228 bpath.StartingNode = Id;
00229 std::vector<BrowsePath> bpaths;
00230 bpaths.push_back(bpath);
00231 TranslateBrowsePathsParameters params;
00232 params.BrowsePaths = bpaths;
00233
00234 std::vector<BrowsePathResult> result = Server->Views()->TranslateBrowsePathsToNodeIds(params);
00235 CheckStatusCode(result.front().Status);
00236
00237 NodeId node =result.front().Targets.front().Node ;
00238 return Node(Server, node);
00239 }
00240
00241 std::string Node::ToString() const
00242 {
00243 std::ostringstream os;
00244 os << "Node(" << Id << ")";
00245 return os.str();
00246 }
00247
00248 Node Node::AddFolder(const std::string& nodeid, const std::string& browsename) const
00249 {
00250 NodeId node = ToNodeId(nodeid, this->Id.GetNamespaceIndex());
00251 QualifiedName qn = ToQualifiedName(browsename, GetBrowseName().NamespaceIndex);
00252 return AddFolder(node, qn);
00253 }
00254
00255 Node Node::AddFolder(uint32_t namespaceIdx, const std::string& name) const
00256 {
00257 NodeId nodeid = NumericNodeId(0, namespaceIdx);
00258 QualifiedName qn = ToQualifiedName(name, namespaceIdx);
00259 return AddFolder(nodeid, qn);
00260 }
00261
00262 Node Node::AddFolder(const NodeId& nodeid, const QualifiedName& browsename) const
00263 {
00264
00265 AddNodesItem item;
00266 item.BrowseName = browsename;
00267 item.ParentNodeId = this->Id;
00268 item.RequestedNewNodeId = nodeid;
00269 item.Class = NodeClass::Object;
00270 item.ReferenceTypeId = ReferenceId::Organizes;
00271 item.TypeDefinition = ObjectId::FolderType;
00272 ObjectAttributes attr;
00273 attr.DisplayName = LocalizedText(browsename.Name);
00274 attr.Description = LocalizedText(browsename.Name);
00275 attr.WriteMask = 0;
00276 attr.UserWriteMask = 0;
00277 attr.EventNotifier = 0;
00278 item.Attributes = attr;
00279
00280 std::vector<AddNodesResult> addnodesresults = Server->NodeManagement()->AddNodes(std::vector<AddNodesItem>({item}));
00281 AddNodesResult res = addnodesresults.front();
00282 CheckStatusCode(res.Status);
00283
00284 return Node(Server, res.AddedNodeId);
00285 }
00286
00287 Node Node::AddObject(const std::string& nodeid, const std::string& browsename) const
00288 {
00289 NodeId node = ToNodeId(nodeid, this->Id.GetNamespaceIndex());
00290 QualifiedName qn = ToQualifiedName(browsename, GetBrowseName().NamespaceIndex);
00291 return AddObject(node, qn);
00292 }
00293
00294 Node Node::AddObject(uint32_t namespaceIdx, const std::string& name) const
00295 {
00296
00297 NodeId nodeid = NumericNodeId(0, namespaceIdx);
00298 QualifiedName qn = ToQualifiedName(name, namespaceIdx);
00299 return AddObject(nodeid, qn);
00300 }
00301
00302 Node Node::AddObject(const NodeId& nodeid, const QualifiedName& browsename) const
00303 {
00304 AddNodesItem item;
00305 item.BrowseName = browsename;
00306 item.ParentNodeId = this->Id;
00307 item.RequestedNewNodeId = nodeid;
00308 item.Class = NodeClass::Object;
00309 item.ReferenceTypeId = ReferenceId::HasComponent;
00310 item.TypeDefinition = ObjectId::BaseObjectType;
00311 ObjectAttributes attr;
00312 attr.DisplayName = LocalizedText(browsename.Name);
00313 attr.Description = LocalizedText(browsename.Name);
00314 attr.WriteMask = 0;
00315 attr.UserWriteMask = 0;
00316 attr.EventNotifier = 0;
00317 item.Attributes = attr;
00318
00319 std::vector<AddNodesResult> addnodesresults = Server->NodeManagement()->AddNodes(std::vector<AddNodesItem>({item}));
00320
00321 AddNodesResult res = addnodesresults.front();
00322 CheckStatusCode(res.Status);
00323
00324 return Node(Server, res.AddedNodeId);
00325 }
00326
00327 Node Node::AddVariable(uint32_t namespaceIdx, const std::string& name, const Variant& val) const
00328 {
00329 NodeId nodeid = NumericNodeId(0, namespaceIdx);
00330 QualifiedName qn = ToQualifiedName(name, namespaceIdx);
00331 return AddVariable(nodeid, qn, val);
00332 }
00333
00334 Node Node::AddVariable(const std::string& nodeid, const std::string& browsename, const Variant& val) const
00335 {
00336 NodeId node = ToNodeId(nodeid, this->Id.GetNamespaceIndex());
00337 QualifiedName qn = ToQualifiedName(browsename, GetBrowseName().NamespaceIndex);
00338 return AddVariable(node, qn, val);
00339 }
00340
00341 Node Node::AddVariable(const NodeId& nodeid, const QualifiedName& browsename, const Variant& val) const
00342 {
00343 ObjectId datatype = VariantTypeToDataType(val.Type());
00344
00345 AddNodesItem item;
00346 item.BrowseName = browsename;
00347 item.ParentNodeId = this->Id;
00348 item.RequestedNewNodeId = nodeid;
00349 item.Class = NodeClass::Variable;
00350 item.ReferenceTypeId = ReferenceId::HasComponent;
00351 item.TypeDefinition = ObjectId::BaseDataVariableType;
00352 VariableAttributes attr;
00353 attr.DisplayName = LocalizedText(browsename.Name);
00354 attr.Description = LocalizedText(browsename.Name);
00355 attr.WriteMask = (uint32_t)OpenFileMode::Read;
00356 attr.UserWriteMask = (uint32_t)OpenFileMode::Read;
00357 attr.Value = val;
00358 attr.Type = datatype;
00359 attr.Rank = -1;
00360 attr.Dimensions = val.Dimensions;
00361 attr.AccessLevel = VariableAccessLevel::CurrentRead;
00362 attr.UserAccessLevel = VariableAccessLevel::CurrentRead;
00363 attr.MinimumSamplingInterval = 1;
00364 attr.Historizing = 0;
00365 item.Attributes = attr;
00366
00367 std::vector<AddNodesResult> addnodesresults = Server->NodeManagement()->AddNodes(std::vector<AddNodesItem>({item}));
00368
00369 AddNodesResult res = addnodesresults.front();
00370 CheckStatusCode(res.Status);
00371
00372 return Node(Server, res.AddedNodeId);
00373 }
00374
00375
00376 Node Node::AddProperty(uint32_t namespaceIdx, const std::string& name, const Variant& val) const
00377 {
00378 NodeId nodeid = NumericNodeId(0, namespaceIdx);
00379 const QualifiedName& qname = ToQualifiedName(name, namespaceIdx);
00380 return AddProperty(nodeid, qname, val);
00381 }
00382
00383 Node Node::AddProperty(const std::string& nodeid, const std::string& browsename, const Variant& val) const
00384 {
00385 NodeId node = ToNodeId(nodeid, this->Id.GetNamespaceIndex());
00386 QualifiedName qn = ToQualifiedName(browsename, GetBrowseName().NamespaceIndex);
00387 return AddProperty(node, qn, val);
00388 }
00389
00390 Node Node::AddProperty(const NodeId& nodeid, const QualifiedName& browsename, const Variant& val) const
00391 {
00392
00393 ObjectId datatype = VariantTypeToDataType(val.Type());
00394
00395 AddNodesItem item;
00396 item.BrowseName = browsename;
00397 item.ParentNodeId = this->Id;
00398 item.RequestedNewNodeId = nodeid;
00399 item.Class = NodeClass::Variable;
00400 item.ReferenceTypeId = ReferenceId::HasProperty;
00401 item.TypeDefinition = ObjectId::PropertyType;
00402 VariableAttributes attr;
00403 attr.DisplayName = LocalizedText(browsename.Name);
00404 attr.Description = LocalizedText(browsename.Name);
00405 attr.WriteMask = 0;
00406 attr.UserWriteMask = 0;
00407 attr.Value = val;
00408 attr.Type = datatype;
00409 attr.Rank = 0;
00410 attr.Dimensions = val.Dimensions;
00411 attr.AccessLevel = VariableAccessLevel::CurrentRead;
00412 attr.UserAccessLevel = VariableAccessLevel::CurrentRead;
00413 attr.MinimumSamplingInterval = 0;
00414 attr.Historizing = 0;
00415 item.Attributes = attr;
00416
00417 std::vector<AddNodesResult> addnodesresults = Server->NodeManagement()->AddNodes(std::vector<AddNodesItem>({item}));
00418
00419 AddNodesResult res = addnodesresults.front();
00420 CheckStatusCode(res.Status);
00421
00422 return Node(Server, res.AddedNodeId);
00423
00424 }
00425
00426 Node Node::AddMethod(uint32_t namespaceIdx, const std::string& name, std::function<std::vector<OpcUa::Variant> (std::vector<OpcUa::Variant> arguments)> method) const
00427 {
00428 NodeId nodeid = NumericNodeId(0, namespaceIdx);
00429 QualifiedName qn = ToQualifiedName(name, namespaceIdx);
00430 return AddVariable(nodeid, qn, method);
00431 }
00432
00433 Node Node::AddMethod(const std::string& nodeid, const std::string& browsename, std::function<std::vector<OpcUa::Variant> (std::vector<OpcUa::Variant> arguments)> method) const
00434 {
00435 NodeId node = ToNodeId(nodeid, this->Id.GetNamespaceIndex());
00436 QualifiedName qn = ToQualifiedName(browsename, GetBrowseName().NamespaceIndex);
00437 return AddVariable(node, qn, method);
00438 }
00439
00440 Node Node::AddMethod(const NodeId& nodeid, const QualifiedName& browsename, std::function<std::vector<OpcUa::Variant> (std::vector<OpcUa::Variant> arguments)> method) const
00441 {
00442 AddNodesItem item;
00443 item.BrowseName = browsename;
00444 item.ParentNodeId = this->Id;
00445 item.RequestedNewNodeId = nodeid;
00446 item.Class = NodeClass::Method;
00447 item.ReferenceTypeId = ReferenceId::HasComponent;
00448
00449 MethodAttributes attr;
00450 attr.DisplayName = LocalizedText(browsename.Name);
00451 attr.Description = LocalizedText(browsename.Name);
00452 attr.WriteMask = 0;
00453 attr.UserWriteMask = 0;
00454 attr.Executable = true;
00455 attr.UserExecutable = true;
00456 item.Attributes = attr;
00457
00458 std::vector<AddNodesResult> addnodesresults = Server->NodeManagement()->AddNodes(std::vector<AddNodesItem>({item}));
00459
00460 AddNodesResult res = addnodesresults.front();
00461 CheckStatusCode(res.Status);
00462
00463
00464 return Node(Server, res.AddedNodeId);
00465 }
00466
00467
00468
00469 Variant Node::GetValue() const
00470 {
00471 return (GetAttribute(AttributeId::Value)).Value;
00472 }
00473
00474 DataValue Node::GetDataValue() const
00475 {
00476 return GetAttribute(AttributeId::Value);
00477 }
00478
00479 Variant Node::GetDataType() const
00480 {
00481 return (GetAttribute(AttributeId::DataType)).Value;
00482 }
00483
00484 }
00485
00486
00487 std::ostream& OpcUa::operator<<(std::ostream& os, const Node& node)
00488 {
00489 os << node.ToString();
00490 return os;
00491 }
00492