UniSet  2.6.0
ModbusTCPServer.h
00001 // -------------------------------------------------------------------------
00002 #ifndef ModbusTCPServer_H_
00003 #define ModbusTCPServer_H_
00004 // -------------------------------------------------------------------------
00005 #include <string>
00006 #include <queue>
00007 #include <ev++.h>
00008 #include <sigc++/sigc++.h>
00009 #include "Mutex.h"
00010 #include "Debug.h"
00011 #include "Configuration.h"
00012 #include "PassiveTimer.h"
00013 #include "ModbusTypes.h"
00014 #include "ModbusServer.h"
00015 #include "ModbusTCPSession.h"
00016 #include "UTCPSocket.h"
00017 #include "EventLoopServer.h"
00018 // -------------------------------------------------------------------------
00019 namespace uniset
00020 {
00021 // -------------------------------------------------------------------------
00029 class ModbusTCPServer:
00030     public EventLoopServer,
00031     public ModbusServer
00032 {
00033     public:
00034         ModbusTCPServer( const std::string& addr, int port = 502 );
00035         virtual ~ModbusTCPServer();
00036 
00040         void run( const std::unordered_set<ModbusRTU::ModbusAddr>& vmbaddr, bool thread = false );
00041 
00042         virtual bool isActive() const override;
00043 
00044         void setMaxSessions( size_t num );
00045         inline size_t getMaxSessions()
00046         {
00047             return maxSessions;
00048         }
00049 
00051         void setSessionTimeout( timeout_t msec );
00052         inline timeout_t getSessionTimeout()
00053         {
00054             return sessTimeout;
00055         }
00056 
00058         size_t getCountSessions();
00059 
00060         inline void setIgnoreAddrMode( bool st )
00061         {
00062             ignoreAddr = st;
00063         }
00064         inline bool getIgnoreAddrMode()
00065         {
00066             return ignoreAddr;
00067         }
00068 
00069         virtual void terminate();
00070 
00071         // Сбор статистики по соединениям...
00072         struct SessionInfo
00073         {
00074             SessionInfo( const std::string& a, unsigned int ask ): iaddr(a), askCount(ask) {}
00075 
00076             std::string iaddr;
00077             unsigned int askCount;
00078         };
00079 
00080         typedef std::list<SessionInfo> Sessions;
00081 
00082         void getSessions( Sessions& lst );
00083 
00084         inline std::string getInetAddress()
00085         {
00086             return iaddr;
00087         }
00088         inline int getInetPort()
00089         {
00090             return port;
00091         }
00092 
00093         // -------------------------------------------------
00094         // Таймер.
00095         // Т.к. eventLoop() "бесконечный", то сделана возможность
00096         // подключиться к сигналу "таймера", например для обновления статистики по сессиям
00097         // \warning Следует иметь ввиду, что обработчик сигнала, должен быть максимально коротким
00098         // т.к. на это время останавливается работа основного потока (eventLoop)
00099         // -------------------------------------------------
00100         typedef sigc::signal<void> TimerSignal;
00101         TimerSignal signal_timer();
00102 
00103         void setTimer( timeout_t msec );
00104         inline timeout_t getTimer()
00105         {
00106             return tmTime;
00107         }
00108 
00109     protected:
00110 
00111         // ожидание (при этом время отдаётся eventloop-у)
00112         virtual void iowait( timeout_t msec ) override;
00113 
00114         // функция receive пока не поддерживается...
00115         virtual ModbusRTU::mbErrCode realReceive( const std::unordered_set<ModbusRTU::ModbusAddr>& vaddr, timeout_t msecTimeout ) override;
00116 
00117         virtual void evprepare() override;
00118         virtual void evfinish() override;
00119 
00120         virtual void ioAccept(ev::io& watcher, int revents);
00121         void onTimer( ev::timer& t, int revents );
00122 
00123         void sessionFinished( const ModbusTCPSession* s );
00124 
00125         virtual size_t getNextData( unsigned char* buf, int len ) override
00126         {
00127             return 0;
00128         }
00129 
00130         virtual ModbusRTU::mbErrCode sendData( unsigned char* buf, int len ) override
00131         {
00132             return  ModbusRTU::erHardwareError;
00133         }
00134 
00136         virtual void setChannelTimeout( timeout_t msec ) override {};
00137 
00138         int port = { 0 };
00139         std::string iaddr;
00140         std::string myname;
00141         std::queue<unsigned char> qrecv;
00142         ModbusRTU::ADUHeader curQueryHeader;
00143 
00144         std::mutex sMutex;
00145         typedef std::list<std::shared_ptr<ModbusTCPSession>> SessionList;
00146         SessionList slist;
00147 
00148         bool ignoreAddr = { false };
00149 
00150         size_t maxSessions = { 100 };
00151         size_t sessCount = { 0 };
00152 
00153         timeout_t sessTimeout = { 10000 }; // msec
00154 
00155         ev::io io;
00156         ev::timer ioTimer;
00157         std::shared_ptr<UTCPSocket> sock;
00158 
00159         const std::unordered_set<ModbusRTU::ModbusAddr>* vmbaddr = { nullptr };
00160         TimerSignal m_timer_signal;
00161 
00162         timeout_t tmTime_msec = { UniSetTimer::WaitUpTime }; // время по умолчанию для таймера (TimerSignal)
00163         double tmTime = { 0.0 };
00164 
00165         PassiveTimer ptWait;
00166 
00167     private:
00168         // транслирование сигналов от Sessions..
00169         void postReceiveEvent( ModbusRTU::mbErrCode res );
00170         ModbusRTU::mbErrCode preReceiveEvent( const std::unordered_set<ModbusRTU::ModbusAddr> vaddr, timeout_t tout );
00171 };
00172 // -------------------------------------------------------------------------
00173 } // end of namespace uniset
00174 // -------------------------------------------------------------------------
00175 #endif // ModbusTCPServer_H_
00176 // -------------------------------------------------------------------------