UniSet 2.32.1
extensions/ModbusSlave/MBSlave.h
1/*
2 * Copyright (c) 2015 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 _MBSlave_H_
18#define _MBSlave_H_
19// -----------------------------------------------------------------------------
20#include <ostream>
21#include <string>
22#include <memory>
23#include <map>
24#include <unordered_map>
25#include <vector>
26#include <condition_variable>
27#include <atomic>
28#include <mutex>
29#include "UniSetObject.h"
30#include "modbus/ModbusTypes.h"
31#include "modbus/ModbusServerSlot.h"
32#include "modbus/ModbusTCPServer.h"
33#include "modbus/ModbusTCPServerSlot.h"
34#include "PassiveTimer.h"
35#include "Trigger.h"
36#include "Mutex.h"
37#include "SMInterface.h"
38#include "SharedMemory.h"
39#include "IOBase.h"
40#include "VTypes.h"
41#include "ThreadCreator.h"
42#include "LogServer.h"
43#include "LogAgregator.h"
44#include "VMonitor.h"
45// -----------------------------------------------------------------------------
46#ifndef vmonit
47#define vmonit( var ) vmon.add( #var, var )
48#endif
49// -------------------------------------------------------------------------
50namespace uniset
51{
52 // -----------------------------------------------------------------------------
313 // -----------------------------------------------------------------------------
315 class MBSlave:
316 public UniSetObject
317 {
318 public:
319 MBSlave( uniset::ObjectId objId, uniset::ObjectId shmID, const std::shared_ptr<SharedMemory>& ic = nullptr, const std::string& prefix = "mbs" );
320 virtual ~MBSlave();
321
323 static std::shared_ptr<MBSlave> init_mbslave(int argc, const char* const* argv,
324 uniset::ObjectId shmID, const std::shared_ptr<SharedMemory>& ic = nullptr,
325 const std::string& prefix = "mbs" );
326
327 static void help_print( int argc, const char* const* argv );
328
329 static const int NoSafetyState = -1;
330
331 enum AccessMode
332 {
333 amRW,
334 amRO,
335 amWO
336 };
337
338 std::string amode2str( AccessMode m );
339
340 struct BitRegProperty;
341
343 public IOBase
344 {
345 ModbusRTU::ModbusData mbreg;
346 AccessMode amode;
347 VTypes::VType vtype;
348 size_t wnum;
349 size_t nbyte;
350 std::shared_ptr<BitRegProperty> bitreg;
351 ModbusRTU::RegID regID;
352
353 IOProperty():
354 mbreg(0),
355 amode(amRW),
356 vtype(VTypes::vtUnknown),
357 wnum(0),
358 nbyte(0),
359 regID(0)
360 {}
361
362 friend std::ostream& operator<<( std::ostream& os, IOProperty& p );
363 };
364
365
367 {
368 typedef std::vector<IOProperty> BitSensorMap;
369
370 ModbusRTU::ModbusData mbreg;
371 BitSensorMap bvec;
372
373 BitRegProperty(): mbreg(0), bvec(ModbusRTU::BitsPerData) {}
374
376 bool check( const IOController_i::SensorInfo& si );
377
378 friend std::ostream& operator<<( std::ostream& os, BitRegProperty& p );
379 friend std::ostream& operator<<( std::ostream& os, BitRegProperty* p );
380 };
381
382 inline long getConnCount()
383 {
384 return connCount;
385 }
386
387 inline std::shared_ptr<LogAgregator> getLogAggregator()
388 {
389 return loga;
390 }
391 inline std::shared_ptr<DebugStream> log()
392 {
393 return mblog;
394 }
395
396 virtual uniset::SimpleInfo* getInfo( const char* userparam = 0 ) override;
397
398#ifndef DISABLE_REST_API
399 // http API
400 virtual Poco::JSON::Object::Ptr httpHelp( const Poco::URI::QueryParameters& p ) override;
401 virtual Poco::JSON::Object::Ptr httpRequest( const std::string& req, const Poco::URI::QueryParameters& p ) override;
402#endif
403
404 protected:
405
407 ModbusRTU::mbErrCode readCoilStatus( ModbusRTU::ReadCoilMessage& query,
408 ModbusRTU::ReadCoilRetMessage& reply );
410 ModbusRTU::mbErrCode readInputStatus( ModbusRTU::ReadInputStatusMessage& query,
411 ModbusRTU::ReadInputStatusRetMessage& reply );
412
414 ModbusRTU::mbErrCode readOutputRegisters( ModbusRTU::ReadOutputMessage& query,
415 ModbusRTU::ReadOutputRetMessage& reply );
416
418 ModbusRTU::mbErrCode readInputRegisters( ModbusRTU::ReadInputMessage& query,
419 ModbusRTU::ReadInputRetMessage& reply );
420
422 ModbusRTU::mbErrCode forceSingleCoil( ModbusRTU::ForceSingleCoilMessage& query,
423 ModbusRTU::ForceSingleCoilRetMessage& reply );
424
426 ModbusRTU::mbErrCode forceMultipleCoils( ModbusRTU::ForceCoilsMessage& query,
427 ModbusRTU::ForceCoilsRetMessage& reply );
428
429
431 ModbusRTU::mbErrCode writeOutputRegisters( ModbusRTU::WriteOutputMessage& query,
432 ModbusRTU::WriteOutputRetMessage& reply );
433
435 ModbusRTU::mbErrCode writeOutputSingleRegister( ModbusRTU::WriteSingleOutputMessage& query,
436 ModbusRTU::WriteSingleOutputRetMessage& reply );
437
439 // ModbusRTU::mbErrCode journalCommand( ModbusRTU::JournalCommandMessage& query,
440 // ModbusRTU::JournalCommandRetMessage& reply );
441
443 ModbusRTU::mbErrCode setDateTime( ModbusRTU::SetDateTimeMessage& query,
444 ModbusRTU::SetDateTimeRetMessage& reply );
445
447 ModbusRTU::mbErrCode remoteService( ModbusRTU::RemoteServiceMessage& query,
448 ModbusRTU::RemoteServiceRetMessage& reply );
449
450 ModbusRTU::mbErrCode fileTransfer( ModbusRTU::FileTransferMessage& query,
451 ModbusRTU::FileTransferRetMessage& reply );
452
453 ModbusRTU::mbErrCode diagnostics( ModbusRTU::DiagnosticMessage& query,
454 ModbusRTU::DiagnosticRetMessage& reply );
455
456 ModbusRTU::mbErrCode read4314( ModbusRTU::MEIMessageRDI& query,
457 ModbusRTU::MEIMessageRetRDI& reply );
458
459 // т.к. в функциях (much_real_read,nuch_real_write) расчёт на отсортированность IOMap
460 // то использовать unordered_map нельзя
461 typedef std::map<ModbusRTU::RegID, IOProperty> RegMap;
462
463 typedef std::unordered_map<ModbusRTU::ModbusAddr, RegMap> IOMap;
464
465 IOMap iomap;
467 // т.к. пороговые датчики не связаны напрямую с обменом, создаём для них отдельный список
468 // и отдельно его проверяем потом
469 typedef std::list<IOBase> ThresholdList;
470 ThresholdList thrlist;
471
472 std::shared_ptr<ModbusServerSlot> mbslot;
473 std::unordered_set<ModbusRTU::ModbusAddr> vaddr;
474 std::string default_mbaddr = { "" };
475
476 xmlNode* cnode = { 0 };
477 std::string s_field = { "" };
478 std::string s_fvalue = { "" };
479 int default_mbfunc = {0}; // функция по умолчанию, для вычисления RegID
480
481 std::shared_ptr<SMInterface> shm;
482
483 virtual void sysCommand( const uniset::SystemMessage* msg ) override;
484 virtual void sensorInfo( const uniset::SensorMessage* sm ) override;
485 virtual void timerInfo( const uniset::TimerMessage* tm ) override;
486 void askSensors( UniversalIO::UIOCommand cmd );
487 bool waitSMReady();
488 virtual void execute_rtu();
489 virtual void execute_tcp();
490 virtual void updateStatistics();
491 virtual void updateTCPStatistics();
492 virtual void updateThresholds();
493 virtual void postReceiveEvent( ModbusRTU::mbErrCode res );
494 void runTCPServer();
495
496 virtual bool activateObject() override;
497 virtual bool deactivateObject() override;
498
499 // действия при завершении работы
500 virtual void finalThread();
501
502 enum Timer
503 {
504 tmCheckExchange
505 };
506
507 uniset::timeout_t checkExchangeTime = { 10000 }; // контроль "живости" потока обмена, мсек
508
509 virtual void initIterators();
510 bool initItem( UniXML::iterator& it );
511 bool readItem( const std::shared_ptr<UniXML>& xml, UniXML::iterator& it, xmlNode* sec );
512
513 void readConfiguration();
514 bool check_item( UniXML::iterator& it );
515
516 ModbusRTU::mbErrCode real_write( RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData val, const int fn = 0 );
517 ModbusRTU::mbErrCode real_write( RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData* dat, size_t& i, size_t count, const int fn = 0 );
518 ModbusRTU::mbErrCode real_read( RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData& val, const int fn = 0 );
519 ModbusRTU::mbErrCode much_real_read( RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData* dat, size_t count, const int fn = 0 );
520 ModbusRTU::mbErrCode much_real_write(RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData* dat, size_t count, const int fn = 0 );
521
522 ModbusRTU::mbErrCode real_read_it( RegMap& rmap, RegMap::iterator& it, ModbusRTU::ModbusData& val );
523 ModbusRTU::mbErrCode real_bitreg_read_it( std::shared_ptr<BitRegProperty>& bp, ModbusRTU::ModbusData& val );
524 ModbusRTU::mbErrCode real_read_prop( IOProperty* p, ModbusRTU::ModbusData& val );
525
526 ModbusRTU::mbErrCode real_write_it(RegMap& rmap, RegMap::iterator& it, ModbusRTU::ModbusData* dat, size_t& i, size_t count );
527 ModbusRTU::mbErrCode real_bitreg_write_it( std::shared_ptr<BitRegProperty>& bp, const ModbusRTU::ModbusData val );
528 ModbusRTU::mbErrCode real_write_prop(IOProperty* p, ModbusRTU::ModbusData* dat, size_t& i, size_t count );
529
530#ifndef DISABLE_REST_API
531 // http api
532 Poco::JSON::Object::Ptr request_regs( const std::string& req, const Poco::URI::QueryParameters& p );
533 Poco::JSON::Object::Ptr get_regs(ModbusRTU::ModbusAddr addr, const RegMap& rmap, const std::vector<std::string>& q_regs );
534 Poco::JSON::Object::Ptr get_reginfo( const IOProperty& prop );
535#endif
536 MBSlave();
537 timeout_t initPause = { 3000 };
538 uniset::uniset_rwmutex mutex_start;
539 std::unique_ptr< ThreadCreator<MBSlave> > thr;
540
541 std::mutex mutexStartNotify;
542 std::condition_variable startNotifyEvent;
543
544 PassiveTimer ptHeartBeat;
545 uniset::ObjectId sidHeartBeat = { uniset::DefaultObjectId };
546 long maxHeartBeat = { 10 };
547 IOController::IOStateList::iterator itHeartBeat;
548 uniset::ObjectId sidTestSMReady = {uniset::DefaultObjectId };
549
550 IOController::IOStateList::iterator itAskCount;
552
553 IOController::IOStateList::iterator itRespond;
555 bool respond_invert = { false };
556
557 PassiveTimer ptTimeout;
558 long connCount = { 0 };
559 long restartTCPServerCount = { 0 };
560
561 std::atomic_bool activated = { false };
562 std::atomic_bool canceled = {false };
563 timeout_t activateTimeout = { 20000 }; // msec
564 bool smPingOK = { false };
565 timeout_t wait_msec = { 3000 };
566 bool force = { false };
568 bool mbregFromID = {0};
569 bool checkMBFunc = {0};
570 bool noMBFuncOptimize = {0}; // флаг отключающий принудительное преобразование функций (0x06->0x10, 0x05->0x0F) см. initItem()
571
572 int getOptimizeWriteFunction( const int fn ); // функция возвращает оптимизированную функцию (если оптимизация включена)
573
574 typedef std::unordered_map<int, std::string> FileList;
575 FileList flist;
576 std::string prefix = { "" };
577 std::string prop_prefix = { "" };
578
579 ModbusRTU::ModbusData buf[ModbusRTU::MAXLENPACKET / 2 + 1];
581 // данные для ответа на запрос 0x2B(43)/0x0E(14)
582 // 'MEI' - modbus encapsulated interface
583 // 'RDI' - read device identification
584 typedef std::unordered_map<int, std::string> MEIValMap;
585 typedef std::unordered_map<int, MEIValMap> MEIObjIDMap;
586 typedef std::unordered_map<int, MEIObjIDMap> MEIDevIDMap;
587
588 MEIDevIDMap meidev;
589
590 std::shared_ptr<LogAgregator> loga;
591 std::shared_ptr<DebugStream> mblog;
592 std::shared_ptr<LogServer> logserv;
593 std::string logserv_host = {""};
594 int logserv_port = {0};
595 VMonitor vmon;
596 std::string mbtype = { "" };
597
598 // ----------------------------------------------------------------------------
599 // TCPServer section..
600 void initTCPClients( UniXML::iterator confnode );
601
602 timeout_t sockTimeout = { 30000 };
603 timeout_t sessTimeout = { 2000 };
604 timeout_t updateStatTime = { 4000 };
605 ModbusTCPServer::Sessions sess;
606 std::mutex sessMutex;
607 size_t sessMaxNum = { 5 };
608 std::shared_ptr<ModbusTCPServerSlot> tcpserver;
609
611 {
612 ClientInfo(): iaddr(""), respond_s(uniset::DefaultObjectId), invert(false),
613 askCount(0), askcount_s(uniset::DefaultObjectId)
614 {
615 ptTimeout.setTiming(0);
616 }
617
618 std::string iaddr = { "" };
619
621 IOController::IOStateList::iterator respond_it;
622 bool invert = { false };
623 PassiveTimer ptTimeout;
624 timeout_t tout = { 2000 };
625
626 long askCount = { 0 };
628 IOController::IOStateList::iterator askcount_it;
629
630 inline void initIterators( const std::shared_ptr<SMInterface>& shm )
631 {
632 shm->initIterator( respond_it );
633 shm->initIterator( askcount_it );
634 }
635
636 const std::string getShortInfo() const;
637 };
638
639 typedef std::unordered_map<std::string, ClientInfo> ClientsMap;
640 ClientsMap cmap;
641
642 uniset::ObjectId sesscount_id = { uniset::DefaultObjectId };
643 IOController::IOStateList::iterator sesscount_it;
644
645 std::atomic_bool tcpCancelled = { true };
646
647 bool tcpBreakIfFailRun = { false };
648 timeout_t tcpRepeatCreateSocketPause = { 30000 };
649 };
650 // --------------------------------------------------------------------------
651} // end of namespace uniset
652// -----------------------------------------------------------------------------
653#endif // _MBSlave_H_
654// -----------------------------------------------------------------------------
Definition Utilities/MBTester/MBSlave.h:14
Definition extensions/ModbusSlave/MBSlave.h:317
ModbusRTU::mbErrCode readInputRegisters(ModbusRTU::ReadInputMessage &query, ModbusRTU::ReadInputRetMessage &reply)
Definition extensions/ModbusSlave/mbslave.cc:2493
virtual bool activateObject() override
Активизация объекта (переопределяется для необходимых действий после активизации)
Definition extensions/ModbusSlave/mbslave.cc:1159
IOMap iomap
Definition extensions/ModbusSlave/MBSlave.h:465
ModbusRTU::mbErrCode writeOutputSingleRegister(ModbusRTU::WriteSingleOutputMessage &query, ModbusRTU::WriteSingleOutputRetMessage &reply)
Definition extensions/ModbusSlave/mbslave.cc:1766
ModbusRTU::ModbusData buf[ModbusRTU::MAXLENPACKET/2+1]
Definition extensions/ModbusSlave/MBSlave.h:579
ModbusRTU::mbErrCode writeOutputRegisters(ModbusRTU::WriteOutputMessage &query, ModbusRTU::WriteOutputRetMessage &reply)
Definition extensions/ModbusSlave/mbslave.cc:1743
ModbusRTU::mbErrCode readOutputRegisters(ModbusRTU::ReadOutputMessage &query, ModbusRTU::ReadOutputRetMessage &reply)
Definition extensions/ModbusSlave/mbslave.cc:1698
ModbusRTU::mbErrCode readInputStatus(ModbusRTU::ReadInputStatusMessage &query, ModbusRTU::ReadInputStatusRetMessage &reply)
Definition extensions/ModbusSlave/mbslave.cc:2642
ModbusTCPServer::Sessions sess
Definition extensions/ModbusSlave/MBSlave.h:605
ModbusRTU::mbErrCode readCoilStatus(ModbusRTU::ReadCoilMessage &query, ModbusRTU::ReadCoilRetMessage &reply)
Definition extensions/ModbusSlave/mbslave.cc:2563
timeout_t sessTimeout
Definition extensions/ModbusSlave/MBSlave.h:603
ModbusRTU::mbErrCode setDateTime(ModbusRTU::SetDateTimeMessage &query, ModbusRTU::SetDateTimeRetMessage &reply)
Definition extensions/ModbusSlave/mbslave.cc:2536
ModbusRTU::mbErrCode remoteService(ModbusRTU::RemoteServiceMessage &query, ModbusRTU::RemoteServiceRetMessage &reply)
Definition extensions/ModbusSlave/mbslave.cc:2542
virtual bool deactivateObject() override
Деактивация объекта (переопределяется для необходимых действий при завершении работы)
Definition extensions/ModbusSlave/mbslave.cc:1176
std::unordered_set< ModbusRTU::ModbusAddr > vaddr
Definition extensions/ModbusSlave/MBSlave.h:473
static std::shared_ptr< MBSlave > init_mbslave(int argc, const char *const *argv, uniset::ObjectId shmID, const std::shared_ptr< SharedMemory > &ic=nullptr, const std::string &prefix="mbs")
Definition extensions/ModbusSlave/mbslave.cc:1635
bool force
Definition extensions/ModbusSlave/MBSlave.h:566
timeout_t sockTimeout
Definition extensions/ModbusSlave/MBSlave.h:602
ModbusRTU::mbErrCode forceMultipleCoils(ModbusRTU::ForceCoilsMessage &query, ModbusRTU::ForceCoilsRetMessage &reply)
Definition extensions/ModbusSlave/mbslave.cc:2721
ModbusRTU::mbErrCode forceSingleCoil(ModbusRTU::ForceSingleCoilMessage &query, ModbusRTU::ForceSingleCoilRetMessage &reply)
Definition extensions/ModbusSlave/mbslave.cc:2758
Пассивный таймер
Definition PassiveTimer.h:94
Definition MessageType.h:127
Definition MessageType.h:171
Definition MessageType.h:214
Definition UniSetObject.h:80
Definition Mutex.h:32
Definition Calibration.h:27
const ObjectId DefaultObjectId
Definition UniSetTypes.h:71
long ObjectId
Definition UniSetTypes_i.idl:30
Definition IOController_i.idl:58
Definition IOBase.h:35
Definition extensions/ModbusSlave/MBSlave.h:367
ModbusRTU::ModbusData mbreg
Definition extensions/ModbusSlave/MBSlave.h:370
bool check(const IOController_i::SensorInfo &si)
Definition extensions/ModbusSlave/mbslave.cc:1509
Definition extensions/ModbusSlave/MBSlave.h:611
Definition extensions/ModbusSlave/MBSlave.h:344
size_t wnum
Definition extensions/ModbusSlave/MBSlave.h:348
ModbusRTU::ModbusData mbreg
Definition extensions/ModbusSlave/MBSlave.h:345
std::shared_ptr< BitRegProperty > bitreg
Definition extensions/ModbusSlave/MBSlave.h:350
VTypes::VType vtype
Definition extensions/ModbusSlave/MBSlave.h:347
size_t nbyte
Definition extensions/ModbusSlave/MBSlave.h:349
Definition UniSetTypes_i.idl:65