|
UniSet
2.2.1
|
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 // -----------------------------------------------------------------------------
1.7.6.1