CVB++ 14.0
OpcUa/ServerClientInteraction
1// ----------------------------------------------------------------------------
24// ----------------------------------------------------------------------------
25
26
27#include <iostream>
28#include <memory>
29#include <locale>
30#include <codecvt>
31#include <thread>
32
33#include <cvb/opcua/server.hpp>
34#include <cvb/opcua/client.hpp>
35
36#if defined _WIN32 && defined(UNICODE)
37#define STDOUT std::wcout
38#else
39#define STDOUT std::cout
40#endif
41
42int main(int, char*[])
43{
44 try
45 {
46 // shared between server and client
47 bool started = false;
48 bool stopped = false;
49 auto nodeName = CVB_LIT("TestFloatNode");
50 std::thread th; // server thread
51
52 // setup a server
53 auto server = [&]()
54 {
55 try
56 {
57 // create actual server object
58 auto server = Cvb::OpcUa::Server::Create(4840);
59
60 // add a custom namespace (these are used for filtering/sorting data, but are optional, Namespace "0" always exists).
61 auto nsIndex = server->AddNameSpace("My Custom Namespace");
62
63 // create a nodeId to the "objects" folder, this folder exists/should exist in all server implementations.
64 auto root = Cvb::OpcUa::NodeID::Create(Cvb::OpcUa::Namespace0NodeID::OBJECTSFOLDER);
65 // create a nodeId of a "folder" type. This is needed to create a folder.
66 auto type = Cvb::OpcUa::NodeID::Create(Cvb::OpcUa::Namespace0NodeID::FOLDERTYPE);
67 // create a folder node with the previous namespace and nodeId.
68 auto folder = Cvb::OpcUa::ObjectNode::CreateFromType(nsIndex, "My Custom Folder", *root, *type);
69 // add the node
70 server->AddNode(*folder);
71
72 // create a "float" node.
73 auto node = Cvb::OpcUa::FloatNode::Create(nsIndex, nodeName, *folder->NodeID(), 5.5);
74
75 // add the float node.
76 server->AddNode(*node);
77
78 // register a callback to the float node.
79 auto callbackCookieWrite = node->RegisterWriteCallback([&node]()
80 {
81 STDOUT << CVB_LIT("write to ") << node->DisplayName() << std::endl;
82 });
83
84 // start the server
85 server->Start();
86
87 // this simply tells the client thread that the server is ready and can be connected on.
88 started = true;
89
90 // wait until end of the test.
91 while (!stopped)
93
94 // stop the server.
95 server->Stop();
96
97 // unregister the callback.
98 node->UnregisterCallback(callbackCookieWrite);
99 }
101 {
102 started = true; // to ignore waiting
103 stopped = true;
104 std::cout << e1.what() << std::endl;
105 }
106 catch (const std::exception & ex)
107 {
108 started = true; // to ignore waiting
109 stopped = true;
110 std::cout << ex.what() << std::endl;
111 }
112
113 };
114 // start server
115 th = std::thread(server);
116
117 // wait until server is ready
118 while (!started)
120
121 if (stopped)
122 throw std::runtime_error("server creation failed");
123
124 try
125 {
126 // create and connect client (client stops/disconnects at the end of its livetime, hence the extra scope)
127 auto client = Cvb::OpcUa::Client::Create(CVB_LIT("opc.tcp://127.0.0.1:4840"));
128
129 // get server objectsfolder nodeid
130 auto obj = client->Node(*Cvb::OpcUa::NodeID::Create(Cvb::OpcUa::Namespace0NodeID::OBJECTSFOLDER));
131
132 // defining our browsefilter
134 // apply the browsefilter. the result is a vector of nodeIds.
135 auto result = obj->Browse(*bf);
136
137 // iterate results
138 for (const auto & element : result)
139 {
140 // get generic node (and node properties)
141 auto node = client->Node<Cvb::OpcUa::BaseNode>(*element);
142
143 // print node displayname and expandedtext (nodeid/namespace)
144 auto name = node->DisplayName();
145 auto ns = node->NodeID()->ExpandedText();
146 std::cout << ns << " " << name << std::endl;
147
148 // read and write the value of all FloatNodes
149 if (node->NodeClass() == Cvb::OpcUa::NodeClass::Variable)
150 {
151 // get the node again as a variable node (this way we can get a specific type extracted)
152 auto vnode = client->Node<Cvb::OpcUa::VariableNode>(*element);
153 if (vnode->DataType() == Cvb::OpcUa::DataType::Double || vnode->DataType() == Cvb::OpcUa::DataType::Float)
154 {
155 // now get the node a float
156 auto fnode = client->Node<Cvb::OpcUa::FloatNode>(*element);
157
158 // read -> write -> read
159 auto tmp = fnode->Value();
160 std::cout << "node value before change " << tmp << std::endl;
161 fnode->SetValue(tmp + 1.1);
162 std::cout << "node value after change" << fnode->Value() << std::endl;
163 }
164 }
165 }
166 // the end of the scope will disconnect the client from the server
167
168 // stop the server
169 stopped = true;
170 }
172 {
173 std::cout << "client: " << e1.what() << std::endl;
174 stopped = true;
175 }
176 catch (const std::exception & ex)
177 {
178 std::cout << "client: " << ex.what() << std::endl;
179 stopped = true;
180 }
181 th.join();
182 }
184 {
185 std::cout << e1.what() << std::endl;
186 return e1.ErrorCode();
187 }
188 catch (const std::exception & ex)
189 {
190 std::cout << ex.what() << std::endl;
191 return -1;
192 }
193 return 0;
194}
An OPCUA BaseNode. This is the base for all other node classes. For instantiation of a specific node ...
Definition: decl_base_node.hpp:35
String DisplayName() const
Returns the humanreadable name of a node.
Definition: decl_base_node.hpp:91
static BrowseFilterPtr Create()
Creates an even simpler BrowseFilter for browsing the OPCUA client.
Definition: browse_filter.hpp:76
static OpcUa::ClientPtr Create(const Cvb::String &Url)
Creates an OPCUA Client object. And connect it to a given server. There is no disconnect/connect func...
Definition: detail_client.hpp:24
A FloatNode object provides an interface for storage and manipulation of floating point numbers.
Definition: float_node.hpp:24
static FloatNodePtr Create(std::uint16_t namespaceIndex, const Cvb::String &name, const OpcUa::NodeID &parentNodeID, double value)
Creates an OPCUA Variable with the specified parameter, data type and set its value as double.
Definition: float_node.hpp:45
double Value() const
Returns the saved value of the node.
Definition: float_node.hpp:66
static NodeIDPtr Create(Namespace0NodeID id)
Creates an id based on a predefined Namespace0 node id.
Definition: node_id.hpp:48
static ObjectNodePtr CreateFromType(const std::uint16_t NameSpaceIndex, const Cvb::String &Name, const OpcUa::NodeID &Parent, const OpcUa::NodeID &TypeDefinition)
Creates a OPCUA object node with a given type definition.
Definition: object_node.hpp:49
Special runtime exception to carry a native error code.
Definition: exception.hpp:25
int ErrorCode()
Retuns the error code. See Cvb::ErrorCodes.
Definition: exception.hpp:50
static ServerPtr Create(const std::uint16_t port)
Creates an OPCUA server with the specified port number.
Definition: detail_server.hpp:23
An OPCUA VariableNode object. It handles the data modeling acording to the OPCUA specification.
Definition: variable_node.hpp:26
@ Variable
Variable BaseNode Class.
@ Float
single precision floating point number
@ Double
double precision floating point number
T sleep_for(T... args)