Preparing 3rd benchmark for porting with capability-based RMI
authorrtrimana <rtrimana@uci.edu>
Thu, 5 Jan 2017 01:31:23 +0000 (17:31 -0800)
committerrtrimana <rtrimana@uci.edu>
Thu, 5 Jan 2017 01:31:23 +0000 (17:31 -0800)
38 files changed:
benchmarks/IrrigationController/Makefile
benchmarks/Makefile
benchmarks/SpeakerController/GPSGatewayCallback_CallbackSkeleton.java [new file with mode: 0644]
benchmarks/SpeakerController/GPSGatewaySmart_Stub.java [new file with mode: 0644]
benchmarks/SpeakerController/Makefile
benchmarks/SpeakerController/RoomSmart_Stub.java [new file with mode: 0644]
benchmarks/SpeakerController/SpeakerCallback_CallbackSkeleton.java [new file with mode: 0644]
benchmarks/SpeakerController/SpeakerController.java
benchmarks/SpeakerController/SpeakerSmart_Stub.java [new file with mode: 0644]
benchmarks/drivers/AudioRoom/AudioRoom.config [new file with mode: 0644]
benchmarks/drivers/AudioRoom/AudioRoom.java [new file with mode: 0644]
benchmarks/drivers/AudioRoom/Room_Skeleton.java [new file with mode: 0644]
benchmarks/drivers/GPSPhoneGateway/GPSPhoneGateway.config [new file with mode: 0644]
benchmarks/drivers/GPSPhoneGateway/GPSPhoneGateway.java [new file with mode: 0644]
benchmarks/drivers/GPSPhoneGateway/PhoneInfo.java [new file with mode: 0644]
benchmarks/drivers/GPSPhoneGateway/PhoneInfoInterface.java [new file with mode: 0644]
benchmarks/drivers/IHome/IHome.config [new file with mode: 0644]
benchmarks/drivers/IHome/IHome.java [new file with mode: 0644]
benchmarks/drivers/Makefile
benchmarks/interfaces/GPSGateway.java [new file with mode: 0644]
benchmarks/interfaces/GPSGatewayCallback.java [new file with mode: 0644]
benchmarks/interfaces/GPSGatewaySmart.java [new file with mode: 0644]
benchmarks/interfaces/GPSGatewaySmartCallback.java [new file with mode: 0644]
benchmarks/interfaces/Speaker.java [new file with mode: 0644]
benchmarks/interfaces/SpeakerCallback.java [new file with mode: 0644]
benchmarks/interfaces/SpeakerSmart.java [new file with mode: 0644]
benchmarks/interfaces/SpeakerSmartCallback.java [new file with mode: 0644]
iotjava/Makefile
localconfig/iotpolicy/AudioRoom/audioroom.pol [new file with mode: 0644]
localconfig/iotpolicy/AudioRoom/roomsmart.req [new file with mode: 0644]
localconfig/iotpolicy/GPSPhoneGateway/gpsgatewaycallback.pol [new file with mode: 0644]
localconfig/iotpolicy/GPSPhoneGateway/gpsphonegateway.pol [new file with mode: 0644]
localconfig/iotpolicy/GPSPhoneGateway/smartgpsgateway.req [new file with mode: 0644]
localconfig/iotpolicy/GPSPhoneGateway/smartgpsgatewaycallback.req [new file with mode: 0644]
localconfig/iotpolicy/IHome/ihome.pol [new file with mode: 0644]
localconfig/iotpolicy/IHome/smartspeaker.req [new file with mode: 0644]
localconfig/iotpolicy/IHome/smartspeakercallback.req [new file with mode: 0644]
localconfig/iotpolicy/IHome/speakercallback.pol [new file with mode: 0644]

index ff040f3563ea73d8696f6da971897cafe43b9e60..e338f79834af1c0f189e260c92019b75bfe0f706 100644 (file)
@@ -12,7 +12,7 @@ all: irrigation
 
 PHONY += irrigation
 irrigation:
-       $(JAVAC) $(JFLAGS) $(CHECKER_OPT) $(ASTUBS) *.java
+       $(JAVAC) $(JFLAGS) *.java
        cd  $(BIN_DIR)/IrrigationController; $(JAR) $(JARFLAGS) IrrigationController.jar ../IrrigationController/*.class ../iotcode/interfaces/*.class
        cp IrrigationController.config $(BIN_DIR)/IrrigationController
        cp -rf ./resources ./help_files $(BIN_DIR)/IrrigationController
index 3a130ebc12be8e16e200bde6fdbd0f567d88d67b..f4cbd4c69c601c52ccc9c8981c6a634b7338040a 100644 (file)
@@ -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
+all: interfaces annotation drivers Lifxtest SmartLights Irrigation Speaker
 
 PHONY += interfaces
 interfaces:
diff --git a/benchmarks/SpeakerController/GPSGatewayCallback_CallbackSkeleton.java b/benchmarks/SpeakerController/GPSGatewayCallback_CallbackSkeleton.java
new file mode 100644 (file)
index 0000000..91c2d15
--- /dev/null
@@ -0,0 +1,55 @@
+package SpeakerController;
+
+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 GPSGatewayCallback_CallbackSkeleton implements GPSGatewayCallback {
+
+       private GPSGatewayCallback mainObj;
+       private int objectId = 0;
+       private String callbackAddress;
+       
+
+       public GPSGatewayCallback_CallbackSkeleton(GPSGatewayCallback _mainObj, String _callbackAddress, int _objectId) throws Exception {
+               callbackAddress = _callbackAddress;
+               mainObj = _mainObj;
+               objectId = _objectId;
+       }
+
+       public void newRoomIDRetrieved(int _roomIdentifier) {
+               mainObj.newRoomIDRetrieved(_roomIdentifier);
+       }
+
+       public void newRingStatusRetrieved(boolean _ringStatus) {
+               mainObj.newRingStatusRetrieved(_ringStatus);
+       }
+
+       public void ___newRoomIDRetrieved(IoTRMIObject rmiObj) {
+               Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class }, 
+               new Class<?>[] { null });
+               newRoomIDRetrieved((int) paramObj[0]);
+       }
+
+       public void ___newRingStatusRetrieved(IoTRMIObject rmiObj) {
+               Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { boolean.class }, 
+               new Class<?>[] { null });
+               newRingStatusRetrieved((boolean) paramObj[0]);
+       }
+
+       public void invokeMethod(IoTRMIObject rmiObj) throws IOException {
+               int methodId = rmiObj.getMethodId();
+               switch (methodId) {
+                       case 0: ___newRoomIDRetrieved(rmiObj); break;
+                       case 1: ___newRingStatusRetrieved(rmiObj); break;
+                       default: 
+                       throw new Error("Method Id " + methodId + " not recognized!");
+               }
+       }
+
+}
diff --git a/benchmarks/SpeakerController/GPSGatewaySmart_Stub.java b/benchmarks/SpeakerController/GPSGatewaySmart_Stub.java
new file mode 100644 (file)
index 0000000..f5bc2ca
--- /dev/null
@@ -0,0 +1,146 @@
+package SpeakerController;
+
+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 GPSGatewaySmart_Stub implements GPSGatewaySmart {
+
+       private IoTRMICall rmiCall;
+       private String callbackAddress;
+       private int[] ports;
+
+       private final static int objectId = 0;
+       // Callback properties
+       private IoTRMIObject rmiObj;
+       List<GPSGatewayCallback> listCallbackObj;
+       private int objIdCnt = 0;
+       private final static int object0Id = 0; //GPSGatewaySmartCallback
+       private static Integer[] object0Permission = { 0, 1 };
+       private static List<Integer> set0Allowed;
+       
+
+       public GPSGatewaySmart_Stub(int _port, String _skeletonAddress, String _callbackAddress, int _rev, int[] _ports) throws Exception {
+               callbackAddress = _callbackAddress;
+               ports = _ports;
+               rmiCall = new IoTRMICall(_port, _skeletonAddress, _rev);
+               set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+               listCallbackObj = new ArrayList<GPSGatewayCallback>();
+               set0Allowed.add(-9999);
+               ___initCallBack();
+       }
+
+       public void setNewRoomIDAvailable(boolean bValue) {
+               int methodId = 5;
+               Class<?> retType = void.class;
+               Class<?>[] paramCls = new Class<?>[] { boolean.class };
+               Object[] paramObj = new Object[] { bValue };
+               rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+       }
+
+       public void setNewRingStatusAvailable(boolean bValue) {
+               int methodId = 6;
+               Class<?> retType = void.class;
+               Class<?>[] paramCls = new Class<?>[] { boolean.class };
+               Object[] paramObj = new Object[] { bValue };
+               rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+       }
+
+       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 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 int getRoomID() {
+               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;
+       }
+
+       public void registerCallback(GPSGatewayCallback _callbackTo) {
+               try {
+                       GPSGatewayCallback_CallbackSkeleton skel0 = new GPSGatewayCallback_CallbackSkeleton(_callbackTo, callbackAddress, objIdCnt++);
+                       listCallbackObj.add(skel0);
+               } catch (Exception ex) {
+                       ex.printStackTrace();
+                       throw new Error("Exception when generating skeleton objects!");
+               }
+
+               int methodId = 7;
+               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);
+                                               GPSGatewayCallback_CallbackSkeleton skel = (GPSGatewayCallback_CallbackSkeleton) listCallbackObj.get(objId);
+                                               if (skel != null) {
+                                                       int methodId = IoTRMIObject.getMethodId(method);
+                                                       if (!set0Allowed.contains(methodId)) {
+                                                               throw new Error("Callback object for GPSGatewayCallback is not allowed to access method: " + methodId);
+                                                       }
+                                                       skel.invokeMethod(rmiObj);
+                                               } else {
+                                                       throw new Error("GPSGatewayCallback: Object with Id " + objId + " not found!");
+                                               }
+                                       }
+                               } catch (Exception ex) {
+                                       ex.printStackTrace();
+                                       throw new Error("Error instantiating class GPSGatewayCallback_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 boolean getRingStatus() {
+               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;
+       }
+
+}
index 80be525562913b1514785b278a65b15aa6ca233a..1c042f0b9a657f280e996690f50c4e68a511ae7e 100644 (file)
@@ -10,25 +10,10 @@ JLAYERJARS := $(JLAYERDIR)/jl1.0.1.jar
 JFLAGS = -d $(BIN_DIR) -cp $(BOOFJARS):$(BIN_DIR):.:$(JLAYERJARS)
 JARFLAGS = cf 
 
-# checker option
-#
-CHECKER_OPT = -processor iotchecker.IoTJavaChecker
+all: speaker
 
-ASTUBS = -Astubs=../../checker/astubs/ 
-
-all: check
-
-PHONY += check
-check:
-       $(JAVAC) $(JFLAGS) $(CHECKER_OPT) $(ASTUBS) *.java
-       cd  $(BIN_DIR)/SpeakerController; $(JAR) $(JARFLAGS) SpeakerController.jar ../SpeakerController/*.class ../iotcode/interfaces/*.class
-       cp SpeakerController.config $(BIN_DIR)/SpeakerController
-       zip -r SpeakerController.zip ./music
-       mv SpeakerController.zip $(BIN_DIR)/SpeakerController
-
-PHONY += nocheck
-
-nocheck:
+PHONY += speaker
+speaker:
        $(JAVAC) $(JFLAGS) *.java
        cd  $(BIN_DIR)/SpeakerController; $(JAR) $(JARFLAGS) SpeakerController.jar ../SpeakerController/*.class ../iotcode/interfaces/*.class
        cp SpeakerController.config $(BIN_DIR)/SpeakerController
diff --git a/benchmarks/SpeakerController/RoomSmart_Stub.java b/benchmarks/SpeakerController/RoomSmart_Stub.java
new file mode 100644 (file)
index 0000000..a45b775
--- /dev/null
@@ -0,0 +1,36 @@
+package SpeakerController;
+
+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/SpeakerController/SpeakerCallback_CallbackSkeleton.java b/benchmarks/SpeakerController/SpeakerCallback_CallbackSkeleton.java
new file mode 100644 (file)
index 0000000..808ae44
--- /dev/null
@@ -0,0 +1,44 @@
+package SpeakerController;
+
+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 SpeakerCallback_CallbackSkeleton implements SpeakerCallback {
+
+       private SpeakerCallback mainObj;
+       private int objectId = 0;
+       private String callbackAddress;
+       
+
+       public SpeakerCallback_CallbackSkeleton(SpeakerCallback _mainObj, String _callbackAddress, int _objectId) throws Exception {
+               callbackAddress = _callbackAddress;
+               mainObj = _mainObj;
+               objectId = _objectId;
+       }
+
+       public void speakerDone() {
+               mainObj.speakerDone();
+       }
+
+       public void ___speakerDone(IoTRMIObject rmiObj) {
+               Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] {  }, 
+               new Class<?>[] {  });
+               speakerDone();
+       }
+
+       public void invokeMethod(IoTRMIObject rmiObj) throws IOException {
+               int methodId = rmiObj.getMethodId();
+               switch (methodId) {
+                       case 0: ___speakerDone(rmiObj); break;
+                       default: 
+                       throw new Error("Method Id " + methodId + " not recognized!");
+               }
+       }
+
+}
index 17fcd67f2fe0ad08d3ceb4097dfcd49107a6c98d..00b6dbaf5d0d8dccfd6275dca269e21d42023f80 100644 (file)
@@ -7,7 +7,7 @@ import iotruntime.slave.IoTRelation;
 
 // IoT driver packages
 import iotcode.interfaces.*;
-//import iotcode.annotation.*;
+import iotcode.annotation.*;
 
 
 // Standard Java packages
@@ -26,7 +26,7 @@ import java.rmi.RemoteException;
 import java.rmi.server.UnicastRemoteObject;
 
 // Checker annotations
-import iotchecker.qual.*;
+//import iotchecker.qual.*;
 
 /** Class SpeakerController for the smart home application benchmark
  *  <p>
@@ -50,23 +50,23 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
        /**
         * IoT Sets of Devices
         */
-       @config private IoTSet < @NonLocalRemote GPSGateway > gpsSet;
-       @config private IoTSet < @NonLocalRemote Speaker > speakerSet;
+       @config private IoTSet < GPSGatewaySmart > gpsSet;
+       @config private IoTSet < SpeakerSmart > speakerSet;
 
        /**
         * IoT Sets of Things that are not devices such as rooms
         */
-       @config private IoTSet < @NonLocalRemote Room > audioRooms;
+       @config private IoTSet < RoomSmart > audioRooms;
 
        /**
         * IoT Relations
         */
-       @config private IoTRelation < @NonLocalRemote Room, @NonLocalRemote Speaker > roomSpeakerRel;
+       @config private IoTRelation < RoomSmart, SpeakerSmart > roomSpeakerRel;
 
        /**
         * The state that the room main lights are supposed to be in
         */
-       Map < @NonLocalRemote Room, Boolean > roomSpeakersOnOffStatus = new HashMap < @NonLocalRemote Room, Boolean > ();
+       Map < RoomSmart, Boolean > roomSpeakersOnOffStatus = new HashMap < RoomSmart, Boolean > ();
 
        // used to notify if new data is available
        private AtomicBoolean newDataAvailable = new AtomicBoolean(false);
@@ -87,22 +87,13 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
 
        /** Callback method for when room ID is retrieved.
         *
-        * @param _ggw [GPSGateway].
+        * @param _roomIdentifier [int].
         * @return [void] None.
         */
-       public void newRoomIDRetrieved(@NonLocalRemote GPSGateway _ggw) {
-
-               try {
-                       // get the parameters that the interface (phone app) reads from the user
-                       roomIdentifier = _ggw.getRoomID();
+       public void newRoomIDRetrieved(int _roomIdentifier) {
 
-                       System.out.println("DEBUG: New room ID is retrieved from phone!!! Room: " + roomIdentifier);
-
-                       // Data is read, so we set this back to false
-                       _ggw.setNewRoomIDAvailable(false);
-               } catch (RemoteException ex) {
-                       ex.printStackTrace();
-               }
+               roomIdentifier = _roomIdentifier;
+               System.out.println("DEBUG: New room ID is retrieved from phone!!! Room: " + roomIdentifier);
 
                // new data available so set it to true
                newDataAvailable.set(true);
@@ -111,22 +102,13 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
 
        /** Callback method for when ring status is retrieved.
         *
-        * @param _ggw [GPSGateway].
+        * @param _ringStatus [boolean].
         * @return [void] None.
         */
-       public void newRingStatusRetrieved(@NonLocalRemote GPSGateway _ggw) {
-
-               try {
-                       // get the parameters that the interface (phone app) reads from the user
-                       ringStatus = _ggw.getRingStatus();
+       public void newRingStatusRetrieved(boolean _ringStatus) {
 
-                       System.out.println("DEBUG: New ring status is retrieved from phone!!! Status: " + ringStatus);
-
-                       // Data is read, so we set this back to false
-                       _ggw.setNewRingStatusAvailable(false);
-               } catch (RemoteException ex) {
-                       ex.printStackTrace();
-               }
+               ringStatus = _ringStatus;
+               System.out.println("DEBUG: New ring status is retrieved from phone!!! Status: " + ringStatus);
 
                // new data available so set it to true
                newDataAvailable.set(true);
@@ -135,11 +117,10 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
 
        /** Callback method when a speaker has finished playing what is in its audio buffer.
         *
-        * @param _speaker [Speaker].
         * @return [void] None.
         */
-       public void speakerDone(@NonLocalRemote Speaker _speaker) {
-               for (@NonLocalRemote Speaker speakers : speakerSet.values()) {
+       public void speakerDone() {
+               for (SpeakerSmart speakers : speakerSet.values()) {
                        playbackDone.set(true);
                }
        }
@@ -157,7 +138,7 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
        private void updateSpeakersAction() {
 
                // Stream music on speakers based on their status
-               for (@NonLocalRemote Room room : audioRooms.values()) {
+               for (RoomSmart room : audioRooms.values()) {
 
                        // Check status of the room
                        if (roomSpeakersOnOffStatus.get(room)) {
@@ -168,15 +149,15 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
 
                                // Get the speaker objects one by one assuming that we could have
                                // more than one speaker per room
-                               for (@NonLocalRemote Speaker speakers : roomSpeakerRel.get(room)) {
+                               for (SpeakerSmart speakers : roomSpeakerRel.get(room)) {
                                        // System.out.println("DEBUG: Turn on speaker!");
 
-                                       try {
+                                       //try {
 
                                                // start the speaker playback if the speaker is not playing yet
                                                if (!speakers.getPlaybackState()) {
 
-                                                       System.out.println("Turning a speaker On");
+                                                       System.out.println("Turning a speaker On in room: " + room.getRoomID());
                                                        speakers.startPlayback();
                                                        speakers.setPosition(currentPosition);
 
@@ -187,9 +168,9 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
                                                }
 
 
-                                       } catch (RemoteException e) {
-                                               e.printStackTrace();
-                                       }
+                                       //} catch (RemoteException e) {
+                                       //      e.printStackTrace();
+                                       //}
                                }
 
                                if (currPosCount != 0) {
@@ -201,12 +182,12 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
                                        if (Math.abs(currentPosOfSpeakers - currentPosition) > CURRENT_POSITION_SAMPLE_THRESHOLD) {
                                                // we were kind of far so update all the positions
 
-                                               for (@NonLocalRemote Speaker speakers : roomSpeakerRel.get(room)) {
-                                                       try {
+                                               for (SpeakerSmart speakers : roomSpeakerRel.get(room)) {
+                                                       //try {
                                                                speakers.setPosition(currentPosOfSpeakers);
-                                                       } catch (RemoteException e) {
-                                                               e.printStackTrace();
-                                                       }
+                                                       //} catch (RemoteException e) {
+                                                       //      e.printStackTrace();
+                                                       //}
                                                }
                                        }
 
@@ -216,7 +197,7 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
 
 
 
-                       } else {
+                       } /*else {
                                // Room status is "off"
 
                                // used to get the average of the speakers position
@@ -225,7 +206,7 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
 
                                // Get the speaker objects one by one assuming that we could have
                                // more than one speaker per room
-                               for (@NonLocalRemote Speaker speakers : roomSpeakerRel.get(room)) {
+                               for (Speaker speakers : roomSpeakerRel.get(room)) {
                                        // System.out.println("DEBUG: Turn off speaker!");
                                        try {
                                                // Turning off speaker if they are still on
@@ -251,7 +232,7 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
                                if (currPosCount != 0) {
                                        currentPosition = (int)(currPosTotal / currPosCount);
                                }
-                       }
+                       }*/
                }
 
                // a speaker has finished playing and so we should change all the audio buffers
@@ -278,7 +259,7 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
                        if (ringStatus) {
 
                                // Turn off all speakers if ring status is true (phone is ringing)
-                               for (@NonLocalRemote Room room : audioRooms.values()) {
+                               for (RoomSmart room : audioRooms.values()) {
 
                                        // System.out.println("DEBUG: Update status off for speakers! Phone is ringing!!!");
                                        // Turn off speaker
@@ -289,9 +270,9 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
                                // Phone is not ringing... just play music on the right speaker
 
                                // Check for every room
-                               for (@NonLocalRemote Room room : audioRooms.values()) {
+                               for (RoomSmart room : audioRooms.values()) {
 
-                                       try {
+                                       //try {
                                                // Turn on the right speaker based on room ID sent from phone app
                                                // Stream audio to a speaker based on room ID
                                                if (room.getRoomID() == roomIdentifier) {
@@ -309,9 +290,9 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
                                                        roomSpeakersOnOffStatus.put(room, false);
                                                }
 
-                                       } catch (RemoteException ex) {
-                                               ex.printStackTrace();
-                                       }
+                                       //} catch (RemoteException ex) {
+                                       //      ex.printStackTrace();
+                                       //}
                                }
                        }
                        // Finish processing data - put this back to false
@@ -328,7 +309,7 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
                System.out.println("Stopping all device playback");
                // stop all devices that are still playing and clear their buffers
                // they are about to end playback anyways
-               for (@NonLocalRemote Speaker speakers : speakerSet.values()) {
+               for (SpeakerSmart speakers : speakerSet.values()) {
                        try {
 
                                if (speakers.getPlaybackState()) {
@@ -390,7 +371,7 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
 
                System.out.println("Loading Speakers");
                // send the new data to all the speakers
-               for (@NonLocalRemote Speaker speakers : speakerSet.values()) {
+               for (SpeakerSmart speakers : speakerSet.values()) {
                        System.out.println("Loading a single speaker with data");
                        try {
                                speakers.loadData(compressedArray, 0, compressedArray.length);
@@ -418,27 +399,27 @@ public class SpeakerController extends UnicastRemoteObject implements GPSGateway
        public void init() throws RemoteException, InterruptedException {
 
                // Initialize the rooms
-               for (@NonLocalRemote Room room : audioRooms.values()) {
+               for (RoomSmart room : audioRooms.values()) {
                        // All rooms start with the speakers turned off
                        roomSpeakersOnOffStatus.put(room, false);
                }
 
                // Setup the cameras, start them all and assign each one a motion detector
-               for (@NonLocalRemote GPSGateway gw : gpsSet.values()) {
+               for (GPSGatewaySmart gw : gpsSet.values()) {
 
-                       try {
+                       //try {
                                // initialize, register callback, and start the gateway
                                gw.init();
                                gw.registerCallback(this);
                                gw.start();
-                       } catch (RemoteException ex) {
-                               ex.printStackTrace();
-                       }
+                       //} catch (RemoteException ex) {
+                       //      ex.printStackTrace();
+                       //}
                }
 
 
                //Initialize the speakers
-               for (@NonLocalRemote Speaker speakers : speakerSet.values()) {
+               for (SpeakerSmart speakers : speakerSet.values()) {
                        speakers.init();
                }
 
diff --git a/benchmarks/SpeakerController/SpeakerSmart_Stub.java b/benchmarks/SpeakerController/SpeakerSmart_Stub.java
new file mode 100644 (file)
index 0000000..71147e6
--- /dev/null
@@ -0,0 +1,174 @@
+package SpeakerController;
+
+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 SpeakerSmart_Stub implements SpeakerSmart {
+
+       private IoTRMICall rmiCall;
+       private String callbackAddress;
+       private int[] ports;
+
+       private final static int objectId = 0;
+       // Callback properties
+       private IoTRMIObject rmiObj;
+       List<SpeakerCallback> listCallbackObj;
+       private int objIdCnt = 0;
+       private final static int object0Id = 0; //SpeakerSmartCallback
+       private static Integer[] object0Permission = { 0 };
+       private static List<Integer> set0Allowed;
+       
+
+       public SpeakerSmart_Stub(int _port, String _skeletonAddress, String _callbackAddress, int _rev, int[] _ports) throws Exception {
+               callbackAddress = _callbackAddress;
+               ports = _ports;
+               rmiCall = new IoTRMICall(_port, _skeletonAddress, _rev);
+               set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+               listCallbackObj = new ArrayList<SpeakerCallback>();
+               set0Allowed.add(-9999);
+               ___initCallBack();
+       }
+
+       public int getPosition() {
+               int methodId = 6;
+               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 stopPlayback() {
+               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 void clearData() {
+               int methodId = 9;
+               Class<?> retType = void.class;
+               Class<?>[] paramCls = new Class<?>[] {  };
+               Object[] paramObj = new Object[] {  };
+               rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+       }
+
+       public boolean startPlayback() {
+               int methodId = 1;
+               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 boolean getPlaybackState() {
+               int methodId = 3;
+               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 boolean setVolume(float _percent) {
+               int methodId = 4;
+               Class<?> retType = boolean.class;
+               Class<?>[] paramCls = new Class<?>[] { float.class };
+               Object[] paramObj = new Object[] { _percent };
+               Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+               return (boolean)retObj;
+       }
+
+       public float getVolume() {
+               int methodId = 5;
+               Class<?> retType = float.class;
+               Class<?>[] paramCls = new Class<?>[] {  };
+               Object[] paramObj = new Object[] {  };
+               Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+               return (float)retObj;
+       }
+
+       public void setPosition(int _mSec) {
+               int methodId = 7;
+               Class<?> retType = void.class;
+               Class<?>[] paramCls = new Class<?>[] { int.class };
+               Object[] paramObj = new Object[] { _mSec };
+               rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+       }
+
+       public void loadData(short _samples[], int _offs, int _len) {
+               int methodId = 8;
+               Class<?> retType = void.class;
+               Class<?>[] paramCls = new Class<?>[] { short[].class, int.class, int.class };
+               Object[] paramObj = new Object[] { _samples, _offs, _len };
+               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);
+       }
+
+       public void registerCallback(SpeakerCallback _cb) {
+               try {
+                       SpeakerCallback_CallbackSkeleton skel0 = new SpeakerCallback_CallbackSkeleton(_cb, 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);
+                                               SpeakerCallback_CallbackSkeleton skel = (SpeakerCallback_CallbackSkeleton) listCallbackObj.get(objId);
+                                               if (skel != null) {
+                                                       int methodId = IoTRMIObject.getMethodId(method);
+                                                       if (!set0Allowed.contains(methodId)) {
+                                                               throw new Error("Callback object for SpeakerCallback is not allowed to access method: " + methodId);
+                                                       }
+                                                       skel.invokeMethod(rmiObj);
+                                               } else {
+                                                       throw new Error("SpeakerCallback: Object with Id " + objId + " not found!");
+                                               }
+                                       }
+                               } catch (Exception ex) {
+                                       ex.printStackTrace();
+                                       throw new Error("Error instantiating class SpeakerCallback_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);
+       }
+
+}
diff --git a/benchmarks/drivers/AudioRoom/AudioRoom.config b/benchmarks/drivers/AudioRoom/AudioRoom.config
new file mode 100644 (file)
index 0000000..6af9ab2
--- /dev/null
@@ -0,0 +1 @@
+INTERFACE_CLASS=Room
diff --git a/benchmarks/drivers/AudioRoom/AudioRoom.java b/benchmarks/drivers/AudioRoom/AudioRoom.java
new file mode 100644 (file)
index 0000000..06714b0
--- /dev/null
@@ -0,0 +1,27 @@
+package iotcode.AudioRoom;
+
+import iotcode.interfaces.Room;
+
+/** AudioRoom holds room ID that tells which room it is
+ *  in association with speakers
+ *
+ * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version     1.0                
+ * @since       2016-04-29
+ */
+public class AudioRoom implements Room {
+
+       /**
+        *  AudioRoom class properties
+        */
+       private int iRoomID;
+
+       public AudioRoom(int _iRoomID) {
+               this.iRoomID = _iRoomID;
+               System.out.println("AudioRoom ID: " + this.iRoomID);
+       }
+
+       public int getRoomID() {
+               return this.iRoomID;
+       }
+}
diff --git a/benchmarks/drivers/AudioRoom/Room_Skeleton.java b/benchmarks/drivers/AudioRoom/Room_Skeleton.java
new file mode 100644 (file)
index 0000000..b9b9b3b
--- /dev/null
@@ -0,0 +1,63 @@
+package iotcode.AudioRoom;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.Room;
+
+public class Room_Skeleton implements Room {
+
+       private Room mainObj;
+       private IoTRMIObject rmiObj;
+
+       private String callbackAddress;
+       private final static int object0Id = 0; //RoomSmart
+       private static Integer[] object0Permission = { 0 };
+       private static List<Integer> set0Allowed;
+       
+
+       public Room_Skeleton(Room _mainObj, String _callbackAddress, int _port) throws Exception {
+               mainObj = _mainObj;
+               callbackAddress = _callbackAddress;
+               rmiObj = new IoTRMIObject(_port);
+               set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+               ___waitRequestInvokeMethod();
+       }
+
+       public int getRoomID() {
+               return mainObj.getRoomID();
+       }
+
+       public void ___getRoomID() throws IOException {
+               Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] {  }, 
+               new Class<?>[] {  });
+               Object retObj = getRoomID();
+               rmiObj.sendReturnObj(retObj);
+       }
+
+       private void ___waitRequestInvokeMethod() throws IOException {
+               while (true) {
+                       rmiObj.getMethodBytes();
+                       int _objectId = rmiObj.getObjectId();
+                       int methodId = rmiObj.getMethodId();
+                       if (_objectId == object0Id) {
+                               if (!set0Allowed.contains(methodId)) {
+                                       throw new Error("Object with object Id: " + _objectId + "  is not allowed to access method: " + methodId);
+                               }
+                       }
+                       else {
+                               throw new Error("Object Id: " + _objectId + " not recognized!");
+                       }
+                       switch (methodId) {
+                               case 0: ___getRoomID(); break;
+                               default: 
+                               throw new Error("Method Id " + methodId + " not recognized!");
+                       }
+               }
+       }
+
+}
diff --git a/benchmarks/drivers/GPSPhoneGateway/GPSPhoneGateway.config b/benchmarks/drivers/GPSPhoneGateway/GPSPhoneGateway.config
new file mode 100644 (file)
index 0000000..081970f
--- /dev/null
@@ -0,0 +1 @@
+INTERFACE_CLASS=GPSGateway
diff --git a/benchmarks/drivers/GPSPhoneGateway/GPSPhoneGateway.java b/benchmarks/drivers/GPSPhoneGateway/GPSPhoneGateway.java
new file mode 100644 (file)
index 0000000..404292b
--- /dev/null
@@ -0,0 +1,204 @@
+package iotcode.GPSPhoneGateway;
+
+// Java standard library
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.Iterator;
+import java.util.List;
+import java.net.UnknownHostException;
+
+// RMI Packages
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+// IoTRuntime library
+import iotruntime.stub.IoTRemoteCall;
+import iotruntime.slave.IoTSet;
+import iotruntime.slave.IoTDeviceAddress;
+import iotcode.annotation.*;
+import iotcode.interfaces.*;
+
+// Checker annotations
+//import iotchecker.qual.*;
+
+/** GPSPhoneGateway that uses IoTRemoteCall and PhoneInfo class
+ *  to get information from a phone app
+ *
+ * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version     1.0                
+ * @since       2016-04-27
+ */
+public class GPSPhoneGateway implements GPSGateway {
+
+       /**
+        * PhoneGateway class properties
+        */
+       private PhoneInfo phoneInfo;
+       private IoTRemoteCall iotRemCall;
+       private List<GPSGatewaySmartCallback> listPGWCallback;
+       private AtomicBoolean doEnd;
+       private Thread callbackThread;
+       private Thread workerThread;
+       private IoTDeviceAddress iotDevAdd;
+
+       @config private IoTSet<IoTDeviceAddress> gps_address;
+
+       /**
+        * Constructor
+        */
+       public GPSPhoneGateway() throws RemoteException {
+       }
+
+       /**
+        * Init() function
+        */
+       public void init() {
+
+               // Get address
+               Iterator it = gps_address.iterator();
+               iotDevAdd = (IoTDeviceAddress) it.next();
+//             try {
+//                     iotDevAdd = new IoTDeviceAddress("192.168.2.100", 1234, 8000);
+//             } catch (Exception ex) {
+//             }
+               System.out.println("Address: " + iotDevAdd.getCompleteAddress());
+               System.out.println("Source port: " + iotDevAdd.getSourcePortNumber());
+               System.out.println("Destination port: " + iotDevAdd.getDestinationPortNumber());
+
+               // Get server
+               phoneInfo = new PhoneInfo();
+               listPGWCallback = new ArrayList<GPSGatewaySmartCallback>();
+               doEnd = new AtomicBoolean(false);
+
+               // Threads
+               callbackThread = null;
+               workerThread = null;
+       }
+
+       /**
+        * Start() function to start threads
+        */
+       public void start() {
+               doEnd.set(false);
+
+               // Launch IoTRemoteCall server in a separate thread
+               workerThread = new Thread(new Runnable() {
+                       public void run() {
+                               iotRemCall = new IoTRemoteCall(PhoneInfoInterface.class, 
+                                       phoneInfo, iotDevAdd.getDestinationPortNumber(),
+                                       IoTDeviceAddress.getLocalHostAddress());
+                       }
+               });
+               workerThread.start();
+               System.out.println("GPSPhoneGateway: Worker thread started!");
+
+               callbackThread = new Thread(new Runnable() {
+                       public void run() {
+                               doCallbacks();
+                       }
+               });
+               callbackThread.start();
+               System.out.println("GPSPhoneGateway: Callback thread started!");
+       }
+
+       /**
+        * Stop() function to stop threads
+        */
+       public void stop() {
+               doEnd.set(true);
+
+               try {
+                       callbackThread.join();
+                       workerThread.join();
+               } catch (Exception e) {
+                       e.printStackTrace();
+               }
+       }
+
+       /**
+        * Register callbacks
+        */
+       public void registerCallback(GPSGatewaySmartCallback _c) {
+               listPGWCallback.add(_c);
+       }
+
+       /**
+        * Do callbacks
+        */
+       private void doCallbacks() {
+
+               while (!doEnd.get()) {
+
+                       for (GPSGatewaySmartCallback c : listPGWCallback) {
+
+                               //try {
+                                       // Only call back if there is new data  
+                                       if (phoneInfo.isNewRoomIDAvailable()) {
+
+                                               System.out.println("GPSPhoneGateway: new room ID available - call back!");
+                                               // Call back!
+                                               //c.newRoomIDRetrieved(this);
+                                               c.newRoomIDRetrieved(this.getRoomID());
+                                               //this.setNewRoomIDAvailable(false);
+
+                                               // Set back to false after reading
+                                               phoneInfo.setNewRoomIDAvailable(false);
+
+                                       } else if (phoneInfo.isNewRingStatusAvailable()) {
+
+                                               System.out.println("GPSPhoneGateway: new ring status available - call back!");
+                                               // Call back!
+                                               //c.newRingStatusRetrieved(this);
+                                               c.newRingStatusRetrieved(this.getRingStatus());
+                                               //this.setNewRingStatusAvailable(false);
+
+                                               // Set back to false after reading
+                                               phoneInfo.setNewRingStatusAvailable(false);
+                                       }
+
+                               //} catch (RemoteException ex) {
+                               //      ex.printStackTrace();
+                               //}
+                       }
+               }
+       }
+
+       /**
+        * Simply return phoneInfo.iRoomIdentifier
+        */
+       public int getRoomID() {
+
+               return phoneInfo.getRoomID();
+       }
+
+       /**
+        * Simply return phoneInfo.bRingStatus
+        */
+       public boolean getRingStatus() {
+
+               return phoneInfo.getRingStatus();
+       }
+
+       /**
+        * Set phoneInfo.bNewRoomIDAvail
+        */
+       public void setNewRoomIDAvailable(boolean bValue) {
+
+               phoneInfo.setNewRoomIDAvailable(bValue);
+       }
+
+       /**
+        * Set phoneInfo.bNewRingStatusAvail
+        */
+       public void setNewRingStatusAvailable(boolean bValue) {
+
+               phoneInfo.setNewRingStatusAvailable(bValue);
+       }
+
+/*     public static void main(String[] args) throws UnknownHostException, RemoteException {
+
+               @LocalRemote GPSPhoneGateway gpg = new @LocalRemote GPSPhoneGateway();
+               gpg.init();
+               gpg.start();
+       }*/
+}
diff --git a/benchmarks/drivers/GPSPhoneGateway/PhoneInfo.java b/benchmarks/drivers/GPSPhoneGateway/PhoneInfo.java
new file mode 100644 (file)
index 0000000..c09697b
--- /dev/null
@@ -0,0 +1,104 @@
+package iotcode.GPSPhoneGateway;
+
+/** PhoneInfo that implements PhoneInfoInterface
+ *
+ * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version     1.0                
+ * @since       2016-04-27
+ */
+public class PhoneInfo implements PhoneInfoInterface {
+
+       /**
+        * PhoneInfo class properties
+        */
+       private int iRoomIdentifier;
+       private boolean bRingStatus;
+       private boolean bNewRoomIDAvail;
+       private boolean bNewRingStatusAvail;
+
+       /**
+        * Constructor
+        */
+       public PhoneInfo() {
+               this.iRoomIdentifier = 0;
+               this.bRingStatus = false;
+               this.bNewRoomIDAvail = false;
+               this.bNewRingStatusAvail = false;
+       }
+
+       /**
+        * Set room identifier info from the phone app using IoTRemoteCall
+        *
+        * @param   iId         Room identifier (integer)
+        * @return  String
+        */
+       public String setRoomID(Integer iId) {
+
+               this.iRoomIdentifier = iId;
+               this.bNewRoomIDAvail = true;
+               System.out.println("New room ID set: " + this.iRoomIdentifier);
+               return "info sent";
+       }
+
+       /**
+        * Set ring status info from the phone app using IoTRemoteCall
+        *
+        * @param   bStatus             Ring status (true/false)
+        * @return  String
+        */
+       public String setRingStatus(Boolean bStatus) {
+
+               this.bRingStatus = bStatus;
+               this.bNewRingStatusAvail = true;
+               System.out.println("New ring status set: " + this.bRingStatus);
+               return "info sent";
+       }
+
+       /**
+        * Simply return this.iRoomIdentifier
+        */
+       public int getRoomID() {
+
+               return this.iRoomIdentifier;
+       }
+
+       /**
+        * Simply return this.bRingStatus
+        */
+       public boolean getRingStatus() {
+
+               return this.bRingStatus;
+       }
+       
+       /**
+        * Simply return this.bNewRoomIDAvail
+        */
+       public boolean isNewRoomIDAvailable() {
+
+               return this.bNewRoomIDAvail;
+       }
+
+       /**
+        * Simply return this.bNewRingStatusAvail
+        */
+       public boolean isNewRingStatusAvailable() {
+
+               return this.bNewRingStatusAvail;
+       }
+
+       /**
+        * Set this.bNewRoomIDAvail
+        */
+       public void setNewRoomIDAvailable(boolean bValue) {
+
+               this.bNewRoomIDAvail = bValue;
+       }
+
+       /**
+        * Set this.bNewRingStatusAvail
+        */
+       public void setNewRingStatusAvailable(boolean bValue) {
+
+               this.bNewRingStatusAvail = bValue;
+       }
+}
diff --git a/benchmarks/drivers/GPSPhoneGateway/PhoneInfoInterface.java b/benchmarks/drivers/GPSPhoneGateway/PhoneInfoInterface.java
new file mode 100644 (file)
index 0000000..08b17c1
--- /dev/null
@@ -0,0 +1,18 @@
+package iotcode.GPSPhoneGateway;
+
+/** PhoneInfoInterface interface to be implemented by a real class
+ *
+ * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version     1.0                
+ * @since       2016-04-27
+ */
+public interface PhoneInfoInterface {
+
+       /** 
+        * GPSPhoneGateway takes 2 inputs
+        * - Room identifier (getRoomID)
+        * - Phone status (getRingStatus: ringing/not ringing)
+        */
+       String setRoomID(Integer iId);
+       String setRingStatus(Boolean bStatus);
+}
diff --git a/benchmarks/drivers/IHome/IHome.config b/benchmarks/drivers/IHome/IHome.config
new file mode 100644 (file)
index 0000000..276b02e
--- /dev/null
@@ -0,0 +1 @@
+INTERFACE_CLASS=Speaker
\ No newline at end of file
diff --git a/benchmarks/drivers/IHome/IHome.java b/benchmarks/drivers/IHome/IHome.java
new file mode 100644 (file)
index 0000000..a9bcf0d
--- /dev/null
@@ -0,0 +1,970 @@
+package iotcode.IHome;
+
+// IoT Packages
+import iotcode.interfaces.*;
+import iotcode.annotation.*;
+import iotruntime.IoTUDP;
+import iotruntime.IoTTCP;
+import iotruntime.slave.IoTSet;
+import iotruntime.slave.IoTDeviceAddress;
+
+// RMI Packages
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+// Checker annotations
+//import iotchecker.qual.*;
+
+// Standard Java Packages
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.io.PrintWriter;
+import java.io.ByteArrayInputStream;
+import java.util.LinkedList;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+
+public class IHome implements Speaker {
+
+
+    /*******************************************************************************************************************************************
+    **  Constants
+    *******************************************************************************************************************************************/
+
+    public static final float VOLUME_MUTED_VALUE_DB = (float) (-144.0);
+    public static final float VOLUME_MIN_VALUE_DB = (float) (-30.0);
+    public static final float VOLUME_MAX_VALUE_DB = (float) (-0.0);
+    public static final float DEFAULT_VOLUME = (float) (30.0);
+
+    public static final long SEQUENCE_NUMBER_INITIAL_VALUE = 18086;
+    public static final long SEQUENCE_NUMBER_WRAP_AROUND = 32768L;
+    public static final long RTP_TIMESTAMP_INITIAL_VALUE = 3132223670L;
+    public static final long RTP_TIMESTAMP_INCREMENT_VALUE = 352L;
+    public static final long SOURCE_ID = 1326796157;
+    public static final long SEQUENCE_ID = 0x86b27741;
+
+    private IoTDeviceAddress tcpAddress = null;
+    private IoTDeviceAddress myAddress = null;
+    private IoTDeviceAddress controlAddress = null;
+    private IoTDeviceAddress timingAddress = null;
+    private IoTDeviceAddress serverAddress = null;
+
+    private IoTTCP iHomeTCPConnection = null;
+
+    private AtomicBoolean driverIsShuttingDown = new AtomicBoolean();
+    private boolean didClose = false;
+
+    private AtomicBoolean didEnd = new AtomicBoolean();
+    private AtomicBoolean playbackStarted = new AtomicBoolean();
+    private AtomicBoolean playbackFileIsDone = new AtomicBoolean();
+    private AtomicBoolean isDoneEnding = new AtomicBoolean();
+    private AtomicBoolean playbackState = new AtomicBoolean();
+
+    private AtomicBoolean didInit = new AtomicBoolean();
+    private AtomicBoolean playbackAboutToStart = new AtomicBoolean();
+    private AtomicBoolean settingVolume = new AtomicBoolean();
+    private AtomicBoolean playbackAboutToStop = new AtomicBoolean();
+
+
+
+    private long sequenceNumber = SEQUENCE_NUMBER_INITIAL_VALUE;
+    private long rtpTimestamp = RTP_TIMESTAMP_INITIAL_VALUE;
+
+    private long currentPlaybackTime = 0;
+    static Semaphore currentPlaybackTimeMutex = new Semaphore(1);
+
+    private long desiredPlaybackTime = 0;
+    static Semaphore desiredPlaybackTimeMutex = new Semaphore(1);
+
+
+    private String connectionURL = "";
+    private float currentVolume = DEFAULT_VOLUME;
+    private LinkedList audioLinkedList = new LinkedList();
+
+    private List < SpeakerSmartCallback > callbackList = new CopyOnWriteArrayList< SpeakerSmartCallback > ();
+
+    /*******************************************************************************************************************************************
+    **  Threads
+    *******************************************************************************************************************************************/
+    private Thread timingThread = null;
+    private Thread audioThread = null;
+    private Thread controlThread = null;
+    private Thread monitorThread = null;
+
+
+    @config private IoTSet<IoTDeviceAddress> speakerAddresses;
+
+    public IHome() {
+        didInit.set(false);
+        playbackAboutToStart.set(false);
+        settingVolume.set(false);
+    }
+
+    /*******************************************************************************************************************************************
+    **
+    **  Speaker Interface Methods
+    **
+    *******************************************************************************************************************************************/
+
+    public void init() {
+
+        if (didInit.compareAndSet(false, true) == false) {
+            return; // already init
+        }
+
+        didEnd.set(false);
+        isDoneEnding.set(true);
+        playbackFileIsDone.set(false);
+        Map<String, Integer> addrCount = new HashMap<String, Integer>();
+
+
+        // get correct addresses
+        for (IoTDeviceAddress devAdrr : speakerAddresses.values()) {
+            if (addrCount.containsKey(devAdrr.getAddress())) {
+                addrCount.put(devAdrr.getAddress(), addrCount.get(devAdrr.getAddress()) + 1);
+            } else {
+                addrCount.put(devAdrr.getAddress(), 1);
+            }
+        }
+
+        for (IoTDeviceAddress devAdrr : speakerAddresses.values()) {
+            if (addrCount.get(devAdrr.getAddress()) <= 1) {
+                myAddress = devAdrr;
+            } else {
+                if (devAdrr.getIsDstPortWildcard()) {
+                    if (controlAddress == null) {
+                        controlAddress = devAdrr;
+                    } else if (timingAddress == null) {
+                        timingAddress = devAdrr;
+                    } else {
+                        serverAddress = devAdrr;
+                    }
+                } else {
+                    tcpAddress = devAdrr;
+                }
+            }
+        }
+
+        System.out.println("tcpAddress: " + tcpAddress.getAddress() + ":" + tcpAddress.getSourcePortNumber() +
+                           ":" + tcpAddress.getDestinationPortNumber());
+        System.out.println("myAddress: " + myAddress.getAddress() + ":" + myAddress.getSourcePortNumber() +
+                           ":" + myAddress.getDestinationPortNumber());
+        System.out.println("controlAddress: " + controlAddress.getAddress() + ":" + controlAddress.getSourcePortNumber() +
+                           ":" + controlAddress.getDestinationPortNumber());
+        System.out.println("timingAddress: " + timingAddress.getAddress() + ":" + timingAddress.getSourcePortNumber() +
+                           ":" + timingAddress.getDestinationPortNumber());
+        System.out.println("serverAddress: " + serverAddress.getAddress() + ":" + serverAddress.getSourcePortNumber() +
+                           ":" + serverAddress.getDestinationPortNumber());
+
+        // Launch the worker function in a separate thread.
+        monitorThread = new Thread(new Runnable() {
+            public void run() {
+                monitorThreadWorker();
+            }
+        });
+        monitorThread.start();
+    }
+
+
+
+    public boolean startPlayback() {
+
+
+        if (playbackAboutToStart.compareAndSet(false, true) == false) {
+            return false;
+        }
+
+        if (playbackStarted.get()) {
+            return true;
+        }
+
+        if (isDoneEnding.get() == false) {
+            return false;
+        }
+
+        // Reset all Parameters
+        didEnd.set(false);
+        playbackFileIsDone.set(false);
+        playbackState.set(true);
+
+        try {
+            currentPlaybackTimeMutex.acquire();
+            currentPlaybackTime = 0;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        currentPlaybackTimeMutex.release();
+
+
+
+        try {
+            desiredPlaybackTimeMutex.acquire();
+            desiredPlaybackTime = 0;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        desiredPlaybackTimeMutex.release();
+
+        sequenceNumber = SEQUENCE_NUMBER_INITIAL_VALUE;
+        rtpTimestamp = RTP_TIMESTAMP_INITIAL_VALUE;
+
+        try {
+            // start TCP connection
+            iHomeTCPConnection = new IoTTCP(tcpAddress);
+            iHomeTCPConnection.setReuseAddress(true);
+
+            // Get in and out communication
+            PrintWriter tcpOut = new PrintWriter(iHomeTCPConnection.getOutputStream(), true);
+            BufferedReader tcpIn = new BufferedReader(new InputStreamReader(iHomeTCPConnection.getInputStream()));
+
+
+            String session = String.valueOf(SOURCE_ID);
+            connectionURL = "rtsp://" + myAddress.getAddress() + "/" + session;
+
+            // Construct The commands
+            String optionsCommand = "OPTIONS * RTSP/1.0\r\n" +
+                                    "CSeq: 1\r\n" +
+                                    "User-Agent: iTunes/11.0.4 (Windows; N)\r\n" +
+                                    "Client-Instance: c0cb804fd20e80f6\r\n" +
+                                    "Apple-Challenge: i8j36XRYVmSZs9nZ7Kf0Cg\r\n\r\n";
+
+            String announceCommandBody = "v=0\r\n" +
+                                         "o=iTunes " + session + " 0 IN IP4 " + myAddress.getAddress() + "\r\n" +
+                                         "s=iTunes\r\n" +
+                                         "c=IN IP4 " + tcpAddress.getAddress() + "\r\n" +
+                                         "t=0 0\r\n" +
+                                         "m=audio 0 RTP/AVP 96\r\n" +
+                                         "a=rtpmap:96 AppleLossless\r\n" +
+                                         "a=fmtp:96 352 0 16 40 10 14 2 255 0 0 44100\r\n";
+
+            String announceCommand = "ANNOUNCE " + connectionURL + " RTSP/1.0\r\n" +
+                                     "CSeq: 1\r\n" +
+                                     "Content-Type: application/sdp\r\n" +
+                                     "Content-Length: " + announceCommandBody.length() + "\r\n" +
+                                     "User-Agent: iTunes/11.0.4 (Windows; N)\r\n\r\n" +
+                                     announceCommandBody;
+
+
+            // get the ports that we are going to tell the iHome to use
+            int ourControlPort = controlAddress.getSourcePortNumber();
+            int ourTimingPort = timingAddress.getSourcePortNumber();
+
+            String setupCommand = "SETUP " + connectionURL + " RTSP/1.0\r\n" +
+                                  "CSeq: 2\r\n" +
+                                  "Transport: RTP/AVP/UDP;unicast;interleaved=0-1;mode=record;control_port=" + Integer.toString(ourControlPort) + ";timing_port=" + Integer.toString(ourTimingPort) + "\r\n" +
+                                  "User-Agent: iTunes/11.0.4 (Windows; N)\r\n\r\n";
+
+            String recordCommand = "RECORD " + connectionURL + " RTSP/1.0\r\nCSeq: 3\r\nSession: 1\r\nRange: npt=0-\r\nRTP-Info: seq=" + sequenceNumber + ";rtptime=" + rtpTimestamp + "\r\nUser-Agent: iTunes/11.0.4 (Windows; N)\r\n\r\n";
+
+
+            Thread.sleep(100);
+            tcpOut.print(optionsCommand);
+            tcpOut.flush();
+            while (!tcpIn.ready()) {
+            }
+            while (tcpIn.ready()) {
+                String answer = tcpIn.readLine();
+                System.out.println(answer);
+            }
+
+            Thread.sleep(100);
+            tcpOut.print(announceCommand);
+            tcpOut.flush();
+
+            while (!tcpIn.ready()) {
+            }
+            while (tcpIn.ready()) {
+                String answer = tcpIn.readLine();
+                System.out.println(answer);
+            }
+
+            Thread.sleep(100);
+            tcpOut.print(setupCommand);
+            tcpOut.flush();
+            while (!tcpIn.ready()) {
+            }
+
+            // ports that the speaker told us to communicate over
+            int serverPort = -1;
+            int controlPort = -1;
+            int timingPort = -1;
+
+            while (tcpIn.ready()) {
+                String answer = tcpIn.readLine();
+                System.out.println(answer);
+
+                if (answer.contains("Transport")) {
+
+                    String[] splitString = answer.split(";");
+
+                    for (String str : splitString) {
+                        String[] keyValue = str.split("=");
+
+                        if (keyValue.length == 2) {
+                            if (keyValue[0].equals("server_port")) {
+                                serverPort = Integer.parseInt(keyValue[1]);
+
+                            } else if (keyValue[0].equals("control_port")) {
+                                controlPort = Integer.parseInt(keyValue[1]);
+
+                            } else if (keyValue[0].equals("timing_port")) {
+                                timingPort = Integer.parseInt(keyValue[1]);
+                            }
+
+                        }
+                    }
+
+                }
+            }
+
+            serverAddress.setDstPort(serverPort);
+            controlAddress.setDstPort(controlPort);
+            timingAddress.setDstPort(timingPort);
+
+            // Launch the worker function in a separate thread.
+            // Must launch timing thread before record message since record message
+            // syncs with timing
+            timingThread = new Thread(new Runnable() {
+                public void run() {
+                    timingWorkerFunction();
+                }
+            });
+            timingThread.start();
+
+
+            // give the timing thread some time to set itself up
+            Thread.sleep(100);
+
+            tcpOut.print(recordCommand);
+            tcpOut.flush();
+            while (!tcpIn.ready()) {
+            }
+            while (tcpIn.ready()) {
+                String answer = tcpIn.readLine();
+                System.out.println(answer);
+            }
+
+
+
+
+            // Launch the worker function in a separate thread.
+            controlThread = new Thread(new Runnable() {
+                public void run() {
+                    controlWorkerFunction();
+                }
+            });
+            controlThread.start();
+
+
+            playbackFileIsDone.set(false);
+
+            // wait for audio Data
+            Thread.sleep(1000);
+
+            // Launch the worker function in a separate thread.
+            audioThread = new Thread(new Runnable() {
+                public void run() {
+                    audioWorkerFunction();
+                }
+            });
+            audioThread.start();
+
+
+
+
+            // playback has officially Started
+            playbackStarted.set(true);
+
+            // playback started
+            playbackAboutToStart.set(true);
+
+            // Set the volume to the current volume
+            setVolume(currentVolume);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+
+        return true;
+    }
+
+    public boolean stopPlayback() {
+
+        if (playbackAboutToStop.compareAndSet(false, true) == false) {
+            return false;
+        }
+
+        isDoneEnding.set(false);
+        playbackState.set(false);
+        if (playbackStarted.get() == false) {
+            return false;
+        }
+
+        playbackStarted.set(false);
+        didEnd.set(true);
+
+        try {
+            timingThread.join();
+            audioThread.join();
+            controlThread.join();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        isDoneEnding.set(true);
+
+
+        String teardownCommand = "TEARDOWN " + connectionURL + " RTSP/1.0\r\n" +
+                                 "CSeq: 32\r\n" +
+                                 "Session: 1\r\n" +
+                                 "User-Agent: iTunes/11.0.4 (Windows; N)\r\n\r\n";
+
+
+
+        try {
+            // Get in and out communication
+            PrintWriter tcpOut = new PrintWriter(iHomeTCPConnection.getOutputStream(), true);
+            BufferedReader tcpIn = new BufferedReader(new InputStreamReader(iHomeTCPConnection.getInputStream()));
+
+            tcpOut.print(teardownCommand);
+            tcpOut.flush();
+            while (!tcpIn.ready()) {
+            }
+            while (tcpIn.ready()) {
+                String answer = tcpIn.readLine();
+                System.out.println(answer);
+            }
+
+            // close the connection
+            iHomeTCPConnection.close();
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        playbackAboutToStop.set(false);
+
+        return true;
+    }
+
+
+    public boolean getPlaybackState() {
+        return playbackState.get();
+    }
+
+    public boolean setVolume(float _percent) {
+
+        if (settingVolume.compareAndSet(false, true) == false) {
+            return false;
+        }
+
+        // keep in range of percentage
+        if (_percent < 0) {
+            _percent = 0;
+        } else if (_percent > 100) {
+            _percent = 100;
+        }
+
+        // cant set the volume if there is no playback
+        if (playbackStarted.get() == false) {
+            return false;
+        }
+
+        // convert the volume from a percentage to a db
+        float dbVolume = 0;
+        if (_percent > 0) {
+
+            dbVolume = ((float)(_percent / 100.0) * (float)(VOLUME_MAX_VALUE_DB - VOLUME_MIN_VALUE_DB)) + (float)VOLUME_MIN_VALUE_DB;
+
+            // cap the volume to a level that the speaker supports
+            if (dbVolume > VOLUME_MAX_VALUE_DB) {
+                dbVolume = VOLUME_MAX_VALUE_DB;
+            }
+        }
+
+        // construct the command
+        String body = "volume: " + String.format("%f", dbVolume) + "\r\n";
+        String volumeCommand = "SET_PARAMETER " + connectionURL + " RTSP/1.0\r\nCSeq: 4\r\nSession: 1\r\nContent-Type: text/parameters\r\nContent-Length: " + body.length() + "\r\nUser-Agent: iTunes/11.0.4 (Windows; N)\r\n\r\n" + body;
+
+
+
+        try {
+            // Get in and out communication
+            PrintWriter tcpOut = new PrintWriter(iHomeTCPConnection.getOutputStream(), true);
+            BufferedReader tcpIn = new BufferedReader(new InputStreamReader(iHomeTCPConnection.getInputStream()));
+
+            // send and flush
+            tcpOut.print(volumeCommand);
+            tcpOut.flush();
+
+            // Wait for data to come back
+            while (!tcpIn.ready()) {
+            }
+
+            // read the data from the iHome
+            while (tcpIn.ready()) {
+                String answer = tcpIn.readLine();
+                System.out.println(answer);
+            }
+
+            // update the current volume parameter
+            currentVolume = _percent;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        settingVolume.set(false);
+
+        return true;
+    }
+
+    public float getVolume() {
+
+        while (settingVolume.get()) {
+            // block until volume set is done
+        }
+        return currentVolume;
+    }
+
+    public void loadData(short[] _samples, int _offs, int _len) {
+
+        short[] sample = new short[_len];
+        int j = _offs;
+        for (int i = 0; i < _len; i++, j++) {
+            sample[i] = _samples[j];
+        }
+        synchronized (audioLinkedList) {
+            audioLinkedList.addLast(sample);
+        }
+    }
+
+    public void clearData() {
+        synchronized (audioLinkedList) {
+            audioLinkedList.clear();
+        }
+    }
+
+    public int getPosition() {
+        long pTime = 0;
+        try {
+            currentPlaybackTimeMutex.acquire();
+            pTime = currentPlaybackTime;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        currentPlaybackTimeMutex.release();
+
+        int mSecPos = (int)((pTime * 1000) / 44100);
+        return mSecPos;
+    }
+
+    public void setPosition(int _mSec) {
+        int sampleNumber = (_mSec * 44100) / 1000;
+
+        try {
+            desiredPlaybackTimeMutex.acquire();
+            desiredPlaybackTime = sampleNumber;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        desiredPlaybackTimeMutex.release();
+    }
+
+
+    public void registerCallback(SpeakerSmartCallback _cb) {
+        callbackList.add(_cb);
+    }
+
+
+    /*******************************************************************************************************************************************
+    **
+    **  Helper Methods
+    **
+    *******************************************************************************************************************************************/
+
+
+    private void timingWorkerFunction() {
+        try {
+            IoTUDP timingUDP = new IoTUDP(timingAddress);
+
+            byte[] receiveData = new byte[1024];
+            byte[] sendData = new byte[32];
+
+            while (didEnd.get() == false) {
+
+                receiveData = timingUDP.recieveData(receiveData.length);
+
+                long nanotime = nanoTime();
+                int seconds = (int)((nanotime / 1000000000) & 0xffffffff);
+                long fractions = ((( nanotime % 1000000000) * (0xffffffffL)) / 1000000000);
+
+                sendData[0] = (byte)0x80;                   // Header bit field
+                sendData[1] = (byte)0xd3;                   // mark bit and message payload number
+
+                sendData[2] = (byte) 0x00;
+                sendData[3] = (byte) 0x07;
+
+                sendData[4] = (byte) 0x00;
+                sendData[5] = (byte) 0x00;
+                sendData[6] = (byte) 0x00;
+                sendData[7] = (byte) 0x00;
+
+                // origin time-stamp
+                sendData[8] = receiveData[24];
+                sendData[9] = receiveData[25];
+                sendData[10] = receiveData[26];
+                sendData[11] = receiveData[27];
+                sendData[12] = receiveData[28];
+                sendData[13] = receiveData[29];
+                sendData[14] = receiveData[30];
+                sendData[15] = receiveData[31];
+
+                // arrival time-stamp
+                sendData[16] = (byte)((seconds >> 24) & 0xff);
+                sendData[17] = (byte)((seconds >> 16) & 0xff);
+                sendData[18] = (byte)((seconds >> 8) & 0xff);
+                sendData[19] = (byte)((seconds >> 0) & 0xff);
+                sendData[20] = (byte)((fractions >> 24) & 0xff);
+                sendData[21] = (byte)((fractions >> 16) & 0xff);
+                sendData[22] = (byte)((fractions >> 8) & 0xff);
+                sendData[23] = (byte)((fractions >> 0) & 0xff);
+
+
+                nanotime = nanoTime();
+                seconds = (int)( nanotime / 1000000000);
+                fractions = ((( nanotime % 1000000000) * (0xffffffffL)) / 1000000000);
+
+                // transmit time-stamp
+                sendData[24] = (byte)((seconds >> 24) & 0xff);
+                sendData[25] = (byte)((seconds >> 16) & 0xff);
+                sendData[26] = (byte)((seconds >> 8) & 0xff);
+                sendData[27] = (byte)((seconds >> 0) & 0xff);
+                sendData[28] = (byte)((fractions >> 24) & 0xff);
+                sendData[29] = (byte)((fractions >> 16) & 0xff);
+                sendData[30] = (byte)((fractions >> 8) & 0xff);
+                sendData[31] = (byte)((fractions >> 0) & 0xff);
+
+                // Send the Data
+                timingUDP.sendData(sendData);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void controlWorkerFunction() {
+
+        try {
+
+            IoTUDP controlUDP = new IoTUDP(controlAddress);
+            controlUDP.setSoTimeout(1);
+            byte[] sendData = new byte[20];
+            boolean first = true;
+
+
+            while (didEnd.get() == false) {
+
+                try {
+                    byte[] receiveData = new byte[24];
+                    receiveData = controlUDP.recieveData(receiveData.length);
+
+                    // System.out.println("Control Packet Arrived");
+                    // String packetData = bytesToHex(receiveData);
+                    // System.out.println(packetData);
+
+                } catch (Exception e) {
+                    // e.printStackTrace();
+                }
+
+
+                long rtpTimestampCopy = rtpTimestamp;
+                long nanotime = nanoTime();
+                int seconds = (int)( nanotime / 1000000000);
+                long fractions = (( nanotime % 1000000000) * (0xffffffffL)) / 1000000000;
+
+
+                if (first) {
+                    sendData[0] = (byte)0x90;                       // Header bit field
+                    first = false;
+                } else {
+                    sendData[0] = (byte)0x80;                       // Header bit field
+                }
+
+
+                sendData[1] = (byte)0xd4;                   // mark bit and message payload number
+                sendData[2] = (byte)0x00;
+                sendData[3] = (byte)0x07;
+
+                // time-stamp of packet
+                sendData[4] = (byte)((rtpTimestampCopy >> 24) & 0xFF);
+                sendData[5] = (byte)((rtpTimestampCopy >> 16) & 0xFF);
+                sendData[6] = (byte)((rtpTimestampCopy >> 8) & 0xFF);
+                sendData[7] = (byte)((rtpTimestampCopy >> 0) & 0xFF);
+
+                // ntp time-stamp
+                sendData[8] = (byte)((seconds >> 24) & 0xff);
+                sendData[9] = (byte)((seconds >> 16) & 0xff);
+                sendData[10] = (byte)((seconds >> 8) & 0xff);
+                sendData[11] = (byte)((seconds >> 0) & 0xff);
+
+                sendData[12] = (byte)((fractions >> 24) & 0xff);
+                sendData[13] = (byte)((fractions >> 16) & 0xff);
+                sendData[14] = (byte)((fractions >> 8) & 0xff);
+                sendData[15] = (byte)((fractions >> 0) & 0xff);
+
+                rtpTimestampCopy += 88200;
+                sendData[16] = (byte)((rtpTimestampCopy >> 24) & 0xFF);
+                sendData[17] = (byte)((rtpTimestampCopy >> 16) & 0xFF);
+                sendData[18] = (byte)((rtpTimestampCopy >> 8) & 0xFF);
+                sendData[19] = (byte)((rtpTimestampCopy >> 0) & 0xFF);
+
+                // send the data
+                controlUDP.sendData(sendData);
+
+                // System.out.println("---------------------------------------------");
+                // System.out.println("Sending Control Sync");
+                // System.out.println("---------------------------------------------");
+
+                Thread.sleep(1000);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void audioWorkerFunction() {
+        try {
+
+            IoTUDP serverUDP = new IoTUDP(serverAddress);
+
+            // current frame being played
+            long frameCounter = 0;
+
+            // used for bit packing for audio stream
+            short[] array = null;
+            int offset = 0;
+
+            int noAudioCount = 0;
+
+            while (didEnd.get() == false) {
+
+                byte[] sendData = new byte[352 * 4 + 19];
+
+                sendData[0] = (byte)0x80;
+
+                if (frameCounter == 0) {
+                    sendData[1] = (byte)0xe0;
+                    // frameCounter = 1;
+                } else {
+                    sendData[1] = (byte)0x60;
+                }
+
+                sendData[2] = (byte)((sequenceNumber >> 8) & 0xFF);
+                sendData[3] = (byte)((sequenceNumber >> 0) & 0xFF);
+
+                long rtpTmp = rtpTimestamp;
+
+                sendData[4] = (byte)((rtpTmp >> 24) & 0xFF);
+                sendData[5] = (byte)((rtpTmp >> 16) & 0xFF);
+                sendData[6] = (byte)((rtpTmp >> 8) & 0xFF);
+                sendData[7] = (byte)((rtpTmp >> 0) & 0xFF);
+
+                sendData[8] = (byte)((SEQUENCE_ID >> 24) & 0xFF);
+                sendData[9] = (byte)((SEQUENCE_ID >> 16) & 0xFF);
+                sendData[10] = (byte)((SEQUENCE_ID >> 8) & 0xFF);
+                sendData[11] = (byte)((SEQUENCE_ID >> 0) & 0xFF);
+
+                sendData[12] = (byte) 0x20;
+                sendData[13] = (byte) 0x00;
+                sendData[14] = (byte) 0x12;
+                sendData[15] = (byte) 0x00;
+                sendData[16] = (byte) 0x00;
+                sendData[17] = (byte) 0x02;
+                sendData[18] = (byte) 0xc0;
+
+                for (int i = 19; i < sendData.length; i += 4) {
+                    if (array != null && (offset + 1) >= array.length) {
+                        array = null;
+                    }
+
+                    if (array == null) {
+                        offset = 0;
+
+                        synchronized (audioLinkedList) {
+                            array = (short[])audioLinkedList.poll();
+                        }
+                    }
+
+                    if (array != null) {
+
+                        long time1 = 0;
+                        long time2 = 0;
+
+                        try {
+                            desiredPlaybackTimeMutex.acquire();
+                            time1 = desiredPlaybackTime;
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+
+                        desiredPlaybackTimeMutex.release();
+
+
+                        try {
+                            currentPlaybackTimeMutex.acquire();
+                            time2 = currentPlaybackTime;
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                        currentPlaybackTimeMutex.release();
+
+
+                        while ((time2 < time1)) {
+                            offset++;
+
+                            try {
+                                currentPlaybackTimeMutex.acquire();
+                                currentPlaybackTime++;
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                            currentPlaybackTimeMutex.release();
+
+
+                            if ((offset + 1) >= array.length) {
+                                offset = 0;
+                                synchronized (audioLinkedList) {
+                                    array = (short[])audioLinkedList.poll();
+                                }
+
+                                if (array == null) {
+                                    break;
+                                }
+                            }
+                        }
+                    }
+
+                    short l = 0;
+                    short r = 0;
+
+                    if (array != null) {
+                        l = array[offset++];
+                        r = array[offset++];
+
+                        try {
+                            currentPlaybackTimeMutex.acquire();
+                            currentPlaybackTime++;
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                        currentPlaybackTimeMutex.release();
+
+
+                        try {
+                            desiredPlaybackTimeMutex.acquire();
+                            desiredPlaybackTime++;
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+
+                        desiredPlaybackTimeMutex.release();
+
+                        noAudioCount = 0;
+                    } else {
+                        noAudioCount++;
+
+                        if (noAudioCount > 10) {
+                            noAudioCount = 0;
+                            if (playbackFileIsDone.get() == false) {
+                                playbackFileIsDone.set(true);
+                            }
+                        }
+                    }
+
+                    sendData[i - 1] |= (byte)((l >> 15) & 1);
+                    sendData[i] = (byte)((l >> 7) & 0xff);
+                    sendData[i + 1] = (byte)(((l << 1) & 0xfe) | ((r >> 15) & 1));
+                    sendData[i + 2] = (byte)((r >> 7) & 0xff);
+                    sendData[i + 3] = (byte)((r << 1) & 0xfe);
+                }
+
+
+                sequenceNumber++;
+                sequenceNumber = sequenceNumber % SEQUENCE_NUMBER_WRAP_AROUND;
+                rtpTimestamp += RTP_TIMESTAMP_INCREMENT_VALUE;
+
+                frameCounter++;
+                serverUDP.sendData(sendData);
+
+
+                // need to sleep for a bit
+                if ((frameCounter % 2) == 0) {
+                    Thread.sleep(7);
+                } else {
+                    Thread.sleep(6);
+                }
+
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void monitorThreadWorker() {
+        while (driverIsShuttingDown.get() == false) {
+            if (playbackFileIsDone.get()) {
+                stopPlayback();
+                playbackFileIsDone.set(false);
+
+                for (SpeakerSmartCallback c : callbackList) {
+                    try {
+                        //c.speakerDone(this);
+                                               c.speakerDone();
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+    }
+
+    private void endDriver() {
+        stopPlayback();
+
+        driverIsShuttingDown.set(true);
+        try {
+            monitorThread.join();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        didClose = true;
+    }
+
+    /**
+     * close() called by the garbage collector right before trashing object
+     */
+    public void finalize() {
+        if (!didClose) {
+            endDriver();
+        }
+    }
+
+    private static long nanoTime() {
+        long nanotime = System.nanoTime();
+        return nanotime;
+    }
+}
+
+
+
+
index 342d3fbcdbc77ee4b9ed9d89f3c6761735ef4f8f..5e6706b399e89e77debc5024f625ec2d18e616f6 100644 (file)
@@ -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
+all: light camera labroom greenlawn sprinkler moisture weathergateway audioroom gpsgateway ihome
 
 # Compile
 #
@@ -56,4 +56,22 @@ weathergateway:
        cp WeatherPhoneGateway/WeatherPhoneGateway.config $(BIN_DIR)/iotcode/WeatherPhoneGateway
        cd $(BIN_DIR)/iotcode/WeatherPhoneGateway; $(JAR) $(JARFLAGS) WeatherPhoneGateway.jar ../../iotcode/WeatherPhoneGateway/*.class ../../iotcode/interfaces/WeatherGateway*.class
 
+PHONY += audioroom
+audioroom:
+       $(JAVAC) $(JFLAGS) AudioRoom/*.java
+       cp AudioRoom/AudioRoom.config $(BIN_DIR)/iotcode/AudioRoom
+       cd $(BIN_DIR)/iotcode/AudioRoom; $(JAR) $(JARFLAGS) AudioRoom.jar ../../iotcode/AudioRoom/*.class ../../iotcode/interfaces/Room*.class
+
+PHONY += gpsgateway
+gpsgateway:
+       $(JAVAC) $(JFLAGS) GPSPhoneGateway/*.java
+       cp GPSPhoneGateway/GPSPhoneGateway.config $(BIN_DIR)/iotcode/GPSPhoneGateway
+       cd $(BIN_DIR)/iotcode/GPSPhoneGateway; $(JAR) $(JARFLAGS) GPSPhoneGateway.jar ../../iotcode/GPSPhoneGateway/*.class ../../iotcode/interfaces/GPSGateway*.class
+
+PHONY += ihome
+ihome:
+       $(JAVAC) $(JFLAGS) IHome/*.java
+       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: $(PHONY)
diff --git a/benchmarks/interfaces/GPSGateway.java b/benchmarks/interfaces/GPSGateway.java
new file mode 100644 (file)
index 0000000..243ae87
--- /dev/null
@@ -0,0 +1,15 @@
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface GPSGateway {
+       public void init();
+       public void start();
+       public void stop();
+       public int getRoomID();
+       public boolean getRingStatus();
+       public void setNewRoomIDAvailable(boolean bValue);
+       public void setNewRingStatusAvailable(boolean bValue);
+       public void registerCallback(GPSGatewaySmartCallback _callbackTo);
+}
diff --git a/benchmarks/interfaces/GPSGatewayCallback.java b/benchmarks/interfaces/GPSGatewayCallback.java
new file mode 100644 (file)
index 0000000..c07b893
--- /dev/null
@@ -0,0 +1,9 @@
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface GPSGatewayCallback {
+       public void newRoomIDRetrieved(int _roomIdentifier);
+       public void newRingStatusRetrieved(boolean _ringStatus);
+}
diff --git a/benchmarks/interfaces/GPSGatewaySmart.java b/benchmarks/interfaces/GPSGatewaySmart.java
new file mode 100644 (file)
index 0000000..542ae43
--- /dev/null
@@ -0,0 +1,16 @@
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface GPSGatewaySmart {
+
+       public void setNewRoomIDAvailable(boolean bValue);
+       public void setNewRingStatusAvailable(boolean bValue);
+       public void stop();
+       public void start();
+       public void init();
+       public int getRoomID();
+       public void registerCallback(GPSGatewayCallback _callbackTo);
+       public boolean getRingStatus();
+}
diff --git a/benchmarks/interfaces/GPSGatewaySmartCallback.java b/benchmarks/interfaces/GPSGatewaySmartCallback.java
new file mode 100644 (file)
index 0000000..2bfed5f
--- /dev/null
@@ -0,0 +1,10 @@
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface GPSGatewaySmartCallback {
+
+       public void newRoomIDRetrieved(int _roomIdentifier);
+       public void newRingStatusRetrieved(boolean _ringStatus);
+}
diff --git a/benchmarks/interfaces/Speaker.java b/benchmarks/interfaces/Speaker.java
new file mode 100644 (file)
index 0000000..c6406f0
--- /dev/null
@@ -0,0 +1,18 @@
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface Speaker {
+       public void init();
+       public boolean startPlayback();
+       public boolean stopPlayback();
+       public boolean getPlaybackState();
+       public boolean setVolume(float _percent);
+       public float getVolume();
+       public int getPosition();
+       public void setPosition(int _mSec);
+       public void loadData(short _samples[], int _offs, int _len);
+       public void clearData();
+       public void registerCallback(SpeakerSmartCallback _cb);
+}
diff --git a/benchmarks/interfaces/SpeakerCallback.java b/benchmarks/interfaces/SpeakerCallback.java
new file mode 100644 (file)
index 0000000..0b3e343
--- /dev/null
@@ -0,0 +1,8 @@
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface SpeakerCallback {
+       public void speakerDone();
+}
diff --git a/benchmarks/interfaces/SpeakerSmart.java b/benchmarks/interfaces/SpeakerSmart.java
new file mode 100644 (file)
index 0000000..336ce8c
--- /dev/null
@@ -0,0 +1,19 @@
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface SpeakerSmart {
+
+       public int getPosition();
+       public boolean stopPlayback();
+       public void clearData();
+       public boolean startPlayback();
+       public boolean getPlaybackState();
+       public boolean setVolume(float _percent);
+       public float getVolume();
+       public void setPosition(int _mSec);
+       public void loadData(short _samples[], int _offs, int _len);
+       public void init();
+       public void registerCallback(SpeakerCallback _cb);
+}
diff --git a/benchmarks/interfaces/SpeakerSmartCallback.java b/benchmarks/interfaces/SpeakerSmartCallback.java
new file mode 100644 (file)
index 0000000..a2213bb
--- /dev/null
@@ -0,0 +1,9 @@
+package iotcode.interfaces;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public interface SpeakerSmartCallback {
+
+       public void speakerDone();
+}
index dd425ca26992ae500368ad942bdd26155c9a496b..f996ce56212bbcbb126a476d95f7d4e59e2120c2 100644 (file)
@@ -76,6 +76,25 @@ run-compiler-moist:
        cp ../localconfig/iotpolicy/SpruceSensor/*.req $(BIN_DIR)/iotpolicy/
        cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler sprucesensor.pol smartsensor.req moisturesensorcallback.pol moisturesensorcallback.req -java Java
 
+# SpeakerController
+PHONY += run-compiler-audiorm
+run-compiler-audiorm:
+       cp ../localconfig/iotpolicy/AudioRoom/*.pol $(BIN_DIR)/iotpolicy/
+       cp ../localconfig/iotpolicy/AudioRoom/*.req $(BIN_DIR)/iotpolicy/
+       cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler audioroom.pol roomsmart.req -java Java
+
+PHONY += run-compiler-spkr
+run-compiler-spkr:
+       cp ../localconfig/iotpolicy/IHome/*.pol $(BIN_DIR)/iotpolicy/
+       cp ../localconfig/iotpolicy/IHome/*.req $(BIN_DIR)/iotpolicy/
+       cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler ihome.pol smartspeaker.req speakercallback.pol smartspeakercallback.req -java Java
+
+PHONY += run-compiler-ggw
+run-compiler-ggw:
+       cp ../localconfig/iotpolicy/GPSPhoneGateway/*.pol $(BIN_DIR)/iotpolicy/
+       cp ../localconfig/iotpolicy/GPSPhoneGateway/*.req $(BIN_DIR)/iotpolicy/
+       cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler gpsphonegateway.pol smartgpsgateway.req gpsgatewaycallback.pol smartgpsgatewaycallback.req -java Java
+
 # TODO: Can remove this later - just to test-compile the resulted files from the compiler
 PHONY += compile
 compile:
diff --git a/localconfig/iotpolicy/AudioRoom/audioroom.pol b/localconfig/iotpolicy/AudioRoom/audioroom.pol
new file mode 100644 (file)
index 0000000..17f3bbd
--- /dev/null
@@ -0,0 +1,11 @@
+public interface Room {
+
+       public int getRoomID();
+
+       capability Basic {
+               description = "Get room ID";
+               method = "getRoomID()";
+       }
+}
+
+
diff --git a/localconfig/iotpolicy/AudioRoom/roomsmart.req b/localconfig/iotpolicy/AudioRoom/roomsmart.req
new file mode 100644 (file)
index 0000000..71de3c9
--- /dev/null
@@ -0,0 +1,3 @@
+
+requires Room with Basic as interface RoomSmart;
+
diff --git a/localconfig/iotpolicy/GPSPhoneGateway/gpsgatewaycallback.pol b/localconfig/iotpolicy/GPSPhoneGateway/gpsgatewaycallback.pol
new file mode 100644 (file)
index 0000000..984c39a
--- /dev/null
@@ -0,0 +1,13 @@
+public interface GPSGatewayCallback {
+
+       public void newRoomIDRetrieved(int _roomIdentifier);
+       public void newRingStatusRetrieved(boolean _ringStatus);
+
+       capability Callback {
+               description = "Callback methods";
+               method = "newRoomIDRetrieved(int _roomIdentifier)";
+               method = "newRingStatusRetrieved(boolean _ringStatus)";
+       }
+}
+
+
diff --git a/localconfig/iotpolicy/GPSPhoneGateway/gpsphonegateway.pol b/localconfig/iotpolicy/GPSPhoneGateway/gpsphonegateway.pol
new file mode 100644 (file)
index 0000000..5a1e769
--- /dev/null
@@ -0,0 +1,29 @@
+public interface GPSGateway {
+
+       public void init();
+       public void start();
+       public void stop();
+       public int getRoomID();
+       public boolean getRingStatus();
+       public void setNewRoomIDAvailable(boolean bValue);
+       public void setNewRingStatusAvailable(boolean bValue);
+       public void registerCallback(GPSGatewayCallback _callbackTo);
+
+       capability Initialize {
+               description = "Initialize object";
+               method = "init()";
+               method = "start()";
+               method = "stop()";
+               method = "registerCallback(GPSGatewayCallback _callbackTo)";
+       }
+
+       capability GPSUpdate {
+               description = "Manage GPS data update";
+               method = "getRoomID()";
+               method = "getRingStatus()";
+               method = "setNewRoomIDAvailable(boolean bValue)";
+               method = "setNewRingStatusAvailable(boolean bValue)";
+       }
+}
+
+
diff --git a/localconfig/iotpolicy/GPSPhoneGateway/smartgpsgateway.req b/localconfig/iotpolicy/GPSPhoneGateway/smartgpsgateway.req
new file mode 100644 (file)
index 0000000..d2811b0
--- /dev/null
@@ -0,0 +1,3 @@
+
+requires GPSGateway with Initialize, GPSUpdate as interface GPSGatewaySmart;
+
diff --git a/localconfig/iotpolicy/GPSPhoneGateway/smartgpsgatewaycallback.req b/localconfig/iotpolicy/GPSPhoneGateway/smartgpsgatewaycallback.req
new file mode 100644 (file)
index 0000000..b9e8ddf
--- /dev/null
@@ -0,0 +1,3 @@
+
+requires GPSGatewayCallback with Callback as interface GPSGatewaySmartCallback;
+
diff --git a/localconfig/iotpolicy/IHome/ihome.pol b/localconfig/iotpolicy/IHome/ihome.pol
new file mode 100644 (file)
index 0000000..520c974
--- /dev/null
@@ -0,0 +1,47 @@
+public interface Speaker {
+
+       public void init();
+       public boolean startPlayback();
+       public boolean stopPlayback();
+       public boolean getPlaybackState();
+       public boolean setVolume(float _percent);
+       public float getVolume();
+       public int getPosition();
+       public void setPosition(int _mSec);
+       public void loadData(short _samples[], int _offs, int _len);
+       public void clearData();
+       public void registerCallback(SpeakerCallback _cb);
+
+       capability Initialize {
+               description = "Initialize object";
+               method = "init()";
+               method = "registerCallback(SpeakerCallback _cb)";
+       }
+
+       capability Playback {
+               description = "Manage playback";
+               method = "startPlayback()";
+               method = "stopPlayback()";
+               method = "getPlaybackState()";
+       }
+
+       capability Volume {
+               description = "Manage volume";
+               method = "setVolume(float _percent)";
+               method = "getVolume()";
+       }
+
+       capability Position {
+               description = "Manage position in the song";
+               method = "getPosition()";
+               method = "setPosition(int _mSec)";
+       }
+
+       capability Data {
+               description = "Manage song data";
+               method = "loadData(short _samples[], int _offs, int _len)";
+               method = "clearData()";
+       }
+}
+
+
diff --git a/localconfig/iotpolicy/IHome/smartspeaker.req b/localconfig/iotpolicy/IHome/smartspeaker.req
new file mode 100644 (file)
index 0000000..a569383
--- /dev/null
@@ -0,0 +1,3 @@
+
+requires Speaker with Initialize, Playback, Volume, Position, Data as interface SpeakerSmart;
+
diff --git a/localconfig/iotpolicy/IHome/smartspeakercallback.req b/localconfig/iotpolicy/IHome/smartspeakercallback.req
new file mode 100644 (file)
index 0000000..23ad981
--- /dev/null
@@ -0,0 +1,3 @@
+
+requires SpeakerCallback with Callback as interface SpeakerSmartCallback;
+
diff --git a/localconfig/iotpolicy/IHome/speakercallback.pol b/localconfig/iotpolicy/IHome/speakercallback.pol
new file mode 100644 (file)
index 0000000..8a2fb15
--- /dev/null
@@ -0,0 +1,11 @@
+public interface SpeakerCallback {
+
+       public void speakerDone();
+
+       capability Callback {
+               description = "Callback method";
+               method = "speakerDone()";
+       }
+}
+
+