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