4f1c915e9b50de1ca76713c2004fada6b05cf3af
[iot2.git] / benchmarks / Java / SmartLightsController / SmartLightsController.java
1 package SmartLightsController;
2
3 // IoT Runtime packages
4 import iotruntime.slave.IoTSet;
5 import iotruntime.slave.IoTRelation;
6
7 // IoT driver packages
8 import iotcode.interfaces.*;
9 import iotcode.annotation.*;
10
11
12 // Standard Java packages
13 import java.util.HashMap;
14 import java.util.Map;
15 import java.util.Date;  // TODO: Get rid of all depreciated stuff for date, switch to Calender
16 import java.util.concurrent.Semaphore;
17
18 // RMI packages
19 import java.rmi.RemoteException;
20
21 // Checker annotations
22 //import iotchecker.qual.*;
23
24 /** Class Smart Lights Controller for the smart home application benchmark
25  *
26  * @author      Ali Younis <ayounis @ uci.edu>
27  * @version     1.0
28  * @since       2016-01-27
29  */
30 public class SmartLightsController {
31
32         /*
33          *  Constants
34          */
35         public static final int MOTION_TIME_THRESHOLD = 60;     // in seconds
36         public static final int CHECK_TIME_WAIT = 1;                    // in seconds
37         public static final int COLOR_TEMP_MIN_KELVIN = 2500;   // In Kelvin
38         public static final int COLOR_TEMP_MAX_KELVIN = 9000;   // In Kelvin
39         public static final int CAMERA_FPS = 15;                                // In frames per second
40
41         /*
42          *  IoT Sets of Devices
43          */
44         @config private IoTSet<LightBulbSmart> mainRoomLightBulbs;
45         @config private IoTSet<CameraSmart> cameras;
46
47         /*
48          *  IoT Sets of Things that are not devices such as rooms
49          */
50         @config private IoTSet<RoomSmart> rooms;
51
52         /*
53          *  IoT Relations
54          */
55         @config private IoTRelation<RoomSmart,CameraSmart> roomCameraRel;
56         @config private IoTRelation<RoomSmart,LightBulbSmart> roomMainBulbRel;
57
58
59         /*
60          *  The state that the room main lights are supposed to be in
61          */
62         Map<RoomSmart, Boolean> roomLightOnOffStatus =
63                 new HashMap<RoomSmart, Boolean>();
64         Map<RoomSmart, ColorTemperature> roomLightColorTemperature =
65                 new HashMap<RoomSmart, ColorTemperature>();
66
67         /*
68          *  Motion detectors that are bound to specific cameras
69          */
70         private Map<CameraSmart, MotionDetection>
71         camMotionDetect = new HashMap<CameraSmart, MotionDetection>();
72
73
74         /*******************************************************************************************************************************************
75         **
76         **  Variables
77         **
78         *******************************************************************************************************************************************/
79         long lastTimeChecked = 0;
80
81         boolean print830 = true;
82         boolean print1030 = true;
83         boolean print730 = true;
84         boolean print930 = true;
85         boolean printNite = true;
86
87         /*******************************************************************************************************************************************
88         **
89         ** Private Helper Methods
90         **
91         *******************************************************************************************************************************************/
92
93         /** Method to detect if a room has seen motion within the last few seconds (time specified as parameter).
94          *   Checks all the motion detectors for the given room
95          *
96          *   @param _room            [RoomSmart] , RoomSmart of interest.
97          *   @param _numberOfSeconds [int]  , Number of seconds in the past that we consider recent.
98          *   @param _upperThreshold  [int]  , Number of seconds as an upper bound before we turn off.
99          *
100          *   @return [boolean] if motion was detected recently.
101          */
102         private boolean roomDidHaveMotionRecently(RoomSmart _room, int _numberOfSeconds) {
103                 long currentTimeSeconds = (new Date()).getTime() / 1000;
104
105                 // Loop through all the motion sensors in the room
106                 for (CameraSmart cam : roomCameraRel.get(_room)) {
107                         long lastDetectedMotionSeconds = currentTimeSeconds;
108
109                         Date motionTime = ((MotionDetection)camMotionDetect.get(cam)).getTimestampOfLastMotion();
110
111                         // Motion was detected at least once
112                         if (motionTime != null) {
113                                 lastDetectedMotionSeconds = motionTime.getTime() / 1000;
114                         } else {
115                                 // motionTime == null means this is the initialization phase
116                                 // so we return false to initialize the lightbulbs to off
117                                 return false;
118                         }
119
120                         // Did detect motion recently
121                         if (Math.abs(currentTimeSeconds - lastDetectedMotionSeconds) < _numberOfSeconds) {
122                                 return true;
123                         }
124                 }
125
126                 return false;
127         }
128
129
130
131         /**  Set the temperature of the room based on the time of day.
132          *  Do this to make sure people are able to get a good nights sleep.
133          *  based on this: https://justgetflux.com/research.html
134          *
135          *   @return [void] None;
136          */
137         private void setRoomColorTemperatureForSleep() throws RemoteException {
138
139                 long currentTimeSeconds = (new Date()).getTime() / 1000;
140                 Date today = new Date();
141                 Date beginningOfToday = new Date(today.getYear(),
142                         today.getMonth(), today.getDate());
143
144                 long secondsSinceStartOfDay = currentTimeSeconds - (beginningOfToday.getTime() / 1000);
145
146                 for (RoomSmart room : rooms.values()) {
147
148                         // before 8:30 am
149                         if (secondsSinceStartOfDay <= 30600) {
150                                 ColorTemperature colTemp = roomLightColorTemperature.get(room);
151                                 colTemp.temperature = COLOR_TEMP_MIN_KELVIN;
152                                 roomLightColorTemperature.put(room, colTemp);
153
154                                 if (print830) {
155                                         System.out.println("Before 8:30am!");
156                                         System.out.println("Color temperature: " + colTemp.temperature);
157                                         print830 = false;
158                                         print1030 = true;
159                                         print730 = true;
160                                         print930 = true;
161                                         printNite = true;
162                                 }
163
164                         } else if ((secondsSinceStartOfDay > 30600) && (secondsSinceStartOfDay < 37800)) {
165                                 // 8:30am - 10:30 am
166                                 // Slowly turn lights from warm to work white
167                                 double newKelvinValue = (double) (secondsSinceStartOfDay - 30600) / (37800 - 30600);
168                                 newKelvinValue = (newKelvinValue * (COLOR_TEMP_MAX_KELVIN - COLOR_TEMP_MIN_KELVIN)) + COLOR_TEMP_MIN_KELVIN;
169                                 ColorTemperature colTemp = roomLightColorTemperature.get(room);
170                                 colTemp.temperature = (int)newKelvinValue;
171                                 roomLightColorTemperature.put(room, colTemp);
172
173                                 if (print1030) {
174                                         System.out.println("8:30am - 10:30am!");
175                                         print830 = true;
176                                         print1030 = false;
177                                         print730 = true;
178                                         print930 = true;
179                                         printNite = true;
180                                 }
181
182                         } else if ((secondsSinceStartOfDay > 37800 ) && (secondsSinceStartOfDay < 70200)) {
183                                 // Between 10:30am and 7:30pm
184                                 // Keep white Work Light
185                                 ColorTemperature colTemp = roomLightColorTemperature.get(room);
186                                 colTemp.temperature = COLOR_TEMP_MAX_KELVIN;
187                                 roomLightColorTemperature.put(room, colTemp);
188
189                                 if (print730) {
190                                         System.out.println("10:30am - 7:30pm!");
191                                         System.out.println("Color temperature: " + colTemp.temperature);
192                                         print830 = true;
193                                         print1030 = true;
194                                         print730 = false;
195                                         print930 = true;
196                                         printNite = true;
197                                 }
198
199                         } else if ((secondsSinceStartOfDay > 70200) && (secondsSinceStartOfDay < 77400)) {
200                                 // Between 7:30pm and 9:30pm
201                                 // Slowly turn lights from work to warm
202                                 double newKelvinValue = (double) (secondsSinceStartOfDay - 30600) / (37800 - 30600);
203                                 newKelvinValue = (newKelvinValue * (COLOR_TEMP_MAX_KELVIN - COLOR_TEMP_MIN_KELVIN)) + COLOR_TEMP_MIN_KELVIN;
204                                 ColorTemperature colTemp = roomLightColorTemperature.get(room);
205                                 colTemp.temperature = (int)newKelvinValue;
206                                 roomLightColorTemperature.put(room, colTemp);
207
208                                 if (print930) {
209                                         System.out.println("7:30pm - 9:30pm!");
210                                         print830 = true;
211                                         print1030 = true;
212                                         print730 = true;
213                                         print930 = false;
214                                         printNite = true;
215                                 }
216
217                         } else if (secondsSinceStartOfDay > 77400) {
218                                 // past 9:30pm
219                                 // Keep warm Light
220                                 ColorTemperature colTemp = roomLightColorTemperature.get(room);
221                                 colTemp.temperature = COLOR_TEMP_MIN_KELVIN;
222                                 roomLightColorTemperature.put(room, colTemp);
223
224                                 if (printNite) {
225                                         System.out.println("After 9:30pm!");
226                                         System.out.println("Color temperature: " + colTemp.temperature);
227                                         print830 = true;
228                                         print1030 = true;
229                                         print730 = true;
230                                         print930 = true;
231                                         printNite = false;
232                                 }
233                         }
234                 }
235         }
236
237
238
239         /** Sets bulbs to the proper state.  Sets the On/Off state as well as the color.
240          * The method changes the state of the bulb.  It does not calculate what the state
241          * of the bulb should be, this is done elsewhere.
242          *
243          * When setting the color of the bulb, a best attempt effort is made.  If the needed
244          * temperature and color of the bulb is outside the bulb range then the system gets
245          * as close as it can
246          *
247          *   @return [void] None;
248          */
249         private void setMainBulbs() throws RemoteException {
250
251                 for (RoomSmart room : rooms.values()) {
252
253                         // Lights in room should be turned off
254                         if (!roomLightOnOffStatus.get(room)) {
255
256                                 // turn the bulbs off if they are on
257                                 for (LightBulbSmart bulb : roomMainBulbRel.get(room)) {
258                                         if (bulb.getState()) {
259                                                 bulb.turnOff();
260                                                 System.out.println("SmartLightsController: Send off signal!!!");
261                                         }
262                                 }
263
264                         } else {
265
266                                 // Lights in room should be turned on
267                                 // set the color of the bulbs
268                                 ColorTemperature colTemp = roomLightColorTemperature.get(room);
269                                 for (LightBulbSmart bulb : roomMainBulbRel.get(room)) {
270                                         // Turn on the bulb if they are off
271                                         if (!bulb.getState()) {
272                                                 bulb.turnOn();
273                                                 System.out.println("SmartLightsController: Send on signal!!!");
274                                         }
275
276                                         // Get the requested color of the room
277                                         double hue = colTemp.hue;
278                                         double saturation = colTemp.saturation;
279                                         double brightness = colTemp.brightness;
280                                         int temperature = colTemp.temperature;
281
282                                         // Make sure hue is in range that light bulb supports
283                                         if (hue < bulb.getHueRangeLowerBound()) {
284                                                 hue = bulb.getHueRangeLowerBound();
285                                         } else if (hue > bulb.getHueRangeUpperBound()) {
286                                                 hue = bulb.getHueRangeUpperBound();
287                                         }
288
289                                         // Make sure saturation is in range that light bulb supports
290                                         if (saturation < bulb.getSaturationRangeLowerBound()) {
291                                                 saturation = bulb.getSaturationRangeLowerBound();
292                                         } else if (saturation > bulb.getSaturationRangeUpperBound()) {
293                                                 saturation = bulb.getSaturationRangeUpperBound();
294                                         }
295
296                                         // Make sure brightness is in range that light bulb supports
297                                         if (brightness < bulb.getBrightnessRangeLowerBound()) {
298                                                 brightness = bulb.getBrightnessRangeLowerBound();
299                                         } else if (brightness > bulb.getBrightnessRangeUpperBound()) {
300                                                 brightness = bulb.getBrightnessRangeUpperBound();
301                                         }
302
303                                         // Make sure temperature is in range that light bulb supports
304                                         if (temperature < bulb.getTemperatureRangeLowerBound()) {
305                                                 temperature = bulb.getTemperatureRangeLowerBound();
306                                         } else if (temperature > bulb.getTemperatureRangeUpperBound()) {
307                                                 temperature = bulb.getTemperatureRangeUpperBound();
308                                         }
309
310                                         // Actually set the bulb to that color and temp
311                                         bulb.setColor(hue, saturation, brightness);
312                                         bulb.setTemperature(temperature);
313                                 }
314                         }
315                 }
316         }
317
318
319         /********************************************************************************************************
320         ** Public methods, called by the runtime
321         *********************************************************************************************************/
322
323         /** Initialization method, called by the runtime (effectively the main of the controller)
324          *   This method runs a continuous loop and is blocking
325          *
326          *   @return [void] None;
327          */
328         public void init() throws RemoteException, InterruptedException {
329
330                 System.out.println("Initialized init()!");
331                 // Initialize the rooms
332                 for (RoomSmart room : rooms.values()) {
333
334                         // All rooms start with the lights turned off
335                         roomLightOnOffStatus.put(room, false);
336
337                         // All rooms have a default color and temperature
338                         roomLightColorTemperature.put(room, new ColorTemperature(0, 0, 100, 2500));
339                 }
340                 System.out.println("Initialized rooms!");
341
342                 // Setup the cameras, start them all and assign each one a motion detector
343 /*              for (CameraSmart cam : cameras.values()) {
344
345                         // Each camera will have a motion detector unique to it since the motion detection has state
346                         MotionDetection mo = new MotionDetection(12, 0.5f, 10, 10);
347
348                         // initialize the camera, might need to setup some stuff internally
349                         cam.init();
350
351                         // set the camera parameters.
352                         cam.setFPS(CAMERA_FPS);
353                         cam.setResolution(Resolution.RES_VGA);
354
355                         // camera will call the motion detector directly with data not this controller
356                         cam.registerCallback(mo);
357
358                         // Start the camera (example is start the HTTP stream if it is a network camera)
359                         cam.start();
360
361                         // Remember which motion detector is for what camera
362                         camMotionDetect.put(cam, mo);
363                 }
364                 System.out.println("Initialized cameras!");
365 */
366                 System.out.println("Skipped cameras!");
367
368                 //Initialize the light-bulbs, will turn off the bulb
369                 for (LightBulbSmart bulb : mainRoomLightBulbs.values()) {
370                         System.out.println("Trying to init bulb?");
371                         bulb.init();
372                         System.out.println("Done init!");
373                         Thread.sleep(1000);
374                 }
375                 System.out.println("Initialized bulbs!");
376                 
377                 System.out.println("STOP here until we have 2 more working cameras!");
378                 while (true) { }
379
380                 // Run the main loop that will keep check the bulbs and rooms periodically
381 /*              while (true) {
382
383                         // Run this code every <specified time>
384                         long currentTimeSeconds = (new Date()).getTime() / 1000;
385                         if ((currentTimeSeconds - lastTimeChecked) > CHECK_TIME_WAIT) {
386                                 lastTimeChecked = currentTimeSeconds;
387
388                                 // Check for motion in rooms and if there is motion then turn on the lights
389                                 for (RoomSmart room : rooms.values()) {
390
391                                         if (roomDidHaveMotionRecently(room, MOTION_TIME_THRESHOLD)) {
392
393                                                 // Motion was detected
394                                                 roomLightOnOffStatus.put(room, true);
395
396                                         } else {
397
398                                                 // No motion was detected
399                                                 roomLightOnOffStatus.put(room, false);
400
401                                         }
402                                 }
403
404                                 // Check what the temperature of the light in the room should be
405                                 setRoomColorTemperatureForSleep();
406
407                                 // Set the bulbs to the new values
408                                 setMainBulbs();
409
410                         } else {
411                                 try {
412                                         Thread.sleep(CHECK_TIME_WAIT * 100); // sleep for a tenth of the time
413                                 } catch (Exception e) {
414
415                                 }
416                         }
417
418                 }*/
419         }
420 }
421
422
423
424