ChimeraTK-ControlSystemAdapter-OPCUAAdapter 04.00.05
Loading...
Searching...
No Matches
csa_opcua_adapter_example.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) 2018-2019 Andreas Ebner <Andreas.Ebner@iosb.fraunhofer.de>
20 */
21
22extern "C" {
23#include "csa_namespace.h"
24
25#include <signal.h>
26#include <unistd.h>
27}
28
29#include "ChimeraTK/ControlSystemAdapter/ControlSystemPVManager.h"
30#include "csa_opcua_adapter.h"
32
33#include <errno.h>
34#include <stdlib.h>
35#include <time.h>
36
37#include <chrono>
38#include <iostream>
39
40using namespace std;
41using namespace ChimeraTK;
42
45
46/* FUNCTIONS */
47static void SigHandler_Int(int /*sign*/) {
48 cout << "Received SIGINT... terminating" << endl;
50 csaOPCUA->stop();
52 cout << "terminated threads" << endl;
53}
54
55int main() {
56 signal(SIGINT, SigHandler_Int); // Registriert CTRL-C/SIGINT
57 signal(SIGTERM, SigHandler_Int); // Registriert SIGTERM
58
59 clock_t start = clock();
60
61 // Create the managers
62 std::pair<boost::shared_ptr<ControlSystemPVManager>, boost::shared_ptr<DevicePVManager>> pvManagers =
63 createPVManager();
64
65 boost::shared_ptr<DevicePVManager> devManager = pvManagers.second;
66 boost::shared_ptr<ControlSystemPVManager> csManager = pvManagers.first;
67
68 // Generate dummy data
69 ProcessArray<int8_t>::SharedPtr intA8dev = devManager->createProcessArray<int8_t>(
70 SynchronizationDirection::controlSystemToDevice, "int8Scalar", 1, "Iatrou^2/Rahm");
71 ProcessArray<uint8_t>::SharedPtr intAu8dev = devManager->createProcessArray<uint8_t>(
72 SynchronizationDirection::controlSystemToDevice, "uint8Scalar", 1, "mIatrou*Rahm");
73 ProcessArray<int16_t>::SharedPtr intA16dev =
74 devManager->createProcessArray<int16_t>(SynchronizationDirection::controlSystemToDevice, "int16Scalar", 1);
75 ProcessArray<uint16_t>::SharedPtr intAu16dev =
76 devManager->createProcessArray<uint16_t>(SynchronizationDirection::controlSystemToDevice, "uint16Scalar", 1);
77 ProcessArray<int32_t>::SharedPtr intA32dev =
78 devManager->createProcessArray<int32_t>(SynchronizationDirection::controlSystemToDevice, "int32Scalar", 1);
79 ProcessArray<uint32_t>::SharedPtr intAu32dev =
80 devManager->createProcessArray<uint32_t>(SynchronizationDirection::controlSystemToDevice, "uint32Scalar", 1);
81 ProcessArray<float>::SharedPtr intAfdev =
82 devManager->createProcessArray<float>(SynchronizationDirection::controlSystemToDevice, "floatScalar", 1);
83 ProcessArray<double>::SharedPtr intAddev =
84 devManager->createProcessArray<double>(SynchronizationDirection::controlSystemToDevice, "doubleScalar", 1);
85 ProcessArray<string>::SharedPtr stringAddev =
86 devManager->createProcessArray<string>(SynchronizationDirection::controlSystemToDevice, "stringScalar", 1);
87 ProcessArray<string>::SharedPtr stringAddev2 = devManager->createProcessArray<string>(
88 SynchronizationDirection::deviceToControlSystem, "1/FOLDER/defaultSep/stringScalar", 1, "my description", "desc");
89
90 ProcessArray<int8_t>::SharedPtr intB15A8dev =
91 devManager->createProcessArray<int8_t>(SynchronizationDirection::controlSystemToDevice, "int8Array_s15", 15,
92 "mIatrou*Rahm", "Die Einheit ist essentiel und sollte SI Einheit sein...");
93 ProcessArray<uint8_t>::SharedPtr intB10Au8dev = devManager->createProcessArray<uint8_t>(
94 SynchronizationDirection::controlSystemToDevice, "uint8Array_s10", 10, "1/Rahm");
95 ProcessArray<int16_t>::SharedPtr intB15A16dev = devManager->createProcessArray<int16_t>(
96 SynchronizationDirection::controlSystemToDevice, "int16Array_s15", 15, "Iatrou", "Beschreibung eines Iatrous");
97 ProcessArray<uint16_t>::SharedPtr intB10Au16dev =
98 devManager->createProcessArray<uint16_t>(SynchronizationDirection::controlSystemToDevice, "uint16Array_s10", 10);
99 ProcessArray<int32_t>::SharedPtr intB15A32dev =
100 devManager->createProcessArray<int32_t>(SynchronizationDirection::controlSystemToDevice, "int32Array_s15", 15);
101 ProcessArray<uint32_t>::SharedPtr intB10Au32dev =
102 devManager->createProcessArray<uint32_t>(SynchronizationDirection::controlSystemToDevice, "uint32Array_s10", 10);
103 ProcessArray<double>::SharedPtr intB15Afdev =
104 devManager->createProcessArray<double>(SynchronizationDirection::controlSystemToDevice, "doubleArray_s15", 15);
105 ProcessArray<float>::SharedPtr intB10Addev =
106 devManager->createProcessArray<float>(SynchronizationDirection::controlSystemToDevice, "floatArray_s10", 10);
107
108 // data generation cycle time in ms
109 ProcessArray<int32_t>::SharedPtr dtDev =
110 devManager->createProcessArray<int32_t>(SynchronizationDirection::controlSystemToDevice, "dt", 1);
111 // time since server start in ms
112 ProcessArray<int32_t>::SharedPtr tDev =
113 devManager->createProcessArray<int32_t>(SynchronizationDirection::deviceToControlSystem, "t", 1);
114 ProcessArray<double>::SharedPtr periodDev =
115 devManager->createProcessArray<double>(SynchronizationDirection::controlSystemToDevice, "period", 1);
116 ProcessArray<double>::SharedPtr amplitudeDev =
117 devManager->createProcessArray<double>(SynchronizationDirection::controlSystemToDevice, "amplitude", 1);
118 ProcessArray<double>::SharedPtr double_sineDev =
119 devManager->createProcessArray<double>(SynchronizationDirection::deviceToControlSystem, "double_sine", 1);
120 ProcessArray<int32_t>::SharedPtr int_sineDev =
121 devManager->createProcessArray<int32_t>(SynchronizationDirection::deviceToControlSystem, "int_sine", 1);
122 ProcessArray<ChimeraTK::Boolean>::SharedPtr boolDev =
123 devManager->createProcessArray<ChimeraTK::Boolean>(SynchronizationDirection::deviceToControlSystem, "bool", 1);
124 ProcessArray<ChimeraTK::Void>::SharedPtr voidDev =
125 devManager->createProcessArray<ChimeraTK::Void>(SynchronizationDirection::deviceToControlSystem, "void", 1);
126
127 // example mapping variable
128 ProcessArray<int8_t>::SharedPtr intB15A8devMap = devManager->createProcessArray<int8_t>(
129 SynchronizationDirection::controlSystemToDevice, "Mein/Name_ist#int8Array_s15", 15, "Iatrou^2/Rahm");
130 ProcessArray<int8_t>::SharedPtr intB15A8devMap2 = devManager->createProcessArray<int8_t>(
131 SynchronizationDirection::controlSystemToDevice, "Mein/Name_ist#int8Array", 15, "Iatrou^2/Rahm");
132 ProcessArray<uint8_t>::SharedPtr intB10Au8devMap1 =
133 devManager->createProcessArray<uint8_t>(SynchronizationDirection::controlSystemToDevice,
134 "/Dein/Name//ist/uint8Array_s10", 10, "Iatrou^2/Rahm", "Beschreibung");
135 ProcessArray<uint8_t>::SharedPtr intB10Au8devMap2 = devManager->createProcessArray<uint8_t>(
136 SynchronizationDirection::controlSystemToDevice, "Unser/Name/ist_uint8Array_s10", 10);
137 ProcessArray<uint32_t>::SharedPtr intAu32devMap = devManager->createProcessArray<uint32_t>(
138 SynchronizationDirection::controlSystemToDevice, "Ist/Name/dieser/uint32Scalar", 1);
139 ProcessArray<int32_t>::SharedPtr intA32devMap = devManager->createProcessArray<int32_t>(
140 SynchronizationDirection::controlSystemToDevice, "Ist/Name/dieser/int32Scalar", 1);
141 ProcessArray<double>::SharedPtr doubledevMap = devManager->createProcessArray<double>(
142 SynchronizationDirection::controlSystemToDevice, "Ist/Name/dieser/doubleScalar", 1);
143
144 time_t t;
145 time(&t);
146 srand((unsigned int)t);
147 for(int32_t i = 1000; i < 65535; i = i + 1000) {
148 string nameDouble = "testDoubleArray_" + to_string(i);
149 string nameInt = "testIntArray_" + to_string(i);
150 ProcessArray<double>::SharedPtr testDoubleArray =
151 devManager->createProcessArray<double>(SynchronizationDirection::bidirectional, nameDouble, i);
152 ProcessArray<int32_t>::SharedPtr testIntArray =
153 devManager->createProcessArray<int32_t>(SynchronizationDirection::deviceToControlSystem, nameInt, i);
154 for(int32_t k = 0; k < i; k++) {
155 if(k % 2 == 0) {
156 testDoubleArray->accessChannel(0).at(k) = rand() % 6 + 1;
157 testIntArray->accessChannel(0).at(k) = rand() % 6 + 1;
158 }
159 else {
160 testDoubleArray->accessChannel(0).at(k) = rand() % 50 + 10;
161 testIntArray->accessChannel(0).at(k) = rand() % 50 + 10;
162 }
163 }
164 testDoubleArray->write();
165 testIntArray->write();
166 }
167
168 /* Adding some folder with variables
169 *
170 */
171 time(&t);
172 srand((unsigned int)t);
173 for(int32_t n = 1; n < 10; n++) {
174 for(int32_t i = 1000; i < 65535; i = i + 10000) {
175 string nameDouble = "folder/f" + to_string(n) + "/testDoubleArray_" + to_string(i);
176 string nameInt = "folder/f" + to_string(n) + "/testIntArray_" + to_string(i);
177 ProcessArray<double>::SharedPtr testDoubleArray =
178 devManager->createProcessArray<double>(SynchronizationDirection::deviceToControlSystem, nameDouble, i);
179 ProcessArray<int32_t>::SharedPtr testIntArray =
180 devManager->createProcessArray<int32_t>(SynchronizationDirection::deviceToControlSystem, nameInt, i);
181 for(int32_t k = i - 10; k < i; k++) {
182 if(k % 2 == 0) {
183 testDoubleArray->accessChannel(0).at(k) = rand() % 6 + 1;
184 testIntArray->accessChannel(0).at(k) = rand() % 6 + 1;
185 }
186 else {
187 testDoubleArray->accessChannel(0).at(k) = rand() % 50 + 10;
188 testIntArray->accessChannel(0).at(k) = rand() % 50 + 10;
189 }
190 }
191 testDoubleArray->write();
192 testIntArray->write();
193 }
194 }
195
196 ProcessArray<double>::SharedPtr testDoubleArray = devManager->createProcessArray<double>(
197 SynchronizationDirection::deviceToControlSystem, "testDoubleArray_65535", 65535);
198 ProcessArray<int32_t>::SharedPtr testIntArray = devManager->createProcessArray<int32_t>(
199 SynchronizationDirection::deviceToControlSystem, "testIntArray_65535", 65535);
200 for(int32_t i = 0; i < 65535; i++) {
201 if(i % 2 == 0) {
202 testDoubleArray->accessChannel(0).at(i) = rand() % 6 + 1;
203 testIntArray->accessChannel(0).at(i) = rand() % 6 + 1;
204 }
205 else {
206 testDoubleArray->accessChannel(0).at(i) = rand() % 50 + 10;
207 testIntArray->accessChannel(0).at(i) = rand() % 50 + 10;
208 }
209 }
210 testDoubleArray->write();
211 testIntArray->write();
212
213 stringAddev2->accessChannel(0).at(0) = "Test value";
214 stringAddev2->write();
215 // start values
216 int32_t microseconds = 1000000;
217 double period = 3.141;
218 double amplitude = 10;
219
220 csManager->getProcessArray<string>("stringScalar")->accessChannel(0) = vector<string>{"Merk"};
221 // Set values
222 csManager->getProcessArray<int32_t>("dt")->accessChannel(0) = vector<int32_t>{microseconds};
223 csManager->getProcessArray<int32_t>("dt")->write();
224 csManager->getProcessArray<double>("period")->accessChannel(0) = vector<double>{period};
225 csManager->getProcessArray<double>("period")->write();
226 csManager->getProcessArray<double>("amplitude")->accessChannel(0) = vector<double>{amplitude};
227 csManager->getProcessArray<double>("amplitude")->write();
228
229 csManager->getProcessArray<int8_t>("int8Scalar")->accessChannel(0) = vector<int8_t>{12};
230 cout << "write dummy Data..." << std::endl;
231
232 string pathToConfig = "opcuaAdapter_mapping.xml";
233 csaOPCUA = new csa_opcua_adapter(csManager, pathToConfig);
234 csaOPCUA->start();
235 while(!csaOPCUA->getUAAdapter()->running) {
236 };
237
238 // Only for Sin ValueGenerator
240
241 float duration = ((float)(clock() - start) / CLOCKS_PER_SEC) * 1000.0f;
242 printf("Start duration: %.3f ms\n", duration);
243
244 // Server is running
245 std::cout << "server is running..." << std::endl;
246 while(csaOPCUA->isRunning()) {
247 sleep(2);
248 }
249
250 return 0;
251}
This class provide the two parts of the OPCUA Adapter.
bool isRunning()
Checks if the opcua server is still running and return the suitable bool value.
~csa_opcua_adapter()
Destructor to stop the running thread, hence it stops the OPC UA server.
void start()
Start all objects in single threads for this case only the opc ua server.
std::shared_ptr< ua_uaadapter > getUAAdapter()
Return the uaadapter, hence the OPC UA server.
void stop()
Stop all objects in single threads for this case only the opc ua server.
csa_opcua_adapter * csaOPCUA
runtime_value_generator * valGen
boost::shared_ptr< ChimeraTK::ControlSystemPVManager > csManager
boost::shared_ptr< ChimeraTK::DevicePVManager > devManager