From dc73888086445b67a93e0651199411fe4d8b1aa0 Mon Sep 17 00:00:00 2001 From: rtrimana Date: Thu, 5 Jan 2017 17:08:30 -0800 Subject: [PATCH] Adjusting files in ZigbeeTest; preparing things for 4th benchmark, i.e. generating stubs and skeletons, fixing code, checking in mysql config files, etc. --- .../AlarmSmart_Stub.java | 92 +++ .../CameraCallback_CallbackSkeleton.java | 44 ++ .../CameraSmart_Stub.java | 184 ++++++ .../HomeSecurityController.config | 1 + .../HomeSecurityController.java | 539 ++++++++++++++++++ benchmarks/HomeSecurityController/Makefile | 19 + .../MotionDetection.java | 463 +++++++++++++++ .../MotionDetectionCallback.java | 20 + .../RoomSmart_Stub.java | 36 ++ ...thingsSensorCallback_CallbackSkeleton.java | 44 ++ .../SmartthingsSensorSmart_Stub.java | 140 +++++ .../IrrigationController/MotionDetection.java | 6 +- .../MotionDetectionCallback.java | 12 +- benchmarks/Makefile | 6 +- .../MotionDetection.java | 6 +- .../MotionDetectionCallback.java | 7 +- .../drivers/EspAlarm/Alarm_Skeleton.java | 123 ++++ benchmarks/drivers/EspAlarm/EspAlarm.config | 4 + benchmarks/drivers/EspAlarm/EspAlarm.java | 372 ++++++++++++ benchmarks/drivers/HomeRoom/HomeRoom.config | 4 + benchmarks/drivers/HomeRoom/HomeRoom.java | 27 + .../drivers/HomeRoom/Room_Skeleton.java | 63 ++ benchmarks/drivers/Makefile | 32 +- .../drivers/MotionSensor/MotionSensor.config | 4 + .../drivers/MotionSensor/MotionSensor.java | 240 ++++++++ ...hingsSensorSmartCallback_CallbackStub.java | 36 ++ .../SmartthingsSensor_Skeleton.java | 151 +++++ .../MultipurposeSensor.config | 4 + .../MultipurposeSensor.java | 237 ++++++++ ...hingsSensorSmartCallback_CallbackStub.java | 36 ++ .../SmartthingsSensor_Skeleton.java | 151 +++++ ...hingsSensorSmartCallback_CallbackStub.java | 36 ++ .../SmartthingsSensor_Skeleton.java | 151 +++++ .../WaterLeakSensor/WaterLeakSensor.config | 4 + .../WaterLeakSensor/WaterLeakSensor.java | 238 ++++++++ benchmarks/interfaces/Alarm.java | 12 + benchmarks/interfaces/AlarmSmart.java | 13 + benchmarks/interfaces/SmartthingsSensor.java | 14 + .../interfaces/SmartthingsSensorCallback.java | 8 + .../interfaces/SmartthingsSensorSmart.java | 15 + .../SmartthingsSensorSmartCallback.java | 9 + benchmarks/other/ZigbeeTest/MotionSensor.java | 16 +- .../other/ZigbeeTest/MultipurposeSensor.java | 16 +- .../other/ZigbeeTest/SmartthingsSensor.java | 3 + .../ZigbeeTest/SmartthingsSensorCallback.java | 3 +- .../other/ZigbeeTest/WaterLeakSensor.java | 16 +- .../other/ZigbeeTest/ZigbeeTest_motion.java | 2 +- .../ZigbeeTest/ZigbeeTest_multipurpose.java | 2 +- .../ZigbeeTest/ZigbeeTest_waterleak.java | 2 +- iotjava/Makefile | 25 +- localconfig/iotpolicy/EspAlarm/espalarm.pol | 29 + localconfig/iotpolicy/EspAlarm/smartalarm.req | 3 + localconfig/iotpolicy/LabRoom/labroom.pol | 11 - localconfig/iotpolicy/LabRoom/roomsmart.req | 3 - .../audioroom.pol => Room/room.pol} | 0 .../{AudioRoom => Room}/roomsmart.req | 0 .../SmartthingsSensor/smartthingssensor.pol | 31 + .../SmartthingsSensor/smartthingssensor.req | 3 + .../smartthingssensorcallback.pol | 11 + .../smartthingssensorcallback.req | 3 + localconfig/mysql/roomCameraRelation.config | 2 + localconfig/mysql/roomSet.config | 2 +- others/Mysql/IoTMain.gz | Bin 5046 -> 5206 bytes 63 files changed, 3732 insertions(+), 54 deletions(-) create mode 100644 benchmarks/HomeSecurityController/AlarmSmart_Stub.java create mode 100644 benchmarks/HomeSecurityController/CameraCallback_CallbackSkeleton.java create mode 100644 benchmarks/HomeSecurityController/CameraSmart_Stub.java create mode 100644 benchmarks/HomeSecurityController/HomeSecurityController.config create mode 100644 benchmarks/HomeSecurityController/HomeSecurityController.java create mode 100644 benchmarks/HomeSecurityController/Makefile create mode 100644 benchmarks/HomeSecurityController/MotionDetection.java create mode 100644 benchmarks/HomeSecurityController/MotionDetectionCallback.java create mode 100644 benchmarks/HomeSecurityController/RoomSmart_Stub.java create mode 100644 benchmarks/HomeSecurityController/SmartthingsSensorCallback_CallbackSkeleton.java create mode 100644 benchmarks/HomeSecurityController/SmartthingsSensorSmart_Stub.java create mode 100644 benchmarks/drivers/EspAlarm/Alarm_Skeleton.java create mode 100644 benchmarks/drivers/EspAlarm/EspAlarm.config create mode 100644 benchmarks/drivers/EspAlarm/EspAlarm.java create mode 100644 benchmarks/drivers/HomeRoom/HomeRoom.config create mode 100644 benchmarks/drivers/HomeRoom/HomeRoom.java create mode 100644 benchmarks/drivers/HomeRoom/Room_Skeleton.java create mode 100644 benchmarks/drivers/MotionSensor/MotionSensor.config create mode 100644 benchmarks/drivers/MotionSensor/MotionSensor.java create mode 100644 benchmarks/drivers/MotionSensor/SmartthingsSensorSmartCallback_CallbackStub.java create mode 100644 benchmarks/drivers/MotionSensor/SmartthingsSensor_Skeleton.java create mode 100644 benchmarks/drivers/MultipurposeSensor/MultipurposeSensor.config create mode 100644 benchmarks/drivers/MultipurposeSensor/MultipurposeSensor.java create mode 100644 benchmarks/drivers/MultipurposeSensor/SmartthingsSensorSmartCallback_CallbackStub.java create mode 100644 benchmarks/drivers/MultipurposeSensor/SmartthingsSensor_Skeleton.java create mode 100644 benchmarks/drivers/WaterLeakSensor/SmartthingsSensorSmartCallback_CallbackStub.java create mode 100644 benchmarks/drivers/WaterLeakSensor/SmartthingsSensor_Skeleton.java create mode 100644 benchmarks/drivers/WaterLeakSensor/WaterLeakSensor.config create mode 100644 benchmarks/drivers/WaterLeakSensor/WaterLeakSensor.java create mode 100644 benchmarks/interfaces/Alarm.java create mode 100644 benchmarks/interfaces/AlarmSmart.java create mode 100644 benchmarks/interfaces/SmartthingsSensor.java create mode 100644 benchmarks/interfaces/SmartthingsSensorCallback.java create mode 100644 benchmarks/interfaces/SmartthingsSensorSmart.java create mode 100644 benchmarks/interfaces/SmartthingsSensorSmartCallback.java create mode 100644 localconfig/iotpolicy/EspAlarm/espalarm.pol create mode 100644 localconfig/iotpolicy/EspAlarm/smartalarm.req delete mode 100644 localconfig/iotpolicy/LabRoom/labroom.pol delete mode 100644 localconfig/iotpolicy/LabRoom/roomsmart.req rename localconfig/iotpolicy/{AudioRoom/audioroom.pol => Room/room.pol} (100%) rename localconfig/iotpolicy/{AudioRoom => Room}/roomsmart.req (100%) create mode 100644 localconfig/iotpolicy/SmartthingsSensor/smartthingssensor.pol create mode 100644 localconfig/iotpolicy/SmartthingsSensor/smartthingssensor.req create mode 100644 localconfig/iotpolicy/SmartthingsSensor/smartthingssensorcallback.pol create mode 100644 localconfig/iotpolicy/SmartthingsSensor/smartthingssensorcallback.req diff --git a/benchmarks/HomeSecurityController/AlarmSmart_Stub.java b/benchmarks/HomeSecurityController/AlarmSmart_Stub.java new file mode 100644 index 0000000..3dc3500 --- /dev/null +++ b/benchmarks/HomeSecurityController/AlarmSmart_Stub.java @@ -0,0 +1,92 @@ +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 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 structRet = new ArrayList(); + 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; + } + +} diff --git a/benchmarks/HomeSecurityController/CameraCallback_CallbackSkeleton.java b/benchmarks/HomeSecurityController/CameraCallback_CallbackSkeleton.java new file mode 100644 index 0000000..a980927 --- /dev/null +++ b/benchmarks/HomeSecurityController/CameraCallback_CallbackSkeleton.java @@ -0,0 +1,44 @@ +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!"); + } + } + +} diff --git a/benchmarks/HomeSecurityController/CameraSmart_Stub.java b/benchmarks/HomeSecurityController/CameraSmart_Stub.java new file mode 100644 index 0000000..d58dfba --- /dev/null +++ b/benchmarks/HomeSecurityController/CameraSmart_Stub.java @@ -0,0 +1,184 @@ +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 listCallbackObj; + private static int objIdCnt = 0; + private final static int object0Id = 0; //CameraSmartCallback + private static Integer[] object0Permission = { 0 }; + private static List 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(Arrays.asList(object0Permission)); + listCallbackObj = new ArrayList(); + 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 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 enumRetVal = new ArrayList(); + for (int i = 0; i < retLen; i++) { + enumRetVal.add(enumVals[retEnum[i]]); + } + return enumRetVal; + } + +} diff --git a/benchmarks/HomeSecurityController/HomeSecurityController.config b/benchmarks/HomeSecurityController/HomeSecurityController.config new file mode 100644 index 0000000..5a44766 --- /dev/null +++ b/benchmarks/HomeSecurityController/HomeSecurityController.config @@ -0,0 +1 @@ +ADDITIONAL_ZIP_FILE=No diff --git a/benchmarks/HomeSecurityController/HomeSecurityController.java b/benchmarks/HomeSecurityController/HomeSecurityController.java new file mode 100644 index 0000000..5129e4a --- /dev/null +++ b/benchmarks/HomeSecurityController/HomeSecurityController.java @@ -0,0 +1,539 @@ +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 + * @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 + *

+ * 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 smartSensorsSet; + @config private IoTSet camSet; + @config private IoTSet alarmSet; + @config private IoTSet roomSet; + //@config private IoTSet doorlockSet; + //@config private IoTSet outletSet; + + @config private IoTRelation roomSensorRelation; + @config private IoTRelation roomCameraRelation; + //@config private IoTRelation roomDoorLockRelation; + //@config private IoTRelation roomOutletRelation; + + /******************************************************************************************************************************************* + ** + ** Variables + ** + *******************************************************************************************************************************************/ + long lastTimeChecked = 0; + + private static int sensorId = 0; + + /******************************************************************************************************************************************* + ** + ** States data structures + ** + *******************************************************************************************************************************************/ + // Camera and motion detection + private Map camMotionDetect = + new HashMap(); + // Smartthings sensors (true = motion, leakage, etc.) + private Map senDetectStatus = + new ConcurrentHashMap(); + // Camera (true = motion) + private Map camDetectStatus = + new HashMap(); + // Doorlock (true = open - not locked) + //private Map doorlockStatus = + // new HashMap(); + // Outlet (true = on - outlet is used) + //private Map outletStatus = + // new HashMap(); + + // Alarm status + private Map alarmStatus = + new HashMap(); + + 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 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 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 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 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 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 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 + *

+ * 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 + *

+ * 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 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 + 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(); + } + } + + } + } +} + + diff --git a/benchmarks/HomeSecurityController/Makefile b/benchmarks/HomeSecurityController/Makefile new file mode 100644 index 0000000..16ca57a --- /dev/null +++ b/benchmarks/HomeSecurityController/Makefile @@ -0,0 +1,19 @@ +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) diff --git a/benchmarks/HomeSecurityController/MotionDetection.java b/benchmarks/HomeSecurityController/MotionDetection.java new file mode 100644 index 0000000..dceeb7f --- /dev/null +++ b/benchmarks/HomeSecurityController/MotionDetection.java @@ -0,0 +1,463 @@ +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 + * @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 + callbackList = new ArrayList(); + + // 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) { + + // } + + // } +} + diff --git a/benchmarks/HomeSecurityController/MotionDetectionCallback.java b/benchmarks/HomeSecurityController/MotionDetectionCallback.java new file mode 100644 index 0000000..9ee6906 --- /dev/null +++ b/benchmarks/HomeSecurityController/MotionDetectionCallback.java @@ -0,0 +1,20 @@ +package HomeSecurityController; + +/** Interface MotionDetectionCallback for allowing callbacks from the MotionDetection class. + * + * + * @author Ali Younis + * @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); +} diff --git a/benchmarks/HomeSecurityController/RoomSmart_Stub.java b/benchmarks/HomeSecurityController/RoomSmart_Stub.java new file mode 100644 index 0000000..0c04049 --- /dev/null +++ b/benchmarks/HomeSecurityController/RoomSmart_Stub.java @@ -0,0 +1,36 @@ +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; + } + +} diff --git a/benchmarks/HomeSecurityController/SmartthingsSensorCallback_CallbackSkeleton.java b/benchmarks/HomeSecurityController/SmartthingsSensorCallback_CallbackSkeleton.java new file mode 100644 index 0000000..6e09471 --- /dev/null +++ b/benchmarks/HomeSecurityController/SmartthingsSensorCallback_CallbackSkeleton.java @@ -0,0 +1,44 @@ +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!"); + } + } + +} diff --git a/benchmarks/HomeSecurityController/SmartthingsSensorSmart_Stub.java b/benchmarks/HomeSecurityController/SmartthingsSensorSmart_Stub.java new file mode 100644 index 0000000..87eff75 --- /dev/null +++ b/benchmarks/HomeSecurityController/SmartthingsSensorSmart_Stub.java @@ -0,0 +1,140 @@ +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 listCallbackObj; + private int objIdCnt = 0; + private final static int object0Id = 0; //SmartthingsSensorSmartCallback + private static Integer[] object0Permission = { 0 }; + private static List 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(Arrays.asList(object0Permission)); + listCallbackObj = new ArrayList(); + 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); + } + +} diff --git a/benchmarks/IrrigationController/MotionDetection.java b/benchmarks/IrrigationController/MotionDetection.java index 767dd67..0ae1e70 100644 --- a/benchmarks/IrrigationController/MotionDetection.java +++ b/benchmarks/IrrigationController/MotionDetection.java @@ -416,10 +416,10 @@ class MotionDetection extends UnicastRemoteObject implements CameraCallback { // 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 { diff --git a/benchmarks/IrrigationController/MotionDetectionCallback.java b/benchmarks/IrrigationController/MotionDetectionCallback.java index d7dfb83..3f89aa2 100644 --- a/benchmarks/IrrigationController/MotionDetectionCallback.java +++ b/benchmarks/IrrigationController/MotionDetectionCallback.java @@ -8,19 +8,13 @@ package IrrigationController; * @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); } diff --git a/benchmarks/Makefile b/benchmarks/Makefile index f4cbd4c..5ed4629 100644 --- a/benchmarks/Makefile +++ b/benchmarks/Makefile @@ -4,7 +4,7 @@ BOOFJARS := $(BOOFDIR)/BoofCV-feature-0.21.jar:$(BOOFDIR)/BoofCV-io-0.21.jar:$(B include $(BASE)/common.mk -all: interfaces annotation drivers Lifxtest SmartLights Irrigation Speaker +all: interfaces annotation drivers Lifxtest SmartLights Irrigation Speaker HomeSecurity PHONY += interfaces interfaces: @@ -34,4 +34,8 @@ PHONY += Speaker Speaker: $(MAKE) -C SpeakerController +PHONY += HomeSecurity +HomeSecurity: + $(MAKE) -C HomeSecurityController + .PHONY: $(PHONY) diff --git a/benchmarks/SmartLightsController/MotionDetection.java b/benchmarks/SmartLightsController/MotionDetection.java index d9c608e..bd47350 100644 --- a/benchmarks/SmartLightsController/MotionDetection.java +++ b/benchmarks/SmartLightsController/MotionDetection.java @@ -416,10 +416,10 @@ class MotionDetection implements CameraCallback { // 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 { diff --git a/benchmarks/SmartLightsController/MotionDetectionCallback.java b/benchmarks/SmartLightsController/MotionDetectionCallback.java index 5517abc..98d9636 100644 --- a/benchmarks/SmartLightsController/MotionDetectionCallback.java +++ b/benchmarks/SmartLightsController/MotionDetectionCallback.java @@ -8,10 +8,7 @@ package SmartLightsController; * @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. * @@ -19,5 +16,5 @@ public interface MotionDetectionCallback extends Remote { * * @return [void] None. */ - public void motionDetected(MotionDetection _md) throws RemoteException; + public void motionDetected(MotionDetection _md); } diff --git a/benchmarks/drivers/EspAlarm/Alarm_Skeleton.java b/benchmarks/drivers/EspAlarm/Alarm_Skeleton.java new file mode 100644 index 0000000..8d8ab89 --- /dev/null +++ b/benchmarks/drivers/EspAlarm/Alarm_Skeleton.java @@ -0,0 +1,123 @@ +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 set0Allowed; + + + public Alarm_Skeleton(Alarm _mainObj, String _callbackAddress, int _port) throws Exception { + mainObj = _mainObj; + callbackAddress = _callbackAddress; + rmiObj = new IoTRMIObject(_port); + set0Allowed = new ArrayList(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 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 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!"); + } + } + } + +} diff --git a/benchmarks/drivers/EspAlarm/EspAlarm.config b/benchmarks/drivers/EspAlarm/EspAlarm.config new file mode 100644 index 0000000..0912d87 --- /dev/null +++ b/benchmarks/drivers/EspAlarm/EspAlarm.config @@ -0,0 +1,4 @@ +# Skeleton/original interface +INTERFACE_CLASS=Alarm +# Stub +INTERFACE_STUB_CLASS=AlarmSmart diff --git a/benchmarks/drivers/EspAlarm/EspAlarm.java b/benchmarks/drivers/EspAlarm/EspAlarm.java new file mode 100644 index 0000000..a162ed9 --- /dev/null +++ b/benchmarks/drivers/EspAlarm/EspAlarm.java @@ -0,0 +1,372 @@ +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 , Rahmadi Trimananda + * @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 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] list of the states for the zones. + */ + public List 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(); + } 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] Parsed zone data. + */ + private List parseGetResponse(byte[] _packetData) { + String recString = new String(_packetData); + List retStates = new ArrayList(); + + 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) { + + } + } + } + +} + + diff --git a/benchmarks/drivers/HomeRoom/HomeRoom.config b/benchmarks/drivers/HomeRoom/HomeRoom.config new file mode 100644 index 0000000..f10cb63 --- /dev/null +++ b/benchmarks/drivers/HomeRoom/HomeRoom.config @@ -0,0 +1,4 @@ +# Skeleton/original interface +INTERFACE_CLASS=Room +# Stub +INTERFACE_STUB_CLASS=RoomSmart diff --git a/benchmarks/drivers/HomeRoom/HomeRoom.java b/benchmarks/drivers/HomeRoom/HomeRoom.java new file mode 100644 index 0000000..5a31372 --- /dev/null +++ b/benchmarks/drivers/HomeRoom/HomeRoom.java @@ -0,0 +1,27 @@ +package iotcode.HomeRoom; + +import iotcode.interfaces.Room; + +/** AudioRoom holds room ID that tells which room it is + * in association with speakers + * + * @author Rahmadi Trimananda + * @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; + } +} diff --git a/benchmarks/drivers/HomeRoom/Room_Skeleton.java b/benchmarks/drivers/HomeRoom/Room_Skeleton.java new file mode 100644 index 0000000..7a02025 --- /dev/null +++ b/benchmarks/drivers/HomeRoom/Room_Skeleton.java @@ -0,0 +1,63 @@ +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 set0Allowed; + + + public Room_Skeleton(Room _mainObj, String _callbackAddress, int _port) throws Exception { + mainObj = _mainObj; + callbackAddress = _callbackAddress; + rmiObj = new IoTRMIObject(_port); + set0Allowed = new ArrayList(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!"); + } + } + } + +} diff --git a/benchmarks/drivers/Makefile b/benchmarks/drivers/Makefile index 08aca6d..46e189d 100644 --- a/benchmarks/drivers/Makefile +++ b/benchmarks/drivers/Makefile @@ -10,7 +10,7 @@ JFLAGS = -d $(BIN_DIR) -cp $(BIN_DIR):$(PHONEJARS):$(BOOFJARS):$(JLAYERJARS) 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 # @@ -74,4 +74,34 @@ ihome: 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) diff --git a/benchmarks/drivers/MotionSensor/MotionSensor.config b/benchmarks/drivers/MotionSensor/MotionSensor.config new file mode 100644 index 0000000..61eb381 --- /dev/null +++ b/benchmarks/drivers/MotionSensor/MotionSensor.config @@ -0,0 +1,4 @@ +# Skeleton/original interface +INTERFACE_CLASS=SmartthingsSensor +# Stub +INTERFACE_STUB_CLASS=SmartthingsSensorSmart diff --git a/benchmarks/drivers/MotionSensor/MotionSensor.java b/benchmarks/drivers/MotionSensor/MotionSensor.java new file mode 100644 index 0000000..6520de0 --- /dev/null +++ b/benchmarks/drivers/MotionSensor/MotionSensor.java @@ -0,0 +1,240 @@ +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 + * @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 devUdpAddress; + @config private IoTSet devZigbeeAddress; + + public MotionSensor(IoTSet dSet, IoTSet 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); + } +} diff --git a/benchmarks/drivers/MotionSensor/SmartthingsSensorSmartCallback_CallbackStub.java b/benchmarks/drivers/MotionSensor/SmartthingsSensorSmartCallback_CallbackStub.java new file mode 100644 index 0000000..037968d --- /dev/null +++ b/benchmarks/drivers/MotionSensor/SmartthingsSensorSmartCallback_CallbackStub.java @@ -0,0 +1,36 @@ +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); + } + +} diff --git a/benchmarks/drivers/MotionSensor/SmartthingsSensor_Skeleton.java b/benchmarks/drivers/MotionSensor/SmartthingsSensor_Skeleton.java new file mode 100644 index 0000000..4dc20e1 --- /dev/null +++ b/benchmarks/drivers/MotionSensor/SmartthingsSensor_Skeleton.java @@ -0,0 +1,151 @@ +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 set0Allowed; + + + public SmartthingsSensor_Skeleton(SmartthingsSensor _mainObj, String _callbackAddress, int _port) throws Exception { + mainObj = _mainObj; + callbackAddress = _callbackAddress; + rmiObj = new IoTRMIObject(_port); + set0Allowed = new ArrayList(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!"); + } + } + } + +} diff --git a/benchmarks/drivers/MultipurposeSensor/MultipurposeSensor.config b/benchmarks/drivers/MultipurposeSensor/MultipurposeSensor.config new file mode 100644 index 0000000..61eb381 --- /dev/null +++ b/benchmarks/drivers/MultipurposeSensor/MultipurposeSensor.config @@ -0,0 +1,4 @@ +# Skeleton/original interface +INTERFACE_CLASS=SmartthingsSensor +# Stub +INTERFACE_STUB_CLASS=SmartthingsSensorSmart diff --git a/benchmarks/drivers/MultipurposeSensor/MultipurposeSensor.java b/benchmarks/drivers/MultipurposeSensor/MultipurposeSensor.java new file mode 100644 index 0000000..d2123e3 --- /dev/null +++ b/benchmarks/drivers/MultipurposeSensor/MultipurposeSensor.java @@ -0,0 +1,237 @@ +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 + * @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 devUdpAddress; + @config private IoTSet devZigbeeAddress; + + public MultipurposeSensor(IoTSet dSet, IoTSet 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); + } +} diff --git a/benchmarks/drivers/MultipurposeSensor/SmartthingsSensorSmartCallback_CallbackStub.java b/benchmarks/drivers/MultipurposeSensor/SmartthingsSensorSmartCallback_CallbackStub.java new file mode 100644 index 0000000..6ed7f31 --- /dev/null +++ b/benchmarks/drivers/MultipurposeSensor/SmartthingsSensorSmartCallback_CallbackStub.java @@ -0,0 +1,36 @@ +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); + } + +} diff --git a/benchmarks/drivers/MultipurposeSensor/SmartthingsSensor_Skeleton.java b/benchmarks/drivers/MultipurposeSensor/SmartthingsSensor_Skeleton.java new file mode 100644 index 0000000..db2f2d6 --- /dev/null +++ b/benchmarks/drivers/MultipurposeSensor/SmartthingsSensor_Skeleton.java @@ -0,0 +1,151 @@ +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 set0Allowed; + + + public SmartthingsSensor_Skeleton(SmartthingsSensor _mainObj, String _callbackAddress, int _port) throws Exception { + mainObj = _mainObj; + callbackAddress = _callbackAddress; + rmiObj = new IoTRMIObject(_port); + set0Allowed = new ArrayList(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!"); + } + } + } + +} diff --git a/benchmarks/drivers/WaterLeakSensor/SmartthingsSensorSmartCallback_CallbackStub.java b/benchmarks/drivers/WaterLeakSensor/SmartthingsSensorSmartCallback_CallbackStub.java new file mode 100644 index 0000000..ac06a99 --- /dev/null +++ b/benchmarks/drivers/WaterLeakSensor/SmartthingsSensorSmartCallback_CallbackStub.java @@ -0,0 +1,36 @@ +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); + } + +} diff --git a/benchmarks/drivers/WaterLeakSensor/SmartthingsSensor_Skeleton.java b/benchmarks/drivers/WaterLeakSensor/SmartthingsSensor_Skeleton.java new file mode 100644 index 0000000..e52f126 --- /dev/null +++ b/benchmarks/drivers/WaterLeakSensor/SmartthingsSensor_Skeleton.java @@ -0,0 +1,151 @@ +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 set0Allowed; + + + public SmartthingsSensor_Skeleton(SmartthingsSensor _mainObj, String _callbackAddress, int _port) throws Exception { + mainObj = _mainObj; + callbackAddress = _callbackAddress; + rmiObj = new IoTRMIObject(_port); + set0Allowed = new ArrayList(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!"); + } + } + } + +} diff --git a/benchmarks/drivers/WaterLeakSensor/WaterLeakSensor.config b/benchmarks/drivers/WaterLeakSensor/WaterLeakSensor.config new file mode 100644 index 0000000..61eb381 --- /dev/null +++ b/benchmarks/drivers/WaterLeakSensor/WaterLeakSensor.config @@ -0,0 +1,4 @@ +# Skeleton/original interface +INTERFACE_CLASS=SmartthingsSensor +# Stub +INTERFACE_STUB_CLASS=SmartthingsSensorSmart diff --git a/benchmarks/drivers/WaterLeakSensor/WaterLeakSensor.java b/benchmarks/drivers/WaterLeakSensor/WaterLeakSensor.java new file mode 100644 index 0000000..ca85856 --- /dev/null +++ b/benchmarks/drivers/WaterLeakSensor/WaterLeakSensor.java @@ -0,0 +1,238 @@ +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 + * @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 devUdpAddress; + @config private IoTSet devZigbeeAddress; + + public WaterLeakSensor(IoTSet dSet, IoTSet 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); + } +} diff --git a/benchmarks/interfaces/Alarm.java b/benchmarks/interfaces/Alarm.java new file mode 100644 index 0000000..ab55c2b --- /dev/null +++ b/benchmarks/interfaces/Alarm.java @@ -0,0 +1,12 @@ +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 getZoneStates(); + public int getNumberOfZones(); + public boolean doesHaveZoneTimers(); +} diff --git a/benchmarks/interfaces/AlarmSmart.java b/benchmarks/interfaces/AlarmSmart.java new file mode 100644 index 0000000..103e29a --- /dev/null +++ b/benchmarks/interfaces/AlarmSmart.java @@ -0,0 +1,13 @@ +package iotcode.interfaces; + +import java.util.List; +import java.util.ArrayList; + +public interface AlarmSmart { + + public boolean doesHaveZoneTimers(); + public List getZoneStates(); + public void init(); + public void setZone(int _zone, boolean _onOff, int _onDurationSeconds); + public int getNumberOfZones(); +} diff --git a/benchmarks/interfaces/SmartthingsSensor.java b/benchmarks/interfaces/SmartthingsSensor.java new file mode 100644 index 0000000..a951a6c --- /dev/null +++ b/benchmarks/interfaces/SmartthingsSensor.java @@ -0,0 +1,14 @@ +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); +} diff --git a/benchmarks/interfaces/SmartthingsSensorCallback.java b/benchmarks/interfaces/SmartthingsSensorCallback.java new file mode 100644 index 0000000..853dd12 --- /dev/null +++ b/benchmarks/interfaces/SmartthingsSensorCallback.java @@ -0,0 +1,8 @@ +package iotcode.interfaces; + +import java.util.List; +import java.util.ArrayList; + +public interface SmartthingsSensorCallback { + public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue); +} diff --git a/benchmarks/interfaces/SmartthingsSensorSmart.java b/benchmarks/interfaces/SmartthingsSensorSmart.java new file mode 100644 index 0000000..2c70dbf --- /dev/null +++ b/benchmarks/interfaces/SmartthingsSensorSmart.java @@ -0,0 +1,15 @@ +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(); +} diff --git a/benchmarks/interfaces/SmartthingsSensorSmartCallback.java b/benchmarks/interfaces/SmartthingsSensorSmartCallback.java new file mode 100644 index 0000000..314d583 --- /dev/null +++ b/benchmarks/interfaces/SmartthingsSensorSmartCallback.java @@ -0,0 +1,9 @@ +package iotcode.interfaces; + +import java.util.List; +import java.util.ArrayList; + +public interface SmartthingsSensorSmartCallback { + + public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue); +} diff --git a/benchmarks/other/ZigbeeTest/MotionSensor.java b/benchmarks/other/ZigbeeTest/MotionSensor.java index 2ad5490..68dfe29 100644 --- a/benchmarks/other/ZigbeeTest/MotionSensor.java +++ b/benchmarks/other/ZigbeeTest/MotionSensor.java @@ -38,6 +38,8 @@ public class MotionSensor implements IoTZigbeeCallback, SmartthingsSensor { private List < SmartthingsSensorCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorCallback > (); + private int sensorId = 0; + @config private IoTSet devUdpAddress; @config private IoTSet devZigbeeAddress; @@ -138,6 +140,18 @@ public class MotionSensor implements IoTZigbeeCallback, SmartthingsSensor { } } + public void setId(int id) { + + sensorId = id; + + } + + public int getId() { + + return sensorId; + + } + public int getValue() { int tmp = 0; @@ -202,7 +216,7 @@ public class MotionSensor implements IoTZigbeeCallback, SmartthingsSensor { 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(); diff --git a/benchmarks/other/ZigbeeTest/MultipurposeSensor.java b/benchmarks/other/ZigbeeTest/MultipurposeSensor.java index a21155f..0243091 100644 --- a/benchmarks/other/ZigbeeTest/MultipurposeSensor.java +++ b/benchmarks/other/ZigbeeTest/MultipurposeSensor.java @@ -38,6 +38,8 @@ public class MultipurposeSensor implements IoTZigbeeCallback, SmartthingsSensor private List < SmartthingsSensorCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorCallback > (); + private int sensorId = 0; + @config private IoTSet devUdpAddress; @config private IoTSet devZigbeeAddress; @@ -136,6 +138,18 @@ public class MultipurposeSensor implements IoTZigbeeCallback, SmartthingsSensor } } + public void setId(int id) { + + sensorId = id; + + } + + public int getId() { + + return sensorId; + + } + public int getValue() { int tmp = 0; @@ -198,7 +212,7 @@ public class MultipurposeSensor implements IoTZigbeeCallback, SmartthingsSensor 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(); diff --git a/benchmarks/other/ZigbeeTest/SmartthingsSensor.java b/benchmarks/other/ZigbeeTest/SmartthingsSensor.java index d739f19..aba8819 100644 --- a/benchmarks/other/ZigbeeTest/SmartthingsSensor.java +++ b/benchmarks/other/ZigbeeTest/SmartthingsSensor.java @@ -46,6 +46,9 @@ public interface SmartthingsSensor extends Remote { */ 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 * diff --git a/benchmarks/other/ZigbeeTest/SmartthingsSensorCallback.java b/benchmarks/other/ZigbeeTest/SmartthingsSensorCallback.java index 2367da1..5342538 100644 --- a/benchmarks/other/ZigbeeTest/SmartthingsSensorCallback.java +++ b/benchmarks/other/ZigbeeTest/SmartthingsSensorCallback.java @@ -11,6 +11,5 @@ 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); } diff --git a/benchmarks/other/ZigbeeTest/WaterLeakSensor.java b/benchmarks/other/ZigbeeTest/WaterLeakSensor.java index 75923a4..8a56aab 100644 --- a/benchmarks/other/ZigbeeTest/WaterLeakSensor.java +++ b/benchmarks/other/ZigbeeTest/WaterLeakSensor.java @@ -41,6 +41,8 @@ public class WaterLeakSensor implements IoTZigbeeCallback, SmartthingsSensor { @config private IoTSet devUdpAddress; @config private IoTSet devZigbeeAddress; + private int sensorId = 0; + public WaterLeakSensor(IoTSet dSet, IoTSet zigSet) { devUdpAddress = dSet; devZigbeeAddress = zigSet; @@ -136,6 +138,18 @@ public class WaterLeakSensor implements IoTZigbeeCallback, SmartthingsSensor { } } + public void setId(int id) { + + sensorId = id; + + } + + public int getId() { + + return sensorId; + + } + public int getValue() { int tmp = 0; @@ -199,7 +213,7 @@ public class WaterLeakSensor implements IoTZigbeeCallback, SmartthingsSensor { 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(); diff --git a/benchmarks/other/ZigbeeTest/ZigbeeTest_motion.java b/benchmarks/other/ZigbeeTest/ZigbeeTest_motion.java index 832e0be..7dde4b1 100644 --- a/benchmarks/other/ZigbeeTest/ZigbeeTest_motion.java +++ b/benchmarks/other/ZigbeeTest/ZigbeeTest_motion.java @@ -17,7 +17,7 @@ public class ZigbeeTest_motion implements SmartthingsSensorCallback { //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); diff --git a/benchmarks/other/ZigbeeTest/ZigbeeTest_multipurpose.java b/benchmarks/other/ZigbeeTest/ZigbeeTest_multipurpose.java index 8265f6b..bec2d37 100644 --- a/benchmarks/other/ZigbeeTest/ZigbeeTest_multipurpose.java +++ b/benchmarks/other/ZigbeeTest/ZigbeeTest_multipurpose.java @@ -15,7 +15,7 @@ public class ZigbeeTest_multipurpose implements SmartthingsSensorCallback { 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); diff --git a/benchmarks/other/ZigbeeTest/ZigbeeTest_waterleak.java b/benchmarks/other/ZigbeeTest/ZigbeeTest_waterleak.java index 856fe20..5064290 100644 --- a/benchmarks/other/ZigbeeTest/ZigbeeTest_waterleak.java +++ b/benchmarks/other/ZigbeeTest/ZigbeeTest_waterleak.java @@ -16,7 +16,7 @@ public class ZigbeeTest_waterleak implements SmartthingsSensorCallback { 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); diff --git a/iotjava/Makefile b/iotjava/Makefile index a0a67f1..9a5fb1f 100644 --- a/iotjava/Makefile +++ b/iotjava/Makefile @@ -41,9 +41,9 @@ run-compiler-lifx: 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: @@ -77,12 +77,6 @@ run-compiler-moist: 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/ @@ -95,6 +89,19 @@ run-compiler-ggw: 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: diff --git a/localconfig/iotpolicy/EspAlarm/espalarm.pol b/localconfig/iotpolicy/EspAlarm/espalarm.pol new file mode 100644 index 0000000..ce7742f --- /dev/null +++ b/localconfig/iotpolicy/EspAlarm/espalarm.pol @@ -0,0 +1,29 @@ +public interface Alarm { + + public void init(); + public void setZone(int _zone, boolean _onOff, int _onDurationSeconds); + public List 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; + } +} + + diff --git a/localconfig/iotpolicy/EspAlarm/smartalarm.req b/localconfig/iotpolicy/EspAlarm/smartalarm.req new file mode 100644 index 0000000..f703a43 --- /dev/null +++ b/localconfig/iotpolicy/EspAlarm/smartalarm.req @@ -0,0 +1,3 @@ + +requires Alarm with Initialize, Zone as interface AlarmSmart; + diff --git a/localconfig/iotpolicy/LabRoom/labroom.pol b/localconfig/iotpolicy/LabRoom/labroom.pol deleted file mode 100644 index 17f3bbd..0000000 --- a/localconfig/iotpolicy/LabRoom/labroom.pol +++ /dev/null @@ -1,11 +0,0 @@ -public interface Room { - - public int getRoomID(); - - capability Basic { - description = "Get room ID"; - method = "getRoomID()"; - } -} - - diff --git a/localconfig/iotpolicy/LabRoom/roomsmart.req b/localconfig/iotpolicy/LabRoom/roomsmart.req deleted file mode 100644 index 71de3c9..0000000 --- a/localconfig/iotpolicy/LabRoom/roomsmart.req +++ /dev/null @@ -1,3 +0,0 @@ - -requires Room with Basic as interface RoomSmart; - diff --git a/localconfig/iotpolicy/AudioRoom/audioroom.pol b/localconfig/iotpolicy/Room/room.pol similarity index 100% rename from localconfig/iotpolicy/AudioRoom/audioroom.pol rename to localconfig/iotpolicy/Room/room.pol diff --git a/localconfig/iotpolicy/AudioRoom/roomsmart.req b/localconfig/iotpolicy/Room/roomsmart.req similarity index 100% rename from localconfig/iotpolicy/AudioRoom/roomsmart.req rename to localconfig/iotpolicy/Room/roomsmart.req diff --git a/localconfig/iotpolicy/SmartthingsSensor/smartthingssensor.pol b/localconfig/iotpolicy/SmartthingsSensor/smartthingssensor.pol new file mode 100644 index 0000000..de3686a --- /dev/null +++ b/localconfig/iotpolicy/SmartthingsSensor/smartthingssensor.pol @@ -0,0 +1,31 @@ +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()"; + } +} + + diff --git a/localconfig/iotpolicy/SmartthingsSensor/smartthingssensor.req b/localconfig/iotpolicy/SmartthingsSensor/smartthingssensor.req new file mode 100644 index 0000000..8d80d3d --- /dev/null +++ b/localconfig/iotpolicy/SmartthingsSensor/smartthingssensor.req @@ -0,0 +1,3 @@ + +requires SmartthingsSensor with Initialize, Value, SensorId as interface SmartthingsSensorSmart; + diff --git a/localconfig/iotpolicy/SmartthingsSensor/smartthingssensorcallback.pol b/localconfig/iotpolicy/SmartthingsSensor/smartthingssensorcallback.pol new file mode 100644 index 0000000..0bb4b58 --- /dev/null +++ b/localconfig/iotpolicy/SmartthingsSensor/smartthingssensorcallback.pol @@ -0,0 +1,11 @@ +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)"; + } +} + + diff --git a/localconfig/iotpolicy/SmartthingsSensor/smartthingssensorcallback.req b/localconfig/iotpolicy/SmartthingsSensor/smartthingssensorcallback.req new file mode 100644 index 0000000..87fbe69 --- /dev/null +++ b/localconfig/iotpolicy/SmartthingsSensor/smartthingssensorcallback.req @@ -0,0 +1,3 @@ + +requires SmartthingsSensorCallback with Callback as interface SmartthingsSensorSmartCallback; + diff --git a/localconfig/mysql/roomCameraRelation.config b/localconfig/mysql/roomCameraRelation.config index 3297815..8b82643 100644 --- a/localconfig/mysql/roomCameraRelation.config +++ b/localconfig/mysql/roomCameraRelation.config @@ -3,4 +3,6 @@ FIRST Room OTHER Camera +WHERE +TYPE_SOURCE LIKE 'HomeRoom%' ; diff --git a/localconfig/mysql/roomSet.config b/localconfig/mysql/roomSet.config index a085212..6f5dc60 100644 --- a/localconfig/mysql/roomSet.config +++ b/localconfig/mysql/roomSet.config @@ -1,5 +1,5 @@ SELECT * FROM Room WHERE -TYPE='LabRoom' +TYPE='HomeRoom' ; diff --git a/others/Mysql/IoTMain.gz b/others/Mysql/IoTMain.gz index 4ae5fee5b2bebd3f7f9b28552470c499fd5dd966..0c9918cbd035331e598ac8cf61d242efc79c8881 100644 GIT binary patch literal 5206 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 M2b}X`TUqe{07~WZ@&Et; -- 2.34.1