UniSet  2.2.1
MBExchange.h
00001 #ifndef _MBExchange_H_
00002 #define _MBExchange_H_
00003 // -----------------------------------------------------------------------------
00004 #include <ostream>
00005 #include <string>
00006 #include <map>
00007 #include <unordered_map>
00008 #include <memory>
00009 #include "IONotifyController.h"
00010 #include "UniSetObject.h"
00011 #include "PassiveTimer.h"
00012 #include "DelayTimer.h"
00013 #include "Trigger.h"
00014 #include "Mutex.h"
00015 #include "Calibration.h"
00016 #include "SMInterface.h"
00017 #include "SharedMemory.h"
00018 #include "ThreadCreator.h"
00019 #include "IOBase.h"
00020 #include "VTypes.h"
00021 #include "MTR.h"
00022 #include "RTUStorage.h"
00023 #include "modbus/ModbusClient.h"
00024 #include "LogAgregator.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 // -----------------------------------------------------------------------------
00036 class MBExchange:
00037     public UniSetObject
00038 {
00039     public:
00040         MBExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, const std::shared_ptr<SharedMemory>& ic = nullptr,
00041                     const std::string& prefix = "mb" );
00042         virtual ~MBExchange();
00043 
00045         static void help_print( int argc, const char* const* argv );
00046 
00047         static const int NoSafetyState = -1;
00048 
00050         enum ExchangeMode
00051         {
00052             emNone = 0,       
00053             emWriteOnly = 1,  
00054             emReadOnly = 2,   
00055             emSkipSaveToSM = 3, 
00056             emSkipExchange = 4 
00057         };
00058 
00059         friend std::ostream& operator<<( std::ostream& os, const ExchangeMode& em );
00060 
00061         enum DeviceType
00062         {
00063             dtUnknown,      
00064             dtRTU,          
00065             dtMTR,          
00066             dtRTU188        
00067         };
00068 
00069         static DeviceType getDeviceType( const std::string& dtype );
00070         friend std::ostream& operator<<( std::ostream& os, const DeviceType& dt );
00071 
00072         struct RTUDevice;
00073         struct RegInfo;
00074 
00075         struct RSProperty:
00076             public IOBase
00077         {
00078             // only for RTU
00079             short nbit;             
00080             VTypes::VType vType;    
00081             short rnum;             
00082             short nbyte;            
00084             RSProperty():
00085                 nbit(-1), vType(VTypes::vtUnknown),
00086                 rnum(VTypes::wsize(VTypes::vtUnknown)),
00087                 nbyte(0)
00088             {}
00089 
00090             // т.к. IOBase содержит rwmutex с запрещённым конструктором копирования
00091             // приходится здесь тоже объявлять разрешенными только операции "перемещения"
00092             RSProperty( const RSProperty& r ) = delete;
00093             RSProperty& operator=(const RSProperty& r) = delete;
00094             RSProperty( RSProperty&& r ) = default;
00095             RSProperty& operator=(RSProperty&& r) = default;
00096 
00097             std::shared_ptr<RegInfo> reg;
00098         };
00099 
00100         friend std::ostream& operator<<( std::ostream& os, const RSProperty& p );
00101 
00102         typedef std::list<RSProperty> PList;
00103         static std::ostream& print_plist( std::ostream& os, const PList& p );
00104 
00105         typedef std::map<ModbusRTU::RegID, std::shared_ptr<RegInfo>> RegMap;
00106         struct RegInfo
00107         {
00108             // т.к. RSProperty содержит rwmutex с запрещённым конструктором копирования
00109             // приходится здесь тоже объявлять разрешенными только операции "перемещения"
00110             RegInfo( const RegInfo& r ) = default;
00111             RegInfo& operator=(const RegInfo& r) = delete;
00112             RegInfo( RegInfo&& r ) = delete;
00113             RegInfo& operator=(RegInfo&& r) = default;
00114 
00115             RegInfo():
00116                 mbval(0), mbreg(0), mbfunc(ModbusRTU::fnUnknown),
00117                 id(0), dev(0),
00118                 rtuJack(RTUStorage::nUnknown), rtuChan(0),
00119                 mtrType(MTR::mtUnknown),
00120                 q_num(0), q_count(1), mb_initOK(false), sm_initOK(false)
00121             {}
00122 
00123             ModbusRTU::ModbusData mbval;
00124             ModbusRTU::ModbusData mbreg;            
00125             ModbusRTU::SlaveFunctionCode mbfunc;    
00126             PList slst;
00127             ModbusRTU::RegID id;
00128 
00129             std::shared_ptr<RTUDevice> dev;
00130 
00131             // only for RTU188
00132             RTUStorage::RTUJack rtuJack;
00133             int rtuChan;
00134 
00135             // only for MTR
00136             MTR::MTRType mtrType;    
00138             // optimization
00139             unsigned int q_num;      
00140             unsigned int q_count;    
00142             RegMap::iterator rit;
00143 
00144             // начальная инициалиазция для "записываемых" регистров
00145             // Механизм:
00146             // Если tcp_preinit="1", то сперва будет сделано чтение значения из устройства.
00147             // при этом флаг mb_init=false пока не пройдёт успешной инициализации
00148             // Если tcp_preinit="0", то флаг mb_init сразу выставляется в true.
00149             bool mb_initOK;    
00151             // Флаг sm_init означает, что писать в устройство нельзя, т.к. значение в "карте регистров"
00152             // ещё не инициализировано из SM
00153             bool sm_initOK;    
00154         };
00155 
00156         friend std::ostream& operator<<( std::ostream& os, RegInfo& r );
00157         friend std::ostream& operator<<( std::ostream& os, RegInfo* r );
00158 
00159         struct RTUDevice
00160         {
00161             RTUDevice():
00162                 mbaddr(0),
00163                 dtype(dtUnknown),
00164                 resp_id(UniSetTypes::DefaultObjectId),
00165                 resp_state(false),
00166                 resp_invert(false),
00167                 numreply(0),
00168                 prev_numreply(0),
00169                 ask_every_reg(false),
00170                 mode_id(UniSetTypes::DefaultObjectId),
00171                 mode(emNone),
00172                 speed(ComPort::ComSpeed38400),
00173                 rtu188(0)
00174             {
00175             }
00176 
00177             ModbusRTU::ModbusAddr mbaddr;    
00178             std::unordered_map<unsigned int, std::shared_ptr<RegMap>> pollmap;
00179 
00180             DeviceType dtype;    
00182             // resp - respond..(контроль наличия связи)
00183             UniSetTypes::ObjectId resp_id;
00184             IOController::IOStateList::iterator resp_it;
00185             DelayTimer resp_Delay; // таймер для формирования задержки на отпускание (пропадание связи)
00186             PassiveTimer resp_ptInit; // таймер для формирования задержки на инициализацию связи (задержка на выставление датчика связи после запуска)
00187             bool resp_state;
00188             bool resp_invert;
00189             bool resp_force = { false };
00190             std::atomic<unsigned int> numreply; // количество успешных запросов..
00191             std::atomic<unsigned int> prev_numreply;
00192 
00193             //
00194             bool ask_every_reg; 
00196             // режим работы
00197             UniSetTypes::ObjectId mode_id;
00198             IOController::IOStateList::iterator mode_it;
00199             long mode; // режим работы с устройством (см. ExchangeMode)
00200 
00201             // return TRUE if state changed
00202             bool checkRespond( std::shared_ptr<DebugStream>& log );
00203 
00204             // специфические поля для RS
00205             ComPort::Speed speed;
00206             std::shared_ptr<RTUStorage> rtu188;
00207 
00208             std::string getShortInfo() const;
00209         };
00210 
00211         friend std::ostream& operator<<( std::ostream& os, RTUDevice& d );
00212 
00213         typedef std::unordered_map<ModbusRTU::ModbusAddr, std::shared_ptr<RTUDevice>> RTUDeviceMap;
00214 
00215         friend std::ostream& operator<<( std::ostream& os, RTUDeviceMap& d );
00216         void printMap(RTUDeviceMap& d);
00217 
00218         // ----------------------------------
00219         enum Timer
00220         {
00221             tmExchange
00222         };
00223 
00224         void execute();
00225 
00226         inline std::shared_ptr<LogAgregator> getLogAggregator()
00227         {
00228             return loga;
00229         }
00230         inline std::shared_ptr<DebugStream> log()
00231         {
00232             return mblog;
00233         }
00234 
00235         virtual UniSetTypes::SimpleInfo* getInfo( CORBA::Long userparam = 0 ) override;
00236 
00237     protected:
00238         virtual void step();
00239         virtual void sysCommand( const UniSetTypes::SystemMessage* msg ) override;
00240         virtual void sensorInfo( const UniSetTypes::SensorMessage* sm ) override;
00241         virtual void timerInfo( const UniSetTypes::TimerMessage* tm ) override;
00242         virtual void askSensors( UniversalIO::UIOCommand cmd );
00243         virtual void initOutput();
00244         virtual void sigterm( int signo ) override;
00245         virtual bool activateObject() override;
00246         virtual void initIterators();
00247         virtual void initValues();
00248 
00249         struct InitRegInfo
00250         {
00251             InitRegInfo():
00252                 dev(0), mbreg(0),
00253                 mbfunc(ModbusRTU::fnUnknown),
00254                 initOK(false)
00255             {}
00256             RSProperty p;
00257             std::shared_ptr<RTUDevice> dev;
00258             ModbusRTU::ModbusData mbreg;
00259             ModbusRTU::SlaveFunctionCode mbfunc;
00260             bool initOK;
00261             std::shared_ptr<RegInfo> ri;
00262         };
00263         typedef std::list<InitRegInfo> InitList;
00264 
00265         void firstInitRegisters();
00266         bool preInitRead( InitList::iterator& p );
00267         bool initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty* p );
00268         bool allInitOK;
00269 
00270         RTUDeviceMap devices;
00271         InitList initRegList;    
00272         UniSetTypes::uniset_rwmutex pollMutex;
00273 
00274         virtual std::shared_ptr<ModbusClient> initMB( bool reopen = false ) = 0;
00275 
00276         virtual bool poll();
00277         bool pollRTU( std::shared_ptr<RTUDevice>& dev, RegMap::iterator& it );
00278 
00279         void updateSM();
00280         void updateRTU(RegMap::iterator& it);
00281         void updateMTR(RegMap::iterator& it);
00282         void updateRTU188(RegMap::iterator& it);
00283         void updateRSProperty( RSProperty* p, bool write_only = false );
00284         virtual void updateRespondSensors();
00285 
00286         bool checkUpdateSM( bool wrFunc, long devMode );
00287         bool checkPoll( bool wrFunc );
00288 
00289         bool checkProcActive();
00290         void setProcActive( bool st );
00291         void waitSMReady();
00292 
00293         void readConfiguration();
00294         bool readItem( const std::shared_ptr<UniXML>& xml, UniXML::iterator& it, xmlNode* sec );
00295         bool initItem( UniXML::iterator& it );
00296         void initDeviceList();
00297         void initOffsetList();
00298 
00299         std::shared_ptr<RTUDevice> addDev( RTUDeviceMap& dmap, ModbusRTU::ModbusAddr a, UniXML::iterator& it );
00300         std::shared_ptr<RegInfo> addReg(std::shared_ptr<RegMap>& devices, ModbusRTU::RegID id, ModbusRTU::ModbusData r, UniXML::iterator& it, std::shared_ptr<RTUDevice> dev );
00301         RSProperty* addProp( PList& plist, RSProperty&& p );
00302 
00303         bool initMTRitem(UniXML::iterator& it, std::shared_ptr<RegInfo>& p );
00304         bool initRTU188item(UniXML::iterator& it, std::shared_ptr<RegInfo>& p );
00305         bool initRSProperty( RSProperty& p, UniXML::iterator& it );
00306         bool initRegInfo(std::shared_ptr<RegInfo>& r, UniXML::iterator& it, std::shared_ptr<RTUDevice>& dev  );
00307         bool initRTUDevice( std::shared_ptr<RTUDevice>& d, UniXML::iterator& it );
00308         virtual bool initDeviceInfo( RTUDeviceMap& m, ModbusRTU::ModbusAddr a, UniXML::iterator& it );
00309 
00310         std::string initPropPrefix( const std::string& def_prop_prefix = "" );
00311 
00312         void rtuQueryOptimization( RTUDeviceMap& m );
00313 
00314         xmlNode* cnode = { 0 };
00315         std::string s_field;
00316         std::string s_fvalue;
00317 
00318         std::shared_ptr<SMInterface> shm;
00319 
00320         timeout_t initPause = { 3000 };
00321         UniSetTypes::uniset_rwmutex mutex_start;
00322 
00323         bool force =  { false };        
00324         bool force_out = { false };    
00325         bool mbregFromID = { false };
00326         int polltime = { 100 };    
00327         timeout_t sleepPause_usec;
00328         unsigned int maxQueryCount = { ModbusRTU::MAXDATALEN }; 
00330         PassiveTimer ptHeartBeat;
00331         UniSetTypes::ObjectId sidHeartBeat = { UniSetTypes::DefaultObjectId };
00332         int maxHeartBeat = { 10 };
00333         IOController::IOStateList::iterator itHeartBeat;
00334         UniSetTypes::ObjectId test_id = { UniSetTypes::DefaultObjectId };
00335 
00336         UniSetTypes::ObjectId sidExchangeMode = { UniSetTypes::DefaultObjectId }; 
00337         IOController::IOStateList::iterator itExchangeMode;
00338         long exchangeMode = {emNone}; 
00340         std::atomic_bool activated = { false };
00341         int activateTimeout = { 20000 }; // msec
00342         bool noQueryOptimization = { false };
00343         bool no_extimer = { false };
00344 
00345         std::string prefix;
00346 
00347         timeout_t stat_time = { 0 };      
00348         unsigned int poll_count = { 0 };
00349         PassiveTimer ptStatistic; 
00351         std::string prop_prefix;  
00353         std::shared_ptr<ModbusClient> mb;
00354 
00355         // определение timeout для соединения
00356         timeout_t recv_timeout = { 500 }; // msec
00357         timeout_t default_timeout = { 5000 }; // msec
00358 
00359         int aftersend_pause = { 0 };
00360 
00361         PassiveTimer ptReopen; 
00362         Trigger trReopen;
00363 
00364         PassiveTimer ptInitChannel; 
00366         // т.к. пороговые датчики не связаны напрямую с обменом, создаём для них отдельный список
00367         // и отдельно его проверяем потом
00368         typedef std::list<IOBase> ThresholdList;
00369         ThresholdList thrlist;
00370 
00371         std::string defaultMBtype;
00372         std::string defaultMBaddr;
00373         bool defaultMBinitOK = { false }; // флаг определяющий нужно ли ждать "первого обмена" или при запуске сохранять в SM значение default.
00374 
00375         std::shared_ptr<LogAgregator> loga;
00376         std::shared_ptr<DebugStream> mblog;
00377         std::shared_ptr<LogServer> logserv;
00378         std::string logserv_host = {""};
00379         int logserv_port = {0};
00380         const std::shared_ptr<SharedMemory> ic;
00381 
00382         VMonitor vmon;
00383 
00384         unsigned long ncycle = { 0 }; 
00386     private:
00387         MBExchange();
00388 
00389 };
00390 // -----------------------------------------------------------------------------
00391 #endif // _MBExchange_H_
00392 // -----------------------------------------------------------------------------