UniSet  1.7.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 "IONotifyController.h"
00009 #include "UniSetObject_LT.h"
00010 #include "PassiveTimer.h"
00011 #include "DelayTimer.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             RegInfo* reg;
00082         };
00083 
00084         friend std::ostream& operator<<( std::ostream& os, const RSProperty& p );
00085 
00086         typedef std::list<RSProperty> PList;
00087         static std::ostream& print_plist( std::ostream& os, PList& p );
00088 
00089         typedef unsigned long RegID;
00090 
00091         typedef std::map<RegID,RegInfo*> RegMap;
00092         struct RegInfo
00093         {
00094             RegInfo():
00095                 mbval(0),mbreg(0),mbfunc(ModbusRTU::fnUnknown),
00096                 id(0),dev(0),
00097                 rtuJack(RTUStorage::nUnknown),rtuChan(0),
00098                 mtrType(MTR::mtUnknown),
00099                 q_num(0),q_count(1),mb_initOK(false),sm_initOK(false)
00100             {}
00101 
00102             ModbusRTU::ModbusData mbval;
00103             ModbusRTU::ModbusData mbreg;            
00104             ModbusRTU::SlaveFunctionCode mbfunc;    
00105             PList slst;
00106             RegID id;
00107 
00108             RTUDevice* dev;
00109 
00110             // only for RTU188
00111             RTUStorage::RTUJack rtuJack;
00112             int rtuChan;
00113 
00114             // only for MTR
00115             MTR::MTRType mtrType;   
00117             // optimization
00118             int q_num;      
00119             int q_count;    
00121             RegMap::iterator rit;
00122 
00123             // начальная инициалиазция для "записываемых" регистров
00124             // Механизм:
00125             // Если tcp_preinit="1", то сперва будет сделано чтение значения из устройства.
00126             // при этом флаг mb_init=false пока не пройдёт успешной инициализации
00127             // Если tcp_preinit="0", то флаг mb_init сразу выставляется в true.
00128             bool mb_initOK; 
00130             // Флаг sm_init означает, что писать в устройство нельзя, т.к. значение в "карте регистров"
00131             // ещё не инициализировано из SM
00132             bool sm_initOK; 
00133         };
00134 
00135         friend std::ostream& operator<<( std::ostream& os, RegInfo& r );
00136         friend std::ostream& operator<<( std::ostream& os, RegInfo* r );
00137 
00138         struct RTUDevice
00139         {
00140             RTUDevice():
00141             respnond(false),
00142             mbaddr(0),
00143             dtype(dtUnknown),
00144             resp_id(UniSetTypes::DefaultObjectId),
00145             resp_state(false),
00146             resp_invert(false),
00147             numreply(0),
00148             prev_numreply(0),
00149             ask_every_reg(false),
00150             mode_id(UniSetTypes::DefaultObjectId),
00151             mode(emNone),
00152             speed(ComPort::ComSpeed38400),
00153             rtu(0)
00154             {
00155             }
00156             
00157             bool respnond;
00158             ModbusRTU::ModbusAddr mbaddr;   
00159             RegMap regmap;
00160 
00161             DeviceType dtype;   
00163             UniSetTypes::ObjectId resp_id;
00164             IOController::DIOStateList::iterator resp_dit;
00165             DelayTimer resp_Delay;
00166             PassiveTimer resp_ptInit;
00167             bool resp_state;
00168             bool resp_invert;
00169             ost::AtomicCounter numreply;
00170             ost::AtomicCounter prev_numreply;
00171             bool ask_every_reg;
00172             UniSetTypes::ObjectId mode_id;
00173             IOController::AIOStateList::iterator mode_ait;
00174             long mode; // режим работы с устройством (см. ExchangeMode)
00175 
00176             // return TRUE if state changed
00177             bool checkRespond();
00178 
00179             // специфические поля для RS
00180             ComPort::Speed speed;
00181             RTUStorage* rtu;
00182         };
00183 
00184         friend std::ostream& operator<<( std::ostream& os, RTUDevice& d );
00185         
00186         typedef std::map<ModbusRTU::ModbusAddr,RTUDevice*> RTUDeviceMap;
00187 
00188         friend std::ostream& operator<<( std::ostream& os, RTUDeviceMap& d );
00189         void printMap(RTUDeviceMap& d);
00190         
00191         // ----------------------------------
00192         static RegID genRegID( const ModbusRTU::ModbusData r, const int fn );   
00193 
00194         enum Timer
00195         {
00196             tmExchange
00197         };
00198 
00199         void execute();
00200     
00201     protected:
00202         virtual void step();
00203         virtual void processingMessage( UniSetTypes::VoidMessage *msg );
00204         virtual void sysCommand( UniSetTypes::SystemMessage *msg );
00205         virtual void sensorInfo( UniSetTypes::SensorMessage*sm );
00206         virtual void timerInfo( UniSetTypes::TimerMessage *tm );
00207         virtual void askSensors( UniversalIO::UIOCommand cmd ); 
00208         virtual void initOutput();
00209         virtual void sigterm( int signo );
00210         virtual bool activateObject();
00211         virtual void initIterators();
00212         virtual void initValues();
00213 
00214         struct InitRegInfo
00215         {
00216             InitRegInfo():
00217             dev(0),mbreg(0),
00218             mbfunc(ModbusRTU::fnUnknown),
00219             initOK(false),ri(0)
00220             {}
00221             RSProperty p;
00222             RTUDevice* dev;
00223             ModbusRTU::ModbusData mbreg;
00224             ModbusRTU::SlaveFunctionCode mbfunc;
00225             bool initOK;
00226             RegInfo* ri;
00227         };
00228         typedef std::list<InitRegInfo> InitList;
00229 
00230         void firstInitRegisters();
00231         bool preInitRead( InitList::iterator& p );
00232         bool initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty* p );
00233         bool allInitOK;
00234       
00235         RTUDeviceMap rmap;
00236         InitList initRegList;   
00237         UniSetTypes::uniset_mutex pollMutex;
00238 
00239         virtual ModbusClient* initMB( bool reopen=false )= 0;
00240         
00241         virtual void poll();
00242         bool pollRTU( RTUDevice* dev, RegMap::iterator& it );
00243         
00244         void updateSM();
00245         void updateRTU(RegMap::iterator& it);
00246         void updateMTR(RegMap::iterator& it);
00247         void updateRTU188(RegMap::iterator& it);
00248         void updateRSProperty( RSProperty* p, bool write_only=false );
00249         virtual void updateRespondSensors();
00250         
00251         bool checkUpdateSM( bool wrFunc, long devMode );
00252         bool checkPoll( bool wrFunc );
00253         
00254         bool checkProcActive();
00255         void setProcActive( bool st );
00256         void waitSMReady();
00257 
00258         void readConfiguration();
00259         bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec );
00260         bool initItem( UniXML_iterator& it );
00261         void initDeviceList();
00262         void initOffsetList();
00263 
00264         RTUDevice* addDev( RTUDeviceMap& dmap, ModbusRTU::ModbusAddr a, UniXML_iterator& it );
00265         RegInfo* addReg( RegMap& rmap, RegID id, ModbusRTU::ModbusData r, UniXML_iterator& it,
00266                             RTUDevice* dev, RegInfo* rcopy=0 );
00267         RSProperty* addProp( PList& plist, RSProperty& p );
00268 
00269         bool initMTRitem( UniXML_iterator& it, RegInfo* p );
00270         bool initRTU188item( UniXML_iterator& it, RegInfo* p );
00271         bool initRSProperty( RSProperty& p, UniXML_iterator& it );
00272         bool initRegInfo( RegInfo* r, UniXML_iterator& it, RTUDevice* dev  );
00273         bool initRTUDevice( RTUDevice* d, UniXML_iterator& it );
00274         virtual bool initDeviceInfo( RTUDeviceMap& m, ModbusRTU::ModbusAddr a, UniXML_iterator& it );
00275 
00276         void rtuQueryOptimization( RTUDeviceMap& m );
00277 
00278         xmlNode* cnode;
00279         std::string s_field;
00280         std::string s_fvalue;
00281 
00282         SMInterface* shm;
00283         
00284         bool initPause;
00285         UniSetTypes::uniset_mutex mutex_start;
00286 
00287         bool force;     
00288         bool force_out; 
00289         bool mbregFromID;
00290         int polltime;   
00291         timeout_t sleepPause_usec;
00292 
00293         PassiveTimer ptHeartBeat;
00294         UniSetTypes::ObjectId sidHeartBeat;
00295         int maxHeartBeat;
00296         IOController::AIOStateList::iterator aitHeartBeat;
00297         UniSetTypes::ObjectId test_id;
00298 
00299         UniSetTypes::ObjectId sidExchangeMode; 
00300         IOController::AIOStateList::iterator aitExchangeMode;
00301         long exchangeMode; 
00303         UniSetTypes::uniset_mutex actMutex;
00304         bool activated;
00305         int activateTimeout;
00306         bool noQueryOptimization;
00307         bool no_extimer;
00308         
00309         std::string prefix;
00310         
00311         timeout_t stat_time;        
00312         int poll_count;
00313         PassiveTimer ptStatistic;   
00315         std::string prop_prefix;  
00317         ModbusClient* mb;
00318 
00319         // определение timeout для соединения
00320         PassiveTimer ptTimeout;
00321         bool pollActivated;
00322         int recv_timeout;
00323         
00324         int aftersend_pause;
00325         
00326         PassiveTimer ptReopen; 
00327         Trigger trReopen;
00328 
00329         // т.к. пороговые датчики не связаны напрямую с обменом, создаём для них отдельный список
00330         // и отдельно его проверяем потом
00331         typedef std::list<IOBase> ThresholdList;
00332         ThresholdList thrlist;
00333 
00334         bool defaultMBinitOK; // флаг определяющий нужно ли ждать "первого обмена" или при запуске сохранять в SM значение default
00335         
00336      private:
00337         MBExchange();
00338 
00339 };
00340 // -----------------------------------------------------------------------------
00341 #endif // _MBExchange_H_
00342 // -----------------------------------------------------------------------------