191 const std::string& _prefix =
"opcua" );
194 static std::shared_ptr<OPCUAExchange> init_opcuaexchange(
int argc,
const char*
const* argv,
196 const std::string& prefix =
"opcua");
198 static void help_print(
int argc,
const char*
const* argv );
202 static uint8_t firstBit( uint32_t mask );
205 static uint32_t getBits( uint32_t value, uint32_t mask, uint8_t offset );
207 static uint32_t setBits( uint32_t value, uint32_t set, uint32_t mask, uint8_t offset );
209 static uint32_t forceSetBits( uint32_t value, uint32_t set, uint32_t mask, uint8_t offset );
211 using Tick = uint8_t;
213 static const size_t numChannels = 2;
216 std::vector<std::vector<OPCUAClient::ResultVar>> results;
217 std::vector<std::vector<opcua::ua::ReadValueId>> ids;
221 std::vector<std::vector<opcua::ua::WriteValue>> ids;
238 uint32_t mask = { 0 };
239 uint8_t offset = { 0 };
240 OPCUAClient::VarType vtype = { OPCUAClient::VarType::Int32 };
246 int32_t set(
float val );
248 std::string attrName = {
""};
251 std::shared_ptr<ReadGroup> gr;
252 size_t grIndex = {0};
253 size_t grNumber = {0};
256 opcua::StatusCode status();
257 const opcua::ua::ReadValueId& ref();
259 uint32_t subscriptionId = {0U};
260 uint32_t monitoredItemId = {0U};
261 bool subscriptionState = {
false};
267 std::shared_ptr<WriteGroup> gr;
268 size_t grIndex = {0};
269 size_t grNumber = {0};
270 bool set( int32_t val );
271 bool setF(
float val );
272 opcua::StatusCode status();
273 const opcua::ua::WriteValue& ref();
274 static opcua::Variant initValue(
const std::string&
stype, int32_t defvalue );
278 friend std::ostream& operator<<(std::ostream& os,
const OPCAttribute& inf );
279 friend std::ostream& operator<<(std::ostream& os,
const std::shared_ptr<OPCAttribute>& inf );
305 std::chrono::system_clock::time_point time;
306 std::chrono::system_clock::time_point lastSeen;
307 size_t channel { 0 };
308 std::string operation;
309 UA_StatusCode statusCode { UA_STATUSCODE_GOOD };
314 typedef std::list<IOBase> ThresholdList;
317 ThresholdList thrlist;
319#ifndef DISABLE_REST_API
321 virtual Poco::JSON::Object::Ptr httpHelp(
const Poco::URI::QueryParameters& p )
override;
323 virtual Poco::JSON::Object::Ptr httpGetMyInfo( Poco::JSON::Object::Ptr root )
override;
334 void channel1Thread();
335 void channel2Thread();
336 void channelThread( Channel* ch );
338 void channelExchange( Tick tick, Channel* ch,
bool writeOn );
339 void updateFromChannel( Channel* ch );
340 void updateToChannel( Channel* ch );
343 bool isUpdateSM(
bool wrFunc )
const noexcept;
346 virtual void askSensors( UniversalIO::UIOCommand cmd );
352#ifndef DISABLE_REST_API
354 Poco::JSON::Object::Ptr httpGetParam(
const Poco::URI::QueryParameters& p );
355 Poco::JSON::Object::Ptr httpSetParam( Poco::Net::HTTPServerResponse& resp,
const Poco::URI::QueryParameters& p );
356 Poco::JSON::Object::Ptr httpStatus();
357 Poco::JSON::Object::Ptr buildLogServerInfo();
360 Poco::JSON::Object::Ptr httpGet(
const Poco::URI::QueryParameters& p );
361 Poco::JSON::Object::Ptr httpSensors(
const Poco::URI::QueryParameters& p );
362 Poco::JSON::Object::Ptr httpSensor( Poco::Net::HTTPServerResponse& resp,
const Poco::URI::QueryParameters& p );
363 Poco::JSON::Object::Ptr httpDiagnostics(
const Poco::URI::QueryParameters& p );
364 Poco::JSON::Object::Ptr httpTakeControl( Poco::Net::HTTPServerResponse& resp,
const Poco::URI::QueryParameters& p );
365 Poco::JSON::Object::Ptr httpReleaseControl( Poco::Net::HTTPServerResponse& resp,
const Poco::URI::QueryParameters& p );
368 std::string formatTime(
const std::chrono::system_clock::time_point& tp )
const;
369 Poco::JSON::Object::Ptr sensorToJson(
const std::shared_ptr<OPCAttribute>& attr,
bool detailed =
false,
const std::string& cachedName =
"" )
const;
372 bool httpEnabledSetParams {
true };
376 void addError(
size_t channel,
const std::string& operation, UA_StatusCode status,
const std::string& nodeid =
"" );
383 void readConfiguration();
385 bool readItem(
const std::shared_ptr<UniXML>& xml,
UniXML::iterator& it, xmlNode* sec );
387 bool tryConnect(Channel* ch);
394 typedef std::vector< std::shared_ptr<OPCAttribute> > IOList;
396 size_t maxItem = { 0 };
397 size_t maxReadItems = { 0 };
398 size_t maxWriteItems = { 0 };
404 std::shared_ptr<OPCUAClient> client;
407 std::atomic_bool status = {
false };
411 std::unordered_map<Tick, std::shared_ptr<ReadGroup>> readValues;
412 std::unordered_map<Tick, std::shared_ptr<WriteGroup>> writeValues;
414 IOController::IOStateList::iterator respond_it;
415 std::atomic_bool needSubscription = {
false };
419 std::atomic_uint32_t currentChannel = { 0 };
421 uniset::timeout_t reconnectPause = { 10000 };
422 int filtersize = { 0 };
423 float filterT = { 0.0 };
426 std::string s_fvalue;
427 std::optional<std::regex> s_fvalue_re;
429 std::shared_ptr<SMInterface> shm;
430 std::string prop_prefix;
431 const std::string argprefix;
433 PassiveTimer ptHeartBeat;
435 int maxHeartBeat = { 10 };
436 IOController::IOStateList::iterator itHeartBeat;
442 bool enableSubscription = {
false};
443 double publishingInterval = { 0.0 };
444 double samplingInterval = { -1.0 };
445 uint16_t timeoutIterate = {100};
448 std::atomic_bool subscription_ok = {
false};
449 std::atomic_bool newSessionActivated = {
false};
451 std::atomic_bool activated = {
false };
452 std::atomic_bool cancelled = {
false };
453 std::atomic_bool readconf_ok = {
false };
458 IOController::IOStateList::iterator itRespond;
460 std::shared_ptr<LogAgregator> loga;
461 std::shared_ptr<DebugStream> opclog;
462 std::shared_ptr<LogServer> logserv;
463 std::string logserv_host = {
""};
464 int logserv_port = {0};
466 std::shared_ptr< ThreadCreator<OPCUAExchange> > thrChannel[numChannels];
469 IOController::IOStateList::iterator itExchangeMode;
478 std::string operation;
479 UA_StatusCode statusCode;
482 bool operator==(
const ErrorKey& other )
const noexcept
484 return channel == other.channel &&
485 statusCode == other.statusCode &&
486 operation == other.operation &&
487 nodeid == other.nodeid;
493 size_t operator()(
const ErrorKey& k )
const noexcept
495 size_t h1 = std::hash<size_t> {}(k.channel);
496 size_t h2 = std::hash<UA_StatusCode> {}(k.statusCode);
497 size_t h3 = std::hash<std::string> {}(k.operation);
498 size_t h4 = std::hash<std::string> {}(k.nodeid);
499 return ((h1 ^ (h2 << 1)) ^ (h3 << 2)) ^ (h4 << 3);
504 mutable std::list<ErrorRecord> errorHistory;
505 mutable std::unordered_map<ErrorKey, std::list<ErrorRecord>::iterator,
ErrorKeyHash> errorHistoryIndex;
507 mutable std::mutex errorHistoryMutex;
510 std::atomic<uint64_t> totalReadErrors { 0 };
511 std::atomic<uint64_t> totalWriteErrors { 0 };
512 std::atomic<uint64_t> totalConnectionLosses { 0 };
515 std::chrono::steady_clock::time_point startTime;
518 void doCreateSubscription(
int nchannel);