UniSet  2.2.1
extensions/ModbusSlave/MBSlave.h
00001 // -----------------------------------------------------------------------------
00002 #ifndef _MBSlave_H_
00003 #define _MBSlave_H_
00004 // -----------------------------------------------------------------------------
00005 #include <ostream>
00006 #include <string>
00007 #include <memory>
00008 #include <map>
00009 #include <unordered_map>
00010 #include <vector>
00011 #include <condition_variable>
00012 #include <atomic>
00013 #include <mutex>
00014 #include "UniSetObject.h"
00015 #include "modbus/ModbusTypes.h"
00016 #include "modbus/ModbusServerSlot.h"
00017 #include "PassiveTimer.h"
00018 #include "Trigger.h"
00019 #include "Mutex.h"
00020 #include "SMInterface.h"
00021 #include "SharedMemory.h"
00022 #include "IOBase.h"
00023 #include "VTypes.h"
00024 #include "ThreadCreator.h"
00025 #include "LogServer.h"
00026 #include "LogAgregator.h"
00027 #include "VMonitor.h"
00028 // -----------------------------------------------------------------------------
00029 #ifndef vmonit
00030 #define vmonit( var ) vmon.add( #var, var )
00031 #endif
00032 // -----------------------------------------------------------------------------
00276 // -----------------------------------------------------------------------------
00277 namespace std
00278 {
00279     template<>
00280     class hash<ModbusRTU::mbErrCode>
00281     {
00282         public:
00283             size_t operator()(const ModbusRTU::mbErrCode& e) const
00284             {
00285                 return std::hash<int>()((int)e);
00286             }
00287     };
00288 }
00289 // -----------------------------------------------------------------------------
00291 class MBSlave:
00292     public UniSetObject
00293 {
00294     public:
00295         MBSlave( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, const std::shared_ptr<SharedMemory>& ic = nullptr, const std::string& prefix = "mbs" );
00296         virtual ~MBSlave();
00297 
00299         static std::shared_ptr<MBSlave> init_mbslave(int argc, const char* const* argv,
00300                 UniSetTypes::ObjectId shmID, const std::shared_ptr<SharedMemory>& ic = nullptr,
00301                 const std::string& prefix = "mbs" );
00302 
00304         static void help_print( int argc, const char* const* argv );
00305 
00306         static const int NoSafetyState = -1;
00307 
00308         enum AccessMode
00309         {
00310             amRW,
00311             amRO,
00312             amWO
00313         };
00314 
00315         struct BitRegProperty;
00316 
00317         struct IOProperty:
00318             public IOBase
00319         {
00320             ModbusRTU::ModbusData mbreg;    
00321             AccessMode amode;
00322             VTypes::VType vtype;    
00323             int wnum;               
00324             int nbyte;              
00325             bool rawdata;           
00326             std::shared_ptr<BitRegProperty> bitreg; 
00327             ModbusRTU::RegID regID;
00328 
00329             IOProperty():
00330                 mbreg(0),
00331                 amode(amRW),
00332                 vtype(VTypes::vtUnknown),
00333                 wnum(0),
00334                 nbyte(0),
00335                 rawdata(false),
00336                 regID(0)
00337             {}
00338 
00339             friend std::ostream& operator<<( std::ostream& os, IOProperty& p );
00340         };
00341 
00342 
00343         struct BitRegProperty
00344         {
00345             typedef std::vector<IOProperty> BitSensorMap;
00346 
00347             ModbusRTU::ModbusData mbreg; 
00348             BitSensorMap bvec;
00349 
00350             BitRegProperty(): mbreg(0), bvec(ModbusRTU::BitsPerData) {}
00351 
00353             bool check( const IOController_i::SensorInfo& si );
00354 
00355             friend std::ostream& operator<<( std::ostream& os, BitRegProperty& p );
00356             friend std::ostream& operator<<( std::ostream& os, BitRegProperty* p );
00357         };
00358 
00359         inline long getAskCount()
00360         {
00361             return askCount;
00362         }
00363 
00364         inline std::shared_ptr<LogAgregator> getLogAggregator()
00365         {
00366             return loga;
00367         }
00368         inline std::shared_ptr<DebugStream> log()
00369         {
00370             return mblog;
00371         }
00372 
00373         virtual UniSetTypes::SimpleInfo* getInfo( CORBA::Long userparam = 0 ) override;
00374 
00375     protected:
00376 
00378         ModbusRTU::mbErrCode readCoilStatus( ModbusRTU::ReadCoilMessage& query,
00379                                              ModbusRTU::ReadCoilRetMessage& reply );
00381         ModbusRTU::mbErrCode readInputStatus( ModbusRTU::ReadInputStatusMessage& query,
00382                                               ModbusRTU::ReadInputStatusRetMessage& reply );
00383 
00385         ModbusRTU::mbErrCode readOutputRegisters( ModbusRTU::ReadOutputMessage& query,
00386                 ModbusRTU::ReadOutputRetMessage& reply );
00387 
00389         ModbusRTU::mbErrCode readInputRegisters( ModbusRTU::ReadInputMessage& query,
00390                 ModbusRTU::ReadInputRetMessage& reply );
00391 
00393         ModbusRTU::mbErrCode forceSingleCoil( ModbusRTU::ForceSingleCoilMessage& query,
00394                                               ModbusRTU::ForceSingleCoilRetMessage& reply );
00395 
00397         ModbusRTU::mbErrCode forceMultipleCoils( ModbusRTU::ForceCoilsMessage& query,
00398                 ModbusRTU::ForceCoilsRetMessage& reply );
00399 
00400 
00402         ModbusRTU::mbErrCode writeOutputRegisters( ModbusRTU::WriteOutputMessage& query,
00403                 ModbusRTU::WriteOutputRetMessage& reply );
00404 
00406         ModbusRTU::mbErrCode writeOutputSingleRegister( ModbusRTU::WriteSingleOutputMessage& query,
00407                 ModbusRTU::WriteSingleOutputRetMessage& reply );
00408 
00410         //        ModbusRTU::mbErrCode journalCommand( ModbusRTU::JournalCommandMessage& query,
00411         //                                                            ModbusRTU::JournalCommandRetMessage& reply );
00412 
00414         ModbusRTU::mbErrCode setDateTime( ModbusRTU::SetDateTimeMessage& query,
00415                                           ModbusRTU::SetDateTimeRetMessage& reply );
00416 
00418         ModbusRTU::mbErrCode remoteService( ModbusRTU::RemoteServiceMessage& query,
00419                                             ModbusRTU::RemoteServiceRetMessage& reply );
00420 
00421         ModbusRTU::mbErrCode fileTransfer( ModbusRTU::FileTransferMessage& query,
00422                                            ModbusRTU::FileTransferRetMessage& reply );
00423 
00424         ModbusRTU::mbErrCode diagnostics( ModbusRTU::DiagnosticMessage& query,
00425                                           ModbusRTU::DiagnosticRetMessage& reply );
00426 
00427         ModbusRTU::mbErrCode read4314( ModbusRTU::MEIMessageRDI& query,
00428                                        ModbusRTU::MEIMessageRetRDI& reply );
00429 
00433         virtual ModbusRTU::mbErrCode checkRegister( ModbusRTU::ModbusData reg, ModbusRTU::ModbusData& val )
00434         {
00435             return ModbusRTU::erNoError;
00436         }
00437 
00438         // т.к. в функциях (much_real_read,nuch_real_write) рассчёт на отсортированность IOMap
00439         // то использовать unordered_map нельзя
00440         typedef std::map<ModbusRTU::RegID, IOProperty> RegMap;
00441 
00442         typedef std::unordered_map<ModbusRTU::ModbusAddr, RegMap> IOMap;
00443 
00444         IOMap iomap;  
00446         std::shared_ptr<ModbusServerSlot> mbslot;
00447         std::unordered_set<ModbusRTU::ModbusAddr> vaddr; 
00448         std::string default_mbaddr = { "" };
00449 
00450         xmlNode* cnode = { 0 };
00451         std::string s_field = { "" };
00452         std::string s_fvalue = { "" };
00453         int default_mbfunc = {0}; // функция по умолчанию, для вычисления RegID
00454 
00455         std::shared_ptr<SMInterface> shm;
00456 
00457         virtual void sysCommand( const UniSetTypes::SystemMessage* msg ) override;
00458         virtual void sensorInfo( const UniSetTypes::SensorMessage* sm ) override;
00459         void askSensors( UniversalIO::UIOCommand cmd );
00460         void waitSMReady();
00461         virtual void execute_rtu();
00462         virtual void execute_tcp();
00463 
00464         virtual bool activateObject() override;
00465         virtual bool deactivateObject() override;
00466 
00467         // действия при завершении работы
00468         virtual void sigterm( int signo ) override;
00469         virtual void finalThread();
00470 
00471         virtual void initIterators();
00472         bool initItem( UniXML::iterator& it );
00473         bool readItem( const std::shared_ptr<UniXML>& xml, UniXML::iterator& it, xmlNode* sec );
00474 
00475         void readConfiguration();
00476         bool check_item( UniXML::iterator& it );
00477 
00478         ModbusRTU::mbErrCode real_write( RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData val, const int fn = 0 );
00479         ModbusRTU::mbErrCode real_write( RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData* dat, int& i, int count, const int fn = 0  );
00480         ModbusRTU::mbErrCode real_read( RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData& val, const int fn = 0  );
00481         ModbusRTU::mbErrCode much_real_read( RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData* dat, int count, const int fn = 0  );
00482         ModbusRTU::mbErrCode much_real_write( RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData* dat, int count, const int fn = 0  );
00483 
00484         ModbusRTU::mbErrCode real_read_it( RegMap& rmap, RegMap::iterator& it, ModbusRTU::ModbusData& val );
00485         ModbusRTU::mbErrCode real_bitreg_read_it( std::shared_ptr<BitRegProperty>& bp, ModbusRTU::ModbusData& val );
00486         ModbusRTU::mbErrCode real_read_prop( IOProperty* p, ModbusRTU::ModbusData& val );
00487 
00488         ModbusRTU::mbErrCode real_write_it(RegMap& rmap, RegMap::iterator& it, ModbusRTU::ModbusData* dat, int& i, int count );
00489         ModbusRTU::mbErrCode real_bitreg_write_it( std::shared_ptr<BitRegProperty>& bp, const ModbusRTU::ModbusData val );
00490         ModbusRTU::mbErrCode real_write_prop( IOProperty* p, ModbusRTU::ModbusData* dat, int& i, int count );
00491 
00492         MBSlave();
00493         timeout_t initPause = { 3000 };
00494         UniSetTypes::uniset_rwmutex mutex_start;
00495         std::shared_ptr< ThreadCreator<MBSlave> > thr;
00496 
00497         std::mutex mutexStartNotify;
00498         std::condition_variable startNotifyEvent;
00499 
00500         PassiveTimer ptHeartBeat;
00501         UniSetTypes::ObjectId sidHeartBeat = { UniSetTypes::DefaultObjectId };
00502         int maxHeartBeat = { 10 };
00503         IOController::IOStateList::iterator itHeartBeat;
00504         UniSetTypes::ObjectId test_id = { UniSetTypes::DefaultObjectId };
00505 
00506         IOController::IOStateList::iterator itAskCount;
00507         UniSetTypes::ObjectId askcount_id = { UniSetTypes::DefaultObjectId };
00508 
00509         IOController::IOStateList::iterator itRespond;
00510         UniSetTypes::ObjectId respond_id = { UniSetTypes::DefaultObjectId };
00511         bool respond_invert = { false };
00512 
00513         PassiveTimer ptTimeout;
00514         long askCount = { 0 };
00515         typedef std::unordered_map<ModbusRTU::mbErrCode, unsigned int> ExchangeErrorMap;
00516         ExchangeErrorMap errmap;     
00518         std::atomic_bool activated = { false };
00519         std::atomic_bool cancelled = { false };
00520         int activateTimeout = { 20000 }; // msec
00521         bool pingOK = { false };
00522         timeout_t wait_msec = { 3000 };
00523         bool force = { false };        
00525         bool mbregFromID = {0};
00526         bool checkMBFunc = {0};
00527         bool noMBFuncOptimize = {0}; // флаг отключающий принудительное преобразование функций (0x06->0x10, 0x05->0x0F) см. initItem()
00528 
00529         int getOptimizeWriteFunction( const int fn ); // функция возвращает оптимизированную функцию (если оптимизация включена)
00530 
00531         typedef std::unordered_map<int, std::string> FileList;
00532         FileList flist;
00533         std::string prefix = { "" };
00534         std::string prop_prefix = { "" };
00535 
00536         ModbusRTU::ModbusData buf[ModbusRTU::MAXLENPACKET / 2 + 1]; 
00538         // данные для ответа на запрос 0x2B(43)/0x0E(14)
00539         // 'MEI' - modbus encapsulated interface
00540         // 'RDI' - read device identification
00541         typedef std::unordered_map<int, std::string> MEIValMap;
00542         typedef std::unordered_map<int, MEIValMap> MEIObjIDMap;
00543         typedef std::unordered_map<int, MEIObjIDMap> MEIDevIDMap;
00544 
00545         MEIDevIDMap meidev;
00546 
00547         std::shared_ptr<LogAgregator> loga;
00548         std::shared_ptr<DebugStream> mblog;
00549         std::shared_ptr<LogServer> logserv;
00550         std::string logserv_host = {""};
00551         int logserv_port = {0};
00552         VMonitor vmon;
00553 };
00554 // -----------------------------------------------------------------------------
00555 #endif // _MBSlave_H_
00556 // -----------------------------------------------------------------------------