1 package org.wcb.autohome;
2 /***
3 * Copyright (C) 1999 Walter Bogaardt
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library 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 GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 *
19 * Project: Alice X10 Home Automation
20 *
21 */
22
23 import org.wcb.autohome.interfaces.X10DeviceConstants;
24 import org.wcb.autohome.interfaces.IHAGateway;
25 import org.wcb.autohome.interfaces.IX10Events;
26 import org.wcb.autohome.interfaces.IX10Module;
27 import org.wcb.autohome.exceptions.HomeException;
28
29 import java.util.Vector;
30 import java.util.GregorianCalendar;
31 import java.util.Calendar;
32 import java.rmi.RemoteException;
33
34 /***
35 * Filename: $Id: EventsHandler.java,v 1.11 2004/02/25 21:38:32 wbogaardt Exp $
36 *
37 * Abstract: The EventsHandler is a threaded daemon that runs in the background
38 * and parses through a vector and runs various events one at a time.
39 * until the stop run is called. The event runs if it meets conditions
40 * of date and time.
41 *
42 * $Log: EventsHandler.java,v $
43 * Revision 1.11 2004/02/25 21:38:32 wbogaardt
44 * added javadocs and fixed formating for checkstyle report
45 *
46 * Revision 1.10 2004/01/16 00:53:34 wbogaardt
47 * Fixed a very obscure bug with the Macro Panel that it didn't added new
48 * x10 devices to the drop down of available x10 device for the macro. Modified Macro triggers to change the events to
49 * integer verses strings cleaner this way.
50 *
51 * Revision 1.9 2003/12/22 20:51:29 wbogaardt
52 * refactored name assignments and formatted code for readability.
53 *
54 * Revision 1.8 2003/12/19 20:51:38 wbogaardt
55 * internationalization
56 *
57 * Revision 1.7 2003/12/13 05:36:50 wbogaardt
58 * fixed javadoc comments.
59 *
60 * Revision 1.6 2003/12/11 23:10:07 wbogaardt
61 * cleaned up exception handeling and logging of system.out messages
62 *
63 * Revision 1.5 2003/10/11 04:02:06 wbogaardt
64 * fixed event handler to work again
65 *
66 * Revision 1.4 2003/10/10 18:39:09 wbogaardt
67 * changed date time information from a string to a calendar object
68 *
69 *
70 *@author wbogaardt
71 *@version 1.0
72 */
73 public class EventsHandler implements Runnable, X10DeviceConstants {
74
75 private Thread tTimerThread;
76 private Vector vCurrentEventsModel = null;
77 private IHAGateway gw;
78
79 /***
80 * This creates an event handler and uses the passed in interface
81 * to know if the running events can be executed.
82 * @param gateway The Home automation gateway, which has status of serial port connection.
83 */
84 public EventsHandler(IHAGateway gateway) {
85 this.gw = gateway;
86 }
87
88 /***
89 * This is a threaded object so it must implement
90 * start method calls.
91 */
92 public void start()
93 {
94 tTimerThread = new Thread(this);
95 tTimerThread.start();
96 run();
97 }
98
99 /***
100 * This is the main run method for this thread.
101 */
102 public void run()
103 {
104 int delay = 30000;
105 while (Thread.currentThread() == tTimerThread)
106 {
107 try
108 {
109 Thread.sleep(delay);
110 }
111 catch (InterruptedException ie)
112 {
113 break;
114 }
115 parseEvents();
116 }
117 }
118
119 /***
120 * This is used to stop the thread. When the
121 * user click on stop running.
122 */
123 public void stop()
124 {
125 tTimerThread = null;
126 }
127
128 /***
129 *Sets the events into the daemon to run
130 *this vector gets parsed every minute to determin if certain elements
131 *in the vector meet the requirements if it meets the time requirements
132 *then the event is run appropriately.
133 *
134 *@param items - List of items/events to run.
135 */
136 public void setModel(Vector items)
137 {
138 vCurrentEventsModel = items;
139 }
140
141 /***
142 *Gets the events that the daemon is running
143 *this vector gets parsed every minute to determin if certain elements
144 *in the vector meet the requirements if it meets the time requirements
145 *then the event is run appropriately.
146 *
147 *@return Vector - List of items/events that are running.
148 */
149 public Vector getModel()
150 {
151 if (vCurrentEventsModel.size() < 1)
152 {
153 return null;
154 }
155 return vCurrentEventsModel;
156 }
157
158 /***
159 * Parse the entire table model and find the rows
160 * that the system needs to execute.
161 */
162 private void parseEvents()
163 {
164 GregorianCalendar currDate = new GregorianCalendar();
165 int currHour = currDate.get(Calendar.HOUR_OF_DAY);
166 int currMin = currDate.get(Calendar.MINUTE);
167 IX10Events row;
168 Calendar timestamp;
169 String status;
170 IX10Module module;
171
172 for (int i = 0; i < vCurrentEventsModel.size(); i++)
173 {
174
175 row = (IX10Events) vCurrentEventsModel.elementAt(i);
176 module = row.getModule();
177 if (checkDayOfWeek(row))
178 {
179 timestamp = row.getTime();
180 status = row.getAction();
181
182 if (currHour == timestamp.get(Calendar.HOUR_OF_DAY) && currMin == timestamp.get(Calendar.MINUTE))
183 {
184 if (module.getType() == LAMP_MODULE_ON && status.equalsIgnoreCase("off"))
185 {
186 sendLampCommand(module, 0, status);
187 }
188 if (module.getType() == LAMP_MODULE_ON && status.equalsIgnoreCase("on"))
189 {
190 sendLampCommand(module, 1, status);
191 }
192 if (module.getType() == LAMP_MODULE_ON && status.startsWith("-"))
193 {
194 sendLampCommand(module, 2, status);
195 }
196 if (module.getType() == LAMP_MODULE_ON && status.startsWith("+"))
197 {
198 sendLampCommand(module, 3, status);
199 }
200 if (module.getType() == APPLIANCE_MODULE_ON && status.equalsIgnoreCase("off"))
201 {
202 sendApplianceCommand(module, 0);
203 }
204 if (module.getType() == APPLIANCE_MODULE_ON && status.equalsIgnoreCase("on"))
205 {
206 sendApplianceCommand(module, 1);
207 }
208 if (status.startsWith("All Lights Off"))
209 {
210 sendAllCommand(module, 0);
211 }
212 if (status.startsWith("All Lights ON"))
213 {
214 sendAllCommand(module, 1);
215 }
216 if (status.startsWith("All Off"))
217 {
218 sendAllCommand(module, 2);
219 }
220 }
221 }
222 }
223 }
224
225 /***
226 * This is a prepatory command to parse the Light modules information
227 * into information that can be assimilated by the CM11A or CM17A X10 API Java interface
228 * We need to get the device broken down to house code and id and the starting
229 * Lamp status(off/on) then we need to check if a dim command is associated with
230 * the module to dim/brighten the lamp.
231 * @param deviceID x10Module to send command to
232 * @param status 0 turn off lamp; 1 turn on lamp; 2 dim lamp; 3 brighten lamp;
233 * @param dimCmds percentage to dim or brighten;
234 */
235 private void sendLampCommand(IX10Module deviceID, int status, String dimCmds)
236 {
237 int iPercentage = 0;
238 if (status > 1)
239 {
240 try
241 {
242 String sPercentage = dimCmds.substring(1, dimCmds.length());
243 iPercentage = Integer.parseInt(sPercentage);
244 }
245 catch (NumberFormatException nfe)
246 {
247 printMessage("Not a valid number:" + nfe);
248 }
249 }
250 switch (status)
251 {
252 case 0:
253 printMessage("Turn off lamp " + deviceID.getDescription());
254 try
255 {
256 gw.deviceCommands(deviceID, 0);
257 }
258 catch (RemoteException re)
259 {
260 printMessage("Unable to connect to gateway." + re);
261 }
262 catch (HomeException he)
263 {
264 printMessage("Invalid Command");
265 }
266 break;
267 case 1:
268 printMessage("Turn on lamp " + deviceID.getDescription());
269 try
270 {
271 gw.deviceCommands(deviceID, 1);
272 }
273 catch (RemoteException re)
274 {
275 printMessage("Unable to connect to gateway." + re);
276 }
277 catch (HomeException he)
278 {
279 printMessage("Invalid Command");
280 }
281 break;
282 case 2:
283 this.printMessage("Dimming " + deviceID.getDescription() + " to " + iPercentage + " percent.");
284 try
285 {
286 gw.lampIntensity(deviceID, 0, iPercentage);
287 }
288 catch (RemoteException re)
289 {
290 printMessage("Unable to connect to gateway." + re);
291 }
292 catch (HomeException he)
293 {
294 printMessage("Invalid Command");
295 }
296 break;
297 case 3:
298 this.printMessage("Brightening " + deviceID.getDescription() + " to " + iPercentage + " percent.");
299 try
300 {
301 gw.lampIntensity(deviceID, 1, iPercentage);
302 }
303 catch (RemoteException re)
304 {
305 printMessage("Unable to connect to gateway.:" + re);
306 }
307 catch (HomeException he)
308 {
309 printMessage("Invalid Command");
310 }
311 break;
312 }
313 }
314
315 /***
316 * Breaks down the device id into houseCode and moduleID and then
317 * sends the appropriate on or off command to the
318 * AutoHomeAdminSession controller.
319 * @param deviceID X10 module to send command to.
320 * @param iCmnd 0 turn off appliance; 1 - turn on appliance
321 */
322 private void sendApplianceCommand(IX10Module deviceID, int iCmnd)
323 {
324 switch(iCmnd)
325 {
326 case 0:
327 printMessage("Turn off appliance " + deviceID.getDescription());
328 try
329 {
330 gw.deviceCommands(deviceID, 0);
331 }
332 catch (RemoteException re)
333 {
334 printMessage("Unable to connect to gateway. " + re);
335 }
336 catch (HomeException he)
337 {
338 printMessage("Invalid Command");
339 }
340 break;
341 case 1:
342 printMessage("Turn on appliance " + deviceID.getDescription());
343 try
344 {
345 gw.deviceCommands(deviceID, 1);
346 }
347 catch (RemoteException re)
348 {
349 printMessage("Unable to connect to gateway. " + re);
350 }
351 catch (HomeException he)
352 {
353 printMessage("Invalid Command");
354 }
355 break;
356 }
357 }
358
359 /***
360 * Breaks down the device id into houseCode and moduleID and then
361 * sends the appropriate on or off command to the entire house
362 * codes A - P.
363 * @param deviceID The x10 module section to send command to.
364 * @param cmnd 0 - All lights off; 1 - All lights on; 2 - all devices off
365 */
366 private void sendAllCommand(IX10Module deviceID, int cmnd)
367 {
368 char house = deviceID.getHouseCode();
369 try
370 {
371 gw.allCommandToSection(house, cmnd);
372 }
373 catch (RemoteException re)
374 {
375 printMessage("Unable to connect to gateway. " + re);
376 }
377 catch (HomeException he)
378 {
379 printMessage("Invalid command sent.");
380 }
381 }
382
383 /***
384 * Checks if the string value has same date to return true
385 * @param evt Alice X10Events object
386 * @return True if the current system date and the event are the same.
387 */
388 private boolean checkDayOfWeek(IX10Events evt)
389 {
390 GregorianCalendar currDay = new GregorianCalendar();
391 if (currDay.get(Calendar.DAY_OF_WEEK) == 1 && evt.getSunday())
392 {
393 return true;
394 }
395 if (evt.getMonday() && currDay.get(Calendar.DAY_OF_WEEK) == 2)
396 {
397 return true;
398 }
399 if (evt.getTuesday() && currDay.get(Calendar.DAY_OF_WEEK) == 3)
400 {
401 return true;
402 }
403 if (evt.getWednesday() && currDay.get(Calendar.DAY_OF_WEEK) == 4)
404 {
405 return true;
406 }
407 if (evt.getThursday() && currDay.get(Calendar.DAY_OF_WEEK) == 5)
408 {
409 return true;
410 }
411 if (evt.getFriday() && currDay.get(Calendar.DAY_OF_WEEK) == 6)
412 {
413 return true;
414 }
415 if (evt.getSaturday() && currDay.get(Calendar.DAY_OF_WEEK) == 7)
416 {
417 return true;
418 }
419 return false;
420 }
421
422 /***
423 * Prints the message to the console or speaks it.
424 * @param message
425 */
426 private void printMessage(String message)
427 {
428 AutoHomeAdminSession.getInstance().printMessage(message);
429 }
430 }
431
432
433
434
435
436
437
438
439
440
441
442