From: rtrimana <rtrimana@uci.edu>
Date: Fri, 2 Mar 2018 18:40:07 +0000 (-0800)
Subject: Adjusting back into the original lengthy version of IrrigationController; for testing... 
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=02f34d5ef81b2605f3ee42fe62f0f62a7e292aaf;p=iot2.git

Adjusting back into the original lengthy version of IrrigationController; for testing purposes we can still use the files in testing_version folder
---

diff --git a/benchmarks/Java/IrrigationController/IrrigationController.java b/benchmarks/Java/IrrigationController/IrrigationController.java
index a30bffd..a646ff1 100644
--- a/benchmarks/Java/IrrigationController/IrrigationController.java
+++ b/benchmarks/Java/IrrigationController/IrrigationController.java
@@ -31,15 +31,10 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 	**
 	*******************************************************************************************************************************************/
 	// private static final int NUMBER_OF_TIMES_PER_WEEK_TO_WATER = 2;
-	//TODO: Change these back to normal - this is just for testing to make it awake all the time
-//	private static final int TIME_HOURS_TO_WATER_GRASS = 7;		// 7 am
-	private static final int TIME_HOURS_TO_WATER_GRASS = 3;
-//	private static final int TIME_MINUTES_TO_WATER_GRASS = 30;	// 30 minutes
-	private static final int TIME_MINUTES_TO_WATER_GRASS = 30;
-//	private static final int TIME_TO_RECOVER_GRASS_FOR = 8 * 24 * 60 * 60;	// 8 days
-	private static final int TIME_TO_RECOVER_GRASS_FOR = 10;
-//	private static final int TIME_TO_HIBERNATE_GRASS_FOR = 30 * 24 * 60 * 60;		// 30 days
-	private static final int TIME_TO_HIBERNATE_GRASS_FOR = 10;
+	private static final int TIME_HOURS_TO_WATER_GRASS = 7;		// 7 am
+	private static final int TIME_MINUTES_TO_WATER_GRASS = 30;	// 30 minutes
+	private static final int TIME_TO_RECOVER_GRASS_FOR = 8 * 24 * 60 * 60;	// 8 days
+	private static final int TIME_TO_HIBERNATE_GRASS_FOR = 30 * 24 * 60 * 60;		// 30 days
 	public static final int CAMERA_FPS = 15;													// In frames per second
 
 
@@ -147,12 +142,12 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 			// Seconds since the start of the day to start the watering
 			long secondsForWateringStart = (TIME_HOURS_TO_WATER_GRASS * 3600) + (TIME_MINUTES_TO_WATER_GRASS * 60);
 
-//			System.out.println("beginingOfToday " + beginingOfToday);
-//			System.out.println("secondsSinceStartOfDay " + secondsSinceStartOfDay);
-//			System.out.println("secondsForWateringStart " + secondsForWateringStart);
+			System.out.println("beginingOfToday " + beginingOfToday);
+			System.out.println("secondsSinceStartOfDay " + secondsSinceStartOfDay);
+			System.out.println("secondsForWateringStart " + secondsForWateringStart);
 
 			// check if the current time is within the start watering interval
-			/*if ((secondsSinceStartOfDay < secondsForWateringStart) || (secondsSinceStartOfDay > (secondsForWateringStart + (60 * 60)))) {
+			if ((secondsSinceStartOfDay < secondsForWateringStart) || (secondsSinceStartOfDay > (secondsForWateringStart + (60 * 60)))) {
 				System.out.println("Sleep for 10 minutes.. ");
 				try {
 					//Thread.sleep(10 * 60 * 1000);						// sleep for 10 minutes
@@ -162,11 +157,11 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 				}
 
 				continue;
-			}*/
+			}
 
 			// check if we already checked if we should water today
 			// we only need to do this once per day
-			/*if ((dayOfLastCheck == currentDate.getDate()) && (monthOfLastCheck == currentDate.getMonth())) {
+			if ((dayOfLastCheck == currentDate.getDate()) && (monthOfLastCheck == currentDate.getMonth())) {
 				System.out.println("Sleep for 1 hour...");
 				try {
 					Thread.sleep(60 * 60 * 1000);						// sleep for an hour
@@ -175,7 +170,7 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 				}
 
 				continue;
-			}*/
+			}
 
 			// we decided to check if we should water today so save the fact that we chose to water on this day
 			dayOfLastCheck = currentDate.getDate();
@@ -187,11 +182,11 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 			}
 			// check if we are in hibernation mode and do the correct loop action
 			if (isHibernationMode) {
-//				System.out.println("Hibernation mode!");
+				System.out.println("Hibernation mode!");
 				// If we are in hibernation mode then use the hibernation loop code
 				wateringHibernationLoop(currentDate);
 			} else {
-//				System.out.println("Normal mode!");
+				System.out.println("Normal mode!");
 				// Using the normal watering loop code
 				wateringNormalLoop(currentDate);
 			}
@@ -210,15 +205,6 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 	public void informationRetrieved(double _inchesPerWeek, int _weatherZipCode, int _daysToWaterOn, double _inchesPerMinute) {
 
 		System.out.println("DEBUG: Information is retrieved from phone!!!");
-		/*try {
-			// get the parameters that the interface (phone app) reads from the user
-			inchesPerWeek = _wgw.getInchesPerWeek();
-			weatherZipCode = _wgw.getWeatherZipCode();
-			daysToWaterOn = _wgw.getDaysToWaterOn();
-			inchesPerMinute.add(_wgw.getInchesPerMinute());
-		} catch(RemoteException ex) {
-			ex.printStackTrace();
-		}*/
 
 		inchesPerWeek = _inchesPerWeek;
 		weatherZipCode = _weatherZipCode;
@@ -264,11 +250,6 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 				e.printStackTrace();
 			}
 		}
-		// TODO: Use a phone input interface later
-		/*inchesPerWeek = 20.00;
-		weatherZipCode = 92612;
-		daysToWaterOn = 255;
-		inchesPerMinute.add(1.50);*/
 
 		System.out.println("DEBUG: inchesPerWeek: " + inchesPerWeek);
 		System.out.println("DEBUG: weatherZipCode: " + weatherZipCode);
@@ -282,21 +263,17 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 
 		// Setup the cameras, start them all and assign each one a motion detector
 		for (CameraSmart cam : cameraSet.values()) {
-			//try {
-				// initialize the camera, might need to setup some stuff internally
-				cam.init();
 
-				// set the camera parameters.
-				cam.setFPS(CAMERA_FPS);
-				cam.setResolution(Resolution.RES_VGA);
+			// initialize the camera, might need to setup some stuff internally
+			cam.init();
 
-				// Start the camera (example is start the HTTP stream if it is a network camera)
-				cam.start();
-				System.out.println("DEBUG: Init camera! " + cam.toString());
-			//} catch (RemoteException e) {
-			//	e.printStackTrace();
-			//}
+			// set the camera parameters.
+			cam.setFPS(CAMERA_FPS);
+			cam.setResolution(Resolution.RES_VGA);
 
+			// Start the camera (example is start the HTTP stream if it is a network camera)
+			cam.start();
+			System.out.println("DEBUG: Init camera! " + cam.toString());
 		}
 
 		// counter so that we can match the lawn inches per min data with the specific lawn
@@ -314,12 +291,7 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 				Iterator camIt = cameras.iterator();
 				CameraSmart cam = (CameraSmart)camIt.next();
 				System.out.println("DEBUG: Registering callback to camera: " + cam.toString());
-				//try {
-					// setup the callback
-					cam.registerCallback(mo);
-				//} catch (RemoteException e) {
-				//	e.printStackTrace();
-				//}
+				cam.registerCallback(mo);
 			}
 
 			// we also only need 1 sprinkler controller per lawn so grab the first one
@@ -370,8 +342,6 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 
 		// get the weather data for the next little bit
 		List<DayWeather> weatherData = weatherGrabber.getWeatherData();
-		// TODO: Replace this with the WeatherGrabber.getWeatherData() above
-//		List<DayWeather> weatherData = new ArrayList<DayWeather>();
 
 		// Go through each lawn and check if we should water it and if we should, water it
 		for (LawnState ls : lawns) {
@@ -392,7 +362,7 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 		// if we are in recovery mode then run the recovery action
 		// we are still in hibernation mode but we need to recover the grass
 		if (isInHibernationRecoveryMode) {
-//			System.out.println("DEBUG: Recovery mode!");
+			System.out.println("DEBUG: Recovery mode!");
 			hibernationRecoveryLoop(_currentDate);
 			return;
 		}
@@ -404,7 +374,7 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 			// start recovery mode
 			isInHibernationRecoveryMode = true;
 			hibernationRecoveryModeStartDate = null;
-//			System.out.println("DEBUG: We enter recovery mode for the first time!");
+			System.out.println("DEBUG: We enter recovery mode for the first time!");
 			// first cycle of recovery
 			hibernationRecoveryLoop(_currentDate);
 			return;
@@ -422,7 +392,7 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 			if (!lawnHasMotion) {
 				continue;
 			}
-//			System.out.println("DEBUG: We water the lawn! (wateringHibernationLoop)");
+			System.out.println("DEBUG: We water the lawn! (wateringHibernationLoop)");
 			// water specific lawn since it has motion
 			waterLawn(ls, _currentDate, weatherData);
 		}
@@ -448,7 +418,7 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 		// we have been in recovery mode long enough
 		if (elapsedTime >= TIME_TO_RECOVER_GRASS_FOR) {
 
-//			System.out.println("DEBUG: We have been in recovery mode long enough!");
+			System.out.println("DEBUG: We have been in recovery mode long enough!");
 			// reset the recovery mode
 			isInHibernationRecoveryMode = false;
 			hibernationRecoveryModeStartDate = null;
@@ -470,7 +440,7 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 		// Go through each lawn and check if we should water it and if we should, water it
 		for (LawnState ls : lawns) {
 
-//			System.out.println("DEBUG: We water the lawn! (hibernationRecoveryLoop)");
+			System.out.println("DEBUG: We water the lawn! (hibernationRecoveryLoop)");
 			// water specific lawn since it has motion
 			waterLawn(ls, _currentDate, weatherData);
 		}
@@ -491,10 +461,6 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 		// check if today or tomorrow is a wet day
 		boolean todayIsWetDay = _weatherData.get(0).getIsWetDay();
 		boolean tomorrowIsWetDay = _weatherData.get(1).getIsWetDay();
-		// TODO: Remove this later - hack the values for now!!!
-//		boolean todayIsWetDay = false;
-//		boolean tomorrowIsWetDay = false;
-
 		// lawn cannot wait anymore for water so water not
 		boolean lawnNeedsWaterNow = _ls.needsWateringUrgently(_currentDate);
 		if (lawnNeedsWaterNow) {
@@ -502,10 +468,9 @@ public class IrrigationController extends UnicastRemoteObject implements Weather
 			System.out.println("DEBUG: Is wet day? " + todayIsWetDay);
 			System.out.println("DEBUG: Tomorrow is wet day? " + tomorrowIsWetDay);
 			// if it is not going to rain today then water the lawn
-			// TODO: Put this back to uncommented!!! Only for testing!!!
-//			if (!todayIsWetDay) {
+			if (!todayIsWetDay) {
 				_ls.waterLawn(_currentDate);
-//			}
+			}
 			return;
 		}
 
diff --git a/benchmarks/Java/IrrigationController/LawnState.java b/benchmarks/Java/IrrigationController/LawnState.java
index 10ac4f0..3558354 100644
--- a/benchmarks/Java/IrrigationController/LawnState.java
+++ b/benchmarks/Java/IrrigationController/LawnState.java
@@ -204,8 +204,7 @@ public class LawnState extends UnicastRemoteObject implements MotionDetectionCal
 	public boolean needsWateringUrgently(Date _currentDate) {
 
 		// get difference between now and last time watered
-		// TODO: Remove this to uncommented!!! This is only for testing!!!
-/*		long timeElapsed = (_currentDate.getTime() - lastTimeWatered.getTime()) / 1000;
+		long timeElapsed = (_currentDate.getTime() - lastTimeWatered.getTime()) / 1000;
 
 		// needs watering now urgently
 		if (timeElapsed >= MAX_TIME_BETWEEN_WATERING_SESSIONS) {
@@ -215,7 +214,7 @@ public class LawnState extends UnicastRemoteObject implements MotionDetectionCal
 		// calculate the average moisture readings of all the
 		// sensors in this lawn
 		double averageMoistureValue = getAverageMoistureReading();
-
+		System.out.println("DEBUG: Average moisture value: " + averageMoistureValue);
 		// is a valid average
 		if (averageMoistureValue != -1) {
 			// moisture is very low so we need to water now!
@@ -228,11 +227,6 @@ public class LawnState extends UnicastRemoteObject implements MotionDetectionCal
 		}
 
 		return false;
-*/
-		double averageMoistureValue = getAverageMoistureReading();
-//		System.out.println("DEBUG: Average moisture value: " + averageMoistureValue);
-
-		return true;
 	}
 
 
@@ -502,12 +496,12 @@ public class LawnState extends UnicastRemoteObject implements MotionDetectionCal
 			System.out.println("DEBUG: Current time stamp: " + currentTime.getTime());
 			System.out.println("Time elapsed: " + (currentTime.getTime() - readingTimestamp.getTime()) / 1000);			
 
-			//long timeElapsedSinceLastWatering = (currentTime.getTime() - readingTimestamp.getTime()) / 1000;
+			long timeElapsedSinceLastWatering = (currentTime.getTime() - readingTimestamp.getTime()) / 1000;
 
 			// if reading is old then dont use it since it is noise
-			//if (timeElapsedSinceLastWatering > TWO_HOURS) {
-			//	continue;
-			//}
+			if (timeElapsedSinceLastWatering > TWO_HOURS) {
+				continue;
+			}
 
 			// Do averaging
 			numberOfReadings++;
diff --git a/benchmarks/Java/IrrigationController/test_version/IrrigationController.java b/benchmarks/Java/IrrigationController/test_version/IrrigationController.java
new file mode 100644
index 0000000..909e24c
--- /dev/null
+++ b/benchmarks/Java/IrrigationController/test_version/IrrigationController.java
@@ -0,0 +1,526 @@
+package IrrigationController;
+// Standard Java Packages
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+
+// RMI packages
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+
+// IoT Runtime Packages
+import iotruntime.slave.IoTSet;
+import iotruntime.slave.IoTRelation;
+import iotruntime.slave.IoTAddress;
+import iotcode.annotation.*;
+
+// IoT Driver Packages
+import iotcode.interfaces.*;
+import iotcode.WeatherPhoneGateway.*;
+
+public class IrrigationController extends UnicastRemoteObject implements WeatherGatewayCallback {
+
+
+	/*******************************************************************************************************************************************
+	**
+	**  Constants
+	**
+	*******************************************************************************************************************************************/
+	// private static final int NUMBER_OF_TIMES_PER_WEEK_TO_WATER = 2;
+	//TODO: Change these back to normal - this is just for testing to make it awake all the time
+//	private static final int TIME_HOURS_TO_WATER_GRASS = 7;		// 7 am
+	private static final int TIME_HOURS_TO_WATER_GRASS = 3;
+//	private static final int TIME_MINUTES_TO_WATER_GRASS = 30;	// 30 minutes
+	private static final int TIME_MINUTES_TO_WATER_GRASS = 30;
+//	private static final int TIME_TO_RECOVER_GRASS_FOR = 8 * 24 * 60 * 60;	// 8 days
+	private static final int TIME_TO_RECOVER_GRASS_FOR = 10;
+//	private static final int TIME_TO_HIBERNATE_GRASS_FOR = 30 * 24 * 60 * 60;		// 30 days
+	private static final int TIME_TO_HIBERNATE_GRASS_FOR = 10;
+	public static final int CAMERA_FPS = 15;													// In frames per second
+
+
+	/*******************************************************************************************************************************************
+	**
+	**  Variables
+	**
+	*******************************************************************************************************************************************/
+	private int dayOfLastCheck = -1;
+	private int monthOfLastCheck = -1;
+	private boolean isInHibernationRecoveryMode = false;
+	private Date hibernationRecoveryModeStartDate = null;
+	private boolean isHibernationMode = false;
+	private Date hibernationModeStartDate = null;
+	private List<LawnState> lawns = new ArrayList<LawnState>();
+	private WeatherGrabber weatherGrabber = null;
+
+	// used to block until gui is done and the settings are ready to be polled
+	private AtomicBoolean waitingForInterface = new AtomicBoolean(true);
+
+	// the settings from the interface, used to setup the system
+	private double inchesPerWeek = 0;
+	private int weatherZipCode = 0;
+	private int daysToWaterOn = 0;
+	private List<Double> inchesPerMinute;
+
+	private static int sensorId = 0;
+
+	/*******************************************************************************************************************************************
+	**
+	**  IoT Sets and Relations
+	**
+	*******************************************************************************************************************************************/
+	@config private IoTSet<IoTAddress> weatherDataAddresses;
+	@config private IoTSet<IoTAddress> weatherDataAddressMain;
+	@config private IoTSet<WeatherGatewaySmart> gwSet;
+	@config private IoTSet<LawnSmart> lawnSet;
+	@config private IoTSet<MoistureSensorSmart> moistureSensorsSet;
+	@config private IoTSet<CameraSmart> cameraSet;
+	@config private IoTRelation<LawnSmart, CameraSmart> lawnCameraRelation;
+	@config private IoTRelation<LawnSmart, SprinklerSmart> lawnSprinklerRelation;
+	@config private IoTRelation<LawnSmart, MoistureSensorSmart> lawnMoistureSensorRelation;
+
+
+	public IrrigationController() throws RemoteException {
+
+	}
+
+	/*******************************************************************************************************************************************
+	**
+	**  Public Methods
+	**
+	*******************************************************************************************************************************************/
+
+
+	/** Method to set whether the controller should maintain the lawns in hibernation mode
+	 *   or in normal mode.  Lawns should be put in hibernation mode in drought conditions
+	 *
+	 *   @param _hibMode [boolean] set the hibernation mode for this lawn controllers (true = hibernation)
+	 *
+	 *   @return [void] None.
+	 */
+	public void setHibernationMode(boolean _hibMode) {
+
+		// change hibernation mode status
+		isHibernationMode = _hibMode;
+
+		// set the start date for when we started this hibernation mode
+		if (_hibMode) {
+
+			// make sure we dont reset this cycle
+			if (!isHibernationMode) {
+				hibernationModeStartDate = new Date();
+			}
+		} else {
+			// reset all hibernation stuff
+			hibernationModeStartDate = null;
+			isInHibernationRecoveryMode = false;
+			hibernationRecoveryModeStartDate = null;
+		}
+	}
+
+	/** Method to start the controller and run the main control loop
+	 *
+	 *   @return [void] None.
+	 */
+	public void init() throws RemoteException {
+
+		// initialize the controller
+		initController();
+		System.out.println("Initialized controller!");
+
+		// Main Loop
+		while (true) {
+
+			// get the current time of day (date and time)
+			Date currentDate = new Date();
+
+			// get the epoch time till the beginning of the day
+			Date beginingOfToday = new Date(currentDate.getYear(), currentDate.getMonth(), currentDate.getDate());
+
+			// calculate the seconds since the start of the day.
+			long secondsSinceStartOfDay = (currentDate.getTime() - beginingOfToday.getTime()) / 1000;
+
+			// Seconds since the start of the day to start the watering
+			long secondsForWateringStart = (TIME_HOURS_TO_WATER_GRASS * 3600) + (TIME_MINUTES_TO_WATER_GRASS * 60);
+
+//			System.out.println("beginingOfToday " + beginingOfToday);
+//			System.out.println("secondsSinceStartOfDay " + secondsSinceStartOfDay);
+//			System.out.println("secondsForWateringStart " + secondsForWateringStart);
+
+			// check if the current time is within the start watering interval
+			/*if ((secondsSinceStartOfDay < secondsForWateringStart) || (secondsSinceStartOfDay > (secondsForWateringStart + (60 * 60)))) {
+				System.out.println("Sleep for 10 minutes.. ");
+				try {
+					//Thread.sleep(10 * 60 * 1000);						// sleep for 10 minutes
+					Thread.sleep(10);						// sleep for 10 seconds
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+
+				continue;
+			}*/
+
+			// check if we already checked if we should water today
+			// we only need to do this once per day
+			/*if ((dayOfLastCheck == currentDate.getDate()) && (monthOfLastCheck == currentDate.getMonth())) {
+				System.out.println("Sleep for 1 hour...");
+				try {
+					Thread.sleep(60 * 60 * 1000);						// sleep for an hour
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+
+				continue;
+			}*/
+
+			// we decided to check if we should water today so save the fact that we chose to water on this day
+			dayOfLastCheck = currentDate.getDate();
+			monthOfLastCheck = currentDate.getMonth();
+
+			// update the lawn states everyday
+			for (LawnState ls : lawns) {
+				ls.updateLawn(currentDate);
+			}
+			// check if we are in hibernation mode and do the correct loop action
+			if (isHibernationMode) {
+//				System.out.println("Hibernation mode!");
+				// If we are in hibernation mode then use the hibernation loop code
+				wateringHibernationLoop(currentDate);
+			} else {
+//				System.out.println("Normal mode!");
+				// Using the normal watering loop code
+				wateringNormalLoop(currentDate);
+			}
+		}
+	}
+
+
+	/** Callback method for when the information is retrieved.
+	 *
+	 * @param _inchesPerWeek [double].
+	 * @param _weatherZipCode [int].
+	 * @param _daysToWaterOn [int].
+	 * @param _inchesPerMinute [double].
+	 * @return [void] None.
+	 */
+	public void informationRetrieved(double _inchesPerWeek, int _weatherZipCode, int _daysToWaterOn, double _inchesPerMinute) {
+
+		System.out.println("DEBUG: Information is retrieved from phone!!!");
+		/*try {
+			// get the parameters that the interface (phone app) reads from the user
+			inchesPerWeek = _wgw.getInchesPerWeek();
+			weatherZipCode = _wgw.getWeatherZipCode();
+			daysToWaterOn = _wgw.getDaysToWaterOn();
+			inchesPerMinute.add(_wgw.getInchesPerMinute());
+		} catch(RemoteException ex) {
+			ex.printStackTrace();
+		}*/
+
+		inchesPerWeek = _inchesPerWeek;
+		weatherZipCode = _weatherZipCode;
+		daysToWaterOn = _daysToWaterOn;
+		inchesPerMinute.add(_inchesPerMinute);
+
+		// the gui is done so release the spin wait that was waiting for the gui
+		waitingForInterface.set(false);
+	}
+
+	/*******************************************************************************************************************************************
+	**
+	**  Helper Methods
+	**
+	*******************************************************************************************************************************************/
+
+
+	/** Method to initialize the controller variables and all the drivers and such
+	 *
+	 *   @return [void] None.
+	 */
+	private void initController() throws RemoteException {
+
+		// Setup the weather grabber object with the correct address of the weather api
+		Iterator it = weatherDataAddresses.iterator();
+		weatherGrabber = new WeatherGrabber((IoTAddress)it.next());
+
+		// Initialize inchesPerMinute
+		inchesPerMinute = new ArrayList<Double>();
+
+		// We setup a Gateway object to get information from the phone app
+		for (WeatherGatewaySmart gw : gwSet.values()) {
+			gw.init();
+			gw.registerCallback(this);
+			gw.start();
+		}
+
+		System.out.println("DEBUG: Waiting for phone to send weather information");
+		while (waitingForInterface.get()) {
+			try {
+				Thread.sleep(1000);
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+		// TODO: Use a phone input interface later
+		/*inchesPerWeek = 20.00;
+		weatherZipCode = 92612;
+		daysToWaterOn = 255;
+		inchesPerMinute.add(1.50);*/
+
+		System.out.println("DEBUG: inchesPerWeek: " + inchesPerWeek);
+		System.out.println("DEBUG: weatherZipCode: " + weatherZipCode);
+		System.out.println("DEBUG: daysToWaterOn: " + daysToWaterOn);
+		System.out.println("DEBUG: inchesPerMinute: " + inchesPerMinute.get(0));
+
+		// set the zip code and the the number of days of the weather grabber
+		// here the number of days is set to the max that the grabber supports
+		weatherGrabber.setZipcode(weatherZipCode);
+		weatherGrabber.setNumberOfDays(16);
+
+		// Setup the cameras, start them all and assign each one a motion detector
+		for (CameraSmart cam : cameraSet.values()) {
+
+			// initialize the camera, might need to setup some stuff internally
+			cam.init();
+
+			// set the camera parameters.
+			cam.setFPS(CAMERA_FPS);
+			cam.setResolution(Resolution.RES_VGA);
+
+			// Start the camera (example is start the HTTP stream if it is a network camera)
+			cam.start();
+			System.out.println("DEBUG: Init camera! " + cam.toString());
+		}
+
+		// counter so that we can match the lawn inches per min data with the specific lawn
+		int counter = 0;
+		for (LawnSmart l : lawnSet.values()) {
+			// create a motionDetector for each lawn object
+			MotionDetection mo = new MotionDetection(12, 0.5f, 10, 10);
+
+			// for 1 camera, if there are any then register the camera for that lawn
+			HashSet<CameraSmart> cameras = lawnCameraRelation.get(l);
+			System.out.println("DEBUG: Camera.size(): " + cameras.size());
+			if (cameras.size() >= 1) {
+
+				// we only need 1 camera per lawn so get the first one in the list
+				Iterator camIt = cameras.iterator();
+				CameraSmart cam = (CameraSmart)camIt.next();
+				System.out.println("DEBUG: Registering callback to camera: " + cam.toString());
+				//try {
+					// setup the callback
+					cam.registerCallback(mo);
+				//} catch (RemoteException e) {
+				//	e.printStackTrace();
+				//}
+			}
+
+			// we also only need 1 sprinkler controller per lawn so grab the first one
+			HashSet<SprinklerSmart> sprinklers = lawnSprinklerRelation.get(l);
+			Iterator sprinklersIt = sprinklers.iterator();
+			SprinklerSmart spr = (SprinklerSmart)sprinklersIt.next();
+
+			// init the sprinkler controller, do it here since it only needs to be done once per controller
+			try {
+				spr.init();
+				// Wait until sprinkler is active
+				Thread.sleep(30000);
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+			System.out.println("DEBUG: Init sprinkler: " + spr.toString());
+
+			// get and init the moisture sensors for this specific lawn
+			HashSet<MoistureSensorSmart> sensors = lawnMoistureSensorRelation.get(l);
+			for (MoistureSensorSmart sen : sensors) {
+				System.out.println("DEBUG: Init sensors: " + sen.toString());
+				try {
+					sen.init();
+					sen.setId(sensorId++);
+				} catch (Exception e) {
+					e.printStackTrace();
+				}
+			}
+
+			// create the lawn objects
+			System.out.println("DEBUG: Creating a LawnState object");
+			LawnState ls = 
+				new LawnState(l, daysToWaterOn, mo, inchesPerMinute.get(counter), inchesPerWeek, spr, counter, sensors);
+			lawns.add(ls);
+
+			// dont forget to increment the counter
+			counter++;
+		}
+	}
+
+	/** Main loop for when the controller is watering the lawns under normal conditions, not in hibernation mode
+	 *
+	 *   @param _currentDate [Date] current date
+	 *
+	 *   @return [void] None.
+	 */
+	private void wateringNormalLoop(Date _currentDate) {
+
+		// get the weather data for the next little bit
+		List<DayWeather> weatherData = weatherGrabber.getWeatherData();
+		// TODO: Replace this with the WeatherGrabber.getWeatherData() above
+//		List<DayWeather> weatherData = new ArrayList<DayWeather>();
+
+		// Go through each lawn and check if we should water it and if we should, water it
+		for (LawnState ls : lawns) {
+
+			// water for specific lawn
+			waterLawn(ls, _currentDate, weatherData);
+		}
+	}
+
+	/** Main loop for when the controller is watering the lawns in hibernation mode
+	 *
+	 *   @param _currentDate [Date] current date
+	 *
+	 *   @return [void] None.
+	 */
+	private void wateringHibernationLoop(Date _currentDate) {
+
+		// if we are in recovery mode then run the recovery action
+		// we are still in hibernation mode but we need to recover the grass
+		if (isInHibernationRecoveryMode) {
+//			System.out.println("DEBUG: Recovery mode!");
+			hibernationRecoveryLoop(_currentDate);
+			return;
+		}
+
+		// check if we should enter recovery mode
+		long elapsedTime = (_currentDate.getTime() - hibernationModeStartDate.getTime()) / 1000;
+		if (elapsedTime >= TIME_TO_HIBERNATE_GRASS_FOR) {
+
+			// start recovery mode
+			isInHibernationRecoveryMode = true;
+			hibernationRecoveryModeStartDate = null;
+//			System.out.println("DEBUG: We enter recovery mode for the first time!");
+			// first cycle of recovery
+			hibernationRecoveryLoop(_currentDate);
+			return;
+		}
+
+		// get the weather data for the next little bit
+		List<DayWeather> weatherData = weatherGrabber.getWeatherData();
+
+		// Go through each lawn and check if we should water it and if we should, water it
+		for (LawnState ls : lawns) {
+
+			boolean lawnHasMotion = ls.lawnHasSufficientMotion();
+
+			// there is no motion on the lawn so no need to water it
+			if (!lawnHasMotion) {
+				continue;
+			}
+//			System.out.println("DEBUG: We water the lawn! (wateringHibernationLoop)");
+			// water specific lawn since it has motion
+			waterLawn(ls, _currentDate, weatherData);
+		}
+	}
+
+
+	/** Main loop for when the controller is watering the lawns in hibernation mode
+	 *
+	 *   @param _currentDate [Date] current date
+	 *
+	 *   @return [void] None.
+	 */
+	private void hibernationRecoveryLoop(Date _currentDate) {
+
+		// start recovery mode if it wasnt started yet
+		if (hibernationRecoveryModeStartDate == null) {
+			hibernationRecoveryModeStartDate = _currentDate;
+		}
+
+		// time since this mode was started
+		long elapsedTime = (_currentDate.getTime() - hibernationRecoveryModeStartDate.getTime()) / 1000;
+
+		// we have been in recovery mode long enough
+		if (elapsedTime >= TIME_TO_RECOVER_GRASS_FOR) {
+
+//			System.out.println("DEBUG: We have been in recovery mode long enough!");
+			// reset the recovery mode
+			isInHibernationRecoveryMode = false;
+			hibernationRecoveryModeStartDate = null;
+
+			// revived grass so restart the grass hibernation cycle
+			hibernationModeStartDate = _currentDate;
+
+			// do the hibernation loop since we are no longer in recovery mode
+			wateringHibernationLoop(_currentDate);
+			return;
+		}
+
+
+		// if we got here then we are trying to recover the grass
+
+		// get the weather data for the next little bit
+		List<DayWeather> weatherData = weatherGrabber.getWeatherData();
+
+		// Go through each lawn and check if we should water it and if we should, water it
+		for (LawnState ls : lawns) {
+
+//			System.out.println("DEBUG: We water the lawn! (hibernationRecoveryLoop)");
+			// water specific lawn since it has motion
+			waterLawn(ls, _currentDate, weatherData);
+		}
+
+	}
+
+
+	/** Method for watering a specific lawn if it needs to be watered
+	 *
+	 *   @param _ls [LawnState] lawn to water
+	 *   @param _currentDate [Date] current date
+	 *   @param _weatherData [List<DayWeather>] latest weather data
+	 *
+	 *   @return [void] None.
+	 */
+	private void waterLawn(LawnState _ls, Date _currentDate,  List<DayWeather> _weatherData) {
+
+		// check if today or tomorrow is a wet day
+		boolean todayIsWetDay = _weatherData.get(0).getIsWetDay();
+		boolean tomorrowIsWetDay = _weatherData.get(1).getIsWetDay();
+		// TODO: Remove this later - hack the values for now!!!
+//		boolean todayIsWetDay = false;
+//		boolean tomorrowIsWetDay = false;
+
+		// lawn cannot wait anymore for water so water not
+		boolean lawnNeedsWaterNow = _ls.needsWateringUrgently(_currentDate);
+		if (lawnNeedsWaterNow) {
+			System.out.println("DEBUG: Need water now!!!");
+			System.out.println("DEBUG: Is wet day? " + todayIsWetDay);
+			System.out.println("DEBUG: Tomorrow is wet day? " + tomorrowIsWetDay);
+			// if it is not going to rain today then water the lawn
+			// TODO: Put this back to uncommented!!! Only for testing!!!
+//			if (!todayIsWetDay) {
+				_ls.waterLawn(_currentDate);
+//			}
+			return;
+		}
+
+		// check if this lawn needs watering based on watering algoritm/sensors/ext
+		boolean shouldWaterLawn = _ls.needsWatering(_currentDate);
+
+		// should not water this lawn then just skip to the next lawn
+		if (!shouldWaterLawn) {
+			return;
+		}
+
+		// it is going to rain soon so wait it out.
+		// Grass is not in critical condition so it can wait a bit.
+		if (todayIsWetDay || tomorrowIsWetDay) {
+			return;
+		}
+
+		// if we got here then we need to water the lawn
+		_ls.waterLawn(_currentDate);
+	}
+}
+
diff --git a/benchmarks/Java/IrrigationController/test_version/LawnState.java b/benchmarks/Java/IrrigationController/test_version/LawnState.java
new file mode 100644
index 0000000..10ac4f0
--- /dev/null
+++ b/benchmarks/Java/IrrigationController/test_version/LawnState.java
@@ -0,0 +1,539 @@
+package IrrigationController;
+
+// Standard Java Packages
+import java.util.Date;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.Map;
+
+// RMI packages
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+
+// IoT Driver Packages
+import iotcode.interfaces.*;
+
+// Checker annotations
+//import iotchecker.qual.*;
+
+/** Class LawnState that represents the state of the lawn, also help calculate if the lawn needs to be watered.
+ *
+ * @author      Ali Younis <ayounis @ uci.edu>
+ * @version     1.0
+ * @since       2016-04-04
+ */
+
+public class LawnState extends UnicastRemoteObject implements MotionDetectionCallback, MoistureSensorCallback {
+
+
+	/*******************************************************************************************************************************************
+	**
+	**  Constants
+	**
+	*******************************************************************************************************************************************/
+	private static final long MAX_TIME_BETWEEN_WATERING_SESSIONS = 4 * 24 * 60 * 60;	// 5 days
+	private static final int MAX_DAYS_RAINED_RECORD = 20;
+	private static final int RAINED_RECENTLY_DAYS_INTERVAL = 1;
+	private static final long TWENTY_FIVE_HOURS = 25 * 60 * 60;
+	private static final long TWO_HOURS = 2 * 60 * 60;
+
+	private static final long NEW_MOTION_THRESHOLD = 2 * 60;	// 2 minutes
+	private static final long AMOUNT_OF_MOTION_FOR_ACTIVE = 60 * 60;	// 1 hour
+	private static final long AMOUNT_OF_TIME_FOR_ACTIVE_TO_HOLD = 7 * 24 * 60 * 60;		// 1 week
+
+	private static final double MOISTURE_LEVEL_FOR_NORMAL_WATERING = 25;		// Percentage
+	private static final double MOISTURE_LEVEL_FOR_EMERGENCY_WATERING = 5;	// Percentage
+	private static final double MOISTURE_LEVEL_FOR_NO_WATERING = 80;	// Percentage
+
+	/*******************************************************************************************************************************************
+	**
+	**  Variables
+	**
+	*******************************************************************************************************************************************/
+	private boolean isInHibernationMode = false;
+	private Date lastTimeWatered = null;
+	private boolean didWaterSinceLastSchedualedDate = false;
+	private List<Date> daysRained = new ArrayList<Date>();
+	private int daysToWaterOn = 0;
+	private LawnSmart iotLawnObject;
+	private MotionDetection motionDetector;
+	private double inchesPerMinute = 0;
+	private double inchesPerWeek = 0;
+	private double timePerWatering = 0;
+	private double timePerWeek = 0;
+	private double timeWateredSoFar = 0;
+	private SprinklerSmart sprinkler;
+	private int zone = 0;
+	private Date lastMotionDetectedTime = null;
+	private Date startOfThisMotion = null;
+	private Date lastUpdateDate = null;
+	private Lock mutex = new ReentrantLock();
+	private long totalMotionOnLawn = 0;
+	private long numberOfMotionsOnLawnToday = 0;
+	private boolean lawnIsActive = false;
+	private Date lawnBecameActiceDate = null;
+	private Map<Integer, Double> moistureSensorReadings = 
+		new ConcurrentHashMap<Integer, Double>();
+	private Map<Integer, Date> moistureSensorUpdateTimes = 
+		new ConcurrentHashMap<Integer, Date>();
+
+
+	// 0th bit = Monday, 1th bit = Tuesday ext
+	public LawnState(LawnSmart _l, int _daysToWaterOn, MotionDetection _mo, 
+					double _inchesPerMinute, double _inchesPerWeek, SprinklerSmart _sprinkler, 
+					int _zone, Set<MoistureSensorSmart> _moistureSensors) throws RemoteException {
+		iotLawnObject = _l;
+		daysToWaterOn = _daysToWaterOn;
+		inchesPerMinute = _inchesPerMinute;
+		inchesPerWeek = _inchesPerWeek;
+		sprinkler = _sprinkler;
+		zone = _zone;
+
+		// register the callback with self
+		motionDetector = _mo;
+		_mo.registerCallback(this);
+
+		// register callback to self
+		for (MoistureSensorSmart sen : _moistureSensors) {
+
+			try {
+				sen.registerCallback(this);
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+
+		// parse the days that we are going to water on
+		int numberOfDaysForWatering = 0;
+		for (int i = 0; i < 7; i++) {
+			if ((daysToWaterOn & (1 << i)) > 0) {
+				numberOfDaysForWatering++;
+			}
+		}
+
+		// calculate lawn watering water amounts
+		timePerWeek = _inchesPerWeek / _inchesPerMinute;
+		timePerWatering = timePerWeek / (double)numberOfDaysForWatering;
+	}
+
+	/*******************************************************************************************************************************************
+	**
+	**  Public Methods
+	**
+	*******************************************************************************************************************************************/
+
+
+	/** Method to update the lawn state, updates lawn activity state based on activity timeout
+	 *
+	 *   @param _currentDate  [Date], the current date and time.
+	 *
+	 *   @return [void] None.
+	 */
+	public void updateLawn(Date _currentDate) {
+		if (lastUpdateDate != null) {
+
+			// check if we already did an update today
+			if ((lastUpdateDate.getDate() == _currentDate.getDate())
+					&& (lastUpdateDate.getMonth() == _currentDate.getMonth())
+					&& (lastUpdateDate.getYear() == _currentDate.getYear())) {
+				return;
+			}
+		}
+
+		lastUpdateDate = _currentDate;
+
+		// lawn was active at some time so check if it can be deemed inactive because
+		// time has passed and it has not been active in that time
+		if (lawnBecameActiceDate != null) {
+			long timeElapsed = (_currentDate.getTime() - lawnBecameActiceDate.getTime()) / 1000;
+
+			if (timeElapsed >= AMOUNT_OF_TIME_FOR_ACTIVE_TO_HOLD) {
+				lawnBecameActiceDate = null;
+				lawnIsActive = false;
+			}
+		}
+
+
+		// check activity of lawn
+		boolean isActiveLawn = false;
+		try {
+			mutex.lock();
+			if (totalMotionOnLawn >= AMOUNT_OF_MOTION_FOR_ACTIVE) {
+				isActiveLawn = true;
+			}
+
+			// reset motion counters
+			totalMotionOnLawn = 0;
+			numberOfMotionsOnLawnToday = 0;
+
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		finally {
+			mutex.unlock();
+		}
+
+		// update lawn state
+		if (isActiveLawn) {
+			lawnIsActive = true;
+			lawnBecameActiceDate = _currentDate;
+		}
+	}
+
+
+	/** Method to test if this lawn is active or not.
+	 *
+	 *   @return [Boolean] lawn is active.
+	 */
+	public boolean lawnHasSufficientMotion() {
+		return lawnIsActive;
+	}
+
+
+	/** Method to test if this lawn should be watered or not right now.
+	 *   Lawn urgently needs to be watered right now.
+	 *
+	 *   @param _currentDate  [Date], the current date and time.
+	 *
+	 *   @return [Boolean] lawn does need watering.
+	 */
+	public boolean needsWateringUrgently(Date _currentDate) {
+
+		// get difference between now and last time watered
+		// TODO: Remove this to uncommented!!! This is only for testing!!!
+/*		long timeElapsed = (_currentDate.getTime() - lastTimeWatered.getTime()) / 1000;
+
+		// needs watering now urgently
+		if (timeElapsed >= MAX_TIME_BETWEEN_WATERING_SESSIONS) {
+			return true;
+		}
+
+		// calculate the average moisture readings of all the
+		// sensors in this lawn
+		double averageMoistureValue = getAverageMoistureReading();
+
+		// is a valid average
+		if (averageMoistureValue != -1) {
+			// moisture is very low so we need to water now!
+			if (averageMoistureValue <= MOISTURE_LEVEL_FOR_EMERGENCY_WATERING) {
+				return true;
+			} else if (averageMoistureValue >= MOISTURE_LEVEL_FOR_NO_WATERING) {
+				// moisture is high so no need to water
+				return false;
+			}
+		}
+
+		return false;
+*/
+		double averageMoistureValue = getAverageMoistureReading();
+//		System.out.println("DEBUG: Average moisture value: " + averageMoistureValue);
+
+		return true;
+	}
+
+
+	/** Method to test if this lawn should be watered or not
+	 *
+	 *   @param _currentDate  [Date], the current date and time.
+	 *
+	 *   @return [Boolean] lawn does need watering.
+	 */
+	public boolean needsWatering(Date _currentDate) {
+
+		// only check if we have watered since the last date
+		if (didWaterSinceLastSchedualedDate) {
+			// get the day of the week from the date and convert it to be
+			// 0=Monday, 1=Sunday, ....
+			int dayOfWeek = _currentDate.getDay();
+			dayOfWeek = (dayOfWeek - 1) % 7;
+
+			// Calculate what we should mask out days to water byte to see if it is a 1
+			int mask = (1 << dayOfWeek);
+
+			// mask the bye
+			int shouldWaterToday = daysToWaterOn & mask;
+
+			// if the post masked data is 0 then we should not water today since that bit was not set to 1
+			// do not water today
+			if (shouldWaterToday == 0) {
+				return false;
+			}
+
+		}
+
+		// it is a scheduled day so we need to water soon;
+		didWaterSinceLastSchedualedDate = false;
+
+		// check if it rained in the last little bit so there is no need to water this grass right now.
+		if (didRainRecently(_currentDate, RAINED_RECENTLY_DAYS_INTERVAL)) {
+			return false;
+		}
+
+		// The grass was never watered before so water now
+		if (lastTimeWatered == null) {
+			return true;
+		}
+
+		// calculate the average moisture readings of all the
+		// sensors in this lawn
+		double averageMoistureValue = getAverageMoistureReading();
+
+		// is a valid average
+		if (averageMoistureValue != -1) {
+			// moisture is low enough to need to water now
+			if (averageMoistureValue <= MOISTURE_LEVEL_FOR_NORMAL_WATERING) {
+				return true;
+			} else if (averageMoistureValue >= MOISTURE_LEVEL_FOR_NO_WATERING) {
+				// moisture is high so no need to water
+				return false;
+			}
+		}
+
+		// if got here then no condition says we should not water today so we should
+		// water the grass today
+		return true;
+	}
+
+
+	/** Method to get the date of the last time the lawn was watered
+	 *
+	 *   @return [Date] date of last watering.
+	 */
+	public Date getLastTimeWatered() {
+		return lastTimeWatered;
+	}
+
+	/** Method to keep track of the last few times it rained on this lawn
+	 *
+	 *   @param _dateOfRain  [Date], the date of the rain.
+	 *
+	 *   @return [void] None.
+	 */
+	public void rainedOnDate(Date _dateOfRain) {
+
+		// the grass was technically watered on this day
+		lastTimeWatered = _dateOfRain;
+
+		didWaterSinceLastSchedualedDate = true;
+
+		// it rained on this date
+		daysRained.add(_dateOfRain);
+
+		// only keep the last 20 days that it rained
+		if (daysRained.size() > 20) {
+			daysRained.remove(0);
+		}
+
+	}
+
+
+	/** Method to water lawn, calculates how much to water and sends water signal to controller
+	 *
+	 *   @param _currentDate  [Date], the current date and time.
+	 *
+	 *   @return [void] None.
+	 */
+	public void waterLawn(Date _currentDate) {
+		lastTimeWatered = _currentDate;
+		didWaterSinceLastSchedualedDate = true;
+
+		// get the day of the week from the date and convert it to be
+		// 0=Monday, 1=Sunday, ....
+		int dayOfWeek = _currentDate.getDay();
+		dayOfWeek = (dayOfWeek - 1) % 7;
+
+
+		// check if it is the last day to water for this week
+		boolean isLastDay = true;
+		for (int i = 6; i > dayOfWeek; i--) {
+			int mask = (1 << dayOfWeek);
+
+			int shouldWaterToday = daysToWaterOn & mask;
+
+			if (shouldWaterToday != 0) {
+				isLastDay = false;
+				break;
+			}
+		}
+
+
+		int secondsToWater = 0;
+		if (isLastDay) {
+
+			// last day of week to water so water the remaining amount
+			double minutesToWater = timePerWeek - timeWateredSoFar;
+			timeWateredSoFar = 0;
+			secondsToWater = (int)((double)(minutesToWater * 60));
+
+		} else {
+
+			// if it is not the last day then just water a normal amount
+			timeWateredSoFar += timePerWatering;
+			secondsToWater = (int)((double)(timePerWatering * 60));
+		}
+
+		try {
+			System.out.println("DEBUG: We water the lawn!!! Zone: " + zone + " Seconds to water: " + secondsToWater);
+			sprinkler.setZone(zone, true, secondsToWater);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+	}
+
+	/** Method callback from the motion detection callback interface, processes the motion
+	 *  to see how long the motion was and saves that motion.
+	 *
+	 *   @param _md  [MotionDetection], motion detector with the motion
+	 *
+	 *   @return [void] None.
+	 */
+	public void motionDetected(long timeStampOfLastMotion) {
+
+		Date currMotTime = new Date(timeStampOfLastMotion);
+
+		if (lastMotionDetectedTime == null) {
+			lastMotionDetectedTime = currMotTime;
+		}
+
+		if (startOfThisMotion == null) {
+			startOfThisMotion = currMotTime;
+		}
+
+		long timeElapsed = (currMotTime.getTime() - lastMotionDetectedTime.getTime()) / 1000;
+
+		if (timeElapsed >= NEW_MOTION_THRESHOLD) {
+			try {
+				mutex.lock();
+				long motiontime = (lastMotionDetectedTime.getTime() - startOfThisMotion.getTime()) / 1000;
+				totalMotionOnLawn += motiontime;
+				numberOfMotionsOnLawnToday++;
+
+
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+			finally {
+				mutex.unlock();
+			}
+
+			startOfThisMotion = currMotTime;
+		}
+
+		lastMotionDetectedTime = currMotTime;
+	}
+
+
+	/** Callback method for when a new moisture reading is available.
+	 *   Called when a new reading is ready by the sensor and the sensor
+	 *   can be checked for the frame data.
+	 *
+	 *   @param _sensor [MoistureSensor] .
+	 *
+	 *   @return [void] None.
+	 */
+	public void newReadingAvailable(int sensorId, float moisture, long timeStampOfLastReading) {
+
+		moistureSensorReadings.put(sensorId, (double) moisture);
+		moistureSensorUpdateTimes.put(sensorId, new Date(timeStampOfLastReading));
+	}
+
+
+	/*******************************************************************************************************************************************
+	**
+	**  Helper Methods
+	**
+	*******************************************************************************************************************************************/
+
+	/** Method to check if it rained recently in the near past.
+	 *
+	 *   @param _numberOfDaysInPast  [long], number of days in the past to check if it rained recently.
+	 *   @param _currentDate  [Date], the current date and time.
+	 *
+	 *   @return [boolean] weather it rained recently or not.
+	 */
+	private boolean didRainRecently(Date _currentDate, long _numberOfDaysInPast) {
+
+		// it never rained before
+		if (daysRained.size() == 0) {
+			return false;
+		}
+
+		// convert the days to seconds for calculation
+		long numberOfSecondsInPast = _numberOfDaysInPast * 24 * 60 * 60;
+
+		// go through all the stored days that it rained on
+		for (Date d : daysRained) {
+
+			// check the difference time and convert to seconds.
+			long numberOfSecondsDifference = (_currentDate.getTime() - d.getTime()) / 1000;
+
+			// if it rained in the last specified time then return true
+			if (numberOfSecondsDifference < numberOfSecondsInPast) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+
+	/** Method calculate the average moisture readings of the most recent moisture reading of each sensor
+	 *   if that reading is not stale
+	 *
+	 *   @return [double] average value of moisture readings.
+	 */
+	private double getAverageMoistureReading() {
+
+		Date currentTime = new Date();
+		double total = 0;
+		int numberOfReadings = 0;
+
+		for (Integer sen : moistureSensorReadings.keySet()) {
+
+			// check the timestamp of the watering of the lawn
+			Date readingTimestamp = moistureSensorUpdateTimes.get(sen);
+
+			System.out.println("DEBUG: Sensor reading time stamp: " + readingTimestamp.getTime());
+			System.out.println("DEBUG: Current time stamp: " + currentTime.getTime());
+			System.out.println("Time elapsed: " + (currentTime.getTime() - readingTimestamp.getTime()) / 1000);			
+
+			//long timeElapsedSinceLastWatering = (currentTime.getTime() - readingTimestamp.getTime()) / 1000;
+
+			// if reading is old then dont use it since it is noise
+			//if (timeElapsedSinceLastWatering > TWO_HOURS) {
+			//	continue;
+			//}
+
+			// Do averaging
+			numberOfReadings++;
+			total += moistureSensorReadings.get(sen);
+
+			System.out.println("DEBUG: Sensor reading value: " + moistureSensorReadings.get(sen) + " with total: " + total);
+		}
+
+
+		// if no readings were valid then return -1 so that we can signal that moisture cannot be used for now
+		if (numberOfReadings == 0) {
+			return -1;
+		}
+
+		// return the calculated average of all the recent moisture readings
+		return total / (double)numberOfReadings;
+	}
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/benchmarks/drivers/Java/BlossomSprinkler/BlossomSprinkler.java b/benchmarks/drivers/Java/BlossomSprinkler/BlossomSprinkler.java
index dc05c0d..209b2fe 100644
--- a/benchmarks/drivers/Java/BlossomSprinkler/BlossomSprinkler.java
+++ b/benchmarks/drivers/Java/BlossomSprinkler/BlossomSprinkler.java
@@ -90,7 +90,6 @@ public class BlossomSprinkler implements Sprinkler {
 
         // create the correct number of zones for this controller
         for (int i = 0; i < NUMBER_OF_ZONES; i++) {
-            //zoneStates.add(new ZoneState(i, false, 0));
 			ZoneState zTmp = new ZoneState();
 			zTmp.zoneNumber = i;
 			zTmp.onOffState = false;
@@ -123,7 +122,6 @@ public class BlossomSprinkler implements Sprinkler {
                 {
                     // We replaced methods with fields
 			        //z.zoneNumber, z.onOffState z.duration
-                    //if (z.getZoneNumber() == _zone) {
                     if (z.zoneNumber == _zone) {
 
                         // turn on or off the valve
@@ -206,10 +204,7 @@ public class BlossomSprinkler implements Sprinkler {
             try {
                 zoneStateMutex.acquire();
                 for (ZoneState z : zoneStates) {
-					//System.out.println("Iterating on zone: " + z.zoneNumber);
                     if (z.onOffState) {
-						//System.out.println("Turning on zone: " + z.zoneNumber);
-						//System.out.println("Duration: " + z.duration);
                         // if on and time has expired then turn off
                         if (z.duration == 0) {