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