1 /*
2     LinKNX KNX home automation platform
3     Copyright (C) 2007-2009 Jean-François Meessen <linknx@ouaye.net>
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 
20 #ifndef IOPORT_H
21 #define IOPORT_H
22 
23 #include "config.h"
24 #include "logger.h"
25 #include "threads.h"
26 #include <string>
27 #include <memory>
28 #include "ticpp.h"
29 #include "ruleserver.h"
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <termios.h>
34 #include <regex.h>
35 
36 
37 
38 class IOPortListener
39 {
40 public:
~IOPortListener()41     virtual ~IOPortListener() {};
42     virtual void onDataReceived(const uint8_t* buf, unsigned int len) = 0;
43 };
44 
45 class RxThread;
46 class ConnectCondition;
47 class IOPort;
48 
49 class IOPortManager
50 {
51 public:
52     static IOPortManager* instance();
reset()53     static void reset()
54     {
55         if (instance_m)
56             delete instance_m;
57         instance_m = 0;
58     };
59     void addPort(IOPort* conn);
60     void removePort(IOPort* conn);
61 
62     IOPort* getPort(const std::string& id);
63 
64     virtual void importXml(ticpp::Element* pConfig);
65     virtual void exportXml(ticpp::Element* pConfig);
66 
67 //    virtual void exportObjectValues(ticpp::Element* pObjects);
68 
69 private:
70     IOPortManager();
71     virtual ~IOPortManager();
72 
73     typedef std::pair<std::string ,IOPort*> IOPortPair_t;
74     typedef std::map<std::string ,IOPort*> IOPortMap_t;
75     IOPortMap_t portMap_m;
76     static IOPortManager* instance_m;
77 };
78 
79 class IOPort
80 {
81 public:
82     enum Direction
83     {
84         In,
85         Out,
86         InOut
87     };
88 
89     IOPort();
90     virtual ~IOPort();
91 
92     static IOPort* create(ticpp::Element* pConfig);
93     static IOPort* create(const std::string& type);
94 
95     virtual void importXml(ticpp::Element* pConfig);
96     virtual void exportXml(ticpp::Element* pConfig);
97 
setID(const char * id)98     void setID(const char* id) { id_m = id; };
getID()99     const char* getID() { return id_m.c_str(); };
100 
101     void addListener(IOPortListener *l); // { if (rxThread_m) rxThread_m->addListener(l); };
102     bool removeListener(IOPortListener *l); // { if (rxThread_m) return (rxThread_m->removeListener(l)) else return false; };
103     void addConnectListener(ConnectCondition *c);
104     bool removeConnectListener(ConnectCondition *c);
105     void onConnect();
106     virtual bool isRxEnabled() = 0;
107     virtual bool mustConnect() = 0;
108     virtual int send(const uint8_t* buf, int len) = 0;
109     virtual int get(uint8_t* buf, int len, pth_event_t stop) = 0;
110 
111 private:
112     std::auto_ptr<RxThread> rxThread_m;
113     std::string id_m;
114 
115     typedef std::list<ConnectCondition*> ConnectListenerList_t;
116     ConnectListenerList_t connectListenerList_m;
117 
118     // Direction dir_m;
119 
120     static Logger& logger_m;
121 };
122 
123 class RxThread : public Thread
124 {
125 public:
126     RxThread(IOPort *port);
127     virtual ~RxThread();
128 
startPort()129     void startPort() { isRunning_m = true; Start(); };
stopPort()130     void stopPort() { isRunning_m = false; Stop(); };
131 
132     void addListener(IOPortListener *listener);
133     bool removeListener(IOPortListener *listener);
134 
135 private:
136     IOPort *port_m;
137     bool isRunning_m;
138     pth_event_t stop_m;
139     typedef std::list<IOPortListener*> ListenerList_t;
140     ListenerList_t listenerList_m;
141 
142     void Run (pth_sem_t * stop);
143     static Logger& logger_m;
144 };
145 
146 class UdpIOPort : public IOPort
147 {
148 public:
149     UdpIOPort();
150     virtual ~UdpIOPort();
151 
152     virtual void importXml(ticpp::Element* pConfig);
153     virtual void exportXml(ticpp::Element* pConfig);
154 
155     int send(const uint8_t* buf, int len);
156     int get(uint8_t* buf, int len, pth_event_t stop);
isRxEnabled()157     virtual bool isRxEnabled() { return rxport_m > 0; };
mustConnect()158     virtual bool mustConnect() { return false; };
159 
160 private:
161     std::string host_m;
162     int sockfd_m;
163     int port_m;
164     int rxport_m;
165     struct sockaddr_in addr_m;
166     static Logger& logger_m;
167 };
168 
169 class TcpClientIOPort : public IOPort
170 {
171 public:
172     TcpClientIOPort();
173     virtual ~TcpClientIOPort();
174 
175     virtual void importXml(ticpp::Element* pConfig);
176     virtual void exportXml(ticpp::Element* pConfig);
177 
178     int send(const uint8_t* buf, int len);
179     int get(uint8_t* buf, int len, pth_event_t stop);
isRxEnabled()180     virtual bool isRxEnabled() { return permanent_m; };
mustConnect()181     virtual bool mustConnect() { return true; };
182 
183 private:
184     struct Socket
185     {
186         Socket(TcpClientIOPort *ioport);
187 
188         ~Socket();
189 
190         TcpClientIOPort *ioport_m;
191         int sockfd_m;
192     };
193 
194     std::string host_m;
195     // Permanent socket or -1 if connection is not permanent.
196     int permanentSockfd_m;
197     int port_m;
198     bool permanent_m;
199     struct sockaddr_in addr_m;
200     static Logger& logger_m;
201 
202     // void connectToServer();
203     // void disconnectFromServer();
204 };
205 
206 class SerialIOPort : public IOPort
207 {
208 public:
209     SerialIOPort();
210     virtual ~SerialIOPort();
211 
212     virtual void importXml(ticpp::Element* pConfig);
213     virtual void exportXml(ticpp::Element* pConfig);
214 
215     int send(const uint8_t* buf, int len);
216     int get(uint8_t* buf, int len, pth_event_t stop);
isRxEnabled()217     virtual bool isRxEnabled() { return true; };
mustConnect()218     virtual bool mustConnect() { return true; };
219 
220 private:
221     std::string dev_m;
222     speed_t speed_m;
223     int fd_m;
224     bool modeRaw_m;
225     int timeout_m;
226     int msglength_m;
227     struct termios oldtio_m, newtio_m;
228     static Logger& logger_m;
229 };
230 
231 class TxAction : public Action
232 {
233 public:
234     TxAction();
235     virtual ~TxAction();
236 
237     virtual void importXml(ticpp::Element* pConfig);
238     virtual void exportXml(ticpp::Element* pConfig);
239 
240     void sendData(IOPort* port);
241 private:
242     virtual void Run (pth_sem_t * stop);
243 
244     int varFlags_m;
245     enum replaceVarFlags
246     {
247         VarEnabled = 1,
248         VarData = 2,
249     };
250     std::string data_m;
251     std::string port_m;
252     bool hex_m;
253 };
254 
255 class RxCondition : public Condition, public IOPortListener
256 {
257 public:
258     RxCondition(ChangeListener* cl);
259     virtual ~RxCondition();
260 
261     virtual bool evaluate();
262     virtual void importXml(ticpp::Element* pConfig);
263     virtual void exportXml(ticpp::Element* pConfig);
264     virtual void statusXml(ticpp::Element* pStatus);
265 
266     virtual void onDataReceived(const uint8_t* buf, unsigned int len);
267 
268 private:
269     std::string port_m;
270     std::string exp_m;
271     regex_t regex_m;
272     bool regexFlag_m;
273     bool value_m;
274     bool hex_m;
275     regmatch_t* pmatch_m;
276     std::vector<Object*> objects_m;
277     ChangeListener* cl_m;
278 };
279 
280 class ConnectCondition : public Condition
281 {
282 public:
283     ConnectCondition(ChangeListener* cl);
284     virtual ~ConnectCondition();
285 
286     virtual bool evaluate();
287     virtual void importXml(ticpp::Element* pConfig);
288     virtual void exportXml(ticpp::Element* pConfig);
289     virtual void statusXml(ticpp::Element* pStatus);
290 
291     virtual void onConnect();
292 
293 private:
294     std::string port_m;
295     bool value_m;
296     ChangeListener* cl_m;
297 };
298 
299 
300 #endif
301