UniSet  2.6.0
ModbusTCPServer.h
1 // -------------------------------------------------------------------------
2 #ifndef ModbusTCPServer_H_
3 #define ModbusTCPServer_H_
4 // -------------------------------------------------------------------------
5 #include <string>
6 #include <queue>
7 #include <ev++.h>
8 #include <sigc++/sigc++.h>
9 #include "Mutex.h"
10 #include "Debug.h"
11 #include "Configuration.h"
12 #include "PassiveTimer.h"
13 #include "ModbusTypes.h"
14 #include "ModbusServer.h"
15 #include "ModbusTCPSession.h"
16 #include "UTCPSocket.h"
17 #include "EventLoopServer.h"
18 // -------------------------------------------------------------------------
19 namespace uniset
20 {
21  // -------------------------------------------------------------------------
30  public EventLoopServer,
31  public ModbusServer
32  {
33  public:
34  ModbusTCPServer( const std::string& addr, int port = 502 );
35  virtual ~ModbusTCPServer();
36 
40  void run( const std::unordered_set<ModbusRTU::ModbusAddr>& vmbaddr, bool thread = false );
41 
42  virtual bool isActive() const override;
43 
44  void setMaxSessions( size_t num );
45  inline size_t getMaxSessions()
46  {
47  return maxSessions;
48  }
49 
51  void setSessionTimeout( timeout_t msec );
52  inline timeout_t getSessionTimeout()
53  {
54  return sessTimeout;
55  }
56 
58  size_t getCountSessions();
59 
60  inline void setIgnoreAddrMode( bool st )
61  {
62  ignoreAddr = st;
63  }
64  inline bool getIgnoreAddrMode()
65  {
66  return ignoreAddr;
67  }
68 
69  virtual void terminate();
70 
71  // Сбор статистики по соединениям...
72  struct SessionInfo
73  {
74  SessionInfo( const std::string& a, unsigned int ask ): iaddr(a), askCount(ask) {}
75 
76  std::string iaddr;
77  unsigned int askCount;
78  };
79 
80  typedef std::list<SessionInfo> Sessions;
81 
82  void getSessions( Sessions& lst );
83 
84  inline std::string getInetAddress()
85  {
86  return iaddr;
87  }
88  inline int getInetPort()
89  {
90  return port;
91  }
92 
93  // -------------------------------------------------
94  // Таймер.
95  // Т.к. eventLoop() "бесконечный", то сделана возможность
96  // подключиться к сигналу "таймера", например для обновления статистики по сессиям
97  // \warning Следует иметь ввиду, что обработчик сигнала, должен быть максимально коротким
98  // т.к. на это время останавливается работа основного потока (eventLoop)
99  // -------------------------------------------------
100  typedef sigc::signal<void> TimerSignal;
101  TimerSignal signal_timer();
102 
103  void setTimer( timeout_t msec );
104  inline timeout_t getTimer()
105  {
106  return tmTime;
107  }
108 
109  protected:
110 
111  // ожидание (при этом время отдаётся eventloop-у)
112  virtual void iowait( timeout_t msec ) override;
113 
114  // функция receive пока не поддерживается...
115  virtual ModbusRTU::mbErrCode realReceive( const std::unordered_set<ModbusRTU::ModbusAddr>& vaddr, timeout_t msecTimeout ) override;
116 
117  virtual void evprepare() override;
118  virtual void evfinish() override;
119 
120  virtual void ioAccept(ev::io& watcher, int revents);
121  void onTimer( ev::timer& t, int revents );
122 
123  void sessionFinished( const ModbusTCPSession* s );
124 
125  virtual size_t getNextData( unsigned char* buf, int len ) override
126  {
127  return 0;
128  }
129 
130  virtual ModbusRTU::mbErrCode sendData( unsigned char* buf, int len ) override
131  {
132  return ModbusRTU::erHardwareError;
133  }
134 
136  virtual void setChannelTimeout( timeout_t msec ) override {};
137 
138  int port = { 0 };
139  std::string iaddr;
140  std::string myname;
141  std::queue<unsigned char> qrecv;
142  ModbusRTU::ADUHeader curQueryHeader;
143 
144  std::mutex sMutex;
145  typedef std::list<std::shared_ptr<ModbusTCPSession>> SessionList;
146  SessionList slist;
147 
148  bool ignoreAddr = { false };
149 
150  size_t maxSessions = { 100 };
151  size_t sessCount = { 0 };
152 
153  timeout_t sessTimeout = { 10000 }; // msec
154 
155  ev::io io;
156  ev::timer ioTimer;
157  std::shared_ptr<UTCPSocket> sock;
158 
159  const std::unordered_set<ModbusRTU::ModbusAddr>* vmbaddr = { nullptr };
160  TimerSignal m_timer_signal;
161 
162  timeout_t tmTime_msec = { UniSetTimer::WaitUpTime }; // время по умолчанию для таймера (TimerSignal)
163  double tmTime = { 0.0 };
164 
165  PassiveTimer ptWait;
166 
167  private:
168  // транслирование сигналов от Sessions..
169  void postReceiveEvent( ModbusRTU::mbErrCode res );
170  ModbusRTU::mbErrCode preReceiveEvent( const std::unordered_set<ModbusRTU::ModbusAddr> vaddr, timeout_t tout );
171  };
172  // -------------------------------------------------------------------------
173 } // end of namespace uniset
174 // -------------------------------------------------------------------------
175 #endif // ModbusTCPServer_H_
176 // -------------------------------------------------------------------------