UniSet  2.7.0
MBExchange.h
1 /*
2  * Copyright (c) 2015 Pavel Vainerman.
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as
6  * published by the Free Software Foundation, version 2.1.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  * Lesser General Lesser Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 // -----------------------------------------------------------------------------
17 #ifndef _MBExchange_H_
18 #define _MBExchange_H_
19 // -----------------------------------------------------------------------------
20 #include <ostream>
21 #include <string>
22 #include <map>
23 #include <unordered_map>
24 #include <memory>
25 #include "IONotifyController.h"
26 #include "UniSetObject.h"
27 #include "PassiveTimer.h"
28 #include "DelayTimer.h"
29 #include "Trigger.h"
30 #include "Mutex.h"
31 #include "Calibration.h"
32 #include "SMInterface.h"
33 #include "SharedMemory.h"
34 #include "ThreadCreator.h"
35 #include "IOBase.h"
36 #include "VTypes.h"
37 #include "MTR.h"
38 #include "RTUStorage.h"
39 #include "modbus/ModbusClient.h"
40 #include "LogAgregator.h"
41 #include "LogServer.h"
42 #include "LogAgregator.h"
43 #include "VMonitor.h"
44 // -----------------------------------------------------------------------------
45 #ifndef vmonit
46 #define vmonit( var ) vmon.add( #var, var )
47 #endif
48 // -------------------------------------------------------------------------
49 namespace uniset
50 {
51  // -----------------------------------------------------------------------------
55  class MBExchange:
56  public UniSetObject
57  {
58  public:
59  MBExchange( uniset::ObjectId objId, uniset::ObjectId shmID, const std::shared_ptr<SharedMemory>& ic = nullptr,
60  const std::string& prefix = "mb" );
61  virtual ~MBExchange();
62 
64  static void help_print( int argc, const char* const* argv );
65 
68  {
69  emNone = 0,
71  emReadOnly = 2,
74  };
75  friend std::ostream& operator<<( std::ostream& os, const ExchangeMode& em );
76 
78  enum SafeMode
79  {
80  safeNone = 0,
83  };
84 
85 
86  friend std::string to_string( const SafeMode& m );
87  friend std::ostream& operator<<( std::ostream& os, const SafeMode& m );
88 
90  {
95  };
96 
97  static DeviceType getDeviceType( const std::string& dtype ) noexcept;
98  friend std::ostream& operator<<( std::ostream& os, const DeviceType& dt );
99 
100  struct RTUDevice;
101  struct RegInfo;
102 
103  struct RSProperty:
104  public IOBase
105  {
106  // only for RTU
107  int8_t nbit;
108  VTypes::VType vType;
109  uint16_t rnum;
110  uint8_t nbyte;
112  RSProperty():
113  nbit(-1), vType(VTypes::vtUnknown),
114  rnum(VTypes::wsize(VTypes::vtUnknown)),
115  nbyte(0)
116  {}
117 
118  // т.к. IOBase содержит rwmutex с запрещённым конструктором копирования
119  // приходится здесь тоже объявлять разрешенными только операции "перемещения"
120  RSProperty( const RSProperty& r ) = delete;
121  RSProperty& operator=(const RSProperty& r) = delete;
122  RSProperty( RSProperty&& r ) = default;
123  RSProperty& operator=(RSProperty&& r) = default;
124 
125  std::shared_ptr<RegInfo> reg;
126  };
127 
128  friend std::ostream& operator<<( std::ostream& os, const RSProperty& p );
129 
130  typedef std::list<RSProperty> PList;
131  static std::ostream& print_plist( std::ostream& os, const PList& p );
132 
133  typedef std::map<ModbusRTU::RegID, std::shared_ptr<RegInfo>> RegMap;
134  struct RegInfo
135  {
136  // т.к. RSProperty содержит rwmutex с запрещённым конструктором копирования
137  // приходится здесь тоже объявлять разрешенными только операции "перемещения"
138  RegInfo( const RegInfo& r ) = default;
139  RegInfo& operator=(const RegInfo& r) = delete;
140  RegInfo( RegInfo&& r ) = delete;
141  RegInfo& operator=(RegInfo&& r) = default;
142  RegInfo() = default;
143 
144  ModbusRTU::ModbusData mbval = { 0 };
145  ModbusRTU::ModbusData mbreg = { 0 };
146  ModbusRTU::SlaveFunctionCode mbfunc = { ModbusRTU::fnUnknown };
147  PList slst;
148  ModbusRTU::RegID regID = { 0 };
149 
150  std::shared_ptr<RTUDevice> dev;
151 
152  // only for RTU188
153  RTUStorage::RTUJack rtuJack = { RTUStorage::nUnknown };
154  int rtuChan = { 0 };
155 
156  // only for MTR
157  MTR::MTRType mtrType = { MTR::mtUnknown };
159  // optimization
160  size_t q_num = { 0 };
161  size_t q_count = { 1 };
163  RegMap::iterator rit;
164 
165  // начальная инициалиазция для "записываемых" регистров
166  // Механизм:
167  // Если tcp_preinit="1", то сперва будет сделано чтение значения из устройства.
168  // при этом флаг mb_init=false пока не пройдёт успешной инициализации
169  // Если tcp_preinit="0", то флаг mb_init сразу выставляется в true.
170  bool mb_initOK = { false };
172  // Флаг sm_init означает, что писать в устройство нельзя, т.к. значение в "карте регистров"
173  // ещё не инициализировано из SM
174  bool sm_initOK = { false };
175  };
176 
177  friend std::ostream& operator<<( std::ostream& os, const RegInfo& r );
178  friend std::ostream& operator<<( std::ostream& os, const RegInfo* r );
179 
180  struct RTUDevice
181  {
182  ModbusRTU::ModbusAddr mbaddr = { 0 };
183  std::unordered_map<size_t, std::shared_ptr<RegMap>> pollmap;
184 
185  DeviceType dtype = { dtUnknown };
187  // resp - respond..(контроль наличия связи)
189  IOController::IOStateList::iterator resp_it;
190  DelayTimer resp_Delay; // таймер для формирования задержки на отпускание (пропадание связи)
191  PassiveTimer resp_ptInit; // таймер для формирования задержки на инициализацию связи (задержка на выставление датчика связи после запуска)
192  bool resp_state = { false };
193  bool resp_invert = { false };
194  bool resp_force = { false };
195  Trigger trInitOK; // триггер для "инициализации"
196  std::atomic<size_t> numreply = { 0 }; // количество успешных запросов..
197  std::atomic<size_t> prev_numreply = { 0 };
198 
199  //
200  bool ask_every_reg = { false };
202  // режим работы
204  IOController::IOStateList::iterator mode_it;
205  long mode = { emNone }; // режим работы с устройством (см. ExchangeMode)
206 
207  // safe mode
208  long safeMode = { safeNone };
210  IOController::IOStateList::iterator safemode_it;
211  long safemode_value = { 1 };
212 
213  // return TRUE if state changed
214  bool checkRespond( std::shared_ptr<DebugStream>& log );
215 
216  // специфические поля для RS
217  ComPort::Speed speed = { ComPort::ComSpeed38400 };
218  std::shared_ptr<RTUStorage> rtu188;
219 
220  std::string getShortInfo() const;
221  };
222 
223  friend std::ostream& operator<<( std::ostream& os, RTUDevice& d );
224 
225  typedef std::unordered_map<ModbusRTU::ModbusAddr, std::shared_ptr<RTUDevice>> RTUDeviceMap;
226 
227  friend std::ostream& operator<<( std::ostream& os, RTUDeviceMap& d );
228  void printMap(RTUDeviceMap& d);
229 
230  // ----------------------------------
231  enum Timer
232  {
233  tmExchange
234  };
235 
236  void execute();
237 
238  inline std::shared_ptr<LogAgregator> getLogAggregator()
239  {
240  return loga;
241  }
242  inline std::shared_ptr<DebugStream> log()
243  {
244  return mblog;
245  }
246 
247  virtual uniset::SimpleInfo* getInfo( const char* userparam = 0 ) override;
248 
249  protected:
250  virtual void step();
251  virtual void sysCommand( const uniset::SystemMessage* msg ) override;
252  virtual void sensorInfo( const uniset::SensorMessage* sm ) override;
253  virtual void timerInfo( const uniset::TimerMessage* tm ) override;
254  virtual void askSensors( UniversalIO::UIOCommand cmd );
255  virtual void initOutput();
256  virtual bool deactivateObject() override;
257  virtual bool activateObject() override;
258  virtual void initIterators();
259  virtual void initValues();
260 
261  struct InitRegInfo
262  {
263  InitRegInfo():
264  dev(0), mbreg(0),
265  mbfunc(ModbusRTU::fnUnknown),
266  initOK(false)
267  {}
268  RSProperty p;
269  std::shared_ptr<RTUDevice> dev;
270  ModbusRTU::ModbusData mbreg;
271  ModbusRTU::SlaveFunctionCode mbfunc;
272  bool initOK;
273  std::shared_ptr<RegInfo> ri;
274  };
275  typedef std::list<InitRegInfo> InitList;
276 
277  void firstInitRegisters();
278  bool preInitRead( InitList::iterator& p );
279  bool initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty* p );
280  bool allInitOK;
281 
282  RTUDeviceMap devices;
283  InitList initRegList;
285  virtual std::shared_ptr<ModbusClient> initMB( bool reopen = false ) = 0;
286 
287  virtual bool poll();
288  bool pollRTU( std::shared_ptr<RTUDevice>& dev, RegMap::iterator& it );
289 
290  void updateSM();
291 
292  // в функции передаётся итератор,
293  // т.к. в них идёт итерирование в случае если запрос в несколько регистров
294  void updateRTU(RegMap::iterator& it);
295  void updateMTR(RegMap::iterator& it);
296  void updateRTU188(RegMap::iterator& it);
297  void updateRSProperty( RSProperty* p, bool write_only = false );
298  virtual void updateRespondSensors();
299 
300  bool isUpdateSM( bool wrFunc, long devMode ) const noexcept;
301  bool isPollEnabled( bool wrFunc ) const noexcept;
302  bool isSafeMode( std::shared_ptr<RTUDevice>& dev ) const noexcept;
303 
304  bool isProcActive() const;
305  void setProcActive( bool st );
306  bool waitSMReady();
307 
308  void readConfiguration();
309  bool readItem( const std::shared_ptr<UniXML>& xml, UniXML::iterator& it, xmlNode* sec );
310  bool initItem( UniXML::iterator& it );
311  void initDeviceList();
312  void initOffsetList();
313 
314  std::shared_ptr<RTUDevice> addDev( RTUDeviceMap& dmap, ModbusRTU::ModbusAddr a, UniXML::iterator& it );
315  std::shared_ptr<RegInfo> addReg(std::shared_ptr<RegMap>& devices, ModbusRTU::RegID id, ModbusRTU::ModbusData r, UniXML::iterator& it, std::shared_ptr<RTUDevice> dev );
316  RSProperty* addProp( PList& plist, RSProperty&& p );
317 
318  bool initMTRitem(UniXML::iterator& it, std::shared_ptr<RegInfo>& p );
319  bool initRTU188item(UniXML::iterator& it, std::shared_ptr<RegInfo>& p );
320  bool initRSProperty( RSProperty& p, UniXML::iterator& it );
321  bool initRegInfo(std::shared_ptr<RegInfo>& r, UniXML::iterator& it, std::shared_ptr<RTUDevice>& dev );
322  bool initRTUDevice( std::shared_ptr<RTUDevice>& d, UniXML::iterator& it );
323  virtual bool initDeviceInfo( RTUDeviceMap& m, ModbusRTU::ModbusAddr a, UniXML::iterator& it );
324 
325  std::string initPropPrefix( const std::string& def_prop_prefix = "" );
326 
327  void rtuQueryOptimization( RTUDeviceMap& m );
328  void rtuQueryOptimizationForDevice( const std::shared_ptr<RTUDevice>& d );
329  void rtuQueryOptimizationForRegMap( const std::shared_ptr<RegMap>& regmap );
330 
331  xmlNode* cnode = { 0 };
332  std::string s_field;
333  std::string s_fvalue;
334 
335  std::shared_ptr<SMInterface> shm;
336 
337  timeout_t initPause = { 3000 };
338  uniset::uniset_rwmutex mutex_start;
339 
340  bool force = { false };
341  bool force_out = { false };
342  bool mbregFromID = { false };
343  timeout_t polltime = { 100 };
344  timeout_t sleepPause_msec = { 10 };
345  size_t maxQueryCount = { ModbusRTU::MAXDATALEN };
347  PassiveTimer ptHeartBeat;
348  uniset::ObjectId sidHeartBeat = { uniset::DefaultObjectId };
349  long maxHeartBeat = { 10 };
350  IOController::IOStateList::iterator itHeartBeat;
352 
354  IOController::IOStateList::iterator itExchangeMode;
355  long exchangeMode = { emNone };
357  std::atomic_bool activated = { false };
358  std::atomic_bool canceled = { false };
359  timeout_t activateTimeout = { 20000 }; // msec
360  bool noQueryOptimization = { false };
361  bool notUseExchangeTimer = { false };
362 
363  std::string prefix;
364 
365  timeout_t stat_time = { 0 };
366  size_t poll_count = { 0 };
368  std::string statInfo = { "" };
369 
370  std::string prop_prefix;
372  std::shared_ptr<ModbusClient> mb;
373 
374  // определение timeout для соединения
375  timeout_t recv_timeout = { 500 }; // msec
376  timeout_t default_timeout = { 5000 }; // msec
377 
378  timeout_t aftersend_pause = { 0 };
379 
381  Trigger trReopen;
382 
385  // т.к. пороговые датчики не связаны напрямую с обменом, создаём для них отдельный список
386  // и отдельно его проверяем потом
387  typedef std::list<IOBase> ThresholdList;
388  ThresholdList thrlist;
389 
390  std::string defaultMBtype;
391  std::string defaultMBaddr;
392  bool defaultMBinitOK = { false }; // флаг определяющий нужно ли ждать "первого обмена" или при запуске сохранять в SM значение default.
393 
394  std::shared_ptr<LogAgregator> loga;
395  std::shared_ptr<DebugStream> mblog;
396  std::shared_ptr<LogServer> logserv;
397  std::string logserv_host = {""};
398  int logserv_port = {0};
399  const std::shared_ptr<SharedMemory> ic;
400 
401  VMonitor vmon;
402 
403  size_t ncycle = { 0 };
405  private:
406  MBExchange();
407 
408  };
409  // --------------------------------------------------------------------------
410 } // end of namespace uniset
411 // -----------------------------------------------------------------------------
412 #endif // _MBExchange_H_
413 // -----------------------------------------------------------------------------
Пассивный таймер
Definition: PassiveTimer.h:92
Definition: MBExchange.h:91
size_t maxQueryCount
Definition: MBExchange.h:345
size_t ncycle
Definition: MBExchange.h:403
Definition: MBExchange.h:55
PassiveTimer ptReopen
Definition: MBExchange.h:380
Definition: CallbackTimer.h:29
Definition: MBExchange.h:134
Definition: MBExchange.h:72
VTypes::VType vType
Definition: MBExchange.h:108
Definition: UniXML.h:43
Definition: MBExchange.h:71
uniset::ObjectId sidExchangeMode
Definition: MBExchange.h:353
void updateRSProperty(RSProperty *p, bool write_only=false)
Definition: MBExchange.cc:1348
long exchangeMode
Definition: MBExchange.h:355
Definition: MBExchange.h:82
Definition: MessageType.h:168
Definition: UniSetObject.h:73
Definition: VMonitor.h:116
Definition: MBExchange.h:73
Definition: MBExchange.h:261
ExchangeMode
Definition: MBExchange.h:67
const ObjectId DefaultObjectId
Definition: UniSetTypes.h:69
SafeMode
Definition: MBExchange.h:78
virtual bool activateObject() override
Активизация объекта (переопределяется для необходимых действий после активизации) ...
Definition: MBExchange.cc:2990
DeviceType
Definition: MBExchange.h:89
PassiveTimer ptInitChannel
Definition: MBExchange.h:383
Definition: Trigger.h:29
uint8_t nbyte
Definition: MBExchange.h:110
Definition: MBExchange.h:94
Definition: MBExchange.h:180
bool force
Definition: MBExchange.h:340
Definition: DelayTimer.h:29
Definition: MessageType.h:124
uint16_t rnum
Definition: MBExchange.h:109
Definition: MBExchange.h:92
bool force_out
Definition: MBExchange.h:341
Definition: Mutex.h:31
int8_t nbit
Definition: MBExchange.h:107
Definition: MBExchange.h:80
std::string prop_prefix
Definition: MBExchange.h:370
Definition: IOBase.h:34
timeout_t stat_time
Definition: MBExchange.h:365
Definition: MessageType.h:211
InitList initRegList
Definition: MBExchange.h:283
timeout_t polltime
Definition: MBExchange.h:343
static void help_print(int argc, const char *const *argv)
Definition: MBExchange.cc:256
Definition: UniSetTypes_i.idl:64
void updateMTR(RegMap::iterator &it)
Definition: MBExchange.cc:1800
Definition: MBExchange.h:69
Definition: MBExchange.h:93
Definition: MBExchange.h:103
virtual bool deactivateObject() override
Деактивиция объекта (переопределяется для необходимых действий при завершении работы) ...
Definition: MBExchange.cc:362
static bool initItem(IOBase *b, UniXML::iterator &it, const std::shared_ptr< SMInterface > &shm, const std::string &prefix, bool init_prefix_only, std::shared_ptr< DebugStream > dlog=nullptr, std::string myname="", int def_filtersize=0, float def_filterT=0.0, float def_lsparam=0.2, float def_iir_coeff_prev=0.5, float def_iir_coeff_new=0.5)
Definition: IOBase.cc:549
PassiveTimer ptStatistic
Definition: MBExchange.h:367
long ObjectId
Definition: UniSetTypes_i.idl:30
Definition: MBExchange.h:70