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 "Trigger.h"
00012 #include "Mutex.h"
00013 #include "Calibration.h"
00014 #include "SMInterface.h"
00015 #include "SharedMemory.h"
00016 #include "ThreadCreator.h"
00017 #include "IOBase.h"
00018 #include "VTypes.h"
00019 #include "MTR.h"
00020 #include "RTUStorage.h"
00021 #include "modbus/ModbusClient.h"
00022 // -----------------------------------------------------------------------------
00026 class MBExchange:
00027     public UniSetObject_LT
00028 {
00029     public:
00030         MBExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId shmID, SharedMemory* ic=0,
00031                         const std::string prefix="mb" );
00032         virtual ~MBExchange();
00033     
00035         static void help_print( int argc, const char* const* argv );
00036 
00037         static const int NoSafetyState=-1;
00038 
00040         enum ExchangeMode
00041         {
00042             emNone=0,       
00043             emWriteOnly=1,  
00044             emReadOnly=2,       
00045             emSkipSaveToSM=3,   
00046             emSkipExchange=4  
00047         };
00048 
00049         friend std::ostream& operator<<( std::ostream& os, const ExchangeMode& em );
00050         
00051         enum DeviceType
00052         {
00053             dtUnknown,      
00054             dtRTU,          
00055             dtMTR,          
00056             dtRTU188        
00057         };
00058 
00059         static DeviceType getDeviceType( const std::string& dtype );
00060         friend std::ostream& operator<<( std::ostream& os, const DeviceType& dt );
00061 
00062         struct RTUDevice;
00063         struct RegInfo;
00064 
00065         struct RSProperty:
00066             public IOBase
00067         {
00068             // only for RTU
00069             short nbit;             
00070             VTypes::VType vType;    
00071             short rnum;             
00072             short nbyte;            
00074             RSProperty():
00075                 nbit(-1),vType(VTypes::vtUnknown),
00076                 rnum(VTypes::wsize(VTypes::vtUnknown)),
00077                 nbyte(0),reg(0)
00078             {}
00079 
00080             RegInfo* reg;
00081         };
00082 
00083         friend std::ostream& operator<<( std::ostream& os, const RSProperty& p );
00084 
00085         typedef std::list<RSProperty> PList;
00086         static std::ostream& print_plist( std::ostream& os, PList& p );
00087 
00088         typedef unsigned long RegID;
00089 
00090         typedef std::map<RegID,RegInfo*> RegMap;
00091         struct RegInfo
00092         {
00093             RegInfo():
00094                 mbval(0),mbreg(0),mbfunc(ModbusRTU::fnUnknown),
00095                 id(0),dev(0),
00096                 rtuJack(RTUStorage::nUnknown),rtuChan(0),
00097                 mtrType(MTR::mtUnknown),
00098                 q_num(0),q_count(1),mb_initOK(true),sm_initOK(true)
00099             {}
00100 
00101             ModbusRTU::ModbusData mbval;
00102             ModbusRTU::ModbusData mbreg;            
00103             ModbusRTU::SlaveFunctionCode mbfunc;    
00104             PList slst;
00105             RegID id;
00106 
00107             RTUDevice* dev;
00108 
00109             // only for RTU188
00110             RTUStorage::RTUJack rtuJack;
00111             int rtuChan;
00112 
00113             // only for MTR
00114             MTR::MTRType mtrType;   
00116             // optimization
00117             int q_num;      
00118             int q_count;    
00120             RegMap::iterator rit;
00121 
00122             // начальная инициалиазция для "записываемых" регистров
00123             // Механизм:
00124             // Если tcp_preinit="1", то сперва будет сделано чтение значения из устройства.
00125             // при этом флаг mb_init=false пока не пройдёт успешной инициализации
00126             // Если tcp_preinit="0", то флаг mb_init сразу выставляется в true.
00127             bool mb_initOK; 
00129             // Флаг sm_init означает, что писать в устройство нельзя, т.к. значение в "карте регистров"
00130             // ещё не инициализировано из SM
00131             bool sm_initOK; 
00132         };
00133 
00134         friend std::ostream& operator<<( std::ostream& os, RegInfo& r );
00135         friend std::ostream& operator<<( std::ostream& os, RegInfo* r );
00136 
00137         struct RTUDevice
00138         {
00139             RTUDevice():
00140             respnond(false),
00141             mbaddr(0),
00142             dtype(dtUnknown),
00143             resp_id(UniSetTypes::DefaultObjectId),
00144             resp_state(false),
00145             resp_invert(false),
00146             resp_real(false),
00147             resp_init(false),
00148             ask_every_reg(false),
00149             mode_id(UniSetTypes::DefaultObjectId),
00150             mode(emNone),
00151             speed(ComPort::ComSpeed38400),
00152             rtu(0)
00153             {
00154                 resp_trTimeout.change(false);
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             PassiveTimer resp_ptTimeout;
00166             Trigger resp_trTimeout;
00167             bool resp_state;
00168             bool resp_invert;
00169             bool resp_real;
00170             bool resp_init;
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 
00213         struct InitRegInfo
00214         {
00215             InitRegInfo():
00216             dev(0),mbreg(0),
00217             mbfunc(ModbusRTU::fnUnknown),
00218             initOK(false),ri(0)
00219             {}
00220             RSProperty p;
00221             RTUDevice* dev;
00222             ModbusRTU::ModbusData mbreg;
00223             ModbusRTU::SlaveFunctionCode mbfunc;
00224             bool initOK;
00225             RegInfo* ri;
00226         };
00227         typedef std::list<InitRegInfo> InitList;
00228 
00229         void firstInitRegisters();
00230         bool preInitRead( InitList::iterator& p );
00231         bool initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty* p );
00232         bool allInitOK;
00233       
00234         RTUDeviceMap rmap;
00235         InitList initRegList;   
00236         UniSetTypes::uniset_mutex pollMutex;
00237 
00238         virtual ModbusClient* initMB( bool reopen=false )= 0;
00239         
00240         virtual void poll();
00241         bool pollRTU( RTUDevice* dev, RegMap::iterator& it );
00242         
00243         void updateSM();
00244         void updateRTU(RegMap::iterator& it);
00245         void updateMTR(RegMap::iterator& it);
00246         void updateRTU188(RegMap::iterator& it);
00247         void updateRSProperty( RSProperty* p, bool write_only=false );
00248         virtual void updateRespondSensors();
00249         
00250         bool checkUpdateSM( bool wrFunc, long devMode );
00251         bool checkPoll( bool wrFunc );
00252         
00253         bool checkProcActive();
00254         void setProcActive( bool st );
00255         void waitSMReady();
00256 
00257         void readConfiguration();
00258         bool readItem( UniXML& xml, UniXML_iterator& it, xmlNode* sec );
00259         bool initItem( UniXML_iterator& it );
00260         void initDeviceList();
00261         void initOffsetList();
00262 
00263         RTUDevice* addDev( RTUDeviceMap& dmap, ModbusRTU::ModbusAddr a, UniXML_iterator& it );
00264         RegInfo* addReg( RegMap& rmap, RegID id, ModbusRTU::ModbusData r, UniXML_iterator& it,
00265                             RTUDevice* dev, RegInfo* rcopy=0 );
00266         RSProperty* addProp( PList& plist, RSProperty& p );
00267 
00268         bool initMTRitem( UniXML_iterator& it, RegInfo* p );
00269         bool initRTU188item( UniXML_iterator& it, RegInfo* p );
00270         bool initRSProperty( RSProperty& p, UniXML_iterator& it );
00271         bool initRegInfo( RegInfo* r, UniXML_iterator& it, RTUDevice* dev  );
00272         bool initRTUDevice( RTUDevice* d, UniXML_iterator& it );
00273         virtual bool initDeviceInfo( RTUDeviceMap& m, ModbusRTU::ModbusAddr a, UniXML_iterator& it );
00274 
00275         void rtuQueryOptimization( RTUDeviceMap& m );
00276 
00277         xmlNode* cnode;
00278         std::string s_field;
00279         std::string s_fvalue;
00280 
00281         SMInterface* shm;
00282         
00283         bool initPause;
00284         UniSetTypes::uniset_mutex mutex_start;
00285 
00286         bool force;     
00287         bool force_out; 
00288         bool mbregFromID;
00289         int polltime;   
00290         timeout_t sleepPause_usec;
00291 
00292         PassiveTimer ptHeartBeat;
00293         UniSetTypes::ObjectId sidHeartBeat;
00294         int maxHeartBeat;
00295         IOController::AIOStateList::iterator aitHeartBeat;
00296         UniSetTypes::ObjectId test_id;
00297 
00298         UniSetTypes::ObjectId sidExchangeMode; 
00299         IOController::AIOStateList::iterator aitExchangeMode;
00300         long exchangeMode; 
00302         UniSetTypes::uniset_mutex actMutex;
00303         bool activated;
00304         int activateTimeout;
00305         bool noQueryOptimization;
00306         bool no_extimer;
00307         
00308         std::string prefix;
00309         
00310         timeout_t stat_time;        
00311         int poll_count;
00312         PassiveTimer ptStatistic;   
00314         std::string prop_prefix;  
00316         ModbusClient* mb;
00317 
00318         // определение timeout для соединения
00319         PassiveTimer ptTimeout;
00320         bool pollActivated;
00321         int recv_timeout;
00322         
00323         int aftersend_pause;
00324         
00325         PassiveTimer ptReopen; 
00326         Trigger trReopen;
00327 
00328         // т.к. пороговые датчики не связаны напрямую с обменом, создаём для них отдельный список
00329         // и отдельно его проверяем потом
00330         typedef std::list<IOBase> ThresholdList;
00331         ThresholdList thrlist;
00332 
00333      private:
00334         MBExchange();
00335 
00336 };
00337 // -----------------------------------------------------------------------------
00338 #endif // _MBExchange_H_
00339 // -----------------------------------------------------------------------------