c146c6f61e4190cae0ea02309672f256f19972ef
[iot2.git] / benchmarks / Java / HomeSecurityController / HomeSecurityController.java
1 package HomeSecurityController;
2
3 // Standard Java Packages
4 import java.util.Date;
5 import java.util.Iterator;
6 import java.util.ArrayList;
7 import java.util.HashMap;
8 import java.util.List;
9 import java.util.Map;
10
11 import java.util.Set;
12 import java.util.HashSet;
13 import java.util.concurrent.atomic.AtomicBoolean;
14 import java.util.concurrent.ConcurrentHashMap;
15
16 // RMI packages
17 import java.rmi.RemoteException;
18 import java.rmi.server.UnicastRemoteObject;
19
20 // IoT Runtime Packages
21 import iotruntime.slave.IoTSet;
22 import iotruntime.slave.IoTRelation;
23 import iotruntime.slave.IoTAddress;
24 import iotcode.annotation.*;
25
26 // IoT Driver Packages
27 import iotcode.interfaces.*;
28
29 // IoT Cloud
30 import iotcloud.*;
31
32 /** Class Home Security Controller for the home security application benchmark
33  *
34  * @author      Rahmadi Trimananda <rtrimana @ uci.edu>
35  * @version     1.0
36  * @since       2016-12-14
37  */
38 public class HomeSecurityController implements SmartthingsSensorCallback, SmartthingsActuatorCallback {
39
40         /*
41          *  Constants
42          */
43         private static final int MOTION_TIME_THRESHOLD = 60;    // in seconds
44         private static final int CAMERA_FPS = 15;
45         private static final int CHECK_TIME_WAIT = 1;                   // in seconds
46         private static final int SECOND_TO_TURN_ON = 60;                // in seconds
47         private static final int SECOND_TO_TURN_OFF = 1;                // in seconds
48         private static final int LOCK_DOOR = 0;
49         private static final int UNLOCK_DOOR = 1;
50         // For IoTCloud
51         private static final String BASE_URL = "http://dc-6.calit2.uci.edu/test.iotcloud/";
52         private static final String PASSWORD = "reallysecret";
53         private static final int LOCAL_MACHINE_ID = 399;
54         private static final int LISTENING_PORT = -1;   // We don't use any listening port for this application
55         
56         /**
57          *  IoT Sets and Relations
58          *  <p>
59          *  Devices involved:
60          *  1) Multipurpose sensor (detect windows open/close) - Smartthings sensor
61          *  2) Motion sensor (detect motion in certain radius) - Smartthings sensor
62          *  3) Water leak sensor (detect leakage) - Smartthings sensor
63          *  4) Camera (detect motion)
64          *  5) Alarm (using ESP board) - assuming 1 house alarm
65          *  6) Room (object as place of device)
66          *  7) Doorlock (detect open/locked)
67          */
68         @config private IoTSet<SmartthingsSensorSmart> smartSensorsSet;
69         @config private IoTSet<CameraSmart> camSet;
70         @config private IoTSet<AlarmSmart> alarmSet;
71         @config private IoTSet<RoomSmart> roomSet;
72         @config private IoTSet<SmartthingsActuatorSmart> doorlockSet;
73         // Set of addresses for Fidelius connection (dc-6.calit2.uci.edu) to give access
74         @config private IoTSet<IoTAddress> iotcloudServer;
75
76         @config private IoTRelation<RoomSmart, SmartthingsSensorSmart> roomSensorRelation;
77         @config private IoTRelation<RoomSmart, CameraSmart> roomCameraRelation;
78         //@config private IoTRelation<RoomSmart, DoorLock> roomDoorLockRelation;
79
80         /*******************************************************************************************************************************************
81         **
82         **  Variables
83         **
84         *******************************************************************************************************************************************/
85         long lastTimeChecked = 0;
86
87         private static int sensorId = 0;
88         private static int doorlockId = 0;
89         // Initialize values 1 and 0 (for active and not active)
90         private final IoTString ACTIVE = new IoTString("1");            // ACTIVE can mean detecting or being locked for doorlock
91         private final IoTString NOT_ACTIVE = new IoTString("0");        // NOT_ACTIVE can mean not detecting or being unlocked for doorlock
92         private Table t1 = null;
93
94         /*******************************************************************************************************************************************
95         **
96         **  States data structures
97         **
98         *******************************************************************************************************************************************/
99         // Camera and motion detection
100         private Map<CameraSmart, MotionDetection> camMotionDetect =
101                 new HashMap<CameraSmart, MotionDetection>();
102         // Smartthings sensors (true = motion, leakage, etc.)
103         private Map<Integer, Boolean> senDetectStatus =
104                 new ConcurrentHashMap<Integer, Boolean>();
105         // Camera (true = motion)
106         private Map<CameraSmart, Boolean> camDetectStatus =
107                 new ConcurrentHashMap<CameraSmart, Boolean>();
108         // Doorlock (true = locked)
109         private Map<Integer, Boolean> doorlockStatus =
110                 new ConcurrentHashMap<Integer, Boolean>();
111
112         // Alarm status
113         private Map<Integer, Boolean> alarmStatus =
114                 new HashMap<Integer, Boolean>();
115
116         public HomeSecurityController() {
117
118         }
119
120
121         /*******************************************************************************************************************************************
122         **
123         **  Helper Methods
124         **
125         *******************************************************************************************************************************************/
126
127         /** Method to initialize IoTCloud server (dc-6.calit2.uci.edu)
128          *
129          *   @return [void] None.
130          */
131         private void initIoTCloudServer() {
132
133                 try {
134                         System.out.println("DEBUG: Initialize IoTCloud table!");
135                         // Get and init the IoTCloud server address
136                         // Setup table
137                         t1 = new Table(BASE_URL, PASSWORD, LOCAL_MACHINE_ID, LISTENING_PORT);
138                     t1.initTable();
139                         // Setup is done somewhere else, we just do rebuild()
140                         //t1.rebuild();
141                         System.out.println("DEBUG: Table initialized!");
142                         // Initialize sensors!
143                         // TODO: Still deciding whether to initialize all devices here or inside each init method
144                         int id = 0;
145                         // Initialize alarms! One alarm for now
146                         for(AlarmSmart alarm : alarmSet.values()) {
147                                 createKeyIoTCloud("alarm", NOT_ACTIVE);
148                                 System.out.println("DEBUG: Setting alarm to NOT-ACTIVE!");
149                         }
150                         // TODO: Just use alarm for now as a status to cloud
151                         /*for(SmartthingsSensorSmart smartSensor : smartSensorsSet.values()) {
152                                 
153                                 createKeyIoTCloud("sensor" + Integer.toString(id++), NOT_ACTIVE);
154                                 System.out.println("DEBUG: Setting sensor" + id + " to NOT-ACTIVE!");                           
155                         }
156                         // Initialize cameras! One camera for now...
157                         for(CameraSmart cam : camSet.values()) {
158                                 createKeyIoTCloud("camera", NOT_ACTIVE);
159                                 System.out.println("DEBUG: Setting camera to NOT-ACTIVE!");
160                         }
161                         int doorId = 0;
162                         for(SmartthingsActuatorSmart doorlock : doorlockSet.values()) {
163                                 createKeyIoTCloud("doorlock" + Integer.toString(doorId), NOT_ACTIVE);
164                                 System.out.println("DEBUG: Setting doorlock" + id + " to NOT-ACTIVE!");
165                         }*/
166
167                 } catch(Exception e) {
168                         e.printStackTrace();
169                 }
170                 System.out.println("DEBUG: Cloud server transactions committed successfully!");
171         }
172
173         /** Method to create key IoTCloud
174          *
175          *   @param key                 [String] , encrypted key.
176          *   @param val                         [IoTString] , encrypted value.
177          *
178          *   @return [void] None.
179          */
180         private void createKeyIoTCloud(String key, IoTString val) {
181
182                 try {
183                         IoTString iotKey = new IoTString(key);
184                         t1.update();
185                         t1.createNewKey(iotKey, LOCAL_MACHINE_ID);
186                         t1.startTransaction();
187                         t1.addKV(iotKey, val);
188                         t1.commitTransaction();
189                         t1.update();
190                         System.out.println("DEBUG: Successfully committed transaction for: " + key);
191                 } catch(Exception e) {
192                         e.printStackTrace();
193                 }
194         }
195
196         /** Method to update IoTCloud
197          *
198          *   @param key                 [String] , encrypted key.
199          *   @param val                         [IoTString] , encrypted value.
200          *
201          *   @return [void] None.
202          */
203         private void updateIoTCloud(String key, IoTString val) {
204
205                 try {
206                         IoTString iotKey = new IoTString(key);
207                         t1.update();
208                         t1.startTransaction();
209                         t1.addKV(iotKey, val);
210                         t1.commitTransaction();
211                         t1.update();
212                         System.out.println("DEBUG: Successfully committed transaction for: " + key);
213                 } catch(Exception e) {
214                         e.printStackTrace();
215                 }
216         }
217
218         /** Method to read IoTCloud
219          *
220          *   @param key                 [String] , encrypted key.
221          *   @param val                         [IoTString] , encrypted value.
222          *
223          *   @return [boolean] Check if it is ACTIVE or NOT_ACTIVE (true or false).
224          */
225         private boolean readIoTCloud(String key, IoTString iotTestVal) {
226
227                 t1.update();
228                 IoTString iotKey = new IoTString(key);
229                 IoTString iotVal = t1.getCommitted(iotKey);
230
231                 // Matching value and test value
232                 if ((iotVal != null) && (iotVal.equals(iotTestVal) == true))
233             return true;
234         // Mismatch between value and test value
235         return false;
236         }
237
238         /** Method to initialize Smartthings sensors
239          *
240          *   @return [void] None.
241          */
242         private void initSmartthingsSensors(RoomSmart rm) {
243
244                 // Get and init the IAS sensors for this specific room
245                 HashSet<SmartthingsSensorSmart> sensors = roomSensorRelation.get(rm);
246                 System.out.println("DEBUG: We have " + sensors.size() + " sensors!");
247                 for (SmartthingsSensorSmart sen : sensors) {
248         
249                         try {
250                                 // Initialize sensors
251                                 sen.init();
252                                 System.out.println("DEBUG: Initialized smartthings sensor! ID: " + sensorId + " Room ID: " + rm.getRoomID());
253                                 senDetectStatus.put(sensorId, false);
254                                 System.out.println("DEBUG: Initialized sensor detection to false!");
255                                 // Initialize IoTCloud
256 //                              createKeyIoTCloud("sensor" + Integer.toString(sensorId), NOT_ACTIVE);
257 //                              System.out.println("DEBUG: Setting sensor" + sensorId + " to NOT-ACTIVE!");
258                                 sen.setId(sensorId++);
259                                 sen.registerCallback(this);
260                                 System.out.println("DEBUG: Registered sensor callback!");
261                         } catch (Exception e) {
262                                 e.printStackTrace();
263                         }
264                 }
265         }
266
267
268         /** Method to initialize cameras
269          *
270          *   @return [void] None.
271          */
272         private void initCameras() {
273
274                 // Setup the cameras, start them all and assign each one a motion detector
275                 for (CameraSmart cam : camSet.values()) {
276
277                         // Each camera will have a motion detector unique to it since the motion detection has state
278                         MotionDetection mo = new MotionDetection(12, 0.5f, 10, 10);
279
280                         // initialize the camera, might need to setup some stuff internally
281                         cam.init();
282
283                         // set the camera parameters.
284                         cam.setFPS(CAMERA_FPS);
285                         cam.setResolution(Resolution.RES_VGA);
286
287                         // camera will call the motion detector directly with data not this controller
288                         cam.registerCallback(mo);
289
290                         // Start the camera (example is start the HTTP stream if it is a network camera)
291                         cam.start();
292                         System.out.println("DEBUG: Initialized camera!");
293
294                         // Remember which motion detector is for what camera
295                         camMotionDetect.put(cam, mo);
296
297                         // Initialize detection to false
298                         camDetectStatus.put(cam, false);
299
300                         // Initialize IoTCloud
301 //                      createKeyIoTCloud("camera", NOT_ACTIVE);
302 //                      System.out.println("DEBUG: Setting camera to NOT-ACTIVE!");
303                 }
304         }
305
306
307         /** Method to initialize alarms
308          *
309          *   @return [void] None.
310          */
311         private void initAlarms() {
312
313                 // Get and init the alarm (this single alarm set can serve multiple zones / rooms)
314                 Iterator alarmIt = alarmSet.iterator();
315                 AlarmSmart alm = (AlarmSmart) alarmIt.next();
316                 // Initialize IoTCloud - only 1 alarm
317 //              createKeyIoTCloud("alarm", NOT_ACTIVE);
318 //              System.out.println("DEBUG: Setting alarm to NOT-ACTIVE!");
319                 // Initialize the alarm controller, do it here since it only needs to be done once per controller
320                 try {
321                         alm.init();
322                         System.out.println("DEBUG: Initialized alarm!");
323                         // TODO: Check that this initialization works for multiple times - might be that setZone() only works once!
324                         //for (RoomSmart room : roomSet.values()) {
325                         //      turnOffAlarms(room.getRoomID());
326                         //      System.out.println("DEBUG: Initialized alarm for room (turn off): " + room.getRoomID());
327                         //}
328                 } catch (Exception e) {
329                         e.printStackTrace();
330                 }
331         }
332
333
334         /** Method to initialize doorlocks
335          *
336          *   @return [void] None.
337          */
338         private void initDoorLocks() {
339
340                 // Get and init the doorlocks (we only assume 1 main doorlock)
341                 Set<SmartthingsActuatorSmart> doorlocks = doorlockSet.values();
342                 for (SmartthingsActuatorSmart doorlock : doorlocks) {
343         
344                         try {
345                                 // Initialize doorlocks
346                                 doorlock.init();
347                                 System.out.println("DEBUG: Initialized doorlock! ID: " + doorlockId);
348                                 doorlockStatus.put(doorlockId, false);
349                                 System.out.println("DEBUG: Initialized doorlock status to false!");
350                                 // Initialize IoTCloud
351 //                              createKeyIoTCloud("doorlock" + Integer.toString(doorlockId), NOT_ACTIVE);
352 //                              System.out.println("DEBUG: Setting doorlock to NOT-ACTIVE!");
353                                 doorlock.setId(doorlockId++);
354                                 doorlock.registerCallback(this);
355                                 System.out.println("DEBUG: Registered doorlock callback!");
356                         } catch (Exception e) {
357                                 e.printStackTrace();
358                         }
359                 }
360         }
361
362
363         /** Method to detect if a room has seen motion within the last few seconds (time specified as parameter).
364          *   Checks all the motion detectors for the given room
365          *
366          *   @param _room            [RoomSmart] , Room of interest.
367          *   @param _numberOfSeconds [int]  , Number of seconds in the past that we consider recent.
368          *   @param _upperThreshold  [int]  , Number of seconds as an upper bound before we turn off.
369          *
370          *   @return [boolean] None.
371          */
372         private boolean roomDidHaveMotionRecently(RoomSmart _room, int _numberOfSeconds) {
373                 long currentTimeSeconds = (new Date()).getTime() / 1000;
374
375                 // Loop through all the cameras in the room
376                 for (CameraSmart cam : roomCameraRelation.get(_room)) {
377                         long lastDetectedMotionSeconds = currentTimeSeconds;
378
379                         Date motionTime = ((MotionDetection)camMotionDetect.get(cam)).getTimestampOfLastMotion();
380
381                         // Motion was detected at least once
382                         if (motionTime != null) {
383                                 lastDetectedMotionSeconds = motionTime.getTime() / 1000;
384                         } else {
385                                 // motionTime == null means this is the initialization phase
386                                 // so we put false
387                                 return false;
388                         }
389
390                         // Did detect motion recently
391                         if (Math.abs(currentTimeSeconds - lastDetectedMotionSeconds) < _numberOfSeconds) {
392                                 return true;
393                         }
394                 }
395
396                 return false;
397         }
398
399
400         /** Method to update state data structures for Smartthings sensors
401          *
402          *   @return [void] None.
403          */
404         public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
405
406                 System.out.println("DEBUG: Sensor reading value: " + _value);
407
408                 String sensor = "sensor" + Integer.toString(_sensorId);
409                 if(_activeValue) {
410                         System.out.println("DEBUG: Sensor " + sensorId + " is detecting something: " + _activeValue);
411                         senDetectStatus.put(_sensorId, true);
412                         //updateIoTCloud(sensor, ACTIVE);
413                 } else {
414                         //System.out.println("DEBUG: Sensor " + sensorId + " is not detecting something: " + _activeValue);
415                         senDetectStatus.put(_sensorId, false);
416                         //updateIoTCloud(sensor, NOT_ACTIVE);
417                 }
418         }
419
420         /** Method to update state data structures for Smartthings actuators
421          *
422          *   @return [void] None.
423          */
424         public void newActuatorReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
425
426                 System.out.println("DEBUG: Actuator " + _sensorId + " reading value: " + _value);
427
428                 // Update IoTCloud              
429                 String actuator = "doorlock" + Integer.toString(_sensorId);
430                 if(_activeValue) {
431                         System.out.println("DEBUG: Actuator " + _sensorId + " is detecting something: " + _activeValue);
432                         doorlockStatus.put(_sensorId, true);
433                         //updateIoTCloud(actuator, ACTIVE);
434                 } else {
435                         //System.out.println("DEBUG: Actuator " + _sensorId + " is not detecting something: " + _activeValue);
436                         doorlockStatus.put(_sensorId, false);
437                         //updateIoTCloud(actuator, NOT_ACTIVE);
438                 }
439         }
440
441
442         /** Update the status of all devices
443          *
444          *   @return [void] None.
445          */
446         private void updateUniversalStatus() {
447
448                 // Check for motion in rooms and if there is motion then report
449                 for (RoomSmart room : roomSet.values()) {
450
451                         // Update status of camera
452                         updateCameraStatus(room);
453
454                         // Update status of other devices if any
455                         // ...
456                 }
457         }
458
459
460         /** Update the status of all devices
461          *
462          *   @return [void] None.
463          */
464         private void updateCameraStatus(RoomSmart room) {
465
466                 HashSet<CameraSmart> cameras = roomCameraRelation.get(room);
467                 if (roomDidHaveMotionRecently(room, MOTION_TIME_THRESHOLD)) {
468
469                         // Motion was detected
470                         System.out.println("DEBUG: Camera detected something!");
471                         for(CameraSmart cam : cameras) {
472                                 camDetectStatus.put(cam, true);
473                                 //updateIoTCloud("camera", ACTIVE);
474                         }
475                 } else {
476
477                         // No motion was detected
478                         //System.out.println("DEBUG: Camera didn't detect anything!");
479                         for(CameraSmart cam : cameras) {
480                                 camDetectStatus.put(cam, false);
481                                 //updateIoTCloud("camera", NOT_ACTIVE);
482                         }
483                 }
484         }
485
486         /** Method to turn on alarms
487          *
488          *   @return [void] None.
489          */
490         private void turnOnAlarms(int zoneId) {
491
492                 // Get and init the alarm (this single alarm set can serve multiple zones / rooms)
493                 Iterator alarmIt = alarmSet.iterator();
494                 AlarmSmart alm = (AlarmSmart) alarmIt.next();
495                 alm.setZone(zoneId, true, SECOND_TO_TURN_OFF);
496                 updateIoTCloud("alarm", ACTIVE);
497         }
498
499
500         /** Method to turn off alarms
501          *
502          *   @return [void] None.
503          */
504         private void turnOffAlarms(int zoneId) {
505
506                 // Get and init the alarm (this single alarm set can serve multiple zones / rooms)
507                 Iterator alarmIt = alarmSet.iterator();
508                 AlarmSmart alm = (AlarmSmart) alarmIt.next();
509                 // Turn this alarm off indefinitely
510                 alm.setZone(zoneId, false, SECOND_TO_TURN_ON);
511                 updateIoTCloud("alarm", NOT_ACTIVE);
512         }
513
514
515         /** Method to lock doors
516          *
517          *   @return [void] None.
518          */
519         private void lockDoors() {
520
521                 // Get and lock the doorlocks (we only assume 1 main doorlock)
522                 Set<SmartthingsActuatorSmart> doorlocks = doorlockSet.values();
523                 for (SmartthingsActuatorSmart doorlock : doorlocks) {
524         
525                         doorlock.actuate(LOCK_DOOR);
526                         int doorId = doorlock.getId();
527                         System.out.println("DEBUG: Lock doorlock! ID: " + doorId);
528                         doorlockStatus.put(doorId, true);
529                         //updateIoTCloud("doorlock" + doorId, ACTIVE);
530                 }
531         }
532
533
534         /** Check status of devices and turn on alarm accordingly
535          *  <p>
536          *  Simple rule is whenever any sensor or camera detect something unusual
537          *      (sensor/camera becomes active) then we sound the corresponding alarm.
538          *  This means we send the signal to the right zone in the EspAlarm
539          *
540          *   @return [void] None.
541          */
542         private void decideToTurnOnAlarm() {
543
544                 int zoneId = 0;
545
546                 // Check for motion in rooms and if there is motion then report
547                 for (RoomSmart room : roomSet.values()) {
548
549                         // Loop through all the cameras in the room
550                         for (CameraSmart cam : roomCameraRelation.get(room)) {
551
552                                 // Get the right camera and the right detection status (true or false)
553                                 if (camDetectStatus.get(cam)) {
554                                         zoneId = room.getRoomID();
555                                         turnOnAlarms(zoneId);
556                                         System.out.println("DETECTION: Camera active in room: " + zoneId);
557                                         lockDoors();
558                                         while(readIoTCloud("alarm", ACTIVE)) { 
559                                                 System.out.println("DETECTION: Now alarm is on so wait here until turned off!");
560                                                 try {
561                                                         Thread.sleep(5000); // sleep for a tenth of the time
562                                                 } catch (Exception e) {
563                                                         e.printStackTrace();
564                                                 }
565                                         } // Wait until turned off!
566                                         System.out.println("DETECTION: Now alarm is turned off!");
567                                         cleanUp();
568                                         return;
569                                 }
570                         }
571
572                         // Loop through all the cameras in the room
573                         for (SmartthingsSensorSmart sensor : roomSensorRelation.get(room)) {
574
575                                 // Get the right sensor and the right detection status (true or false)
576                                 //System.out.println("ABOUT TO DETECT: Reading sensor: " + sensor.getId());
577                                 if (senDetectStatus.get(sensor.getId())) {
578                                         zoneId = room.getRoomID();
579                                         turnOnAlarms(zoneId);
580                                         System.out.println("DETECTION: Sensor active in room: " + zoneId);
581                                         System.out.println("DETECTION: Detection by sensor: " + sensor.getId());
582                                         lockDoors();
583                                         while(readIoTCloud("alarm", ACTIVE)) { 
584                                                 System.out.println("DETECTION: Now alarm is on so wait here until turned off!");
585                                                 try {
586                                                         Thread.sleep(5000); // sleep for a tenth of the time
587                                                 } catch (Exception e) {
588                                                         e.printStackTrace();
589                                                 }
590                                         } // Wait until turned off!
591                                         System.out.println("DETECTION: Now alarm is turned off!");
592                                         cleanUp();
593                                         return;
594                                 }
595                         }
596                 }
597         }
598
599
600         /** Clean up all status booleans
601          *  <p>
602          *
603          *   @return [void] None.
604          */
605         private void cleanUp() {
606
607                 // Clear sensor status
608                 for (Boolean senStatus : senDetectStatus.values()) {
609                         senStatus = false;
610                 }
611                 // Clear camera status
612                 for (Boolean camStatus : camDetectStatus.values()) {
613                         camStatus = false;
614                 }
615                 // Clear doorlock status
616                 for (Boolean doorStatus : doorlockStatus.values()) {
617                         doorStatus = false;
618                 }
619                 // Clear alarm status
620                 updateIoTCloud("alarm", NOT_ACTIVE);
621                 // Turn off alaarms
622                 for (RoomSmart room : roomSet.values()) {
623                         int zoneId = room.getRoomID();
624                         turnOffAlarms(zoneId);
625                 }
626         }
627
628
629         /*******************************************************************************************************************************************
630         **
631         **  Public Methods
632         **
633         *******************************************************************************************************************************************/
634
635         /** Initialization method, called by the runtime (effectively the main of the controller)
636          *   This method runs a continuous loop and is blocking
637          *
638          *   @return [void] None;
639          */
640         public void init() {
641
642                 // Initialize IoTCloud server
643                 initIoTCloudServer();
644
645                 // Iterate over the set of rooms
646                 for (RoomSmart rm : roomSet.values()) {
647
648                         // Init all Smartthings sensors
649                         initSmartthingsSensors(rm);
650                         //try {
651                         //      Thread.sleep(5000);
652                         //} catch (Exception e) {
653                         //      e.printStackTrace();
654                         //}
655
656                 }
657                 // Init all doorlocks
658                 initDoorLocks();
659
660                 // Init all alarms
661                 initAlarms();
662
663                 // Init all cameras
664                 initCameras();
665
666                 System.out.println("DEBUG: Initialized all devices! Now starting detection loop!");
667
668                 // Run the main loop that will keep checking the sensors and cameras periodically
669                 while (true) {
670
671                         // Run this code every <specified time>
672                         long currentTimeSeconds = (new Date()).getTime() / 1000;
673                         if ((currentTimeSeconds - lastTimeChecked) > CHECK_TIME_WAIT) {
674                                 lastTimeChecked = currentTimeSeconds;
675
676                                 // Update the status of all devices
677                                 updateUniversalStatus();
678
679                                 // Decide to turn on alarm if any of the sensor/camera detects something unusual
680                                 decideToTurnOnAlarm();
681
682                         } else {
683
684                                 try {
685
686                                         Thread.sleep(CHECK_TIME_WAIT * 100); // sleep for a tenth of the time
687
688                                 } catch (Exception e) {
689
690                                         e.printStackTrace();
691                                 }
692                         }
693
694                 }
695         }
696 }
697
698