UniSet  2.6.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 
66  static const int NoSafetyState = -1;
67 
70  {
71  emNone = 0,
73  emReadOnly = 2,
76  };
77 
78  friend std::ostream& operator<<( std::ostream& os, const ExchangeMode& em );
79 
81  {
86  };
87 
88  static DeviceType getDeviceType( const std::string& dtype );
89  friend std::ostream& operator<<( std::ostream& os, const DeviceType& dt );
90 
91  struct RTUDevice;
92  struct RegInfo;
93 
94  struct RSProperty:
95  public IOBase
96  {
97  // only for RTU
98  short nbit;
99  VTypes::VType vType;
100  unsigned short rnum;
101  unsigned short nbyte;
103  RSProperty():
104  nbit(-1), vType(VTypes::vtUnknown),
105  rnum(VTypes::wsize(VTypes::vtUnknown)),
106  nbyte(0)
107  {}
108 
109  // т.к. IOBase содержит rwmutex с запрещённым конструктором копирования
110  // приходится здесь тоже объявлять разрешенными только операции "перемещения"
111  RSProperty( const RSProperty& r ) = delete;
112  RSProperty& operator=(const RSProperty& r) = delete;
113  RSProperty( RSProperty&& r ) = default;
114  RSProperty& operator=(RSProperty&& r) = default;
115 
116  std::shared_ptr<RegInfo> reg;
117  };
118 
119  friend std::ostream& operator<<( std::ostream& os, const RSProperty& p );
120 
121  typedef std::list<RSProperty> PList;
122  static std::ostream& print_plist( std::ostream& os, const PList& p );
123 
124  typedef std::map<ModbusRTU::RegID, std::shared_ptr<RegInfo>> RegMap;
125  struct RegInfo
126  {
127  // т.к. RSProperty содержит rwmutex с запрещённым конструктором копирования
128  // приходится здесь тоже объявлять разрешенными только операции "перемещения"
129  RegInfo( const RegInfo& r ) = default;
130  RegInfo& operator=(const RegInfo& r) = delete;
131  RegInfo( RegInfo&& r ) = delete;
132  RegInfo& operator=(RegInfo&& r) = default;
133 
134  RegInfo():
135  mbval(0), mbreg(0), mbfunc(ModbusRTU::fnUnknown),
136  id(0), dev(0),
137  rtuJack(RTUStorage::nUnknown), rtuChan(0),
138  mtrType(MTR::mtUnknown),
139  q_num(0), q_count(1), mb_initOK(false), sm_initOK(false)
140  {}
141 
142  ModbusRTU::ModbusData mbval;
143  ModbusRTU::ModbusData mbreg;
144  ModbusRTU::SlaveFunctionCode mbfunc;
145  PList slst;
146  ModbusRTU::RegID id;
147 
148  std::shared_ptr<RTUDevice> dev;
149 
150  // only for RTU188
151  RTUStorage::RTUJack rtuJack;
152  int rtuChan;
153 
154  // only for MTR
155  MTR::MTRType mtrType;
157  // optimization
158  size_t q_num;
159  size_t q_count;
161  RegMap::iterator rit;
162 
163  // начальная инициалиазция для "записываемых" регистров
164  // Механизм:
165  // Если tcp_preinit="1", то сперва будет сделано чтение значения из устройства.
166  // при этом флаг mb_init=false пока не пройдёт успешной инициализации
167  // Если tcp_preinit="0", то флаг mb_init сразу выставляется в true.
168  bool mb_initOK;
170  // Флаг sm_init означает, что писать в устройство нельзя, т.к. значение в "карте регистров"
171  // ещё не инициализировано из SM
172  bool sm_initOK;
173  };
174 
175  friend std::ostream& operator<<( std::ostream& os, RegInfo& r );
176  friend std::ostream& operator<<( std::ostream& os, RegInfo* r );
177 
178  struct RTUDevice
179  {
180  RTUDevice():
181  mbaddr(0),
182  dtype(dtUnknown),
183  resp_id(uniset::DefaultObjectId),
184  resp_state(false),
185  resp_invert(false),
186  numreply(0),
187  prev_numreply(0),
188  ask_every_reg(false),
189  mode_id(uniset::DefaultObjectId),
190  mode(emNone),
191  speed(ComPort::ComSpeed38400),
192  rtu188(0)
193  {
194  }
195 
196  ModbusRTU::ModbusAddr mbaddr;
197  std::unordered_map<unsigned int, std::shared_ptr<RegMap>> pollmap;
198 
201  // resp - respond..(контроль наличия связи)
202  uniset::ObjectId resp_id;
203  IOController::IOStateList::iterator resp_it;
204  DelayTimer resp_Delay; // таймер для формирования задержки на отпускание (пропадание связи)
205  PassiveTimer resp_ptInit; // таймер для формирования задержки на инициализацию связи (задержка на выставление датчика связи после запуска)
206  bool resp_state;
207  bool resp_invert;
208  bool resp_force = { false };
209  Trigger trInitOK; // триггер для "инициализации"
210  std::atomic<size_t> numreply; // количество успешных запросов..
211  std::atomic<size_t> prev_numreply;
212 
213  //
216  // режим работы
217  uniset::ObjectId mode_id;
218  IOController::IOStateList::iterator mode_it;
219  long mode; // режим работы с устройством (см. ExchangeMode)
220 
221  // return TRUE if state changed
222  bool checkRespond( std::shared_ptr<DebugStream>& log );
223 
224  // специфические поля для RS
225  ComPort::Speed speed;
226  std::shared_ptr<RTUStorage> rtu188;
227 
228  std::string getShortInfo() const;
229  };
230 
231  friend std::ostream& operator<<( std::ostream& os, RTUDevice& d );
232 
233  typedef std::unordered_map<ModbusRTU::ModbusAddr, std::shared_ptr<RTUDevice>> RTUDeviceMap;
234 
235  friend std::ostream& operator<<( std::ostream& os, RTUDeviceMap& d );
236  void printMap(RTUDeviceMap& d);
237 
238  // ----------------------------------
239  enum Timer
240  {
241  tmExchange
242  };
243 
244  void execute();
245 
246  inline std::shared_ptr<LogAgregator> getLogAggregator()
247  {
248  return loga;
249  }
250  inline std::shared_ptr<DebugStream> log()
251  {
252  return mblog;
253  }
254 
255  virtual uniset::SimpleInfo* getInfo( const char* userparam = 0 ) override;
256 
257  protected:
258  virtual void step();
259  virtual void sysCommand( const uniset::SystemMessage* msg ) override;
260  virtual void sensorInfo( const uniset::SensorMessage* sm ) override;
261  virtual void timerInfo( const uniset::TimerMessage* tm ) override;
262  virtual void askSensors( UniversalIO::UIOCommand cmd );
263  virtual void initOutput();
264  virtual void sigterm( int signo ) override;
265  virtual bool activateObject() override;
266  virtual void initIterators();
267  virtual void initValues();
268 
269  struct InitRegInfo
270  {
271  InitRegInfo():
272  dev(0), mbreg(0),
273  mbfunc(ModbusRTU::fnUnknown),
274  initOK(false)
275  {}
276  RSProperty p;
277  std::shared_ptr<RTUDevice> dev;
278  ModbusRTU::ModbusData mbreg;
279  ModbusRTU::SlaveFunctionCode mbfunc;
280  bool initOK;
281  std::shared_ptr<RegInfo> ri;
282  };
283  typedef std::list<InitRegInfo> InitList;
284 
285  void firstInitRegisters();
286  bool preInitRead( InitList::iterator& p );
287  bool initSMValue( ModbusRTU::ModbusData* data, int count, RSProperty* p );
288  bool allInitOK;
289 
290  RTUDeviceMap devices;
291  InitList initRegList;
292  // uniset::uniset_rwmutex pollMutex;
293 
294  virtual std::shared_ptr<ModbusClient> initMB( bool reopen = false ) = 0;
295 
296  virtual bool poll();
297  bool pollRTU( std::shared_ptr<RTUDevice>& dev, RegMap::iterator& it );
298 
299  void updateSM();
300  void updateRTU(RegMap::iterator& it);
301  void updateMTR(RegMap::iterator& it);
302  void updateRTU188(RegMap::iterator& it);
303  void updateRSProperty( RSProperty* p, bool write_only = false );
304  virtual void updateRespondSensors();
305 
306  bool checkUpdateSM( bool wrFunc, long devMode );
307  bool checkPoll( bool wrFunc ) const;
308 
309  bool checkProcActive() const;
310  void setProcActive( bool st );
311  void waitSMReady();
312 
313  void readConfiguration();
314  bool readItem( const std::shared_ptr<UniXML>& xml, UniXML::iterator& it, xmlNode* sec );
315  bool initItem( UniXML::iterator& it );
316  void initDeviceList();
317  void initOffsetList();
318 
319  std::shared_ptr<RTUDevice> addDev( RTUDeviceMap& dmap, ModbusRTU::ModbusAddr a, UniXML::iterator& it );
320  std::shared_ptr<RegInfo> addReg(std::shared_ptr<RegMap>& devices, ModbusRTU::RegID id, ModbusRTU::ModbusData r, UniXML::iterator& it, std::shared_ptr<RTUDevice> dev );
321  RSProperty* addProp( PList& plist, RSProperty&& p );
322 
323  bool initMTRitem(UniXML::iterator& it, std::shared_ptr<RegInfo>& p );
324  bool initRTU188item(UniXML::iterator& it, std::shared_ptr<RegInfo>& p );
325  bool initRSProperty( RSProperty& p, UniXML::iterator& it );
326  bool initRegInfo(std::shared_ptr<RegInfo>& r, UniXML::iterator& it, std::shared_ptr<RTUDevice>& dev );
327  bool initRTUDevice( std::shared_ptr<RTUDevice>& d, UniXML::iterator& it );
328  virtual bool initDeviceInfo( RTUDeviceMap& m, ModbusRTU::ModbusAddr a, UniXML::iterator& it );
329 
330  std::string initPropPrefix( const std::string& def_prop_prefix = "" );
331 
332  void rtuQueryOptimization( RTUDeviceMap& m );
333 
334  xmlNode* cnode = { 0 };
335  std::string s_field;
336  std::string s_fvalue;
337 
338  std::shared_ptr<SMInterface> shm;
339 
340  timeout_t initPause = { 3000 };
341  uniset::uniset_rwmutex mutex_start;
342 
343  bool force = { false };
344  bool force_out = { false };
345  bool mbregFromID = { false };
346  timeout_t polltime = { 100 };
347  timeout_t sleepPause_msec;
348  size_t maxQueryCount = { ModbusRTU::MAXDATALEN };
350  PassiveTimer ptHeartBeat;
351  uniset::ObjectId sidHeartBeat = { uniset::DefaultObjectId };
352  long maxHeartBeat = { 10 };
353  IOController::IOStateList::iterator itHeartBeat;
355 
357  IOController::IOStateList::iterator itExchangeMode;
358  long exchangeMode = {emNone};
360  std::atomic_bool activated = { false };
361  timeout_t activateTimeout = { 20000 }; // msec
362  bool noQueryOptimization = { false };
363  bool no_extimer = { false };
364 
365  std::string prefix;
366 
367  timeout_t stat_time = { 0 };
368  size_t poll_count = { 0 };
370  std::string statInfo = { "" };
371 
372  std::string prop_prefix;
374  std::shared_ptr<ModbusClient> mb;
375 
376  // определение timeout для соединения
377  timeout_t recv_timeout = { 500 }; // msec
378  timeout_t default_timeout = { 5000 }; // msec
379 
380  timeout_t aftersend_pause = { 0 };
381 
383  Trigger trReopen;
384 
387  // т.к. пороговые датчики не связаны напрямую с обменом, создаём для них отдельный список
388  // и отдельно его проверяем потом
389  typedef std::list<IOBase> ThresholdList;
390  ThresholdList thrlist;
391 
392  std::string defaultMBtype;
393  std::string defaultMBaddr;
394  bool defaultMBinitOK = { false }; // флаг определяющий нужно ли ждать "первого обмена" или при запуске сохранять в SM значение default.
395 
396  std::shared_ptr<LogAgregator> loga;
397  std::shared_ptr<DebugStream> mblog;
398  std::shared_ptr<LogServer> logserv;
399  std::string logserv_host = {""};
400  int logserv_port = {0};
401  const std::shared_ptr<SharedMemory> ic;
402 
403  VMonitor vmon;
404 
405  size_t ncycle = { 0 };
407  private:
408  MBExchange();
409 
410  };
411  // --------------------------------------------------------------------------
412 } // end of namespace uniset
413 // -----------------------------------------------------------------------------
414 #endif // _MBExchange_H_
415 // -----------------------------------------------------------------------------
Пассивный таймер
Definition: PassiveTimer.h:90
short nbit
Definition: MBExchange.h:98
Definition: MBExchange.h:82
MTR::MTRType mtrType
Definition: MBExchange.h:155
size_t maxQueryCount
Definition: MBExchange.h:348
size_t ncycle
Definition: MBExchange.h:405
Definition: MBExchange.h:55
PassiveTimer ptReopen
Definition: MBExchange.h:382
Definition: CallbackTimer.h:29
Definition: MBExchange.h:125
Definition: MBExchange.h:74
VTypes::VType vType
Definition: MBExchange.h:99
bool initItem(UniXML::iterator &it)
Definition: MBExchange.cc:2317
Definition: UniXML.h:43
Definition: MBExchange.h:73
uniset::ObjectId sidExchangeMode
Definition: MBExchange.h:356
long exchangeMode
Definition: MBExchange.h:358
ModbusRTU::ModbusAddr mbaddr
Definition: MBExchange.h:196
unsigned short rnum
Definition: MBExchange.h:100
bool ask_every_reg
Definition: MBExchange.h:214
Definition: MessageType.h:166
Definition: UniSetObject.h:73
Definition: MBExchange.h:75
Definition: MBExchange.h:269
ExchangeMode
Definition: MBExchange.h:69
ModbusRTU::ModbusData mbreg
Definition: MBExchange.h:143
const ObjectId DefaultObjectId
Definition: UniSetTypes.h:56
virtual void sigterm(int signo) override
Definition: MBExchange.cc:358
DeviceType dtype
Definition: MBExchange.h:199
size_t q_num
Definition: MBExchange.h:158
virtual bool activateObject() override
Активизация объекта (переопределяется для необходимых действий после активизации) ...
Definition: MBExchange.cc:2785
DeviceType
Definition: MBExchange.h:80
PassiveTimer ptInitChannel
Definition: MBExchange.h:385
bool mb_initOK
Definition: MBExchange.h:168
Definition: Trigger.h:29
Definition: MBExchange.h:85
Definition: MBExchange.h:178
bool force
Definition: MBExchange.h:343
Definition: DelayTimer.h:29
Definition: MessageType.h:122
Definition: MBExchange.h:83
bool force_out
Definition: MBExchange.h:344
Definition: Mutex.h:32
std::string prop_prefix
Definition: MBExchange.h:372
Definition: IOBase.h:38
timeout_t stat_time
Definition: MBExchange.h:367
Definition: MessageType.h:209
InitList initRegList
Definition: MBExchange.h:291
timeout_t polltime
Definition: MBExchange.h:346
static void help_print(int argc, const char *const *argv)
Definition: MBExchange.cc:256
bool sm_initOK
Definition: MBExchange.h:172
unsigned short nbyte
Definition: MBExchange.h:101
Definition: UniSetTypes_i.idl:64
Definition: MBExchange.h:71
ModbusRTU::SlaveFunctionCode mbfunc
Definition: MBExchange.h:144
Definition: MBExchange.h:84
Definition: MBExchange.h:94
PassiveTimer ptStatistic
Definition: MBExchange.h:369
long ObjectId
Definition: UniSetTypes_i.idl:30
size_t q_count
Definition: MBExchange.h:159
Definition: MBExchange.h:72