--- /dev/null
+package HomeSecurityController;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class AlarmSmart_Stub implements AlarmSmart {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private final static int objectId = 0;
+
+
+ public AlarmSmart_Stub(int _port, String _skeletonAddress, String _callbackAddress, int _rev, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ ports = _ports;
+ rmiCall = new IoTRMICall(_port, _skeletonAddress, _rev);
+ }
+
+ public boolean doesHaveZoneTimers() {
+ int methodId = 4;
+ Class<?> retType = boolean.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ return (boolean)retObj;
+ }
+
+ public List<ZoneState> getZoneStates() {
+ int methodId = 2;
+ Class<?> retType = int.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ Object retLenObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ int retLen = (int) retLenObj;
+ Class<?>[] retCls = new Class<?>[3*retLen];
+ Class<?>[] retClsVal = new Class<?>[3*retLen];
+ int retPos = 0;
+ for(int i = 0; i < retLen; i++) {
+ retCls[retPos] = int.class;
+ retClsVal[retPos++] = null;
+ retCls[retPos] = boolean.class;
+ retClsVal[retPos++] = null;
+ retCls[retPos] = int.class;
+ retClsVal[retPos++] = null;
+ }
+ Object[] retObj = rmiCall.getStructObjects(retCls, retClsVal);
+ List<ZoneState> structRet = new ArrayList<ZoneState>();
+ int retObjPos = 0;
+ for(int i = 0; i < retLen; i++) {
+ ZoneState structRetMem = new ZoneState();
+ structRetMem.zoneNumber = (int) retObj[retObjPos++];
+ structRetMem.onOffState = (boolean) retObj[retObjPos++];
+ structRetMem.duration = (int) retObj[retObjPos++];
+ structRet.add(structRetMem);
+ }
+ return structRet;
+ }
+
+ public void init() {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+ public void setZone(int _zone, boolean _onOff, int _onDurationSeconds) {
+ int methodId = 1;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int.class, boolean.class, int.class };
+ Object[] paramObj = new Object[] { _zone, _onOff, _onDurationSeconds };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+ public int getNumberOfZones() {
+ int methodId = 3;
+ Class<?> retType = int.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ return (int)retObj;
+ }
+
+}
--- /dev/null
+package HomeSecurityController;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class CameraCallback_CallbackSkeleton implements CameraCallback {
+
+ private CameraCallback mainObj;
+ private int objectId = 0;
+ private String callbackAddress;
+
+
+ public CameraCallback_CallbackSkeleton(CameraCallback _mainObj, String _callbackAddress, int _objectId) throws Exception {
+ callbackAddress = _callbackAddress;
+ mainObj = _mainObj;
+ objectId = _objectId;
+ }
+
+ public void newCameraFrameAvailable(byte latestFrame[], long timeStamp) {
+ mainObj.newCameraFrameAvailable(latestFrame, timeStamp);
+ }
+
+ public void ___newCameraFrameAvailable(IoTRMIObject rmiObj) {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { byte[].class, long.class },
+ new Class<?>[] { null, null });
+ newCameraFrameAvailable((byte[]) paramObj[0], (long) paramObj[1]);
+ }
+
+ public void invokeMethod(IoTRMIObject rmiObj) throws IOException {
+ int methodId = rmiObj.getMethodId();
+ switch (methodId) {
+ case 0: ___newCameraFrameAvailable(rmiObj); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+
+}
--- /dev/null
+package HomeSecurityController;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class CameraSmart_Stub implements CameraSmart {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private final static int objectId = 0;
+ // Callback properties
+ private IoTRMIObject rmiObj;
+ List<CameraCallback> listCallbackObj;
+ private static int objIdCnt = 0;
+ private final static int object0Id = 0; //CameraSmartCallback
+ private static Integer[] object0Permission = { 0 };
+ private static List<Integer> set0Allowed;
+
+
+ public CameraSmart_Stub(int _port, String _skeletonAddress, String _callbackAddress, int _rev, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ ports = _ports;
+ rmiCall = new IoTRMICall(_port, _skeletonAddress, _rev);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ listCallbackObj = new ArrayList<CameraCallback>();
+ set0Allowed.add(-9999);
+ ___initCallBack();
+ }
+
+ public int getMaxFPS() {
+ int methodId = 8;
+ Class<?> retType = int.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ return (int)retObj;
+ }
+
+ public boolean setFPS(int _fps) {
+ int methodId = 7;
+ Class<?> retType = boolean.class;
+ Class<?>[] paramCls = new Class<?>[] { int.class };
+ Object[] paramObj = new Object[] { _fps };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ return (boolean)retObj;
+ }
+
+ public int getMinFPS() {
+ int methodId = 9;
+ Class<?> retType = int.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ return (int)retObj;
+ }
+
+ public boolean setResolution(Resolution _res) {
+ int methodId = 6;
+ Class<?> retType = boolean.class;
+ int paramEnum0[] = new int[1];
+ paramEnum0[0] = _res.ordinal();
+ Class<?>[] paramCls = new Class<?>[] { int[].class };
+ Object[] paramObj = new Object[] { paramEnum0 };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ return (boolean)retObj;
+ }
+
+ public void stop() {
+ int methodId = 2;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+ public void start() {
+ int methodId = 1;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+ public long getTimestamp() {
+ int methodId = 4;
+ Class<?> retType = long.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ return (long)retObj;
+ }
+
+ public byte[] getLatestFrame() {
+ int methodId = 3;
+ Class<?> retType = byte[].class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ return (byte[])retObj;
+ }
+
+ public void init() {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+ public void registerCallback(CameraCallback _callbackTo) {
+ try {
+ CameraCallback_CallbackSkeleton skel0 = new CameraCallback_CallbackSkeleton(_callbackTo, callbackAddress, objIdCnt++);
+ listCallbackObj.add(skel0);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Exception when generating skeleton objects!");
+ }
+
+ int methodId = 10;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int.class };
+ Object[] paramObj = new Object[] { new Integer(1) };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+ public void ___initCallBack() {
+ Thread thread = new Thread() {
+ public void run() {
+ try {
+ rmiObj = new IoTRMIObject(ports[0]);
+ while (true) {
+ byte[] method = rmiObj.getMethodBytes();
+ int objId = IoTRMIObject.getObjectId(method);
+ CameraCallback_CallbackSkeleton skel = (CameraCallback_CallbackSkeleton) listCallbackObj.get(objId);
+ if (skel != null) {
+ int methodId = IoTRMIObject.getMethodId(method);
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Callback object for CameraCallback is not allowed to access method: " + methodId);
+ }
+ skel.invokeMethod(rmiObj);
+ } else {
+ throw new Error("CameraCallback: Object with Id " + objId + " not found!");
+ }
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Error instantiating class CameraCallback_CallbackSkeleton!");
+ }
+ }
+ };
+ thread.start();
+
+ int methodId = -9998;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int[].class, String.class, int.class };
+ Object[] paramObj = new Object[] { ports, callbackAddress, 0 };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+ public List<Resolution> getSupportedResolutions() {
+ int methodId = 5;
+ Class<?> retType = int[].class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ int[] retEnum = (int[]) retObj;
+ Resolution[] enumVals = Resolution.values();
+ int retLen = retEnum.length;
+ List<Resolution> enumRetVal = new ArrayList<Resolution>();
+ for (int i = 0; i < retLen; i++) {
+ enumRetVal.add(enumVals[retEnum[i]]);
+ }
+ return enumRetVal;
+ }
+
+}
--- /dev/null
+ADDITIONAL_ZIP_FILE=No
--- /dev/null
+package HomeSecurityController;
+
+// Standard Java Packages
+import java.util.Date;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import java.util.HashSet;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.ConcurrentHashMap;
+
+// RMI packages
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+
+// IoT Runtime Packages
+import iotruntime.slave.IoTSet;
+import iotruntime.slave.IoTRelation;
+import iotcode.annotation.*;
+
+// IoT Driver Packages
+import iotcode.interfaces.*;
+
+// Checker annotations
+//import iotchecker.qual.*;
+
+/** Class Home Security Controller for the home security application benchmark
+ *
+ * @author Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version 1.0
+ * @since 2016-12-14
+ */
+public class HomeSecurityController implements SmartthingsSensorCallback {
+
+ /*
+ * Constants
+ */
+ private static final int MOTION_TIME_THRESHOLD = 60; // in seconds
+ private static final int CAMERA_FPS = 15;
+ private static final int CHECK_TIME_WAIT = 1; // in seconds
+ private static final int SECOND_TO_TURN_ON = 60; // in seconds
+
+ /**
+ * IoT Sets and Relations
+ * <p>
+ * Devices involved:
+ * 1) Multipurpose sensor (detect windows open/close) - Smartthings sensor
+ * 2) Motion sensor (detect motion in certain radius) - Smartthings sensor
+ * 3) Water leak sensor (detect leakage) - Smartthings sensor
+ * 4) Camera (detect motion)
+ * 5) Alarm (using ESP board) - assuming 1 house alarm
+ * 6) Room (object as place of device)
+ *
+ * Additionals (for more extensive home management)
+ * 7) Doorlock (detect open/locked)
+ * 8) Power outlet (detect on/off, monitor watt)
+ */
+ // This comprises multipurpose, motion, and water leak sensors
+ // TODO: Per 01/2017, doorlock and outlet are not ready, ESP board will be used for alarm
+ @config private IoTSet<SmartthingsSensorSmart> smartSensorsSet;
+ @config private IoTSet<CameraSmart> camSet;
+ @config private IoTSet<AlarmSmart> alarmSet;
+ @config private IoTSet<RoomSmart> roomSet;
+ //@config private IoTSet<DoorLock> doorlockSet;
+ //@config private IoTSet<Outlet> outletSet;
+
+ @config private IoTRelation<RoomSmart, SmartthingsSensorSmart> roomSensorRelation;
+ @config private IoTRelation<RoomSmart, CameraSmart> roomCameraRelation;
+ //@config private IoTRelation<RoomSmart, DoorLock> roomDoorLockRelation;
+ //@config private IoTRelation<RoomSmart, Outlet> roomOutletRelation;
+
+ /*******************************************************************************************************************************************
+ **
+ ** Variables
+ **
+ *******************************************************************************************************************************************/
+ long lastTimeChecked = 0;
+
+ private static int sensorId = 0;
+
+ /*******************************************************************************************************************************************
+ **
+ ** States data structures
+ **
+ *******************************************************************************************************************************************/
+ // Camera and motion detection
+ private Map<CameraSmart, MotionDetection> camMotionDetect =
+ new HashMap<CameraSmart, MotionDetection>();
+ // Smartthings sensors (true = motion, leakage, etc.)
+ private Map<Integer, Boolean> senDetectStatus =
+ new ConcurrentHashMap<Integer, Boolean>();
+ // Camera (true = motion)
+ private Map<CameraSmart, Boolean> camDetectStatus =
+ new HashMap<CameraSmart, Boolean>();
+ // Doorlock (true = open - not locked)
+ //private Map<DoorLock, Boolean> doorlockStatus =
+ // new HashMap<DoorLock, Boolean>();
+ // Outlet (true = on - outlet is used)
+ //private Map<Outlet, Boolean> outletStatus =
+ // new HashMap<Outlet, Boolean>();
+
+ // Alarm status
+ private Map<Integer, Boolean> alarmStatus =
+ new HashMap<Integer, Boolean>();
+
+ public HomeSecurityController() {
+
+ }
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** Helper Methods
+ **
+ *******************************************************************************************************************************************/
+
+
+ /** Method to initialize Smartthings sensors
+ *
+ * @return [void] None.
+ */
+ private void initSmartthingsSensors(RoomSmart rm) {
+
+ // Get and init the IAS sensors for this specific room
+ HashSet<SmartthingsSensorSmart> sensors = roomSensorRelation.get(rm);
+ for (SmartthingsSensorSmart sen : sensors) {
+
+ try {
+ // Initialize sensors
+ sen.init();
+ sen.setId(sensorId++);
+ System.out.println("DEBUG: Initialized smartthings sensor!");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+
+ /** Method to initialize cameras
+ *
+ * @return [void] None.
+ */
+ private void initCameras(RoomSmart rm) {
+
+ // Get and init the cameras for this specific room
+ HashSet<CameraSmart> cameras = roomCameraRelation.get(rm);
+ // Setup the cameras, start them all and assign each one a motion detector
+ for (CameraSmart cam : camSet.values()) {
+
+ // Each camera will have a motion detector unique to it since the motion detection has state
+ MotionDetection mo = new MotionDetection(12, 0.5f, 10, 10);
+
+ // 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);
+
+ // camera will call the motion detector directly with data not this controller
+ cam.registerCallback(mo);
+
+ // Start the camera (example is start the HTTP stream if it is a network camera)
+ cam.start();
+ System.out.println("DEBUG: Initialized camera!");
+
+ // Remember which motion detector is for what camera
+ camMotionDetect.put(cam, mo);
+ }
+ }
+
+
+ /** Method to initialize alarms
+ *
+ * @return [void] None.
+ */
+ private void initAlarms() {
+
+ // Get and init the alarm (this single alarm set can serve multiple zones / rooms)
+ Iterator alarmIt = alarmSet.iterator();
+ AlarmSmart alm = (AlarmSmart) alarmIt.next();
+ // init the alarm controller, do it here since it only needs to be done once per controller
+ try {
+ alm.init();
+ System.out.println("DEBUG: Initialized alarm!");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ /** Method to initialize doorlocks
+ *
+ * @return [void] None.
+ */
+ private void initDoorLocks(RoomSmart rm) {
+
+ // Get and init the doorlocks for this specific room
+ /*HashSet<DoorLock> doorlocks = roomDoorLockRelation.get(rm);
+ for (DoorLock doorlock : doorlocks) {
+
+ try {
+ // Initialize doorlocks
+ doorlock.init();
+ System.out.println("DEBUG: Initialized doorlock!");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }*/
+ }
+
+
+ /** Method to initialize power outlets
+ *
+ * @return [void] None.
+ */
+ private void initOutlets(RoomSmart rm) {
+
+ // Get and init the outlets for this specific room
+ /*HashSet<Outlet> outlets = roomOutletRelation.get(rm);
+ for (Outlet outlet : outlets) {
+
+ try {
+ // Initialize outlets
+ outlet.init();
+ System.out.println("DEBUG: Initialized outlet!");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }*/
+ }
+
+
+ /** Method to detect if a room has seen motion within the last few seconds (time specified as parameter).
+ * Checks all the motion detectors for the given room
+ *
+ * @param _room [RoomSmart] , Room of interest.
+ * @param _numberOfSeconds [int] , Number of seconds in the past that we consider recent.
+ * @param _upperThreshold [int] , Number of seconds as an upper bound before we turn off.
+ *
+ * @return [void] None.
+ */
+ private void updateCameraStatus(RoomSmart _room, int _numberOfSeconds) {
+ long currentTimeSeconds = (new Date()).getTime() / 1000;
+
+ // Loop through all the cameras in the room
+ for (CameraSmart cam : roomCameraRelation.get(_room)) {
+ long lastDetectedMotionSeconds = currentTimeSeconds;
+
+ Date motionTime = ((MotionDetection)camMotionDetect.get(cam)).getTimestampOfLastMotion();
+
+ // Motion was detected at least once
+ if (motionTime != null) {
+ lastDetectedMotionSeconds = motionTime.getTime() / 1000;
+ } else {
+ // motionTime == null means this is the initialization phase
+ // so we put false
+ camDetectStatus.put(cam, false);
+ }
+
+ // Did detect motion recently
+ if (Math.abs(currentTimeSeconds - lastDetectedMotionSeconds) < _numberOfSeconds) {
+ camDetectStatus.put(cam, true);
+ }
+ }
+ }
+
+
+ /** Method to update state data structures for Smartthings sensors
+ *
+ * @return [void] None.
+ */
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
+
+ System.out.println("DEBUG: Sensor reading value: " + _value);
+ if(_activeValue) {
+
+ senDetectStatus.put(_sensorId, true);
+
+ } else {
+
+ senDetectStatus.put(_sensorId, false);
+ }
+ }
+
+
+ /** Method to update state data structures for doorlocks
+ *
+ * @return [void] None.
+ */
+ private void updateDoorLockStatus(RoomSmart rm) {
+
+ // Get and init the outlets for this specific room
+ /*HashSet<DoorLock> doorlocks = roomDoorLockRelation.get(rm);
+ for (DoorLock doorlock : doorlocks) {
+
+ // Change is detected! Set to true for report...
+ if(isChangeDetected()) {
+
+ doorlockStatus.put(doorlock, true);
+ } else {
+
+ doorlockStatus.put(doorlock, false);
+ }
+ }*/
+ }
+
+
+ /** Method to update state data structures for outlets
+ *
+ * @return [void] None.
+ */
+ private void updateOutletStatus(RoomSmart rm) {
+
+ // Get and init the outlets for this specific room
+ /*HashSet<Outlet> outlets = roomOutletRelation.get(rm);
+ for (Outlet outlet : outlets) {
+
+ // Change is detected! Set to true for report...
+ if(isChangeDetected()) {
+
+ outletStatus.put(outlet, true);
+ } else {
+
+ outletStatus.put(outlet, false);
+ }
+ }*/
+ }
+
+
+ /** Update the status of all devices
+ *
+ * @return [void] None.
+ */
+ private void updateUniversalStatus() {
+
+ // Check for motion in rooms and if there is motion then report
+ for (RoomSmart room : roomSet.values()) {
+
+ // Update status of camera
+ updateCameraStatus(room, MOTION_TIME_THRESHOLD);
+
+ // Update status of doorlocks
+ //updateDoorLockStatus(room);
+
+ // Update status of outlets
+ //updateOutletStatus(room);
+ }
+ }
+
+
+ /** Method to turn on alarms
+ *
+ * @return [void] None.
+ */
+ private void turnOnAlarms(int zoneId) {
+
+ // Get and init the alarm (this single alarm set can serve multiple zones / rooms)
+ Iterator alarmIt = alarmSet.iterator();
+ AlarmSmart alm = (AlarmSmart) alarmIt.next();
+ alm.setZone(zoneId, true, SECOND_TO_TURN_ON);
+ }
+
+
+ /** Method to turn off alarms
+ *
+ * @return [void] None.
+ */
+ private void turnOffAlarms(int zoneId) {
+
+ // Get and init the alarm (this single alarm set can serve multiple zones / rooms)
+ Iterator alarmIt = alarmSet.iterator();
+ AlarmSmart alm = (AlarmSmart) alarmIt.next();
+ // Turn this alarm off indefinitely
+ alm.setZone(zoneId, false, -1);
+ }
+
+
+ /** Check status of devices and turn on alarm accordingly
+ * <p>
+ * Simple rule is whenever any sensor or camera detect something unusual
+ * (sensor/camera becomes active) then we sound the corresponding alarm.
+ * This means we send the signal to the right zone in the EspAlarm
+ *
+ * @return [void] None.
+ */
+ private void decideToTurnOnAlarm() {
+
+ int zoneId = 0;
+
+ // Check for motion in rooms and if there is motion then report
+ for (RoomSmart room : roomSet.values()) {
+
+ // Loop through all the cameras in the room
+ for (CameraSmart cam : roomCameraRelation.get(room)) {
+
+ // Get the right camera and the right detection status (true or false)
+ if (camDetectStatus.get(cam)) {
+ zoneId = room.getRoomID();
+ turnOnAlarms(zoneId);
+ System.out.println("DETECTION: Camera active in room: " + zoneId);
+ }
+ }
+
+ // Loop through all the cameras in the room
+ for (SmartthingsSensorSmart sensor : roomSensorRelation.get(room)) {
+
+ // Get the right sensor and the right detection status (true or false)
+ if (senDetectStatus.get(sensor.getId())) {
+ zoneId = room.getRoomID();
+ turnOnAlarms(zoneId);
+ System.out.println("DETECTION: Sensor active in room: " + zoneId);
+ }
+ }
+ }
+ }
+
+
+ /** Check status of devices and turn off alarm accordingly
+ * <p>
+ * If everything (camera and sensors) is set back to normal
+ * then the system will turn off the alarm
+ *
+ * @return [void] None.
+ */
+ // TODO: Need to fix this part later
+ // TODO: Perhaps we should use a phone app to turn off the alarm
+ /*private void decideToTurnOffAlarm() {
+
+ // Check for motion in rooms and if there is motion then report
+ for (RoomSmart room : roomSet.values()) {
+
+ int zoneId = room.getRoomID();
+ // Loop through all the cameras in the room
+ for (CameraSmart cam : roomCameraRelation.get(room)) {
+
+ // Get the right camera and the right detection status (true or false)
+ if (camDetectStatus.get(cam)) // Camera still active so alarm is still on, so false for off-alarm status
+
+ alarmStatus.put(zoneId, false);
+
+ else
+
+ alarmStatus.put(zoneId, true);
+
+ }
+
+ // Loop through all the cameras in the room
+ for (SmartthingsSensor sensor : roomSensorRelation.get(room)) {
+
+ // Get the right sensor and the right detection status (true or false)
+ if (senDetectStatus.get(sensor.getId())) // Sensor still active so alarm is still on, so false for off-alarm status
+
+ alarmStatus.put(zoneId, false);
+
+ else
+
+ alarmStatus.put(zoneId, true);
+ }
+ }
+
+ // Turn on alarm in the right zone
+ for (Map.Entry<Integer, Boolean> alEnt : alarmStatus.entrySet()) {
+ if (alEnt.getValue()) // if this zone is true, that means we need to turn off its alarm
+ turnOffAlarms(alEnt.getKey());
+ }
+ }*/
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** Public Methods
+ **
+ *******************************************************************************************************************************************/
+
+ /** Initialization method, called by the runtime (effectively the main of the controller)
+ * This method runs a continuous loop and is blocking
+ *
+ * @return [void] None;
+ */
+ public void init() {
+
+ // Iterate over the set of rooms
+ for (RoomSmart rm : roomSet.values()) {
+
+ // Init all Smartthings sensors
+ initSmartthingsSensors(rm);
+
+ // Init all cameras
+ initCameras(rm);
+
+ // Init all doorlocks
+ //initDoorLocks(rm);
+
+ // Init all outlets
+ //initOutlets(rm);
+ }
+
+ // Init all alarms
+ initAlarms();
+
+ // Run the main loop that will keep checking the sensors and cameras periodically
+ while (true) {
+
+ // Run this code every <specified time>
+ long currentTimeSeconds = (new Date()).getTime() / 1000;
+ if ((currentTimeSeconds - lastTimeChecked) > CHECK_TIME_WAIT) {
+ lastTimeChecked = currentTimeSeconds;
+
+ // Update the status of all devices
+ updateUniversalStatus();
+
+ // Decide to turn on alarm if any of the sensor/camera detects something unusual
+ decideToTurnOnAlarm();
+
+ // Decide to turn off alarm if every sensor/camera goes back to normal
+ //decideToTurnOffAlarm();
+
+ } else {
+
+ try {
+
+ Thread.sleep(CHECK_TIME_WAIT * 100); // sleep for a tenth of the time
+
+ } catch (Exception e) {
+
+ e.printStackTrace();
+ }
+ }
+
+ }
+ }
+}
+
+
--- /dev/null
+BASE = ../..
+
+include $(BASE)/common.mk
+
+BOOFDIR := ../libs/boofcv_libs
+BOOFJARS := $(BOOFDIR)/BoofCV-feature-0.21.jar:$(BOOFDIR)/BoofCV-io-0.21.jar:$(BOOFDIR)/BoofCV-visualize-0.21.jar:$(BOOFDIR)/BoofCV-ip-0.21.jar:$(CHECKERJARS)
+
+JFLAGS = -d $(BIN_DIR) -cp $(BOOFJARS):$(BIN_DIR):.
+JARFLAGS = cf
+
+all: homesecurity
+
+PHONY += homesecurity
+homesecurity:
+ $(JAVAC) $(JFLAGS) *.java
+ cp HomeSecurityController.config $(BIN_DIR)/HomeSecurityController
+ cd $(BIN_DIR)/HomeSecurityController; $(JAR) $(JARFLAGS) HomeSecurityController.jar ../HomeSecurityController/HomeSecurityController*.class ../HomeSecurityController/MotionDetection*.class ../iotcode/interfaces/SmartthingsSensor*.class ../iotcode/interfaces/Camera*.class ../iotcode/interfaces/Alarm*.class ../iotcode/interfaces/Room*.class ../iotcode/interfaces/ZoneState*.class
+
+.PHONY: $(PHONY)
--- /dev/null
+package HomeSecurityController;
+
+// IoT packages
+import iotcode.annotation.*;
+import iotcode.interfaces.*;
+
+// BoofCv packages
+import boofcv.alg.background.BackgroundModelStationary;
+import boofcv.factory.background.ConfigBackgroundGaussian;
+import boofcv.factory.background.FactoryBackgroundModel;
+import boofcv.gui.binary.VisualizeBinaryData;
+import boofcv.gui.image.ImageGridPanel;
+import boofcv.gui.image.ShowImages;
+import boofcv.io.MediaManager;
+import boofcv.io.UtilIO;
+import boofcv.io.image.SimpleImageSequence;
+import boofcv.io.image.ConvertBufferedImage;
+import boofcv.io.wrapper.DefaultMediaManager;
+import boofcv.struct.image.ImageBase;
+import boofcv.struct.image.ImageFloat32;
+import boofcv.struct.image.ImageType;
+import boofcv.struct.image.ImageUInt8;
+import boofcv.alg.filter.blur.BlurImageOps;
+
+
+// Standard Java Packages
+import java.awt.image.BufferedImage;
+import java.util.Date;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.awt.image.ColorModel;
+import java.awt.image.WritableRaster;
+import java.util.List;
+import java.util.ArrayList;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import javax.imageio.ImageIO;
+
+// RMI Packages
+import java.rmi.RemoteException;
+
+// For testing
+import java.net.*;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+import java.util.Iterator;
+
+// Checker annotations
+//import iotchecker.qual.*;
+
+/** Class MotionDetection to do motion detection using images
+ *
+ *
+ * @author Ali Younis <ayounis @ uci.edu>
+ * @version 1.0
+ * @since 2016-03-21
+ */
+class MotionDetection implements CameraCallback {
+
+ // Define Like variables
+ private static boolean DO_GRAPHICAL_USER_INTERFACE = false;
+
+ /*******************************************************************************************************************************************
+ **
+ ** Constants
+ **
+ *******************************************************************************************************************************************/
+ private final float MOTION_DETECTED_THRESHOLD_PERCENTAGE = 15;
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** Variables
+ **
+ *******************************************************************************************************************************************/
+
+ // Timestamp buffer and locks needed for that safety on that buffer
+ // This is the buffer for post-detection algorithm use
+ private Date timestampOfLastMotion = null;
+ private ReadWriteLock timestampReadWriteLock = new ReentrantReadWriteLock();
+ private Lock timestampReadLock = timestampReadWriteLock.readLock();
+ private Lock timestampWriteLock = timestampReadWriteLock.writeLock();
+
+ // Flag for when new data is available and ready for processing
+ private AtomicBoolean newFrameAvailable = new AtomicBoolean(false);
+
+ // Flag for determining if motion has been detected and therefore
+ // the callbacks should be issued
+ private AtomicBoolean motionDetected = new AtomicBoolean(false);
+
+ // Image and timestamp buffers and locks needed for that safety on those buffers
+ // Timestamp buffer for pre-detection algorithm use
+ private BufferedImage latestImage = null;
+ private Date possibleDate = null;
+ private ReadWriteLock imageReadWriteLock = new ReentrantReadWriteLock();
+ private Lock imageReadLock = imageReadWriteLock.readLock();
+ private Lock imageWriteLock = imageReadWriteLock.writeLock();
+
+ // List of objects wishing to receive callbacks from this class.
+ private List<MotionDetectionCallback>
+ callbackList = new ArrayList<MotionDetectionCallback>();
+
+ // Variables to help with motion detection
+ private ConfigBackgroundGaussian configGaussian = null;
+ private BackgroundModelStationary backgroundDetector = null;
+ private ImageUInt8 segmented = null;
+ private ImageFloat32 newFrameFloat = null;
+
+ // counts the number of frames since a background image is added to algorithm
+ private int frameCounter = 0;
+
+ private CameraSmart _camera;
+
+ /*******************************************************************************************************************************************
+ **
+ ** Threads
+ **
+ *******************************************************************************************************************************************/
+ private Thread workThread = null;
+ private Thread callBackThread = null;
+
+ /*******************************************************************************************************************************************
+ **
+ ** GUI Stuff (Used Only for Testing)
+ **
+ *******************************************************************************************************************************************/
+ ImageGridPanel gui;
+
+ /** Constructor
+ *
+ * @param _threshold [float], Variable for gaussian background detector.
+ * @param _learnSpeed [float], Variable for gaussian background detector.
+ * @param _initialVariance [float], Variable for gaussian background detector.
+ * @param _minDifference [float], Variable for gaussian background detector.
+ *
+ */
+ public MotionDetection(float _threshold, float _learnSpeed, float _initialVariance, float _minDifference) {
+
+ // Configure the Gaussian model used for background detection
+ configGaussian = new ConfigBackgroundGaussian(_threshold, _learnSpeed);
+ configGaussian.initialVariance = _initialVariance;
+ configGaussian.minimumDifference = _minDifference;
+
+ // setup the background detector
+ ImageType imageType = ImageType.single(ImageFloat32.class);
+ backgroundDetector = FactoryBackgroundModel.stationaryGaussian(configGaussian, imageType);
+
+ // setup the gui if we are going to use it
+ if (DO_GRAPHICAL_USER_INTERFACE) {
+
+ // create an image grid for images to place on, tile fashion
+ gui = new ImageGridPanel(1, 2);
+
+ // make the window large so we dont have to manually resize with the mouse
+ gui.setSize(1920, 1080);
+
+ // Make the window visible and set the title
+ ShowImages.showWindow(gui, "Static Scene: Background Segmentation", true);
+ }
+
+ // Launch the worker thread
+ workThread = new Thread(new Runnable() {
+ public void run() {
+
+ while (true) {
+ runMotionDetection();
+ }
+ }
+ });
+ workThread.start();
+
+
+ // Launch the callback thread
+ callBackThread = new Thread(new Runnable() {
+ public void run() {
+
+ while (true) {
+ doCallbacks();
+ }
+ }
+ });
+ callBackThread.start();
+ }
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** Public Methods
+ **
+ *******************************************************************************************************************************************/
+
+ /** Method to add a new frame to the motion detector.
+ *
+ * @param _newFrame [byte[]], Frame data of new frame.
+ * @param _timestamp [Date] , Timestamp of new frame.
+ *
+ * @return [void] None.
+ */
+ public void addFrame(byte[] _newFrame, Date _timestamp) {
+ BufferedImage img = null;
+
+ try {
+ // Parse the byte array into a Buffered Image
+ InputStream in = new ByteArrayInputStream(_newFrame);
+ img = ImageIO.read(in);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return;
+ }
+
+ // Save the image and timestamp for use later
+ imageWriteLock.lock();// lock the image and timestamp buffers since multithread
+ latestImage = img;// image into image buffer
+ possibleDate = _timestamp;// timestamp into timestamp buffer
+ imageWriteLock.unlock();// Never forget to unlock
+
+ // flag the worker thread that there is new data ready for processing
+ newFrameAvailable.set(true);
+ }
+
+ /** Method to get the timestamp of the last time motion was detected
+ *
+ * @return [Date] timestamp of last motion or null if no motion was ever detected.
+ */
+ public Date getTimestampOfLastMotion() {
+ Date ret = null;
+
+ // Be safe because multithread
+ timestampReadLock.lock();
+
+ // Checks if there was ever motion, if not then timestampOfLastMotion
+ // will be null
+ if (timestampOfLastMotion != null) {
+ // Clone since we don't know what the other person is going to do
+ // with the timestamp
+ ret = (Date)timestampOfLastMotion.clone();
+ }
+
+ timestampReadLock.unlock();
+
+ return ret;
+ }
+
+
+ /** Method to add a new frame to the motion detector from a camera
+ *
+ * @param _camera [Camera], Camera that has the new data.
+ *
+ * @return [void] None.
+ */
+ public void newCameraFrameAvailable(byte[] latestFrame, long timeStamp) {
+ BufferedImage img = null;
+
+ try {
+ // Parse the byte array into a Buffered Image
+ //InputStream in = new ByteArrayInputStream(_camera.getLatestFrame());
+ InputStream in = new ByteArrayInputStream(latestFrame);
+ img = ImageIO.read(in);
+
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ return;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ return;
+
+ }
+
+ // Save the image and timestamp for use later
+ imageWriteLock.lock(); // lock the image and timestamp buffers since multithread
+ latestImage = img; // image into image buffer
+
+ // timestamp from camera into timestamp buffer
+ long dateLong = timeStamp;
+ possibleDate = new Date(dateLong);
+
+ imageWriteLock.unlock(); // Never forget to unlock
+
+ // flag the worker thread that there is new data ready for processing
+ newFrameAvailable.set(true);
+ }
+
+ /** Method to register an object to recieve callbacks from this motion detector
+ *
+ * @param _mdc [MotionDetectionCallback], object to recieve callbacks.
+ *
+ * @return [void] None.
+ */
+ public void registerCallback(MotionDetectionCallback _mdc) {
+ callbackList.add(_mdc);
+ }
+
+ /*******************************************************************************************************************************************
+ **
+ ** Helper Methods
+ **
+ *******************************************************************************************************************************************/
+
+ /** Method that constantly loops checking if new data is available. If there is
+ * new data, it is processed.
+ * This method should be run on a separate thread.
+ *
+ * @return [void] None.
+ */
+ private void runMotionDetection() {
+
+ // check if there is a new frame availble, only runs detection if there is new data to save
+ // computation time
+ if (!newFrameAvailable.get()) {
+ return;
+ }
+
+ // Lock since we are accessing the data buffers
+ imageReadLock.lock();
+
+ // processing data so now the buffered data is old
+ newFrameAvailable.set(false);
+
+ // copy from buffer to local for processing
+ Date tmpDate = possibleDate;
+
+ // Allocate space for the segmented image based on the first image we received
+ // cannot pre-allocate this since we do not know what the size of the images is
+ // before the first image arrives
+ if (segmented == null) {
+ segmented = new ImageUInt8(latestImage.getWidth(), latestImage.getHeight());
+ }
+
+ // copy from data buffers and convert into correct data type for BoofCv libraries
+ newFrameFloat = ConvertBufferedImage.convertFrom(latestImage, newFrameFloat);
+
+ // All done accessing the data buffers
+ imageReadLock.unlock();
+
+ // Run background detection
+ backgroundDetector.segment(newFrameFloat, segmented);
+
+ // Update the background baseline every 10 frames, helps the algorithm
+ frameCounter++;
+ if (frameCounter > 10) {
+ backgroundDetector.updateBackground(newFrameFloat);
+ frameCounter = 0;
+ }
+
+ // get the raw pixel data, gray-scale image
+ byte[] frameData = segmented.getData();
+
+ // count the number of pixels of the image that was deemed as "motion"
+ double count = 0;
+ double countMotion = 0;
+ for (byte b : frameData) {
+ count++;
+ if (b > 0) {
+ countMotion++;
+ }
+ }
+
+ // calculate the percentage of the image that was in motion
+ double percentMotion = (countMotion / count) * 100.0;
+
+ // Check if a high enough percentage of the image was in motion to say that there was motion in this frame of data
+ if (percentMotion > MOTION_DETECTED_THRESHOLD_PERCENTAGE) {
+
+ // Motion detected so save timestamp of this frame to another buffer
+ timestampWriteLock.lock();
+ timestampOfLastMotion = (Date)tmpDate.clone(); // clone to a different buffer
+ timestampWriteLock.unlock();
+
+ System.out.println("Motion Detected (with percentage: " + Double.toString(percentMotion) + "%)");
+ }
+
+ // Do output to the screen if we are using gui mode
+ if (DO_GRAPHICAL_USER_INTERFACE) {
+
+ // change image data unto correct type for rendering
+ BufferedImage visualized1 = new BufferedImage(segmented.width, segmented.height, BufferedImage.TYPE_INT_RGB);
+ VisualizeBinaryData.renderBinary(segmented, false, visualized1);
+
+ // change image data unto correct type for rendering
+ BufferedImage visualized2 = null;
+ visualized2 = ConvertBufferedImage.convertTo(newFrameFloat, visualized2, true);
+
+ // place the images into the image grid
+ gui.setImage(0, 1, visualized1);
+ gui.setImage(0, 2, visualized2);
+
+ // trigger rendering
+ gui.repaint();
+ }
+ }
+
+ /** Method that constantly loops checking if the callbacks should be issues and
+ * issues the callbacks if they should be issues.
+ * This method should be run on a separate thread.
+ *
+ * @return [void] None.
+ */
+ private void doCallbacks() {
+
+ // Keep looping forever for callback
+ while (true) {
+
+ // If motion detected
+ if (motionDetected.compareAndSet(true, false)) {
+
+ // Motion was detected so issue callbacks to all objects that registered
+ // to receive callback from this class.
+ for (MotionDetectionCallback c : callbackList) {
+ //try {
+ c.motionDetected(this);
+ //} catch (RemoteException re) {
+ //}
+ }
+
+ } else {
+
+ // Sleep for 15 millisec to give time for new frame to arrive
+ try {
+ Thread.sleep(15);
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+ }
+
+
+
+
+ // /*******************************************************************************************************************************************
+ // ** Main Method used for testing
+ // *******************************************************************************************************************************************/
+ // public static void main(String[] args) {
+ // MotionDetection mo = new MotionDetection(12, 0.5f, 10, 10);
+
+ // AmcrestCamera cam = null;
+ // try {
+
+ // InetAddress addr = InetAddress.getByName("192.168.1.29");
+ // cam = new AmcrestCamera(addr, "admin", "55779CatSoundz32");
+ // cam.registerCallback(mo);
+ // cam.start();
+ // // cam.streamDisconnect();
+
+ // } catch (Exception e) {
+
+ // }
+
+ // while (true) {
+
+ // }
+
+ // }
+}
+
--- /dev/null
+package HomeSecurityController;
+
+/** Interface MotionDetectionCallback for allowing callbacks from the MotionDetection class.
+ *
+ *
+ * @author Ali Younis <ayounis @ uci.edu>
+ * @version 1.0
+ * @since 2016-03-21
+ */
+
+public interface MotionDetectionCallback {
+
+ /** Callback method for when motion is detected.
+ *
+ * @param _md [MotionDetection].
+ *
+ * @return [void] None.
+ */
+ public void motionDetected(MotionDetection _md);
+}
--- /dev/null
+package HomeSecurityController;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.RoomSmart;
+
+public class RoomSmart_Stub implements RoomSmart {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private final static int objectId = 0;
+
+
+ public RoomSmart_Stub(int _port, String _skeletonAddress, String _callbackAddress, int _rev, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ ports = _ports;
+ rmiCall = new IoTRMICall(_port, _skeletonAddress, _rev);
+ }
+
+ public int getRoomID() {
+ int methodId = 0;
+ Class<?> retType = int.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ return (int)retObj;
+ }
+
+}
--- /dev/null
+package HomeSecurityController;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensorCallback_CallbackSkeleton implements SmartthingsSensorCallback {
+
+ private SmartthingsSensorCallback mainObj;
+ private int objectId = 0;
+ private String callbackAddress;
+
+
+ public SmartthingsSensorCallback_CallbackSkeleton(SmartthingsSensorCallback _mainObj, String _callbackAddress, int _objectId) throws Exception {
+ callbackAddress = _callbackAddress;
+ mainObj = _mainObj;
+ objectId = _objectId;
+ }
+
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
+ mainObj.newReadingAvailable(_sensorId, _value, _activeValue);
+ }
+
+ public void ___newReadingAvailable(IoTRMIObject rmiObj) {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class, int.class, boolean.class },
+ new Class<?>[] { null, null, null });
+ newReadingAvailable((int) paramObj[0], (int) paramObj[1], (boolean) paramObj[2]);
+ }
+
+ public void invokeMethod(IoTRMIObject rmiObj) throws IOException {
+ int methodId = rmiObj.getMethodId();
+ switch (methodId) {
+ case 0: ___newReadingAvailable(rmiObj); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+
+}
--- /dev/null
+package HomeSecurityController;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensorSmart_Stub implements SmartthingsSensorSmart {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private final static int objectId = 0;
+ // Callback properties
+ private IoTRMIObject rmiObj;
+ List<SmartthingsSensorCallback> listCallbackObj;
+ private int objIdCnt = 0;
+ private final static int object0Id = 0; //SmartthingsSensorSmartCallback
+ private static Integer[] object0Permission = { 0 };
+ private static List<Integer> set0Allowed;
+
+
+ public SmartthingsSensorSmart_Stub(int _port, String _skeletonAddress, String _callbackAddress, int _rev, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ ports = _ports;
+ rmiCall = new IoTRMICall(_port, _skeletonAddress, _rev);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ listCallbackObj = new ArrayList<SmartthingsSensorCallback>();
+ set0Allowed.add(-9999);
+ ___initCallBack();
+ }
+
+ public long getTimestampOfLastReading() {
+ int methodId = 3;
+ Class<?> retType = long.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ return (long)retObj;
+ }
+
+ public boolean isActiveValue() {
+ int methodId = 2;
+ Class<?> retType = boolean.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ return (boolean)retObj;
+ }
+
+ public int getId() {
+ int methodId = 5;
+ Class<?> retType = int.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ return (int)retObj;
+ }
+
+ public void registerCallback(SmartthingsSensorCallback _callbackTo) {
+ try {
+ SmartthingsSensorCallback_CallbackSkeleton skel0 = new SmartthingsSensorCallback_CallbackSkeleton(_callbackTo, callbackAddress, objIdCnt++);
+ listCallbackObj.add(skel0);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Exception when generating skeleton objects!");
+ }
+
+ int methodId = 6;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int.class };
+ Object[] paramObj = new Object[] { new Integer(1) };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+ public void ___initCallBack() {
+ Thread thread = new Thread() {
+ public void run() {
+ try {
+ rmiObj = new IoTRMIObject(ports[0]);
+ while (true) {
+ byte[] method = rmiObj.getMethodBytes();
+ int objId = IoTRMIObject.getObjectId(method);
+ SmartthingsSensorCallback_CallbackSkeleton skel = (SmartthingsSensorCallback_CallbackSkeleton) listCallbackObj.get(objId);
+ if (skel != null) {
+ int methodId = IoTRMIObject.getMethodId(method);
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Callback object for SmartthingsSensorCallback is not allowed to access method: " + methodId);
+ }
+ skel.invokeMethod(rmiObj);
+ } else {
+ throw new Error("SmartthingsSensorCallback: Object with Id " + objId + " not found!");
+ }
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Error instantiating class SmartthingsSensorCallback_CallbackSkeleton!");
+ }
+ }
+ };
+ thread.start();
+
+ int methodId = -9998;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int[].class, String.class, int.class };
+ Object[] paramObj = new Object[] { ports, callbackAddress, 0 };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+ public int getValue() {
+ int methodId = 1;
+ Class<?> retType = int.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ return (int)retObj;
+ }
+
+ public void setId(int id) {
+ int methodId = 4;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int.class };
+ Object[] paramObj = new Object[] { id };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+ public void init() {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+}
// Motion was detected so issue callbacks to all objects that registered
// to receive callback from this class.
for (MotionDetectionCallback c : callbackList) {
- try {
+ //try {
c.motionDetected(this.getTimestampOfLastMotion());
- } catch (RemoteException re) {
- }
+ //} catch (RemoteException re) {
+ //}
}
} else {
* @since 2016-03-21
*/
-// Checker annotations
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-
-
-public interface MotionDetectionCallback extends Remote {
+public interface MotionDetectionCallback {
/** Callback method for when motion is detected.
*
- * @param _md [MotionDetection].
+ * @param timeStampOfLastMotion [long].
*
* @return [void] None.
*/
- //public void motionDetected(@NonLocalRemote MotionDetection _wg) throws RemoteException;
- public void motionDetected(long timeStampOfLastMotion) throws RemoteException;
+ public void motionDetected(long timeStampOfLastMotion);
}
include $(BASE)/common.mk
-all: interfaces annotation drivers Lifxtest SmartLights Irrigation Speaker
+all: interfaces annotation drivers Lifxtest SmartLights Irrigation Speaker HomeSecurity
PHONY += interfaces
interfaces:
Speaker:
$(MAKE) -C SpeakerController
+PHONY += HomeSecurity
+HomeSecurity:
+ $(MAKE) -C HomeSecurityController
+
.PHONY: $(PHONY)
// Motion was detected so issue callbacks to all objects that registered
// to receive callback from this class.
for (MotionDetectionCallback c : callbackList) {
- try {
+ //try {
c.motionDetected(this);
- } catch (RemoteException re) {
- }
+ //} catch (RemoteException re) {
+ //}
}
} else {
* @since 2016-03-21
*/
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-
-public interface MotionDetectionCallback extends Remote {
+public interface MotionDetectionCallback {
/** Callback method for when motion is detected.
*
*
* @return [void] None.
*/
- public void motionDetected(MotionDetection _md) throws RemoteException;
+ public void motionDetected(MotionDetection _md);
}
--- /dev/null
+package iotcode.EspAlarm;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class Alarm_Skeleton implements Alarm {
+
+ private Alarm mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private final static int object0Id = 0; //AlarmSmart
+ private static Integer[] object0Permission = { 4, 2, 0, 1, 3 };
+ private static List<Integer> set0Allowed;
+
+
+ public Alarm_Skeleton(Alarm _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public void setZone(int _zone, boolean _onOff, int _onDurationSeconds) {
+ mainObj.setZone(_zone, _onOff, _onDurationSeconds);
+ }
+
+ public List<ZoneState> getZoneStates() {
+ return mainObj.getZoneStates();
+ }
+
+ public int getNumberOfZones() {
+ return mainObj.getNumberOfZones();
+ }
+
+ public boolean doesHaveZoneTimers() {
+ return mainObj.doesHaveZoneTimers();
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___setZone() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class, boolean.class, int.class },
+ new Class<?>[] { null, null, null });
+ setZone((int) paramObj[0], (boolean) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___getZoneStates() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ List<ZoneState> retStruct = getZoneStates();
+ int retLen = retStruct.size();
+ Object retLenObj = retLen;
+ rmiObj.sendReturnObj(retLenObj);
+ Class<?>[] retCls = new Class<?>[3*retLen];
+ Object[] retObj = new Object[3*retLen];
+ int retPos = 0;
+ for(int i = 0; i < retLen; i++) {
+ retCls[retPos] = int.class;
+ retObj[retPos++] = retStruct.get(i).zoneNumber;
+ retCls[retPos] = boolean.class;
+ retObj[retPos++] = retStruct.get(i).onOffState;
+ retCls[retPos] = int.class;
+ retObj[retPos++] = retStruct.get(i).duration;
+ }
+ rmiObj.sendReturnObj(retCls, retObj);
+ }
+
+ public void ___getNumberOfZones() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getNumberOfZones();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___doesHaveZoneTimers() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = doesHaveZoneTimers();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___setZone(); break;
+ case 2: ___getZoneStates(); break;
+ case 3: ___getNumberOfZones(); break;
+ case 4: ___doesHaveZoneTimers(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=Alarm
+# Stub
+INTERFACE_STUB_CLASS=AlarmSmart
--- /dev/null
+package iotcode.EspAlarm;
+
+// Standard Java Packages
+import java.io.*;
+import java.net.*;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.security.InvalidParameterException;
+import java.util.Date;
+import java.util.Iterator;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.ArrayList;
+
+// IoT Packages
+import iotruntime.IoTUDP;
+import iotruntime.slave.IoTDeviceAddress;
+import iotruntime.slave.IoTSet;
+import iotcode.interfaces.ZoneState;
+import iotcode.interfaces.Alarm;
+
+//import iotchecker.qual.*;
+import iotcode.annotation.*;
+
+/** Class EspAlarm for the ESP8266 plrg Alarm.
+ *
+ * @author Ali Younis <ayounis @ uci.edu>, Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version 1.0
+ * @since 2016-12-21
+ */
+
+public class EspAlarm implements Alarm {
+
+ /*******************************************************************************************************************************************
+ **
+ ** Variables
+ **
+ *******************************************************************************************************************************************/
+
+ private IoTUDP communicationSockect;
+ private Semaphore socketMutex = new Semaphore(1);
+ private AtomicBoolean sendSocketFlag = new AtomicBoolean(false);
+ private AtomicBoolean doingRead = new AtomicBoolean(false);
+ private AtomicBoolean didInit = new AtomicBoolean(false);
+ private Semaphore settingZone = new Semaphore(1);
+
+ /*******************************************************************************************************************************************
+ **
+ ** Threads
+ **
+ *******************************************************************************************************************************************/
+
+ // Main worker thread will do the receive loop
+ Thread workerThread = null;
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** IoT Sets and Relations
+ **
+ *******************************************************************************************************************************************/
+
+ // IoTSet of Device Addresses.
+ // Will be filled with only 1 address.
+ @config private IoTSet<IoTDeviceAddress> alm_Addresses;
+
+ /*public EspSprinkler(IoTUDP _udp) {
+ communicationSockect = _udp;
+ }*/
+
+ public EspAlarm() {
+ communicationSockect = null;
+ }
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** Interface Methods
+ **
+ *******************************************************************************************************************************************/
+
+ /** Method to set the state of a specified zone. Interface implementation.
+ *
+ * @param _zone [int] : zone number to set.
+ * @param _onOff [boolean] : the state to set the zone to, on or off.
+ * @param _onDurationSeconds [int]: the duration to set the state on to, if -1 then infinite.
+ *
+ * @return [void] None.
+ */
+ public void setZone(int _zone, boolean _onOff, int _onDurationSeconds) {
+
+ try {
+ settingZone.acquire();
+ String sendString = "SET,";
+ sendString += Integer.toString(_zone);
+ sendString += ", ";
+
+ if (_onOff) {
+ sendString += "1";
+ } else {
+ sendString += "0";
+ }
+ sendString += ", ";
+ sendString += Integer.toString(_onDurationSeconds);
+
+ sendPacket(sendString.getBytes(StandardCharsets.UTF_8));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ settingZone.release();
+ }
+
+
+ /** Method to get the current state of all the zones. Interface implementation.
+ *
+ * @param None.
+ *
+ * @return [List<ZoneState>] list of the states for the zones.
+ */
+ public List<ZoneState> getZoneStates() {
+ doingRead.set(true);
+ sendGetInformation();
+
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ int loopCount = 0;
+ while (true) {
+ // Communication resource is busy so try again later
+ if (sendSocketFlag.get()) {
+ continue;
+ }
+
+ try {
+ socketMutex.acquire();
+ } catch (InterruptedException e) {
+ }
+
+ byte[] dat = null;
+ try {
+ dat = communicationSockect.recieveData(1024);
+ } catch (java.net.SocketTimeoutException e) {
+ // Timeout occurred
+
+ } catch (IOException e) {
+ // Problem but might be able to recover??
+ e.printStackTrace();
+
+ }
+
+ // Never forget to release!
+ socketMutex.release();
+
+ // A packed arrived
+ if (dat != null) {
+ doingRead.set(false);
+ return parseGetResponse(dat);
+
+ // return new ArrayList<ZoneState>();
+ } else {
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ loopCount++;
+
+ if (loopCount > 3) {
+ sendGetInformation();
+ loopCount = 0;
+ }
+ }
+ }
+ }
+
+
+ /** Method to get the number of zones this sprinkler can control. Interface implementation.
+ *
+ * @param None.
+ *
+ * @return [int] number of zones that can be controlled.
+ */
+ public int getNumberOfZones() {
+ return 9;
+ }
+
+
+ /** Method to get whether or not this sprinkler can control durations. Interface implementation.
+ *
+ * @param None.
+ *
+ * @return [boolean] boolean if this sprinkler can do durations.
+ */
+ public boolean doesHaveZoneTimers() {
+ return true;
+ }
+
+
+ /** Method to initialize the sprinkler. Interface implementation.
+ *
+ * @param None.
+ *
+ * @return [void] None.
+ */
+ public void init() {
+
+ if (didInit.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ try {
+ Iterator itr = alm_Addresses.iterator();
+ IoTDeviceAddress deviceAddress = (IoTDeviceAddress)itr.next();
+ System.out.println("Address: " + deviceAddress.getCompleteAddress());
+
+ // Create the communication channel
+ communicationSockect = new IoTUDP(deviceAddress);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ // Launch the worker function in a separate thread.
+ workerThread = new Thread(new Runnable() {
+ public void run() {
+ workerFunction();
+ }
+ });
+ workerThread.start();
+ }
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** Private Handlers
+ **
+ *******************************************************************************************************************************************/
+
+ /** Method to send the get information udp packet to get the latest sprinkler state.
+ *
+ * @param None.
+ *
+ * @return [void] None.
+ */
+ public void sendGetInformation() {
+ String sendString = "GET";
+ sendPacket(sendString.getBytes(StandardCharsets.UTF_8));
+ }
+
+
+ /** Method to parse the UDP packet data into a meaningful representation.
+ *
+ * @param _packetData [byte[]] raw packet data from the udp packet.
+ *
+ * @return [List<ZoneState>] Parsed zone data.
+ */
+ private List<ZoneState> parseGetResponse(byte[] _packetData) {
+ String recString = new String(_packetData);
+ List<ZoneState> retStates = new ArrayList<ZoneState>();
+
+ String[] lines = recString.split("\n");
+
+ for (int i = 0; i < 9; i++) {
+ String[] splitSting = lines[i].split(",");
+
+ int zoneNum = Integer.parseInt(splitSting[0].trim());
+ int onOffInt = Integer.parseInt(splitSting[1].trim());
+ boolean onOff = onOffInt != 0;
+ int duration = Integer.parseInt(splitSting[2].trim());
+
+ //ZoneState zTmp = new ZoneState(zoneNum, onOff, duration);
+ ZoneState zTmp = new ZoneState();
+ zTmp.zoneNumber = zoneNum;
+ zTmp.onOffState = onOff;
+ zTmp.duration = duration;
+ retStates.add(zTmp);
+ }
+
+ return retStates;
+ }
+
+
+ /** Method to parse the UDP packet data into a meaningful representation.
+ *
+ * @param _packetData [byte[]] bytes to send over the udp channel.
+ *
+ * @return [void] None.
+ */
+ private void sendPacket(byte[] _packetData) {
+ // System.out.println("About to send");
+ sendSocketFlag.set(true);
+
+ try {
+ socketMutex.acquire();
+ } catch (InterruptedException e) {
+ System.out.println("mutex Error");
+ }
+
+ try {
+ communicationSockect.sendData(_packetData);
+
+ } catch (IOException e) {
+ System.out.println("Socket Send Error");
+ }
+
+ sendSocketFlag.set(false);
+ socketMutex.release();
+ }
+
+
+ /** Method to constantly flush the udp socket expect when we wish to read the incoming data.
+ *
+ * @param None.
+ *
+ * @return [void] None.
+ */
+ private void workerFunction() {
+ try {
+ // Need timeout on receives since we are not sure if a packet will be available
+ // for processing so don't block waiting
+ communicationSockect.setSoTimeout(50);
+ } catch (IOException e) {
+ }
+
+
+
+ while (true) {
+
+ // Communication resource is busy so try again later
+ if (sendSocketFlag.get()) {
+ continue;
+ }
+
+ if (doingRead.get()) {
+ continue;
+ }
+
+ try {
+ socketMutex.acquire();
+ } catch (InterruptedException e) {
+ }
+
+ byte[] dat = null;
+ try {
+ dat = communicationSockect.recieveData(1024);
+ } catch (java.net.SocketTimeoutException e) {
+ // Timeout occurred
+
+ } catch (IOException e) {
+ // Problem but might be able to recover??
+ e.printStackTrace();
+
+ }
+
+ // Never forget to release!
+ socketMutex.release();
+
+ // Wait a bit as to not tie up system resources
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+
+ }
+ }
+ }
+
+}
+
+
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=Room
+# Stub
+INTERFACE_STUB_CLASS=RoomSmart
--- /dev/null
+package iotcode.HomeRoom;
+
+import iotcode.interfaces.Room;
+
+/** AudioRoom holds room ID that tells which room it is
+ * in association with speakers
+ *
+ * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version 1.0
+ * @since 2016-04-29
+ */
+public class HomeRoom implements Room {
+
+ /**
+ * AudioRoom class properties
+ */
+ private int iRoomID;
+
+ public HomeRoom(int _iRoomID) {
+ this.iRoomID = _iRoomID;
+ System.out.println("AudioRoom ID: " + this.iRoomID);
+ }
+
+ public int getRoomID() {
+ return this.iRoomID;
+ }
+}
--- /dev/null
+package iotcode.HomeRoom;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.Room;
+
+public class Room_Skeleton implements Room {
+
+ private Room mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private final static int object0Id = 0; //RoomSmart
+ private static Integer[] object0Permission = { 0 };
+ private static List<Integer> set0Allowed;
+
+
+ public Room_Skeleton(Room _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ ___waitRequestInvokeMethod();
+ }
+
+ public int getRoomID() {
+ return mainObj.getRoomID();
+ }
+
+ public void ___getRoomID() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getRoomID();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___getRoomID(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
JARFLAGS = cf
INTFACE_DIR = iotcode/interfaces
-all: light camera labroom greenlawn sprinkler moisture weathergateway audioroom gpsgateway ihome
+all: light camera labroom greenlawn sprinkler moisture weathergateway audioroom gpsgateway ihome homeroom alarm motion multipurpose waterleak
# Compile
#
cp IHome/IHome.config $(BIN_DIR)/iotcode/IHome
cd $(BIN_DIR)/iotcode/IHome; $(JAR) $(JARFLAGS) IHome.jar ../../iotcode/IHome/*.class ../../iotcode/interfaces/Speaker*.class
+PHONY += homeroom
+homeroom:
+ $(JAVAC) $(JFLAGS) HomeRoom/*.java
+ cp HomeRoom/HomeRoom.config $(BIN_DIR)/iotcode/HomeRoom
+ cd $(BIN_DIR)/iotcode/HomeRoom; $(JAR) $(JARFLAGS) HomeRoom.jar ../../iotcode/HomeRoom/*.class ../../iotcode/interfaces/Room*.class
+
+PHONY += alarm
+alarm:
+ $(JAVAC) $(JFLAGS) EspAlarm/*.java
+ cp EspAlarm/EspAlarm.config $(BIN_DIR)/iotcode/EspAlarm
+ cd $(BIN_DIR)/iotcode/EspAlarm; $(JAR) $(JARFLAGS) EspAlarm.jar ../../iotcode/EspAlarm/*.class ../../iotcode/interfaces/Alarm*.class ../../iotcode/interfaces/ZoneState*.class
+
+PHONY += motion
+motion:
+ $(JAVAC) $(JFLAGS) MotionSensor/*.java
+ cp MotionSensor/MotionSensor.config $(BIN_DIR)/iotcode/MotionSensor
+ cd $(BIN_DIR)/iotcode/MotionSensor; $(JAR) $(JARFLAGS) MotionSensor.jar ../../iotcode/MotionSensor/*.class ../../iotcode/interfaces/SmartthingsSensor*.class ../../iotcode/interfaces/Camera*.class ../../IrrigationController/MotionDetection*.class
+
+PHONY += multipurpose
+multipurpose:
+ $(JAVAC) $(JFLAGS) MultipurposeSensor/*.java
+ cp MultipurposeSensor/MultipurposeSensor.config $(BIN_DIR)/iotcode/MultipurposeSensor
+ cd $(BIN_DIR)/iotcode/MultipurposeSensor; $(JAR) $(JARFLAGS) MultipurposeSensor.jar ../../iotcode/MultipurposeSensor/*.class ../../iotcode/interfaces/SmartthingsSensor*.class ../../iotcode/interfaces/Camera*.class ../../IrrigationController/MotionDetection*.class
+
+PHONY += waterleak
+waterleak:
+ $(JAVAC) $(JFLAGS) WaterLeakSensor/*.java
+ cp MotionSensor/WaterLeakSensor.config $(BIN_DIR)/iotcode/WaterLeakSensor
+ cd $(BIN_DIR)/iotcode/WaterLeakSensor; $(JAR) $(JARFLAGS) WaterLeakSensor.jar ../../iotcode/WaterLeakSensor/*.class ../../iotcode/interfaces/SmartthingsSensor*.class ../../iotcode/interfaces/Camera*.class ../../IrrigationController/MotionDetection*.class
+
.PHONY: $(PHONY)
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=SmartthingsSensor
+# Stub
+INTERFACE_STUB_CLASS=SmartthingsSensorSmart
--- /dev/null
+package iotcode.MotionSensor;
+
+// Standard Java Packages
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Semaphore;
+
+// Checker annotations
+//import iotchecker.qual.*;
+import iotcode.annotation.*;
+
+// IoT Packages
+import iotruntime.slave.*;
+import iotcode.interfaces.*;
+import iotruntime.zigbee.*;
+
+/** Class Smartthings sensor driver for Smartthings sensor devices.
+ *
+ * @author Changwoo Lee, Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version 1.0
+ * @since 2016-12-01
+ */
+public class MotionSensor implements IoTZigbeeCallback, SmartthingsSensor {
+
+ private final int TIMEOUT_FOR_RESEND_MSEC = 900;
+
+ private IoTZigbee zigConnection = null;
+ private boolean didClose; // make sure that the clean up was done correctly
+ private boolean detectStatus = false;
+
+ private int detectedValue = 0;
+ private Date timestampOfLastDetecting = null;
+
+ private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
+ private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
+ private AtomicBoolean didWriteAttrb = new AtomicBoolean(false);
+ private AtomicBoolean didMatchDscr = new AtomicBoolean(false);
+ static Semaphore gettingLatestDataMutex = new Semaphore(1);
+
+ private List < SmartthingsSensorSmartCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorSmartCallback > ();
+
+ private int sensorId = 0;
+
+ @config private IoTSet<IoTDeviceAddress> devUdpAddress;
+ @config private IoTSet<IoTZigbeeAddress> devZigbeeAddress;
+
+ public MotionSensor(IoTSet<IoTDeviceAddress> dSet, IoTSet<IoTZigbeeAddress> zigSet) {
+ //devUdpAddress = dSet;
+ //devZigbeeAddress = zigSet;
+ }
+
+ public void init() {
+
+ if (didAlreadyInit.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyClose.set(false);
+
+ try {
+ Iterator itrUdp = devUdpAddress.iterator();
+ Iterator itrZig = devZigbeeAddress.iterator();
+
+ zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
+
+ // DEBUG
+ System.out.println("DEBUG: Allocate iterators to print out addresses!");
+ Iterator itrDebugUdp = devUdpAddress.iterator();
+ IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
+ System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
+ System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
+ System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
+
+ Iterator itrDebugZig = devZigbeeAddress.iterator();
+ IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
+ System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
+
+ zigConnection.registerCallback(this);
+ System.out.println("Register callback!");
+ zigConnection.init();
+ System.out.println("Initialized!");
+
+ //made by changwoo
+ sleep(10);
+
+ System.out.println("Sending Management Permit Joining Request");
+ for(int z=0; z<3; z++){
+ zigConnection.sendManagementPermitJoiningRequest(0x0001, 0x0036, 0x00);
+ sleep(0);
+ }
+
+ //made by changwoo
+ while (!didWriteAttrb.get()) {
+ System.out.println("Sending Write Attribute Request");
+ zigConnection.sendWriteAttributesCommand(0x0002, 0x0500, 0x0104, 0x01);
+ sleep(0);
+ }
+
+ //made by changwoo
+ System.out.println("Sending Enrollment Reponse");
+ zigConnection.sendEnrollmentResponse(0x0003, 0x0500, 0x0104, 0x01);
+ sleep(0);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ //made by changwoo
+ private void sleep(int multipleTime){
+ if(multipleTime<=0){
+ multipleTime=1;
+ }
+ try{
+ Thread.sleep(TIMEOUT_FOR_RESEND_MSEC*multipleTime);
+ } catch(Exception e){
+ e.printStackTrace();
+ }
+ }
+
+ public void close() {
+
+ if (didAlreadyClose.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyInit.set(false);
+
+
+ try {
+ zigConnection.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public void Finalize() {
+ if (!didClose) {
+ close();
+ }
+ }
+
+ public void setId(int id) {
+
+ sensorId = id;
+
+ }
+
+ public int getId() {
+
+ return sensorId;
+
+ }
+
+ public int getValue() {
+
+ int tmp = 0;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = detectedValue;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+
+ return tmp;
+ }
+
+ // MotionSensor:
+ // - 24 = no motion = false
+ // - 26 = motion = true
+ // After getting 26, if there is no motion for ~12 seconds then we get back 24
+ public boolean isActiveValue() {
+
+ int tmp = getValue();
+ if (tmp == 26)
+ detectStatus = true;
+ else // Getting 24 here
+ detectStatus = false;
+
+ return detectStatus;
+ }
+
+ public long getTimestampOfLastReading() {
+
+ Date tmp = null;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = (Date)timestampOfLastDetecting.clone();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+ long retLong = tmp.getTime();
+
+ return retLong;
+ }
+
+ public void newMessageAvailable(IoTZigbeeMessage _zm) {
+
+ //made by changwoo
+ if(_zm instanceof IoTZigbeeMessageZclZoneStatusChangeNotification){
+ IoTZigbeeMessageZclZoneStatusChangeNotification message = (IoTZigbeeMessageZclZoneStatusChangeNotification)_zm;
+ if(message.getSuccessOrFail()){
+ //do something!
+
+ try {
+ gettingLatestDataMutex.acquire();
+ detectedValue = message.getStatus();
+ timestampOfLastDetecting = new Date();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+ try {
+ for (SmartthingsSensorSmartCallback cb : callbackList) {
+ cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }//if
+
+ //made by changwoo
+ } else if (_zm instanceof IoTZigbeeMessageZclWriteAttributesResponse) {
+ IoTZigbeeMessageZclWriteAttributesResponse message = (IoTZigbeeMessageZclWriteAttributesResponse)_zm;
+ if (message.getSuccessOrFail()) {
+ didWriteAttrb.set(true);
+ }
+ }
+ }
+
+ public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
+ callbackList.add(_callbackTo);
+ }
+}
--- /dev/null
+package iotcode.MotionSensor;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensorSmartCallback_CallbackStub implements SmartthingsSensorSmartCallback {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private int objectId = 0;
+
+
+ public SmartthingsSensorSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ objectId = _objectId;
+ rmiCall = _rmiCall;
+ ports = _ports;
+ }
+
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int.class, int.class, boolean.class };
+ Object[] paramObj = new Object[] { _sensorId, _value, _activeValue };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+}
--- /dev/null
+package iotcode.MotionSensor;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensor_Skeleton implements SmartthingsSensor {
+
+ private SmartthingsSensor mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private int objIdCnt = 0;
+ private IoTRMICall rmiCall;
+ private int[] ports;
+
+ private final static int object0Id = 0; //SmartthingsSensorSmart
+ private static Integer[] object0Permission = { 3, 2, 5, 6, 1, 4, 0 };
+ private static List<Integer> set0Allowed;
+
+
+ public SmartthingsSensor_Skeleton(SmartthingsSensor _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ set0Allowed.add(-9998);
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public int getValue() {
+ return mainObj.getValue();
+ }
+
+ public boolean isActiveValue() {
+ return mainObj.isActiveValue();
+ }
+
+ public long getTimestampOfLastReading() {
+ return mainObj.getTimestampOfLastReading();
+ }
+
+ public void setId(int id) {
+ mainObj.setId(id);
+ }
+
+ public int getId() {
+ return mainObj.getId();
+ }
+
+ public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
+ mainObj.registerCallback(_callbackTo);
+ }
+
+ public void ___regCB() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
+ ports = (int[]) paramObj[0];
+ rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___getValue() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getValue();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___isActiveValue() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = isActiveValue();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getTimestampOfLastReading() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getTimestampOfLastReading();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___setId() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ setId((int) paramObj[0]);
+ }
+
+ public void ___getId() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getId();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___registerCallback() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ try {
+ SmartthingsSensorSmartCallback stub0 = new SmartthingsSensorSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
+ objIdCnt++;
+ registerCallback(stub0);
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Exception from callback object instantiation!");
+ }
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___getValue(); break;
+ case 2: ___isActiveValue(); break;
+ case 3: ___getTimestampOfLastReading(); break;
+ case 4: ___setId(); break;
+ case 5: ___getId(); break;
+ case 6: ___registerCallback(); break;
+ case -9998: ___regCB(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=SmartthingsSensor
+# Stub
+INTERFACE_STUB_CLASS=SmartthingsSensorSmart
--- /dev/null
+package iotcode.MultipurposeSensor;
+
+// Standard Java Packages
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Semaphore;
+
+// Checker annotations
+//import iotchecker.qual.*;
+import iotcode.annotation.*;
+
+// IoT Packages
+import iotruntime.slave.*;
+import iotcode.interfaces.*;
+import iotruntime.zigbee.*;
+
+/** Class Smartthings sensor driver for Smartthings sensor devices.
+ *
+ * @author Changwoo Lee, Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version 1.0
+ * @since 2016-12-01
+ */
+public class MultipurposeSensor implements IoTZigbeeCallback, SmartthingsSensor {
+
+ private final int TIMEOUT_FOR_RESEND_MSEC = 900;
+
+ private IoTZigbee zigConnection = null;
+ private boolean didClose; // make sure that the clean up was done correctly
+ private boolean detectStatus = false;
+
+ private int detectedValue = 0;
+ private Date timestampOfLastDetecting = null;
+
+ private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
+ private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
+ private AtomicBoolean didWriteAttrb = new AtomicBoolean(false);
+ private AtomicBoolean didMatchDscr = new AtomicBoolean(false);
+ static Semaphore gettingLatestDataMutex = new Semaphore(1);
+
+ private List < SmartthingsSensorSmartCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorSmartCallback > ();
+
+ private int sensorId = 0;
+
+ @config private IoTSet<IoTDeviceAddress> devUdpAddress;
+ @config private IoTSet<IoTZigbeeAddress> devZigbeeAddress;
+
+ public MultipurposeSensor(IoTSet<IoTDeviceAddress> dSet, IoTSet<IoTZigbeeAddress> zigSet) {
+ //devUdpAddress = dSet;
+ //devZigbeeAddress = zigSet;
+ }
+
+ public void init() {
+
+ if (didAlreadyInit.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyClose.set(false);
+
+ try {
+ Iterator itrUdp = devUdpAddress.iterator();
+ Iterator itrZig = devZigbeeAddress.iterator();
+
+ zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
+
+ // DEBUG
+ System.out.println("DEBUG: Allocate iterators to print out addresses!");
+ Iterator itrDebugUdp = devUdpAddress.iterator();
+ IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
+ System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
+ System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
+ System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
+
+ Iterator itrDebugZig = devZigbeeAddress.iterator();
+ IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
+ System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
+
+ zigConnection.registerCallback(this);
+ System.out.println("Register callback!");
+ zigConnection.init();
+ System.out.println("Initialized!");
+
+ //made by changwoo
+ sleep(10);
+ System.out.println("Sending Management Permit Joining Request");
+ for(int z=0; z<3; z++){
+ zigConnection.sendManagementPermitJoiningRequest(0x0001, 0x0036, 0x00);
+ sleep(0);
+ }
+
+ //made by changwoo
+ while (!didWriteAttrb.get()) {
+ System.out.println("Sending Write Attribute Request");
+ zigConnection.sendWriteAttributesCommand(0x0002, 0x0500, 0x0104, 0x01);
+ sleep(0);
+ }
+
+ //made by changwoo
+ System.out.println("Sending Enrollment Reponse");
+ zigConnection.sendEnrollmentResponse(0x0003, 0x0500, 0x0104, 0x01);
+ sleep(0);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ //made by changwoo
+ private void sleep(int multipleTime){
+ if(multipleTime<=0){
+ multipleTime=1;
+ }
+ try{
+ Thread.sleep(TIMEOUT_FOR_RESEND_MSEC*multipleTime);
+ } catch(Exception e){
+ e.printStackTrace();
+ }
+ }
+
+ public void close() {
+
+ if (didAlreadyClose.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyInit.set(false);
+
+
+ try {
+ zigConnection.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void Finalize() {
+ if (!didClose) {
+ close();
+ }
+ }
+
+ public void setId(int id) {
+
+ sensorId = id;
+
+ }
+
+ public int getId() {
+
+ return sensorId;
+
+ }
+
+ public int getValue() {
+
+ int tmp = 0;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = detectedValue;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+
+ return tmp;
+ }
+
+ // MultipurposeSensor:
+ // - 24 = close = false
+ // - 25 = open = true
+ public boolean isActiveValue() {
+
+ int tmp = getValue();
+ if (tmp == 25)
+ detectStatus = true;
+ else // Getting 24 here
+ detectStatus = false;
+
+ return detectStatus;
+ }
+
+ public long getTimestampOfLastReading() {
+
+ Date tmp = null;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = (Date)timestampOfLastDetecting.clone();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+ long retLong = tmp.getTime();
+
+ return retLong;
+ }
+
+ public void newMessageAvailable(IoTZigbeeMessage _zm) {
+
+ //made by changwoo
+ if(_zm instanceof IoTZigbeeMessageZclZoneStatusChangeNotification){
+ IoTZigbeeMessageZclZoneStatusChangeNotification message = (IoTZigbeeMessageZclZoneStatusChangeNotification)_zm;
+ if(message.getSuccessOrFail()){
+ //do something!
+ try {
+ gettingLatestDataMutex.acquire();
+ detectedValue = message.getStatus();
+ timestampOfLastDetecting = new Date();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+ try {
+ for (SmartthingsSensorSmartCallback cb : callbackList) {
+ cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }//if
+
+ //made by changwoo
+ }//if
+ else if (_zm instanceof IoTZigbeeMessageZclWriteAttributesResponse) {
+ IoTZigbeeMessageZclWriteAttributesResponse message = (IoTZigbeeMessageZclWriteAttributesResponse)_zm;
+ if (message.getSuccessOrFail()) {
+ didWriteAttrb.set(true);
+ }//if
+ }//else if
+ }
+
+ public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
+ callbackList.add(_callbackTo);
+ }
+}
--- /dev/null
+package iotcode.MultipurposeSensor;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensorSmartCallback_CallbackStub implements SmartthingsSensorSmartCallback {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private int objectId = 0;
+
+
+ public SmartthingsSensorSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ objectId = _objectId;
+ rmiCall = _rmiCall;
+ ports = _ports;
+ }
+
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int.class, int.class, boolean.class };
+ Object[] paramObj = new Object[] { _sensorId, _value, _activeValue };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+}
--- /dev/null
+package iotcode.MultipurposeSensor;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensor_Skeleton implements SmartthingsSensor {
+
+ private SmartthingsSensor mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private int objIdCnt = 0;
+ private IoTRMICall rmiCall;
+ private int[] ports;
+
+ private final static int object0Id = 0; //SmartthingsSensorSmart
+ private static Integer[] object0Permission = { 3, 2, 5, 6, 1, 4, 0 };
+ private static List<Integer> set0Allowed;
+
+
+ public SmartthingsSensor_Skeleton(SmartthingsSensor _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ set0Allowed.add(-9998);
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public int getValue() {
+ return mainObj.getValue();
+ }
+
+ public boolean isActiveValue() {
+ return mainObj.isActiveValue();
+ }
+
+ public long getTimestampOfLastReading() {
+ return mainObj.getTimestampOfLastReading();
+ }
+
+ public void setId(int id) {
+ mainObj.setId(id);
+ }
+
+ public int getId() {
+ return mainObj.getId();
+ }
+
+ public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
+ mainObj.registerCallback(_callbackTo);
+ }
+
+ public void ___regCB() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
+ ports = (int[]) paramObj[0];
+ rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___getValue() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getValue();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___isActiveValue() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = isActiveValue();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getTimestampOfLastReading() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getTimestampOfLastReading();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___setId() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ setId((int) paramObj[0]);
+ }
+
+ public void ___getId() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getId();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___registerCallback() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ try {
+ SmartthingsSensorSmartCallback stub0 = new SmartthingsSensorSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
+ objIdCnt++;
+ registerCallback(stub0);
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Exception from callback object instantiation!");
+ }
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___getValue(); break;
+ case 2: ___isActiveValue(); break;
+ case 3: ___getTimestampOfLastReading(); break;
+ case 4: ___setId(); break;
+ case 5: ___getId(); break;
+ case 6: ___registerCallback(); break;
+ case -9998: ___regCB(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+package iotcode.WaterLeakSensor;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensorSmartCallback_CallbackStub implements SmartthingsSensorSmartCallback {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private int objectId = 0;
+
+
+ public SmartthingsSensorSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ objectId = _objectId;
+ rmiCall = _rmiCall;
+ ports = _ports;
+ }
+
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int.class, int.class, boolean.class };
+ Object[] paramObj = new Object[] { _sensorId, _value, _activeValue };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+}
--- /dev/null
+package iotcode.WaterLeakSensor;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensor_Skeleton implements SmartthingsSensor {
+
+ private SmartthingsSensor mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private int objIdCnt = 0;
+ private IoTRMICall rmiCall;
+ private int[] ports;
+
+ private final static int object0Id = 0; //SmartthingsSensorSmart
+ private static Integer[] object0Permission = { 3, 2, 5, 6, 1, 4, 0 };
+ private static List<Integer> set0Allowed;
+
+
+ public SmartthingsSensor_Skeleton(SmartthingsSensor _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ set0Allowed.add(-9998);
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public int getValue() {
+ return mainObj.getValue();
+ }
+
+ public boolean isActiveValue() {
+ return mainObj.isActiveValue();
+ }
+
+ public long getTimestampOfLastReading() {
+ return mainObj.getTimestampOfLastReading();
+ }
+
+ public void setId(int id) {
+ mainObj.setId(id);
+ }
+
+ public int getId() {
+ return mainObj.getId();
+ }
+
+ public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
+ mainObj.registerCallback(_callbackTo);
+ }
+
+ public void ___regCB() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
+ ports = (int[]) paramObj[0];
+ rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___getValue() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getValue();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___isActiveValue() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = isActiveValue();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getTimestampOfLastReading() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getTimestampOfLastReading();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___setId() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ setId((int) paramObj[0]);
+ }
+
+ public void ___getId() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getId();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___registerCallback() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ try {
+ SmartthingsSensorSmartCallback stub0 = new SmartthingsSensorSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
+ objIdCnt++;
+ registerCallback(stub0);
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Exception from callback object instantiation!");
+ }
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___getValue(); break;
+ case 2: ___isActiveValue(); break;
+ case 3: ___getTimestampOfLastReading(); break;
+ case 4: ___setId(); break;
+ case 5: ___getId(); break;
+ case 6: ___registerCallback(); break;
+ case -9998: ___regCB(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=SmartthingsSensor
+# Stub
+INTERFACE_STUB_CLASS=SmartthingsSensorSmart
--- /dev/null
+package iotcode.WaterLeakSensor;
+
+// Standard Java Packages
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Semaphore;
+
+// Checker annotations
+//import iotchecker.qual.*;
+import iotcode.annotation.*;
+
+// IoT Packages
+import iotruntime.slave.*;
+import iotcode.interfaces.*;
+import iotruntime.zigbee.*;
+
+/** Class Smartthings sensor driver for Smartthings sensor devices.
+ *
+ * @author Changwoo Lee, Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version 1.0
+ * @since 2016-12-01
+ */
+public class WaterLeakSensor implements IoTZigbeeCallback, SmartthingsSensor {
+
+ private final int TIMEOUT_FOR_RESEND_MSEC = 900;
+
+ private IoTZigbee zigConnection = null;
+ private boolean didClose; // make sure that the clean up was done correctly
+ private boolean detectStatus = false;
+
+ private int detectedValue = 0;
+ private Date timestampOfLastDetecting = null;
+
+ private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
+ private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
+ private AtomicBoolean didWriteAttrb = new AtomicBoolean(false);
+ private AtomicBoolean didMatchDscr = new AtomicBoolean(false);
+ static Semaphore gettingLatestDataMutex = new Semaphore(1);
+
+ private List < SmartthingsSensorSmartCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorSmartCallback > ();
+
+ private int sensorId = 0;
+
+ @config private IoTSet<IoTDeviceAddress> devUdpAddress;
+ @config private IoTSet<IoTZigbeeAddress> devZigbeeAddress;
+
+ public WaterLeakSensor(IoTSet<IoTDeviceAddress> dSet, IoTSet<IoTZigbeeAddress> zigSet) {
+ //devUdpAddress = dSet;
+ //devZigbeeAddress = zigSet;
+ }
+
+ public void init() {
+
+ if (didAlreadyInit.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyClose.set(false);
+
+ try {
+ Iterator itrUdp = devUdpAddress.iterator();
+ Iterator itrZig = devZigbeeAddress.iterator();
+
+ zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
+
+ // DEBUG
+ System.out.println("DEBUG: Allocate iterators to print out addresses!");
+ Iterator itrDebugUdp = devUdpAddress.iterator();
+ IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
+ System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
+ System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
+ System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
+
+ Iterator itrDebugZig = devZigbeeAddress.iterator();
+ IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
+ System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
+
+ zigConnection.registerCallback(this);
+ System.out.println("Register callback!");
+ zigConnection.init();
+ System.out.println("Initialized!");
+
+ //made by changwoo
+ sleep(10);
+ System.out.println("Sending Management Permit Joining Request");
+ for(int z=0; z<3; z++){
+ zigConnection.sendManagementPermitJoiningRequest(0x0001, 0x0036, 0x00);
+ sleep(0);
+ }
+
+ //made by changwoo
+ while (!didWriteAttrb.get()) {
+ System.out.println("Sending Write Attribute Request");
+ zigConnection.sendWriteAttributesCommand(0x0002, 0x0500, 0x0104, 0x01);
+ sleep(0);
+ }
+
+ //made by changwoo
+ System.out.println("Sending Enrollment Reponse");
+ zigConnection.sendEnrollmentResponse(0x0003, 0x0500, 0x0104, 0x01);
+ sleep(0);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ //made by changwoo
+ private void sleep(int multipleTime){
+ if(multipleTime<=0){
+ multipleTime=1;
+ }
+ try{
+ Thread.sleep(TIMEOUT_FOR_RESEND_MSEC*multipleTime);
+ } catch(Exception e){
+ e.printStackTrace();
+ }
+ }
+
+ public void close() {
+
+ if (didAlreadyClose.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyInit.set(false);
+
+
+ try {
+ zigConnection.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void Finalize() {
+ if (!didClose) {
+ close();
+ }
+ }
+
+ public void setId(int id) {
+
+ sensorId = id;
+
+ }
+
+ public int getId() {
+
+ return sensorId;
+
+ }
+
+ public int getValue() {
+
+ int tmp = 0;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = detectedValue;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+
+ return tmp;
+ }
+
+ // WaterLeakSensor:
+ // - 24 = no leak = false
+ // - 25 = leak = true
+ public boolean isActiveValue() {
+
+ int tmp = getValue();
+ if (tmp == 25)
+ detectStatus = true;
+ else // Getting 24 here
+ detectStatus = false;
+
+ return detectStatus;
+ }
+
+ public long getTimestampOfLastReading() {
+
+ Date tmp = null;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = (Date)timestampOfLastDetecting.clone();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+ long retLong = tmp.getTime();
+
+ return retLong;
+ }
+
+ public void newMessageAvailable(IoTZigbeeMessage _zm) {
+
+ //made by changwoo
+ if(_zm instanceof IoTZigbeeMessageZclZoneStatusChangeNotification){
+ IoTZigbeeMessageZclZoneStatusChangeNotification message = (IoTZigbeeMessageZclZoneStatusChangeNotification)_zm;
+ if(message.getSuccessOrFail()){
+ //do something!
+
+ try {
+ gettingLatestDataMutex.acquire();
+ detectedValue = message.getStatus();
+ timestampOfLastDetecting = new Date();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+ try {
+ for (SmartthingsSensorSmartCallback cb : callbackList) {
+ cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }//if
+
+ //made by changwoo
+ }//if
+ else if (_zm instanceof IoTZigbeeMessageZclWriteAttributesResponse) {
+ IoTZigbeeMessageZclWriteAttributesResponse message = (IoTZigbeeMessageZclWriteAttributesResponse)_zm;
+ if (message.getSuccessOrFail()) {
+ didWriteAttrb.set(true);
+ }//if
+ }//else if
+ }
+
+ public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
+ callbackList.add(_callbackTo);
+ }
+}
--- /dev/null
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface Alarm {
+ public void init();
+ public void setZone(int _zone, boolean _onOff, int _onDurationSeconds);
+ public List<ZoneState> getZoneStates();
+ public int getNumberOfZones();
+ public boolean doesHaveZoneTimers();
+}
--- /dev/null
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface AlarmSmart {
+
+ public boolean doesHaveZoneTimers();
+ public List<ZoneState> getZoneStates();
+ public void init();
+ public void setZone(int _zone, boolean _onOff, int _onDurationSeconds);
+ public int getNumberOfZones();
+}
--- /dev/null
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface SmartthingsSensor {
+ public void init();
+ public int getValue();
+ public boolean isActiveValue();
+ public long getTimestampOfLastReading();
+ public void setId(int id);
+ public int getId();
+ public void registerCallback(SmartthingsSensorSmartCallback _callbackTo);
+}
--- /dev/null
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface SmartthingsSensorCallback {
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue);
+}
--- /dev/null
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface SmartthingsSensorSmart {
+
+ public long getTimestampOfLastReading();
+ public boolean isActiveValue();
+ public int getId();
+ public void registerCallback(SmartthingsSensorCallback _callbackTo);
+ public int getValue();
+ public void setId(int id);
+ public void init();
+}
--- /dev/null
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface SmartthingsSensorSmartCallback {
+
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue);
+}
private List < SmartthingsSensorCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorCallback > ();
+ private int sensorId = 0;
+
@config private IoTSet<IoTDeviceAddress> devUdpAddress;
@config private IoTSet<IoTZigbeeAddress> devZigbeeAddress;
}
}
+ public void setId(int id) {
+
+ sensorId = id;
+
+ }
+
+ public int getId() {
+
+ return sensorId;
+
+ }
+
public int getValue() {
int tmp = 0;
gettingLatestDataMutex.release();
try {
for (SmartthingsSensorCallback cb : callbackList) {
- cb.newReadingAvailable(this.getValue(), this.isActiveValue());
+ cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
}
} catch (Exception e) {
e.printStackTrace();
private List < SmartthingsSensorCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorCallback > ();
+ private int sensorId = 0;
+
@config private IoTSet<IoTDeviceAddress> devUdpAddress;
@config private IoTSet<IoTZigbeeAddress> devZigbeeAddress;
}
}
+ public void setId(int id) {
+
+ sensorId = id;
+
+ }
+
+ public int getId() {
+
+ return sensorId;
+
+ }
+
public int getValue() {
int tmp = 0;
gettingLatestDataMutex.release();
try {
for (SmartthingsSensorCallback cb : callbackList) {
- cb.newReadingAvailable(this.getValue(), this.isActiveValue());
+ cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
}
} catch (Exception e) {
e.printStackTrace();
*/
public void init() throws RemoteException;
+ public void setId(int id);
+
+ public int getId();
/** Register an object to retrieve callbacks when new sensor reading is available
*
public interface SmartthingsSensorCallback {
- //public void newReadingAvailable(@NonLocalRemote SmartthingsSensor _sensor) throws RemoteException;
- public void newReadingAvailable(int _value, boolean _activeValue);
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue);
}
@config private IoTSet<IoTDeviceAddress> devUdpAddress;
@config private IoTSet<IoTZigbeeAddress> devZigbeeAddress;
+ private int sensorId = 0;
+
public WaterLeakSensor(IoTSet<IoTDeviceAddress> dSet, IoTSet<IoTZigbeeAddress> zigSet) {
devUdpAddress = dSet;
devZigbeeAddress = zigSet;
}
}
+ public void setId(int id) {
+
+ sensorId = id;
+
+ }
+
+ public int getId() {
+
+ return sensorId;
+
+ }
+
public int getValue() {
int tmp = 0;
gettingLatestDataMutex.release();
try {
for (SmartthingsSensorCallback cb : callbackList) {
- cb.newReadingAvailable(this.getValue(), this.isActiveValue());
+ cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
}
} catch (Exception e) {
e.printStackTrace();
//000d6f000bbd5398
//000d6f00057c92a7
- public void newReadingAvailable(int _value, boolean _activeValue) {
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
System.out.println("New Message!!!!");
System.out.println("motion : "+ _value);
System.out.println("active? : "+ _activeValue);
private static final String MY_IP_ADDRESS = "192.168.2.108";
public static final String DEVIDE_MAC_ADDRESS = "000d6f000bbd3413"; //Multipurpose sensor
- public void newReadingAvailable(int _value, boolean _activeValue) {
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
System.out.println("New Message!!!!");
System.out.println("multipurpose : "+ _value);
System.out.println("active? : "+ _activeValue);
private static final int PORT_NUMBER = 5959;
public static final String DEVIDE_MAC_ADDRESS = "000d6f000ada75e3"; //water leak
- public void newReadingAvailable(int _value, boolean _activeValue) {
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
System.out.println("New Message!!!!");
System.out.println("water leak : "+ _value);
System.out.println("active? : "+ _activeValue);
PHONY += run-compiler-room
run-compiler-room:
- cp ../localconfig/iotpolicy/LabRoom/*.pol $(BIN_DIR)/iotpolicy/
- cp ../localconfig/iotpolicy/LabRoom/*.req $(BIN_DIR)/iotpolicy/
- cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler labroom.pol roomsmart.req -java Java
+ cp ../localconfig/iotpolicy/Room/*.pol $(BIN_DIR)/iotpolicy/
+ cp ../localconfig/iotpolicy/Room/*.req $(BIN_DIR)/iotpolicy/
+ cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler room.pol roomsmart.req -java Java
PHONY += run-compiler-cam
run-compiler-cam:
cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler sprucesensor.pol smartsensor.req moisturesensorcallback.pol moisturesensorcallback.req -java Java
# SpeakerController
-PHONY += run-compiler-audiorm
-run-compiler-audiorm:
- cp ../localconfig/iotpolicy/AudioRoom/*.pol $(BIN_DIR)/iotpolicy/
- cp ../localconfig/iotpolicy/AudioRoom/*.req $(BIN_DIR)/iotpolicy/
- cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler audioroom.pol roomsmart.req -java Java
-
PHONY += run-compiler-spkr
run-compiler-spkr:
cp ../localconfig/iotpolicy/IHome/*.pol $(BIN_DIR)/iotpolicy/
cp ../localconfig/iotpolicy/GPSPhoneGateway/*.req $(BIN_DIR)/iotpolicy/
cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler gpsphonegateway.pol smartgpsgateway.req gpsgatewaycallback.pol smartgpsgatewaycallback.req -java Java
+# HomeSecurityController
+PHONY += run-compiler-alarm
+run-compiler-alarm:
+ cp ../localconfig/iotpolicy/EspAlarm/*.pol $(BIN_DIR)/iotpolicy/
+ cp ../localconfig/iotpolicy/EspAlarm/*.req $(BIN_DIR)/iotpolicy/
+ cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler espalarm.pol smartalarm.req -java Java
+
+PHONY += run-compiler-smart
+run-compiler-smart:
+ cp ../localconfig/iotpolicy/SmartthingsSensor/*.pol $(BIN_DIR)/iotpolicy/
+ cp ../localconfig/iotpolicy/SmartthingsSensor/*.req $(BIN_DIR)/iotpolicy/
+ cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler smartthingssensor.pol smartthingssensor.req smartthingssensorcallback.pol smartthingssensorcallback.req -java Java
+
# TODO: Can remove this later - just to test-compile the resulted files from the compiler
PHONY += compile
compile:
+++ /dev/null
-public interface Room {
-
- public int getRoomID();
-
- capability Basic {
- description = "Get room ID";
- method = "getRoomID()";
- }
-}
-
-
+++ /dev/null
-
-requires Room with Basic as interface RoomSmart;
-
--- /dev/null
+public interface Alarm {
+
+ public void init();
+ public void setZone(int _zone, boolean _onOff, int _onDurationSeconds);
+ public List<ZoneState> getZoneStates();
+ public int getNumberOfZones();
+ public boolean doesHaveZoneTimers();
+
+ capability Initialize {
+ description = "Initialize object";
+ method = "init()";
+ }
+
+ capability Zone {
+ description = "Manage zones";
+ method = "setZone(int _zone, boolean _onOff, int _onDurationSeconds)";
+ method = "getZoneStates()";
+ method = "getNumberOfZones()";
+ method = "doesHaveZoneTimers()";
+ }
+
+ struct ZoneState {
+ int zoneNumber;
+ boolean onOffState;
+ int duration;
+ }
+}
+
+
--- /dev/null
+
+requires Alarm with Initialize, Zone as interface AlarmSmart;
+
+++ /dev/null
-public interface Room {
-
- public int getRoomID();
-
- capability Basic {
- description = "Get room ID";
- method = "getRoomID()";
- }
-}
-
-
+++ /dev/null
-
-requires Room with Basic as interface RoomSmart;
-
--- /dev/null
+public interface Room {
+
+ public int getRoomID();
+
+ capability Basic {
+ description = "Get room ID";
+ method = "getRoomID()";
+ }
+}
+
+
--- /dev/null
+
+requires Room with Basic as interface RoomSmart;
+
--- /dev/null
+public interface SmartthingsSensor {
+
+ public void init();
+ public int getValue();
+ public boolean isActiveValue();
+ public long getTimestampOfLastReading();
+ public void setId(int id);
+ public int getId();
+ public void registerCallback(SmartthingsSensorCallback _callbackTo);
+
+ capability Initialize {
+ description = "Initialize object";
+ method = "init()";
+ method = "registerCallback(SmartthingsSensorCallback _callbackTo)";
+ }
+
+ capability Value {
+ description = "Handle value";
+ method = "getValue()";
+ method = "isActiveValue()";
+ method = "getTimestampOfLastReading()";
+ }
+
+ capability SensorId {
+ description = "Manage sensor Id";
+ method = "setId(int id)";
+ method = "getId()";
+ }
+}
+
+
--- /dev/null
+
+requires SmartthingsSensor with Initialize, Value, SensorId as interface SmartthingsSensorSmart;
+
--- /dev/null
+public interface SmartthingsSensorCallback {
+
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue);
+
+ capability Callback {
+ description = "Callback method";
+ method = "newReadingAvailable(int _sensorId, int _value, boolean _activeValue)";
+ }
+}
+
+
--- /dev/null
+
+requires SmartthingsSensorCallback with Callback as interface SmartthingsSensorSmartCallback;
+
Room
OTHER
Camera
+WHERE
+TYPE_SOURCE LIKE 'HomeRoom%'
;
SELECT * FROM
Room
WHERE
-TYPE='LabRoom'
+TYPE='HomeRoom'
;