UniSet 2.35.2
OPCUAExchange.h
1/*
2 * Copyright (c) 2023 Pavel Vainerman.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation, version 2.1.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Lesser Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16// -----------------------------------------------------------------------------
17#ifndef OPCUAExchange_H_
18#define OPCUAExchange_H_
19// -----------------------------------------------------------------------------
20#include <vector>
21#include <memory>
22#include <deque>
23#include <string>
24#include <regex>
25#include <optional>
26#include "UniXML.h"
27#include "ThreadCreator.h"
28#include "PassiveTimer.h"
29#include "Trigger.h"
30#include "IONotifyController.h"
31#include "UniSetObject.h"
32#include "Mutex.h"
33#include "MessageType.h"
34#include "SMInterface.h"
35#include "IOBase.h"
36#include "SharedMemory.h"
37#include "LogServer.h"
38#include "DebugStream.h"
39#include "LogAgregator.h"
40#include "OPCUAClient.h"
41// -------------------------------------------------------------------------
42#ifndef vmonit
43#define vmonit( var ) vmon.add( #var, var )
44#endif
45// -------------------------------------------------------------------------
46namespace uniset
47{
48 // ---------------------------------------------------------------------
177 // ---------------------------------------------------------------------
180 public UniSetObject
181 {
182 public:
183 OPCUAExchange( uniset::ObjectId id, xmlNode* cnode,
184 uniset::ObjectId icID, const std::shared_ptr<SharedMemory>& shm = nullptr,
185 const std::string& _prefix = "opcua" );
186 virtual ~OPCUAExchange();
187
188 static std::shared_ptr<OPCUAExchange> init_opcuaexchange(int argc, const char* const* argv,
189 uniset::ObjectId icID, const std::shared_ptr<SharedMemory>& ic = nullptr,
190 const std::string& prefix = "opcua");
191
192 static void help_print( int argc, const char* const* argv );
193
194 virtual uniset::SimpleInfo* getInfo( const char* userparam = 0 ) override;
195
196 static uint8_t firstBit( uint32_t mask );
197
198 // offset = firstBit(mask)
199 static uint32_t getBits( uint32_t value, uint32_t mask, uint8_t offset );
200 // if mask = 0 return value
201 static uint32_t setBits( uint32_t value, uint32_t set, uint32_t mask, uint8_t offset );
202 // if mask=0 return set
203 static uint32_t forceSetBits( uint32_t value, uint32_t set, uint32_t mask, uint8_t offset );
204
205 using Tick = uint8_t;
206
207 static const size_t numChannels = 2;
209 {
210 std::vector<std::vector<OPCUAClient::ResultVar>> results;
211 std::vector<std::vector<UA_ReadValueId>> ids;
212 };
214 {
215 std::vector<std::vector<UA_WriteValue>> ids;
216 };
219 public IOBase
220 {
221 // т.к. IOBase содержит rwmutex с запрещённым конструктором копирования
222 // приходится здесь тоже объявлять разрешенными только операции "перемещения"
223 OPCAttribute(const OPCAttribute& r ) = delete;
224 OPCAttribute& operator=(const OPCAttribute& r) = delete;
225 OPCAttribute(OPCAttribute&& r ) = default;
226 OPCAttribute& operator=(OPCAttribute&& r) = default;
227 OPCAttribute() = default;
228
230 int32_t val { 0 };
231 Tick tick = { 0 }; // на каждом ли тике работать с этим аттрибутом
232 uint32_t mask = { 0 };
233 uint8_t offset = { 0 };
234 OPCUAClient::VarType vtype = { OPCUAClient::VarType::Int32 };
235
236 // with precision
237 float as_float();
238
239 // with precision/noprecision
240 int32_t set( float val );
241
242 std::string attrName = {""};
243 struct RdValue
244 {
245 std::shared_ptr<ReadGroup> gr;
246 size_t grIndex = {0}; // индекс в запросе (номер в запросе)
247 size_t grNumber = {0}; // Номер группы запроса в общем списке
248 int32_t get();
249 float getF();
250 bool statusOk();
251 UA_StatusCode status();
252 const UA_ReadValueId& ref();
253 // Subscription
254 uint32_t subscriptionId = {0U};
255 uint32_t monitoredItemId = {0U};
256 bool subscriptionState = {false};
257 };
258 RdValue rval[numChannels];
259
260 struct WrValue
261 {
262 std::shared_ptr<WriteGroup> gr;
263 size_t grIndex = {0}; // индекс в запросе (номер в запросе)
264 size_t grNumber = {0}; // Номер группы запроса в общем списке
265 bool set( int32_t val );
266 bool setF( float val );
267 bool statusOk();
268 UA_StatusCode status();
269 const UA_WriteValue& ref();
270 static void init( UA_WriteValue* wval, const std::string& nodeId, const std::string& type, int32_t defvalue );
271 };
272 WrValue wval[numChannels];
273
274 friend std::ostream& operator<<(std::ostream& os, const OPCAttribute& inf );
275 friend std::ostream& operator<<(std::ostream& os, const std::shared_ptr<OPCAttribute>& inf );
276 };
277
280 {
281 emNone = 0,
286 emLastNumber
287 };
288
291 {
292 smNone = 0,
294 smAny = 2,
295 smLastNumber
296 };
297
298 typedef std::list<IOBase> ThresholdList;
299 // т.к. пороговые датчики не связаны напрямую с обменом, создаём для них отдельный список
300 // и отдельно его проверяем потом
301 ThresholdList thrlist;
302
303 protected:
304
305 enum Timers
306 {
307 tmUpdates
308 };
309
310 struct Channel;
311 void channel1Thread();
312 void channel2Thread();
313 void channelThread( Channel* ch );
314 bool prepare();
315 void channelExchange( Tick tick, Channel* ch, bool writeOn );
316 void updateFromChannel( Channel* ch );
317 void updateToChannel( Channel* ch );
318 void updateFromSM();
319 void writeToSM();
320 bool isUpdateSM( bool wrFunc ) const noexcept;
321
322 virtual void sysCommand( const uniset::SystemMessage* sm ) override;
323 virtual void askSensors( UniversalIO::UIOCommand cmd );
324 virtual void sensorInfo( const uniset::SensorMessage* sm ) override;
325 virtual void timerInfo( const uniset::TimerMessage* sm ) override;
326 virtual bool activateObject() override;
327 virtual bool deactivateObject() override;
328
329 // чтение файла конфигурации
330 void readConfiguration();
331 bool initIOItem( UniXML::iterator& it );
332 bool readItem( const std::shared_ptr<UniXML>& xml, UniXML::iterator& it, xmlNode* sec );
333 bool waitSM();
334 bool tryConnect(Channel* ch);
335 void initOutputs();
336 void createSubscription(int nchannel);
337
338 xmlNode* confnode = { 0 };
339 timeout_t polltime = { 100 };
340 timeout_t updatetime = { 100 };
342 typedef std::vector< std::shared_ptr<OPCAttribute> > IOList;
343 IOList iolist;
344 size_t maxItem = { 0 };
345 size_t maxReadItems = { 0 };
346 size_t maxWriteItems = { 0 };
347
348 struct Channel
349 {
350 size_t num;
351 size_t idx;
352 std::shared_ptr<OPCUAClient> client;
353 uniset::Trigger trStatus;
354 uniset::PassiveTimer ptTimeout;
355 std::atomic_bool status = { false };
356 std::string addr;
357 std::string user;
358 std::string pass;
359 std::unordered_map<Tick, std::shared_ptr<ReadGroup>> readValues;
360 std::unordered_map<Tick, std::shared_ptr<WriteGroup>> writeValues;
362 IOController::IOStateList::iterator respond_it;
363 };
364 Channel channels[numChannels];
365 uniset::Trigger noConnections;
366 std::atomic_uint32_t currentChannel = { 0 };
367
368 uniset::timeout_t reconnectPause = { 10000 };
369 int filtersize = { 0 };
370 float filterT = { 0.0 };
371
372 std::string s_field;
373 std::string s_fvalue;
374 std::optional<std::regex> s_fvalue_re;
375
376 std::shared_ptr<SMInterface> shm;
377 std::string prop_prefix;
378 const std::string argprefix;
379
380 PassiveTimer ptHeartBeat;
381 uniset::ObjectId sidHeartBeat;
382 int maxHeartBeat = { 10 };
383 IOController::IOStateList::iterator itHeartBeat;
384
385 bool force = { false };
386 bool force_out = { false };
387 bool writeToAllChannels = { false };
388 timeout_t smReadyTimeout = { 15000 };
389 bool enableSubscription = {false};
390 double publishingInterval = { 0.0 };
391 double samplingInterval = { -1.0 };
392 uint16_t timeoutIterate = {100};
393 uint16_t stopOnError = {0U};
394 uint32_t connectCount = {0U};
395 std::atomic_bool subscription_ok = {false};
396
397 std::atomic_bool activated = { false };
398 std::atomic_bool cancelled = { false };
399 std::atomic_bool readconf_ok = { false };
400
401 int activateTimeout;
402 uniset::ObjectId sidTestSMReady = { uniset::DefaultObjectId };
404 IOController::IOStateList::iterator itRespond;
405
406 std::shared_ptr<LogAgregator> loga;
407 std::shared_ptr<DebugStream> opclog;
408 std::shared_ptr<LogServer> logserv;
409 std::string logserv_host = {""};
410 int logserv_port = {0};
411
412 std::shared_ptr< ThreadCreator<OPCUAExchange> > thrChannel[numChannels];
413
415 IOController::IOStateList::iterator itExchangeMode;
416 long exchangeMode = { emNone };
418 VMonitor vmon;
419
420 private:
421 };
422 // --------------------------------------------------------------------------
423} // end of namespace uniset
424// -----------------------------------------------------------------------------
425#endif // OPCUAExchange_H_
426// -----------------------------------------------------------------------------
Definition OPCUAExchange.h:181
timeout_t smReadyTimeout
Definition OPCUAExchange.h:388
bool writeToAllChannels
Definition OPCUAExchange.h:387
uniset::ObjectId sidExchangeMode
Definition OPCUAExchange.h:414
bool force
Definition OPCUAExchange.h:385
timeout_t updatetime
Definition OPCUAExchange.h:340
virtual bool activateObject() override
Активизация объекта (переопределяется для необходимых действий после активизации)
Definition OPCUAExchange.cc:1371
bool force_out
Definition OPCUAExchange.h:386
uint16_t stopOnError
Definition OPCUAExchange.h:393
xmlNode * confnode
Definition OPCUAExchange.h:338
virtual bool deactivateObject() override
Деактивация объекта (переопределяется для необходимых действий при завершении работы)
Definition OPCUAExchange.cc:1385
IOList iolist
Definition OPCUAExchange.h:343
uint32_t connectCount
Definition OPCUAExchange.h:394
timeout_t polltime
Definition OPCUAExchange.h:339
StopMode
Definition OPCUAExchange.h:291
@ smFirstOnly
Definition OPCUAExchange.h:293
@ smAny
Definition OPCUAExchange.h:294
@ smNone
Definition OPCUAExchange.h:292
ExchangeMode
Definition OPCUAExchange.h:280
@ emSkipExchange
Definition OPCUAExchange.h:285
@ emNone
Definition OPCUAExchange.h:281
@ emWriteOnly
Definition OPCUAExchange.h:282
@ emSkipSaveToSM
Definition OPCUAExchange.h:284
@ emReadOnly
Definition OPCUAExchange.h:283
long exchangeMode
Definition OPCUAExchange.h:416
Пассивный таймер
Definition PassiveTimer.h:94
Definition MessageType.h:127
Definition MessageType.h:171
Definition MessageType.h:214
Definition Trigger.h:31
Definition UniSetObject.h:80
Definition VMonitor.h:117
Definition Mutex.h:32
Definition Calibration.h:27
const ObjectId DefaultObjectId
Definition UniSetTypes.h:71
long ObjectId
Definition UniSetTypes_i.idl:30
Definition IOBase.h:35
Definition OPCUAExchange.h:349
Definition OPCUAExchange.h:244
Definition OPCUAExchange.h:261
Definition OPCUAExchange.h:220
Definition OPCUAExchange.h:209
Definition OPCUAExchange.h:214
Definition UniSetTypes_i.idl:65