PHONY += drivers
drivers:
- $(MAKE) -C drivers
+ $(MAKE) -C drivers/Java
PHONY += Lifxtest
Lifxtest:
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=Camera
-# Stub
-INTERFACE_STUB_CLASS=CameraSmart
+++ /dev/null
-package iotcode.AmcrestCamera;
-
-// IoT Packages
-import iotcode.annotation.*;
-import iotcode.interfaces.*;
-import iotruntime.IoTHTTP;
-import iotruntime.slave.IoTSet;
-import iotruntime.slave.IoTDeviceAddress;
-
-// Standard Java Packages
-import java.io.IOException;
-import java.io.DataInputStream;
-import java.io.InputStream;
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.WritableRaster;
-import java.awt.image.BufferedImage;
-import javax.imageio.ImageIO;
-import java.util.Base64;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.Iterator;
-import javax.imageio.ImageIO;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Semaphore;
-
-// RMI Packages
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-
-// Checker annotations
-//import iotchecker.qual.*;
-
-public class AmcrestCamera implements Camera {
-
- /*******************************************************************************************************************************************
- **
- ** Variables
- **
- *******************************************************************************************************************************************/
- private String credentialUsername = "";
- private String credentialPassword = "";
- private DataInputStream dataInStream = null;
- private boolean isStreamConnected = false;
- private byte[] latestImage = null;
- private ReadWriteLock imageReadWriteLock = new ReentrantReadWriteLock();
- private Lock imageReadLock = imageReadWriteLock.readLock();
- private Lock imageWriteLock = imageReadWriteLock.writeLock();
- private AtomicBoolean newFrameAvailable = new AtomicBoolean(false);
- private ReadWriteLock timestampReadWriteLock = new ReentrantReadWriteLock();
- private Lock timestampReadLock = timestampReadWriteLock.readLock();
- private Lock timestampWriteLock = timestampReadWriteLock.writeLock();
- private Date latestImageTimestamp = null;
- private List <CameraSmartCallback> callbackList =
- new CopyOnWriteArrayList <CameraSmartCallback> ();
- private AtomicBoolean doEnd = new AtomicBoolean(false);
- private IoTDeviceAddress deviceAddress = null;
- private AtomicBoolean didInit = new AtomicBoolean();
- private AtomicBoolean didStart = new AtomicBoolean();
- static Semaphore settingsSettings = new Semaphore(1);
-
- /*******************************************************************************************************************************************
- **
- ** Threads
- **
- *******************************************************************************************************************************************/
- private Thread callbackThread = null;
- private Thread workerThread = null;
-
-
- /*******************************************************************************************************************************************
- **
- ** IoT Sets and Relations
- **
- *******************************************************************************************************************************************/
-
- // IoTSet of Device Addresses.
- // Will be filled with only 1 address.
- @config private IoTSet<IoTDeviceAddress> cam_addresses;
-
-
- public AmcrestCamera(String _credentialUsername, String _credentialPassword) throws RemoteException {
- credentialUsername = _credentialUsername;
- credentialPassword = _credentialPassword;
- }
-
- /*******************************************************************************************************************************************
- **
- ** Camera Interface Methods
- **
- *******************************************************************************************************************************************/
-
- public byte[] getLatestFrame() {
-
- byte[] newImage = null;
-
- imageReadLock.lock();
- try {
- if (latestImage != null) {
- newImage = Arrays.copyOf(latestImage, latestImage.length);
- }
- } catch (Exception x) {
- x.printStackTrace();
- }
- imageReadLock.unlock();
-
- return newImage;
- }
-
- public long getTimestamp() {
- timestampReadLock.lock();
- Date ret = (Date)latestImageTimestamp.clone();
- timestampReadLock.unlock();
- long retLong = ret.getTime();
- return retLong;
- }
-
- public void registerCallback(CameraSmartCallback _callbackTo) {
- callbackList.add(_callbackTo);
- }
-
- public boolean setFPS(int _fps) {
- try {
- settingsSettings.acquire();
-
- String camUrlString = "/cgi-bin/configManager.cgi?action=setConfig&Encode[0].MainFormat[0].Video.FPS=" + Integer.toString(_fps);
-
- try {
-
- String credsPreBase64 = credentialUsername + ":" + credentialPassword;
- String credsBase64 = Base64.getEncoder().encodeToString(credsPreBase64.getBytes("utf-8"));
- String httpAuthCredentials = "Basic " + credsBase64;
-
- IoTHTTP httpConnection = new IoTHTTP(deviceAddress);
- httpConnection.setURL(camUrlString);
- httpConnection.openConnection();
- httpConnection.setDoInput(true);
- httpConnection.setRequestProperty("Authorization", httpAuthCredentials);
- httpConnection.connect();
-
- InputStream is = httpConnection.getInputStream();
- BufferedInputStream bis = new BufferedInputStream(is);
- DataInputStream din = new DataInputStream(bis);
-
- // wait for a response
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ie) {
- }
-
- byte[] byteBuf = new byte[100];
- try {
- int r = din.read(byteBuf, 0, byteBuf.length);
- String retString = new String(byteBuf);
-
- if (!retString.substring(0, 2).equals("OK")) {
- httpConnection.disconnect();
- return false;
- }
-
- } catch (Exception e) {
- httpConnection.disconnect();
- return false;
- // e.printStackTrace();
- }
-
- httpConnection.disconnect();
- } catch (IOException e) {
- return false;
- } catch (Exception e) {
- return false;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- settingsSettings.release();
-
- return true;
- }
-
- public int getMaxFPS() {
- // Hard coded since this is hardware dependant
- return 30;
- }
-
- public int getMinFPS() {
- // Hard coded since this is hardware dependant
- return 5;
- }
-
- public List<Resolution> getSupportedResolutions() {
-
- // Hard coded since this is hardware dependant
- List<Resolution> ret = new ArrayList<Resolution>();
- ret.add(Resolution.RES_1080P);
- ret.add(Resolution.RES_720P);
- ret.add(Resolution.RES_VGA);
- return ret;
- }
-
- public boolean setResolution(Resolution _res) {
-
- try {
- settingsSettings.acquire();
-
-
- String camUrlString = "/cgi-bin/configManager.cgi?action=setConfig";
-
- if (_res == Resolution.RES_1080P) {
- camUrlString += "&Encode[0].MainFormat[0].Video.Height=1080&Encode[0].MainFormat[0].Video.Width=1920";
-
- } else if (_res == Resolution.RES_720P) {
- camUrlString += "&Encode[0].MainFormat[0].Video.Height=720&Encode[0].MainFormat[0].Video.Width=1280";
-
- } else if (_res == Resolution.RES_VGA) {
- camUrlString += "&Encode[0].MainFormat[0].Video.Height=480&Encode[0].MainFormat[0].Video.Width=640";
- }
-
-
- try {
-
- String credsPreBase64 = credentialUsername + ":" + credentialPassword;
- String credsBase64 = Base64.getEncoder().encodeToString(credsPreBase64.getBytes("utf-8"));
- String httpAuthCredentials = "Basic " + credsBase64;
-
- IoTHTTP httpConnection = new IoTHTTP(deviceAddress);
- httpConnection.setURL(camUrlString);
- httpConnection.openConnection();
- httpConnection.setDoInput(true);
- httpConnection.setRequestProperty("Authorization", httpAuthCredentials);
- httpConnection.connect();
-
- InputStream is = httpConnection.getInputStream();
- BufferedInputStream bis = new BufferedInputStream(is);
- DataInputStream din = new DataInputStream(bis);
-
- // wait for a response
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ie) {
- }
-
- byte[] byteBuf = new byte[100];
- try {
- int r = din.read(byteBuf, 0, byteBuf.length);
- String retString = new String(byteBuf);
-
- if (!retString.substring(0, 2).equals("OK")) {
- httpConnection.disconnect();
- return false;
- }
-
- } catch (Exception e) {
- httpConnection.disconnect();
- return false;
- // e.printStackTrace();
- }
-
- httpConnection.disconnect();
- } catch (IOException e) {
- return false;
- } catch (Exception e) {
- return false;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- settingsSettings.release();
-
- return true;
- }
-
- public void start() {
-
- if (didStart.compareAndSet(false, true) == false) {
- return; // already started
- }
-
-
-
- doEnd.set(false);
-
- if (!streamConnect()) {
- return;
- }
-
- callbackThread = new Thread(new Runnable() {
- public void run() {
- doCallbacks();
- }
- });
- callbackThread.start();
-
- workerThread = new Thread(new Runnable() {
- public void run() {
- doWork();
- }
- });
- workerThread.start();
- }
-
- public void stop() {
- if (didStart.compareAndSet(true, false) == false) {
- return; // already stopped
- }
-
- doEnd.set(true);
-
- try {
- callbackThread.join();
- workerThread.join();
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- streamDisconnect();
- }
-
- public void init() {
- if (didInit.compareAndSet(false, true) == false) {
- return; // already init
- }
-
- // get the device address and save it for later use when creating HTTP connections
- Iterator itr = cam_addresses.iterator();
- deviceAddress = (IoTDeviceAddress)itr.next();
-
- System.out.println("Address: " + deviceAddress.getCompleteAddress());
- }
-
- /*******************************************************************************************************************************************
- **
- ** Helper Methods
- **
- *******************************************************************************************************************************************/
- private byte[] readFromStream(int num) {
- byte[] byteBuf = new byte[num];
- try {
- dataInStream.readFully(byteBuf, 0, byteBuf.length);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- return byteBuf;
- }
-
- private void findBoundry() {
- String boundary = "**************";
- while (true) {
- byte b = readFromStream(1)[0];
- boundary = boundary.substring(1);
- boundary += (char)b;
-
- if (boundary.equals("--myboundary\r\n")) {
- break;
- }
- }
- }
-
- private String getLine() {
- String line = "";
- while (true) {
- byte b = readFromStream(1)[0];
- char c = (char)b;
-
- if (c == '\n') {
- break;
- } else if (c != '\r') {
- line += c;
- }
- }
-
- return line;
- }
-
- private BufferedImage parseImage() {
-
- findBoundry();
-
- String contentTypeString = getLine();
- String contentLengthString = getLine();
-
- // remove the new line characters \r\n
- readFromStream(2);
-
- int imageDataLength = Integer.parseInt(contentLengthString.substring(16));
-
- byte[] imageDataBuf = readFromStream(imageDataLength);
-
- // remove the new line characters \r\n
- readFromStream(2);
-
-
- try {
- InputStream imageInStream = new ByteArrayInputStream(imageDataBuf);
- return ImageIO.read(imageInStream);
-
- } catch (Exception e) {
- e.printStackTrace();
- System.out.println("Has Exception");
-
- }
-
- return null;
- }
-
- private boolean streamConnect() {
-
- try {
-
- String credsPreBase64 = credentialUsername + ":" + credentialPassword;
- String credsBase64 = Base64.getEncoder().encodeToString(credsPreBase64.getBytes("utf-8"));
- String httpAuthCredentials = "Basic " + credsBase64;
-
- IoTHTTP httpConnection = new IoTHTTP(deviceAddress);
- httpConnection.setURL("/cgi-bin/mjpg/video.cgi?");
- httpConnection.openConnection();
- httpConnection.setDoInput(true);
- httpConnection.setRequestProperty("Authorization", httpAuthCredentials);
- httpConnection.connect();
-
- InputStream is = httpConnection.getInputStream();
- BufferedInputStream bis = new BufferedInputStream(is);
- dataInStream = new DataInputStream(bis);
-
- isStreamConnected = true;
-
- } catch (IOException e) {
- isStreamConnected = false;
-
- } catch (Exception e) {
- isStreamConnected = false;
- }
-
- return isStreamConnected;
- }
-
- private void streamDisconnect() {
- try {
- if (isStreamConnected) {
- dataInStream.close();
- isStreamConnected = false;
- }
- } catch (Exception e) {
- }
- }
-
- private void doCallbacks() {
-
- while (!doEnd.get()) {
- if (newFrameAvailable.compareAndSet(true, false)) {
-
- for (CameraSmartCallback c : callbackList) {
-
- c.newCameraFrameAvailable(this.getLatestFrame(), this.getTimestamp());
- }
- } else {
-
- // Sleep for 15 millisec to give time for new frame to arrive
- try {
- Thread.sleep(15);
- } catch (InterruptedException ie) {
- }
- }
- }
-
- }
-
- private void doWork() {
-
- // parse the images that are loaded into the buffer
- while (!doEnd.get()) {
-
- BufferedImage img = parseImage();
-
- if (img != null) {
-
- timestampWriteLock.lock();
- latestImageTimestamp = new Date();
- timestampWriteLock.unlock();
-
- imageWriteLock.lock();
-
- try {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ImageIO.write(img, "jpg", baos);
- baos.flush();
- latestImage = baos.toByteArray();
- baos.close();
-
- } catch (Exception e) {
-
- }
- imageWriteLock.unlock();
-
- newFrameAvailable.set(true);
- }
-
- try {
- if (dataInStream.available() > 120000) {
- dataInStream.skip(120000);
- }
- } catch (Exception e) {
- }
- }
-
- }
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+++ /dev/null
-package iotcode.AmcrestCamera;
-
-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 CameraSmartCallback_CallbackStub implements CameraSmartCallback {
-
- private IoTRMICall rmiCall;
- private String callbackAddress;
- private int[] ports;
-
- private int objectId = 0;
-
-
- public CameraSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
- callbackAddress = _callbackAddress;
- objectId = _objectId;
- rmiCall = _rmiCall;
- ports = _ports;
- }
-
- public void newCameraFrameAvailable(byte latestFrame[], long timeStamp) {
- int methodId = 0;
- Class<?> retType = void.class;
- Class<?>[] paramCls = new Class<?>[] { byte[].class, long.class };
- Object[] paramObj = new Object[] { latestFrame, timeStamp };
- rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
- }
-
-}
+++ /dev/null
-package iotcode.AmcrestCamera;
-
-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 Camera_Skeleton implements Camera {
-
- private Camera mainObj;
- private IoTRMIObject rmiObj;
-
- private String callbackAddress;
- private static int objIdCnt = 0;
- private IoTRMICall rmiCall;
- private int[] ports;
-
- private final static int object0Id = 0; //CameraSmart
- private static Integer[] object0Permission = { 8, 7, 9, 6, 2, 1, 4, 3, 0, 10, 5 };
- private static List<Integer> set0Allowed;
-
-
- public Camera_Skeleton(Camera _mainObj, String _callbackAddress, int _port) throws Exception {
- mainObj = _mainObj;
- callbackAddress = _callbackAddress;
- rmiObj = new IoTRMIObject(_port);
- set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
- set0Allowed.add(-9998);
- ___waitRequestInvokeMethod();
- }
-
- public void init() {
- mainObj.init();
- }
-
- public void start() {
- mainObj.start();
- }
-
- public void stop() {
- mainObj.stop();
- }
-
- public byte[] getLatestFrame() {
- return mainObj.getLatestFrame();
- }
-
- public long getTimestamp() {
- return mainObj.getTimestamp();
- }
-
- public List<Resolution> getSupportedResolutions() {
- return mainObj.getSupportedResolutions();
- }
-
- public boolean setResolution(Resolution _res) {
- return mainObj.setResolution(_res);
- }
-
- public boolean setFPS(int _fps) {
- return mainObj.setFPS(_fps);
- }
-
- public int getMaxFPS() {
- return mainObj.getMaxFPS();
- }
-
- public int getMinFPS() {
- return mainObj.getMinFPS();
- }
-
- public void registerCallback(CameraSmartCallback _callbackTo) {
- mainObj.registerCallback(_callbackTo);
- }
-
- public void ___regCB() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
- ports = (int[]) paramObj[0];
- rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
- }
-
- public void ___init() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- init();
- }
-
- public void ___start() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- start();
- }
-
- public void ___stop() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- stop();
- }
-
- public void ___getLatestFrame() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getLatestFrame();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getTimestamp() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getTimestamp();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getSupportedResolutions() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- List<Resolution> retEnum = getSupportedResolutions();
- int retLen = retEnum.size();
- int[] retEnumVal = new int[retLen];
- for (int i = 0; i < retLen; i++) {
- retEnumVal[i] = retEnum.get(i).ordinal();
- }
- Object retObj = retEnumVal;
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___setResolution() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class },
- new Class<?>[] { null });
- int paramInt0[] = (int[]) paramObj[0];
- Resolution[] enumVals = Resolution.values();
- Resolution paramEnum0 = enumVals[paramInt0[0]];
- Object retObj = setResolution(paramEnum0);
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___setFPS() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- Object retObj = setFPS((int) paramObj[0]);
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getMaxFPS() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getMaxFPS();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getMinFPS() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getMinFPS();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___registerCallback() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- try {
- CameraSmartCallback stub0 = new CameraSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
- objIdCnt++;
- registerCallback(stub0);
- } catch(Exception ex) {
- ex.printStackTrace();
- throw new Error("Exception from callback object instantiation!");
- }
- }
-
- private void ___waitRequestInvokeMethod() throws IOException {
- while (true) {
- rmiObj.getMethodBytes();
- int _objectId = rmiObj.getObjectId();
- int methodId = rmiObj.getMethodId();
- if (_objectId == object0Id) {
- if (!set0Allowed.contains(methodId)) {
- throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
- }
- }
- else {
- throw new Error("Object Id: " + _objectId + " not recognized!");
- }
- switch (methodId) {
- case 0: ___init(); break;
- case 1: ___start(); break;
- case 2: ___stop(); break;
- case 3: ___getLatestFrame(); break;
- case 4: ___getTimestamp(); break;
- case 5: ___getSupportedResolutions(); break;
- case 6: ___setResolution(); break;
- case 7: ___setFPS(); break;
- case 8: ___getMaxFPS(); break;
- case 9: ___getMinFPS(); break;
- case 10: ___registerCallback(); break;
- case -9998: ___regCB(); break;
- default:
- throw new Error("Method Id " + methodId + " not recognized!");
- }
- }
- }
-
-}
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=Room
-# Stub
-INTERFACE_STUB_CLASS=RoomSmart
+++ /dev/null
-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;
- }
-}
+++ /dev/null
-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!");
- }
- }
- }
-
-}
--- /dev/null
+#ifndef _BULBCOLOR_HPP__
+#define _BULBCOLOR_HPP__
+#include <iostream>
+
+class BulbColor {
+
+ private:
+ int hue;
+ int saturation;
+ int brightness;
+ int kelvin;
+
+ public:
+
+ BulbColor(int _hue, int _saturation, int _brightness, int _kelvin) {
+
+ if ((_hue > 65535) || (_hue < 0)) {
+ cerr << "BulbColor: Invalid parameter value for _hue (0-65535)" << endl;
+ exit(1);
+ }
+
+ if ((_saturation > 65535) || (_saturation < 0)) {
+ cerr << "BulbColor: Invalid parameter value for _saturation (0-65535)" << endl;
+ exit(1);
+ }
+
+ if ((_brightness > 65535) || (_brightness < 0)) {
+ cerr << "BulbColor: Invalid parameter value for _brightness (0-65535)" << endl;
+ exit(1);
+ }
+
+ if ((_kelvin > 65535) || (_kelvin < 0)) {
+ cerr << "BulbColor: Invalid parameter value for _kelvin (0-65535)" << endl;
+ exit(1);
+ }
+
+ hue = _hue;
+ saturation = _saturation;
+ brightness = _brightness;
+ kelvin = _kelvin;
+ }
+
+
+ BulbColor(char* data) {
+ hue = ((data[1] & 0xFF) << 8);
+ hue |= (data[0] & 0xFF);
+
+ saturation = ((data[3] & 0xFF) << 8);
+ saturation |= (data[2] & 0xFF);
+
+ brightness = ((data[5] & 0xFF) << 8);
+ brightness |= (data[4] & 0xFF);
+
+ kelvin = ((data[7] & 0xFF) << 8);
+ kelvin |= (data[6] & 0xFF);
+ }
+
+
+ ~BulbColor() {
+ }
+
+
+ int getHue() {
+ return hue;
+ }
+
+
+ int getSaturation() {
+ return saturation;
+ }
+
+
+ int getBrightness() {
+ return brightness;
+ }
+
+
+ int getKelvin() {
+ return kelvin;
+ }
+};
+#endif
--- /dev/null
+#ifndef _DEVICESTATEGROUP_HPP__
+#define _DEVICESTATEGROUP_HPP__
+#include <iostream>
+#include <string>
+
+class DeviceStateGroup {
+
+ private:
+ char group[16];
+ string label;
+ int64_t updatedAt;
+
+ public:
+
+ DeviceStateGroup(char _location[16], string _label, int64_t _updatedAt) {
+
+ strcpy(group, _location);
+ label = _label;
+ updatedAt = _updatedAt;
+ }
+
+
+ ~DeviceStateGroup() {
+ }
+
+
+ char* getGroup() {
+ return group;
+ }
+
+
+ string getLabel() {
+ return label;
+ }
+
+
+ int64_t getUpdatedAt() {
+ return updatedAt;
+ }
+};
+#endif
--- /dev/null
+#ifndef _DEVICESTATEHOSTFIRMWARE_HPP__
+#define _DEVICESTATEHOSTFIRMWARE_HPP__
+#include <iostream>
+
+class DeviceStateHostFirmware {
+ // time of build in nanosecond accuracy
+ // after some tests
+ private:
+ int64_t build;
+ int64_t version; // firmware version
+
+ public:
+
+ DeviceStateHostFirmware(int64_t _build, int64_t _version) {
+
+ build = _build;
+ version = _version;
+ }
+
+
+ ~DeviceStateHostFirmware() {
+ }
+
+
+ int64_t getBuild() {
+ return build;
+ }
+
+
+ int64_t getVersion() {
+ return version;
+ }
+
+};
+#endif
--- /dev/null
+#ifndef _DEVICESTATEHOSTINFO_HPP__
+#define _DEVICESTATEHOSTINFO_HPP__
+#include <iostream>
+
+class DeviceStateHostInfo {
+ private:
+ int64_t signal;
+ int64_t tx;
+ int64_t rx;
+
+ public:
+
+ DeviceStateHostInfo(int64_t _signal, int64_t _tx, int64_t _rx) {
+
+ signal = _signal;
+ tx = _tx;
+ rx = _rx;
+ }
+
+
+ ~DeviceStateHostInfo() {
+ }
+
+
+ int64_t getSignal() {
+ return signal;
+ }
+
+
+ int64_t getTx() {
+ return tx;
+ }
+
+
+ int64_t getRx() {
+ return rx;
+ }
+};
+#endif
--- /dev/null
+#ifndef _DEVICESTATEINFO_HPP__
+#define _DEVICESTATEINFO_HPP__
+#include <iostream>
+
+class DeviceStateInfo {
+ private:
+ int64_t time;
+ int64_t upTime;
+ int64_t downTime;
+
+ public:
+
+ DeviceStateInfo(int64_t _time, int64_t _upTime, int64_t _downTime) {
+
+ time = _time;
+ upTime = _upTime;
+ downTime = _downTime;
+ }
+
+
+ ~DeviceStateInfo() {
+ }
+
+
+ int64_t getTime() {
+ return time;
+ }
+
+
+ int64_t getUpTime() {
+ return upTime;
+ }
+
+
+ int64_t getDownTime() {
+ return downTime;
+ }
+};
+#endif
--- /dev/null
+#ifndef _DEVICESTATELOCATION_HPP__
+#define _DEVICESTATELOCATION_HPP__
+#include <iostream>
+#include <string>
+
+class DeviceStateLocation {
+ private:
+ char location[16];
+ string label;
+ int64_t updatedAt;
+
+ public:
+
+ DeviceStateLocation(char _location[16], string _label, long _updatedAt) {
+
+ strcpy(location, _location);
+ label = _label;
+ updatedAt = _updatedAt;
+ }
+
+
+ ~DeviceStateLocation() {
+ }
+
+
+ char* getLocation() {
+ return location;
+ }
+
+
+ string getLabel() {
+ return label;
+ }
+
+
+ int64_t getUpdatedAt() {
+ return updatedAt;
+ }
+};
+#endif
--- /dev/null
+#ifndef _DEVICESTATELOCATION_HPP__
+#define _DEVICESTATELOCATION_HPP__
+#include <iostream>
+#include <string>
+
+class DeviceStateLocation {
+ private:
+ char location[16];
+ string label;
+ int64_t updatedAt;
+
+ public:
+
+ DeviceStateLocation(char _location[16], String _label, long _updatedAt) {
+
+ strcpy(location, _location);
+ label = _label;
+ updatedAt = _updatedAt;
+ }
+
+
+ ~DeviceStateLocation() {
+ }
+
+
+ char* getLocation() {
+ return location;
+ }
+
+
+ string getLabel() {
+ return label;
+ }
+
+
+ int64_t getUpdatedAt() {
+ return updatedAt;
+ }
+};
+#endif
--- /dev/null
+#ifndef _DEVICESTATESERVICE_HPP__
+#define _DEVICESTATESERVICE_HPP__
+#include <iostream>
+
+class DeviceStateService {
+ private:
+ int service;
+ int64_t port;
+
+ public:
+
+ DeviceStateService(int _service, long _port) {
+
+ service = _service;
+ port = _port;
+ }
+
+
+ ~DeviceStateService() {
+ }
+
+
+ int getService() {
+ return service;
+ }
+
+
+ int64_t getPort() {
+ return port;
+ }
+};
+#endif
--- /dev/null
+#ifndef _DEVICESTATEVERSION_HPP__
+#define _DEVICESTATEVERSION_HPP__
+#include <iostream>
+
+class DeviceStateVersion {
+ private:
+ int64_t vender;
+ int64_t product;
+ int64_t version;
+
+ public:
+
+ DeviceStateVersion(int64_t _vender, int64_t _product, int64_t _version) {
+
+ vender = _vender;
+ product = _product;
+ version = _version;
+ }
+
+
+ ~DeviceStateVersion() {
+ }
+
+
+ int64_t getVender() {
+ return vender;
+ }
+
+
+ int64_t getProduct() {
+ return product;
+ }
+
+
+ int64_t getVersion() {
+ return version;
+ }
+};
+#endif
--- /dev/null
+#ifndef _DEVICESTATEWIFIFIRMWARE_HPP__
+#define _DEVICESTATEWIFIFIRMWARE_HPP__
+#include <iostream>
+
+class DeviceStateWifiFirmware {
+ // time of build in nanosecond accuracy
+ // after some tests
+ private:
+ int64_t build;
+ int64_t version; // firmware version
+
+ public:
+
+ DeviceStateWifiFirmware(int64_t _build, int64_t _version) {
+
+ build = _build;
+ version = _version;
+ }
+
+
+ ~DeviceStateWifiFirmware() {
+ }
+
+
+ int64_t getBuild() {
+ return build;
+ }
+
+
+ int64_t getVersion() {
+ return version;
+ }
+};
+#endif
--- /dev/null
+#ifndef _DEVICESTATEWIFIINFO_HPP__
+#define _DEVICESTATEWIFIINFO_HPP__
+#include <iostream>
+
+class DeviceStateWifiInfo {
+ private:
+ int64_t signal;
+ int64_t tx;
+ int64_t rx;
+
+ public:
+
+ DeviceStateWifiInfo(int64_t _signal, int64_t _tx, int64_t _rx) {
+
+ signal = _signal;
+ tx = _tx;
+ rx = _rx;
+ }
+
+
+ ~DeviceStateWifiInfo() {
+ }
+
+
+ int64_t getSignal() {
+ return signal;
+ }
+
+
+ int64_t getTx() {
+ return tx;
+ }
+
+
+ int64_t getRx() {
+ return rx;
+ }
+};
+#endif
--- /dev/null
+#ifndef _LIFXHEADER_HPP__
+#define _LIFXHEADER_HPP__
+#include <iostream>
+
+class LifxHeader {
+
+ private:
+ // Frame variables
+ int size;
+ int origin;
+ bool tagged;
+ bool addressable;
+ int protocol;
+ int64_t source;
+
+ // Frame address variables
+ char macAddress[8];
+ bool ack_required;
+ bool res_required;
+ int sequence;
+
+ // Protocol header
+ int type;
+
+ public:
+
+ LifxHeader() {
+ origin = 0;
+ addressable = true;
+ protocol =1024;
+ }
+
+
+ ~LifxHeader() {
+ }
+
+
+ void setSize(int _size) {
+ if (_size < 0) {
+ cerr << "Header: size cannot be less than 0" << endl;
+ exit(1);
+ } else if (_size > 65535) {
+ cerr << "Header: size too large" << endl;
+ exit(1);
+ }
+ size = _size;
+ }
+
+
+ void setOrigin(int _origin) {
+ if (_origin < 0) {
+ cerr << "Header: origin cannot be less than 0" << endl;
+ exit(1);
+ } else if (_origin > 3) {
+ cerr << "Header: origin too large" << endl;
+ exit(1);
+ }
+ origin = _origin;
+ }
+
+
+ void setTagged(bool _tagged) {
+ tagged = _tagged;
+ }
+
+
+ void setAddressable(bool _addressable) {
+ addressable = _addressable;
+ }
+
+
+ void setProtocol(int _protocol) {
+ if (_protocol < 0) {
+ cerr << "Header: protocol cannot be less than 0" << endl;
+ exit(1);
+ } else if (_protocol > 4095) {
+ cerr << "Header: protocol too large" << endl;
+ exit(1);
+ }
+ protocol = _protocol;
+ }
+
+
+ void setSource(int64_t _source) {
+ if (_source < 0) {
+ cerr << "Header: source cannot be less than 0" << endl;
+ exit(1);
+ } else if (_source > 4294967295) {
+ cerr << "Header: source too large" << endl;
+ exit(1);
+ }
+ source = _source;
+ }
+
+
+ void setSequence(int _sequence) {
+ if (_sequence < 0) {
+ cerr << "Header: sequence cannot be less than 0" << endl;
+ exit(1);
+ } else if (_sequence > 255) {
+ cerr << "Header: sequence too large" << endl;
+ exit(1);
+ }
+ sequence = _sequence;
+ }
+
+
+ void setType(int _type) {
+ if (_type < 0) {
+ cerr << "Header: type cannot be less than 0" << endl;
+ exit(1);
+ } else if (_type > 65535) {
+ cerr << "Header: type too large" << endl;
+ exit(1);
+ }
+ type = _type;
+ }
+
+
+ void setAck_required(bool _ack_required) {
+ ack_required = _ack_required;
+ }
+
+
+ void setRes_required(bool _res_required) {
+ res_required = _res_required;
+ }
+
+
+ void setMacAddress(char _macAddress[8]) {
+ strcpy(macAddress, _macAddress);
+ }
+
+
+ int getSize() {
+ return size;
+ }
+
+
+ int getOrigin() {
+ return origin;
+ }
+
+
+ bool getTagged() {
+ return tagged;
+ }
+
+
+ bool getAddressable() {
+ return addressable;
+ }
+
+
+ int getProtocol() {
+ return protocol;
+ }
+
+
+ int64_t getSource() {
+ return source;
+ }
+
+
+ int64_t getSequence() {
+ return sequence;
+ }
+
+
+ int getType() {
+ return type;
+ }
+
+
+ char* getHeaderBytes(char headerBytes[36]) {
+
+ //char headerBytes[36];
+ headerBytes[0] = (char)(size & 0xFF);
+ headerBytes[1] = (char)((size >> 8) & 0xFF);
+
+
+ headerBytes[2] = (char)(protocol & 0xFF);
+ headerBytes[3] = (char)((protocol >> 8) & 0x0F);
+
+ headerBytes[3] |= (char)((origin & 0x03) << 6);
+
+ if (tagged) {
+ headerBytes[3] |= (1 << 5);
+ }
+
+ if (addressable) {
+ headerBytes[3] |= (1 << 4);
+ }
+
+ headerBytes[4] = (char)((source >> 0) & 0xFF);
+ headerBytes[5] = (char)((source >> 8) & 0xFF);
+ headerBytes[6] = (char)((source >> 16) & 0xFF);
+ headerBytes[7] = (char)((source >> 24) & 0xFF);
+
+ // fix in a bit
+ headerBytes[8] = macAddress[0];
+ headerBytes[9] = macAddress[1];
+ headerBytes[10] = macAddress[2];
+ headerBytes[11] = macAddress[3];
+ headerBytes[12] = macAddress[4];
+ headerBytes[13] = macAddress[5];
+ headerBytes[14] = macAddress[6];
+ headerBytes[15] = macAddress[7];
+
+ // Reserved and set to 0
+ headerBytes[16] = 0;
+ headerBytes[17] = 0;
+ headerBytes[18] = 0;
+ headerBytes[19] = 0;
+ headerBytes[20] = 0;
+ headerBytes[21] = 0;
+
+ if (ack_required) {
+ headerBytes[22] = (1 << 1);
+ }
+
+ if (res_required) {
+ headerBytes[22] |= (1);
+ }
+
+ headerBytes[23] = (char)(sequence & 0xFF);
+
+ // Reserved and set to 0
+ headerBytes[24] = 0;
+ headerBytes[25] = 0;
+ headerBytes[26] = 0;
+ headerBytes[27] = 0;
+ headerBytes[28] = 0;
+ headerBytes[29] = 0;
+ headerBytes[30] = 0;
+ headerBytes[31] = 0;
+
+ headerBytes[32] = (char)((type >> 0) & 0xFF);
+ headerBytes[33] = (char)((type >> 8) & 0xFF);
+
+ // Reserved and set to 0
+ headerBytes[34] = 0;
+ headerBytes[35] = 0;
+
+ return headerBytes;
+ }
+
+
+ void setFromBytes(char dataBytes[36]) {
+
+ size = dataBytes[0] & 0xFF;
+ size |= ((dataBytes[1] & 0xFF) << 8);
+ size &= 0xFFFF;
+
+ origin = (dataBytes[3] >> 6) & 0x03;
+ tagged = ((dataBytes[3] >> 5) & 0x01) == 1;
+ addressable = ((dataBytes[3] >> 4) & 0x01) == 1;
+
+
+ protocol = (dataBytes[3] & 0x0F) << 8;
+ protocol |= dataBytes[2];
+ protocol &= 0x0FFF;
+
+ source = (dataBytes[7] & 0xFFl) << 24;
+ source |= ((dataBytes[6] & 0xFFl) << 16);
+ source |= ((dataBytes[5] & 0xFFl) << 8);
+ source |= ((dataBytes[4] & 0xFFl));
+
+ macAddress[0] = dataBytes[8];
+ macAddress[1] = dataBytes[9];
+ macAddress[2] = dataBytes[10];
+ macAddress[3] = dataBytes[11];
+ macAddress[4] = dataBytes[12];
+ macAddress[5] = dataBytes[13];
+ macAddress[6] = dataBytes[14];
+ macAddress[7] = dataBytes[15];
+
+ ack_required = (dataBytes[22] & 0x02) == 0x02;
+ res_required = (dataBytes[22] & 0x01) == 0x01;
+
+ sequence = (dataBytes[23] & 0xFF);
+
+ type = ((dataBytes[33] & 0xFF) << 8);
+ type |= (dataBytes[32] & 0xFF);
+ }
+};
+#endif
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=LightBulb
+# Stub
+#INTERFACE_STUB_CLASS=LightBulbTest
+INTERFACE_STUB_CLASS=LightBulbSmart
+
--- /dev/null
+#include <iostream>
+#include <string>
+#include "LifxLightBulb.hpp"
+#include "IoTSet.hpp"
+#include "IoTDeviceAddress.hpp"
+
+using namespace std;
+
+int main(int argc, char *argv[])
+{
+ string macAddress = "D073D5128E300000";
+ string devIPAddress = "192.168.2.126";
+ IoTDeviceAddress devAddress(devIPAddress, 12345, 56700, false, false);
+ unordered_set<IoTDeviceAddress> myset = { devAddress };
+
+ IoTSet<IoTDeviceAddress> setDevAddress(myset);
+ LifxLightBulb *llb = new LifxLightBulb(setDevAddress, macAddress);
+ llb->init();
+
+ cout << "Generated LifxLightBulb object!" << endl;
+
+ delete llb;
+
+ return 0;
+}
--- /dev/null
+#ifndef _LIFXLIGHTBULB_HPP__
+#define _LIFXLIGHTBULB_HPP__
+#include <iostream>
+#include <atomic>
+#include <mutex>
+#include <thread>
+#include <chrono>
+
+#include <string.h>
+#include <time.h>
+
+#include "LightBulb.hpp"
+#include "Socket.hpp"
+#include "IoTRMIUtil.hpp"
+#include "IoTSet.hpp"
+#include "IoTUDP.hpp"
+#include "IoTDeviceAddress.hpp"
+#include "Iterator.hpp"
+
+// Helper classes for LifxLightBulb
+#include "LifxHeader.hpp"
+#include "BulbColor.hpp"
+#include "DeviceStateGroup.hpp"
+#include "DeviceStateHostFirmware.hpp"
+#include "DeviceStateHostInfo.hpp"
+#include "DeviceStateInfo.hpp"
+#include "DeviceStateLocation.hpp"
+#include "DeviceStateService.hpp"
+#include "DeviceStateVersion.hpp"
+#include "DeviceStateWifiFirmware.hpp"
+#include "DeviceStateWifiInfo.hpp"
+#include "LightState.hpp"
+
+
+using namespace std;
+
+// Driver LifxLightBulb
+// Implemented based on LightBulb virtual class (interface)
+
+//std::atomic
+std::atomic<bool> didAlreadyInit(false);
+std::atomic<bool> didGetBulbVersion(false);
+
+class LifxLightBulb //: public LightBulb
+{
+ private:
+ // Constants
+ const static int64_t GET_BULB_VERSION_RESEND_WAIT_SECONDS = 10;
+
+ // Variables
+ IoTUDP *communicationSocket;
+ char bulbMacAddress[8];
+ //TODO:
+ //static Semaphore socketMutex = new Semaphore(1);
+ bool sendSocketFlag = false;
+ int64_t lastSentGetBulbVersionRequest = 0; // time last request sent
+
+ // Current Bulb Values
+ int currentHue = 0;
+ int currentSaturation = 0;
+ int currentBrightness = 65535;
+ int currentTemperature = 9000;
+ bool bulbIsOn = false;
+
+ //std::atomic
+ atomic<bool> didAlreadyInit;
+ atomic<bool> didGetBulbVersion;
+
+ // Mutex locks
+ mutex socketMutex;
+ mutex settingBulbColorMutex;
+ mutex settingBulbTemperatureMutex;
+ mutex bulbStateMutex;
+
+ // color and temperature ranges for the bulbs
+ int hueLowerBound = 0;
+ int hueUpperBound = 0;
+ int saturationLowerBound = 0;
+ int saturationUpperBound = 0;
+ int brightnessLowerBound = 0;
+ int brightnessUpperBound = 0;
+ int temperatureLowerBound = 2500;
+ int temperatureUpperBound = 9000;
+
+ // Check if a state change was requested, used to poll the bulb for if the bulb did
+ // preform the requested state change
+ bool stateDidChange = false;
+
+ // Device address
+ IoTSet<IoTDeviceAddress> lb_addresses;
+
+ public:
+
+ // Constructor
+ LifxLightBulb() {
+ // LB1 macAddress: d0:73:d5:12:8e:30
+ // LB1 macAddress: d0:73:d5:02:41:da
+ string macAddress = "D073D5128E300000"; // bulbMacAddress: [-48, 115, -43, 18, -114, 48, 0, 0]
+ //string macAddress = "D073D50241DA0000"; // bulbMacAddress: [-48, 115, -43, 2, 65, -38, 0, 0]
+ /*bulbMacAddress[0] = 0xD0;
+ bulbMacAddress[1] = 0x73;
+ bulbMacAddress[2] = 0xD5;
+ bulbMacAddress[3] = 0x02;
+ bulbMacAddress[4] = 0x41;
+ bulbMacAddress[5] = 0xDA;
+ bulbMacAddress[6] = 0x00;
+ bulbMacAddress[7] = 0x00;*/
+
+ char tmpMacAddress[16];
+ strcpy(tmpMacAddress, macAddress.c_str());
+ //test[0] = (char) strtol(strTest.c_str(), NULL, 16);
+ for(int i=0; i<16; i=i+2) {
+ // Take 2 digits and then convert
+ char tmpMacByte[2];
+ tmpMacByte[0] = tmpMacAddress[i];
+ tmpMacByte[1] = tmpMacAddress[i+1];
+ bulbMacAddress[i/2] = (char) strtol(tmpMacByte, NULL, 16);
+ }
+ //IoTRMIUtil::printBytes(bulbMacAddress, 8, false);
+ }
+
+
+ LifxLightBulb(IoTSet<IoTDeviceAddress> _devAddress, string macAddress) {
+
+ // Initialize macAddress
+ char tmpMacAddress[16];
+ strcpy(tmpMacAddress, macAddress.c_str());
+ //test[0] = (char) strtol(strTest.c_str(), NULL, 16);
+ for(int i=0; i<16; i=i+2) {
+ // Take 2 digits and then convert
+ char tmpMacByte[2];
+ tmpMacByte[0] = tmpMacAddress[i];
+ tmpMacByte[1] = tmpMacAddress[i+1];
+ bulbMacAddress[i/2] = (char) strtol(tmpMacByte, NULL, 16);
+ }
+ cout << "MAC address is set. Value: ";
+ IoTRMIUtil::printBytes(bulbMacAddress, 8, false);
+
+ // Initialize device address
+ lb_addresses = _devAddress;
+ cout << "Device address is set! " << endl;
+ }
+
+
+ ~LifxLightBulb() {
+
+ // Clean up
+ if (communicationSocket != NULL) {
+
+ delete communicationSocket;
+ communicationSocket = NULL;
+ }
+ }
+
+
+ // Initialize the lightbulb
+ void init() {
+
+ if (didAlreadyInit.exchange(true))
+ return;
+
+ unordered_set<IoTDeviceAddress>::const_iterator itr = lb_addresses.begin();
+ IoTDeviceAddress deviceAddress = *itr;
+ cout << "Address: " << deviceAddress.getAddress() << endl;
+
+ // Create IoTUDP socket
+ communicationSocket = new IoTUDP(deviceAddress);
+
+ // Launch the worker function in a separate thread.
+ thread th1 (&LifxLightBulb::workerFunction, this);
+ th1.join();
+ }
+
+
+ void turnOff() {
+
+ lock_guard<mutex> guard(bulbStateMutex);
+ bulbIsOn = false;
+ sendSetLightPowerPacket(0, 0);
+ stateDidChange = true;
+ cout << "Turning off lightbulb!" << endl;
+ }
+
+
+ void turnOn() {
+
+ lock_guard<mutex> guard(bulbStateMutex);
+ bulbIsOn = true;
+ sendSetLightPowerPacket(65535, 0);
+ stateDidChange = true;
+ }
+
+
+ double getHue() {
+ double tmp = 0;
+ settingBulbColorMutex.lock();
+ tmp = ((double)currentHue / 65535.0) * 360.0;
+ settingBulbColorMutex.unlock();
+
+ return tmp;
+ }
+
+
+ double getSaturation() {
+ double tmp = 0;
+ settingBulbColorMutex.lock();
+ tmp = ((double)currentSaturation / 65535.0) * 360.0;
+ settingBulbColorMutex.unlock();
+
+ return tmp;
+ }
+
+
+ double getBrightness() {
+ double tmp = 0;
+ settingBulbColorMutex.lock();
+ tmp = ((double)currentBrightness / 65535.0) * 360.0;
+ settingBulbColorMutex.unlock();
+
+ return tmp;
+ }
+
+
+ int getTemperature() {
+
+ int tmp = 0;
+ settingBulbTemperatureMutex.lock();
+ tmp = currentTemperature;
+ settingBulbTemperatureMutex.unlock();
+
+ return tmp;
+ }
+
+
+ double getHueRangeLowerBound() {
+ if (!didGetBulbVersion) {
+ return -1;
+ }
+ return ((double)hueLowerBound / 65535.0) * 360.0;
+ }
+
+
+ double getHueRangeUpperBound() {
+ if (!didGetBulbVersion) {
+ return -1;
+ }
+ return ((double)hueUpperBound / 65535.0) * 360.0;
+ }
+
+
+ double getSaturationRangeLowerBound() {
+ if (!didGetBulbVersion) {
+ return -1;
+ }
+ return ((double)saturationLowerBound / 65535.0) * 100.0;
+ }
+
+
+ double getSaturationRangeUpperBound() {
+ if (!didGetBulbVersion) {
+ return -1;
+ }
+ return ((double)saturationUpperBound / 65535.0) * 100.0;
+ }
+
+
+ double getBrightnessRangeLowerBound() {
+ if (!didGetBulbVersion) {
+ return -1;
+ }
+ return ((double)brightnessLowerBound / 65535.0) * 100.0;
+ }
+
+
+ double getBrightnessRangeUpperBound() {
+ if (!didGetBulbVersion) {
+ return -1;
+ }
+ return ((double)brightnessUpperBound / 65535.0) * 100.0;
+ }
+
+
+ int getTemperatureRangeLowerBound() {
+ if (!didGetBulbVersion) {
+ return -1;
+ }
+ return temperatureLowerBound;
+ }
+
+
+ int getTemperatureRangeUpperBound() {
+ if (!didGetBulbVersion) {
+ return -1;
+ }
+ return temperatureUpperBound;
+ }
+
+
+ void setTemperature(int _temperature) {
+
+ settingBulbTemperatureMutex.lock();
+
+ BulbColor* newColor = new BulbColor(currentHue, currentSaturation, currentBrightness, _temperature);
+ sendSetLightColorPacket(newColor, 250);
+
+ currentTemperature = _temperature;
+ stateDidChange = true;
+
+ settingBulbTemperatureMutex.unlock();
+ }
+
+
+ void setColor(double _hue, double _saturation, double _brightness) {
+
+ settingBulbColorMutex.lock();
+
+ _hue /= 360.0;
+ _saturation /= 100.0;
+ _brightness /= 100.0;
+
+
+ int newHue = (int)(_hue * 65535.0);
+ int newSaturation = (int)(_saturation * 65535.0);
+ int newBrightness = (int)(_brightness * 65535.0);
+
+ BulbColor* newColor = new BulbColor(newHue, newSaturation, newBrightness, currentTemperature);
+ sendSetLightColorPacket(newColor, 250);
+
+ currentHue = newHue;
+ currentSaturation = newSaturation;
+ currentBrightness = newBrightness;
+ stateDidChange = true;
+
+ settingBulbColorMutex.unlock();
+ }
+
+
+ bool getState() {
+
+ bool tmp = false;
+
+ bulbStateMutex.lock();
+ tmp = bulbIsOn;
+ bulbStateMutex.unlock();
+
+ return tmp;
+ }
+
+ private:
+ // Private functions
+
+ // Communication helpers
+ void receivedPacket(char* packetData) {
+
+ char headerBytes[36];
+ for (int i = 0; i < 36; i++) {
+ headerBytes[i] = packetData[i];
+ }
+
+ LifxHeader recHeader;
+ recHeader.setFromBytes(headerBytes);
+
+ // load the payload bytes (strip away the header)
+ char payloadBytes[recHeader.getSize()];
+ for (int i = 36; i < recHeader.getSize(); i++) {
+ payloadBytes[i - 36] = packetData[i];
+ }
+
+ int type = recHeader.getType();
+ cout << "Received: " << type;
+
+ DeviceStateService* dat = NULL;
+ switch (type) {
+
+ case 3:
+ dat = parseDeviceStateServiceMessage(payloadBytes);
+ cout << "Service: " << dat->getService();
+ cout << "Port : " << dat->getPort();
+ // Avoid memory leak - delete this object
+ delete dat;
+ break;
+
+ case 33:
+ handleStateVersionMessageReceived(payloadBytes);
+ break;
+
+ case 35:
+ parseDeviceStateInfoMessage(payloadBytes);
+ break;
+
+
+ case 107:
+ handleLightStateMessageReceived(payloadBytes);
+ break;
+
+ default:
+ cout << "unknown packet Type" << endl;
+ }
+
+ }
+
+
+ void sendPacket(char* packetData, int len) {
+ //cout << "sendPacket: About to send" << endl;
+ lock_guard<mutex> guard(socketMutex);
+ sendSocketFlag = true;
+ communicationSocket->sendData(packetData, len);
+ sendSocketFlag = false;
+ }
+
+
+ // Worker function which runs the while loop for receiving data from the bulb.
+ // Is blocking.
+ void workerFunction() {
+ LifxHeader h;
+ // Need timeout on receives since we are not sure if a packet will be available
+ // for processing so don't block waiting
+ // TODO: Check if we can do this here!
+ //communicationSocket.setSoTimeout(50);
+
+ turnOff();
+
+ while (true) {
+
+ // Check if we got the bulb version yet
+ // could have requested it but message could have gotten lost (UDP)
+ if (!didGetBulbVersion) {
+ int64_t currentTime = (int64_t) time(NULL);
+ if ((currentTime - lastSentGetBulbVersionRequest) > GET_BULB_VERSION_RESEND_WAIT_SECONDS) {
+ // Get the bulb version so we know what type of bulb this is.
+ sendGetVersionPacket();
+ lastSentGetBulbVersionRequest = currentTime;
+ }
+ }
+
+ // Communication resource is busy so try again later
+ if (sendSocketFlag) {
+ continue;
+ }
+
+ /*socketMutex.lock();
+
+ char dat[1024];
+ dat = communicationSocket.receiveData(1024);
+
+ // Never forget to release!
+ socketMutex.unlock();
+
+ // A packed arrived
+ if (dat != null) {
+ receivedPacket(dat);
+ }
+
+ // If a state change occurred then request the bulb state to ensure that the
+ // bulb did indeed change its state to the correct state
+ if (stateDidChange) {
+ sendGetLightStatePacket();
+ }
+
+ // Wait a bit as to not tie up system resources
+ this_thread::sleep_for (chrono::milliseconds(100));
+ } catch (Exception e) {
+
+ }*/
+
+
+ }
+ }
+
+
+ // Sending
+ // Device Messages
+ void sendGetServicePacket() {
+ LifxHeader header;
+ header.setSize(36);
+ header.setTagged(true);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(0); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(2);
+
+ char dataBytes[36];
+ header.getHeaderBytes(dataBytes);
+
+ sendPacket(dataBytes, 36);
+ }
+
+
+ void sendGetHostInfoPacket() {
+ LifxHeader header;
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(12);
+
+ char dataBytes[36];
+ header.getHeaderBytes(dataBytes);
+
+ sendPacket(dataBytes, 36);
+ }
+
+
+ void sendGetHostFirmwarePacket() {
+ LifxHeader header;
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(14);
+
+ char dataBytes[36];
+ header.getHeaderBytes(dataBytes);
+
+ sendPacket(dataBytes, 36);
+ }
+
+
+ void sendGetWifiInfoPacket() {
+ LifxHeader header;
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(16);
+
+ char dataBytes[36];
+ header.getHeaderBytes(dataBytes);
+
+ sendPacket(dataBytes, 36);
+ }
+
+
+ void sendGetWifiFirmwarePacket() {
+ LifxHeader header;
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(18);
+
+ char dataBytes[36];
+ header.getHeaderBytes(dataBytes);
+
+ sendPacket(dataBytes, 36);
+ }
+
+
+ void sendGetPowerPacket() {
+ LifxHeader header;
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(20);
+
+ char dataBytes[36];
+ header.getHeaderBytes(dataBytes);
+
+ sendPacket(dataBytes, 36);
+ }
+
+
+ void sendSetPowerPacket(int level) {
+ // Currently only 0 and 65535 are supported
+ // This is a fix for now
+ if ((level != 65535) && (level != 0)) {
+ cerr << "Invalid parameter values" << endl;
+ exit(1);
+ }
+
+ if ((level > 65535) || (level < 0)) {
+ cerr << "Invalid parameter values" << endl;
+ exit(1);
+ }
+
+ char packetBytes[38];
+
+ LifxHeader header;
+ header.setSize(38);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(21);
+ char headerBytes[36];
+ header.getHeaderBytes(headerBytes);
+
+ for (int i = 0; i < 36; i++) {
+ packetBytes[i] = headerBytes[i];
+ }
+
+ packetBytes[36] = (char)(level & 0xFF);
+ packetBytes[37] = (char)((level >> 8) & 0xFF);
+
+ sendPacket(packetBytes, 38);
+ }
+
+
+ void sendGetLabelPacket() {
+ LifxHeader header;
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(23);
+
+ char dataBytes[36];
+ header.getHeaderBytes(dataBytes);
+
+ sendPacket(dataBytes, 36);
+ }
+
+
+ void sendSetLabelPacket(string label) {
+ // Currently only 0 and 65535 are supported
+ // This is a fix for now
+ if (label.length() != 32) {
+ cerr << "Invalid parameter values, label must be 32 bytes long" << endl;
+ exit(1);
+ }
+
+ char packetBytes[68];
+
+ LifxHeader header;
+ header.setSize(68);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(24);
+ char headerBytes[36];
+ header.getHeaderBytes(headerBytes);
+
+ for (int i = 0; i < 36; i++) {
+ packetBytes[i] = headerBytes[i];
+ }
+
+ for (int i = 0; i < 32; i++) {
+ packetBytes[i + 36] = label.c_str()[i];
+ }
+
+ sendPacket(packetBytes, 68);
+ }
+
+
+ void sendGetVersionPacket() {
+ LifxHeader header;
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(32);
+
+ char dataBytes[36];
+ header.getHeaderBytes(dataBytes);
+
+ sendPacket(dataBytes, 36);
+ }
+
+
+ void sendGetInfoPacket() {
+ LifxHeader header;
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(34);
+
+ char dataBytes[36];
+ header.getHeaderBytes(dataBytes);
+
+ sendPacket(dataBytes, 36);
+ }
+
+
+ void sendGetLocationPacket() {
+ LifxHeader header;
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(34);
+
+ char dataBytes[36];
+ header.getHeaderBytes(dataBytes);
+
+ sendPacket(dataBytes, 36);
+ }
+
+
+ void sendGetGroupPacket() {
+ LifxHeader header;
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(51);
+
+ char dataBytes[36];
+ header.getHeaderBytes(dataBytes);
+
+ sendPacket(dataBytes, 36);
+ }
+
+
+ // Sending
+ // Light Messages
+ void sendGetLightStatePacket() {
+ LifxHeader header;
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(101);
+
+ char dataBytes[36];
+ header.getHeaderBytes(dataBytes);
+
+ sendPacket(dataBytes, 36);
+ }
+
+
+ void sendSetLightColorPacket(BulbColor* bulbColor, long duration) {
+
+ if ((duration > 4294967295l) || (duration < 0)) {
+ cerr << "Invalid parameter value, duration out of range (0 - 4294967295)" << endl;
+ exit(1);
+ }
+
+ char packetBytes[49];
+
+ LifxHeader header;
+ header.setSize(49);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(102);
+ char headerBytes[36];
+ header.getHeaderBytes(headerBytes);
+
+ for (int i = 0; i < 36; i++) {
+ packetBytes[i] = headerBytes[i];
+ }
+
+ // 1 reserved packet
+ packetBytes[37] = (char)(bulbColor->getHue() & 0xFF);
+ packetBytes[38] = (char)((bulbColor->getHue() >> 8) & 0xFF);
+
+ packetBytes[39] = (char)(bulbColor->getSaturation() & 0xFF);
+ packetBytes[40] = (char)((bulbColor->getSaturation() >> 8) & 0xFF);
+
+ packetBytes[41] = (char)(bulbColor->getBrightness() & 0xFF);
+ packetBytes[42] = (char)((bulbColor->getBrightness() >> 8) & 0xFF);
+
+ packetBytes[43] = (char)(bulbColor->getKelvin() & 0xFF);
+ packetBytes[44] = (char)((bulbColor->getKelvin() >> 8) & 0xFF);
+
+ packetBytes[45] = (char)((duration >> 0) & 0xFF);
+ packetBytes[46] = (char)((duration >> 8) & 0xFF);
+ packetBytes[47] = (char)((duration >> 16) & 0xFF);
+ packetBytes[48] = (char)((duration >> 24) & 0xFF);
+
+ sendPacket(packetBytes, 49);
+ // Avoid memory leak - delete object
+ delete bulbColor;
+ }
+
+
+ void sendGetLightPowerPacket() {
+ LifxHeader header;
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(116);
+
+ char dataBytes[36];
+ header.getHeaderBytes(dataBytes);
+
+ sendPacket(dataBytes, 36);
+ }
+
+
+ void sendSetLightPowerPacket(int level, long duration) {
+
+ if ((level > 65535) || (duration > 4294967295l)
+ || (level < 0) || (duration < 0)) {
+ cerr << "Invalid parameter values" << endl;
+ exit(1);
+ }
+
+ char packetBytes[42];
+
+
+ LifxHeader header;
+ header.setSize(42);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(117);
+ char headerBytes[36];
+ header.getHeaderBytes(headerBytes);
+
+ for (int i = 0; i < 36; i++) {
+ packetBytes[i] = headerBytes[i];
+ }
+
+ packetBytes[36] = (char)(level & 0xFF);
+ packetBytes[37] = (char)((level >> 8) & 0xFF);
+
+ packetBytes[38] = (char)((duration >> 0) & 0xFF);
+ packetBytes[39] = (char)((duration >> 8) & 0xFF);
+ packetBytes[40] = (char)((duration >> 16) & 0xFF);
+ packetBytes[41] = (char)((duration >> 24) & 0xFF);
+
+ sendPacket(packetBytes, 42);
+ }
+
+
+ void sendEchoRequestPacket(char data[64]) {
+
+ char packetBytes[100];
+
+ LifxHeader header;
+ header.setSize(100);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(58);
+ char headerBytes[36];
+ header.getHeaderBytes(headerBytes);
+
+ for (int i = 0; i < 36; i++) {
+ packetBytes[i] = headerBytes[i];
+ }
+
+ for (int i = 0; i < 64; i++) {
+ packetBytes[i + 36] = data[i];
+ }
+
+ sendPacket(packetBytes, 100);
+ }
+
+
+ // Receiving
+ // Device Messages
+ DeviceStateService* parseDeviceStateServiceMessage(char* payloadData) {
+ int service = payloadData[0];
+ int64_t port = ((payloadData[3] & 0xFF) << 24);
+ port |= ((payloadData[2] & 0xFF) << 16);
+ port |= ((payloadData[1] & 0xFF) << 8);
+ port |= (payloadData[0] & 0xFF);
+
+ return new DeviceStateService(service, port);
+ }
+
+
+ DeviceStateHostInfo* parseDeviceStateHostInfoMessage(char* payloadData) {
+ long signal = ((payloadData[3] & 0xFF) << 24);
+ signal |= ((payloadData[2] & 0xFF) << 16);
+ signal |= ((payloadData[1] & 0xFF) << 8);
+ signal |= (payloadData[0] & 0xFF);
+
+ long tx = ((payloadData[7] & 0xFF) << 24);
+ tx |= ((payloadData[6] & 0xFF) << 16);
+ tx |= ((payloadData[5] & 0xFF) << 8);
+ tx |= (payloadData[4] & 0xFF);
+
+ long rx = ((payloadData[11] & 0xFF) << 24);
+ rx |= ((payloadData[10] & 0xFF) << 16);
+ rx |= ((payloadData[9] & 0xFF) << 8);
+ rx |= (payloadData[8] & 0xFF);
+
+ return new DeviceStateHostInfo(signal, tx, rx);
+ }
+
+
+ DeviceStateHostFirmware* parseDeviceStateHostFirmwareMessage(char* payloadData) {
+ long build = 0;
+ for (int i = 0; i < 8; i++) {
+ build += ((int64_t) payloadData[i] & 0xffL) << (8 * i);
+ }
+
+ // 8 reserved bytes
+
+ int64_t version = ((payloadData[19] & 0xFF) << 24);
+ version |= ((payloadData[18] & 0xFF) << 16);
+ version |= ((payloadData[17] & 0xFF) << 8);
+ version |= (payloadData[16] & 0xFF);
+
+ return new DeviceStateHostFirmware(build, version);
+ }
+
+
+ DeviceStateWifiInfo* parseDeviceStateWifiInfoMessage(char* payloadData) {
+ int64_t signal = ((payloadData[3] & 0xFF) << 24);
+ signal |= ((payloadData[2] & 0xFF) << 16);
+ signal |= ((payloadData[1] & 0xFF) << 8);
+ signal |= (payloadData[0] & 0xFF);
+
+ int64_t tx = ((payloadData[7] & 0xFF) << 24);
+ tx |= ((payloadData[6] & 0xFF) << 16);
+ tx |= ((payloadData[5] & 0xFF) << 8);
+ tx |= (payloadData[4] & 0xFF);
+
+ int64_t rx = ((payloadData[11] & 0xFF) << 24);
+ rx |= ((payloadData[10] & 0xFF) << 16);
+ rx |= ((payloadData[9] & 0xFF) << 8);
+ rx |= (payloadData[8] & 0xFF);
+
+ return new DeviceStateWifiInfo(signal, tx, rx);
+ }
+
+
+ DeviceStateWifiFirmware* parseDeviceStateWifiFirmwareMessage(char* payloadData) {
+ long build = 0;
+ for (int i = 0; i < 8; i++) {
+ build += ((int64_t) payloadData[i] & 0xffL) << (8 * i);
+ }
+
+ // 8 reserved bytes
+
+ int64_t version = ((payloadData[19] & 0xFF) << 24);
+ version |= ((payloadData[18] & 0xFF) << 16);
+ version |= ((payloadData[17] & 0xFF) << 8);
+ version |= (payloadData[16] & 0xFF);
+
+ return new DeviceStateWifiFirmware(build, version);
+ }
+
+
+ int parseStatePowerMessage(char* payloadData) {
+ int level = ((payloadData[1] & 0xFF) << 8);
+ level |= (payloadData[0] & 0xFF);
+ return level;
+ }
+
+
+ DeviceStateVersion* parseDeviceStateVersionMessage(char* payloadData) {
+ int64_t vender = ((payloadData[3] & 0xFF) << 24);
+ vender |= ((payloadData[2] & 0xFF) << 16);
+ vender |= ((payloadData[1] & 0xFF) << 8);
+ vender |= (payloadData[0] & 0xFF);
+
+ int64_t product = ((payloadData[7] & 0xFF) << 24);
+ product |= ((payloadData[6] & 0xFF) << 16);
+ product |= ((payloadData[5] & 0xFF) << 8);
+ product |= (payloadData[4] & 0xFF);
+
+ int64_t version = ((payloadData[11] & 0xFF) << 24);
+ version |= ((payloadData[10] & 0xFF) << 16);
+ version |= ((payloadData[9] & 0xFF) << 8);
+ version |= (payloadData[8] & 0xFF);
+
+ return new DeviceStateVersion(vender, product, version);
+ }
+
+
+ DeviceStateInfo* parseDeviceStateInfoMessage(char* payloadData) {
+ int64_t time = 0;
+ int64_t upTime = 0;
+ int64_t downTime = 0;
+ for (int i = 0; i < 8; i++) {
+ time += ((int64_t) payloadData[i] & 0xffL) << (8 * i);
+ upTime += ((int64_t) payloadData[i + 8] & 0xffL) << (8 * i);
+ downTime += ((int64_t) payloadData[i + 16] & 0xffL) << (8 * i);
+ }
+
+ return new DeviceStateInfo(time, upTime, downTime);
+ }
+
+
+ DeviceStateLocation* parseDeviceStateLocationMessage(char* payloadData) {
+ char location[16];
+ for (int i = 0; i < 16; i++) {
+ location[i] = payloadData[i];
+ }
+
+ char labelBytes[32];
+ for (int i = 0; i < 32; i++) {
+ labelBytes[i] = payloadData[i + 16];
+ }
+
+ int64_t updatedAt = 0;
+ for (int i = 0; i < 8; i++) {
+ updatedAt += ((int64_t) payloadData[48] & 0xffL) << (8 * i);
+ }
+
+ string str(labelBytes);
+ return new DeviceStateLocation(location, str, updatedAt);
+ }
+
+
+ DeviceStateGroup* parseDeviceStateGroupMessage(char* payloadData) {
+ char group[16];
+ for (int i = 0; i < 16; i++) {
+ group[i] = payloadData[i];
+ }
+
+ char labelBytes[32];
+ for (int i = 0; i < 32; i++) {
+ labelBytes[i] = payloadData[i + 16];
+ }
+
+ int64_t updatedAt = 0;
+ for (int i = 0; i < 8; i++) {
+ updatedAt += ((int64_t) payloadData[48] & 0xffL) << (8 * i);
+ }
+
+ string str(labelBytes);
+ return new DeviceStateGroup(group, str, updatedAt);
+ }
+
+
+ // Receiving
+ // Light Messages
+ LightState* parseLightStateMessage(char* payloadData) {
+
+ char colorData[8];
+ for (int i = 0; i < 8; i++) {
+ colorData[i] = payloadData[i];
+ }
+ BulbColor color(colorData);
+
+ int power = ((payloadData[11] & 0xFF) << 8);
+ power |= (payloadData[10] & 0xFF);
+
+ string label(payloadData);
+
+ char labelArray[32];
+ for (int i = 0; i < 32; i++) {
+ labelArray[i] = payloadData[12 + i];
+ }
+
+ return new LightState(&color, power, label);
+ }
+
+
+ int parseLightStatePowerMessage(char* payloadData) {
+ int level = ((payloadData[1] & 0xFF) << 8);
+ level |= (payloadData[0] & 0xFF);
+ return level;
+ }
+
+
+ // Private Handlers
+ void handleStateVersionMessageReceived(char* payloadData) {
+
+ DeviceStateVersion* deviceState = parseDeviceStateVersionMessage(payloadData);
+ int productNumber = (int)deviceState->getProduct();
+
+ bool isColor = false;
+
+ if (productNumber == 1) {// Original 1000
+ isColor = true;
+ } else if (productNumber == 3) {//Color 650
+ isColor = true;
+ } else if (productNumber == 10) {// White 800 (Low Voltage)
+ isColor = false;
+ } else if (productNumber == 11) {// White 800 (High Voltage)
+ isColor = false;
+ } else if (productNumber == 18) {// White 900 BR30 (Low Voltage)
+ isColor = false;
+ } else if (productNumber == 20) {// Color 1000 BR30
+ isColor = true;
+ } else if (productNumber == 22) {// Color 1000
+ isColor = true;
+ }
+
+ if (isColor) {
+ hueLowerBound = 0;
+ hueUpperBound = 65535;
+ saturationLowerBound = 0;
+ saturationUpperBound = 65535;
+ brightnessLowerBound = 0;
+ brightnessUpperBound = 65535;
+ temperatureLowerBound = 2500;
+ temperatureUpperBound = 9000;
+ } else {
+ hueLowerBound = 0;
+ hueUpperBound = 0;
+ saturationLowerBound = 0;
+ saturationUpperBound = 0;
+ brightnessLowerBound = 0;
+ brightnessUpperBound = 65535;// still can dim bulb
+ temperatureLowerBound = 2500;
+ temperatureUpperBound = 9000;
+ }
+
+ didGetBulbVersion.exchange(true);
+ // Avoid memory leak - delete this object
+ delete deviceState;
+ }
+
+
+ void handleLightStateMessageReceived(char* payloadData) {
+ LightState* lightState = parseLightStateMessage(payloadData);
+
+ BulbColor* color = lightState->getColor();
+ int power = lightState->getPower();
+
+ bool bulbWrongColor = false;
+ bulbWrongColor = bulbWrongColor || (color->getHue() != currentHue);
+ bulbWrongColor = bulbWrongColor || (color->getSaturation() != currentSaturation);
+ bulbWrongColor = bulbWrongColor || (color->getBrightness() != currentBrightness);
+ bulbWrongColor = bulbWrongColor || (color->getKelvin() != currentTemperature);
+
+
+ // gets set to true if any of the below if statements are taken
+ stateDidChange = false;
+
+ if (bulbWrongColor) {
+ BulbColor* newColor = new BulbColor(currentHue, currentSaturation, currentBrightness, currentTemperature);
+ sendSetLightColorPacket(newColor, 250);
+ // System.out.println("Failed Check 1");
+ }
+
+ bulbStateMutex.lock();
+ bool bulbIsOnTmp = bulbIsOn;
+ bulbStateMutex.unlock();
+
+ if ((!bulbIsOnTmp) && (power != 0)) {
+ turnOff();
+ // System.out.println("Failed Check 2: " + Integer.toString(power));
+
+ }
+
+ if (bulbIsOnTmp && (power < 65530)) {
+ turnOn();
+ // System.out.println("Failed Check 3: " + Integer.toString(power));
+
+ }
+ // Avoid memory leak - delete object
+ delete lightState;
+ delete color;
+ }
+
+};
+#endif
--- /dev/null
+#ifndef _LIGHTSTATE_HPP__
+#define _LIGHTSTATE_HPP__
+#include <iostream>
+
+#include "BulbColor.hpp"
+
+class LightState {
+ private:
+ BulbColor* color;
+ int power;
+ string label;
+
+ public:
+
+ LightState(BulbColor* _color, int _power, string _label) {
+
+ color = _color;
+ power = _power;
+ label = _label;
+ }
+
+
+ ~LightState() {
+ }
+
+
+ BulbColor* getColor() {
+ return color;
+ }
+
+
+ int getPower() {
+ return power;
+ }
+
+
+ string getLabel() {
+ return label;
+ }
+};
+#endif
--- /dev/null
+BASE = ../../..
+
+include $(BASE)/common.mk
+
+all: light
+
+# Compile
+#
+PHONY += light
+light:
+ cd LifxLightBulb/; $(G++) ./LifxLightBulb.cpp $(BASE)/../iotjava/iotruntime/cpp/socket/Socket.cpp -o ../$(BIN_DIR)/iotcode/LifxLightBulb/LifxLightBulb.o --std=c++11 -pthread -pg -I$(BASE)/../iotjava/iotruntime/cpp/ -I$(BASE)/../iotjava/iotruntime/cpp/socket/ -I$(BASE)/../iotjava/iotruntime/cpp/setrelation/ -I$(BASE)/../iotjava/iotrmi/C++/ -I$(BASE)/../benchmarks/virtuals/
+ cp LifxLightBulb/LifxLightBulb.config $(BIN_DIR)/iotcode/LifxLightBulb
+
+.PHONY: $(PHONY)
+++ /dev/null
-package iotcode.EspAlarm;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import iotrmi.Java.IoTRMICall;
-import iotrmi.Java.IoTRMIObject;
-
-import iotcode.interfaces.*;
-
-public class Alarm_Skeleton implements Alarm {
-
- private Alarm mainObj;
- private IoTRMIObject rmiObj;
-
- private String callbackAddress;
- private final static int object0Id = 0; //AlarmSmart
- private static Integer[] object0Permission = { 4, 2, 0, 1, 3 };
- private static List<Integer> set0Allowed;
-
-
- public Alarm_Skeleton(Alarm _mainObj, String _callbackAddress, int _port) throws Exception {
- mainObj = _mainObj;
- callbackAddress = _callbackAddress;
- rmiObj = new IoTRMIObject(_port);
- set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
- ___waitRequestInvokeMethod();
- }
-
- public void init() {
- mainObj.init();
- }
-
- public void setZone(int _zone, boolean _onOff, int _onDurationSeconds) {
- mainObj.setZone(_zone, _onOff, _onDurationSeconds);
- }
-
- public List<ZoneState> getZoneStates() {
- return mainObj.getZoneStates();
- }
-
- public int getNumberOfZones() {
- return mainObj.getNumberOfZones();
- }
-
- public boolean doesHaveZoneTimers() {
- return mainObj.doesHaveZoneTimers();
- }
-
- public void ___init() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- init();
- }
-
- public void ___setZone() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class, boolean.class, int.class },
- new Class<?>[] { null, null, null });
- setZone((int) paramObj[0], (boolean) paramObj[1], (int) paramObj[2]);
- }
-
- public void ___getZoneStates() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- List<ZoneState> retStruct = getZoneStates();
- int retLen = retStruct.size();
- Object retLenObj = retLen;
- rmiObj.sendReturnObj(retLenObj);
- Class<?>[] retCls = new Class<?>[3*retLen];
- Object[] retObj = new Object[3*retLen];
- int retPos = 0;
- for(int i = 0; i < retLen; i++) {
- retCls[retPos] = int.class;
- retObj[retPos++] = retStruct.get(i).zoneNumber;
- retCls[retPos] = boolean.class;
- retObj[retPos++] = retStruct.get(i).onOffState;
- retCls[retPos] = int.class;
- retObj[retPos++] = retStruct.get(i).duration;
- }
- rmiObj.sendReturnObj(retCls, retObj);
- }
-
- public void ___getNumberOfZones() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getNumberOfZones();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___doesHaveZoneTimers() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = doesHaveZoneTimers();
- rmiObj.sendReturnObj(retObj);
- }
-
- private void ___waitRequestInvokeMethod() throws IOException {
- while (true) {
- rmiObj.getMethodBytes();
- int _objectId = rmiObj.getObjectId();
- int methodId = rmiObj.getMethodId();
- if (_objectId == object0Id) {
- if (!set0Allowed.contains(methodId)) {
- throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
- }
- }
- else {
- throw new Error("Object Id: " + _objectId + " not recognized!");
- }
- switch (methodId) {
- case 0: ___init(); break;
- case 1: ___setZone(); break;
- case 2: ___getZoneStates(); break;
- case 3: ___getNumberOfZones(); break;
- case 4: ___doesHaveZoneTimers(); break;
- default:
- throw new Error("Method Id " + methodId + " not recognized!");
- }
- }
- }
-
-}
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=Alarm
-# Stub
-INTERFACE_STUB_CLASS=AlarmSmart
+++ /dev/null
-package iotcode.EspAlarm;
-
-// Standard Java Packages
-import java.io.*;
-import java.net.*;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.security.InvalidParameterException;
-import java.util.Date;
-import java.util.Iterator;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.ArrayList;
-
-// IoT Packages
-import iotruntime.IoTUDP;
-import iotruntime.slave.IoTDeviceAddress;
-import iotruntime.slave.IoTSet;
-import iotcode.interfaces.ZoneState;
-import iotcode.interfaces.Alarm;
-
-//import iotchecker.qual.*;
-import iotcode.annotation.*;
-
-/** Class EspAlarm for the ESP8266 plrg Alarm.
- *
- * @author Ali Younis <ayounis @ uci.edu>, Rahmadi Trimananda <rtrimana @ uci.edu>
- * @version 1.0
- * @since 2016-12-21
- */
-
-public class EspAlarm implements Alarm {
-
- /*******************************************************************************************************************************************
- **
- ** Variables
- **
- *******************************************************************************************************************************************/
-
- private IoTUDP communicationSockect;
- private Semaphore socketMutex = new Semaphore(1);
- private AtomicBoolean sendSocketFlag = new AtomicBoolean(false);
- private AtomicBoolean doingRead = new AtomicBoolean(false);
- private AtomicBoolean didInit = new AtomicBoolean(false);
- private Semaphore settingZone = new Semaphore(1);
-
- /*******************************************************************************************************************************************
- **
- ** Threads
- **
- *******************************************************************************************************************************************/
-
- // Main worker thread will do the receive loop
- Thread workerThread = null;
-
-
- /*******************************************************************************************************************************************
- **
- ** IoT Sets and Relations
- **
- *******************************************************************************************************************************************/
-
- // IoTSet of Device Addresses.
- // Will be filled with only 1 address.
- @config private IoTSet<IoTDeviceAddress> alm_Addresses;
-
- /*public EspSprinkler(IoTUDP _udp) {
- communicationSockect = _udp;
- }*/
-
- public EspAlarm() {
- communicationSockect = null;
- }
-
-
- /*******************************************************************************************************************************************
- **
- ** Interface Methods
- **
- *******************************************************************************************************************************************/
-
- /** Method to set the state of a specified zone. Interface implementation.
- *
- * @param _zone [int] : zone number to set.
- * @param _onOff [boolean] : the state to set the zone to, on or off.
- * @param _onDurationSeconds [int]: the duration to set the state on to, if -1 then infinite.
- *
- * @return [void] None.
- */
- public void setZone(int _zone, boolean _onOff, int _onDurationSeconds) {
-
- try {
- settingZone.acquire();
- String sendString = "SET,";
- sendString += Integer.toString(_zone);
- sendString += ", ";
-
- if (_onOff) {
- sendString += "1";
- } else {
- sendString += "0";
- }
- sendString += ", ";
- sendString += Integer.toString(_onDurationSeconds);
-
- sendPacket(sendString.getBytes(StandardCharsets.UTF_8));
- } catch (Exception e) {
- e.printStackTrace();
- }
- settingZone.release();
- }
-
-
- /** Method to get the current state of all the zones. Interface implementation.
- *
- * @param None.
- *
- * @return [List<ZoneState>] list of the states for the zones.
- */
- public List<ZoneState> getZoneStates() {
- doingRead.set(true);
- sendGetInformation();
-
- try {
- Thread.sleep(100);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- int loopCount = 0;
- while (true) {
- // Communication resource is busy so try again later
- if (sendSocketFlag.get()) {
- continue;
- }
-
- try {
- socketMutex.acquire();
- } catch (InterruptedException e) {
- }
-
- byte[] dat = null;
- try {
- dat = communicationSockect.recieveData(1024);
- } catch (java.net.SocketTimeoutException e) {
- // Timeout occurred
-
- } catch (IOException e) {
- // Problem but might be able to recover??
- e.printStackTrace();
-
- }
-
- // Never forget to release!
- socketMutex.release();
-
- // A packed arrived
- if (dat != null) {
- doingRead.set(false);
- return parseGetResponse(dat);
-
- // return new ArrayList<ZoneState>();
- } else {
- try {
- Thread.sleep(100);
- } catch (Exception e) {
- e.printStackTrace();
- }
- loopCount++;
-
- if (loopCount > 3) {
- sendGetInformation();
- loopCount = 0;
- }
- }
- }
- }
-
-
- /** Method to get the number of zones this sprinkler can control. Interface implementation.
- *
- * @param None.
- *
- * @return [int] number of zones that can be controlled.
- */
- public int getNumberOfZones() {
- return 9;
- }
-
-
- /** Method to get whether or not this sprinkler can control durations. Interface implementation.
- *
- * @param None.
- *
- * @return [boolean] boolean if this sprinkler can do durations.
- */
- public boolean doesHaveZoneTimers() {
- return true;
- }
-
-
- /** Method to initialize the sprinkler. Interface implementation.
- *
- * @param None.
- *
- * @return [void] None.
- */
- public void init() {
-
- if (didInit.compareAndSet(false, true) == false) {
- return; // already init
- }
-
- try {
- Iterator itr = alm_Addresses.iterator();
- IoTDeviceAddress deviceAddress = (IoTDeviceAddress)itr.next();
- System.out.println("Address: " + deviceAddress.getCompleteAddress());
-
- // Create the communication channel
- communicationSockect = new IoTUDP(deviceAddress);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
-
- // Launch the worker function in a separate thread.
- workerThread = new Thread(new Runnable() {
- public void run() {
- workerFunction();
- }
- });
- workerThread.start();
- }
-
-
- /*******************************************************************************************************************************************
- **
- ** Private Handlers
- **
- *******************************************************************************************************************************************/
-
- /** Method to send the get information udp packet to get the latest sprinkler state.
- *
- * @param None.
- *
- * @return [void] None.
- */
- public void sendGetInformation() {
- String sendString = "GET";
- sendPacket(sendString.getBytes(StandardCharsets.UTF_8));
- }
-
-
- /** Method to parse the UDP packet data into a meaningful representation.
- *
- * @param _packetData [byte[]] raw packet data from the udp packet.
- *
- * @return [List<ZoneState>] Parsed zone data.
- */
- private List<ZoneState> parseGetResponse(byte[] _packetData) {
- String recString = new String(_packetData);
- List<ZoneState> retStates = new ArrayList<ZoneState>();
-
- String[] lines = recString.split("\n");
-
- for (int i = 0; i < 9; i++) {
- String[] splitSting = lines[i].split(",");
-
- int zoneNum = Integer.parseInt(splitSting[0].trim());
- int onOffInt = Integer.parseInt(splitSting[1].trim());
- boolean onOff = onOffInt != 0;
- int duration = Integer.parseInt(splitSting[2].trim());
-
- //ZoneState zTmp = new ZoneState(zoneNum, onOff, duration);
- ZoneState zTmp = new ZoneState();
- zTmp.zoneNumber = zoneNum;
- zTmp.onOffState = onOff;
- zTmp.duration = duration;
- retStates.add(zTmp);
- }
-
- return retStates;
- }
-
-
- /** Method to parse the UDP packet data into a meaningful representation.
- *
- * @param _packetData [byte[]] bytes to send over the udp channel.
- *
- * @return [void] None.
- */
- private void sendPacket(byte[] _packetData) {
- // System.out.println("About to send");
- sendSocketFlag.set(true);
-
- try {
- socketMutex.acquire();
- } catch (InterruptedException e) {
- System.out.println("mutex Error");
- }
-
- try {
- communicationSockect.sendData(_packetData);
-
- } catch (IOException e) {
- System.out.println("Socket Send Error");
- }
-
- sendSocketFlag.set(false);
- socketMutex.release();
- }
-
-
- /** Method to constantly flush the udp socket expect when we wish to read the incoming data.
- *
- * @param None.
- *
- * @return [void] None.
- */
- private void workerFunction() {
- try {
- // Need timeout on receives since we are not sure if a packet will be available
- // for processing so don't block waiting
- communicationSockect.setSoTimeout(50);
- } catch (IOException e) {
- }
-
-
-
- while (true) {
-
- // Communication resource is busy so try again later
- if (sendSocketFlag.get()) {
- continue;
- }
-
- if (doingRead.get()) {
- continue;
- }
-
- try {
- socketMutex.acquire();
- } catch (InterruptedException e) {
- }
-
- byte[] dat = null;
- try {
- dat = communicationSockect.recieveData(1024);
- } catch (java.net.SocketTimeoutException e) {
- // Timeout occurred
-
- } catch (IOException e) {
- // Problem but might be able to recover??
- e.printStackTrace();
-
- }
-
- // Never forget to release!
- socketMutex.release();
-
- // Wait a bit as to not tie up system resources
- try {
- Thread.sleep(100);
- } catch (Exception e) {
-
- }
- }
- }
-
-}
-
-
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=Sprinkler
-# Stub
-INTERFACE_STUB_CLASS=SprinklerSmart
+++ /dev/null
-package iotcode.EspSprinkler;
-
-// Standard Java Packages
-import java.io.*;
-import java.net.*;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.security.InvalidParameterException;
-import java.util.Date;
-import java.util.Iterator;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.ArrayList;
-
-// IoT Packages
-import iotruntime.IoTUDP;
-import iotruntime.slave.IoTDeviceAddress;
-import iotruntime.slave.IoTSet;
-import iotcode.interfaces.ZoneState;
-import iotcode.interfaces.Sprinkler;
-import iotcode.annotation.*;
-
-//import iotchecker.qual.*;
-
-/** Class EspSprinkler for the ESP8266 plrg Sprinkler.
- *
- * @author Ali Younis <ayounis @ uci.edu>
- * @version 1.0
- * @since 2016-03-31
- */
-
-public class EspSprinkler implements Sprinkler {
-
- /*******************************************************************************************************************************************
- **
- ** Variables
- **
- *******************************************************************************************************************************************/
-
- private IoTUDP communicationSockect;
- private Semaphore socketMutex = new Semaphore(1);
- private AtomicBoolean sendSocketFlag = new AtomicBoolean(false);
- private AtomicBoolean doingRead = new AtomicBoolean(false);
- private AtomicBoolean didInit = new AtomicBoolean(false);
- private Semaphore settingZone = new Semaphore(1);
-
- /*******************************************************************************************************************************************
- **
- ** Threads
- **
- *******************************************************************************************************************************************/
-
- // Main worker thread will do the receive loop
- Thread workerThread = null;
-
-
- /*******************************************************************************************************************************************
- **
- ** IoT Sets and Relations
- **
- *******************************************************************************************************************************************/
-
- // IoTSet of Device Addresses.
- // Will be filled with only 1 address.
- @config private IoTSet<IoTDeviceAddress> spr_Addresses;
-
- /*public EspSprinkler(IoTUDP _udp) {
- communicationSockect = _udp;
- }*/
-
- public EspSprinkler() {
- communicationSockect = null;
- }
-
-
- /*******************************************************************************************************************************************
- **
- ** Interface Methods
- **
- *******************************************************************************************************************************************/
-
- /** Method to set the state of a specified zone. Interface implementation.
- *
- * @param _zone [int] : zone number to set.
- * @param _onOff [boolean] : the state to set the zone to, on or off.
- * @param _onDurationSeconds [int]: the duration to set the state on to, if -1 then infinite.
- *
- * @return [void] None.
- */
- public void setZone(int _zone, boolean _onOff, int _onDurationSeconds) {
-
- try {
- settingZone.acquire();
- String sendString = "SET,";
- sendString += Integer.toString(_zone);
- sendString += ", ";
-
- if (_onOff) {
- sendString += "1";
- } else {
- sendString += "0";
- }
- sendString += ", ";
- sendString += Integer.toString(_onDurationSeconds);
-
- sendPacket(sendString.getBytes(StandardCharsets.UTF_8));
- } catch (Exception e) {
- e.printStackTrace();
- }
- settingZone.release();
- }
-
-
- /** Method to get the current state of all the zones. Interface implementation.
- *
- * @param None.
- *
- * @return [List<ZoneState>] list of the states for the zones.
- */
- public List<ZoneState> getZoneStates() {
- doingRead.set(true);
- sendGetInformation();
-
- try {
- Thread.sleep(100);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- int loopCount = 0;
- while (true) {
- // Communication resource is busy so try again later
- if (sendSocketFlag.get()) {
- continue;
- }
-
- try {
- socketMutex.acquire();
- } catch (InterruptedException e) {
- }
-
- byte[] dat = null;
- try {
- dat = communicationSockect.recieveData(1024);
- } catch (java.net.SocketTimeoutException e) {
- // Timeout occurred
-
- } catch (IOException e) {
- // Problem but might be able to recover??
- e.printStackTrace();
-
- }
-
- // Never forget to release!
- socketMutex.release();
-
- // A packed arrived
- if (dat != null) {
- doingRead.set(false);
- return parseGetResponse(dat);
-
- // return new ArrayList<ZoneState>();
- } else {
- try {
- Thread.sleep(100);
- } catch (Exception e) {
- e.printStackTrace();
- }
- loopCount++;
-
- if (loopCount > 3) {
- sendGetInformation();
- loopCount = 0;
- }
- }
- }
- }
-
-
- /** Method to get the number of zones this sprinkler can control. Interface implementation.
- *
- * @param None.
- *
- * @return [int] number of zones that can be controlled.
- */
- public int getNumberOfZones() {
- return 9;
- }
-
-
- /** Method to get whether or not this sprinkler can control durations. Interface implementation.
- *
- * @param None.
- *
- * @return [boolean] boolean if this sprinkler can do durations.
- */
- public boolean doesHaveZoneTimers() {
- return true;
- }
-
-
- /** Method to initialize the sprinkler. Interface implementation.
- *
- * @param None.
- *
- * @return [void] None.
- */
- public void init() {
-
- if (didInit.compareAndSet(false, true) == false) {
- return; // already init
- }
-
- try {
- Iterator itr = spr_Addresses.iterator();
- IoTDeviceAddress deviceAddress = (IoTDeviceAddress)itr.next();
- System.out.println("Address: " + deviceAddress.getCompleteAddress());
-
- // Create the communication channel
- communicationSockect = new IoTUDP(deviceAddress);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
-
- // Launch the worker function in a separate thread.
- workerThread = new Thread(new Runnable() {
- public void run() {
- workerFunction();
- }
- });
- workerThread.start();
- }
-
-
- /*******************************************************************************************************************************************
- **
- ** Private Handlers
- **
- *******************************************************************************************************************************************/
-
- /** Method to send the get information udp packet to get the latest sprinkler state.
- *
- * @param None.
- *
- * @return [void] None.
- */
- public void sendGetInformation() {
- String sendString = "GET";
- sendPacket(sendString.getBytes(StandardCharsets.UTF_8));
- }
-
-
- /** Method to parse the UDP packet data into a meaningful representation.
- *
- * @param _packetData [byte[]] raw packet data from the udp packet.
- *
- * @return [List<ZoneState>] Parsed zone data.
- */
- private List<ZoneState> parseGetResponse(byte[] _packetData) {
- String recString = new String(_packetData);
- List<ZoneState> retStates = new ArrayList<ZoneState>();
-
- String[] lines = recString.split("\n");
-
- for (int i = 0; i < 9; i++) {
- String[] splitSting = lines[i].split(",");
-
- int zoneNum = Integer.parseInt(splitSting[0].trim());
- int onOffInt = Integer.parseInt(splitSting[1].trim());
- boolean onOff = onOffInt != 0;
- int duration = Integer.parseInt(splitSting[2].trim());
-
-
- //ZoneState zTmp = new ZoneState(zoneNum, onOff, duration);
- ZoneState zTmp = new ZoneState();
- zTmp.zoneNumber = zoneNum;
- zTmp.onOffState = onOff;
- zTmp.duration = duration;
- retStates.add(zTmp);
- }
-
- return retStates;
- }
-
-
- /** Method to parse the UDP packet data into a meaningful representation.
- *
- * @param _packetData [byte[]] bytes to send over the udp channel.
- *
- * @return [void] None.
- */
- private void sendPacket(byte[] _packetData) {
- // System.out.println("About to send");
- sendSocketFlag.set(true);
-
- try {
- socketMutex.acquire();
- } catch (InterruptedException e) {
- System.out.println("mutex Error");
- }
-
- try {
- communicationSockect.sendData(_packetData);
-
- } catch (IOException e) {
- System.out.println("Socket Send Error");
- }
-
- sendSocketFlag.set(false);
- socketMutex.release();
- }
-
-
- /** Method to constantly flush the udp socket expect when we wish to read the incoming data.
- *
- * @param None.
- *
- * @return [void] None.
- */
- private void workerFunction() {
- try {
- // Need timeout on receives since we are not sure if a packet will be available
- // for processing so don't block waiting
- communicationSockect.setSoTimeout(50);
- } catch (IOException e) {
- }
-
-
-
- while (true) {
-
- // Communication resource is busy so try again later
- if (sendSocketFlag.get()) {
- continue;
- }
-
- if (doingRead.get()) {
- continue;
- }
-
- try {
- socketMutex.acquire();
- } catch (InterruptedException e) {
- }
-
- byte[] dat = null;
- try {
- dat = communicationSockect.recieveData(1024);
- } catch (java.net.SocketTimeoutException e) {
- // Timeout occurred
-
- } catch (IOException e) {
- // Problem but might be able to recover??
- e.printStackTrace();
-
- }
-
- // Never forget to release!
- socketMutex.release();
-
- // Wait a bit as to not tie up system resources
- try {
- Thread.sleep(100);
- } catch (Exception e) {
-
- }
- }
- }
-
-}
-
-
-
-
-
-
-
-
+++ /dev/null
-package iotcode.EspSprinkler;
-
-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 Sprinkler_Skeleton implements Sprinkler {
-
- private Sprinkler mainObj;
- private IoTRMIObject rmiObj;
-
- private String callbackAddress;
- private final static int object0Id = 0; //SprinklerSmart
- private static Integer[] object0Permission = { 4, 2, 0, 1, 3 };
- private static List<Integer> set0Allowed;
-
-
- public Sprinkler_Skeleton(Sprinkler _mainObj, String _callbackAddress, int _port) throws Exception {
- mainObj = _mainObj;
- callbackAddress = _callbackAddress;
- rmiObj = new IoTRMIObject(_port);
- set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
- ___waitRequestInvokeMethod();
- }
-
- public void init() {
- mainObj.init();
- }
-
- public void setZone(int _zone, boolean _onOff, int _onDurationSeconds) {
- mainObj.setZone(_zone, _onOff, _onDurationSeconds);
- }
-
- public List<ZoneState> getZoneStates() {
- return mainObj.getZoneStates();
- }
-
- public int getNumberOfZones() {
- return mainObj.getNumberOfZones();
- }
-
- public boolean doesHaveZoneTimers() {
- return mainObj.doesHaveZoneTimers();
- }
-
- public void ___init() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- init();
- }
-
- public void ___setZone() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class, boolean.class, int.class },
- new Class<?>[] { null, null, null });
- setZone((int) paramObj[0], (boolean) paramObj[1], (int) paramObj[2]);
- }
-
- public void ___getZoneStates() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- List<ZoneState> retStruct = getZoneStates();
- int retLen = retStruct.size();
- Object retLenObj = retLen;
- rmiObj.sendReturnObj(retLenObj);
- Class<?>[] retCls = new Class<?>[3*retLen];
- Object[] retObj = new Object[3*retLen];
- int retPos = 0;
- for(int i = 0; i < retLen; i++) {
- retCls[retPos] = int.class;
- retObj[retPos++] = retStruct.get(i).zoneNumber;
- retCls[retPos] = boolean.class;
- retObj[retPos++] = retStruct.get(i).onOffState;
- retCls[retPos] = int.class;
- retObj[retPos++] = retStruct.get(i).duration;
- }
- rmiObj.sendReturnObj(retCls, retObj);
- }
-
- public void ___getNumberOfZones() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getNumberOfZones();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___doesHaveZoneTimers() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = doesHaveZoneTimers();
- rmiObj.sendReturnObj(retObj);
- }
-
- private void ___waitRequestInvokeMethod() throws IOException {
- while (true) {
- rmiObj.getMethodBytes();
- int _objectId = rmiObj.getObjectId();
- int methodId = rmiObj.getMethodId();
- if (_objectId == object0Id) {
- if (!set0Allowed.contains(methodId)) {
- throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
- }
- }
- else {
- throw new Error("Object Id: " + _objectId + " not recognized!");
- }
- switch (methodId) {
- case 0: ___init(); break;
- case 1: ___setZone(); break;
- case 2: ___getZoneStates(); break;
- case 3: ___getNumberOfZones(); break;
- case 4: ___doesHaveZoneTimers(); break;
- default:
- throw new Error("Method Id " + methodId + " not recognized!");
- }
- }
- }
-
-}
+++ /dev/null
-package iotcode.GPSPhoneGateway;
-
-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 GPSGatewaySmartCallback_CallbackStub implements GPSGatewaySmartCallback {
-
- private IoTRMICall rmiCall;
- private String callbackAddress;
- private int[] ports;
-
- private int objectId = 0;
-
-
- public GPSGatewaySmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
- callbackAddress = _callbackAddress;
- objectId = _objectId;
- rmiCall = _rmiCall;
- ports = _ports;
- }
-
- public void newRoomIDRetrieved(int _roomIdentifier) {
- int methodId = 0;
- Class<?> retType = void.class;
- Class<?>[] paramCls = new Class<?>[] { int.class };
- Object[] paramObj = new Object[] { _roomIdentifier };
- rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
- }
-
- public void newRingStatusRetrieved(boolean _ringStatus) {
- int methodId = 1;
- Class<?> retType = void.class;
- Class<?>[] paramCls = new Class<?>[] { boolean.class };
- Object[] paramObj = new Object[] { _ringStatus };
- rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
- }
-
-}
+++ /dev/null
-package iotcode.GPSPhoneGateway;
-
-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 GPSGateway_Skeleton implements GPSGateway {
-
- private GPSGateway mainObj;
- private IoTRMIObject rmiObj;
-
- private String callbackAddress;
- private int objIdCnt = 0;
- private IoTRMICall rmiCall;
- private int[] ports;
-
- private final static int object0Id = 0; //GPSGatewaySmart
- private static Integer[] object0Permission = { 5, 6, 2, 1, 0, 3, 7, 4 };
- private static List<Integer> set0Allowed;
-
-
- public GPSGateway_Skeleton(GPSGateway _mainObj, String _callbackAddress, int _port) throws Exception {
- mainObj = _mainObj;
- callbackAddress = _callbackAddress;
- rmiObj = new IoTRMIObject(_port);
- set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
- set0Allowed.add(-9998);
- ___waitRequestInvokeMethod();
- }
-
- public void init() {
- mainObj.init();
- }
-
- public void start() {
- mainObj.start();
- }
-
- public void stop() {
- mainObj.stop();
- }
-
- public int getRoomID() {
- return mainObj.getRoomID();
- }
-
- public boolean getRingStatus() {
- return mainObj.getRingStatus();
- }
-
- public void setNewRoomIDAvailable(boolean bValue) {
- mainObj.setNewRoomIDAvailable(bValue);
- }
-
- public void setNewRingStatusAvailable(boolean bValue) {
- mainObj.setNewRingStatusAvailable(bValue);
- }
-
- public void registerCallback(GPSGatewaySmartCallback _callbackTo) {
- mainObj.registerCallback(_callbackTo);
- }
-
- public void ___regCB() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
- ports = (int[]) paramObj[0];
- rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
- }
-
- public void ___init() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- init();
- }
-
- public void ___start() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- start();
- }
-
- public void ___stop() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- stop();
- }
-
- public void ___getRoomID() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getRoomID();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getRingStatus() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getRingStatus();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___setNewRoomIDAvailable() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { boolean.class },
- new Class<?>[] { null });
- setNewRoomIDAvailable((boolean) paramObj[0]);
- }
-
- public void ___setNewRingStatusAvailable() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { boolean.class },
- new Class<?>[] { null });
- setNewRingStatusAvailable((boolean) paramObj[0]);
- }
-
- public void ___registerCallback() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- try {
- GPSGatewaySmartCallback stub0 = new GPSGatewaySmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
- objIdCnt++;
- registerCallback(stub0);
- } catch(Exception ex) {
- ex.printStackTrace();
- throw new Error("Exception from callback object instantiation!");
- }
- }
-
- private void ___waitRequestInvokeMethod() throws IOException {
- while (true) {
- rmiObj.getMethodBytes();
- int _objectId = rmiObj.getObjectId();
- int methodId = rmiObj.getMethodId();
- if (_objectId == object0Id) {
- if (!set0Allowed.contains(methodId)) {
- throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
- }
- }
- else {
- throw new Error("Object Id: " + _objectId + " not recognized!");
- }
- switch (methodId) {
- case 0: ___init(); break;
- case 1: ___start(); break;
- case 2: ___stop(); break;
- case 3: ___getRoomID(); break;
- case 4: ___getRingStatus(); break;
- case 5: ___setNewRoomIDAvailable(); break;
- case 6: ___setNewRingStatusAvailable(); break;
- case 7: ___registerCallback(); break;
- case -9998: ___regCB(); break;
- default:
- throw new Error("Method Id " + methodId + " not recognized!");
- }
- }
- }
-
-}
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=GPSGateway
-# Stub
-INTERFACE_STUB_CLASS=GPSGatewaySmart
+++ /dev/null
-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();
- }*/
-}
+++ /dev/null
-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;
- }
-}
+++ /dev/null
-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);
-}
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=Lawn
-# Stub
-INTERFACE_STUB_CLASS=LawnSmart
+++ /dev/null
-package iotcode.GreenLawn;
-
-import iotcode.interfaces.Lawn;
-
-public class GreenLawn implements Lawn {
-
- public GreenLawn() {
-
- }
-}
+++ /dev/null
-package iotcode.GreenLawn;
-
-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 Lawn_Skeleton implements Lawn {
-
- private Lawn mainObj;
- private IoTRMIObject rmiObj;
-
- private String callbackAddress;
- private final static int object0Id = 0; //LawnSmart
- private static Integer[] object0Permission = { };
- private static List<Integer> set0Allowed;
-
-
- public Lawn_Skeleton(Lawn _mainObj, String _callbackAddress, int _port) throws Exception {
- mainObj = _mainObj;
- callbackAddress = _callbackAddress;
- rmiObj = new IoTRMIObject(_port);
- set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
- ___waitRequestInvokeMethod();
- }
-
- 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) {
- default:
- throw new Error("Method Id " + methodId + " not recognized!");
- }
- }
- }
-
-}
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=Room
-# Stub
-INTERFACE_STUB_CLASS=RoomSmart
+++ /dev/null
-package iotcode.HomeRoom;
-
-import iotcode.interfaces.Room;
-
-/** AudioRoom holds room ID that tells which room it is
- * in association with speakers
- *
- * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
- * @version 1.0
- * @since 2016-04-29
- */
-public class HomeRoom implements Room {
-
- /**
- * AudioRoom class properties
- */
- private int iRoomID;
-
- public HomeRoom(int _iRoomID) {
- this.iRoomID = _iRoomID;
- System.out.println("AudioRoom ID: " + this.iRoomID);
- }
-
- public int getRoomID() {
- return this.iRoomID;
- }
-}
+++ /dev/null
-package iotcode.HomeRoom;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import iotrmi.Java.IoTRMICall;
-import iotrmi.Java.IoTRMIObject;
-
-import iotcode.interfaces.Room;
-
-public class Room_Skeleton implements Room {
-
- private Room mainObj;
- private IoTRMIObject rmiObj;
-
- private String callbackAddress;
- private final static int object0Id = 0; //RoomSmart
- private static Integer[] object0Permission = { 0 };
- private static List<Integer> set0Allowed;
-
-
- public Room_Skeleton(Room _mainObj, String _callbackAddress, int _port) throws Exception {
- mainObj = _mainObj;
- callbackAddress = _callbackAddress;
- rmiObj = new IoTRMIObject(_port);
- set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
- ___waitRequestInvokeMethod();
- }
-
- public int getRoomID() {
- return mainObj.getRoomID();
- }
-
- public void ___getRoomID() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getRoomID();
- rmiObj.sendReturnObj(retObj);
- }
-
- private void ___waitRequestInvokeMethod() throws IOException {
- while (true) {
- rmiObj.getMethodBytes();
- int _objectId = rmiObj.getObjectId();
- int methodId = rmiObj.getMethodId();
- if (_objectId == object0Id) {
- if (!set0Allowed.contains(methodId)) {
- throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
- }
- }
- else {
- throw new Error("Object Id: " + _objectId + " not recognized!");
- }
- switch (methodId) {
- case 0: ___getRoomID(); break;
- default:
- throw new Error("Method Id " + methodId + " not recognized!");
- }
- }
- }
-
-}
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=Speaker
-# Stub
-INTERFACE_STUB_CLASS=SpeakerSmart
+++ /dev/null
-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;
- }
-}
-
-
-
-
+++ /dev/null
-package iotcode.IHome;
-
-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 SpeakerSmartCallback_CallbackStub implements SpeakerSmartCallback {
-
- private IoTRMICall rmiCall;
- private String callbackAddress;
- private int[] ports;
-
- private int objectId = 0;
-
-
- public SpeakerSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
- callbackAddress = _callbackAddress;
- objectId = _objectId;
- rmiCall = _rmiCall;
- ports = _ports;
- }
-
- public void speakerDone() {
- int methodId = 0;
- Class<?> retType = void.class;
- Class<?>[] paramCls = new Class<?>[] { };
- Object[] paramObj = new Object[] { };
- rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
- }
-
-}
+++ /dev/null
-package iotcode.IHome;
-
-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 Speaker_Skeleton implements Speaker {
-
- private Speaker mainObj;
- private IoTRMIObject rmiObj;
-
- private String callbackAddress;
- private int objIdCnt = 0;
- private IoTRMICall rmiCall;
- private int[] ports;
-
- private final static int object0Id = 0; //SpeakerSmart
- private static Integer[] object0Permission = { 6, 2, 9, 1, 3, 4, 5, 7, 8, 0, 10 };
- private static List<Integer> set0Allowed;
-
-
- public Speaker_Skeleton(Speaker _mainObj, String _callbackAddress, int _port) throws Exception {
- mainObj = _mainObj;
- callbackAddress = _callbackAddress;
- rmiObj = new IoTRMIObject(_port);
- set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
- set0Allowed.add(-9998);
- ___waitRequestInvokeMethod();
- }
-
- public void init() {
- mainObj.init();
- }
-
- public boolean startPlayback() {
- return mainObj.startPlayback();
- }
-
- public boolean stopPlayback() {
- return mainObj.stopPlayback();
- }
-
- public boolean getPlaybackState() {
- return mainObj.getPlaybackState();
- }
-
- public boolean setVolume(float _percent) {
- return mainObj.setVolume(_percent);
- }
-
- public float getVolume() {
- return mainObj.getVolume();
- }
-
- public int getPosition() {
- return mainObj.getPosition();
- }
-
- public void setPosition(int _mSec) {
- mainObj.setPosition(_mSec);
- }
-
- public void loadData(short _samples[], int _offs, int _len) {
- mainObj.loadData(_samples, _offs, _len);
- }
-
- public void clearData() {
- mainObj.clearData();
- }
-
- public void registerCallback(SpeakerSmartCallback _cb) {
- mainObj.registerCallback(_cb);
- }
-
- public void ___regCB() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
- ports = (int[]) paramObj[0];
- rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
- }
-
- public void ___init() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- init();
- }
-
- public void ___startPlayback() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = startPlayback();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___stopPlayback() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = stopPlayback();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getPlaybackState() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getPlaybackState();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___setVolume() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { float.class },
- new Class<?>[] { null });
- Object retObj = setVolume((float) paramObj[0]);
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getVolume() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getVolume();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getPosition() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getPosition();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___setPosition() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- setPosition((int) paramObj[0]);
- }
-
- public void ___loadData() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { short[].class, int.class, int.class },
- new Class<?>[] { null, null, null });
- loadData((short[]) paramObj[0], (int) paramObj[1], (int) paramObj[2]);
- }
-
- public void ___clearData() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- clearData();
- }
-
- public void ___registerCallback() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- try {
- SpeakerSmartCallback stub0 = new SpeakerSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
- objIdCnt++;
- registerCallback(stub0);
- } catch(Exception ex) {
- ex.printStackTrace();
- throw new Error("Exception from callback object instantiation!");
- }
- }
-
- private void ___waitRequestInvokeMethod() throws IOException {
- while (true) {
- rmiObj.getMethodBytes();
- int _objectId = rmiObj.getObjectId();
- int methodId = rmiObj.getMethodId();
- if (_objectId == object0Id) {
- if (!set0Allowed.contains(methodId)) {
- throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
- }
- }
- else {
- throw new Error("Object Id: " + _objectId + " not recognized!");
- }
- switch (methodId) {
- case 0: ___init(); break;
- case 1: ___startPlayback(); break;
- case 2: ___stopPlayback(); break;
- case 3: ___getPlaybackState(); break;
- case 4: ___setVolume(); break;
- case 5: ___getVolume(); break;
- case 6: ___getPosition(); break;
- case 7: ___setPosition(); break;
- case 8: ___loadData(); break;
- case 9: ___clearData(); break;
- case 10: ___registerCallback(); break;
- case -9998: ___regCB(); break;
- default:
- throw new Error("Method Id " + methodId + " not recognized!");
- }
- }
- }
-
-}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=Camera
+# Stub
+INTERFACE_STUB_CLASS=CameraSmart
--- /dev/null
+package iotcode.AmcrestCamera;
+
+// IoT Packages
+import iotcode.annotation.*;
+import iotcode.interfaces.*;
+import iotruntime.IoTHTTP;
+import iotruntime.slave.IoTSet;
+import iotruntime.slave.IoTDeviceAddress;
+
+// Standard Java Packages
+import java.io.IOException;
+import java.io.DataInputStream;
+import java.io.InputStream;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.WritableRaster;
+import java.awt.image.BufferedImage;
+import javax.imageio.ImageIO;
+import java.util.Base64;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.Iterator;
+import javax.imageio.ImageIO;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Semaphore;
+
+// RMI Packages
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+// Checker annotations
+//import iotchecker.qual.*;
+
+public class AmcrestCamera implements Camera {
+
+ /*******************************************************************************************************************************************
+ **
+ ** Variables
+ **
+ *******************************************************************************************************************************************/
+ private String credentialUsername = "";
+ private String credentialPassword = "";
+ private DataInputStream dataInStream = null;
+ private boolean isStreamConnected = false;
+ private byte[] latestImage = null;
+ private ReadWriteLock imageReadWriteLock = new ReentrantReadWriteLock();
+ private Lock imageReadLock = imageReadWriteLock.readLock();
+ private Lock imageWriteLock = imageReadWriteLock.writeLock();
+ private AtomicBoolean newFrameAvailable = new AtomicBoolean(false);
+ private ReadWriteLock timestampReadWriteLock = new ReentrantReadWriteLock();
+ private Lock timestampReadLock = timestampReadWriteLock.readLock();
+ private Lock timestampWriteLock = timestampReadWriteLock.writeLock();
+ private Date latestImageTimestamp = null;
+ private List <CameraSmartCallback> callbackList =
+ new CopyOnWriteArrayList <CameraSmartCallback> ();
+ private AtomicBoolean doEnd = new AtomicBoolean(false);
+ private IoTDeviceAddress deviceAddress = null;
+ private AtomicBoolean didInit = new AtomicBoolean();
+ private AtomicBoolean didStart = new AtomicBoolean();
+ static Semaphore settingsSettings = new Semaphore(1);
+
+ /*******************************************************************************************************************************************
+ **
+ ** Threads
+ **
+ *******************************************************************************************************************************************/
+ private Thread callbackThread = null;
+ private Thread workerThread = null;
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** IoT Sets and Relations
+ **
+ *******************************************************************************************************************************************/
+
+ // IoTSet of Device Addresses.
+ // Will be filled with only 1 address.
+ @config private IoTSet<IoTDeviceAddress> cam_addresses;
+
+
+ public AmcrestCamera(String _credentialUsername, String _credentialPassword) throws RemoteException {
+ credentialUsername = _credentialUsername;
+ credentialPassword = _credentialPassword;
+ }
+
+ /*******************************************************************************************************************************************
+ **
+ ** Camera Interface Methods
+ **
+ *******************************************************************************************************************************************/
+
+ public byte[] getLatestFrame() {
+
+ byte[] newImage = null;
+
+ imageReadLock.lock();
+ try {
+ if (latestImage != null) {
+ newImage = Arrays.copyOf(latestImage, latestImage.length);
+ }
+ } catch (Exception x) {
+ x.printStackTrace();
+ }
+ imageReadLock.unlock();
+
+ return newImage;
+ }
+
+ public long getTimestamp() {
+ timestampReadLock.lock();
+ Date ret = (Date)latestImageTimestamp.clone();
+ timestampReadLock.unlock();
+ long retLong = ret.getTime();
+ return retLong;
+ }
+
+ public void registerCallback(CameraSmartCallback _callbackTo) {
+ callbackList.add(_callbackTo);
+ }
+
+ public boolean setFPS(int _fps) {
+ try {
+ settingsSettings.acquire();
+
+ String camUrlString = "/cgi-bin/configManager.cgi?action=setConfig&Encode[0].MainFormat[0].Video.FPS=" + Integer.toString(_fps);
+
+ try {
+
+ String credsPreBase64 = credentialUsername + ":" + credentialPassword;
+ String credsBase64 = Base64.getEncoder().encodeToString(credsPreBase64.getBytes("utf-8"));
+ String httpAuthCredentials = "Basic " + credsBase64;
+
+ IoTHTTP httpConnection = new IoTHTTP(deviceAddress);
+ httpConnection.setURL(camUrlString);
+ httpConnection.openConnection();
+ httpConnection.setDoInput(true);
+ httpConnection.setRequestProperty("Authorization", httpAuthCredentials);
+ httpConnection.connect();
+
+ InputStream is = httpConnection.getInputStream();
+ BufferedInputStream bis = new BufferedInputStream(is);
+ DataInputStream din = new DataInputStream(bis);
+
+ // wait for a response
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ie) {
+ }
+
+ byte[] byteBuf = new byte[100];
+ try {
+ int r = din.read(byteBuf, 0, byteBuf.length);
+ String retString = new String(byteBuf);
+
+ if (!retString.substring(0, 2).equals("OK")) {
+ httpConnection.disconnect();
+ return false;
+ }
+
+ } catch (Exception e) {
+ httpConnection.disconnect();
+ return false;
+ // e.printStackTrace();
+ }
+
+ httpConnection.disconnect();
+ } catch (IOException e) {
+ return false;
+ } catch (Exception e) {
+ return false;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ settingsSettings.release();
+
+ return true;
+ }
+
+ public int getMaxFPS() {
+ // Hard coded since this is hardware dependant
+ return 30;
+ }
+
+ public int getMinFPS() {
+ // Hard coded since this is hardware dependant
+ return 5;
+ }
+
+ public List<Resolution> getSupportedResolutions() {
+
+ // Hard coded since this is hardware dependant
+ List<Resolution> ret = new ArrayList<Resolution>();
+ ret.add(Resolution.RES_1080P);
+ ret.add(Resolution.RES_720P);
+ ret.add(Resolution.RES_VGA);
+ return ret;
+ }
+
+ public boolean setResolution(Resolution _res) {
+
+ try {
+ settingsSettings.acquire();
+
+
+ String camUrlString = "/cgi-bin/configManager.cgi?action=setConfig";
+
+ if (_res == Resolution.RES_1080P) {
+ camUrlString += "&Encode[0].MainFormat[0].Video.Height=1080&Encode[0].MainFormat[0].Video.Width=1920";
+
+ } else if (_res == Resolution.RES_720P) {
+ camUrlString += "&Encode[0].MainFormat[0].Video.Height=720&Encode[0].MainFormat[0].Video.Width=1280";
+
+ } else if (_res == Resolution.RES_VGA) {
+ camUrlString += "&Encode[0].MainFormat[0].Video.Height=480&Encode[0].MainFormat[0].Video.Width=640";
+ }
+
+
+ try {
+
+ String credsPreBase64 = credentialUsername + ":" + credentialPassword;
+ String credsBase64 = Base64.getEncoder().encodeToString(credsPreBase64.getBytes("utf-8"));
+ String httpAuthCredentials = "Basic " + credsBase64;
+
+ IoTHTTP httpConnection = new IoTHTTP(deviceAddress);
+ httpConnection.setURL(camUrlString);
+ httpConnection.openConnection();
+ httpConnection.setDoInput(true);
+ httpConnection.setRequestProperty("Authorization", httpAuthCredentials);
+ httpConnection.connect();
+
+ InputStream is = httpConnection.getInputStream();
+ BufferedInputStream bis = new BufferedInputStream(is);
+ DataInputStream din = new DataInputStream(bis);
+
+ // wait for a response
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ie) {
+ }
+
+ byte[] byteBuf = new byte[100];
+ try {
+ int r = din.read(byteBuf, 0, byteBuf.length);
+ String retString = new String(byteBuf);
+
+ if (!retString.substring(0, 2).equals("OK")) {
+ httpConnection.disconnect();
+ return false;
+ }
+
+ } catch (Exception e) {
+ httpConnection.disconnect();
+ return false;
+ // e.printStackTrace();
+ }
+
+ httpConnection.disconnect();
+ } catch (IOException e) {
+ return false;
+ } catch (Exception e) {
+ return false;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ settingsSettings.release();
+
+ return true;
+ }
+
+ public void start() {
+
+ if (didStart.compareAndSet(false, true) == false) {
+ return; // already started
+ }
+
+
+
+ doEnd.set(false);
+
+ if (!streamConnect()) {
+ return;
+ }
+
+ callbackThread = new Thread(new Runnable() {
+ public void run() {
+ doCallbacks();
+ }
+ });
+ callbackThread.start();
+
+ workerThread = new Thread(new Runnable() {
+ public void run() {
+ doWork();
+ }
+ });
+ workerThread.start();
+ }
+
+ public void stop() {
+ if (didStart.compareAndSet(true, false) == false) {
+ return; // already stopped
+ }
+
+ doEnd.set(true);
+
+ try {
+ callbackThread.join();
+ workerThread.join();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ streamDisconnect();
+ }
+
+ public void init() {
+ if (didInit.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ // get the device address and save it for later use when creating HTTP connections
+ Iterator itr = cam_addresses.iterator();
+ deviceAddress = (IoTDeviceAddress)itr.next();
+
+ System.out.println("Address: " + deviceAddress.getCompleteAddress());
+ }
+
+ /*******************************************************************************************************************************************
+ **
+ ** Helper Methods
+ **
+ *******************************************************************************************************************************************/
+ private byte[] readFromStream(int num) {
+ byte[] byteBuf = new byte[num];
+ try {
+ dataInStream.readFully(byteBuf, 0, byteBuf.length);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return byteBuf;
+ }
+
+ private void findBoundry() {
+ String boundary = "**************";
+ while (true) {
+ byte b = readFromStream(1)[0];
+ boundary = boundary.substring(1);
+ boundary += (char)b;
+
+ if (boundary.equals("--myboundary\r\n")) {
+ break;
+ }
+ }
+ }
+
+ private String getLine() {
+ String line = "";
+ while (true) {
+ byte b = readFromStream(1)[0];
+ char c = (char)b;
+
+ if (c == '\n') {
+ break;
+ } else if (c != '\r') {
+ line += c;
+ }
+ }
+
+ return line;
+ }
+
+ private BufferedImage parseImage() {
+
+ findBoundry();
+
+ String contentTypeString = getLine();
+ String contentLengthString = getLine();
+
+ // remove the new line characters \r\n
+ readFromStream(2);
+
+ int imageDataLength = Integer.parseInt(contentLengthString.substring(16));
+
+ byte[] imageDataBuf = readFromStream(imageDataLength);
+
+ // remove the new line characters \r\n
+ readFromStream(2);
+
+
+ try {
+ InputStream imageInStream = new ByteArrayInputStream(imageDataBuf);
+ return ImageIO.read(imageInStream);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.out.println("Has Exception");
+
+ }
+
+ return null;
+ }
+
+ private boolean streamConnect() {
+
+ try {
+
+ String credsPreBase64 = credentialUsername + ":" + credentialPassword;
+ String credsBase64 = Base64.getEncoder().encodeToString(credsPreBase64.getBytes("utf-8"));
+ String httpAuthCredentials = "Basic " + credsBase64;
+
+ IoTHTTP httpConnection = new IoTHTTP(deviceAddress);
+ httpConnection.setURL("/cgi-bin/mjpg/video.cgi?");
+ httpConnection.openConnection();
+ httpConnection.setDoInput(true);
+ httpConnection.setRequestProperty("Authorization", httpAuthCredentials);
+ httpConnection.connect();
+
+ InputStream is = httpConnection.getInputStream();
+ BufferedInputStream bis = new BufferedInputStream(is);
+ dataInStream = new DataInputStream(bis);
+
+ isStreamConnected = true;
+
+ } catch (IOException e) {
+ isStreamConnected = false;
+
+ } catch (Exception e) {
+ isStreamConnected = false;
+ }
+
+ return isStreamConnected;
+ }
+
+ private void streamDisconnect() {
+ try {
+ if (isStreamConnected) {
+ dataInStream.close();
+ isStreamConnected = false;
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ private void doCallbacks() {
+
+ while (!doEnd.get()) {
+ if (newFrameAvailable.compareAndSet(true, false)) {
+
+ for (CameraSmartCallback c : callbackList) {
+
+ c.newCameraFrameAvailable(this.getLatestFrame(), this.getTimestamp());
+ }
+ } else {
+
+ // Sleep for 15 millisec to give time for new frame to arrive
+ try {
+ Thread.sleep(15);
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+
+ }
+
+ private void doWork() {
+
+ // parse the images that are loaded into the buffer
+ while (!doEnd.get()) {
+
+ BufferedImage img = parseImage();
+
+ if (img != null) {
+
+ timestampWriteLock.lock();
+ latestImageTimestamp = new Date();
+ timestampWriteLock.unlock();
+
+ imageWriteLock.lock();
+
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ImageIO.write(img, "jpg", baos);
+ baos.flush();
+ latestImage = baos.toByteArray();
+ baos.close();
+
+ } catch (Exception e) {
+
+ }
+ imageWriteLock.unlock();
+
+ newFrameAvailable.set(true);
+ }
+
+ try {
+ if (dataInStream.available() > 120000) {
+ dataInStream.skip(120000);
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+package iotcode.AmcrestCamera;
+
+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 CameraSmartCallback_CallbackStub implements CameraSmartCallback {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private int objectId = 0;
+
+
+ public CameraSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ objectId = _objectId;
+ rmiCall = _rmiCall;
+ ports = _ports;
+ }
+
+ public void newCameraFrameAvailable(byte latestFrame[], long timeStamp) {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { byte[].class, long.class };
+ Object[] paramObj = new Object[] { latestFrame, timeStamp };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+}
--- /dev/null
+package iotcode.AmcrestCamera;
+
+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 Camera_Skeleton implements Camera {
+
+ private Camera mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private static int objIdCnt = 0;
+ private IoTRMICall rmiCall;
+ private int[] ports;
+
+ private final static int object0Id = 0; //CameraSmart
+ private static Integer[] object0Permission = { 8, 7, 9, 6, 2, 1, 4, 3, 0, 10, 5 };
+ private static List<Integer> set0Allowed;
+
+
+ public Camera_Skeleton(Camera _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ set0Allowed.add(-9998);
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public void start() {
+ mainObj.start();
+ }
+
+ public void stop() {
+ mainObj.stop();
+ }
+
+ public byte[] getLatestFrame() {
+ return mainObj.getLatestFrame();
+ }
+
+ public long getTimestamp() {
+ return mainObj.getTimestamp();
+ }
+
+ public List<Resolution> getSupportedResolutions() {
+ return mainObj.getSupportedResolutions();
+ }
+
+ public boolean setResolution(Resolution _res) {
+ return mainObj.setResolution(_res);
+ }
+
+ public boolean setFPS(int _fps) {
+ return mainObj.setFPS(_fps);
+ }
+
+ public int getMaxFPS() {
+ return mainObj.getMaxFPS();
+ }
+
+ public int getMinFPS() {
+ return mainObj.getMinFPS();
+ }
+
+ public void registerCallback(CameraSmartCallback _callbackTo) {
+ mainObj.registerCallback(_callbackTo);
+ }
+
+ public void ___regCB() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
+ ports = (int[]) paramObj[0];
+ rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___start() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ start();
+ }
+
+ public void ___stop() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ stop();
+ }
+
+ public void ___getLatestFrame() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getLatestFrame();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getTimestamp() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getTimestamp();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getSupportedResolutions() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ List<Resolution> retEnum = getSupportedResolutions();
+ int retLen = retEnum.size();
+ int[] retEnumVal = new int[retLen];
+ for (int i = 0; i < retLen; i++) {
+ retEnumVal[i] = retEnum.get(i).ordinal();
+ }
+ Object retObj = retEnumVal;
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___setResolution() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class },
+ new Class<?>[] { null });
+ int paramInt0[] = (int[]) paramObj[0];
+ Resolution[] enumVals = Resolution.values();
+ Resolution paramEnum0 = enumVals[paramInt0[0]];
+ Object retObj = setResolution(paramEnum0);
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___setFPS() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ Object retObj = setFPS((int) paramObj[0]);
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getMaxFPS() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getMaxFPS();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getMinFPS() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getMinFPS();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___registerCallback() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ try {
+ CameraSmartCallback stub0 = new CameraSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
+ objIdCnt++;
+ registerCallback(stub0);
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Exception from callback object instantiation!");
+ }
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___start(); break;
+ case 2: ___stop(); break;
+ case 3: ___getLatestFrame(); break;
+ case 4: ___getTimestamp(); break;
+ case 5: ___getSupportedResolutions(); break;
+ case 6: ___setResolution(); break;
+ case 7: ___setFPS(); break;
+ case 8: ___getMaxFPS(); break;
+ case 9: ___getMinFPS(); break;
+ case 10: ___registerCallback(); break;
+ case -9998: ___regCB(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=Room
+# Stub
+INTERFACE_STUB_CLASS=RoomSmart
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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!");
+ }
+ }
+ }
+
+}
--- /dev/null
+package iotcode.EspAlarm;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class Alarm_Skeleton implements Alarm {
+
+ private Alarm mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private final static int object0Id = 0; //AlarmSmart
+ private static Integer[] object0Permission = { 4, 2, 0, 1, 3 };
+ private static List<Integer> set0Allowed;
+
+
+ public Alarm_Skeleton(Alarm _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public void setZone(int _zone, boolean _onOff, int _onDurationSeconds) {
+ mainObj.setZone(_zone, _onOff, _onDurationSeconds);
+ }
+
+ public List<ZoneState> getZoneStates() {
+ return mainObj.getZoneStates();
+ }
+
+ public int getNumberOfZones() {
+ return mainObj.getNumberOfZones();
+ }
+
+ public boolean doesHaveZoneTimers() {
+ return mainObj.doesHaveZoneTimers();
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___setZone() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class, boolean.class, int.class },
+ new Class<?>[] { null, null, null });
+ setZone((int) paramObj[0], (boolean) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___getZoneStates() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ List<ZoneState> retStruct = getZoneStates();
+ int retLen = retStruct.size();
+ Object retLenObj = retLen;
+ rmiObj.sendReturnObj(retLenObj);
+ Class<?>[] retCls = new Class<?>[3*retLen];
+ Object[] retObj = new Object[3*retLen];
+ int retPos = 0;
+ for(int i = 0; i < retLen; i++) {
+ retCls[retPos] = int.class;
+ retObj[retPos++] = retStruct.get(i).zoneNumber;
+ retCls[retPos] = boolean.class;
+ retObj[retPos++] = retStruct.get(i).onOffState;
+ retCls[retPos] = int.class;
+ retObj[retPos++] = retStruct.get(i).duration;
+ }
+ rmiObj.sendReturnObj(retCls, retObj);
+ }
+
+ public void ___getNumberOfZones() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getNumberOfZones();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___doesHaveZoneTimers() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = doesHaveZoneTimers();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___setZone(); break;
+ case 2: ___getZoneStates(); break;
+ case 3: ___getNumberOfZones(); break;
+ case 4: ___doesHaveZoneTimers(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=Alarm
+# Stub
+INTERFACE_STUB_CLASS=AlarmSmart
--- /dev/null
+package iotcode.EspAlarm;
+
+// Standard Java Packages
+import java.io.*;
+import java.net.*;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.security.InvalidParameterException;
+import java.util.Date;
+import java.util.Iterator;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.ArrayList;
+
+// IoT Packages
+import iotruntime.IoTUDP;
+import iotruntime.slave.IoTDeviceAddress;
+import iotruntime.slave.IoTSet;
+import iotcode.interfaces.ZoneState;
+import iotcode.interfaces.Alarm;
+
+//import iotchecker.qual.*;
+import iotcode.annotation.*;
+
+/** Class EspAlarm for the ESP8266 plrg Alarm.
+ *
+ * @author Ali Younis <ayounis @ uci.edu>, Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version 1.0
+ * @since 2016-12-21
+ */
+
+public class EspAlarm implements Alarm {
+
+ /*******************************************************************************************************************************************
+ **
+ ** Variables
+ **
+ *******************************************************************************************************************************************/
+
+ private IoTUDP communicationSockect;
+ private Semaphore socketMutex = new Semaphore(1);
+ private AtomicBoolean sendSocketFlag = new AtomicBoolean(false);
+ private AtomicBoolean doingRead = new AtomicBoolean(false);
+ private AtomicBoolean didInit = new AtomicBoolean(false);
+ private Semaphore settingZone = new Semaphore(1);
+
+ /*******************************************************************************************************************************************
+ **
+ ** Threads
+ **
+ *******************************************************************************************************************************************/
+
+ // Main worker thread will do the receive loop
+ Thread workerThread = null;
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** IoT Sets and Relations
+ **
+ *******************************************************************************************************************************************/
+
+ // IoTSet of Device Addresses.
+ // Will be filled with only 1 address.
+ @config private IoTSet<IoTDeviceAddress> alm_Addresses;
+
+ /*public EspSprinkler(IoTUDP _udp) {
+ communicationSockect = _udp;
+ }*/
+
+ public EspAlarm() {
+ communicationSockect = null;
+ }
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** Interface Methods
+ **
+ *******************************************************************************************************************************************/
+
+ /** Method to set the state of a specified zone. Interface implementation.
+ *
+ * @param _zone [int] : zone number to set.
+ * @param _onOff [boolean] : the state to set the zone to, on or off.
+ * @param _onDurationSeconds [int]: the duration to set the state on to, if -1 then infinite.
+ *
+ * @return [void] None.
+ */
+ public void setZone(int _zone, boolean _onOff, int _onDurationSeconds) {
+
+ try {
+ settingZone.acquire();
+ String sendString = "SET,";
+ sendString += Integer.toString(_zone);
+ sendString += ", ";
+
+ if (_onOff) {
+ sendString += "1";
+ } else {
+ sendString += "0";
+ }
+ sendString += ", ";
+ sendString += Integer.toString(_onDurationSeconds);
+
+ sendPacket(sendString.getBytes(StandardCharsets.UTF_8));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ settingZone.release();
+ }
+
+
+ /** Method to get the current state of all the zones. Interface implementation.
+ *
+ * @param None.
+ *
+ * @return [List<ZoneState>] list of the states for the zones.
+ */
+ public List<ZoneState> getZoneStates() {
+ doingRead.set(true);
+ sendGetInformation();
+
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ int loopCount = 0;
+ while (true) {
+ // Communication resource is busy so try again later
+ if (sendSocketFlag.get()) {
+ continue;
+ }
+
+ try {
+ socketMutex.acquire();
+ } catch (InterruptedException e) {
+ }
+
+ byte[] dat = null;
+ try {
+ dat = communicationSockect.recieveData(1024);
+ } catch (java.net.SocketTimeoutException e) {
+ // Timeout occurred
+
+ } catch (IOException e) {
+ // Problem but might be able to recover??
+ e.printStackTrace();
+
+ }
+
+ // Never forget to release!
+ socketMutex.release();
+
+ // A packed arrived
+ if (dat != null) {
+ doingRead.set(false);
+ return parseGetResponse(dat);
+
+ // return new ArrayList<ZoneState>();
+ } else {
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ loopCount++;
+
+ if (loopCount > 3) {
+ sendGetInformation();
+ loopCount = 0;
+ }
+ }
+ }
+ }
+
+
+ /** Method to get the number of zones this sprinkler can control. Interface implementation.
+ *
+ * @param None.
+ *
+ * @return [int] number of zones that can be controlled.
+ */
+ public int getNumberOfZones() {
+ return 9;
+ }
+
+
+ /** Method to get whether or not this sprinkler can control durations. Interface implementation.
+ *
+ * @param None.
+ *
+ * @return [boolean] boolean if this sprinkler can do durations.
+ */
+ public boolean doesHaveZoneTimers() {
+ return true;
+ }
+
+
+ /** Method to initialize the sprinkler. Interface implementation.
+ *
+ * @param None.
+ *
+ * @return [void] None.
+ */
+ public void init() {
+
+ if (didInit.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ try {
+ Iterator itr = alm_Addresses.iterator();
+ IoTDeviceAddress deviceAddress = (IoTDeviceAddress)itr.next();
+ System.out.println("Address: " + deviceAddress.getCompleteAddress());
+
+ // Create the communication channel
+ communicationSockect = new IoTUDP(deviceAddress);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ // Launch the worker function in a separate thread.
+ workerThread = new Thread(new Runnable() {
+ public void run() {
+ workerFunction();
+ }
+ });
+ workerThread.start();
+ }
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** Private Handlers
+ **
+ *******************************************************************************************************************************************/
+
+ /** Method to send the get information udp packet to get the latest sprinkler state.
+ *
+ * @param None.
+ *
+ * @return [void] None.
+ */
+ public void sendGetInformation() {
+ String sendString = "GET";
+ sendPacket(sendString.getBytes(StandardCharsets.UTF_8));
+ }
+
+
+ /** Method to parse the UDP packet data into a meaningful representation.
+ *
+ * @param _packetData [byte[]] raw packet data from the udp packet.
+ *
+ * @return [List<ZoneState>] Parsed zone data.
+ */
+ private List<ZoneState> parseGetResponse(byte[] _packetData) {
+ String recString = new String(_packetData);
+ List<ZoneState> retStates = new ArrayList<ZoneState>();
+
+ String[] lines = recString.split("\n");
+
+ for (int i = 0; i < 9; i++) {
+ String[] splitSting = lines[i].split(",");
+
+ int zoneNum = Integer.parseInt(splitSting[0].trim());
+ int onOffInt = Integer.parseInt(splitSting[1].trim());
+ boolean onOff = onOffInt != 0;
+ int duration = Integer.parseInt(splitSting[2].trim());
+
+ //ZoneState zTmp = new ZoneState(zoneNum, onOff, duration);
+ ZoneState zTmp = new ZoneState();
+ zTmp.zoneNumber = zoneNum;
+ zTmp.onOffState = onOff;
+ zTmp.duration = duration;
+ retStates.add(zTmp);
+ }
+
+ return retStates;
+ }
+
+
+ /** Method to parse the UDP packet data into a meaningful representation.
+ *
+ * @param _packetData [byte[]] bytes to send over the udp channel.
+ *
+ * @return [void] None.
+ */
+ private void sendPacket(byte[] _packetData) {
+ // System.out.println("About to send");
+ sendSocketFlag.set(true);
+
+ try {
+ socketMutex.acquire();
+ } catch (InterruptedException e) {
+ System.out.println("mutex Error");
+ }
+
+ try {
+ communicationSockect.sendData(_packetData);
+
+ } catch (IOException e) {
+ System.out.println("Socket Send Error");
+ }
+
+ sendSocketFlag.set(false);
+ socketMutex.release();
+ }
+
+
+ /** Method to constantly flush the udp socket expect when we wish to read the incoming data.
+ *
+ * @param None.
+ *
+ * @return [void] None.
+ */
+ private void workerFunction() {
+ try {
+ // Need timeout on receives since we are not sure if a packet will be available
+ // for processing so don't block waiting
+ communicationSockect.setSoTimeout(50);
+ } catch (IOException e) {
+ }
+
+
+
+ while (true) {
+
+ // Communication resource is busy so try again later
+ if (sendSocketFlag.get()) {
+ continue;
+ }
+
+ if (doingRead.get()) {
+ continue;
+ }
+
+ try {
+ socketMutex.acquire();
+ } catch (InterruptedException e) {
+ }
+
+ byte[] dat = null;
+ try {
+ dat = communicationSockect.recieveData(1024);
+ } catch (java.net.SocketTimeoutException e) {
+ // Timeout occurred
+
+ } catch (IOException e) {
+ // Problem but might be able to recover??
+ e.printStackTrace();
+
+ }
+
+ // Never forget to release!
+ socketMutex.release();
+
+ // Wait a bit as to not tie up system resources
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+
+ }
+ }
+ }
+
+}
+
+
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=Sprinkler
+# Stub
+INTERFACE_STUB_CLASS=SprinklerSmart
--- /dev/null
+package iotcode.EspSprinkler;
+
+// Standard Java Packages
+import java.io.*;
+import java.net.*;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.security.InvalidParameterException;
+import java.util.Date;
+import java.util.Iterator;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.ArrayList;
+
+// IoT Packages
+import iotruntime.IoTUDP;
+import iotruntime.slave.IoTDeviceAddress;
+import iotruntime.slave.IoTSet;
+import iotcode.interfaces.ZoneState;
+import iotcode.interfaces.Sprinkler;
+import iotcode.annotation.*;
+
+//import iotchecker.qual.*;
+
+/** Class EspSprinkler for the ESP8266 plrg Sprinkler.
+ *
+ * @author Ali Younis <ayounis @ uci.edu>
+ * @version 1.0
+ * @since 2016-03-31
+ */
+
+public class EspSprinkler implements Sprinkler {
+
+ /*******************************************************************************************************************************************
+ **
+ ** Variables
+ **
+ *******************************************************************************************************************************************/
+
+ private IoTUDP communicationSockect;
+ private Semaphore socketMutex = new Semaphore(1);
+ private AtomicBoolean sendSocketFlag = new AtomicBoolean(false);
+ private AtomicBoolean doingRead = new AtomicBoolean(false);
+ private AtomicBoolean didInit = new AtomicBoolean(false);
+ private Semaphore settingZone = new Semaphore(1);
+
+ /*******************************************************************************************************************************************
+ **
+ ** Threads
+ **
+ *******************************************************************************************************************************************/
+
+ // Main worker thread will do the receive loop
+ Thread workerThread = null;
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** IoT Sets and Relations
+ **
+ *******************************************************************************************************************************************/
+
+ // IoTSet of Device Addresses.
+ // Will be filled with only 1 address.
+ @config private IoTSet<IoTDeviceAddress> spr_Addresses;
+
+ /*public EspSprinkler(IoTUDP _udp) {
+ communicationSockect = _udp;
+ }*/
+
+ public EspSprinkler() {
+ communicationSockect = null;
+ }
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** Interface Methods
+ **
+ *******************************************************************************************************************************************/
+
+ /** Method to set the state of a specified zone. Interface implementation.
+ *
+ * @param _zone [int] : zone number to set.
+ * @param _onOff [boolean] : the state to set the zone to, on or off.
+ * @param _onDurationSeconds [int]: the duration to set the state on to, if -1 then infinite.
+ *
+ * @return [void] None.
+ */
+ public void setZone(int _zone, boolean _onOff, int _onDurationSeconds) {
+
+ try {
+ settingZone.acquire();
+ String sendString = "SET,";
+ sendString += Integer.toString(_zone);
+ sendString += ", ";
+
+ if (_onOff) {
+ sendString += "1";
+ } else {
+ sendString += "0";
+ }
+ sendString += ", ";
+ sendString += Integer.toString(_onDurationSeconds);
+
+ sendPacket(sendString.getBytes(StandardCharsets.UTF_8));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ settingZone.release();
+ }
+
+
+ /** Method to get the current state of all the zones. Interface implementation.
+ *
+ * @param None.
+ *
+ * @return [List<ZoneState>] list of the states for the zones.
+ */
+ public List<ZoneState> getZoneStates() {
+ doingRead.set(true);
+ sendGetInformation();
+
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ int loopCount = 0;
+ while (true) {
+ // Communication resource is busy so try again later
+ if (sendSocketFlag.get()) {
+ continue;
+ }
+
+ try {
+ socketMutex.acquire();
+ } catch (InterruptedException e) {
+ }
+
+ byte[] dat = null;
+ try {
+ dat = communicationSockect.recieveData(1024);
+ } catch (java.net.SocketTimeoutException e) {
+ // Timeout occurred
+
+ } catch (IOException e) {
+ // Problem but might be able to recover??
+ e.printStackTrace();
+
+ }
+
+ // Never forget to release!
+ socketMutex.release();
+
+ // A packed arrived
+ if (dat != null) {
+ doingRead.set(false);
+ return parseGetResponse(dat);
+
+ // return new ArrayList<ZoneState>();
+ } else {
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ loopCount++;
+
+ if (loopCount > 3) {
+ sendGetInformation();
+ loopCount = 0;
+ }
+ }
+ }
+ }
+
+
+ /** Method to get the number of zones this sprinkler can control. Interface implementation.
+ *
+ * @param None.
+ *
+ * @return [int] number of zones that can be controlled.
+ */
+ public int getNumberOfZones() {
+ return 9;
+ }
+
+
+ /** Method to get whether or not this sprinkler can control durations. Interface implementation.
+ *
+ * @param None.
+ *
+ * @return [boolean] boolean if this sprinkler can do durations.
+ */
+ public boolean doesHaveZoneTimers() {
+ return true;
+ }
+
+
+ /** Method to initialize the sprinkler. Interface implementation.
+ *
+ * @param None.
+ *
+ * @return [void] None.
+ */
+ public void init() {
+
+ if (didInit.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ try {
+ Iterator itr = spr_Addresses.iterator();
+ IoTDeviceAddress deviceAddress = (IoTDeviceAddress)itr.next();
+ System.out.println("Address: " + deviceAddress.getCompleteAddress());
+
+ // Create the communication channel
+ communicationSockect = new IoTUDP(deviceAddress);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ // Launch the worker function in a separate thread.
+ workerThread = new Thread(new Runnable() {
+ public void run() {
+ workerFunction();
+ }
+ });
+ workerThread.start();
+ }
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** Private Handlers
+ **
+ *******************************************************************************************************************************************/
+
+ /** Method to send the get information udp packet to get the latest sprinkler state.
+ *
+ * @param None.
+ *
+ * @return [void] None.
+ */
+ public void sendGetInformation() {
+ String sendString = "GET";
+ sendPacket(sendString.getBytes(StandardCharsets.UTF_8));
+ }
+
+
+ /** Method to parse the UDP packet data into a meaningful representation.
+ *
+ * @param _packetData [byte[]] raw packet data from the udp packet.
+ *
+ * @return [List<ZoneState>] Parsed zone data.
+ */
+ private List<ZoneState> parseGetResponse(byte[] _packetData) {
+ String recString = new String(_packetData);
+ List<ZoneState> retStates = new ArrayList<ZoneState>();
+
+ String[] lines = recString.split("\n");
+
+ for (int i = 0; i < 9; i++) {
+ String[] splitSting = lines[i].split(",");
+
+ int zoneNum = Integer.parseInt(splitSting[0].trim());
+ int onOffInt = Integer.parseInt(splitSting[1].trim());
+ boolean onOff = onOffInt != 0;
+ int duration = Integer.parseInt(splitSting[2].trim());
+
+
+ //ZoneState zTmp = new ZoneState(zoneNum, onOff, duration);
+ ZoneState zTmp = new ZoneState();
+ zTmp.zoneNumber = zoneNum;
+ zTmp.onOffState = onOff;
+ zTmp.duration = duration;
+ retStates.add(zTmp);
+ }
+
+ return retStates;
+ }
+
+
+ /** Method to parse the UDP packet data into a meaningful representation.
+ *
+ * @param _packetData [byte[]] bytes to send over the udp channel.
+ *
+ * @return [void] None.
+ */
+ private void sendPacket(byte[] _packetData) {
+ // System.out.println("About to send");
+ sendSocketFlag.set(true);
+
+ try {
+ socketMutex.acquire();
+ } catch (InterruptedException e) {
+ System.out.println("mutex Error");
+ }
+
+ try {
+ communicationSockect.sendData(_packetData);
+
+ } catch (IOException e) {
+ System.out.println("Socket Send Error");
+ }
+
+ sendSocketFlag.set(false);
+ socketMutex.release();
+ }
+
+
+ /** Method to constantly flush the udp socket expect when we wish to read the incoming data.
+ *
+ * @param None.
+ *
+ * @return [void] None.
+ */
+ private void workerFunction() {
+ try {
+ // Need timeout on receives since we are not sure if a packet will be available
+ // for processing so don't block waiting
+ communicationSockect.setSoTimeout(50);
+ } catch (IOException e) {
+ }
+
+
+
+ while (true) {
+
+ // Communication resource is busy so try again later
+ if (sendSocketFlag.get()) {
+ continue;
+ }
+
+ if (doingRead.get()) {
+ continue;
+ }
+
+ try {
+ socketMutex.acquire();
+ } catch (InterruptedException e) {
+ }
+
+ byte[] dat = null;
+ try {
+ dat = communicationSockect.recieveData(1024);
+ } catch (java.net.SocketTimeoutException e) {
+ // Timeout occurred
+
+ } catch (IOException e) {
+ // Problem but might be able to recover??
+ e.printStackTrace();
+
+ }
+
+ // Never forget to release!
+ socketMutex.release();
+
+ // Wait a bit as to not tie up system resources
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+
+ }
+ }
+ }
+
+}
+
+
+
+
+
+
+
+
--- /dev/null
+package iotcode.EspSprinkler;
+
+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 Sprinkler_Skeleton implements Sprinkler {
+
+ private Sprinkler mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private final static int object0Id = 0; //SprinklerSmart
+ private static Integer[] object0Permission = { 4, 2, 0, 1, 3 };
+ private static List<Integer> set0Allowed;
+
+
+ public Sprinkler_Skeleton(Sprinkler _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public void setZone(int _zone, boolean _onOff, int _onDurationSeconds) {
+ mainObj.setZone(_zone, _onOff, _onDurationSeconds);
+ }
+
+ public List<ZoneState> getZoneStates() {
+ return mainObj.getZoneStates();
+ }
+
+ public int getNumberOfZones() {
+ return mainObj.getNumberOfZones();
+ }
+
+ public boolean doesHaveZoneTimers() {
+ return mainObj.doesHaveZoneTimers();
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___setZone() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class, boolean.class, int.class },
+ new Class<?>[] { null, null, null });
+ setZone((int) paramObj[0], (boolean) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___getZoneStates() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ List<ZoneState> retStruct = getZoneStates();
+ int retLen = retStruct.size();
+ Object retLenObj = retLen;
+ rmiObj.sendReturnObj(retLenObj);
+ Class<?>[] retCls = new Class<?>[3*retLen];
+ Object[] retObj = new Object[3*retLen];
+ int retPos = 0;
+ for(int i = 0; i < retLen; i++) {
+ retCls[retPos] = int.class;
+ retObj[retPos++] = retStruct.get(i).zoneNumber;
+ retCls[retPos] = boolean.class;
+ retObj[retPos++] = retStruct.get(i).onOffState;
+ retCls[retPos] = int.class;
+ retObj[retPos++] = retStruct.get(i).duration;
+ }
+ rmiObj.sendReturnObj(retCls, retObj);
+ }
+
+ public void ___getNumberOfZones() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getNumberOfZones();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___doesHaveZoneTimers() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = doesHaveZoneTimers();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___setZone(); break;
+ case 2: ___getZoneStates(); break;
+ case 3: ___getNumberOfZones(); break;
+ case 4: ___doesHaveZoneTimers(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+package iotcode.GPSPhoneGateway;
+
+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 GPSGatewaySmartCallback_CallbackStub implements GPSGatewaySmartCallback {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private int objectId = 0;
+
+
+ public GPSGatewaySmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ objectId = _objectId;
+ rmiCall = _rmiCall;
+ ports = _ports;
+ }
+
+ public void newRoomIDRetrieved(int _roomIdentifier) {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int.class };
+ Object[] paramObj = new Object[] { _roomIdentifier };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+ public void newRingStatusRetrieved(boolean _ringStatus) {
+ int methodId = 1;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { boolean.class };
+ Object[] paramObj = new Object[] { _ringStatus };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+}
--- /dev/null
+package iotcode.GPSPhoneGateway;
+
+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 GPSGateway_Skeleton implements GPSGateway {
+
+ private GPSGateway mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private int objIdCnt = 0;
+ private IoTRMICall rmiCall;
+ private int[] ports;
+
+ private final static int object0Id = 0; //GPSGatewaySmart
+ private static Integer[] object0Permission = { 5, 6, 2, 1, 0, 3, 7, 4 };
+ private static List<Integer> set0Allowed;
+
+
+ public GPSGateway_Skeleton(GPSGateway _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ set0Allowed.add(-9998);
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public void start() {
+ mainObj.start();
+ }
+
+ public void stop() {
+ mainObj.stop();
+ }
+
+ public int getRoomID() {
+ return mainObj.getRoomID();
+ }
+
+ public boolean getRingStatus() {
+ return mainObj.getRingStatus();
+ }
+
+ public void setNewRoomIDAvailable(boolean bValue) {
+ mainObj.setNewRoomIDAvailable(bValue);
+ }
+
+ public void setNewRingStatusAvailable(boolean bValue) {
+ mainObj.setNewRingStatusAvailable(bValue);
+ }
+
+ public void registerCallback(GPSGatewaySmartCallback _callbackTo) {
+ mainObj.registerCallback(_callbackTo);
+ }
+
+ public void ___regCB() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
+ ports = (int[]) paramObj[0];
+ rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___start() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ start();
+ }
+
+ public void ___stop() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ stop();
+ }
+
+ public void ___getRoomID() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getRoomID();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getRingStatus() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getRingStatus();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___setNewRoomIDAvailable() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { boolean.class },
+ new Class<?>[] { null });
+ setNewRoomIDAvailable((boolean) paramObj[0]);
+ }
+
+ public void ___setNewRingStatusAvailable() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { boolean.class },
+ new Class<?>[] { null });
+ setNewRingStatusAvailable((boolean) paramObj[0]);
+ }
+
+ public void ___registerCallback() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ try {
+ GPSGatewaySmartCallback stub0 = new GPSGatewaySmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
+ objIdCnt++;
+ registerCallback(stub0);
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Exception from callback object instantiation!");
+ }
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___start(); break;
+ case 2: ___stop(); break;
+ case 3: ___getRoomID(); break;
+ case 4: ___getRingStatus(); break;
+ case 5: ___setNewRoomIDAvailable(); break;
+ case 6: ___setNewRingStatusAvailable(); break;
+ case 7: ___registerCallback(); break;
+ case -9998: ___regCB(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=GPSGateway
+# Stub
+INTERFACE_STUB_CLASS=GPSGatewaySmart
--- /dev/null
+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();
+ }*/
+}
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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);
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=Lawn
+# Stub
+INTERFACE_STUB_CLASS=LawnSmart
--- /dev/null
+package iotcode.GreenLawn;
+
+import iotcode.interfaces.Lawn;
+
+public class GreenLawn implements Lawn {
+
+ public GreenLawn() {
+
+ }
+}
--- /dev/null
+package iotcode.GreenLawn;
+
+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 Lawn_Skeleton implements Lawn {
+
+ private Lawn mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private final static int object0Id = 0; //LawnSmart
+ private static Integer[] object0Permission = { };
+ private static List<Integer> set0Allowed;
+
+
+ public Lawn_Skeleton(Lawn _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ ___waitRequestInvokeMethod();
+ }
+
+ 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) {
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=Room
+# Stub
+INTERFACE_STUB_CLASS=RoomSmart
--- /dev/null
+package iotcode.HomeRoom;
+
+import iotcode.interfaces.Room;
+
+/** AudioRoom holds room ID that tells which room it is
+ * in association with speakers
+ *
+ * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version 1.0
+ * @since 2016-04-29
+ */
+public class HomeRoom implements Room {
+
+ /**
+ * AudioRoom class properties
+ */
+ private int iRoomID;
+
+ public HomeRoom(int _iRoomID) {
+ this.iRoomID = _iRoomID;
+ System.out.println("AudioRoom ID: " + this.iRoomID);
+ }
+
+ public int getRoomID() {
+ return this.iRoomID;
+ }
+}
--- /dev/null
+package iotcode.HomeRoom;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.Room;
+
+public class Room_Skeleton implements Room {
+
+ private Room mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private final static int object0Id = 0; //RoomSmart
+ private static Integer[] object0Permission = { 0 };
+ private static List<Integer> set0Allowed;
+
+
+ public Room_Skeleton(Room _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ ___waitRequestInvokeMethod();
+ }
+
+ public int getRoomID() {
+ return mainObj.getRoomID();
+ }
+
+ public void ___getRoomID() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getRoomID();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___getRoomID(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=Speaker
+# Stub
+INTERFACE_STUB_CLASS=SpeakerSmart
--- /dev/null
+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;
+ }
+}
+
+
+
+
--- /dev/null
+package iotcode.IHome;
+
+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 SpeakerSmartCallback_CallbackStub implements SpeakerSmartCallback {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private int objectId = 0;
+
+
+ public SpeakerSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ objectId = _objectId;
+ rmiCall = _rmiCall;
+ ports = _ports;
+ }
+
+ public void speakerDone() {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { };
+ Object[] paramObj = new Object[] { };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+}
--- /dev/null
+package iotcode.IHome;
+
+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 Speaker_Skeleton implements Speaker {
+
+ private Speaker mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private int objIdCnt = 0;
+ private IoTRMICall rmiCall;
+ private int[] ports;
+
+ private final static int object0Id = 0; //SpeakerSmart
+ private static Integer[] object0Permission = { 6, 2, 9, 1, 3, 4, 5, 7, 8, 0, 10 };
+ private static List<Integer> set0Allowed;
+
+
+ public Speaker_Skeleton(Speaker _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ set0Allowed.add(-9998);
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public boolean startPlayback() {
+ return mainObj.startPlayback();
+ }
+
+ public boolean stopPlayback() {
+ return mainObj.stopPlayback();
+ }
+
+ public boolean getPlaybackState() {
+ return mainObj.getPlaybackState();
+ }
+
+ public boolean setVolume(float _percent) {
+ return mainObj.setVolume(_percent);
+ }
+
+ public float getVolume() {
+ return mainObj.getVolume();
+ }
+
+ public int getPosition() {
+ return mainObj.getPosition();
+ }
+
+ public void setPosition(int _mSec) {
+ mainObj.setPosition(_mSec);
+ }
+
+ public void loadData(short _samples[], int _offs, int _len) {
+ mainObj.loadData(_samples, _offs, _len);
+ }
+
+ public void clearData() {
+ mainObj.clearData();
+ }
+
+ public void registerCallback(SpeakerSmartCallback _cb) {
+ mainObj.registerCallback(_cb);
+ }
+
+ public void ___regCB() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
+ ports = (int[]) paramObj[0];
+ rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___startPlayback() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = startPlayback();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___stopPlayback() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = stopPlayback();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getPlaybackState() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getPlaybackState();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___setVolume() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { float.class },
+ new Class<?>[] { null });
+ Object retObj = setVolume((float) paramObj[0]);
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getVolume() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getVolume();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getPosition() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getPosition();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___setPosition() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ setPosition((int) paramObj[0]);
+ }
+
+ public void ___loadData() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { short[].class, int.class, int.class },
+ new Class<?>[] { null, null, null });
+ loadData((short[]) paramObj[0], (int) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___clearData() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ clearData();
+ }
+
+ public void ___registerCallback() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ try {
+ SpeakerSmartCallback stub0 = new SpeakerSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
+ objIdCnt++;
+ registerCallback(stub0);
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Exception from callback object instantiation!");
+ }
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___startPlayback(); break;
+ case 2: ___stopPlayback(); break;
+ case 3: ___getPlaybackState(); break;
+ case 4: ___setVolume(); break;
+ case 5: ___getVolume(); break;
+ case 6: ___getPosition(); break;
+ case 7: ___setPosition(); break;
+ case 8: ___loadData(); break;
+ case 9: ___clearData(); break;
+ case 10: ___registerCallback(); break;
+ case -9998: ___regCB(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=Room
+# Stub
+INTERFACE_STUB_CLASS=RoomSmart
--- /dev/null
+package iotcode.LabRoom;
+
+import iotcode.interfaces.Room;
+
+/** LabRoom implements Room as a needed object for room identification
+ *
+ * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version 1.0
+ * @since 2016-04-22
+ */
+public class LabRoom implements Room {
+
+ public LabRoom() {
+
+ }
+
+ public int getRoomID() {
+ return 0;
+ }
+}
--- /dev/null
+package iotcode.LabRoom;
+
+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!");
+ }
+ }
+ }
+
+}
--- /dev/null
+package iotcode.LifxLightBulb;
+
+import java.security.InvalidParameterException;
+
+public class BulbColor {
+
+ private int hue;
+ private int saturation;
+ private int brightness;
+ private int kelvin;
+
+ public BulbColor(int _hue, int _saturation, int _brightness, int _kelvin) {
+
+ if ((hue > 65535) || (hue < 0)) {
+ throw new InvalidParameterException("BulbColor: Invalid parameter value for _hue (0-65535)");
+ }
+
+ if ((saturation > 65535) || (saturation < 0)) {
+ throw new InvalidParameterException("BulbColor: Invalid parameter value for _saturation (0-65535)");
+ }
+
+ if ((brightness > 65535) || (brightness < 0)) {
+ throw new InvalidParameterException("BulbColor: Invalid parameter value for _brightness (0-65535)");
+ }
+
+ if ((kelvin > 65535) || (kelvin < 0)) {
+ throw new InvalidParameterException("BulbColor: Invalid parameter value for _kelvin (0-65535)");
+ }
+
+ hue = _hue;
+ saturation = _saturation;
+ brightness = _brightness;
+ kelvin = _kelvin;
+ }
+
+ public BulbColor(byte[] data) {
+ hue = ((data[1] & 0xFF) << 8);
+ hue |= (data[0] & 0xFF);
+
+ saturation = ((data[3] & 0xFF) << 8);
+ saturation |= (data[2] & 0xFF);
+
+ brightness = ((data[5] & 0xFF) << 8);
+ brightness |= (data[4] & 0xFF);
+
+ kelvin = ((data[7] & 0xFF) << 8);
+ kelvin |= (data[6] & 0xFF);
+ }
+
+ public int getHue() {
+ return hue;
+ }
+
+ public int getSaturation() {
+ return saturation;
+ }
+
+ public int getBrightness() {
+ return brightness;
+ }
+
+ public int getKelvin() {
+ return kelvin;
+ }
+}
+
+
--- /dev/null
+package iotcode.LifxLightBulb;
+
+public class DeviceStateGroup {
+ byte[] group = new byte[16];
+ final String label;
+ final long updatedAt;
+
+ public DeviceStateGroup(byte[] _location, String _label, long _updatedAt) {
+ group = _location;
+ label = _label;
+ updatedAt = _updatedAt;
+ }
+
+ public byte[] getGroup() {
+ return group;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public long getUpdatedAt() {
+ return updatedAt;
+ }
+}
--- /dev/null
+package iotcode.LifxLightBulb;
+
+public class DeviceStateHostFirmware {
+ // time of build in nanosecond accuracy
+ // after some tests
+ final long build;
+ final long version; // firmware version
+
+ public DeviceStateHostFirmware(long _build, long _version) {
+ build = _build;
+ version = _version;
+ }
+
+ public long getBuild() {
+ return build;
+ }
+
+ public long getVersion() {
+ return version;
+ }
+}
--- /dev/null
+package iotcode.LifxLightBulb;
+
+public class DeviceStateHostInfo {
+ final long signal;
+ final long tx;
+ final long rx;
+
+ public DeviceStateHostInfo(long _signal, long _tx, long _rx) {
+ signal = _signal;
+ tx = _tx;
+ rx = _rx;
+ }
+
+ public long getSignal() {
+ return signal;
+ }
+
+ public long getTx() {
+ return tx;
+ }
+
+ public long getRx() {
+ return rx;
+ }
+}
--- /dev/null
+package iotcode.LifxLightBulb;
+
+public class DeviceStateInfo {
+ // all values are in nanoseconds
+ private final long time;
+ private final long upTime;
+ private final long downTime;
+
+ public DeviceStateInfo(long _time, long _upTime, long _downTime) {
+ time = _time;
+ upTime = _upTime;
+ downTime = _downTime;
+ }
+
+ public long getTime() {
+ return time;
+ }
+
+ public long getUpTime() {
+ return upTime;
+ }
+
+ public long getDownTime() {
+ return downTime;
+ }
+}
--- /dev/null
+package iotcode.LifxLightBulb;
+
+public class DeviceStateLocation {
+ byte[] location = new byte[16];
+ final String label;
+ final long updatedAt;
+
+ public DeviceStateLocation(byte[] _location, String _label, long _updatedAt) {
+ location = _location;
+ label = _label;
+ updatedAt = _updatedAt;
+ }
+
+ public byte[] getLocation() {
+ return location;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public long getUpdatedAt() {
+ return updatedAt;
+ }
+}
--- /dev/null
+package iotcode.LifxLightBulb;
+
+public class DeviceStateService {
+ private final int service;
+ private final long port;
+
+ public DeviceStateService(int _service, long _port) {
+ service = _service;
+ port = _port;
+ }
+
+ public int getService() {
+ return service;
+ }
+
+ public long getPort() {
+ return port;
+ }
+}
--- /dev/null
+package iotcode.LifxLightBulb;
+
+public class DeviceStateVersion {
+ final long vender;
+ final long product;
+ final long version;
+
+ public DeviceStateVersion(long _vender, long _product, long _version) {
+ vender = _vender;
+ product = _product;
+ version = _version;
+ }
+
+ public long getVender() {
+ return vender;
+ }
+
+ public long getProduct() {
+ return product;
+ }
+
+ public long getVersion() {
+ return version;
+ }
+}
--- /dev/null
+package iotcode.LifxLightBulb;
+
+public class DeviceStateWifiFirmware {
+ // time of build in nanosecond accuracy
+ // after some tests
+ final long build;
+ final long version; // firmware version
+
+ public DeviceStateWifiFirmware(long _build, long _version) {
+ build = _build;
+ version = _version;
+ }
+
+ public long getBuild() {
+ return build;
+ }
+
+ public long getVersion() {
+ return version;
+ }
+}
--- /dev/null
+package iotcode.LifxLightBulb;
+
+public class DeviceStateWifiInfo {
+ final long signal;
+ final long tx;
+ final long rx;
+
+ public DeviceStateWifiInfo(long _signal, long _tx, long _rx) {
+ signal = _signal;
+ tx = _tx;
+ rx = _rx;
+ }
+
+ public long getSignal() {
+ return signal;
+ }
+
+ public long getTx() {
+ return tx;
+ }
+
+ public long getRx() {
+ return rx;
+ }
+}
--- /dev/null
+package iotcode.LifxLightBulb;
+
+import java.security.InvalidParameterException;
+
+public class LifxHeader {
+ // Frame Variables
+ private int size;
+ private int origin;
+ private boolean tagged;
+ private boolean addressable;
+ private int protocol;
+ private long source;
+
+ //Frame Adress Variables
+ private byte[] macAddress = new byte[8];
+ private boolean ack_required;
+ private boolean res_required;
+ private int sequence;
+
+ //Protocol Header
+ private int type;
+
+ public LifxHeader() {
+ // needed values as per spec
+ origin = 0;
+ addressable = true;
+ protocol = 1024;
+ }
+
+ public void setSize(int _size) {
+ if (_size < 0) {
+ throw new InvalidParameterException("Header: size cannot be less than 0");
+ } else if (_size > 65535) {
+ throw new InvalidParameterException("Header: size to large");
+ }
+ size = _size;
+ }
+
+ public void setOrigin(int _origin) {
+ if (_origin < 0) {
+ throw new InvalidParameterException("Header: origin cannot be less than 0");
+ } else if (_origin > 3) {
+ throw new InvalidParameterException("Header: origin to large");
+ }
+
+ origin = _origin;
+ }
+
+ public void setTagged(boolean _tagged) {
+ tagged = _tagged;
+ }
+
+ public void setAddressable(boolean _addressable) {
+ addressable = _addressable;
+ }
+
+ public void setProtocol(int _protocol) {
+ if (_protocol < 0) {
+ throw new InvalidParameterException("Header: protocol cannot be less than 0");
+ } else if (_protocol > 4095) {
+ throw new InvalidParameterException("Header: protocol to large");
+ }
+
+ protocol = _protocol;
+ }
+
+ public void setSource(long _source) {
+ if (_source < 0) {
+ throw new InvalidParameterException("Header: source cannot be less than 0");
+ } else if (_source > (long)4294967295l) {
+ throw new InvalidParameterException("Header: source to large");
+ }
+ source = _source;
+ }
+
+ public void setSequence(int _sequence) {
+ if (_sequence < 0) {
+ throw new InvalidParameterException("Header: sequence cannot be less than 0");
+ } else if (_sequence > 255) {
+ throw new InvalidParameterException("Header: sequence to large");
+ }
+ sequence = _sequence;
+ }
+
+ public void setType(int _type) {
+ if (_type < 0) {
+ throw new InvalidParameterException("Header: type cannot be less than 0");
+ } else if (_type > 65535) {
+ throw new InvalidParameterException("Header: type to large");
+ }
+ type = _type;
+ }
+
+ public void setAck_required(boolean _ack_required) {
+ ack_required = _ack_required;
+ }
+
+ public void setRes_required(boolean _res_required) {
+ res_required = _res_required;
+ }
+
+ public void setMacAddress(byte[] _macAddress) {
+ macAddress = _macAddress;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public int getOrigin() {
+ return origin;
+ }
+
+ public boolean getTagged() {
+ return tagged;
+ }
+
+ public boolean getAddressable() {
+ return addressable;
+ }
+
+ public int getProtocol() {
+ return protocol;
+ }
+
+ public long getSource() {
+ return source;
+ }
+
+ public int getSequence() {
+ return sequence;
+ }
+
+ public int getType() {
+ return type;
+ }
+
+ public byte[] getMacAddress() {
+ return macAddress;
+ }
+
+ public boolean getAck_required() {
+ return ack_required;
+ }
+
+ public boolean getRes_required() {
+ return res_required;
+ }
+
+ public byte[] getHeaderBytes() {
+ byte[] headerBytes = new byte[36];
+ headerBytes[0] = (byte)(size & 0xFF);
+ headerBytes[1] = (byte)((size >> 8) & 0xFF);
+
+
+ headerBytes[2] = (byte)(protocol & 0xFF);
+ headerBytes[3] = (byte)((protocol >> 8) & 0x0F);
+
+ headerBytes[3] |= (byte)((origin & 0x03) << 6);
+
+ if (tagged) {
+ headerBytes[3] |= (1 << 5);
+ }
+
+ if (addressable) {
+ headerBytes[3] |= (1 << 4);
+ }
+
+ headerBytes[4] = (byte)((source >> 0) & 0xFF);
+ headerBytes[5] = (byte)((source >> 8) & 0xFF);
+ headerBytes[6] = (byte)((source >> 16) & 0xFF);
+ headerBytes[7] = (byte)((source >> 24) & 0xFF);
+
+
+ // fix in a bit
+ headerBytes[8] = macAddress[0];
+ headerBytes[9] = macAddress[1];
+ headerBytes[10] = macAddress[2];
+ headerBytes[11] = macAddress[3];
+ headerBytes[12] = macAddress[4];
+ headerBytes[13] = macAddress[5];
+ headerBytes[14] = macAddress[6];
+ headerBytes[15] = macAddress[7];
+
+ // Reserved and set to 0
+ // headerBytes[16] = 0;
+ // headerBytes[17] = 0;
+ // headerBytes[18] = 0;
+ // headerBytes[19] = 0;
+ // headerBytes[20] = 0;
+ // headerBytes[21] = 0;
+
+ if (ack_required) {
+ headerBytes[22] = (1 << 1);
+ }
+
+ if (res_required) {
+ headerBytes[22] |= (1);
+ }
+
+ headerBytes[23] = (byte)(sequence & 0xFF);
+
+ // Reserved and set to 0
+ //headerBytes[24] = 0;
+ //headerBytes[25] = 0;
+ //headerBytes[26] = 0;
+ //headerBytes[27] = 0;
+ //headerBytes[28] = 0;
+ //headerBytes[29] = 0;
+ //headerBytes[30] = 0;
+ //headerBytes[31] = 0;
+
+ headerBytes[32] = (byte)((type >> 0) & 0xFF);
+ headerBytes[33] = (byte)((type >> 8) & 0xFF);
+
+ // Reserved and set to 0
+ //headerBytes[34] = 0;
+ //headerBytes[35] = 0;
+
+ return headerBytes;
+ }
+
+ public void setFromBytes(byte[] dataBytes) {
+ if (dataBytes.length != 36) {
+ throw new InvalidParameterException("Header: invalid number of bytes");
+ }
+
+ size = dataBytes[0] & 0xFF;
+ size |= ((dataBytes[1] & 0xFF) << 8);
+ size &= 0xFFFF;
+
+ origin = (dataBytes[3] >> 6) & 0x03;
+ tagged = ((dataBytes[3] >> 5) & 0x01) == 1;
+ addressable = ((dataBytes[3] >> 4) & 0x01) == 1;
+
+
+ protocol = (dataBytes[3] & 0x0F) << 8;
+ protocol |= dataBytes[2];
+ protocol &= 0x0FFF;
+
+ source = (dataBytes[7] & 0xFFl) << 24;
+ source |= ((dataBytes[6] & 0xFFl) << 16);
+ source |= ((dataBytes[5] & 0xFFl) << 8);
+ source |= ((dataBytes[4] & 0xFFl));
+
+ macAddress[0] = dataBytes[8];
+ macAddress[1] = dataBytes[9];
+ macAddress[2] = dataBytes[10];
+ macAddress[3] = dataBytes[11];
+ macAddress[4] = dataBytes[12];
+ macAddress[5] = dataBytes[13];
+ macAddress[6] = dataBytes[14];
+ macAddress[7] = dataBytes[15];
+
+ ack_required = (dataBytes[22] & 0x02) == 0x02;
+ res_required = (dataBytes[22] & 0x01) == 0x01;
+
+ sequence = (dataBytes[23] & 0xFF);
+
+ type = ((dataBytes[33] & 0xFF) << 8);
+ type |= (dataBytes[32] & 0xFF);
+ }
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=LightBulb
+# Stub
+#INTERFACE_STUB_CLASS=LightBulbTest
+INTERFACE_STUB_CLASS=LightBulbSmart
+
--- /dev/null
+package iotcode.LifxLightBulb;
+
+// Standard Java Packages
+import java.io.*;
+import java.net.*;
+import java.util.concurrent.Semaphore;
+import java.security.InvalidParameterException;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import java.util.Arrays;
+import java.util.Set;
+import java.util.HashSet;
+
+// IoT Packages
+import iotcode.annotation.*;
+import iotcode.interfaces.LightBulb;
+import iotruntime.IoTUDP;
+import iotruntime.slave.IoTDeviceAddress;
+import iotruntime.slave.IoTSet;
+
+// String to byte conversion
+import javax.xml.bind.DatatypeConverter;
+
+public class LifxLightBulb implements LightBulb {
+
+ /*******************************************************************************************************************************************
+ **
+ ** Constants
+ **
+ *******************************************************************************************************************************************/
+ public static final long GET_BULB_VERSION_RESEND_WAIT_SECONDS = 10;
+
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** Variables
+ **
+ *******************************************************************************************************************************************/
+ private IoTUDP communicationSockect;
+ private byte[] bulbMacAddress = new byte[8];
+ static Semaphore socketMutex = new Semaphore(1);
+ static boolean sendSocketFlag = false;
+ private long lastSentGetBulbVersionRequest = 0; // time last request sent
+
+ // Current Bulb Values
+ private int currentHue = 0;
+ private int currentSaturation = 0;
+ private int currentBrightness = 65535;
+ private int currentTemperature = 9000;
+ private boolean bulbIsOn = false;
+
+
+
+ private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
+
+ private AtomicBoolean didGetBulbVersion = new AtomicBoolean(false);
+ static Semaphore settingBulbColorMutex = new Semaphore(1);
+ static Semaphore settingBulbTempuraturerMutex = new Semaphore(1);
+ static Semaphore bulbStateMutex = new Semaphore(1);
+
+ // color and temperature ranges for the bulbs
+ private int hueLowerBound = 0;
+ private int hueUpperBound = 0;
+ private int saturationLowerBound = 0;
+ private int saturationUpperBound = 0;
+ private int brightnessLowerBound = 0;
+ private int brightnessUpperBound = 0;
+ private int temperatureLowerBound = 2500;
+ private int temperatureUpperBound = 9000;
+
+
+
+ // Check if a state change was requested, used to poll the bulb for if the bulb did
+ // preform the requested state change
+ private boolean stateDidChange = false;
+
+ /*******************************************************************************************************************************************
+ **
+ ** Threads
+ **
+ *******************************************************************************************************************************************/
+
+ // Main worker thread will do the receive loop
+ Thread workerThread = null;
+
+ /*******************************************************************************************************************************************
+ **
+ ** IoT Sets and Relations
+ **
+ *******************************************************************************************************************************************/
+
+ // IoTSet of Device Addresses.
+ // Will be filled with only 1 address.
+ @config private IoTSet<IoTDeviceAddress> lb_addresses;
+
+ /**
+ * Used for testing only
+ */
+ /*public LifxLightBulb(IoTUDP udp, byte[] macAddress) {
+ communicationSockect = udp;
+ bulbMacAddress = macAddress;
+ }
+
+ public LifxLightBulb(IoTSet<IoTDeviceAddress> _lb_addresses, String macAddress) {
+ this(macAddress);
+ lb_addresses = _lb_addresses;
+ }*/
+
+ public LifxLightBulb(String macAddress) {
+ communicationSockect = null;
+
+ // Set the Mac Address to a default value
+ // Probably not needed for anything
+ /*bulbMacAdd[0] = (byte)0x00;
+ bulbMacAdd[1] = (byte)0x00;
+ bulbMacAdd[2] = (byte)0x00;
+ bulbMacAdd[3] = (byte)0x00;
+ bulbMacAdd[4] = (byte)0x00;
+ bulbMacAdd[5] = (byte)0x00;
+ bulbMacAdd[6] = (byte)0x00;
+ bulbMacAdd[7] = (byte)0x00;*/
+
+ bulbMacAddress = DatatypeConverter.parseHexBinary(macAddress);
+ }
+
+
+
+ /*******************************************************************************************************************************************
+ ** Sending
+ ** Device Messages
+ **
+ *******************************************************************************************************************************************/
+ private void sendGetServicePacket() {
+ LifxHeader header = new LifxHeader();
+ header.setSize(36);
+ header.setTagged(true);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(0); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(2);
+
+ byte[] dataBytes = header.getHeaderBytes();
+ sendPacket(dataBytes);
+ }
+
+ private void sendGetHostInfoPacket() {
+ LifxHeader header = new LifxHeader();
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(12);
+
+ byte[] dataBytes = header.getHeaderBytes();
+ sendPacket(dataBytes);
+ }
+
+ private void sendGetHostFirmwarePacket() {
+ LifxHeader header = new LifxHeader();
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(14);
+
+ byte[] dataBytes = header.getHeaderBytes();
+ sendPacket(dataBytes);
+ }
+
+ private void sendGetWifiInfoPacket() {
+ LifxHeader header = new LifxHeader();
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(16);
+
+ byte[] dataBytes = header.getHeaderBytes();
+ sendPacket(dataBytes);
+ }
+
+ private void sendGetWifiFirmwarePacket() {
+ LifxHeader header = new LifxHeader();
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(18);
+
+ byte[] dataBytes = header.getHeaderBytes();
+ sendPacket(dataBytes);
+ }
+
+ private void sendGetPowerPacket() {
+ LifxHeader header = new LifxHeader();
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(20);
+
+ byte[] dataBytes = header.getHeaderBytes();
+ sendPacket(dataBytes);
+ }
+
+ private void sendSetPowerPacket(int level) {
+ // Currently only 0 and 65535 are supported
+ // This is a fix for now
+ if ((level != 65535) && (level != 0)) {
+ throw new InvalidParameterException("Invalid parameter values");
+ }
+
+ if ((level > 65535) || (level < 0)) {
+ throw new InvalidParameterException("Invalid parameter values");
+ }
+
+ byte[] packetBytes = new byte[38];
+
+ LifxHeader header = new LifxHeader();
+ header.setSize(38);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(21);
+ byte[] headerBytes = header.getHeaderBytes();
+
+ for (int i = 0; i < 36; i++) {
+ packetBytes[i] = headerBytes[i];
+ }
+
+ packetBytes[36] = (byte)(level & 0xFF);
+ packetBytes[37] = (byte)((level >> 8) & 0xFF);
+
+ sendPacket(packetBytes);
+ }
+
+ private void sendGetLabelPacket() {
+ LifxHeader header = new LifxHeader();
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(23);
+
+ byte[] dataBytes = header.getHeaderBytes();
+ sendPacket(dataBytes);
+ }
+
+ private void sendSetLabelPacket(String label) {
+ // Currently only 0 and 65535 are supported
+ // This is a fix for now
+ if (label.length() != 32) {
+ throw new InvalidParameterException("Invalid parameter values, label must be 32 bytes long");
+ }
+
+ byte[] packetBytes = new byte[68];
+
+ LifxHeader header = new LifxHeader();
+ header.setSize(68);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(24);
+ byte[] headerBytes = header.getHeaderBytes();
+
+ for (int i = 0; i < 36; i++) {
+ packetBytes[i] = headerBytes[i];
+ }
+
+ for (int i = 0; i < 32; i++) {
+ packetBytes[i + 36] = label.getBytes()[i];
+ }
+
+ sendPacket(packetBytes);
+ }
+
+ private void sendGetVersionPacket() {
+ LifxHeader header = new LifxHeader();
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(32);
+
+ byte[] dataBytes = header.getHeaderBytes();
+ sendPacket(dataBytes);
+ }
+
+ private void sendGetInfoPacket() {
+ LifxHeader header = new LifxHeader();
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(34);
+
+ byte[] dataBytes = header.getHeaderBytes();
+ sendPacket(dataBytes);
+ }
+
+ private void sendGetLocationPacket() {
+ LifxHeader header = new LifxHeader();
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(34);
+
+ byte[] dataBytes = header.getHeaderBytes();
+ sendPacket(dataBytes);
+ }
+
+ private void sendGetGroupPacket() {
+ LifxHeader header = new LifxHeader();
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(51);
+
+ byte[] dataBytes = header.getHeaderBytes();
+ sendPacket(dataBytes);
+ }
+
+
+ /*******************************************************************************************************************************************
+ ** Sending
+ ** Light Messages
+ **
+ *******************************************************************************************************************************************/
+ private void sendGetLightStatePacket() {
+ LifxHeader header = new LifxHeader();
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(101);
+
+ byte[] dataBytes = header.getHeaderBytes();
+ sendPacket(dataBytes);
+ }
+
+ private void sendSetLightColorPacket(BulbColor bulbColor, long duration) {
+
+ if ((duration > 4294967295l) || (duration < 0)) {
+ throw new InvalidParameterException("Invalid parameter value, duration out of range (0 - 4294967295)");
+ }
+
+ byte[] packetBytes = new byte[49];
+
+ LifxHeader header = new LifxHeader();
+ header.setSize(49);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(102);
+ byte[] headerBytes = header.getHeaderBytes();
+
+ for (int i = 0; i < 36; i++) {
+ packetBytes[i] = headerBytes[i];
+ }
+
+ // 1 reserved packet
+ packetBytes[37] = (byte)(bulbColor.getHue() & 0xFF);
+ packetBytes[38] = (byte)((bulbColor.getHue() >> 8) & 0xFF);
+
+ packetBytes[39] = (byte)(bulbColor.getSaturation() & 0xFF);
+ packetBytes[40] = (byte)((bulbColor.getSaturation() >> 8) & 0xFF);
+
+ packetBytes[41] = (byte)(bulbColor.getBrightness() & 0xFF);
+ packetBytes[42] = (byte)((bulbColor.getBrightness() >> 8) & 0xFF);
+
+ packetBytes[43] = (byte)(bulbColor.getKelvin() & 0xFF);
+ packetBytes[44] = (byte)((bulbColor.getKelvin() >> 8) & 0xFF);
+
+ packetBytes[45] = (byte)((duration >> 0) & 0xFF);
+ packetBytes[46] = (byte)((duration >> 8) & 0xFF);
+ packetBytes[47] = (byte)((duration >> 16) & 0xFF);
+ packetBytes[48] = (byte)((duration >> 24) & 0xFF);
+
+ sendPacket(packetBytes);
+ }
+
+ private void sendGetLightPowerPacket() {
+ LifxHeader header = new LifxHeader();
+ header.setSize(36);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(116);
+
+ byte[] dataBytes = header.getHeaderBytes();
+ sendPacket(dataBytes);
+ }
+
+ private void sendSetLightPowerPacket(int level, long duration) {
+
+ if ((level > 65535) || (duration > 4294967295l)
+ || (level < 0) || (duration < 0)) {
+ throw new InvalidParameterException("Invalid parameter values");
+ }
+
+ byte[] packetBytes = new byte[42];
+
+
+ LifxHeader header = new LifxHeader();
+ header.setSize(42);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(117);
+ byte[] headerBytes = header.getHeaderBytes();
+
+ for (int i = 0; i < 36; i++) {
+ packetBytes[i] = headerBytes[i];
+ }
+
+ packetBytes[36] = (byte)(level & 0xFF);
+ packetBytes[37] = (byte)((level >> 8) & 0xFF);
+
+ packetBytes[38] = (byte)((duration >> 0) & 0xFF);
+ packetBytes[39] = (byte)((duration >> 8) & 0xFF);
+ packetBytes[40] = (byte)((duration >> 16) & 0xFF);
+ packetBytes[41] = (byte)((duration >> 24) & 0xFF);
+
+ System.out.println(Arrays.toString(packetBytes));
+
+ sendPacket(packetBytes);
+ }
+
+ private void sendEchoRequestPacket(byte[] data) {
+ // Currently only 0 and 65535 are supported
+ // This is a fix for now
+ if (data.length != 64) {
+ throw new InvalidParameterException("Invalid parameter values, must have 64 bytes");
+ }
+
+ byte[] packetBytes = new byte[100];
+
+ LifxHeader header = new LifxHeader();
+ header.setSize(100);
+ header.setTagged(false);
+ header.setMacAddress(bulbMacAddress);
+ header.setSource(10); // randomly picked
+ header.setAck_required(false);
+ header.setRes_required(false);
+ header.setSequence(0);
+ header.setType(58);
+ byte[] headerBytes = header.getHeaderBytes();
+
+ for (int i = 0; i < 36; i++) {
+ packetBytes[i] = headerBytes[i];
+ }
+
+ for (int i = 0; i < 64; i++) {
+ packetBytes[i + 36] = data[i];
+ }
+
+ sendPacket(packetBytes);
+ }
+
+
+ /*******************************************************************************************************************************************
+ ** Receiving
+ ** Device Messages
+ **
+ *******************************************************************************************************************************************/
+ private DeviceStateService parseDeviceStateServiceMessage(LifxHeader header, byte[] payloadData) {
+ int service = payloadData[0];
+ long port = ((payloadData[3] & 0xFF) << 24);
+ port |= ((payloadData[2] & 0xFF) << 16);
+ port |= ((payloadData[1] & 0xFF) << 8);
+ port |= (payloadData[0] & 0xFF);
+
+ return new DeviceStateService(service, port);
+ }
+
+ private DeviceStateHostInfo parseDeviceStateHostInfoMessage(LifxHeader header, byte[] payloadData) {
+ long signal = ((payloadData[3] & 0xFF) << 24);
+ signal |= ((payloadData[2] & 0xFF) << 16);
+ signal |= ((payloadData[1] & 0xFF) << 8);
+ signal |= (payloadData[0] & 0xFF);
+
+ long tx = ((payloadData[7] & 0xFF) << 24);
+ tx |= ((payloadData[6] & 0xFF) << 16);
+ tx |= ((payloadData[5] & 0xFF) << 8);
+ tx |= (payloadData[4] & 0xFF);
+
+ long rx = ((payloadData[11] & 0xFF) << 24);
+ rx |= ((payloadData[10] & 0xFF) << 16);
+ rx |= ((payloadData[9] & 0xFF) << 8);
+ rx |= (payloadData[8] & 0xFF);
+
+ return new DeviceStateHostInfo(signal, tx, rx);
+ }
+
+ private DeviceStateHostFirmware parseDeviceStateHostFirmwareMessage(LifxHeader header, byte[] payloadData) {
+ long build = 0;
+ for (int i = 0; i < 8; i++) {
+ build += ((long) payloadData[i] & 0xffL) << (8 * i);
+ }
+
+ // 8 reserved bytes
+
+ long version = ((payloadData[19] & 0xFF) << 24);
+ version |= ((payloadData[18] & 0xFF) << 16);
+ version |= ((payloadData[17] & 0xFF) << 8);
+ version |= (payloadData[16] & 0xFF);
+
+ return new DeviceStateHostFirmware(build, version);
+ }
+
+ private DeviceStateWifiInfo parseDeviceStateWifiInfoMessage(LifxHeader header, byte[] payloadData) {
+ long signal = ((payloadData[3] & 0xFF) << 24);
+ signal |= ((payloadData[2] & 0xFF) << 16);
+ signal |= ((payloadData[1] & 0xFF) << 8);
+ signal |= (payloadData[0] & 0xFF);
+
+ long tx = ((payloadData[7] & 0xFF) << 24);
+ tx |= ((payloadData[6] & 0xFF) << 16);
+ tx |= ((payloadData[5] & 0xFF) << 8);
+ tx |= (payloadData[4] & 0xFF);
+
+ long rx = ((payloadData[11] & 0xFF) << 24);
+ rx |= ((payloadData[10] & 0xFF) << 16);
+ rx |= ((payloadData[9] & 0xFF) << 8);
+ rx |= (payloadData[8] & 0xFF);
+
+ return new DeviceStateWifiInfo(signal, tx, rx);
+ }
+
+ private DeviceStateWifiFirmware parseDeviceStateWifiFirmwareMessage(LifxHeader header, byte[] payloadData) {
+ long build = 0;
+ for (int i = 0; i < 8; i++) {
+ build += ((long) payloadData[i] & 0xffL) << (8 * i);
+ }
+
+ // 8 reserved bytes
+
+ long version = ((payloadData[19] & 0xFF) << 24);
+ version |= ((payloadData[18] & 0xFF) << 16);
+ version |= ((payloadData[17] & 0xFF) << 8);
+ version |= (payloadData[16] & 0xFF);
+
+ return new DeviceStateWifiFirmware(build, version);
+ }
+
+ private int parseStatePowerMessage(LifxHeader header, byte[] payloadData) {
+ int level = ((payloadData[1] & 0xFF) << 8);
+ level |= (payloadData[0] & 0xFF);
+ return level;
+ }
+
+ private String parseStateLabelMessage(LifxHeader header, byte[] payloadData) {
+ return new String(payloadData);
+ }
+
+
+ private DeviceStateVersion parseDeviceStateVersionMessage(LifxHeader header, byte[] payloadData) {
+ long vender = ((payloadData[3] & 0xFF) << 24);
+ vender |= ((payloadData[2] & 0xFF) << 16);
+ vender |= ((payloadData[1] & 0xFF) << 8);
+ vender |= (payloadData[0] & 0xFF);
+
+ long product = ((payloadData[7] & 0xFF) << 24);
+ product |= ((payloadData[6] & 0xFF) << 16);
+ product |= ((payloadData[5] & 0xFF) << 8);
+ product |= (payloadData[4] & 0xFF);
+
+ long version = ((payloadData[11] & 0xFF) << 24);
+ version |= ((payloadData[10] & 0xFF) << 16);
+ version |= ((payloadData[9] & 0xFF) << 8);
+ version |= (payloadData[8] & 0xFF);
+
+ return new DeviceStateVersion(vender, product, version);
+ }
+
+ private DeviceStateInfo parseDeviceStateInfoMessage(LifxHeader header, byte[] payloadData) {
+ long time = 0;
+ long upTime = 0;
+ long downTime = 0;
+ for (int i = 0; i < 8; i++) {
+ time += ((long) payloadData[i] & 0xffL) << (8 * i);
+ upTime += ((long) payloadData[i + 8] & 0xffL) << (8 * i);
+ downTime += ((long) payloadData[i + 16] & 0xffL) << (8 * i);
+ }
+
+ return new DeviceStateInfo(time, upTime, downTime);
+ }
+
+ private DeviceStateLocation parseDeviceStateLocationMessage(LifxHeader header, byte[] payloadData) {
+ byte[] location = new byte[16];
+ for (int i = 0; i < 16; i++) {
+ location[i] = payloadData[i];
+ }
+
+ byte[] labelBytes = new byte[32];
+ for (int i = 0; i < 32; i++) {
+ labelBytes[i] = payloadData[i + 16];
+ }
+
+ long updatedAt = 0;
+ for (int i = 0; i < 8; i++) {
+ updatedAt += ((long) payloadData[48] & 0xffL) << (8 * i);
+ }
+
+ return new DeviceStateLocation(location, new String(labelBytes), updatedAt);
+ }
+
+ private DeviceStateGroup parseDeviceStateGroupMessage(LifxHeader header, byte[] payloadData) {
+ byte[] group = new byte[16];
+ for (int i = 0; i < 16; i++) {
+ group[i] = payloadData[i];
+ }
+
+ byte[] labelBytes = new byte[32];
+ for (int i = 0; i < 32; i++) {
+ labelBytes[i] = payloadData[i + 16];
+ }
+
+ long updatedAt = 0;
+ for (int i = 0; i < 8; i++) {
+ updatedAt += ((long) payloadData[48] & 0xffL) << (8 * i);
+ }
+
+ return new DeviceStateGroup(group, new String(labelBytes), updatedAt);
+ }
+
+ private byte[] parseDeviceEchoResponseMessage(LifxHeader header, byte[] payloadData) {
+ return payloadData;
+ }
+
+ /*******************************************************************************************************************************************
+ ** Receiving
+ ** Light Messages
+ **
+ *******************************************************************************************************************************************/
+ private LightState parseLightStateMessage(LifxHeader header, byte[] payloadData) {
+
+ byte[] colorData = new byte[8];
+ for (int i = 0; i < 8; i++) {
+ colorData[i] = payloadData[i];
+ }
+ BulbColor color = new BulbColor(colorData);
+
+ int power = ((payloadData[11] & 0xFF) << 8);
+ power |= (payloadData[10] & 0xFF);
+
+ String label = new String(payloadData);
+
+ byte[] labelArray = new byte[32];
+ for (int i = 0; i < 32; i++) {
+ labelArray[i] = payloadData[12 + i];
+ }
+
+ return new LightState(color, power, label);
+ }
+
+ private int parseLightStatePowerMessage(LifxHeader header, byte[] payloadData) {
+ int level = ((payloadData[1] & 0xFF) << 8);
+ level |= (payloadData[0] & 0xFF);
+ return level;
+ }
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** Private Handlers
+ **
+ *******************************************************************************************************************************************/
+ private void handleStateVersionMessageRecieved(LifxHeader header, byte[] payloadData) {
+
+ DeviceStateVersion deviceState = parseDeviceStateVersionMessage(header, payloadData);
+ int productNumber = (int)deviceState.getProduct();
+
+ boolean isColor = false;
+
+ if (productNumber == 1) {// Original 1000
+ isColor = true;
+ } else if (productNumber == 3) {//Color 650
+ isColor = true;
+ } else if (productNumber == 10) {// White 800 (Low Voltage)
+ isColor = false;
+ } else if (productNumber == 11) {// White 800 (High Voltage)
+ isColor = false;
+ } else if (productNumber == 18) {// White 900 BR30 (Low Voltage)
+ isColor = false;
+ } else if (productNumber == 20) {// Color 1000 BR30
+ isColor = true;
+ } else if (productNumber == 22) {// Color 1000
+ isColor = true;
+ }
+
+ if (isColor) {
+ hueLowerBound = 0;
+ hueUpperBound = 65535;
+ saturationLowerBound = 0;
+ saturationUpperBound = 65535;
+ brightnessLowerBound = 0;
+ brightnessUpperBound = 65535;
+ temperatureLowerBound = 2500;
+ temperatureUpperBound = 9000;
+ } else {
+ hueLowerBound = 0;
+ hueUpperBound = 0;
+ saturationLowerBound = 0;
+ saturationUpperBound = 0;
+ brightnessLowerBound = 0;
+ brightnessUpperBound = 65535;// still can dim bulb
+ temperatureLowerBound = 2500;
+ temperatureUpperBound = 9000;
+ }
+
+ didGetBulbVersion.set(true);
+
+ }
+
+ private void handleLightStateMessageRecieved(LifxHeader header, byte[] payloadData) {
+ LightState lightState = parseLightStateMessage(header, payloadData);
+
+ BulbColor color = lightState.getColor();
+ int power = lightState.getPower();
+
+ boolean bulbWrongColor = false;
+ bulbWrongColor = bulbWrongColor || (color.getHue() != currentHue);
+ bulbWrongColor = bulbWrongColor || (color.getSaturation() != currentSaturation);
+ bulbWrongColor = bulbWrongColor || (color.getBrightness() != currentBrightness);
+ bulbWrongColor = bulbWrongColor || (color.getKelvin() != currentTemperature);
+
+
+ // gets set to true if any of the below if statements are taken
+ stateDidChange = false;
+
+ if (bulbWrongColor) {
+ BulbColor newColor = new BulbColor(currentHue, currentSaturation, currentBrightness, currentTemperature);
+ sendSetLightColorPacket(newColor, 250);
+ // System.out.println("Failed Check 1");
+ }
+
+ try {
+ bulbStateMutex.acquire();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ boolean bulbIsOnTmp = bulbIsOn;
+ bulbStateMutex.release();
+
+ if ((!bulbIsOnTmp) && (power != 0)) {
+ turnOff();
+ // System.out.println("Failed Check 2: " + Integer.toString(power));
+
+ }
+
+ if (bulbIsOnTmp && (power < 65530)) {
+ turnOn();
+ // System.out.println("Failed Check 3: " + Integer.toString(power));
+
+ }
+ }
+
+ /*******************************************************************************************************************************************
+ **
+ ** Light Bulb Interface Methods
+ **
+ *******************************************************************************************************************************************/
+ public double getHue() {
+ double tmp = 0;
+ try {
+ settingBulbColorMutex.acquire();
+ tmp = ((double)currentHue / 65535.0) * 360.0;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ settingBulbColorMutex.release();
+
+
+ return tmp;
+ }
+
+ public double getSaturation() {
+ double tmp = 0;
+ try {
+ settingBulbColorMutex.acquire();
+ tmp = ((double)currentSaturation / 65535.0) * 360.0;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ settingBulbColorMutex.release();
+
+
+ return tmp;
+ }
+
+ public double getBrightness() {
+ double tmp = 0;
+ try {
+ settingBulbColorMutex.acquire();
+ tmp = ((double)currentBrightness / 65535.0) * 360.0;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ settingBulbColorMutex.release();
+
+ return tmp;
+ }
+
+ public int getTemperature() {
+
+ int tmp = 0;
+ try {
+ settingBulbTempuraturerMutex.acquire();
+ tmp = currentTemperature;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ settingBulbTempuraturerMutex.release();
+
+ return tmp;
+ }
+
+ public double getHueRangeLowerBound() {
+ if (!didGetBulbVersion.get()) {
+ return -1;
+ }
+ return ((double)hueLowerBound / 65535.0) * 360.0;
+ }
+
+ public double getHueRangeUpperBound() {
+ if (!didGetBulbVersion.get()) {
+ return -1;
+ }
+ return ((double)hueUpperBound / 65535.0) * 360.0;
+ }
+
+ public double getSaturationRangeLowerBound() {
+ if (!didGetBulbVersion.get()) {
+ return -1;
+ }
+ return ((double)saturationLowerBound / 65535.0) * 100.0;
+ }
+
+ public double getSaturationRangeUpperBound() {
+ if (!didGetBulbVersion.get()) {
+ return -1;
+ }
+ return ((double)saturationUpperBound / 65535.0) * 100.0;
+ }
+
+ public double getBrightnessRangeLowerBound() {
+ if (!didGetBulbVersion.get()) {
+ return -1;
+ }
+ return ((double)brightnessLowerBound / 65535.0) * 100.0;
+ }
+
+ public double getBrightnessRangeUpperBound() {
+ if (!didGetBulbVersion.get()) {
+ return -1;
+ }
+ return ((double)brightnessUpperBound / 65535.0) * 100.0;
+ }
+
+ public int getTemperatureRangeLowerBound() {
+ if (!didGetBulbVersion.get()) {
+ return -1;
+ }
+ return temperatureLowerBound;
+ }
+
+ public int getTemperatureRangeUpperBound() {
+ if (!didGetBulbVersion.get()) {
+ return -1;
+ }
+ return temperatureUpperBound;
+ }
+
+ public void setTemperature(int _temperature) {
+
+ try {
+ settingBulbTempuraturerMutex.acquire();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ BulbColor newColor = new BulbColor(currentHue, currentSaturation, currentBrightness, _temperature);
+ sendSetLightColorPacket(newColor, 250);
+
+ currentTemperature = _temperature;
+ stateDidChange = true;
+
+ settingBulbTempuraturerMutex.release();
+ }
+
+ public void setColor(double _hue, double _saturation, double _brightness) {
+
+ try {
+ settingBulbColorMutex.acquire();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ _hue /= 360.0;
+ _saturation /= 100.0;
+ _brightness /= 100.0;
+
+
+ int newHue = (int)(_hue * 65535.0);
+ int newSaturation = (int)(_saturation * 65535.0);
+ int newBrightness = (int)(_brightness * 65535.0);
+
+ BulbColor newColor = new BulbColor(newHue, newSaturation, newBrightness, currentTemperature);
+ sendSetLightColorPacket(newColor, 250);
+
+ currentHue = newHue;
+ currentSaturation = newSaturation;
+ currentBrightness = newBrightness;
+ stateDidChange = true;
+
+ settingBulbColorMutex.release();
+ }
+
+
+ public void turnOff() {
+
+ try {
+ bulbStateMutex.acquire();
+ bulbIsOn = false;
+ sendSetLightPowerPacket(0, 0);
+ stateDidChange = true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ bulbStateMutex.release();
+ }
+
+ public void turnOn() {
+ try {
+ bulbStateMutex.acquire();
+ bulbIsOn = true;
+ sendSetLightPowerPacket(65535, 0);
+ stateDidChange = true;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+
+ bulbStateMutex.release();
+ }
+
+ public boolean getState() {
+
+ boolean tmp = false;
+ try {
+ bulbStateMutex.acquire();
+ tmp = bulbIsOn;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ bulbStateMutex.release();
+
+ return tmp;
+ }
+
+
+ /*******************************************************************************************************************************************
+ **
+ ** Communication Helpers
+ **
+ *******************************************************************************************************************************************/
+ private void recievedPacket(byte[] packetData) {
+
+ byte[] headerBytes = new byte[36];
+ for (int i = 0; i < 36; i++) {
+ headerBytes[i] = packetData[i];
+ }
+
+ LifxHeader recHeader = new LifxHeader();
+ recHeader.setFromBytes(headerBytes);
+
+ // load the payload bytes (strip away the header)
+ byte[] payloadBytes = new byte[recHeader.getSize()];
+ for (int i = 36; i < recHeader.getSize(); i++) {
+ payloadBytes[i - 36] = packetData[i];
+ }
+
+ System.out.println("Received: " + Integer.toString(recHeader.getType()));
+
+ switch (recHeader.getType()) {
+ case 3:
+ DeviceStateService dat = parseDeviceStateServiceMessage(recHeader, payloadBytes);
+ // System.out.println("Service: " + Integer.toString(dat.getService()));
+ // System.out.println("Port : " + Long.toString(dat.getPort()));
+ break;
+
+
+ case 33:
+ handleStateVersionMessageRecieved(recHeader, payloadBytes);
+ break;
+
+ case 35:
+ parseDeviceStateInfoMessage(recHeader, payloadBytes);
+ break;
+
+
+ case 107:
+ handleLightStateMessageRecieved(recHeader, payloadBytes);
+ break;
+
+ default:
+ // System.out.println("unknown packet Type");
+ }
+
+ }
+
+ private void sendPacket(byte[] packetData) {
+ // System.out.println("About to send");
+ sendSocketFlag = true;
+
+ try {
+ socketMutex.acquire();
+ } catch (InterruptedException e) {
+ System.out.println("mutex Error");
+ }
+
+ try {
+ communicationSockect.sendData(packetData);
+
+ } catch (IOException e) {
+ System.out.println("Socket Send Error");
+ }
+
+ sendSocketFlag = false;
+ socketMutex.release();
+ }
+
+
+ /**
+ * Worker function which runs the while loop for receiving data from the bulb.
+ * Is blocking
+ */
+ private void workerFunction() {
+ LifxHeader h = new LifxHeader();
+
+ try {
+ // Need timeout on receives since we are not sure if a packet will be available
+ // for processing so don't block waiting
+ communicationSockect.setSoTimeout(50);
+ } catch (IOException e) {
+ }
+
+ // Start the bulb in the off state
+ turnOff();
+
+ while (true) {
+
+ // Check if we got the bulb version yet
+ // could have requested it but message could have gotten lost (UDP)
+ if (!didGetBulbVersion.get()) {
+ long currentTime = (new Date().getTime()) / 1000;
+ if ((currentTime - lastSentGetBulbVersionRequest) > GET_BULB_VERSION_RESEND_WAIT_SECONDS) {
+ // Get the bulb version so we know what type of bulb this is.
+ sendGetVersionPacket();
+ lastSentGetBulbVersionRequest = currentTime;
+ }
+ }
+
+ // Communication resource is busy so try again later
+ if (sendSocketFlag) {
+ continue;
+ }
+
+ try {
+ socketMutex.acquire();
+ } catch (InterruptedException e) {
+ }
+
+ byte[] dat = null;
+ try {
+ dat = communicationSockect.recieveData(1024);
+ } catch (java.net.SocketTimeoutException e) {
+ // Timeout occurred
+
+ } catch (IOException e) {
+ // Problem but might be able to recover??
+ e.printStackTrace();
+
+ }
+
+ // Never forget to release!
+ socketMutex.release();
+
+ // A packed arrived
+ if (dat != null) {
+ recievedPacket(dat);
+ }
+
+ // If a state change occurred then request the bulb state to ensure that the
+ // bulb did indeed change its state to the correct state
+ if (stateDidChange) {
+ sendGetLightStatePacket();
+ }
+
+ // Wait a bit as to not tie up system resources
+ try {
+ Thread.sleep(100);
+ } catch (Exception e) {
+
+ }
+
+
+ }
+ }
+
+
+ public void init() {
+
+ if (didAlreadyInit.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ try {
+ // Get the bulb address from the IoTSet
+ Iterator itr = lb_addresses.iterator();
+ IoTDeviceAddress deviceAddress = (IoTDeviceAddress)itr.next();
+
+ System.out.println("Address: " + deviceAddress.getCompleteAddress());
+
+ // Create the communication channel
+ communicationSockect = new IoTUDP(deviceAddress);
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ // Launch the worker function in a separate thread.
+ workerThread = new Thread(new Runnable() {
+ public void run() {
+ workerFunction();
+ }
+ });
+ workerThread.start();
+
+ }
+
+
+ /*public static void main(String[] args) throws Exception {
+
+ System.out.println("Executing main function!");
+ IoTDeviceAddress iotDevAdd = new IoTDeviceAddress("192.168.2.126", 12345, 56700, false, false);
+ Set<IoTDeviceAddress> set = new HashSet<IoTDeviceAddress>();
+ set.add(iotDevAdd);
+ IoTSet<IoTDeviceAddress> iotset = new IoTSet<IoTDeviceAddress>(set);
+ LifxLightBulb lb = new LifxLightBulb(iotset, "D073D5128E300000");
+ lb.init();
+ }*/
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+package iotcode.LifxLightBulb;
+
+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.LightBulb;
+
+public class LightBulb_Skeleton implements LightBulb {
+
+ private LightBulb mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private final static int object0Id = 0; //LightBulbSmart
+ private static Integer[] object0Permission = { 2, 10, 1, 3, 11, 8, 12, 7, 13, 9, 6, 16, 17, 4, 0, 14, 15, 5 };
+ private static List<Integer> set0Allowed;
+
+
+ public LightBulb_Skeleton(LightBulb _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public void turnOff() {
+ mainObj.turnOff();
+ }
+
+ public void turnOn() {
+ mainObj.turnOn();
+ }
+
+ public boolean getState() {
+ return mainObj.getState();
+ }
+
+ public void setColor(double _hue, double _saturation, double _brightness) {
+ mainObj.setColor(_hue, _saturation, _brightness);
+ }
+
+ public void setTemperature(int _temperature) {
+ mainObj.setTemperature(_temperature);
+ }
+
+ public double getBrightness() {
+ return mainObj.getBrightness();
+ }
+
+ public double getHue() {
+ return mainObj.getHue();
+ }
+
+ public double getSaturation() {
+ return mainObj.getSaturation();
+ }
+
+ public int getTemperature() {
+ return mainObj.getTemperature();
+ }
+
+ public double getBrightnessRangeLowerBound() {
+ return mainObj.getBrightnessRangeLowerBound();
+ }
+
+ public double getBrightnessRangeUpperBound() {
+ return mainObj.getBrightnessRangeUpperBound();
+ }
+
+ public double getHueRangeLowerBound() {
+ return mainObj.getHueRangeLowerBound();
+ }
+
+ public double getHueRangeUpperBound() {
+ return mainObj.getHueRangeUpperBound();
+ }
+
+ public double getSaturationRangeLowerBound() {
+ return mainObj.getSaturationRangeLowerBound();
+ }
+
+ public double getSaturationRangeUpperBound() {
+ return mainObj.getSaturationRangeUpperBound();
+ }
+
+ public int getTemperatureRangeLowerBound() {
+ return mainObj.getTemperatureRangeLowerBound();
+ }
+
+ public int getTemperatureRangeUpperBound() {
+ return mainObj.getTemperatureRangeUpperBound();
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___turnOff() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ turnOff();
+ }
+
+ public void ___turnOn() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ turnOn();
+ }
+
+ public void ___getState() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getState();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___setColor() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { double.class, double.class, double.class },
+ new Class<?>[] { null, null, null });
+ setColor((double) paramObj[0], (double) paramObj[1], (double) paramObj[2]);
+ }
+
+ public void ___setTemperature() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ setTemperature((int) paramObj[0]);
+ }
+
+ public void ___getBrightness() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getBrightness();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getHue() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getHue();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getSaturation() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getSaturation();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getTemperature() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getTemperature();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getBrightnessRangeLowerBound() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getBrightnessRangeLowerBound();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getBrightnessRangeUpperBound() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getBrightnessRangeUpperBound();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getHueRangeLowerBound() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getHueRangeLowerBound();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getHueRangeUpperBound() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getHueRangeUpperBound();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getSaturationRangeLowerBound() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getSaturationRangeLowerBound();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getSaturationRangeUpperBound() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getSaturationRangeUpperBound();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getTemperatureRangeLowerBound() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getTemperatureRangeLowerBound();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getTemperatureRangeUpperBound() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getTemperatureRangeUpperBound();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___turnOff(); break;
+ case 2: ___turnOn(); break;
+ case 3: ___getState(); break;
+ case 4: ___setColor(); break;
+ case 5: ___setTemperature(); break;
+ case 6: ___getBrightness(); break;
+ case 7: ___getHue(); break;
+ case 8: ___getSaturation(); break;
+ case 9: ___getTemperature(); break;
+ case 10: ___getBrightnessRangeLowerBound(); break;
+ case 11: ___getBrightnessRangeUpperBound(); break;
+ case 12: ___getHueRangeLowerBound(); break;
+ case 13: ___getHueRangeUpperBound(); break;
+ case 14: ___getSaturationRangeLowerBound(); break;
+ case 15: ___getSaturationRangeUpperBound(); break;
+ case 16: ___getTemperatureRangeLowerBound(); break;
+ case 17: ___getTemperatureRangeUpperBound(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+package iotcode.LifxLightBulb;
+
+public class LightState {
+ private final BulbColor color;
+ private final int power;
+ private final String label;
+
+ public LightState(BulbColor _color, int _power, String _label) {
+ color = _color;
+ power = _power;
+ label = _label;
+ }
+
+ public BulbColor getColor() {
+ return color;
+ }
+
+ public int getPower() {
+ return power;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+}
--- /dev/null
+BASE = ../../..
+
+include $(BASE)/common.mk
+
+BOOFDIR := ../libs/boofcv_libs
+BOOFJARS := $(BOOFDIR)/BoofCV-feature-0.21.jar:$(BOOFDIR)/BoofCV-io-0.21.jar:$(BOOFDIR)/BoofCV-visualize-0.21.jar:$(BOOFDIR)/BoofCV-ip-0.21.jar
+JLAYERDIR := ../libs/jlayer_libs
+JLAYERJARS := $(JLAYERDIR)/jl1.0.1.jar
+JFLAGS = -d $(BIN_DIR) -cp $(BIN_DIR):$(PHONEJARS):$(BOOFJARS):$(JLAYERJARS)
+JARFLAGS = cf
+INTFACE_DIR = iotcode/interfaces
+
+all: light camera labroom greenlawn sprinkler moisture weathergateway audioroom gpsgateway ihome homeroom alarm motion multipurpose waterleak
+
+# Compile
+#
+PHONY += light
+light:
+ $(JAVAC) $(JFLAGS) LifxLightBulb/*.java
+ cp LifxLightBulb/LifxLightBulb.config $(BIN_DIR)/iotcode/LifxLightBulb
+ cd $(BIN_DIR)/iotcode/LifxLightBulb; $(JAR) $(JARFLAGS) LifxLightBulb.jar ../../iotcode/LifxLightBulb/*.class ../../iotcode/interfaces/LightBulb*.class
+
+PHONY += camera
+camera:
+ $(JAVAC) $(JFLAGS) AmcrestCamera/*.java
+ cp AmcrestCamera/AmcrestCamera.config $(BIN_DIR)/iotcode/AmcrestCamera
+ cd $(BIN_DIR)/iotcode/AmcrestCamera; $(JAR) $(JARFLAGS) AmcrestCamera.jar ../../iotcode/AmcrestCamera/*.class ../../iotcode/interfaces/Camera*.class ../../iotcode/interfaces/Resolution*.class
+
+PHONY += labroom
+labroom:
+ $(JAVAC) $(JFLAGS) LabRoom/*.java
+ cp LabRoom/LabRoom.config $(BIN_DIR)/iotcode/LabRoom
+ cd $(BIN_DIR)/iotcode/LabRoom; $(JAR) $(JARFLAGS) LabRoom.jar ../../iotcode/LabRoom/*.class ../../iotcode/interfaces/Room*.class
+
+PHONY += greenlawn
+greenlawn:
+ $(JAVAC) $(JFLAGS) GreenLawn/*.java
+ cp GreenLawn/GreenLawn.config $(BIN_DIR)/iotcode/GreenLawn
+ cd $(BIN_DIR)/iotcode/GreenLawn; $(JAR) $(JARFLAGS) GreenLawn.jar ../../iotcode/GreenLawn/*.class ../../iotcode/interfaces/Lawn*.class
+
+PHONY += sprinkler
+sprinkler:
+ $(JAVAC) $(JFLAGS) EspSprinkler/*.java
+ cp EspSprinkler/EspSprinkler.config $(BIN_DIR)/iotcode/EspSprinkler
+ cd $(BIN_DIR)/iotcode/EspSprinkler; $(JAR) $(JARFLAGS) EspSprinkler.jar ../../iotcode/EspSprinkler/*.class ../../iotcode/interfaces/Sprinkler*.class ../../iotcode/interfaces/ZoneState*.class
+
+PHONY += moisture
+moisture:
+ $(JAVAC) $(JFLAGS) SpruceSensor/*.java
+ cp SpruceSensor/SpruceSensor.config $(BIN_DIR)/iotcode/SpruceSensor
+ cd $(BIN_DIR)/iotcode/SpruceSensor; $(JAR) $(JARFLAGS) SpruceSensor.jar ../../iotcode/SpruceSensor/*.class ../../iotcode/interfaces/MoistureSensor*.class ../../iotcode/interfaces/Camera*.class ../../IrrigationController/MotionDetection*.class
+
+PHONY += weathergateway
+weathergateway:
+ $(JAVAC) $(JFLAGS) WeatherPhoneGateway/*.java
+ 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 += homeroom
+homeroom:
+ $(JAVAC) $(JFLAGS) HomeRoom/*.java
+ cp HomeRoom/HomeRoom.config $(BIN_DIR)/iotcode/HomeRoom
+ cd $(BIN_DIR)/iotcode/HomeRoom; $(JAR) $(JARFLAGS) HomeRoom.jar ../../iotcode/HomeRoom/*.class ../../iotcode/interfaces/Room*.class
+
+PHONY += alarm
+alarm:
+ $(JAVAC) $(JFLAGS) EspAlarm/*.java
+ cp EspAlarm/EspAlarm.config $(BIN_DIR)/iotcode/EspAlarm
+ cd $(BIN_DIR)/iotcode/EspAlarm; $(JAR) $(JARFLAGS) EspAlarm.jar ../../iotcode/EspAlarm/*.class ../../iotcode/interfaces/Alarm*.class ../../iotcode/interfaces/ZoneState*.class
+
+PHONY += motion
+motion:
+ $(JAVAC) $(JFLAGS) MotionSensor/*.java
+ cp MotionSensor/MotionSensor.config $(BIN_DIR)/iotcode/MotionSensor
+ cd $(BIN_DIR)/iotcode/MotionSensor; $(JAR) $(JARFLAGS) MotionSensor.jar ../../iotcode/MotionSensor/*.class ../../iotcode/interfaces/SmartthingsSensor*.class ../../iotcode/interfaces/Camera*.class ../../IrrigationController/MotionDetection*.class
+
+PHONY += multipurpose
+multipurpose:
+ $(JAVAC) $(JFLAGS) MultipurposeSensor/*.java
+ cp MultipurposeSensor/MultipurposeSensor.config $(BIN_DIR)/iotcode/MultipurposeSensor
+ cd $(BIN_DIR)/iotcode/MultipurposeSensor; $(JAR) $(JARFLAGS) MultipurposeSensor.jar ../../iotcode/MultipurposeSensor/*.class ../../iotcode/interfaces/SmartthingsSensor*.class ../../iotcode/interfaces/Camera*.class ../../IrrigationController/MotionDetection*.class
+
+PHONY += waterleak
+waterleak:
+ $(JAVAC) $(JFLAGS) WaterLeakSensor/*.java
+ cp WaterLeakSensor/WaterLeakSensor.config $(BIN_DIR)/iotcode/WaterLeakSensor
+ cd $(BIN_DIR)/iotcode/WaterLeakSensor; $(JAR) $(JARFLAGS) WaterLeakSensor.jar ../../iotcode/WaterLeakSensor/*.class ../../iotcode/interfaces/SmartthingsSensor*.class ../../iotcode/interfaces/Camera*.class ../../IrrigationController/MotionDetection*.class
+
+.PHONY: $(PHONY)
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=SmartthingsSensor
+# Stub
+INTERFACE_STUB_CLASS=SmartthingsSensorSmart
--- /dev/null
+package iotcode.MotionSensor;
+
+// Standard Java Packages
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Semaphore;
+
+// Checker annotations
+//import iotchecker.qual.*;
+import iotcode.annotation.*;
+
+// IoT Packages
+import iotruntime.slave.*;
+import iotcode.interfaces.*;
+import iotruntime.zigbee.*;
+
+/** Class Smartthings sensor driver for Smartthings sensor devices.
+ *
+ * @author Changwoo Lee, Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version 1.0
+ * @since 2016-12-01
+ */
+public class MotionSensor implements IoTZigbeeCallback, SmartthingsSensor {
+
+ private final int TIMEOUT_FOR_RESEND_MSEC = 900;
+
+ private IoTZigbee zigConnection = null;
+ private boolean didClose; // make sure that the clean up was done correctly
+ private boolean detectStatus = false;
+
+ private int detectedValue = 0;
+ private Date timestampOfLastDetecting = null;
+
+ private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
+ private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
+ private AtomicBoolean didWriteAttrb = new AtomicBoolean(false);
+ private AtomicBoolean didMatchDscr = new AtomicBoolean(false);
+ static Semaphore gettingLatestDataMutex = new Semaphore(1);
+
+ private List < SmartthingsSensorSmartCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorSmartCallback > ();
+
+ private int sensorId = 0;
+
+ @config private IoTSet<IoTDeviceAddress> motionSensorUdpAddress;
+ @config private IoTSet<IoTZigbeeAddress> motionSensorZigbeeAddress;
+
+ //public MotionSensor(IoTSet<IoTDeviceAddress> dSet, IoTSet<IoTZigbeeAddress> zigSet) {
+ //motionSensorUdpAddress = dSet;
+ //motionSensorZigbeeAddress = zigSet;
+ //}
+ public MotionSensor() {
+ }
+
+ public void init() {
+
+ if (didAlreadyInit.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyClose.set(false);
+
+ try {
+ Iterator itrUdp = motionSensorUdpAddress.iterator();
+ Iterator itrZig = motionSensorZigbeeAddress.iterator();
+
+ zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
+
+ // DEBUG
+ System.out.println("DEBUG: Allocate iterators to print out addresses!");
+ Iterator itrDebugUdp = motionSensorUdpAddress.iterator();
+ IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
+ System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
+ System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
+ System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
+
+ Iterator itrDebugZig = motionSensorZigbeeAddress.iterator();
+ IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
+ System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
+
+ zigConnection.registerCallback(this);
+ System.out.println("Register callback!");
+ zigConnection.init();
+ System.out.println("Initialized!");
+
+ //made by changwoo
+ sleep(10);
+
+ System.out.println("Sending Management Permit Joining Request");
+ for(int z=0; z<3; z++){
+ zigConnection.sendManagementPermitJoiningRequest(0x0001, 0x0036, 0x00);
+ sleep(0);
+ }
+
+ //made by changwoo
+ while (!didWriteAttrb.get()) {
+ System.out.println("Sending Write Attribute Request");
+ zigConnection.sendWriteAttributesCommand(0x0002, 0x0500, 0x0104, 0x01);
+ sleep(0);
+ }
+
+ //made by changwoo
+ System.out.println("Sending Enrollment Reponse");
+ zigConnection.sendEnrollmentResponse(0x0003, 0x0500, 0x0104, 0x01);
+ sleep(0);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ //made by changwoo
+ private void sleep(int multipleTime){
+ if(multipleTime<=0){
+ multipleTime=1;
+ }
+ try{
+ Thread.sleep(TIMEOUT_FOR_RESEND_MSEC*multipleTime);
+ } catch(Exception e){
+ e.printStackTrace();
+ }
+ }
+
+ public void close() {
+
+ if (didAlreadyClose.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyInit.set(false);
+
+
+ try {
+ zigConnection.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public void Finalize() {
+ if (!didClose) {
+ close();
+ }
+ }
+
+ public void setId(int id) {
+
+ sensorId = id;
+
+ }
+
+ public int getId() {
+
+ return sensorId;
+
+ }
+
+ public int getValue() {
+
+ int tmp = 0;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = detectedValue;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+
+ return tmp;
+ }
+
+ // MotionSensor:
+ // - 24 = no motion = false
+ // - 26 = motion = true
+ // After getting 26, if there is no motion for ~12 seconds then we get back 24
+ public boolean isActiveValue() {
+
+ int tmp = getValue();
+ if (tmp == 26)
+ detectStatus = true;
+ else // Getting 24 here
+ detectStatus = false;
+
+ return detectStatus;
+ }
+
+ public long getTimestampOfLastReading() {
+
+ Date tmp = null;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = (Date)timestampOfLastDetecting.clone();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+ long retLong = tmp.getTime();
+
+ return retLong;
+ }
+
+ public void newMessageAvailable(IoTZigbeeMessage _zm) {
+
+ //made by changwoo
+ if(_zm instanceof IoTZigbeeMessageZclZoneStatusChangeNotification){
+ IoTZigbeeMessageZclZoneStatusChangeNotification message = (IoTZigbeeMessageZclZoneStatusChangeNotification)_zm;
+ if(message.getSuccessOrFail()){
+ //do something!
+
+ try {
+ gettingLatestDataMutex.acquire();
+ detectedValue = message.getStatus();
+ timestampOfLastDetecting = new Date();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+ try {
+ for (SmartthingsSensorSmartCallback cb : callbackList) {
+ cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }//if
+
+ //made by changwoo
+ } else if (_zm instanceof IoTZigbeeMessageZclWriteAttributesResponse) {
+ IoTZigbeeMessageZclWriteAttributesResponse message = (IoTZigbeeMessageZclWriteAttributesResponse)_zm;
+ if (message.getSuccessOrFail()) {
+ didWriteAttrb.set(true);
+ }
+ }
+ }
+
+ public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
+ callbackList.add(_callbackTo);
+ }
+}
--- /dev/null
+package iotcode.MotionSensor;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensorSmartCallback_CallbackStub implements SmartthingsSensorSmartCallback {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private int objectId = 0;
+
+
+ public SmartthingsSensorSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ objectId = _objectId;
+ rmiCall = _rmiCall;
+ ports = _ports;
+ }
+
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int.class, int.class, boolean.class };
+ Object[] paramObj = new Object[] { _sensorId, _value, _activeValue };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+}
--- /dev/null
+package iotcode.MotionSensor;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensor_Skeleton implements SmartthingsSensor {
+
+ private SmartthingsSensor mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private int objIdCnt = 0;
+ private IoTRMICall rmiCall;
+ private int[] ports;
+
+ private final static int object0Id = 0; //SmartthingsSensorSmart
+ private static Integer[] object0Permission = { 3, 2, 5, 6, 1, 4, 0 };
+ private static List<Integer> set0Allowed;
+
+
+ public SmartthingsSensor_Skeleton(SmartthingsSensor _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ set0Allowed.add(-9998);
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public int getValue() {
+ return mainObj.getValue();
+ }
+
+ public boolean isActiveValue() {
+ return mainObj.isActiveValue();
+ }
+
+ public long getTimestampOfLastReading() {
+ return mainObj.getTimestampOfLastReading();
+ }
+
+ public void setId(int id) {
+ mainObj.setId(id);
+ }
+
+ public int getId() {
+ return mainObj.getId();
+ }
+
+ public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
+ mainObj.registerCallback(_callbackTo);
+ }
+
+ public void ___regCB() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
+ ports = (int[]) paramObj[0];
+ rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___getValue() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getValue();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___isActiveValue() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = isActiveValue();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getTimestampOfLastReading() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getTimestampOfLastReading();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___setId() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ setId((int) paramObj[0]);
+ }
+
+ public void ___getId() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getId();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___registerCallback() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ try {
+ SmartthingsSensorSmartCallback stub0 = new SmartthingsSensorSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
+ objIdCnt++;
+ registerCallback(stub0);
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Exception from callback object instantiation!");
+ }
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___getValue(); break;
+ case 2: ___isActiveValue(); break;
+ case 3: ___getTimestampOfLastReading(); break;
+ case 4: ___setId(); break;
+ case 5: ___getId(); break;
+ case 6: ___registerCallback(); break;
+ case -9998: ___regCB(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=SmartthingsSensor
+# Stub
+INTERFACE_STUB_CLASS=SmartthingsSensorSmart
--- /dev/null
+package iotcode.MultipurposeSensor;
+
+// Standard Java Packages
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Semaphore;
+
+// Checker annotations
+//import iotchecker.qual.*;
+import iotcode.annotation.*;
+
+// IoT Packages
+import iotruntime.slave.*;
+import iotcode.interfaces.*;
+import iotruntime.zigbee.*;
+
+/** Class Smartthings sensor driver for Smartthings sensor devices.
+ *
+ * @author Changwoo Lee, Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version 1.0
+ * @since 2016-12-01
+ */
+public class MultipurposeSensor implements IoTZigbeeCallback, SmartthingsSensor {
+
+ private final int TIMEOUT_FOR_RESEND_MSEC = 900;
+
+ private IoTZigbee zigConnection = null;
+ private boolean didClose; // make sure that the clean up was done correctly
+ private boolean detectStatus = false;
+
+ private int detectedValue = 0;
+ private Date timestampOfLastDetecting = null;
+
+ private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
+ private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
+ private AtomicBoolean didWriteAttrb = new AtomicBoolean(false);
+ private AtomicBoolean didMatchDscr = new AtomicBoolean(false);
+ static Semaphore gettingLatestDataMutex = new Semaphore(1);
+
+ private List < SmartthingsSensorSmartCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorSmartCallback > ();
+
+ private int sensorId = 0;
+
+ @config private IoTSet<IoTDeviceAddress> multipurposeSensorUdpAddress;
+ @config private IoTSet<IoTZigbeeAddress> multipurposeSensorZigbeeAddress;
+
+ //public MultipurposeSensor(IoTSet<IoTDeviceAddress> dSet, IoTSet<IoTZigbeeAddress> zigSet) {
+ //multipurposeSensorUdpAddress = dSet;
+ //multipurposeSensorZigbeeAddress = zigSet;
+ //}
+ public MultipurposeSensor() {
+ }
+
+ public void init() {
+
+ if (didAlreadyInit.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyClose.set(false);
+
+ try {
+ Iterator itrUdp = multipurposeSensorUdpAddress.iterator();
+ Iterator itrZig = multipurposeSensorZigbeeAddress.iterator();
+
+ zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
+
+ // DEBUG
+ System.out.println("DEBUG: Allocate iterators to print out addresses!");
+ Iterator itrDebugUdp = multipurposeSensorUdpAddress.iterator();
+ IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
+ System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
+ System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
+ System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
+
+ Iterator itrDebugZig = multipurposeSensorZigbeeAddress.iterator();
+ IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
+ System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
+
+ zigConnection.registerCallback(this);
+ System.out.println("Register callback!");
+ zigConnection.init();
+ System.out.println("Initialized!");
+
+ //made by changwoo
+ sleep(10);
+ System.out.println("Sending Management Permit Joining Request");
+ for(int z=0; z<3; z++){
+ zigConnection.sendManagementPermitJoiningRequest(0x0001, 0x0036, 0x00);
+ sleep(0);
+ }
+
+ //made by changwoo
+ while (!didWriteAttrb.get()) {
+ System.out.println("Sending Write Attribute Request");
+ zigConnection.sendWriteAttributesCommand(0x0002, 0x0500, 0x0104, 0x01);
+ sleep(0);
+ }
+
+ //made by changwoo
+ System.out.println("Sending Enrollment Reponse");
+ zigConnection.sendEnrollmentResponse(0x0003, 0x0500, 0x0104, 0x01);
+ sleep(0);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ //made by changwoo
+ private void sleep(int multipleTime){
+ if(multipleTime<=0){
+ multipleTime=1;
+ }
+ try{
+ Thread.sleep(TIMEOUT_FOR_RESEND_MSEC*multipleTime);
+ } catch(Exception e){
+ e.printStackTrace();
+ }
+ }
+
+ public void close() {
+
+ if (didAlreadyClose.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyInit.set(false);
+
+
+ try {
+ zigConnection.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void Finalize() {
+ if (!didClose) {
+ close();
+ }
+ }
+
+ public void setId(int id) {
+
+ sensorId = id;
+
+ }
+
+ public int getId() {
+
+ return sensorId;
+
+ }
+
+ public int getValue() {
+
+ int tmp = 0;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = detectedValue;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+
+ return tmp;
+ }
+
+ // MultipurposeSensor:
+ // - 24 = close = false
+ // - 25 = open = true
+ public boolean isActiveValue() {
+
+ int tmp = getValue();
+ if (tmp == 25)
+ detectStatus = true;
+ else // Getting 24 here
+ detectStatus = false;
+
+ return detectStatus;
+ }
+
+ public long getTimestampOfLastReading() {
+
+ Date tmp = null;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = (Date)timestampOfLastDetecting.clone();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+ long retLong = tmp.getTime();
+
+ return retLong;
+ }
+
+ public void newMessageAvailable(IoTZigbeeMessage _zm) {
+
+ //made by changwoo
+ if(_zm instanceof IoTZigbeeMessageZclZoneStatusChangeNotification){
+ IoTZigbeeMessageZclZoneStatusChangeNotification message = (IoTZigbeeMessageZclZoneStatusChangeNotification)_zm;
+ if(message.getSuccessOrFail()){
+ //do something!
+ try {
+ gettingLatestDataMutex.acquire();
+ detectedValue = message.getStatus();
+ timestampOfLastDetecting = new Date();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+ try {
+ for (SmartthingsSensorSmartCallback cb : callbackList) {
+ cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }//if
+
+ //made by changwoo
+ }//if
+ else if (_zm instanceof IoTZigbeeMessageZclWriteAttributesResponse) {
+ IoTZigbeeMessageZclWriteAttributesResponse message = (IoTZigbeeMessageZclWriteAttributesResponse)_zm;
+ if (message.getSuccessOrFail()) {
+ didWriteAttrb.set(true);
+ }//if
+ }//else if
+ }
+
+ public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
+ callbackList.add(_callbackTo);
+ }
+}
--- /dev/null
+package iotcode.MultipurposeSensor;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensorSmartCallback_CallbackStub implements SmartthingsSensorSmartCallback {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private int objectId = 0;
+
+
+ public SmartthingsSensorSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ objectId = _objectId;
+ rmiCall = _rmiCall;
+ ports = _ports;
+ }
+
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int.class, int.class, boolean.class };
+ Object[] paramObj = new Object[] { _sensorId, _value, _activeValue };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+}
--- /dev/null
+package iotcode.MultipurposeSensor;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensor_Skeleton implements SmartthingsSensor {
+
+ private SmartthingsSensor mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private int objIdCnt = 0;
+ private IoTRMICall rmiCall;
+ private int[] ports;
+
+ private final static int object0Id = 0; //SmartthingsSensorSmart
+ private static Integer[] object0Permission = { 3, 2, 5, 6, 1, 4, 0 };
+ private static List<Integer> set0Allowed;
+
+
+ public SmartthingsSensor_Skeleton(SmartthingsSensor _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ set0Allowed.add(-9998);
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public int getValue() {
+ return mainObj.getValue();
+ }
+
+ public boolean isActiveValue() {
+ return mainObj.isActiveValue();
+ }
+
+ public long getTimestampOfLastReading() {
+ return mainObj.getTimestampOfLastReading();
+ }
+
+ public void setId(int id) {
+ mainObj.setId(id);
+ }
+
+ public int getId() {
+ return mainObj.getId();
+ }
+
+ public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
+ mainObj.registerCallback(_callbackTo);
+ }
+
+ public void ___regCB() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
+ ports = (int[]) paramObj[0];
+ rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___getValue() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getValue();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___isActiveValue() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = isActiveValue();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getTimestampOfLastReading() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getTimestampOfLastReading();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___setId() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ setId((int) paramObj[0]);
+ }
+
+ public void ___getId() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getId();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___registerCallback() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ try {
+ SmartthingsSensorSmartCallback stub0 = new SmartthingsSensorSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
+ objIdCnt++;
+ registerCallback(stub0);
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Exception from callback object instantiation!");
+ }
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___getValue(); break;
+ case 2: ___isActiveValue(); break;
+ case 3: ___getTimestampOfLastReading(); break;
+ case 4: ___setId(); break;
+ case 5: ___getId(); break;
+ case 6: ___registerCallback(); break;
+ case -9998: ___regCB(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+package iotcode.SpruceSensor;
+
+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 MoistureSensorSmartCallback_CallbackStub implements MoistureSensorSmartCallback {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private int objectId = 0;
+
+
+ public MoistureSensorSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ objectId = _objectId;
+ rmiCall = _rmiCall;
+ ports = _ports;
+ }
+
+ public void newReadingAvailable(int sensorId, float moisture, long timeStampOfLastReading) {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int.class, float.class, long.class };
+ Object[] paramObj = new Object[] { sensorId, moisture, timeStampOfLastReading };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+}
--- /dev/null
+package iotcode.SpruceSensor;
+
+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 MoistureSensor_Skeleton implements MoistureSensor {
+
+ private MoistureSensor mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private int objIdCnt = 0;
+ private IoTRMICall rmiCall;
+ private int[] ports;
+
+ private final static int object0Id = 0; //MoistureSensorSmart
+ private static Integer[] object0Permission = { 2, 4, 5, 1, 3, 0 };
+ private static List<Integer> set0Allowed;
+
+
+ public MoistureSensor_Skeleton(MoistureSensor _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ set0Allowed.add(-9998);
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public float getMoisture() {
+ return mainObj.getMoisture();
+ }
+
+ public long getTimestampOfLastReading() {
+ return mainObj.getTimestampOfLastReading();
+ }
+
+ public void setId(int id) {
+ mainObj.setId(id);
+ }
+
+ public int getId() {
+ return mainObj.getId();
+ }
+
+ public void registerCallback(MoistureSensorSmartCallback _callbackTo) {
+ mainObj.registerCallback(_callbackTo);
+ }
+
+ public void ___regCB() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
+ ports = (int[]) paramObj[0];
+ rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___getMoisture() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getMoisture();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getTimestampOfLastReading() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getTimestampOfLastReading();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___setId() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ setId((int) paramObj[0]);
+ }
+
+ public void ___getId() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getId();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___registerCallback() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ try {
+ MoistureSensorSmartCallback stub0 = new MoistureSensorSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
+ objIdCnt++;
+ registerCallback(stub0);
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Exception from callback object instantiation!");
+ }
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___getMoisture(); break;
+ case 2: ___getTimestampOfLastReading(); break;
+ case 3: ___setId(); break;
+ case 4: ___getId(); break;
+ case 5: ___registerCallback(); break;
+ case -9998: ___regCB(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=MoistureSensor
+# Stub
+INTERFACE_STUB_CLASS=MoistureSensorSmart
--- /dev/null
+package iotcode.SpruceSensor;
+
+// Standard Java Packages
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Semaphore;
+
+
+// Checker annotations
+//import iotchecker.qual.*;
+
+// IoT Packages
+import iotruntime.slave.*;
+import iotcode.interfaces.MoistureSensor;
+import iotcode.interfaces.MoistureSensorSmartCallback;
+import iotruntime.zigbee.*;
+import iotcode.annotation.*;
+
+public class SpruceSensor implements IoTZigbeeCallback, MoistureSensor {
+
+ private final int TIMEOUT_FOR_RESEND_MSEC = 1000;
+
+ private IoTZigbee zigConnection = null;
+ private boolean didClose; // make sure that the clean up was done correctly
+
+ private float humidity = 0;
+ private Date timestampOfLastHumidity = null;
+
+ private AtomicBoolean didBind = new AtomicBoolean(false);
+ private AtomicBoolean didConfigureReporting = new AtomicBoolean(false);
+ private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
+ private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
+ static Semaphore gettingLatestDataMutex = new Semaphore(1);
+
+ private List < MoistureSensorSmartCallback > callbackList = new CopyOnWriteArrayList < MoistureSensorSmartCallback > ();
+
+ private int sensorId = 0;
+
+ @config private IoTSet<IoTDeviceAddress> devUdpAddress;
+ @config private IoTSet<IoTZigbeeAddress> devZigbeeAddress;
+
+ public SpruceSensor() {
+ }
+
+ public void init() {
+
+ if (didAlreadyInit.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyClose.set(false);
+
+ try {
+ Iterator itrUdp = devUdpAddress.iterator();
+ Iterator itrZig = devZigbeeAddress.iterator();
+
+ zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
+
+ // DEBUG
+ System.out.println("DEBUG: Allocate iterators to print out addresses!");
+ Iterator itrDebugUdp = devUdpAddress.iterator();
+ IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
+ System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
+ System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
+ System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
+
+ Iterator itrDebugZig = devZigbeeAddress.iterator();
+ IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
+ System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
+
+ zigConnection.registerCallback(this);
+ System.out.println("Register callback!");
+ zigConnection.init();
+ System.out.println("Initialized!");
+
+ while (!didBind.get()) {
+ zigConnection.sendBindRequest(0x0001, 0x0405, 0x01);
+ try {
+ Thread.sleep(TIMEOUT_FOR_RESEND_MSEC);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ while (!didConfigureReporting.get()) {
+ zigConnection.sendConfigureReportingCommand(0x0001, 0x0405, 0x0104, 0x01, 0x0000, 0x21, 0x0001, 0x0001, null);
+ try {
+ Thread.sleep(TIMEOUT_FOR_RESEND_MSEC);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void close() {
+
+ if (didAlreadyClose.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyInit.set(false);
+
+
+ try {
+ zigConnection.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void Finalize() {
+ if (!didClose) {
+ close();
+ }
+ }
+
+ public void setId(int id) {
+
+ sensorId = id;
+
+ }
+
+ public int getId() {
+
+ return sensorId;
+
+ }
+
+ public float getMoisture() {
+
+ float tmp = 0;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = humidity;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+
+ return tmp;
+ }
+
+ public long getTimestampOfLastReading() {
+
+ Date tmp = null;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = (Date)timestampOfLastHumidity.clone();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+ long retLong = tmp.getTime();
+
+ return retLong;
+ }
+
+ public void newMessageAvailable(IoTZigbeeMessage _zm) {
+
+ if (_zm instanceof IoTZigbeeMessageZdoBindResponse) {
+ IoTZigbeeMessageZdoBindResponse message = (IoTZigbeeMessageZdoBindResponse)_zm;
+ if (message.getSucceeded()) {
+ didBind.set(true);
+ }
+
+ } else if (_zm instanceof IoTZigbeeMessageZclConfigureReportingResponse) {
+ IoTZigbeeMessageZclConfigureReportingResponse message = (IoTZigbeeMessageZclConfigureReportingResponse)_zm;
+ if (message.getAllSuccess()) {
+ didConfigureReporting.set(true);
+ }
+
+ } else if (_zm instanceof IoTZigbeeMessageZclReportAttributes) {
+ IoTZigbeeMessageZclReportAttributes message = (IoTZigbeeMessageZclReportAttributes)_zm;
+ List <IoTZigbeeMessageZclReportAttributes.Attribute> attrList = message.getAttributes();
+
+ if (attrList.size() == 1) {
+ if (attrList.get(0).getAttributeId() == 0) {
+ byte[] data = attrList.get(0).getData();
+
+ int value = (data[0] * 256) + data[1];
+
+ try {
+ gettingLatestDataMutex.acquire();
+ humidity = (float)value / (float)100.0;
+ timestampOfLastHumidity = new Date();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+
+ try {
+ for (MoistureSensorSmartCallback cb : callbackList) {
+ cb.newReadingAvailable(this.getId(), this.getMoisture(), this.getTimestampOfLastReading());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ }
+ }
+
+ public void registerCallback(MoistureSensorSmartCallback _callbackTo) {
+ callbackList.add(_callbackTo);
+ }
+}
--- /dev/null
+package iotcode.WaterLeakSensor;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensorSmartCallback_CallbackStub implements SmartthingsSensorSmartCallback {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private int objectId = 0;
+
+
+ public SmartthingsSensorSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ objectId = _objectId;
+ rmiCall = _rmiCall;
+ ports = _ports;
+ }
+
+ public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { int.class, int.class, boolean.class };
+ Object[] paramObj = new Object[] { _sensorId, _value, _activeValue };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+}
--- /dev/null
+package iotcode.WaterLeakSensor;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import iotrmi.Java.IoTRMICall;
+import iotrmi.Java.IoTRMIObject;
+
+import iotcode.interfaces.*;
+
+public class SmartthingsSensor_Skeleton implements SmartthingsSensor {
+
+ private SmartthingsSensor mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private int objIdCnt = 0;
+ private IoTRMICall rmiCall;
+ private int[] ports;
+
+ private final static int object0Id = 0; //SmartthingsSensorSmart
+ private static Integer[] object0Permission = { 3, 2, 5, 6, 1, 4, 0 };
+ private static List<Integer> set0Allowed;
+
+
+ public SmartthingsSensor_Skeleton(SmartthingsSensor _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ set0Allowed.add(-9998);
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public int getValue() {
+ return mainObj.getValue();
+ }
+
+ public boolean isActiveValue() {
+ return mainObj.isActiveValue();
+ }
+
+ public long getTimestampOfLastReading() {
+ return mainObj.getTimestampOfLastReading();
+ }
+
+ public void setId(int id) {
+ mainObj.setId(id);
+ }
+
+ public int getId() {
+ return mainObj.getId();
+ }
+
+ public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
+ mainObj.registerCallback(_callbackTo);
+ }
+
+ public void ___regCB() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
+ ports = (int[]) paramObj[0];
+ rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___getValue() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getValue();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___isActiveValue() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = isActiveValue();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getTimestampOfLastReading() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getTimestampOfLastReading();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___setId() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ setId((int) paramObj[0]);
+ }
+
+ public void ___getId() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getId();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___registerCallback() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ try {
+ SmartthingsSensorSmartCallback stub0 = new SmartthingsSensorSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
+ objIdCnt++;
+ registerCallback(stub0);
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Exception from callback object instantiation!");
+ }
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___getValue(); break;
+ case 2: ___isActiveValue(); break;
+ case 3: ___getTimestampOfLastReading(); break;
+ case 4: ___setId(); break;
+ case 5: ___getId(); break;
+ case 6: ___registerCallback(); break;
+ case -9998: ___regCB(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=SmartthingsSensor
+# Stub
+INTERFACE_STUB_CLASS=SmartthingsSensorSmart
--- /dev/null
+package iotcode.WaterLeakSensor;
+
+// Standard Java Packages
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Semaphore;
+
+// Checker annotations
+//import iotchecker.qual.*;
+import iotcode.annotation.*;
+
+// IoT Packages
+import iotruntime.slave.*;
+import iotcode.interfaces.*;
+import iotruntime.zigbee.*;
+
+/** Class Smartthings sensor driver for Smartthings sensor devices.
+ *
+ * @author Changwoo Lee, Rahmadi Trimananda <rtrimana @ uci.edu>
+ * @version 1.0
+ * @since 2016-12-01
+ */
+public class WaterLeakSensor implements IoTZigbeeCallback, SmartthingsSensor {
+
+ private final int TIMEOUT_FOR_RESEND_MSEC = 900;
+
+ private IoTZigbee zigConnection = null;
+ private boolean didClose; // make sure that the clean up was done correctly
+ private boolean detectStatus = false;
+
+ private int detectedValue = 0;
+ private Date timestampOfLastDetecting = null;
+
+ private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
+ private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
+ private AtomicBoolean didWriteAttrb = new AtomicBoolean(false);
+ private AtomicBoolean didMatchDscr = new AtomicBoolean(false);
+ static Semaphore gettingLatestDataMutex = new Semaphore(1);
+
+ private List < SmartthingsSensorSmartCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorSmartCallback > ();
+
+ private int sensorId = 0;
+
+ @config private IoTSet<IoTDeviceAddress> waterleakSensorUdpAddress;
+ @config private IoTSet<IoTZigbeeAddress> waterleakSensorZigbeeAddress;
+
+ //public WaterLeakSensor(IoTSet<IoTDeviceAddress> dSet, IoTSet<IoTZigbeeAddress> zigSet) {
+ //waterleakSensorUdpAddress = dSet;
+ //waterleakSensorZigbeeAddress = zigSet;
+ //}
+ public WaterLeakSensor() {
+ }
+
+ public void init() {
+
+ if (didAlreadyInit.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyClose.set(false);
+
+ try {
+ Iterator itrUdp = waterleakSensorUdpAddress.iterator();
+ Iterator itrZig = waterleakSensorZigbeeAddress.iterator();
+
+ zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
+
+ // DEBUG
+ System.out.println("DEBUG: Allocate iterators to print out addresses!");
+ Iterator itrDebugUdp = waterleakSensorUdpAddress.iterator();
+ IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
+ System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
+ System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
+ System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
+
+ Iterator itrDebugZig = waterleakSensorZigbeeAddress.iterator();
+ IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
+ System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
+
+ zigConnection.registerCallback(this);
+ System.out.println("Register callback!");
+ zigConnection.init();
+ System.out.println("Initialized!");
+
+ //made by changwoo
+ sleep(10);
+ System.out.println("Sending Management Permit Joining Request");
+ for(int z=0; z<3; z++){
+ zigConnection.sendManagementPermitJoiningRequest(0x0001, 0x0036, 0x00);
+ sleep(0);
+ }
+
+ //made by changwoo
+ while (!didWriteAttrb.get()) {
+ System.out.println("Sending Write Attribute Request");
+ zigConnection.sendWriteAttributesCommand(0x0002, 0x0500, 0x0104, 0x01);
+ sleep(0);
+ }
+
+ //made by changwoo
+ System.out.println("Sending Enrollment Reponse");
+ zigConnection.sendEnrollmentResponse(0x0003, 0x0500, 0x0104, 0x01);
+ sleep(0);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ //made by changwoo
+ private void sleep(int multipleTime){
+ if(multipleTime<=0){
+ multipleTime=1;
+ }
+ try{
+ Thread.sleep(TIMEOUT_FOR_RESEND_MSEC*multipleTime);
+ } catch(Exception e){
+ e.printStackTrace();
+ }
+ }
+
+ public void close() {
+
+ if (didAlreadyClose.compareAndSet(false, true) == false) {
+ return; // already init
+ }
+
+ didAlreadyInit.set(false);
+
+
+ try {
+ zigConnection.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void Finalize() {
+ if (!didClose) {
+ close();
+ }
+ }
+
+ public void setId(int id) {
+
+ sensorId = id;
+
+ }
+
+ public int getId() {
+
+ return sensorId;
+
+ }
+
+ public int getValue() {
+
+ int tmp = 0;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = detectedValue;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+
+ return tmp;
+ }
+
+ // WaterLeakSensor:
+ // - 24 = no leak = false
+ // - 25 = leak = true
+ public boolean isActiveValue() {
+
+ int tmp = getValue();
+ if (tmp == 25)
+ detectStatus = true;
+ else // Getting 24 here
+ detectStatus = false;
+
+ return detectStatus;
+ }
+
+ public long getTimestampOfLastReading() {
+
+ Date tmp = null;
+ try {
+ gettingLatestDataMutex.acquire();
+ tmp = (Date)timestampOfLastDetecting.clone();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+ long retLong = tmp.getTime();
+
+ return retLong;
+ }
+
+ public void newMessageAvailable(IoTZigbeeMessage _zm) {
+
+ //made by changwoo
+ if(_zm instanceof IoTZigbeeMessageZclZoneStatusChangeNotification){
+ IoTZigbeeMessageZclZoneStatusChangeNotification message = (IoTZigbeeMessageZclZoneStatusChangeNotification)_zm;
+ if(message.getSuccessOrFail()){
+ //do something!
+
+ try {
+ gettingLatestDataMutex.acquire();
+ detectedValue = message.getStatus();
+ timestampOfLastDetecting = new Date();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ gettingLatestDataMutex.release();
+ try {
+ for (SmartthingsSensorSmartCallback cb : callbackList) {
+ cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }//if
+
+ //made by changwoo
+ }//if
+ else if (_zm instanceof IoTZigbeeMessageZclWriteAttributesResponse) {
+ IoTZigbeeMessageZclWriteAttributesResponse message = (IoTZigbeeMessageZclWriteAttributesResponse)_zm;
+ if (message.getSuccessOrFail()) {
+ didWriteAttrb.set(true);
+ }//if
+ }//else if
+ }
+
+ public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
+ callbackList.add(_callbackTo);
+ }
+}
--- /dev/null
+package iotcode.WeatherPhoneGateway;
+
+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 WeatherGatewaySmartCallback_CallbackStub implements WeatherGatewaySmartCallback {
+
+ private IoTRMICall rmiCall;
+ private String callbackAddress;
+ private int[] ports;
+
+ private int objectId = 0;
+
+
+ public WeatherGatewaySmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
+ callbackAddress = _callbackAddress;
+ objectId = _objectId;
+ rmiCall = _rmiCall;
+ ports = _ports;
+ }
+
+ public void informationRetrieved(double _inchesPerWeek, int _weatherZipCode, int _daysToWaterOn, double _inchesPerMinute) {
+ int methodId = 0;
+ Class<?> retType = void.class;
+ Class<?>[] paramCls = new Class<?>[] { double.class, int.class, int.class, double.class };
+ Object[] paramObj = new Object[] { _inchesPerWeek, _weatherZipCode, _daysToWaterOn, _inchesPerMinute };
+ rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
+ }
+
+}
--- /dev/null
+package iotcode.WeatherPhoneGateway;
+
+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 WeatherGateway_Skeleton implements WeatherGateway {
+
+ private WeatherGateway mainObj;
+ private IoTRMIObject rmiObj;
+
+ private String callbackAddress;
+ private int objIdCnt = 0;
+ private IoTRMICall rmiCall;
+ private int[] ports;
+
+ private final static int object0Id = 0; //WeatherGatewaySmart
+ private static Integer[] object0Permission = { 3, 6, 5, 7, 2, 1, 0, 4 };
+ private static List<Integer> set0Allowed;
+
+
+ public WeatherGateway_Skeleton(WeatherGateway _mainObj, String _callbackAddress, int _port) throws Exception {
+ mainObj = _mainObj;
+ callbackAddress = _callbackAddress;
+ rmiObj = new IoTRMIObject(_port);
+ set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
+ set0Allowed.add(-9998);
+ ___waitRequestInvokeMethod();
+ }
+
+ public void init() {
+ mainObj.init();
+ }
+
+ public void start() {
+ mainObj.start();
+ }
+
+ public void stop() {
+ mainObj.stop();
+ }
+
+ public double getInchesPerWeek() {
+ return mainObj.getInchesPerWeek();
+ }
+
+ public int getWeatherZipCode() {
+ return mainObj.getWeatherZipCode();
+ }
+
+ public int getDaysToWaterOn() {
+ return mainObj.getDaysToWaterOn();
+ }
+
+ public double getInchesPerMinute() {
+ return mainObj.getInchesPerMinute();
+ }
+
+ public void registerCallback(WeatherGatewaySmartCallback _callbackTo) {
+ mainObj.registerCallback(_callbackTo);
+ }
+
+ public void ___regCB() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
+ ports = (int[]) paramObj[0];
+ rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
+ }
+
+ public void ___init() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ init();
+ }
+
+ public void ___start() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ start();
+ }
+
+ public void ___stop() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ stop();
+ }
+
+ public void ___getInchesPerWeek() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getInchesPerWeek();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getWeatherZipCode() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getWeatherZipCode();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getDaysToWaterOn() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getDaysToWaterOn();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___getInchesPerMinute() throws IOException {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
+ new Class<?>[] { });
+ Object retObj = getInchesPerMinute();
+ rmiObj.sendReturnObj(retObj);
+ }
+
+ public void ___registerCallback() {
+ Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
+ new Class<?>[] { null });
+ try {
+ WeatherGatewaySmartCallback stub0 = new WeatherGatewaySmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
+ objIdCnt++;
+ registerCallback(stub0);
+ } catch(Exception ex) {
+ ex.printStackTrace();
+ throw new Error("Exception from callback object instantiation!");
+ }
+ }
+
+ private void ___waitRequestInvokeMethod() throws IOException {
+ while (true) {
+ rmiObj.getMethodBytes();
+ int _objectId = rmiObj.getObjectId();
+ int methodId = rmiObj.getMethodId();
+ if (_objectId == object0Id) {
+ if (!set0Allowed.contains(methodId)) {
+ throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
+ }
+ }
+ else {
+ throw new Error("Object Id: " + _objectId + " not recognized!");
+ }
+ switch (methodId) {
+ case 0: ___init(); break;
+ case 1: ___start(); break;
+ case 2: ___stop(); break;
+ case 3: ___getInchesPerWeek(); break;
+ case 4: ___getWeatherZipCode(); break;
+ case 5: ___getDaysToWaterOn(); break;
+ case 6: ___getInchesPerMinute(); break;
+ case 7: ___registerCallback(); break;
+ case -9998: ___regCB(); break;
+ default:
+ throw new Error("Method Id " + methodId + " not recognized!");
+ }
+ }
+ }
+
+}
--- /dev/null
+package iotcode.WeatherPhoneGateway;
+
+/** WeatherInfo that implements WeatherInfoInterface
+ *
+ * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version 1.0
+ * @since 2016-04-26
+ */
+public class WeatherInfo implements WeatherInfoInterface {
+
+ /**
+ * WeatherInfo class properties
+ */
+ private Double dInchesPerWeek;
+ private Integer iWeatherZipCode;
+ private Integer iDaysToWaterOn;
+ private Double dInchesPerMinute;
+ private boolean bNewDataAvailable;
+
+ /**
+ * Constructor
+ */
+ public WeatherInfo() {
+ this.dInchesPerWeek = 0.0;
+ this.iWeatherZipCode = 0;
+ this.iDaysToWaterOn = 0;
+ this.dInchesPerMinute = 0.0;
+ this.bNewDataAvailable = false;
+ }
+
+ /**
+ * Get irrigation info from the phone app using IoTRemoteCall
+ *
+ * @param dInchesPerWeek Rainfall information (inches per week)
+ * @param iWeatherZipCode Area zip code for weather info
+ * @param iDaysToWaterOn Number of days to water the lawn
+ * @param dInchesPerMinute Rainfall information (inches per minute)
+ * @
+ */
+ public String getIrrigationInfo(Double dInchesPerWeek, Integer iWeatherZipCode,
+ Integer iDaysToWaterOn, Double dInchesPerMinute) {
+
+ this.dInchesPerWeek = dInchesPerWeek;
+ this.iWeatherZipCode = iWeatherZipCode;
+ this.iDaysToWaterOn = iDaysToWaterOn;
+ this.dInchesPerMinute = dInchesPerMinute;
+ this.bNewDataAvailable = true;
+ System.out.println("DEBUG: We are getting data from phone!");
+ System.out.println("DEBUG: New data available?" + bNewDataAvailable);
+
+ return "info sent";
+ }
+
+ /**
+ * Simply return this.dInchesPerWeek
+ */
+ public Double getInchesPerWeek() {
+
+ return this.dInchesPerWeek;
+ }
+
+ /**
+ * Simply return this.iWeatherZipCode
+ */
+ public Integer getWeatherZipCode() {
+
+ return this.iWeatherZipCode;
+ }
+
+ /**
+ * Simply return this.iDaysToWaterOn
+ */
+ public Integer getDaysToWaterOn() {
+
+ return this.iDaysToWaterOn;
+ }
+
+ /**
+ * Simply return this.dInchesPerMinute
+ */
+ public Double getInchesPerMinute() {
+
+ return this.dInchesPerMinute;
+ }
+
+ /**
+ * Simply return this.bNewDataAvailable
+ */
+ public boolean isNewDataAvailable() {
+
+ return this.bNewDataAvailable;
+ }
+
+ /**
+ * Set this.bNewDataAvailable
+ */
+ public void setNewDataAvailable(boolean bValue) {
+
+ this.bNewDataAvailable = bValue;
+ }
+}
--- /dev/null
+package iotcode.WeatherPhoneGateway;
+
+/** WeatherInfoInterface interface to be implemented by a real class
+ *
+ * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version 1.0
+ * @since 2016-04-26
+ */
+public interface WeatherInfoInterface {
+
+ /**
+ * WeatherPhoneGateway takes 4 inputs
+ * - inchesPerWeek (double)
+ * - weatherZipCode (int)
+ * - daysToWaterOn (int)
+ * - inchesPerMinute (double)
+ */
+ String getIrrigationInfo(Double dInchesPerWeek, Integer iWeatherZipCode,
+ Integer iDaysToWaterOn, Double dInchesPerMinute);
+}
--- /dev/null
+# Skeleton/original interface
+INTERFACE_CLASS=WeatherGateway
+# Stub
+INTERFACE_STUB_CLASS=WeatherGatewaySmart
--- /dev/null
+package iotcode.WeatherPhoneGateway;
+
+// 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.*;
+
+/** WeatherPhoneProxy that uses IoTRemoteCall and WeatherInfo class
+ * to get information from a phone app
+ *
+ * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version 1.0
+ * @since 2016-04-26
+ */
+public class WeatherPhoneGateway implements WeatherGateway {
+
+ /**
+ * PhoneGateway class properties
+ */
+ private WeatherInfo weatherInfo;
+ private IoTRemoteCall iotRemCall;
+ private List<WeatherGatewaySmartCallback> listPGWCallback;
+ private AtomicBoolean doEnd;
+ private Thread callbackThread;
+ private Thread workerThread;
+ private IoTDeviceAddress iotDevAdd;
+
+ @config private IoTSet<IoTDeviceAddress> ph_address;
+
+ /**
+ * Constructor
+ */
+ /*public WeatherPhoneGateway() throws RemoteException, UnknownHostException {
+
+ iotDevAdd = new IoTDeviceAddress("192.168.2.101", 1234, 8000);
+ weatherInfo = new WeatherInfo();
+
+ // Launch IoTRemoteCall server in a separate thread
+ workerThread = new Thread(new Runnable() {
+ public void run() {
+ iotRemCall = new IoTRemoteCall(WeatherInfoInterface.class,
+ weatherInfo, iotDevAdd.getDestinationPortNumber());
+ }
+ });
+ workerThread.start();
+
+ System.out.println("PhoneGateway is started");
+
+ }*/
+ public WeatherPhoneGateway() {
+ }
+
+ /**
+ * Init() function
+ */
+ public void init() {
+
+ // Get address
+ Iterator it = ph_address.iterator();
+ iotDevAdd = (IoTDeviceAddress) it.next();
+// try {
+// iotDevAdd = new IoTDeviceAddress("192.168.2.101", 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
+ weatherInfo = new WeatherInfo();
+ System.out.println("DEBUG: Is new data available: " + weatherInfo.isNewDataAvailable());
+ listPGWCallback = new ArrayList<WeatherGatewaySmartCallback>();
+ 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(WeatherInfoInterface.class,
+ weatherInfo, iotDevAdd.getDestinationPortNumber(),
+ IoTDeviceAddress.getLocalHostAddress());
+ }
+ });
+ workerThread.start();
+ System.out.println("DEBUG: Started IoTRemoteCall object!!!");
+
+ callbackThread = new Thread(new Runnable() {
+ public void run() {
+ doCallbacks();
+ }
+ });
+ callbackThread.start();
+ System.out.println("DEBUG: Do Callbacks!!!");
+ }
+
+ /**
+ * 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(WeatherGatewaySmartCallback _c) {
+ listPGWCallback.add(_c);
+ }
+
+ /**
+ * Do callbacks
+ */
+ private void doCallbacks() {
+
+ while (!doEnd.get()) {
+ // Only call back if there is new data
+ if (weatherInfo.isNewDataAvailable()) {
+ System.out.println("We get into doCallbacks!");
+ System.out.println("weatherInfo.isNewDataAvailable(): " + weatherInfo.isNewDataAvailable());
+ for (WeatherGatewaySmartCallback c : listPGWCallback) {
+ //try {
+ //c.informationRetrieved(this);
+ c.informationRetrieved(this.getInchesPerWeek(), this.getWeatherZipCode(), this.getDaysToWaterOn(), this.getInchesPerMinute());
+ //} catch (RemoteException ex) {
+ // ex.printStackTrace();
+ //}
+ // We have read data - set this back to false
+ }
+ weatherInfo.setNewDataAvailable(false);
+ }
+ }
+ }
+
+ /**
+ * Simply return this.dInchesPerWeek
+ */
+ public double getInchesPerWeek() {
+
+ return weatherInfo.getInchesPerWeek();
+ }
+
+ /**
+ * Simply return this.iWeatherZipCode
+ */
+ public int getWeatherZipCode() {
+
+ return weatherInfo.getWeatherZipCode();
+ }
+
+ /**
+ * Simply return this.iDaysToWaterOn
+ */
+ public int getDaysToWaterOn() {
+
+ return weatherInfo.getDaysToWaterOn();
+ }
+
+ /**
+ * Simply return this.dInchesPerMinute
+ */
+ public double getInchesPerMinute() {
+
+ return weatherInfo.getInchesPerMinute();
+ }
+
+
+// public static void main(String[] args) throws UnknownHostException, RemoteException {
+
+// @LocalRemote WeatherPhoneGateway wpg = new @LocalRemote WeatherPhoneGateway();
+// wpg.init();
+// wpg.start();
+// }
+}
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=Room
-# Stub
-INTERFACE_STUB_CLASS=RoomSmart
+++ /dev/null
-package iotcode.LabRoom;
-
-import iotcode.interfaces.Room;
-
-/** LabRoom implements Room as a needed object for room identification
- *
- * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
- * @version 1.0
- * @since 2016-04-22
- */
-public class LabRoom implements Room {
-
- public LabRoom() {
-
- }
-
- public int getRoomID() {
- return 0;
- }
-}
+++ /dev/null
-package iotcode.LabRoom;
-
-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!");
- }
- }
- }
-
-}
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-import java.security.InvalidParameterException;
-
-public class BulbColor {
-
- private int hue;
- private int saturation;
- private int brightness;
- private int kelvin;
-
- public BulbColor(int _hue, int _saturation, int _brightness, int _kelvin) {
-
- if ((hue > 65535) || (hue < 0)) {
- throw new InvalidParameterException("BulbColor: Invalid parameter value for _hue (0-65535)");
- }
-
- if ((saturation > 65535) || (saturation < 0)) {
- throw new InvalidParameterException("BulbColor: Invalid parameter value for _saturation (0-65535)");
- }
-
- if ((brightness > 65535) || (brightness < 0)) {
- throw new InvalidParameterException("BulbColor: Invalid parameter value for _brightness (0-65535)");
- }
-
- if ((kelvin > 65535) || (kelvin < 0)) {
- throw new InvalidParameterException("BulbColor: Invalid parameter value for _kelvin (0-65535)");
- }
-
- hue = _hue;
- saturation = _saturation;
- brightness = _brightness;
- kelvin = _kelvin;
- }
-
- public BulbColor(byte[] data) {
- hue = ((data[1] & 0xFF) << 8);
- hue |= (data[0] & 0xFF);
-
- saturation = ((data[3] & 0xFF) << 8);
- saturation |= (data[2] & 0xFF);
-
- brightness = ((data[5] & 0xFF) << 8);
- brightness |= (data[4] & 0xFF);
-
- kelvin = ((data[7] & 0xFF) << 8);
- kelvin |= (data[6] & 0xFF);
- }
-
- public int getHue() {
- return hue;
- }
-
- public int getSaturation() {
- return saturation;
- }
-
- public int getBrightness() {
- return brightness;
- }
-
- public int getKelvin() {
- return kelvin;
- }
-}
-
-
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-public class DeviceStateGroup {
- byte[] group = new byte[16];
- final String label;
- final long updatedAt;
-
- public DeviceStateGroup(byte[] _location, String _label, long _updatedAt) {
- group = _location;
- label = _label;
- updatedAt = _updatedAt;
- }
-
- public byte[] getGroup() {
- return group;
- }
-
- public String getLabel() {
- return label;
- }
-
- public long getUpdatedAt() {
- return updatedAt;
- }
-}
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-public class DeviceStateHostFirmware {
- // time of build in nanosecond accuracy
- // after some tests
- final long build;
- final long version; // firmware version
-
- public DeviceStateHostFirmware(long _build, long _version) {
- build = _build;
- version = _version;
- }
-
- public long getBuild() {
- return build;
- }
-
- public long getVersion() {
- return version;
- }
-}
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-public class DeviceStateHostInfo {
- final long signal;
- final long tx;
- final long rx;
-
- public DeviceStateHostInfo(long _signal, long _tx, long _rx) {
- signal = _signal;
- tx = _tx;
- rx = _rx;
- }
-
- public long getSignal() {
- return signal;
- }
-
- public long getTx() {
- return tx;
- }
-
- public long getRx() {
- return rx;
- }
-}
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-public class DeviceStateInfo {
- // all values are in nanoseconds
- private final long time;
- private final long upTime;
- private final long downTime;
-
- public DeviceStateInfo(long _time, long _upTime, long _downTime) {
- time = _time;
- upTime = _upTime;
- downTime = _downTime;
- }
-
- public long getTime() {
- return time;
- }
-
- public long getUpTime() {
- return upTime;
- }
-
- public long getDownTime() {
- return downTime;
- }
-}
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-public class DeviceStateLocation {
- byte[] location = new byte[16];
- final String label;
- final long updatedAt;
-
- public DeviceStateLocation(byte[] _location, String _label, long _updatedAt) {
- location = _location;
- label = _label;
- updatedAt = _updatedAt;
- }
-
- public byte[] getLocation() {
- return location;
- }
-
- public String getLabel() {
- return label;
- }
-
- public long getUpdatedAt() {
- return updatedAt;
- }
-}
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-public class DeviceStateService {
- private final int service;
- private final long port;
-
- public DeviceStateService(int _service, long _port) {
- service = _service;
- port = _port;
- }
-
- public int getService() {
- return service;
- }
-
- public long getPort() {
- return port;
- }
-}
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-public class DeviceStateVersion {
- final long vender;
- final long product;
- final long version;
-
- public DeviceStateVersion(long _vender, long _product, long _version) {
- vender = _vender;
- product = _product;
- version = _version;
- }
-
- public long getVender() {
- return vender;
- }
-
- public long getProduct() {
- return product;
- }
-
- public long getVersion() {
- return version;
- }
-}
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-public class DeviceStateWifiFirmware {
- // time of build in nanosecond accuracy
- // after some tests
- final long build;
- final long version; // firmware version
-
- public DeviceStateWifiFirmware(long _build, long _version) {
- build = _build;
- version = _version;
- }
-
- public long getBuild() {
- return build;
- }
-
- public long getVersion() {
- return version;
- }
-}
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-public class DeviceStateWifiInfo {
- final long signal;
- final long tx;
- final long rx;
-
- public DeviceStateWifiInfo(long _signal, long _tx, long _rx) {
- signal = _signal;
- tx = _tx;
- rx = _rx;
- }
-
- public long getSignal() {
- return signal;
- }
-
- public long getTx() {
- return tx;
- }
-
- public long getRx() {
- return rx;
- }
-}
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-import java.security.InvalidParameterException;
-
-public class LifxHeader {
- // Frame Variables
- private int size;
- private int origin;
- private boolean tagged;
- private boolean addressable;
- private int protocol;
- private long source;
-
- //Frame Adress Variables
- private byte[] macAddress = new byte[8];
- private boolean ack_required;
- private boolean res_required;
- private int sequence;
-
- //Protocol Header
- private int type;
-
- public LifxHeader() {
- // needed values as per spec
- origin = 0;
- addressable = true;
- protocol = 1024;
- }
-
- public void setSize(int _size) {
- if (_size < 0) {
- throw new InvalidParameterException("Header: size cannot be less than 0");
- } else if (_size > 65535) {
- throw new InvalidParameterException("Header: size to large");
- }
- size = _size;
- }
-
- public void setOrigin(int _origin) {
- if (_origin < 0) {
- throw new InvalidParameterException("Header: origin cannot be less than 0");
- } else if (_origin > 3) {
- throw new InvalidParameterException("Header: origin to large");
- }
-
- origin = _origin;
- }
-
- public void setTagged(boolean _tagged) {
- tagged = _tagged;
- }
-
- public void setAddressable(boolean _addressable) {
- addressable = _addressable;
- }
-
- public void setProtocol(int _protocol) {
- if (_protocol < 0) {
- throw new InvalidParameterException("Header: protocol cannot be less than 0");
- } else if (_protocol > 4095) {
- throw new InvalidParameterException("Header: protocol to large");
- }
-
- protocol = _protocol;
- }
-
- public void setSource(long _source) {
- if (_source < 0) {
- throw new InvalidParameterException("Header: source cannot be less than 0");
- } else if (_source > (long)4294967295l) {
- throw new InvalidParameterException("Header: source to large");
- }
- source = _source;
- }
-
- public void setSequence(int _sequence) {
- if (_sequence < 0) {
- throw new InvalidParameterException("Header: sequence cannot be less than 0");
- } else if (_sequence > 255) {
- throw new InvalidParameterException("Header: sequence to large");
- }
- sequence = _sequence;
- }
-
- public void setType(int _type) {
- if (_type < 0) {
- throw new InvalidParameterException("Header: type cannot be less than 0");
- } else if (_type > 65535) {
- throw new InvalidParameterException("Header: type to large");
- }
- type = _type;
- }
-
- public void setAck_required(boolean _ack_required) {
- ack_required = _ack_required;
- }
-
- public void setRes_required(boolean _res_required) {
- res_required = _res_required;
- }
-
- public void setMacAddress(byte[] _macAddress) {
- macAddress = _macAddress;
- }
-
- public int getSize() {
- return size;
- }
-
- public int getOrigin() {
- return origin;
- }
-
- public boolean getTagged() {
- return tagged;
- }
-
- public boolean getAddressable() {
- return addressable;
- }
-
- public int getProtocol() {
- return protocol;
- }
-
- public long getSource() {
- return source;
- }
-
- public int getSequence() {
- return sequence;
- }
-
- public int getType() {
- return type;
- }
-
- public byte[] getMacAddress() {
- return macAddress;
- }
-
- public boolean getAck_required() {
- return ack_required;
- }
-
- public boolean getRes_required() {
- return res_required;
- }
-
- public byte[] getHeaderBytes() {
- byte[] headerBytes = new byte[36];
- headerBytes[0] = (byte)(size & 0xFF);
- headerBytes[1] = (byte)((size >> 8) & 0xFF);
-
-
- headerBytes[2] = (byte)(protocol & 0xFF);
- headerBytes[3] = (byte)((protocol >> 8) & 0x0F);
-
- headerBytes[3] |= (byte)((origin & 0x03) << 6);
-
- if (tagged) {
- headerBytes[3] |= (1 << 5);
- }
-
- if (addressable) {
- headerBytes[3] |= (1 << 4);
- }
-
- headerBytes[4] = (byte)((source >> 0) & 0xFF);
- headerBytes[5] = (byte)((source >> 8) & 0xFF);
- headerBytes[6] = (byte)((source >> 16) & 0xFF);
- headerBytes[7] = (byte)((source >> 24) & 0xFF);
-
-
- // fix in a bit
- headerBytes[8] = macAddress[0];
- headerBytes[9] = macAddress[1];
- headerBytes[10] = macAddress[2];
- headerBytes[11] = macAddress[3];
- headerBytes[12] = macAddress[4];
- headerBytes[13] = macAddress[5];
- headerBytes[14] = macAddress[6];
- headerBytes[15] = macAddress[7];
-
- // Reserved and set to 0
- // headerBytes[16] = 0;
- // headerBytes[17] = 0;
- // headerBytes[18] = 0;
- // headerBytes[19] = 0;
- // headerBytes[20] = 0;
- // headerBytes[21] = 0;
-
- if (ack_required) {
- headerBytes[22] = (1 << 1);
- }
-
- if (res_required) {
- headerBytes[22] |= (1);
- }
-
- headerBytes[23] = (byte)(sequence & 0xFF);
-
- // Reserved and set to 0
- //headerBytes[24] = 0;
- //headerBytes[25] = 0;
- //headerBytes[26] = 0;
- //headerBytes[27] = 0;
- //headerBytes[28] = 0;
- //headerBytes[29] = 0;
- //headerBytes[30] = 0;
- //headerBytes[31] = 0;
-
- headerBytes[32] = (byte)((type >> 0) & 0xFF);
- headerBytes[33] = (byte)((type >> 8) & 0xFF);
-
- // Reserved and set to 0
- //headerBytes[34] = 0;
- //headerBytes[35] = 0;
-
- return headerBytes;
- }
-
- public void setFromBytes(byte[] dataBytes) {
- if (dataBytes.length != 36) {
- throw new InvalidParameterException("Header: invalid number of bytes");
- }
-
- size = dataBytes[0] & 0xFF;
- size |= ((dataBytes[1] & 0xFF) << 8);
- size &= 0xFFFF;
-
- origin = (dataBytes[3] >> 6) & 0x03;
- tagged = ((dataBytes[3] >> 5) & 0x01) == 1;
- addressable = ((dataBytes[3] >> 4) & 0x01) == 1;
-
-
- protocol = (dataBytes[3] & 0x0F) << 8;
- protocol |= dataBytes[2];
- protocol &= 0x0FFF;
-
- source = (dataBytes[7] & 0xFFl) << 24;
- source |= ((dataBytes[6] & 0xFFl) << 16);
- source |= ((dataBytes[5] & 0xFFl) << 8);
- source |= ((dataBytes[4] & 0xFFl));
-
- macAddress[0] = dataBytes[8];
- macAddress[1] = dataBytes[9];
- macAddress[2] = dataBytes[10];
- macAddress[3] = dataBytes[11];
- macAddress[4] = dataBytes[12];
- macAddress[5] = dataBytes[13];
- macAddress[6] = dataBytes[14];
- macAddress[7] = dataBytes[15];
-
- ack_required = (dataBytes[22] & 0x02) == 0x02;
- res_required = (dataBytes[22] & 0x01) == 0x01;
-
- sequence = (dataBytes[23] & 0xFF);
-
- type = ((dataBytes[33] & 0xFF) << 8);
- type |= (dataBytes[32] & 0xFF);
- }
-}
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=LightBulb
-# Stub
-#INTERFACE_STUB_CLASS=LightBulbTest
-INTERFACE_STUB_CLASS=LightBulbSmart
-
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-// Standard Java Packages
-import java.io.*;
-import java.net.*;
-import java.util.concurrent.Semaphore;
-import java.security.InvalidParameterException;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-// IoT Packages
-import iotcode.annotation.*;
-import iotcode.interfaces.LightBulb;
-import iotruntime.IoTUDP;
-import iotruntime.slave.IoTDeviceAddress;
-import iotruntime.slave.IoTSet;
-
-// String to byte conversion
-import javax.xml.bind.DatatypeConverter;
-
-public class LifxLightBulb implements LightBulb {
-
- /*******************************************************************************************************************************************
- **
- ** Constants
- **
- *******************************************************************************************************************************************/
- public static final long GET_BULB_VERSION_RESEND_WAIT_SECONDS = 10;
-
-
-
- /*******************************************************************************************************************************************
- **
- ** Variables
- **
- *******************************************************************************************************************************************/
- private IoTUDP communicationSockect;
- private byte[] bulbMacAddress = new byte[8];
- static Semaphore socketMutex = new Semaphore(1);
- static boolean sendSocketFlag = false;
- private long lastSentGetBulbVersionRequest = 0; // time last request sent
-
- // Current Bulb Values
- private int currentHue = 0;
- private int currentSaturation = 0;
- private int currentBrightness = 65535;
- private int currentTemperature = 9000;
- private boolean bulbIsOn = false;
-
-
-
- private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
-
- private AtomicBoolean didGetBulbVersion = new AtomicBoolean(false);
- static Semaphore settingBulbColorMutex = new Semaphore(1);
- static Semaphore settingBulbTempuraturerMutex = new Semaphore(1);
- static Semaphore bulbStateMutex = new Semaphore(1);
-
- // color and temperature ranges for the bulbs
- private int hueLowerBound = 0;
- private int hueUpperBound = 0;
- private int saturationLowerBound = 0;
- private int saturationUpperBound = 0;
- private int brightnessLowerBound = 0;
- private int brightnessUpperBound = 0;
- private int temperatureLowerBound = 2500;
- private int temperatureUpperBound = 9000;
-
-
-
- // Check if a state change was requested, used to poll the bulb for if the bulb did
- // preform the requested state change
- private boolean stateDidChange = false;
-
- /*******************************************************************************************************************************************
- **
- ** Threads
- **
- *******************************************************************************************************************************************/
-
- // Main worker thread will do the receive loop
- Thread workerThread = null;
-
- /*******************************************************************************************************************************************
- **
- ** IoT Sets and Relations
- **
- *******************************************************************************************************************************************/
-
- // IoTSet of Device Addresses.
- // Will be filled with only 1 address.
- @config private IoTSet<IoTDeviceAddress> lb_addresses;
-
- /**
- * Used for testing only
- */
- public LifxLightBulb(IoTUDP udp, byte[] macAddress) {
- communicationSockect = udp;
- bulbMacAddress = macAddress;
- }
-
- public LifxLightBulb(String macAddress) {
- communicationSockect = null;
-
- // Set the Mac Address to a default value
- // Probably not needed for anything
- /*bulbMacAdd[0] = (byte)0x00;
- bulbMacAdd[1] = (byte)0x00;
- bulbMacAdd[2] = (byte)0x00;
- bulbMacAdd[3] = (byte)0x00;
- bulbMacAdd[4] = (byte)0x00;
- bulbMacAdd[5] = (byte)0x00;
- bulbMacAdd[6] = (byte)0x00;
- bulbMacAdd[7] = (byte)0x00;*/
-
- bulbMacAddress = DatatypeConverter.parseHexBinary(macAddress);
- }
-
-
-
- /*******************************************************************************************************************************************
- ** Sending
- ** Device Messages
- **
- *******************************************************************************************************************************************/
- private void sendGetServicePacket() {
- LifxHeader header = new LifxHeader();
- header.setSize(36);
- header.setTagged(true);
- header.setMacAddress(bulbMacAddress);
- header.setSource(0); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(2);
-
- byte[] dataBytes = header.getHeaderBytes();
- sendPacket(dataBytes);
- }
-
- private void sendGetHostInfoPacket() {
- LifxHeader header = new LifxHeader();
- header.setSize(36);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(12);
-
- byte[] dataBytes = header.getHeaderBytes();
- sendPacket(dataBytes);
- }
-
- private void sendGetHostFirmwarePacket() {
- LifxHeader header = new LifxHeader();
- header.setSize(36);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(14);
-
- byte[] dataBytes = header.getHeaderBytes();
- sendPacket(dataBytes);
- }
-
- private void sendGetWifiInfoPacket() {
- LifxHeader header = new LifxHeader();
- header.setSize(36);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(16);
-
- byte[] dataBytes = header.getHeaderBytes();
- sendPacket(dataBytes);
- }
-
- private void sendGetWifiFirmwarePacket() {
- LifxHeader header = new LifxHeader();
- header.setSize(36);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(18);
-
- byte[] dataBytes = header.getHeaderBytes();
- sendPacket(dataBytes);
- }
-
- private void sendGetPowerPacket() {
- LifxHeader header = new LifxHeader();
- header.setSize(36);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(20);
-
- byte[] dataBytes = header.getHeaderBytes();
- sendPacket(dataBytes);
- }
-
- private void sendSetPowerPacket(int level) {
- // Currently only 0 and 65535 are supported
- // This is a fix for now
- if ((level != 65535) && (level != 0)) {
- throw new InvalidParameterException("Invalid parameter values");
- }
-
- if ((level > 65535) || (level < 0)) {
- throw new InvalidParameterException("Invalid parameter values");
- }
-
- byte[] packetBytes = new byte[38];
-
- LifxHeader header = new LifxHeader();
- header.setSize(38);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(21);
- byte[] headerBytes = header.getHeaderBytes();
-
- for (int i = 0; i < 36; i++) {
- packetBytes[i] = headerBytes[i];
- }
-
- packetBytes[36] = (byte)(level & 0xFF);
- packetBytes[37] = (byte)((level >> 8) & 0xFF);
-
- sendPacket(packetBytes);
- }
-
- private void sendGetLabelPacket() {
- LifxHeader header = new LifxHeader();
- header.setSize(36);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(23);
-
- byte[] dataBytes = header.getHeaderBytes();
- sendPacket(dataBytes);
- }
-
- private void sendSetLabelPacket(String label) {
- // Currently only 0 and 65535 are supported
- // This is a fix for now
- if (label.length() != 32) {
- throw new InvalidParameterException("Invalid parameter values, label must be 32 bytes long");
- }
-
- byte[] packetBytes = new byte[68];
-
- LifxHeader header = new LifxHeader();
- header.setSize(68);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(24);
- byte[] headerBytes = header.getHeaderBytes();
-
- for (int i = 0; i < 36; i++) {
- packetBytes[i] = headerBytes[i];
- }
-
- for (int i = 0; i < 32; i++) {
- packetBytes[i + 36] = label.getBytes()[i];
- }
-
- sendPacket(packetBytes);
- }
-
- private void sendGetVersionPacket() {
- LifxHeader header = new LifxHeader();
- header.setSize(36);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(32);
-
- byte[] dataBytes = header.getHeaderBytes();
- sendPacket(dataBytes);
- }
-
- private void sendGetInfoPacket() {
- LifxHeader header = new LifxHeader();
- header.setSize(36);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(34);
-
- byte[] dataBytes = header.getHeaderBytes();
- sendPacket(dataBytes);
- }
-
- private void sendGetLocationPacket() {
- LifxHeader header = new LifxHeader();
- header.setSize(36);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(34);
-
- byte[] dataBytes = header.getHeaderBytes();
- sendPacket(dataBytes);
- }
-
- private void sendGetGroupPacket() {
- LifxHeader header = new LifxHeader();
- header.setSize(36);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(51);
-
- byte[] dataBytes = header.getHeaderBytes();
- sendPacket(dataBytes);
- }
-
-
- /*******************************************************************************************************************************************
- ** Sending
- ** Light Messages
- **
- *******************************************************************************************************************************************/
- private void sendGetLightStatePacket() {
- LifxHeader header = new LifxHeader();
- header.setSize(36);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(101);
-
- byte[] dataBytes = header.getHeaderBytes();
- sendPacket(dataBytes);
- }
-
- private void sendSetLightColorPacket(BulbColor bulbColor, long duration) {
-
- if ((duration > 4294967295l) || (duration < 0)) {
- throw new InvalidParameterException("Invalid parameter value, duration out of range (0 - 4294967295)");
- }
-
- byte[] packetBytes = new byte[49];
-
- LifxHeader header = new LifxHeader();
- header.setSize(49);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(102);
- byte[] headerBytes = header.getHeaderBytes();
-
- for (int i = 0; i < 36; i++) {
- packetBytes[i] = headerBytes[i];
- }
-
- // 1 reserved packet
- packetBytes[37] = (byte)(bulbColor.getHue() & 0xFF);
- packetBytes[38] = (byte)((bulbColor.getHue() >> 8) & 0xFF);
-
- packetBytes[39] = (byte)(bulbColor.getSaturation() & 0xFF);
- packetBytes[40] = (byte)((bulbColor.getSaturation() >> 8) & 0xFF);
-
- packetBytes[41] = (byte)(bulbColor.getBrightness() & 0xFF);
- packetBytes[42] = (byte)((bulbColor.getBrightness() >> 8) & 0xFF);
-
- packetBytes[43] = (byte)(bulbColor.getKelvin() & 0xFF);
- packetBytes[44] = (byte)((bulbColor.getKelvin() >> 8) & 0xFF);
-
- packetBytes[45] = (byte)((duration >> 0) & 0xFF);
- packetBytes[46] = (byte)((duration >> 8) & 0xFF);
- packetBytes[47] = (byte)((duration >> 16) & 0xFF);
- packetBytes[48] = (byte)((duration >> 24) & 0xFF);
-
- sendPacket(packetBytes);
- }
-
- private void sendGetLightPowerPacket() {
- LifxHeader header = new LifxHeader();
- header.setSize(36);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(116);
-
- byte[] dataBytes = header.getHeaderBytes();
- sendPacket(dataBytes);
- }
-
- private void sendSetLightPowerPacket(int level, long duration) {
-
- if ((level > 65535) || (duration > 4294967295l)
- || (level < 0) || (duration < 0)) {
- throw new InvalidParameterException("Invalid parameter values");
- }
-
- byte[] packetBytes = new byte[42];
-
-
- LifxHeader header = new LifxHeader();
- header.setSize(42);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(117);
- byte[] headerBytes = header.getHeaderBytes();
-
- for (int i = 0; i < 36; i++) {
- packetBytes[i] = headerBytes[i];
- }
-
- packetBytes[36] = (byte)(level & 0xFF);
- packetBytes[37] = (byte)((level >> 8) & 0xFF);
-
- packetBytes[38] = (byte)((duration >> 0) & 0xFF);
- packetBytes[39] = (byte)((duration >> 8) & 0xFF);
- packetBytes[40] = (byte)((duration >> 16) & 0xFF);
- packetBytes[41] = (byte)((duration >> 24) & 0xFF);
-
- sendPacket(packetBytes);
- }
-
- private void sendEchoRequestPacket(byte[] data) {
- // Currently only 0 and 65535 are supported
- // This is a fix for now
- if (data.length != 64) {
- throw new InvalidParameterException("Invalid parameter values, must have 64 bytes");
- }
-
- byte[] packetBytes = new byte[100];
-
- LifxHeader header = new LifxHeader();
- header.setSize(100);
- header.setTagged(false);
- header.setMacAddress(bulbMacAddress);
- header.setSource(10); // randomly picked
- header.setAck_required(false);
- header.setRes_required(false);
- header.setSequence(0);
- header.setType(58);
- byte[] headerBytes = header.getHeaderBytes();
-
- for (int i = 0; i < 36; i++) {
- packetBytes[i] = headerBytes[i];
- }
-
- for (int i = 0; i < 64; i++) {
- packetBytes[i + 36] = data[i];
- }
-
- sendPacket(packetBytes);
- }
-
-
- /*******************************************************************************************************************************************
- ** Receiving
- ** Device Messages
- **
- *******************************************************************************************************************************************/
- private DeviceStateService parseDeviceStateServiceMessage(LifxHeader header, byte[] payloadData) {
- int service = payloadData[0];
- long port = ((payloadData[3] & 0xFF) << 24);
- port |= ((payloadData[2] & 0xFF) << 16);
- port |= ((payloadData[1] & 0xFF) << 8);
- port |= (payloadData[0] & 0xFF);
-
- return new DeviceStateService(service, port);
- }
-
- private DeviceStateHostInfo parseDeviceStateHostInfoMessage(LifxHeader header, byte[] payloadData) {
- long signal = ((payloadData[3] & 0xFF) << 24);
- signal |= ((payloadData[2] & 0xFF) << 16);
- signal |= ((payloadData[1] & 0xFF) << 8);
- signal |= (payloadData[0] & 0xFF);
-
- long tx = ((payloadData[7] & 0xFF) << 24);
- tx |= ((payloadData[6] & 0xFF) << 16);
- tx |= ((payloadData[5] & 0xFF) << 8);
- tx |= (payloadData[4] & 0xFF);
-
- long rx = ((payloadData[11] & 0xFF) << 24);
- rx |= ((payloadData[10] & 0xFF) << 16);
- rx |= ((payloadData[9] & 0xFF) << 8);
- rx |= (payloadData[8] & 0xFF);
-
- return new DeviceStateHostInfo(signal, tx, rx);
- }
-
- private DeviceStateHostFirmware parseDeviceStateHostFirmwareMessage(LifxHeader header, byte[] payloadData) {
- long build = 0;
- for (int i = 0; i < 8; i++) {
- build += ((long) payloadData[i] & 0xffL) << (8 * i);
- }
-
- // 8 reserved bytes
-
- long version = ((payloadData[19] & 0xFF) << 24);
- version |= ((payloadData[18] & 0xFF) << 16);
- version |= ((payloadData[17] & 0xFF) << 8);
- version |= (payloadData[16] & 0xFF);
-
- return new DeviceStateHostFirmware(build, version);
- }
-
- private DeviceStateWifiInfo parseDeviceStateWifiInfoMessage(LifxHeader header, byte[] payloadData) {
- long signal = ((payloadData[3] & 0xFF) << 24);
- signal |= ((payloadData[2] & 0xFF) << 16);
- signal |= ((payloadData[1] & 0xFF) << 8);
- signal |= (payloadData[0] & 0xFF);
-
- long tx = ((payloadData[7] & 0xFF) << 24);
- tx |= ((payloadData[6] & 0xFF) << 16);
- tx |= ((payloadData[5] & 0xFF) << 8);
- tx |= (payloadData[4] & 0xFF);
-
- long rx = ((payloadData[11] & 0xFF) << 24);
- rx |= ((payloadData[10] & 0xFF) << 16);
- rx |= ((payloadData[9] & 0xFF) << 8);
- rx |= (payloadData[8] & 0xFF);
-
- return new DeviceStateWifiInfo(signal, tx, rx);
- }
-
- private DeviceStateWifiFirmware parseDeviceStateWifiFirmwareMessage(LifxHeader header, byte[] payloadData) {
- long build = 0;
- for (int i = 0; i < 8; i++) {
- build += ((long) payloadData[i] & 0xffL) << (8 * i);
- }
-
- // 8 reserved bytes
-
- long version = ((payloadData[19] & 0xFF) << 24);
- version |= ((payloadData[18] & 0xFF) << 16);
- version |= ((payloadData[17] & 0xFF) << 8);
- version |= (payloadData[16] & 0xFF);
-
- return new DeviceStateWifiFirmware(build, version);
- }
-
- private int parseStatePowerMessage(LifxHeader header, byte[] payloadData) {
- int level = ((payloadData[1] & 0xFF) << 8);
- level |= (payloadData[0] & 0xFF);
- return level;
- }
-
- private String parseStateLabelMessage(LifxHeader header, byte[] payloadData) {
- return new String(payloadData);
- }
-
-
- private DeviceStateVersion parseDeviceStateVersionMessage(LifxHeader header, byte[] payloadData) {
- long vender = ((payloadData[3] & 0xFF) << 24);
- vender |= ((payloadData[2] & 0xFF) << 16);
- vender |= ((payloadData[1] & 0xFF) << 8);
- vender |= (payloadData[0] & 0xFF);
-
- long product = ((payloadData[7] & 0xFF) << 24);
- product |= ((payloadData[6] & 0xFF) << 16);
- product |= ((payloadData[5] & 0xFF) << 8);
- product |= (payloadData[4] & 0xFF);
-
- long version = ((payloadData[11] & 0xFF) << 24);
- version |= ((payloadData[10] & 0xFF) << 16);
- version |= ((payloadData[9] & 0xFF) << 8);
- version |= (payloadData[8] & 0xFF);
-
- return new DeviceStateVersion(vender, product, version);
- }
-
- private DeviceStateInfo parseDeviceStateInfoMessage(LifxHeader header, byte[] payloadData) {
- long time = 0;
- long upTime = 0;
- long downTime = 0;
- for (int i = 0; i < 8; i++) {
- time += ((long) payloadData[i] & 0xffL) << (8 * i);
- upTime += ((long) payloadData[i + 8] & 0xffL) << (8 * i);
- downTime += ((long) payloadData[i + 16] & 0xffL) << (8 * i);
- }
-
- return new DeviceStateInfo(time, upTime, downTime);
- }
-
- private DeviceStateLocation parseDeviceStateLocationMessage(LifxHeader header, byte[] payloadData) {
- byte[] location = new byte[16];
- for (int i = 0; i < 16; i++) {
- location[i] = payloadData[i];
- }
-
- byte[] labelBytes = new byte[32];
- for (int i = 0; i < 32; i++) {
- labelBytes[i] = payloadData[i + 16];
- }
-
- long updatedAt = 0;
- for (int i = 0; i < 8; i++) {
- updatedAt += ((long) payloadData[48] & 0xffL) << (8 * i);
- }
-
- return new DeviceStateLocation(location, new String(labelBytes), updatedAt);
- }
-
- private DeviceStateGroup parseDeviceStateGroupMessage(LifxHeader header, byte[] payloadData) {
- byte[] group = new byte[16];
- for (int i = 0; i < 16; i++) {
- group[i] = payloadData[i];
- }
-
- byte[] labelBytes = new byte[32];
- for (int i = 0; i < 32; i++) {
- labelBytes[i] = payloadData[i + 16];
- }
-
- long updatedAt = 0;
- for (int i = 0; i < 8; i++) {
- updatedAt += ((long) payloadData[48] & 0xffL) << (8 * i);
- }
-
- return new DeviceStateGroup(group, new String(labelBytes), updatedAt);
- }
-
- private byte[] parseDeviceEchoResponseMessage(LifxHeader header, byte[] payloadData) {
- return payloadData;
- }
-
- /*******************************************************************************************************************************************
- ** Receiving
- ** Light Messages
- **
- *******************************************************************************************************************************************/
- private LightState parseLightStateMessage(LifxHeader header, byte[] payloadData) {
-
- byte[] colorData = new byte[8];
- for (int i = 0; i < 8; i++) {
- colorData[i] = payloadData[i];
- }
- BulbColor color = new BulbColor(colorData);
-
- int power = ((payloadData[11] & 0xFF) << 8);
- power |= (payloadData[10] & 0xFF);
-
- String label = new String(payloadData);
-
- byte[] labelArray = new byte[32];
- for (int i = 0; i < 32; i++) {
- labelArray[i] = payloadData[12 + i];
- }
-
- return new LightState(color, power, label);
- }
-
- private int parseLightStatePowerMessage(LifxHeader header, byte[] payloadData) {
- int level = ((payloadData[1] & 0xFF) << 8);
- level |= (payloadData[0] & 0xFF);
- return level;
- }
-
-
- /*******************************************************************************************************************************************
- **
- ** Private Handlers
- **
- *******************************************************************************************************************************************/
- private void handleStateVersionMessageRecieved(LifxHeader header, byte[] payloadData) {
-
- DeviceStateVersion deviceState = parseDeviceStateVersionMessage(header, payloadData);
- int productNumber = (int)deviceState.getProduct();
-
- boolean isColor = false;
-
- if (productNumber == 1) { // Original 1000
- isColor = true;
- } else if (productNumber == 3) { //Color 650
- isColor = true;
- } else if (productNumber == 10) { // White 800 (Low Voltage)
- isColor = false;
- } else if (productNumber == 11) { // White 800 (High Voltage)
- isColor = false;
- } else if (productNumber == 18) { // White 900 BR30 (Low Voltage)
- isColor = false;
- } else if (productNumber == 20) { // Color 1000 BR30
- isColor = true;
- } else if (productNumber == 22) { // Color 1000
- isColor = true;
- }
-
- if (isColor) {
- hueLowerBound = 0;
- hueUpperBound = 65535;
- saturationLowerBound = 0;
- saturationUpperBound = 65535;
- brightnessLowerBound = 0;
- brightnessUpperBound = 65535;
- temperatureLowerBound = 2500;
- temperatureUpperBound = 9000;
- } else {
- hueLowerBound = 0;
- hueUpperBound = 0;
- saturationLowerBound = 0;
- saturationUpperBound = 0;
- brightnessLowerBound = 0;
- brightnessUpperBound = 65535; // still can dim bulb
- temperatureLowerBound = 2500;
- temperatureUpperBound = 9000;
- }
-
- didGetBulbVersion.set(true);
-
- }
-
- private void handleLightStateMessageRecieved(LifxHeader header, byte[] payloadData) {
- LightState lightState = parseLightStateMessage(header, payloadData);
-
- BulbColor color = lightState.getColor();
- int power = lightState.getPower();
-
- boolean bulbWrongColor = false;
- bulbWrongColor = bulbWrongColor || (color.getHue() != currentHue);
- bulbWrongColor = bulbWrongColor || (color.getSaturation() != currentSaturation);
- bulbWrongColor = bulbWrongColor || (color.getBrightness() != currentBrightness);
- bulbWrongColor = bulbWrongColor || (color.getKelvin() != currentTemperature);
-
-
- // gets set to true if any of the below if statements are taken
- stateDidChange = false;
-
- if (bulbWrongColor) {
- BulbColor newColor = new BulbColor(currentHue, currentSaturation, currentBrightness, currentTemperature);
- sendSetLightColorPacket(newColor, 250);
- // System.out.println("Failed Check 1");
- }
-
- try {
- bulbStateMutex.acquire();
- } catch (Exception e) {
- e.printStackTrace();
- }
- boolean bulbIsOnTmp = bulbIsOn;
- bulbStateMutex.release();
-
- if ((!bulbIsOnTmp) && (power != 0)) {
- turnOff();
- // System.out.println("Failed Check 2: " + Integer.toString(power));
-
- }
-
- if (bulbIsOnTmp && (power < 65530)) {
- turnOn();
- // System.out.println("Failed Check 3: " + Integer.toString(power));
-
- }
- }
-
- /*******************************************************************************************************************************************
- **
- ** Light Bulb Interface Methods
- **
- *******************************************************************************************************************************************/
- public double getHue() {
- double tmp = 0;
- try {
- settingBulbColorMutex.acquire();
- tmp = ((double)currentHue / 65535.0) * 360.0;
- } catch (Exception e) {
- e.printStackTrace();
- }
- settingBulbColorMutex.release();
-
-
- return tmp;
- }
-
- public double getSaturation() {
- double tmp = 0;
- try {
- settingBulbColorMutex.acquire();
- tmp = ((double)currentSaturation / 65535.0) * 360.0;
- } catch (Exception e) {
- e.printStackTrace();
- }
- settingBulbColorMutex.release();
-
-
- return tmp;
- }
-
- public double getBrightness() {
- double tmp = 0;
- try {
- settingBulbColorMutex.acquire();
- tmp = ((double)currentBrightness / 65535.0) * 360.0;
- } catch (Exception e) {
- e.printStackTrace();
- }
- settingBulbColorMutex.release();
-
- return tmp;
- }
-
- public int getTemperature() {
-
- int tmp = 0;
- try {
- settingBulbTempuraturerMutex.acquire();
- tmp = currentTemperature;
- } catch (Exception e) {
- e.printStackTrace();
- }
- settingBulbTempuraturerMutex.release();
-
- return tmp;
- }
-
- public double getHueRangeLowerBound() {
- if (!didGetBulbVersion.get()) {
- return -1;
- }
- return ((double)hueLowerBound / 65535.0) * 360.0;
- }
-
- public double getHueRangeUpperBound() {
- if (!didGetBulbVersion.get()) {
- return -1;
- }
- return ((double)hueUpperBound / 65535.0) * 360.0;
- }
-
- public double getSaturationRangeLowerBound() {
- if (!didGetBulbVersion.get()) {
- return -1;
- }
- return ((double)saturationLowerBound / 65535.0) * 100.0;
- }
-
- public double getSaturationRangeUpperBound() {
- if (!didGetBulbVersion.get()) {
- return -1;
- }
- return ((double)saturationUpperBound / 65535.0) * 100.0;
- }
-
- public double getBrightnessRangeLowerBound() {
- if (!didGetBulbVersion.get()) {
- return -1;
- }
- return ((double)brightnessLowerBound / 65535.0) * 100.0;
- }
-
- public double getBrightnessRangeUpperBound() {
- if (!didGetBulbVersion.get()) {
- return -1;
- }
- return ((double)brightnessUpperBound / 65535.0) * 100.0;
- }
-
- public int getTemperatureRangeLowerBound() {
- if (!didGetBulbVersion.get()) {
- return -1;
- }
- return temperatureLowerBound;
- }
-
- public int getTemperatureRangeUpperBound() {
- if (!didGetBulbVersion.get()) {
- return -1;
- }
- return temperatureUpperBound;
- }
-
- public void setTemperature(int _temperature) {
-
- try {
- settingBulbTempuraturerMutex.acquire();
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- BulbColor newColor = new BulbColor(currentHue, currentSaturation, currentBrightness, _temperature);
- sendSetLightColorPacket(newColor, 250);
-
- currentTemperature = _temperature;
- stateDidChange = true;
-
- settingBulbTempuraturerMutex.release();
- }
-
- public void setColor(double _hue, double _saturation, double _brightness) {
-
- try {
- settingBulbColorMutex.acquire();
- } catch (Exception e) {
- e.printStackTrace();
- }
-
-
- _hue /= 360.0;
- _saturation /= 100.0;
- _brightness /= 100.0;
-
-
- int newHue = (int)(_hue * 65535.0);
- int newSaturation = (int)(_saturation * 65535.0);
- int newBrightness = (int)(_brightness * 65535.0);
-
- BulbColor newColor = new BulbColor(newHue, newSaturation, newBrightness, currentTemperature);
- sendSetLightColorPacket(newColor, 250);
-
- currentHue = newHue;
- currentSaturation = newSaturation;
- currentBrightness = newBrightness;
- stateDidChange = true;
-
- settingBulbColorMutex.release();
- }
-
-
- public void turnOff() {
-
- try {
- bulbStateMutex.acquire();
- bulbIsOn = false;
- sendSetLightPowerPacket(0, 0);
- stateDidChange = true;
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- bulbStateMutex.release();
- }
-
- public void turnOn() {
- try {
- bulbStateMutex.acquire();
- bulbIsOn = true;
- sendSetLightPowerPacket(65535, 0);
- stateDidChange = true;
-
- } catch (Exception e) {
- e.printStackTrace();
- }
-
-
- bulbStateMutex.release();
- }
-
- public boolean getState() {
-
- boolean tmp = false;
- try {
- bulbStateMutex.acquire();
- tmp = bulbIsOn;
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- bulbStateMutex.release();
-
- return tmp;
- }
-
-
- /*******************************************************************************************************************************************
- **
- ** Communication Helpers
- **
- *******************************************************************************************************************************************/
- private void recievedPacket(byte[] packetData) {
-
- byte[] headerBytes = new byte[36];
- for (int i = 0; i < 36; i++) {
- headerBytes[i] = packetData[i];
- }
-
- LifxHeader recHeader = new LifxHeader();
- recHeader.setFromBytes(headerBytes);
-
- // load the payload bytes (strip away the header)
- byte[] payloadBytes = new byte[recHeader.getSize()];
- for (int i = 36; i < recHeader.getSize(); i++) {
- payloadBytes[i - 36] = packetData[i];
- }
-
- System.out.println("Received: " + Integer.toString(recHeader.getType()));
-
- switch (recHeader.getType()) {
- case 3:
- DeviceStateService dat = parseDeviceStateServiceMessage(recHeader, payloadBytes);
- // System.out.println("Service: " + Integer.toString(dat.getService()));
- // System.out.println("Port : " + Long.toString(dat.getPort()));
- break;
-
-
- case 33:
- handleStateVersionMessageRecieved(recHeader, payloadBytes);
- break;
-
- case 35:
- parseDeviceStateInfoMessage(recHeader, payloadBytes);
- break;
-
-
- case 107:
- handleLightStateMessageRecieved(recHeader, payloadBytes);
- break;
-
- default:
- // System.out.println("unknown packet Type");
- }
-
- }
-
- private void sendPacket(byte[] packetData) {
- // System.out.println("About to send");
- sendSocketFlag = true;
-
- try {
- socketMutex.acquire();
- } catch (InterruptedException e) {
- System.out.println("mutex Error");
- }
-
- try {
- communicationSockect.sendData(packetData);
-
- } catch (IOException e) {
- System.out.println("Socket Send Error");
- }
-
- sendSocketFlag = false;
- socketMutex.release();
- }
-
-
- /**
- * Worker function which runs the while loop for receiving data from the bulb.
- * Is blocking
- */
- private void workerFunction() {
- LifxHeader h = new LifxHeader();
-
- try {
- // Need timeout on receives since we are not sure if a packet will be available
- // for processing so don't block waiting
- communicationSockect.setSoTimeout(50);
- } catch (IOException e) {
- }
-
- // Start the bulb in the off state
- turnOff();
-
-
- while (true) {
-
- // Check if we got the bulb version yet
- // could have requested it but message could have gotten lost (UDP)
- if (!didGetBulbVersion.get()) {
- long currentTime = (new Date().getTime()) / 1000;
- if ((currentTime - lastSentGetBulbVersionRequest) > GET_BULB_VERSION_RESEND_WAIT_SECONDS) {
- // Get the bulb version so we know what type of bulb this is.
- sendGetVersionPacket();
- lastSentGetBulbVersionRequest = currentTime;
- }
- }
-
- // Communication resource is busy so try again later
- if (sendSocketFlag) {
- continue;
- }
-
- try {
- socketMutex.acquire();
- } catch (InterruptedException e) {
- }
-
- byte[] dat = null;
- try {
- dat = communicationSockect.recieveData(1024);
- } catch (java.net.SocketTimeoutException e) {
- // Timeout occurred
-
- } catch (IOException e) {
- // Problem but might be able to recover??
- e.printStackTrace();
-
- }
-
- // Never forget to release!
- socketMutex.release();
-
- // A packed arrived
- if (dat != null) {
- recievedPacket(dat);
- }
-
- // If a state change occurred then request the bulb state to ensure that the
- // bulb did indeed change its state to the correct state
- if (stateDidChange) {
- sendGetLightStatePacket();
- }
-
- // Wait a bit as to not tie up system resources
- try {
- Thread.sleep(100);
- } catch (Exception e) {
-
- }
-
-
- }
- }
-
-
- public void init() {
-
- if (didAlreadyInit.compareAndSet(false, true) == false) {
- return; // already init
- }
-
- try {
- // Get the bulb address from the IoTSet
- Iterator itr = lb_addresses.iterator();
- IoTDeviceAddress deviceAddress = (IoTDeviceAddress)itr.next();
-
- System.out.println("Address: " + deviceAddress.getCompleteAddress());
-
- // Create the communication channel
- communicationSockect = new IoTUDP(deviceAddress);
-
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- // Launch the worker function in a separate thread.
- workerThread = new Thread(new Runnable() {
- public void run() {
- workerFunction();
- }
- });
- workerThread.start();
-
- }
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-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.LightBulb;
-
-public class LightBulb_Skeleton implements LightBulb {
-
- private LightBulb mainObj;
- private IoTRMIObject rmiObj;
-
- private String callbackAddress;
- private final static int object0Id = 0; //LightBulbSmart
- private static Integer[] object0Permission = { 2, 10, 1, 3, 11, 8, 12, 7, 13, 9, 6, 16, 17, 4, 0, 14, 15, 5 };
- private static List<Integer> set0Allowed;
-
-
- public LightBulb_Skeleton(LightBulb _mainObj, String _callbackAddress, int _port) throws Exception {
- mainObj = _mainObj;
- callbackAddress = _callbackAddress;
- rmiObj = new IoTRMIObject(_port);
- set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
- ___waitRequestInvokeMethod();
- }
-
- public void init() {
- mainObj.init();
- }
-
- public void turnOff() {
- mainObj.turnOff();
- }
-
- public void turnOn() {
- mainObj.turnOn();
- }
-
- public boolean getState() {
- return mainObj.getState();
- }
-
- public void setColor(double _hue, double _saturation, double _brightness) {
- mainObj.setColor(_hue, _saturation, _brightness);
- }
-
- public void setTemperature(int _temperature) {
- mainObj.setTemperature(_temperature);
- }
-
- public double getBrightness() {
- return mainObj.getBrightness();
- }
-
- public double getHue() {
- return mainObj.getHue();
- }
-
- public double getSaturation() {
- return mainObj.getSaturation();
- }
-
- public int getTemperature() {
- return mainObj.getTemperature();
- }
-
- public double getBrightnessRangeLowerBound() {
- return mainObj.getBrightnessRangeLowerBound();
- }
-
- public double getBrightnessRangeUpperBound() {
- return mainObj.getBrightnessRangeUpperBound();
- }
-
- public double getHueRangeLowerBound() {
- return mainObj.getHueRangeLowerBound();
- }
-
- public double getHueRangeUpperBound() {
- return mainObj.getHueRangeUpperBound();
- }
-
- public double getSaturationRangeLowerBound() {
- return mainObj.getSaturationRangeLowerBound();
- }
-
- public double getSaturationRangeUpperBound() {
- return mainObj.getSaturationRangeUpperBound();
- }
-
- public int getTemperatureRangeLowerBound() {
- return mainObj.getTemperatureRangeLowerBound();
- }
-
- public int getTemperatureRangeUpperBound() {
- return mainObj.getTemperatureRangeUpperBound();
- }
-
- public void ___init() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- init();
- }
-
- public void ___turnOff() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- turnOff();
- }
-
- public void ___turnOn() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- turnOn();
- }
-
- public void ___getState() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getState();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___setColor() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { double.class, double.class, double.class },
- new Class<?>[] { null, null, null });
- setColor((double) paramObj[0], (double) paramObj[1], (double) paramObj[2]);
- }
-
- public void ___setTemperature() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- setTemperature((int) paramObj[0]);
- }
-
- public void ___getBrightness() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getBrightness();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getHue() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getHue();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getSaturation() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getSaturation();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getTemperature() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getTemperature();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getBrightnessRangeLowerBound() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getBrightnessRangeLowerBound();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getBrightnessRangeUpperBound() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getBrightnessRangeUpperBound();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getHueRangeLowerBound() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getHueRangeLowerBound();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getHueRangeUpperBound() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getHueRangeUpperBound();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getSaturationRangeLowerBound() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getSaturationRangeLowerBound();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getSaturationRangeUpperBound() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getSaturationRangeUpperBound();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getTemperatureRangeLowerBound() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getTemperatureRangeLowerBound();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getTemperatureRangeUpperBound() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getTemperatureRangeUpperBound();
- rmiObj.sendReturnObj(retObj);
- }
-
- private void ___waitRequestInvokeMethod() throws IOException {
- while (true) {
- rmiObj.getMethodBytes();
- int _objectId = rmiObj.getObjectId();
- int methodId = rmiObj.getMethodId();
- if (_objectId == object0Id) {
- if (!set0Allowed.contains(methodId)) {
- throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
- }
- }
- else {
- throw new Error("Object Id: " + _objectId + " not recognized!");
- }
- switch (methodId) {
- case 0: ___init(); break;
- case 1: ___turnOff(); break;
- case 2: ___turnOn(); break;
- case 3: ___getState(); break;
- case 4: ___setColor(); break;
- case 5: ___setTemperature(); break;
- case 6: ___getBrightness(); break;
- case 7: ___getHue(); break;
- case 8: ___getSaturation(); break;
- case 9: ___getTemperature(); break;
- case 10: ___getBrightnessRangeLowerBound(); break;
- case 11: ___getBrightnessRangeUpperBound(); break;
- case 12: ___getHueRangeLowerBound(); break;
- case 13: ___getHueRangeUpperBound(); break;
- case 14: ___getSaturationRangeLowerBound(); break;
- case 15: ___getSaturationRangeUpperBound(); break;
- case 16: ___getTemperatureRangeLowerBound(); break;
- case 17: ___getTemperatureRangeUpperBound(); break;
- default:
- throw new Error("Method Id " + methodId + " not recognized!");
- }
- }
- }
-
-}
+++ /dev/null
-package iotcode.LifxLightBulb;
-
-public class LightState {
- private final BulbColor color;
- private final int power;
- private final String label;
-
- public LightState(BulbColor _color, int _power, String _label) {
- color = _color;
- power = _power;
- label = _label;
- }
-
- public BulbColor getColor() {
- return color;
- }
-
- public int getPower() {
- return power;
- }
-
- public String getLabel() {
- return label;
- }
-}
+++ /dev/null
-BASE = ../..
-
-include $(BASE)/common.mk
-
-BOOFDIR := ../libs/boofcv_libs
-BOOFJARS := $(BOOFDIR)/BoofCV-feature-0.21.jar:$(BOOFDIR)/BoofCV-io-0.21.jar:$(BOOFDIR)/BoofCV-visualize-0.21.jar:$(BOOFDIR)/BoofCV-ip-0.21.jar
-JLAYERDIR := ../libs/jlayer_libs
-JLAYERJARS := $(JLAYERDIR)/jl1.0.1.jar
-JFLAGS = -d $(BIN_DIR) -cp $(BIN_DIR):$(PHONEJARS):$(BOOFJARS):$(JLAYERJARS)
-JARFLAGS = cf
-INTFACE_DIR = iotcode/interfaces
-
-all: light camera labroom greenlawn sprinkler moisture weathergateway audioroom gpsgateway ihome homeroom alarm motion multipurpose waterleak
-
-# Compile
-#
-PHONY += light
-light:
- $(JAVAC) $(JFLAGS) LifxLightBulb/*.java
- cp LifxLightBulb/LifxLightBulb.config $(BIN_DIR)/iotcode/LifxLightBulb
- cd $(BIN_DIR)/iotcode/LifxLightBulb; $(JAR) $(JARFLAGS) LifxLightBulb.jar ../../iotcode/LifxLightBulb/*.class ../../iotcode/interfaces/LightBulb*.class
-
-PHONY += camera
-camera:
- $(JAVAC) $(JFLAGS) AmcrestCamera/*.java
- cp AmcrestCamera/AmcrestCamera.config $(BIN_DIR)/iotcode/AmcrestCamera
- cd $(BIN_DIR)/iotcode/AmcrestCamera; $(JAR) $(JARFLAGS) AmcrestCamera.jar ../../iotcode/AmcrestCamera/*.class ../../iotcode/interfaces/Camera*.class ../../iotcode/interfaces/Resolution*.class
-
-PHONY += labroom
-labroom:
- $(JAVAC) $(JFLAGS) LabRoom/*.java
- cp LabRoom/LabRoom.config $(BIN_DIR)/iotcode/LabRoom
- cd $(BIN_DIR)/iotcode/LabRoom; $(JAR) $(JARFLAGS) LabRoom.jar ../../iotcode/LabRoom/*.class ../../iotcode/interfaces/Room*.class
-
-PHONY += greenlawn
-greenlawn:
- $(JAVAC) $(JFLAGS) GreenLawn/*.java
- cp GreenLawn/GreenLawn.config $(BIN_DIR)/iotcode/GreenLawn
- cd $(BIN_DIR)/iotcode/GreenLawn; $(JAR) $(JARFLAGS) GreenLawn.jar ../../iotcode/GreenLawn/*.class ../../iotcode/interfaces/Lawn*.class
-
-PHONY += sprinkler
-sprinkler:
- $(JAVAC) $(JFLAGS) EspSprinkler/*.java
- cp EspSprinkler/EspSprinkler.config $(BIN_DIR)/iotcode/EspSprinkler
- cd $(BIN_DIR)/iotcode/EspSprinkler; $(JAR) $(JARFLAGS) EspSprinkler.jar ../../iotcode/EspSprinkler/*.class ../../iotcode/interfaces/Sprinkler*.class ../../iotcode/interfaces/ZoneState*.class
-
-PHONY += moisture
-moisture:
- $(JAVAC) $(JFLAGS) SpruceSensor/*.java
- cp SpruceSensor/SpruceSensor.config $(BIN_DIR)/iotcode/SpruceSensor
- cd $(BIN_DIR)/iotcode/SpruceSensor; $(JAR) $(JARFLAGS) SpruceSensor.jar ../../iotcode/SpruceSensor/*.class ../../iotcode/interfaces/MoistureSensor*.class ../../iotcode/interfaces/Camera*.class ../../IrrigationController/MotionDetection*.class
-
-PHONY += weathergateway
-weathergateway:
- $(JAVAC) $(JFLAGS) WeatherPhoneGateway/*.java
- 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 += homeroom
-homeroom:
- $(JAVAC) $(JFLAGS) HomeRoom/*.java
- cp HomeRoom/HomeRoom.config $(BIN_DIR)/iotcode/HomeRoom
- cd $(BIN_DIR)/iotcode/HomeRoom; $(JAR) $(JARFLAGS) HomeRoom.jar ../../iotcode/HomeRoom/*.class ../../iotcode/interfaces/Room*.class
-
-PHONY += alarm
-alarm:
- $(JAVAC) $(JFLAGS) EspAlarm/*.java
- cp EspAlarm/EspAlarm.config $(BIN_DIR)/iotcode/EspAlarm
- cd $(BIN_DIR)/iotcode/EspAlarm; $(JAR) $(JARFLAGS) EspAlarm.jar ../../iotcode/EspAlarm/*.class ../../iotcode/interfaces/Alarm*.class ../../iotcode/interfaces/ZoneState*.class
-
-PHONY += motion
-motion:
- $(JAVAC) $(JFLAGS) MotionSensor/*.java
- cp MotionSensor/MotionSensor.config $(BIN_DIR)/iotcode/MotionSensor
- cd $(BIN_DIR)/iotcode/MotionSensor; $(JAR) $(JARFLAGS) MotionSensor.jar ../../iotcode/MotionSensor/*.class ../../iotcode/interfaces/SmartthingsSensor*.class ../../iotcode/interfaces/Camera*.class ../../IrrigationController/MotionDetection*.class
-
-PHONY += multipurpose
-multipurpose:
- $(JAVAC) $(JFLAGS) MultipurposeSensor/*.java
- cp MultipurposeSensor/MultipurposeSensor.config $(BIN_DIR)/iotcode/MultipurposeSensor
- cd $(BIN_DIR)/iotcode/MultipurposeSensor; $(JAR) $(JARFLAGS) MultipurposeSensor.jar ../../iotcode/MultipurposeSensor/*.class ../../iotcode/interfaces/SmartthingsSensor*.class ../../iotcode/interfaces/Camera*.class ../../IrrigationController/MotionDetection*.class
-
-PHONY += waterleak
-waterleak:
- $(JAVAC) $(JFLAGS) WaterLeakSensor/*.java
- cp WaterLeakSensor/WaterLeakSensor.config $(BIN_DIR)/iotcode/WaterLeakSensor
- cd $(BIN_DIR)/iotcode/WaterLeakSensor; $(JAR) $(JARFLAGS) WaterLeakSensor.jar ../../iotcode/WaterLeakSensor/*.class ../../iotcode/interfaces/SmartthingsSensor*.class ../../iotcode/interfaces/Camera*.class ../../IrrigationController/MotionDetection*.class
-
-.PHONY: $(PHONY)
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=SmartthingsSensor
-# Stub
-INTERFACE_STUB_CLASS=SmartthingsSensorSmart
+++ /dev/null
-package iotcode.MotionSensor;
-
-// Standard Java Packages
-import java.util.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Semaphore;
-
-// Checker annotations
-//import iotchecker.qual.*;
-import iotcode.annotation.*;
-
-// IoT Packages
-import iotruntime.slave.*;
-import iotcode.interfaces.*;
-import iotruntime.zigbee.*;
-
-/** Class Smartthings sensor driver for Smartthings sensor devices.
- *
- * @author Changwoo Lee, Rahmadi Trimananda <rtrimana @ uci.edu>
- * @version 1.0
- * @since 2016-12-01
- */
-public class MotionSensor implements IoTZigbeeCallback, SmartthingsSensor {
-
- private final int TIMEOUT_FOR_RESEND_MSEC = 900;
-
- private IoTZigbee zigConnection = null;
- private boolean didClose; // make sure that the clean up was done correctly
- private boolean detectStatus = false;
-
- private int detectedValue = 0;
- private Date timestampOfLastDetecting = null;
-
- private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
- private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
- private AtomicBoolean didWriteAttrb = new AtomicBoolean(false);
- private AtomicBoolean didMatchDscr = new AtomicBoolean(false);
- static Semaphore gettingLatestDataMutex = new Semaphore(1);
-
- private List < SmartthingsSensorSmartCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorSmartCallback > ();
-
- private int sensorId = 0;
-
- @config private IoTSet<IoTDeviceAddress> motionSensorUdpAddress;
- @config private IoTSet<IoTZigbeeAddress> motionSensorZigbeeAddress;
-
- //public MotionSensor(IoTSet<IoTDeviceAddress> dSet, IoTSet<IoTZigbeeAddress> zigSet) {
- //motionSensorUdpAddress = dSet;
- //motionSensorZigbeeAddress = zigSet;
- //}
- public MotionSensor() {
- }
-
- public void init() {
-
- if (didAlreadyInit.compareAndSet(false, true) == false) {
- return; // already init
- }
-
- didAlreadyClose.set(false);
-
- try {
- Iterator itrUdp = motionSensorUdpAddress.iterator();
- Iterator itrZig = motionSensorZigbeeAddress.iterator();
-
- zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
-
- // DEBUG
- System.out.println("DEBUG: Allocate iterators to print out addresses!");
- Iterator itrDebugUdp = motionSensorUdpAddress.iterator();
- IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
- System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
- System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
- System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
-
- Iterator itrDebugZig = motionSensorZigbeeAddress.iterator();
- IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
- System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
-
- zigConnection.registerCallback(this);
- System.out.println("Register callback!");
- zigConnection.init();
- System.out.println("Initialized!");
-
- //made by changwoo
- sleep(10);
-
- System.out.println("Sending Management Permit Joining Request");
- for(int z=0; z<3; z++){
- zigConnection.sendManagementPermitJoiningRequest(0x0001, 0x0036, 0x00);
- sleep(0);
- }
-
- //made by changwoo
- while (!didWriteAttrb.get()) {
- System.out.println("Sending Write Attribute Request");
- zigConnection.sendWriteAttributesCommand(0x0002, 0x0500, 0x0104, 0x01);
- sleep(0);
- }
-
- //made by changwoo
- System.out.println("Sending Enrollment Reponse");
- zigConnection.sendEnrollmentResponse(0x0003, 0x0500, 0x0104, 0x01);
- sleep(0);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- //made by changwoo
- private void sleep(int multipleTime){
- if(multipleTime<=0){
- multipleTime=1;
- }
- try{
- Thread.sleep(TIMEOUT_FOR_RESEND_MSEC*multipleTime);
- } catch(Exception e){
- e.printStackTrace();
- }
- }
-
- public void close() {
-
- if (didAlreadyClose.compareAndSet(false, true) == false) {
- return; // already init
- }
-
- didAlreadyInit.set(false);
-
-
- try {
- zigConnection.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
-
- public void Finalize() {
- if (!didClose) {
- close();
- }
- }
-
- public void setId(int id) {
-
- sensorId = id;
-
- }
-
- public int getId() {
-
- return sensorId;
-
- }
-
- public int getValue() {
-
- int tmp = 0;
- try {
- gettingLatestDataMutex.acquire();
- tmp = detectedValue;
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- gettingLatestDataMutex.release();
-
- return tmp;
- }
-
- // MotionSensor:
- // - 24 = no motion = false
- // - 26 = motion = true
- // After getting 26, if there is no motion for ~12 seconds then we get back 24
- public boolean isActiveValue() {
-
- int tmp = getValue();
- if (tmp == 26)
- detectStatus = true;
- else // Getting 24 here
- detectStatus = false;
-
- return detectStatus;
- }
-
- public long getTimestampOfLastReading() {
-
- Date tmp = null;
- try {
- gettingLatestDataMutex.acquire();
- tmp = (Date)timestampOfLastDetecting.clone();
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- gettingLatestDataMutex.release();
- long retLong = tmp.getTime();
-
- return retLong;
- }
-
- public void newMessageAvailable(IoTZigbeeMessage _zm) {
-
- //made by changwoo
- if(_zm instanceof IoTZigbeeMessageZclZoneStatusChangeNotification){
- IoTZigbeeMessageZclZoneStatusChangeNotification message = (IoTZigbeeMessageZclZoneStatusChangeNotification)_zm;
- if(message.getSuccessOrFail()){
- //do something!
-
- try {
- gettingLatestDataMutex.acquire();
- detectedValue = message.getStatus();
- timestampOfLastDetecting = new Date();
- } catch (Exception e) {
- e.printStackTrace();
- }
- gettingLatestDataMutex.release();
- try {
- for (SmartthingsSensorSmartCallback cb : callbackList) {
- cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }//if
-
- //made by changwoo
- } else if (_zm instanceof IoTZigbeeMessageZclWriteAttributesResponse) {
- IoTZigbeeMessageZclWriteAttributesResponse message = (IoTZigbeeMessageZclWriteAttributesResponse)_zm;
- if (message.getSuccessOrFail()) {
- didWriteAttrb.set(true);
- }
- }
- }
-
- public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
- callbackList.add(_callbackTo);
- }
-}
+++ /dev/null
-package iotcode.MotionSensor;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import iotrmi.Java.IoTRMICall;
-import iotrmi.Java.IoTRMIObject;
-
-import iotcode.interfaces.*;
-
-public class SmartthingsSensorSmartCallback_CallbackStub implements SmartthingsSensorSmartCallback {
-
- private IoTRMICall rmiCall;
- private String callbackAddress;
- private int[] ports;
-
- private int objectId = 0;
-
-
- public SmartthingsSensorSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
- callbackAddress = _callbackAddress;
- objectId = _objectId;
- rmiCall = _rmiCall;
- ports = _ports;
- }
-
- public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
- int methodId = 0;
- Class<?> retType = void.class;
- Class<?>[] paramCls = new Class<?>[] { int.class, int.class, boolean.class };
- Object[] paramObj = new Object[] { _sensorId, _value, _activeValue };
- rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
- }
-
-}
+++ /dev/null
-package iotcode.MotionSensor;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import iotrmi.Java.IoTRMICall;
-import iotrmi.Java.IoTRMIObject;
-
-import iotcode.interfaces.*;
-
-public class SmartthingsSensor_Skeleton implements SmartthingsSensor {
-
- private SmartthingsSensor mainObj;
- private IoTRMIObject rmiObj;
-
- private String callbackAddress;
- private int objIdCnt = 0;
- private IoTRMICall rmiCall;
- private int[] ports;
-
- private final static int object0Id = 0; //SmartthingsSensorSmart
- private static Integer[] object0Permission = { 3, 2, 5, 6, 1, 4, 0 };
- private static List<Integer> set0Allowed;
-
-
- public SmartthingsSensor_Skeleton(SmartthingsSensor _mainObj, String _callbackAddress, int _port) throws Exception {
- mainObj = _mainObj;
- callbackAddress = _callbackAddress;
- rmiObj = new IoTRMIObject(_port);
- set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
- set0Allowed.add(-9998);
- ___waitRequestInvokeMethod();
- }
-
- public void init() {
- mainObj.init();
- }
-
- public int getValue() {
- return mainObj.getValue();
- }
-
- public boolean isActiveValue() {
- return mainObj.isActiveValue();
- }
-
- public long getTimestampOfLastReading() {
- return mainObj.getTimestampOfLastReading();
- }
-
- public void setId(int id) {
- mainObj.setId(id);
- }
-
- public int getId() {
- return mainObj.getId();
- }
-
- public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
- mainObj.registerCallback(_callbackTo);
- }
-
- public void ___regCB() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
- ports = (int[]) paramObj[0];
- rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
- }
-
- public void ___init() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- init();
- }
-
- public void ___getValue() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getValue();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___isActiveValue() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = isActiveValue();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getTimestampOfLastReading() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getTimestampOfLastReading();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___setId() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- setId((int) paramObj[0]);
- }
-
- public void ___getId() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getId();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___registerCallback() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- try {
- SmartthingsSensorSmartCallback stub0 = new SmartthingsSensorSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
- objIdCnt++;
- registerCallback(stub0);
- } catch(Exception ex) {
- ex.printStackTrace();
- throw new Error("Exception from callback object instantiation!");
- }
- }
-
- private void ___waitRequestInvokeMethod() throws IOException {
- while (true) {
- rmiObj.getMethodBytes();
- int _objectId = rmiObj.getObjectId();
- int methodId = rmiObj.getMethodId();
- if (_objectId == object0Id) {
- if (!set0Allowed.contains(methodId)) {
- throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
- }
- }
- else {
- throw new Error("Object Id: " + _objectId + " not recognized!");
- }
- switch (methodId) {
- case 0: ___init(); break;
- case 1: ___getValue(); break;
- case 2: ___isActiveValue(); break;
- case 3: ___getTimestampOfLastReading(); break;
- case 4: ___setId(); break;
- case 5: ___getId(); break;
- case 6: ___registerCallback(); break;
- case -9998: ___regCB(); break;
- default:
- throw new Error("Method Id " + methodId + " not recognized!");
- }
- }
- }
-
-}
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=SmartthingsSensor
-# Stub
-INTERFACE_STUB_CLASS=SmartthingsSensorSmart
+++ /dev/null
-package iotcode.MultipurposeSensor;
-
-// Standard Java Packages
-import java.util.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Semaphore;
-
-// Checker annotations
-//import iotchecker.qual.*;
-import iotcode.annotation.*;
-
-// IoT Packages
-import iotruntime.slave.*;
-import iotcode.interfaces.*;
-import iotruntime.zigbee.*;
-
-/** Class Smartthings sensor driver for Smartthings sensor devices.
- *
- * @author Changwoo Lee, Rahmadi Trimananda <rtrimana @ uci.edu>
- * @version 1.0
- * @since 2016-12-01
- */
-public class MultipurposeSensor implements IoTZigbeeCallback, SmartthingsSensor {
-
- private final int TIMEOUT_FOR_RESEND_MSEC = 900;
-
- private IoTZigbee zigConnection = null;
- private boolean didClose; // make sure that the clean up was done correctly
- private boolean detectStatus = false;
-
- private int detectedValue = 0;
- private Date timestampOfLastDetecting = null;
-
- private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
- private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
- private AtomicBoolean didWriteAttrb = new AtomicBoolean(false);
- private AtomicBoolean didMatchDscr = new AtomicBoolean(false);
- static Semaphore gettingLatestDataMutex = new Semaphore(1);
-
- private List < SmartthingsSensorSmartCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorSmartCallback > ();
-
- private int sensorId = 0;
-
- @config private IoTSet<IoTDeviceAddress> multipurposeSensorUdpAddress;
- @config private IoTSet<IoTZigbeeAddress> multipurposeSensorZigbeeAddress;
-
- //public MultipurposeSensor(IoTSet<IoTDeviceAddress> dSet, IoTSet<IoTZigbeeAddress> zigSet) {
- //multipurposeSensorUdpAddress = dSet;
- //multipurposeSensorZigbeeAddress = zigSet;
- //}
- public MultipurposeSensor() {
- }
-
- public void init() {
-
- if (didAlreadyInit.compareAndSet(false, true) == false) {
- return; // already init
- }
-
- didAlreadyClose.set(false);
-
- try {
- Iterator itrUdp = multipurposeSensorUdpAddress.iterator();
- Iterator itrZig = multipurposeSensorZigbeeAddress.iterator();
-
- zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
-
- // DEBUG
- System.out.println("DEBUG: Allocate iterators to print out addresses!");
- Iterator itrDebugUdp = multipurposeSensorUdpAddress.iterator();
- IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
- System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
- System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
- System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
-
- Iterator itrDebugZig = multipurposeSensorZigbeeAddress.iterator();
- IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
- System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
-
- zigConnection.registerCallback(this);
- System.out.println("Register callback!");
- zigConnection.init();
- System.out.println("Initialized!");
-
- //made by changwoo
- sleep(10);
- System.out.println("Sending Management Permit Joining Request");
- for(int z=0; z<3; z++){
- zigConnection.sendManagementPermitJoiningRequest(0x0001, 0x0036, 0x00);
- sleep(0);
- }
-
- //made by changwoo
- while (!didWriteAttrb.get()) {
- System.out.println("Sending Write Attribute Request");
- zigConnection.sendWriteAttributesCommand(0x0002, 0x0500, 0x0104, 0x01);
- sleep(0);
- }
-
- //made by changwoo
- System.out.println("Sending Enrollment Reponse");
- zigConnection.sendEnrollmentResponse(0x0003, 0x0500, 0x0104, 0x01);
- sleep(0);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- //made by changwoo
- private void sleep(int multipleTime){
- if(multipleTime<=0){
- multipleTime=1;
- }
- try{
- Thread.sleep(TIMEOUT_FOR_RESEND_MSEC*multipleTime);
- } catch(Exception e){
- e.printStackTrace();
- }
- }
-
- public void close() {
-
- if (didAlreadyClose.compareAndSet(false, true) == false) {
- return; // already init
- }
-
- didAlreadyInit.set(false);
-
-
- try {
- zigConnection.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public void Finalize() {
- if (!didClose) {
- close();
- }
- }
-
- public void setId(int id) {
-
- sensorId = id;
-
- }
-
- public int getId() {
-
- return sensorId;
-
- }
-
- public int getValue() {
-
- int tmp = 0;
- try {
- gettingLatestDataMutex.acquire();
- tmp = detectedValue;
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- gettingLatestDataMutex.release();
-
- return tmp;
- }
-
- // MultipurposeSensor:
- // - 24 = close = false
- // - 25 = open = true
- public boolean isActiveValue() {
-
- int tmp = getValue();
- if (tmp == 25)
- detectStatus = true;
- else // Getting 24 here
- detectStatus = false;
-
- return detectStatus;
- }
-
- public long getTimestampOfLastReading() {
-
- Date tmp = null;
- try {
- gettingLatestDataMutex.acquire();
- tmp = (Date)timestampOfLastDetecting.clone();
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- gettingLatestDataMutex.release();
- long retLong = tmp.getTime();
-
- return retLong;
- }
-
- public void newMessageAvailable(IoTZigbeeMessage _zm) {
-
- //made by changwoo
- if(_zm instanceof IoTZigbeeMessageZclZoneStatusChangeNotification){
- IoTZigbeeMessageZclZoneStatusChangeNotification message = (IoTZigbeeMessageZclZoneStatusChangeNotification)_zm;
- if(message.getSuccessOrFail()){
- //do something!
- try {
- gettingLatestDataMutex.acquire();
- detectedValue = message.getStatus();
- timestampOfLastDetecting = new Date();
- } catch (Exception e) {
- e.printStackTrace();
- }
- gettingLatestDataMutex.release();
- try {
- for (SmartthingsSensorSmartCallback cb : callbackList) {
- cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }//if
-
- //made by changwoo
- }//if
- else if (_zm instanceof IoTZigbeeMessageZclWriteAttributesResponse) {
- IoTZigbeeMessageZclWriteAttributesResponse message = (IoTZigbeeMessageZclWriteAttributesResponse)_zm;
- if (message.getSuccessOrFail()) {
- didWriteAttrb.set(true);
- }//if
- }//else if
- }
-
- public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
- callbackList.add(_callbackTo);
- }
-}
+++ /dev/null
-package iotcode.MultipurposeSensor;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import iotrmi.Java.IoTRMICall;
-import iotrmi.Java.IoTRMIObject;
-
-import iotcode.interfaces.*;
-
-public class SmartthingsSensorSmartCallback_CallbackStub implements SmartthingsSensorSmartCallback {
-
- private IoTRMICall rmiCall;
- private String callbackAddress;
- private int[] ports;
-
- private int objectId = 0;
-
-
- public SmartthingsSensorSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
- callbackAddress = _callbackAddress;
- objectId = _objectId;
- rmiCall = _rmiCall;
- ports = _ports;
- }
-
- public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
- int methodId = 0;
- Class<?> retType = void.class;
- Class<?>[] paramCls = new Class<?>[] { int.class, int.class, boolean.class };
- Object[] paramObj = new Object[] { _sensorId, _value, _activeValue };
- rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
- }
-
-}
+++ /dev/null
-package iotcode.MultipurposeSensor;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import iotrmi.Java.IoTRMICall;
-import iotrmi.Java.IoTRMIObject;
-
-import iotcode.interfaces.*;
-
-public class SmartthingsSensor_Skeleton implements SmartthingsSensor {
-
- private SmartthingsSensor mainObj;
- private IoTRMIObject rmiObj;
-
- private String callbackAddress;
- private int objIdCnt = 0;
- private IoTRMICall rmiCall;
- private int[] ports;
-
- private final static int object0Id = 0; //SmartthingsSensorSmart
- private static Integer[] object0Permission = { 3, 2, 5, 6, 1, 4, 0 };
- private static List<Integer> set0Allowed;
-
-
- public SmartthingsSensor_Skeleton(SmartthingsSensor _mainObj, String _callbackAddress, int _port) throws Exception {
- mainObj = _mainObj;
- callbackAddress = _callbackAddress;
- rmiObj = new IoTRMIObject(_port);
- set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
- set0Allowed.add(-9998);
- ___waitRequestInvokeMethod();
- }
-
- public void init() {
- mainObj.init();
- }
-
- public int getValue() {
- return mainObj.getValue();
- }
-
- public boolean isActiveValue() {
- return mainObj.isActiveValue();
- }
-
- public long getTimestampOfLastReading() {
- return mainObj.getTimestampOfLastReading();
- }
-
- public void setId(int id) {
- mainObj.setId(id);
- }
-
- public int getId() {
- return mainObj.getId();
- }
-
- public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
- mainObj.registerCallback(_callbackTo);
- }
-
- public void ___regCB() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
- ports = (int[]) paramObj[0];
- rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
- }
-
- public void ___init() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- init();
- }
-
- public void ___getValue() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getValue();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___isActiveValue() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = isActiveValue();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getTimestampOfLastReading() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getTimestampOfLastReading();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___setId() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- setId((int) paramObj[0]);
- }
-
- public void ___getId() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getId();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___registerCallback() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- try {
- SmartthingsSensorSmartCallback stub0 = new SmartthingsSensorSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
- objIdCnt++;
- registerCallback(stub0);
- } catch(Exception ex) {
- ex.printStackTrace();
- throw new Error("Exception from callback object instantiation!");
- }
- }
-
- private void ___waitRequestInvokeMethod() throws IOException {
- while (true) {
- rmiObj.getMethodBytes();
- int _objectId = rmiObj.getObjectId();
- int methodId = rmiObj.getMethodId();
- if (_objectId == object0Id) {
- if (!set0Allowed.contains(methodId)) {
- throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
- }
- }
- else {
- throw new Error("Object Id: " + _objectId + " not recognized!");
- }
- switch (methodId) {
- case 0: ___init(); break;
- case 1: ___getValue(); break;
- case 2: ___isActiveValue(); break;
- case 3: ___getTimestampOfLastReading(); break;
- case 4: ___setId(); break;
- case 5: ___getId(); break;
- case 6: ___registerCallback(); break;
- case -9998: ___regCB(); break;
- default:
- throw new Error("Method Id " + methodId + " not recognized!");
- }
- }
- }
-
-}
+++ /dev/null
-package iotcode.SpruceSensor;
-
-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 MoistureSensorSmartCallback_CallbackStub implements MoistureSensorSmartCallback {
-
- private IoTRMICall rmiCall;
- private String callbackAddress;
- private int[] ports;
-
- private int objectId = 0;
-
-
- public MoistureSensorSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
- callbackAddress = _callbackAddress;
- objectId = _objectId;
- rmiCall = _rmiCall;
- ports = _ports;
- }
-
- public void newReadingAvailable(int sensorId, float moisture, long timeStampOfLastReading) {
- int methodId = 0;
- Class<?> retType = void.class;
- Class<?>[] paramCls = new Class<?>[] { int.class, float.class, long.class };
- Object[] paramObj = new Object[] { sensorId, moisture, timeStampOfLastReading };
- rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
- }
-
-}
+++ /dev/null
-package iotcode.SpruceSensor;
-
-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 MoistureSensor_Skeleton implements MoistureSensor {
-
- private MoistureSensor mainObj;
- private IoTRMIObject rmiObj;
-
- private String callbackAddress;
- private int objIdCnt = 0;
- private IoTRMICall rmiCall;
- private int[] ports;
-
- private final static int object0Id = 0; //MoistureSensorSmart
- private static Integer[] object0Permission = { 2, 4, 5, 1, 3, 0 };
- private static List<Integer> set0Allowed;
-
-
- public MoistureSensor_Skeleton(MoistureSensor _mainObj, String _callbackAddress, int _port) throws Exception {
- mainObj = _mainObj;
- callbackAddress = _callbackAddress;
- rmiObj = new IoTRMIObject(_port);
- set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
- set0Allowed.add(-9998);
- ___waitRequestInvokeMethod();
- }
-
- public void init() {
- mainObj.init();
- }
-
- public float getMoisture() {
- return mainObj.getMoisture();
- }
-
- public long getTimestampOfLastReading() {
- return mainObj.getTimestampOfLastReading();
- }
-
- public void setId(int id) {
- mainObj.setId(id);
- }
-
- public int getId() {
- return mainObj.getId();
- }
-
- public void registerCallback(MoistureSensorSmartCallback _callbackTo) {
- mainObj.registerCallback(_callbackTo);
- }
-
- public void ___regCB() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
- ports = (int[]) paramObj[0];
- rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
- }
-
- public void ___init() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- init();
- }
-
- public void ___getMoisture() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getMoisture();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getTimestampOfLastReading() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getTimestampOfLastReading();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___setId() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- setId((int) paramObj[0]);
- }
-
- public void ___getId() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getId();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___registerCallback() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- try {
- MoistureSensorSmartCallback stub0 = new MoistureSensorSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
- objIdCnt++;
- registerCallback(stub0);
- } catch(Exception ex) {
- ex.printStackTrace();
- throw new Error("Exception from callback object instantiation!");
- }
- }
-
- private void ___waitRequestInvokeMethod() throws IOException {
- while (true) {
- rmiObj.getMethodBytes();
- int _objectId = rmiObj.getObjectId();
- int methodId = rmiObj.getMethodId();
- if (_objectId == object0Id) {
- if (!set0Allowed.contains(methodId)) {
- throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
- }
- }
- else {
- throw new Error("Object Id: " + _objectId + " not recognized!");
- }
- switch (methodId) {
- case 0: ___init(); break;
- case 1: ___getMoisture(); break;
- case 2: ___getTimestampOfLastReading(); break;
- case 3: ___setId(); break;
- case 4: ___getId(); break;
- case 5: ___registerCallback(); break;
- case -9998: ___regCB(); break;
- default:
- throw new Error("Method Id " + methodId + " not recognized!");
- }
- }
- }
-
-}
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=MoistureSensor
-# Stub
-INTERFACE_STUB_CLASS=MoistureSensorSmart
+++ /dev/null
-package iotcode.SpruceSensor;
-
-// Standard Java Packages
-import java.util.Iterator;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Semaphore;
-
-
-// Checker annotations
-//import iotchecker.qual.*;
-
-// IoT Packages
-import iotruntime.slave.*;
-import iotcode.interfaces.MoistureSensor;
-import iotcode.interfaces.MoistureSensorSmartCallback;
-import iotruntime.zigbee.*;
-import iotcode.annotation.*;
-
-public class SpruceSensor implements IoTZigbeeCallback, MoistureSensor {
-
- private final int TIMEOUT_FOR_RESEND_MSEC = 1000;
-
- private IoTZigbee zigConnection = null;
- private boolean didClose; // make sure that the clean up was done correctly
-
- private float humidity = 0;
- private Date timestampOfLastHumidity = null;
-
- private AtomicBoolean didBind = new AtomicBoolean(false);
- private AtomicBoolean didConfigureReporting = new AtomicBoolean(false);
- private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
- private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
- static Semaphore gettingLatestDataMutex = new Semaphore(1);
-
- private List < MoistureSensorSmartCallback > callbackList = new CopyOnWriteArrayList < MoistureSensorSmartCallback > ();
-
- private int sensorId = 0;
-
- @config private IoTSet<IoTDeviceAddress> devUdpAddress;
- @config private IoTSet<IoTZigbeeAddress> devZigbeeAddress;
-
- public SpruceSensor() {
- }
-
- public void init() {
-
- if (didAlreadyInit.compareAndSet(false, true) == false) {
- return; // already init
- }
-
- didAlreadyClose.set(false);
-
- try {
- Iterator itrUdp = devUdpAddress.iterator();
- Iterator itrZig = devZigbeeAddress.iterator();
-
- zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
-
- // DEBUG
- System.out.println("DEBUG: Allocate iterators to print out addresses!");
- Iterator itrDebugUdp = devUdpAddress.iterator();
- IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
- System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
- System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
- System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
-
- Iterator itrDebugZig = devZigbeeAddress.iterator();
- IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
- System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
-
- zigConnection.registerCallback(this);
- System.out.println("Register callback!");
- zigConnection.init();
- System.out.println("Initialized!");
-
- while (!didBind.get()) {
- zigConnection.sendBindRequest(0x0001, 0x0405, 0x01);
- try {
- Thread.sleep(TIMEOUT_FOR_RESEND_MSEC);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- while (!didConfigureReporting.get()) {
- zigConnection.sendConfigureReportingCommand(0x0001, 0x0405, 0x0104, 0x01, 0x0000, 0x21, 0x0001, 0x0001, null);
- try {
- Thread.sleep(TIMEOUT_FOR_RESEND_MSEC);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public void close() {
-
- if (didAlreadyClose.compareAndSet(false, true) == false) {
- return; // already init
- }
-
- didAlreadyInit.set(false);
-
-
- try {
- zigConnection.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public void Finalize() {
- if (!didClose) {
- close();
- }
- }
-
- public void setId(int id) {
-
- sensorId = id;
-
- }
-
- public int getId() {
-
- return sensorId;
-
- }
-
- public float getMoisture() {
-
- float tmp = 0;
- try {
- gettingLatestDataMutex.acquire();
- tmp = humidity;
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- gettingLatestDataMutex.release();
-
- return tmp;
- }
-
- public long getTimestampOfLastReading() {
-
- Date tmp = null;
- try {
- gettingLatestDataMutex.acquire();
- tmp = (Date)timestampOfLastHumidity.clone();
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- gettingLatestDataMutex.release();
- long retLong = tmp.getTime();
-
- return retLong;
- }
-
- public void newMessageAvailable(IoTZigbeeMessage _zm) {
-
- if (_zm instanceof IoTZigbeeMessageZdoBindResponse) {
- IoTZigbeeMessageZdoBindResponse message = (IoTZigbeeMessageZdoBindResponse)_zm;
- if (message.getSucceeded()) {
- didBind.set(true);
- }
-
- } else if (_zm instanceof IoTZigbeeMessageZclConfigureReportingResponse) {
- IoTZigbeeMessageZclConfigureReportingResponse message = (IoTZigbeeMessageZclConfigureReportingResponse)_zm;
- if (message.getAllSuccess()) {
- didConfigureReporting.set(true);
- }
-
- } else if (_zm instanceof IoTZigbeeMessageZclReportAttributes) {
- IoTZigbeeMessageZclReportAttributes message = (IoTZigbeeMessageZclReportAttributes)_zm;
- List <IoTZigbeeMessageZclReportAttributes.Attribute> attrList = message.getAttributes();
-
- if (attrList.size() == 1) {
- if (attrList.get(0).getAttributeId() == 0) {
- byte[] data = attrList.get(0).getData();
-
- int value = (data[0] * 256) + data[1];
-
- try {
- gettingLatestDataMutex.acquire();
- humidity = (float)value / (float)100.0;
- timestampOfLastHumidity = new Date();
- } catch (Exception e) {
- e.printStackTrace();
- }
- gettingLatestDataMutex.release();
-
- try {
- for (MoistureSensorSmartCallback cb : callbackList) {
- cb.newReadingAvailable(this.getId(), this.getMoisture(), this.getTimestampOfLastReading());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- }
- }
-
- public void registerCallback(MoistureSensorSmartCallback _callbackTo) {
- callbackList.add(_callbackTo);
- }
-}
+++ /dev/null
-package iotcode.WaterLeakSensor;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import iotrmi.Java.IoTRMICall;
-import iotrmi.Java.IoTRMIObject;
-
-import iotcode.interfaces.*;
-
-public class SmartthingsSensorSmartCallback_CallbackStub implements SmartthingsSensorSmartCallback {
-
- private IoTRMICall rmiCall;
- private String callbackAddress;
- private int[] ports;
-
- private int objectId = 0;
-
-
- public SmartthingsSensorSmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
- callbackAddress = _callbackAddress;
- objectId = _objectId;
- rmiCall = _rmiCall;
- ports = _ports;
- }
-
- public void newReadingAvailable(int _sensorId, int _value, boolean _activeValue) {
- int methodId = 0;
- Class<?> retType = void.class;
- Class<?>[] paramCls = new Class<?>[] { int.class, int.class, boolean.class };
- Object[] paramObj = new Object[] { _sensorId, _value, _activeValue };
- rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
- }
-
-}
+++ /dev/null
-package iotcode.WaterLeakSensor;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Arrays;
-import iotrmi.Java.IoTRMICall;
-import iotrmi.Java.IoTRMIObject;
-
-import iotcode.interfaces.*;
-
-public class SmartthingsSensor_Skeleton implements SmartthingsSensor {
-
- private SmartthingsSensor mainObj;
- private IoTRMIObject rmiObj;
-
- private String callbackAddress;
- private int objIdCnt = 0;
- private IoTRMICall rmiCall;
- private int[] ports;
-
- private final static int object0Id = 0; //SmartthingsSensorSmart
- private static Integer[] object0Permission = { 3, 2, 5, 6, 1, 4, 0 };
- private static List<Integer> set0Allowed;
-
-
- public SmartthingsSensor_Skeleton(SmartthingsSensor _mainObj, String _callbackAddress, int _port) throws Exception {
- mainObj = _mainObj;
- callbackAddress = _callbackAddress;
- rmiObj = new IoTRMIObject(_port);
- set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
- set0Allowed.add(-9998);
- ___waitRequestInvokeMethod();
- }
-
- public void init() {
- mainObj.init();
- }
-
- public int getValue() {
- return mainObj.getValue();
- }
-
- public boolean isActiveValue() {
- return mainObj.isActiveValue();
- }
-
- public long getTimestampOfLastReading() {
- return mainObj.getTimestampOfLastReading();
- }
-
- public void setId(int id) {
- mainObj.setId(id);
- }
-
- public int getId() {
- return mainObj.getId();
- }
-
- public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
- mainObj.registerCallback(_callbackTo);
- }
-
- public void ___regCB() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
- ports = (int[]) paramObj[0];
- rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
- }
-
- public void ___init() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- init();
- }
-
- public void ___getValue() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getValue();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___isActiveValue() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = isActiveValue();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getTimestampOfLastReading() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getTimestampOfLastReading();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___setId() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- setId((int) paramObj[0]);
- }
-
- public void ___getId() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getId();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___registerCallback() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- try {
- SmartthingsSensorSmartCallback stub0 = new SmartthingsSensorSmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
- objIdCnt++;
- registerCallback(stub0);
- } catch(Exception ex) {
- ex.printStackTrace();
- throw new Error("Exception from callback object instantiation!");
- }
- }
-
- private void ___waitRequestInvokeMethod() throws IOException {
- while (true) {
- rmiObj.getMethodBytes();
- int _objectId = rmiObj.getObjectId();
- int methodId = rmiObj.getMethodId();
- if (_objectId == object0Id) {
- if (!set0Allowed.contains(methodId)) {
- throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
- }
- }
- else {
- throw new Error("Object Id: " + _objectId + " not recognized!");
- }
- switch (methodId) {
- case 0: ___init(); break;
- case 1: ___getValue(); break;
- case 2: ___isActiveValue(); break;
- case 3: ___getTimestampOfLastReading(); break;
- case 4: ___setId(); break;
- case 5: ___getId(); break;
- case 6: ___registerCallback(); break;
- case -9998: ___regCB(); break;
- default:
- throw new Error("Method Id " + methodId + " not recognized!");
- }
- }
- }
-
-}
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=SmartthingsSensor
-# Stub
-INTERFACE_STUB_CLASS=SmartthingsSensorSmart
+++ /dev/null
-package iotcode.WaterLeakSensor;
-
-// Standard Java Packages
-import java.util.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.Semaphore;
-
-// Checker annotations
-//import iotchecker.qual.*;
-import iotcode.annotation.*;
-
-// IoT Packages
-import iotruntime.slave.*;
-import iotcode.interfaces.*;
-import iotruntime.zigbee.*;
-
-/** Class Smartthings sensor driver for Smartthings sensor devices.
- *
- * @author Changwoo Lee, Rahmadi Trimananda <rtrimana @ uci.edu>
- * @version 1.0
- * @since 2016-12-01
- */
-public class WaterLeakSensor implements IoTZigbeeCallback, SmartthingsSensor {
-
- private final int TIMEOUT_FOR_RESEND_MSEC = 900;
-
- private IoTZigbee zigConnection = null;
- private boolean didClose; // make sure that the clean up was done correctly
- private boolean detectStatus = false;
-
- private int detectedValue = 0;
- private Date timestampOfLastDetecting = null;
-
- private AtomicBoolean didAlreadyInit = new AtomicBoolean(false);
- private AtomicBoolean didAlreadyClose = new AtomicBoolean(true);
- private AtomicBoolean didWriteAttrb = new AtomicBoolean(false);
- private AtomicBoolean didMatchDscr = new AtomicBoolean(false);
- static Semaphore gettingLatestDataMutex = new Semaphore(1);
-
- private List < SmartthingsSensorSmartCallback > callbackList = new CopyOnWriteArrayList < SmartthingsSensorSmartCallback > ();
-
- private int sensorId = 0;
-
- @config private IoTSet<IoTDeviceAddress> waterleakSensorUdpAddress;
- @config private IoTSet<IoTZigbeeAddress> waterleakSensorZigbeeAddress;
-
- //public WaterLeakSensor(IoTSet<IoTDeviceAddress> dSet, IoTSet<IoTZigbeeAddress> zigSet) {
- //waterleakSensorUdpAddress = dSet;
- //waterleakSensorZigbeeAddress = zigSet;
- //}
- public WaterLeakSensor() {
- }
-
- public void init() {
-
- if (didAlreadyInit.compareAndSet(false, true) == false) {
- return; // already init
- }
-
- didAlreadyClose.set(false);
-
- try {
- Iterator itrUdp = waterleakSensorUdpAddress.iterator();
- Iterator itrZig = waterleakSensorZigbeeAddress.iterator();
-
- zigConnection = new IoTZigbee((IoTDeviceAddress)itrUdp.next(), (IoTZigbeeAddress)itrZig.next());
-
- // DEBUG
- System.out.println("DEBUG: Allocate iterators to print out addresses!");
- Iterator itrDebugUdp = waterleakSensorUdpAddress.iterator();
- IoTDeviceAddress iotaddDebug = (IoTDeviceAddress)itrDebugUdp.next();
- System.out.println("IP address: " + iotaddDebug.getCompleteAddress());
- System.out.println("Source port: " + iotaddDebug.getSourcePortNumber());
- System.out.println("Destination port: " + iotaddDebug.getDestinationPortNumber());
-
- Iterator itrDebugZig = waterleakSensorZigbeeAddress.iterator();
- IoTZigbeeAddress iotzbaddDebug = (IoTZigbeeAddress)itrDebugZig.next();
- System.out.println("Zigbee address: " + iotzbaddDebug.getAddress());
-
- zigConnection.registerCallback(this);
- System.out.println("Register callback!");
- zigConnection.init();
- System.out.println("Initialized!");
-
- //made by changwoo
- sleep(10);
- System.out.println("Sending Management Permit Joining Request");
- for(int z=0; z<3; z++){
- zigConnection.sendManagementPermitJoiningRequest(0x0001, 0x0036, 0x00);
- sleep(0);
- }
-
- //made by changwoo
- while (!didWriteAttrb.get()) {
- System.out.println("Sending Write Attribute Request");
- zigConnection.sendWriteAttributesCommand(0x0002, 0x0500, 0x0104, 0x01);
- sleep(0);
- }
-
- //made by changwoo
- System.out.println("Sending Enrollment Reponse");
- zigConnection.sendEnrollmentResponse(0x0003, 0x0500, 0x0104, 0x01);
- sleep(0);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- //made by changwoo
- private void sleep(int multipleTime){
- if(multipleTime<=0){
- multipleTime=1;
- }
- try{
- Thread.sleep(TIMEOUT_FOR_RESEND_MSEC*multipleTime);
- } catch(Exception e){
- e.printStackTrace();
- }
- }
-
- public void close() {
-
- if (didAlreadyClose.compareAndSet(false, true) == false) {
- return; // already init
- }
-
- didAlreadyInit.set(false);
-
-
- try {
- zigConnection.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public void Finalize() {
- if (!didClose) {
- close();
- }
- }
-
- public void setId(int id) {
-
- sensorId = id;
-
- }
-
- public int getId() {
-
- return sensorId;
-
- }
-
- public int getValue() {
-
- int tmp = 0;
- try {
- gettingLatestDataMutex.acquire();
- tmp = detectedValue;
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- gettingLatestDataMutex.release();
-
- return tmp;
- }
-
- // WaterLeakSensor:
- // - 24 = no leak = false
- // - 25 = leak = true
- public boolean isActiveValue() {
-
- int tmp = getValue();
- if (tmp == 25)
- detectStatus = true;
- else // Getting 24 here
- detectStatus = false;
-
- return detectStatus;
- }
-
- public long getTimestampOfLastReading() {
-
- Date tmp = null;
- try {
- gettingLatestDataMutex.acquire();
- tmp = (Date)timestampOfLastDetecting.clone();
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- gettingLatestDataMutex.release();
- long retLong = tmp.getTime();
-
- return retLong;
- }
-
- public void newMessageAvailable(IoTZigbeeMessage _zm) {
-
- //made by changwoo
- if(_zm instanceof IoTZigbeeMessageZclZoneStatusChangeNotification){
- IoTZigbeeMessageZclZoneStatusChangeNotification message = (IoTZigbeeMessageZclZoneStatusChangeNotification)_zm;
- if(message.getSuccessOrFail()){
- //do something!
-
- try {
- gettingLatestDataMutex.acquire();
- detectedValue = message.getStatus();
- timestampOfLastDetecting = new Date();
- } catch (Exception e) {
- e.printStackTrace();
- }
- gettingLatestDataMutex.release();
- try {
- for (SmartthingsSensorSmartCallback cb : callbackList) {
- cb.newReadingAvailable(this.getId(), this.getValue(), this.isActiveValue());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }//if
-
- //made by changwoo
- }//if
- else if (_zm instanceof IoTZigbeeMessageZclWriteAttributesResponse) {
- IoTZigbeeMessageZclWriteAttributesResponse message = (IoTZigbeeMessageZclWriteAttributesResponse)_zm;
- if (message.getSuccessOrFail()) {
- didWriteAttrb.set(true);
- }//if
- }//else if
- }
-
- public void registerCallback(SmartthingsSensorSmartCallback _callbackTo) {
- callbackList.add(_callbackTo);
- }
-}
+++ /dev/null
-package iotcode.WeatherPhoneGateway;
-
-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 WeatherGatewaySmartCallback_CallbackStub implements WeatherGatewaySmartCallback {
-
- private IoTRMICall rmiCall;
- private String callbackAddress;
- private int[] ports;
-
- private int objectId = 0;
-
-
- public WeatherGatewaySmartCallback_CallbackStub(IoTRMICall _rmiCall, String _callbackAddress, int _objectId, int[] _ports) throws Exception {
- callbackAddress = _callbackAddress;
- objectId = _objectId;
- rmiCall = _rmiCall;
- ports = _ports;
- }
-
- public void informationRetrieved(double _inchesPerWeek, int _weatherZipCode, int _daysToWaterOn, double _inchesPerMinute) {
- int methodId = 0;
- Class<?> retType = void.class;
- Class<?>[] paramCls = new Class<?>[] { double.class, int.class, int.class, double.class };
- Object[] paramObj = new Object[] { _inchesPerWeek, _weatherZipCode, _daysToWaterOn, _inchesPerMinute };
- rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);
- }
-
-}
+++ /dev/null
-package iotcode.WeatherPhoneGateway;
-
-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 WeatherGateway_Skeleton implements WeatherGateway {
-
- private WeatherGateway mainObj;
- private IoTRMIObject rmiObj;
-
- private String callbackAddress;
- private int objIdCnt = 0;
- private IoTRMICall rmiCall;
- private int[] ports;
-
- private final static int object0Id = 0; //WeatherGatewaySmart
- private static Integer[] object0Permission = { 3, 6, 5, 7, 2, 1, 0, 4 };
- private static List<Integer> set0Allowed;
-
-
- public WeatherGateway_Skeleton(WeatherGateway _mainObj, String _callbackAddress, int _port) throws Exception {
- mainObj = _mainObj;
- callbackAddress = _callbackAddress;
- rmiObj = new IoTRMIObject(_port);
- set0Allowed = new ArrayList<Integer>(Arrays.asList(object0Permission));
- set0Allowed.add(-9998);
- ___waitRequestInvokeMethod();
- }
-
- public void init() {
- mainObj.init();
- }
-
- public void start() {
- mainObj.start();
- }
-
- public void stop() {
- mainObj.stop();
- }
-
- public double getInchesPerWeek() {
- return mainObj.getInchesPerWeek();
- }
-
- public int getWeatherZipCode() {
- return mainObj.getWeatherZipCode();
- }
-
- public int getDaysToWaterOn() {
- return mainObj.getDaysToWaterOn();
- }
-
- public double getInchesPerMinute() {
- return mainObj.getInchesPerMinute();
- }
-
- public void registerCallback(WeatherGatewaySmartCallback _callbackTo) {
- mainObj.registerCallback(_callbackTo);
- }
-
- public void ___regCB() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int[].class, String.class, int.class },new Class<?>[] { null, null, null });
- ports = (int[]) paramObj[0];
- rmiCall = new IoTRMICall(ports[0], (String) paramObj[1], (int) paramObj[2]);
- }
-
- public void ___init() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- init();
- }
-
- public void ___start() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- start();
- }
-
- public void ___stop() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- stop();
- }
-
- public void ___getInchesPerWeek() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getInchesPerWeek();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getWeatherZipCode() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getWeatherZipCode();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getDaysToWaterOn() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getDaysToWaterOn();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___getInchesPerMinute() throws IOException {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { },
- new Class<?>[] { });
- Object retObj = getInchesPerMinute();
- rmiObj.sendReturnObj(retObj);
- }
-
- public void ___registerCallback() {
- Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class },
- new Class<?>[] { null });
- try {
- WeatherGatewaySmartCallback stub0 = new WeatherGatewaySmartCallback_CallbackStub(rmiCall, callbackAddress, objIdCnt, ports);
- objIdCnt++;
- registerCallback(stub0);
- } catch(Exception ex) {
- ex.printStackTrace();
- throw new Error("Exception from callback object instantiation!");
- }
- }
-
- private void ___waitRequestInvokeMethod() throws IOException {
- while (true) {
- rmiObj.getMethodBytes();
- int _objectId = rmiObj.getObjectId();
- int methodId = rmiObj.getMethodId();
- if (_objectId == object0Id) {
- if (!set0Allowed.contains(methodId)) {
- throw new Error("Object with object Id: " + _objectId + " is not allowed to access method: " + methodId);
- }
- }
- else {
- throw new Error("Object Id: " + _objectId + " not recognized!");
- }
- switch (methodId) {
- case 0: ___init(); break;
- case 1: ___start(); break;
- case 2: ___stop(); break;
- case 3: ___getInchesPerWeek(); break;
- case 4: ___getWeatherZipCode(); break;
- case 5: ___getDaysToWaterOn(); break;
- case 6: ___getInchesPerMinute(); break;
- case 7: ___registerCallback(); break;
- case -9998: ___regCB(); break;
- default:
- throw new Error("Method Id " + methodId + " not recognized!");
- }
- }
- }
-
-}
+++ /dev/null
-package iotcode.WeatherPhoneGateway;
-
-/** WeatherInfo that implements WeatherInfoInterface
- *
- * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
- * @version 1.0
- * @since 2016-04-26
- */
-public class WeatherInfo implements WeatherInfoInterface {
-
- /**
- * WeatherInfo class properties
- */
- private Double dInchesPerWeek;
- private Integer iWeatherZipCode;
- private Integer iDaysToWaterOn;
- private Double dInchesPerMinute;
- private boolean bNewDataAvailable;
-
- /**
- * Constructor
- */
- public WeatherInfo() {
- this.dInchesPerWeek = 0.0;
- this.iWeatherZipCode = 0;
- this.iDaysToWaterOn = 0;
- this.dInchesPerMinute = 0.0;
- this.bNewDataAvailable = false;
- }
-
- /**
- * Get irrigation info from the phone app using IoTRemoteCall
- *
- * @param dInchesPerWeek Rainfall information (inches per week)
- * @param iWeatherZipCode Area zip code for weather info
- * @param iDaysToWaterOn Number of days to water the lawn
- * @param dInchesPerMinute Rainfall information (inches per minute)
- * @
- */
- public String getIrrigationInfo(Double dInchesPerWeek, Integer iWeatherZipCode,
- Integer iDaysToWaterOn, Double dInchesPerMinute) {
-
- this.dInchesPerWeek = dInchesPerWeek;
- this.iWeatherZipCode = iWeatherZipCode;
- this.iDaysToWaterOn = iDaysToWaterOn;
- this.dInchesPerMinute = dInchesPerMinute;
- this.bNewDataAvailable = true;
- System.out.println("DEBUG: We are getting data from phone!");
- System.out.println("DEBUG: New data available?" + bNewDataAvailable);
-
- return "info sent";
- }
-
- /**
- * Simply return this.dInchesPerWeek
- */
- public Double getInchesPerWeek() {
-
- return this.dInchesPerWeek;
- }
-
- /**
- * Simply return this.iWeatherZipCode
- */
- public Integer getWeatherZipCode() {
-
- return this.iWeatherZipCode;
- }
-
- /**
- * Simply return this.iDaysToWaterOn
- */
- public Integer getDaysToWaterOn() {
-
- return this.iDaysToWaterOn;
- }
-
- /**
- * Simply return this.dInchesPerMinute
- */
- public Double getInchesPerMinute() {
-
- return this.dInchesPerMinute;
- }
-
- /**
- * Simply return this.bNewDataAvailable
- */
- public boolean isNewDataAvailable() {
-
- return this.bNewDataAvailable;
- }
-
- /**
- * Set this.bNewDataAvailable
- */
- public void setNewDataAvailable(boolean bValue) {
-
- this.bNewDataAvailable = bValue;
- }
-}
+++ /dev/null
-package iotcode.WeatherPhoneGateway;
-
-/** WeatherInfoInterface interface to be implemented by a real class
- *
- * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
- * @version 1.0
- * @since 2016-04-26
- */
-public interface WeatherInfoInterface {
-
- /**
- * WeatherPhoneGateway takes 4 inputs
- * - inchesPerWeek (double)
- * - weatherZipCode (int)
- * - daysToWaterOn (int)
- * - inchesPerMinute (double)
- */
- String getIrrigationInfo(Double dInchesPerWeek, Integer iWeatherZipCode,
- Integer iDaysToWaterOn, Double dInchesPerMinute);
-}
+++ /dev/null
-# Skeleton/original interface
-INTERFACE_CLASS=WeatherGateway
-# Stub
-INTERFACE_STUB_CLASS=WeatherGatewaySmart
+++ /dev/null
-package iotcode.WeatherPhoneGateway;
-
-// 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.*;
-
-/** WeatherPhoneProxy that uses IoTRemoteCall and WeatherInfo class
- * to get information from a phone app
- *
- * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
- * @version 1.0
- * @since 2016-04-26
- */
-public class WeatherPhoneGateway implements WeatherGateway {
-
- /**
- * PhoneGateway class properties
- */
- private WeatherInfo weatherInfo;
- private IoTRemoteCall iotRemCall;
- private List<WeatherGatewaySmartCallback> listPGWCallback;
- private AtomicBoolean doEnd;
- private Thread callbackThread;
- private Thread workerThread;
- private IoTDeviceAddress iotDevAdd;
-
- @config private IoTSet<IoTDeviceAddress> ph_address;
-
- /**
- * Constructor
- */
- /*public WeatherPhoneGateway() throws RemoteException, UnknownHostException {
-
- iotDevAdd = new IoTDeviceAddress("192.168.2.101", 1234, 8000);
- weatherInfo = new WeatherInfo();
-
- // Launch IoTRemoteCall server in a separate thread
- workerThread = new Thread(new Runnable() {
- public void run() {
- iotRemCall = new IoTRemoteCall(WeatherInfoInterface.class,
- weatherInfo, iotDevAdd.getDestinationPortNumber());
- }
- });
- workerThread.start();
-
- System.out.println("PhoneGateway is started");
-
- }*/
- public WeatherPhoneGateway() {
- }
-
- /**
- * Init() function
- */
- public void init() {
-
- // Get address
- Iterator it = ph_address.iterator();
- iotDevAdd = (IoTDeviceAddress) it.next();
-// try {
-// iotDevAdd = new IoTDeviceAddress("192.168.2.101", 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
- weatherInfo = new WeatherInfo();
- System.out.println("DEBUG: Is new data available: " + weatherInfo.isNewDataAvailable());
- listPGWCallback = new ArrayList<WeatherGatewaySmartCallback>();
- 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(WeatherInfoInterface.class,
- weatherInfo, iotDevAdd.getDestinationPortNumber(),
- IoTDeviceAddress.getLocalHostAddress());
- }
- });
- workerThread.start();
- System.out.println("DEBUG: Started IoTRemoteCall object!!!");
-
- callbackThread = new Thread(new Runnable() {
- public void run() {
- doCallbacks();
- }
- });
- callbackThread.start();
- System.out.println("DEBUG: Do Callbacks!!!");
- }
-
- /**
- * 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(WeatherGatewaySmartCallback _c) {
- listPGWCallback.add(_c);
- }
-
- /**
- * Do callbacks
- */
- private void doCallbacks() {
-
- while (!doEnd.get()) {
- // Only call back if there is new data
- if (weatherInfo.isNewDataAvailable()) {
- System.out.println("We get into doCallbacks!");
- System.out.println("weatherInfo.isNewDataAvailable(): " + weatherInfo.isNewDataAvailable());
- for (WeatherGatewaySmartCallback c : listPGWCallback) {
- //try {
- //c.informationRetrieved(this);
- c.informationRetrieved(this.getInchesPerWeek(), this.getWeatherZipCode(), this.getDaysToWaterOn(), this.getInchesPerMinute());
- //} catch (RemoteException ex) {
- // ex.printStackTrace();
- //}
- // We have read data - set this back to false
- }
- weatherInfo.setNewDataAvailable(false);
- }
- }
- }
-
- /**
- * Simply return this.dInchesPerWeek
- */
- public double getInchesPerWeek() {
-
- return weatherInfo.getInchesPerWeek();
- }
-
- /**
- * Simply return this.iWeatherZipCode
- */
- public int getWeatherZipCode() {
-
- return weatherInfo.getWeatherZipCode();
- }
-
- /**
- * Simply return this.iDaysToWaterOn
- */
- public int getDaysToWaterOn() {
-
- return weatherInfo.getDaysToWaterOn();
- }
-
- /**
- * Simply return this.dInchesPerMinute
- */
- public double getInchesPerMinute() {
-
- return weatherInfo.getInchesPerMinute();
- }
-
-
-// public static void main(String[] args) throws UnknownHostException, RemoteException {
-
-// @LocalRemote WeatherPhoneGateway wpg = new @LocalRemote WeatherPhoneGateway();
-// wpg.init();
-// wpg.start();
-// }
-}
--- /dev/null
+#ifndef _LIGHTBULB_HPP__
+#define _LIGHTBULB_HPP__
+#include <iostream>
+
+using namespace std;
+
+class LightBulb
+{
+ public:
+ virtual void init() = 0;
+ virtual void turnOff() = 0;
+ virtual void turnOn() = 0;
+ virtual bool getState() = 0;
+ virtual void setColor(double _hue, double _saturation, double _brightness) = 0;
+ virtual void setTemperature(int _temperature) = 0;
+ virtual double getBrightness() = 0;
+ virtual double getHue() = 0;
+ virtual double getSaturation() = 0;
+ virtual int getTemperature() = 0;
+ virtual double getBrightnessRangeLowerBound() = 0;
+ virtual double getBrightnessRangeUpperBound() = 0;
+ virtual double getHueRangeLowerBound() = 0;
+ virtual double getHueRangeUpperBound() = 0;
+ virtual double getSaturationRangeLowerBound() = 0;
+ virtual double getSaturationRangeUpperBound() = 0;
+ virtual int getTemperatureRangeLowerBound() = 0;
+ virtual int getTemperatureRangeUpperBound() = 0;
+};
+#endif
--- /dev/null
+#ifndef _LIGHTBULBSMART_HPP__
+#define _LIGHTBULBSMART_HPP__
+#include <iostream>
+#include <vector>
+#include <set>
+#include "IoTRMICall.hpp"
+#include "IoTRMIObject.hpp"
+
+using namespace std;
+
+class LightBulbSmart
+{
+ public:
+ virtual void turnOn() = 0;
+ virtual double getBrightnessRangeLowerBound() = 0;
+ virtual void turnOff() = 0;
+ virtual bool getState() = 0;
+ virtual double getBrightnessRangeUpperBound() = 0;
+ virtual double getSaturation() = 0;
+ virtual double getHueRangeLowerBound() = 0;
+ virtual double getHue() = 0;
+ virtual double getHueRangeUpperBound() = 0;
+ virtual int getTemperature() = 0;
+ virtual double getBrightness() = 0;
+ virtual int getTemperatureRangeLowerBound() = 0;
+ virtual int getTemperatureRangeUpperBound() = 0;
+ virtual void setColor(double _hue, double _saturation, double _brightness) = 0;
+ virtual void init() = 0;
+ virtual double getSaturationRangeLowerBound() = 0;
+ virtual double getSaturationRangeUpperBound() = 0;
+ virtual void setTemperature(int _temperature) = 0;
+};
+#endif
run-compiler-lifx:
cp ../localconfig/iotpolicy/LifxLightBulb/*.pol $(BIN_DIR)/iotpolicy/
cp ../localconfig/iotpolicy/LifxLightBulb/*.req $(BIN_DIR)/iotpolicy/
- cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler lifxlightbulb.pol smartlightsbulb.req -java Java
+ #cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler lifxlightbulb.pol smartlightsbulb.req -java Java
+ cd $(BIN_DIR)/iotpolicy; $(JAVA) -cp .:..:../$(PARSERJARS):../$(BIN_DIR) iotpolicy.IoTCompiler lifxlightbulb.pol smartlightsbulb.req -cplus C++
PHONY += run-compiler-room
run-compiler-room:
--- /dev/null
+#ifndef _IOTADDRESS_HPP__
+#define _IOTADDRESS_HPP__
+#include <iostream>
+
+using namespace std;
+
+
+// IoTAddress class for iotruntime
+// Implemented based on IoTAddress.java that is used to wrap address
+//
+// @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+// @version 1.0
+// @since 2017-01-09
+
+class IoTAddress
+{
+ public:
+
+ // Constructor
+ IoTAddress(string _sAddress) {
+
+ inetAddress = _sAddress;
+ }
+
+
+ // Constructor
+ IoTAddress() {
+ }
+
+
+ ~IoTAddress() {
+ }
+
+
+ string getAddress() {
+
+ return inetAddress;
+ }
+
+
+ string getURL(string strURLComplete) {
+
+ return "http://" + inetAddress + strURLComplete;
+ }
+
+
+ // Custom hasher for IoTAddress / IoTDeviceAddress iterator
+ size_t hash(IoTAddress const& devAddress) const {
+
+ std::hash<std::string> hashVal;
+ return hashVal(inetAddress);
+ }
+
+
+ // IoTAddress class properties
+ protected:
+ string inetAddress;
+};
+#endif
--- /dev/null
+#ifndef _IOTDEVICEADDRESS_HPP__
+#define _IOTDEVICEADDRESS_HPP__
+#include <iostream>
+
+#include "IoTAddress.hpp"
+
+using namespace std;
+
+// IoTDeviceAddress class for iotruntime
+// Implemented based on IoTDeviceAddress.java that is used to wrap device address
+//
+// @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+// @version 1.0
+// @since 2017-01-09
+
+
+class IoTDeviceAddress : public IoTAddress
+{
+
+ public:
+
+ // Constructor
+ IoTDeviceAddress(string _sAddress, int _iSrcPort, int _iDstPort, bool _isSrcPortWildCard, bool _isDstPortWildCard) : IoTAddress(_sAddress) {
+
+ iSrcPort = _iSrcPort;
+ iDstPort = _iDstPort;
+ isSrcPortWildCard = _isSrcPortWildCard;
+ isDstPortWildCard = _isDstPortWildCard;
+ }
+
+
+ // Constructor
+ IoTDeviceAddress() {
+ }
+
+
+ ~IoTDeviceAddress() {
+ }
+
+
+ // Getter methods
+ int getSourcePortNumber() {
+
+ return iSrcPort;
+ }
+
+
+ int getDestinationPortNumber() {
+
+ return iDstPort;
+ }
+
+
+ bool getIsSrcPortWildcard() {
+
+ return isSrcPortWildCard;
+ }
+
+
+ bool getIsDstPortWildcard() {
+
+ return isDstPortWildCard;
+ }
+
+
+ // Setter methods
+ void setSrcPort(int port) {
+
+ if (isDstPortWildCard) {
+ iDstPort = port;
+ }
+ }
+
+
+ void setDstPort(int port) {
+
+ if (isSrcPortWildCard) {
+ iSrcPort = port;
+ }
+ }
+
+
+ // IoTDeviceAddress class properties
+ private:
+ int iSrcPort;
+ int iDstPort;
+
+ bool isSrcPortWildCard;
+ bool isDstPortWildCard;
+};
+#endif
--- /dev/null
+#ifndef _IOTUDP_HPP__
+#define _IOTUDP_HPP__
+#include <iostream>
+
+#include "IoTDeviceAddress.hpp"
+
+using namespace std;
+
+// IoTUDP class for iotruntime
+// Implemented based on IoTUDP.java that is used to wrap communication socket for UDP
+//
+// @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+// @version 1.0
+// @since 2017-01-09
+
+class IoTUDP
+{
+ // IoTUDP class properties
+ private:
+ string strHostAddress;
+ int iSrcPort;
+ int iDstPort;
+ UDPSocket *socket;
+ bool didClose;
+
+ public:
+
+ // Constructor
+ IoTUDP(IoTDeviceAddress iotDevAdd) {
+
+ strHostAddress = iotDevAdd.getAddress();
+ iSrcPort = iotDevAdd.getSourcePortNumber();
+ iDstPort = iotDevAdd.getDestinationPortNumber();
+
+ socket = new UDPSocket(iSrcPort);
+ if (socket == NULL) {
+ perror("IoTUDP: UDP socket isn't initialized!");
+ }
+ didClose = false;
+ }
+
+
+ ~IoTUDP() {
+ // Clean up
+ if (socket != NULL) {
+
+ delete socket;
+ socket = NULL;
+ }
+ }
+
+
+ // Send data packet
+ void sendData(const void* buffer, int bufferLen) {
+
+ unsigned short destinationPort = (unsigned short) iDstPort;
+ socket->sendTo(buffer, bufferLen, strHostAddress, destinationPort);
+ }
+
+
+ // Receive data packet
+ int receiveData(void* buffer, int iMaxDataLength) {
+
+ unsigned short destinationPort = (unsigned short) iDstPort;
+ socket->recvFrom(buffer, iMaxDataLength, strHostAddress, destinationPort);
+ }
+};
+#endif
--- /dev/null
+#ifndef _IOTRELATION_HPP__
+#define _IOTRELATION_HPP__
+#include <iostream>
+#include <string>
+#include <unordered_map>
+
+using namespace std;
+
+/** This is the IoTRelation implementation for C++
+ *
+ * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version 1.0
+ * @since 2016-09-06
+ */
+template <class K,class V>
+class IoTRelation {
+ private:
+ unordered_multimap<K,V> rel;
+ public:
+ IoTRelation();
+ IoTRelation(unordered_multimap<K,V> const& s);
+ ~IoTRelation();
+ public:
+ typename unordered_multimap<K,V>::const_iterator find(const K& k); // Find the object based on key
+ bool empty(); // Test is empty?
+ typename unordered_multimap<K,V>::const_iterator begin(); // Iterator
+ typename unordered_multimap<K,V>::const_iterator end(); // Iterator
+ std::pair<typename unordered_multimap<K,V>::const_iterator,
+ typename unordered_multimap<K,V>::const_iterator>
+ equal_range(const K& k); // Equal range iterator
+ int size(); // Set size
+ unordered_multimap<K,V> values(); // Return set contents
+};
+
+
+/**
+ * Default constructor
+ */
+template <class K,class V>
+IoTRelation<K,V>::IoTRelation() {
+
+}
+
+
+/**
+ * Useful constructor
+ */
+template <class K,class V>
+IoTRelation<K,V>::IoTRelation(const unordered_multimap<K,V>& r) {
+
+ rel = r;
+}
+
+
+/**
+ * Default destructor
+ */
+template <class K,class V>
+IoTRelation<K,V>::~IoTRelation() {
+
+ //free(&set);
+}
+
+
+/**
+ * Find the object k in the set
+ */
+template <class K,class V>
+typename unordered_multimap<K,V>::const_iterator IoTRelation<K,V>::find(const K& k) {
+
+ return rel.find(k);
+}
+
+
+/**
+ * Return the "begin" iterator
+ */
+template <class K,class V>
+typename unordered_multimap<K,V>::const_iterator IoTRelation<K,V>::begin() {
+
+ return rel.begin();
+}
+
+
+/**
+ * Return the "end" iterator
+ */
+template <class K,class V>
+typename unordered_multimap<K,V>::const_iterator IoTRelation<K,V>::end() {
+
+ return rel.end();
+}
+
+
+/**
+ * Return the "equal_range" iterator
+ */
+template <class K,class V>
+std::pair<typename unordered_multimap<K,V>::const_iterator,
+ typename unordered_multimap<K,V>::const_iterator>
+ IoTRelation<K,V>::equal_range(const K& k) {
+
+ return rel.equal_range(k);
+}
+
+
+/**
+ * Return the size of the set
+ */
+template <class K,class V>
+int IoTRelation<K,V>::size() {
+
+ return rel.size();
+}
+
+
+/**
+ * Return a new copy of the set
+ */
+template <class K,class V>
+unordered_multimap<K,V> IoTRelation<K,V>::values() {
+
+ return new unordered_multimap<K,V>(rel);
+}
+#endif
+
+
+
+
--- /dev/null
+#ifndef _IOTSET_HPP__
+#define _IOTSET_HPP__
+#include <iostream>
+#include <string>
+#include <unordered_set>
+
+using namespace std;
+
+/** This is the IoTSet implementation for C++
+ *
+ * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version 1.0
+ * @since 2016-09-06
+ */
+template <class T>
+class IoTSet {
+ private:
+ unordered_set<T> set;
+ public:
+ IoTSet();
+ IoTSet(unordered_set<T> const& s);
+ ~IoTSet();
+ public:
+ typename unordered_set<T>::const_iterator find(const T& k); // Find the object
+ bool empty(); // Test is empty?
+ typename unordered_set<T>::const_iterator begin(); // Iterator
+ typename unordered_set<T>::const_iterator end(); // Iterator
+ int size(); // Set size
+ unordered_set<T> values(); // Return set contents
+};
+
+
+/**
+ * Default constructor
+ */
+template <class T>
+IoTSet<T>::IoTSet() {
+
+}
+
+
+/**
+ * Useful constructor
+ */
+template <class T>
+IoTSet<T>::IoTSet(const unordered_set<T>& s) {
+
+ set = s;
+}
+
+
+/**
+ * Default destructor
+ */
+template <class T>
+IoTSet<T>::~IoTSet() {
+
+ //free(&set);
+}
+
+
+/**
+ * Find the object k in the set
+ */
+template <class T>
+typename unordered_set<T>::const_iterator IoTSet<T>::find(const T& k) {
+
+ return set.find(k);
+}
+
+
+/**
+ * Return the "begin" iterator
+ */
+template <class T>
+typename unordered_set<T>::const_iterator IoTSet<T>::begin() {
+
+ return set.begin();
+}
+
+
+/**
+ * Return the "end" iterator
+ */
+template <class T>
+typename unordered_set<T>::const_iterator IoTSet<T>::end() {
+
+ return set.end();
+}
+
+
+/**
+ * Return the size of the set
+ */
+template <class T>
+int IoTSet<T>::size() {
+
+ return set.size();
+}
+
+
+/**
+ * Return a new copy of the set
+ */
+template <class T>
+unordered_set<T> IoTSet<T>::values() {
+
+ return new unordered_set<T>(set);
+}
+#endif
+
--- /dev/null
+#ifndef _ITERATOR_HPP__
+#define _ITERATOR_HPP__
+
+namespace std
+{
+ template<> struct hash<IoTDeviceAddress>
+ {
+ size_t operator()(IoTDeviceAddress const& devAddress) const
+ {
+ return devAddress.hash(devAddress);
+ }
+ };
+}
+
+
+bool operator==(const IoTDeviceAddress& lhs, const IoTDeviceAddress& rhs) {
+ return lhs.hash(lhs) == rhs.hash(rhs);
+}
+
+#endif
--- /dev/null
+/*
+ * C++ sockets on Unix and Windows
+ * Copyright (C) 2002
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/practical/
+
+#include "Socket.hpp"
+
+#ifdef WIN32
+ #include <winsock.h> // For socket(), connect(), send(), and recv()
+ typedef int socklen_t;
+ typedef char raw_type; // Type used for raw data on this platform
+#else
+ #include <sys/types.h> // For data types
+ #include <sys/socket.h> // For socket(), connect(), send(), and recv()
+ #include <netdb.h> // For gethostbyname()
+ #include <arpa/inet.h> // For inet_addr()
+ #include <unistd.h> // For close()
+ #include <netinet/in.h> // For sockaddr_in
+ typedef void raw_type; // Type used for raw data on this platform
+#endif
+
+#include <errno.h> // For errno
+#include <string.h> // For memset
+
+using namespace std;
+
+#ifdef WIN32
+static bool initialized = false;
+#endif
+
+// SocketException Code
+
+SocketException::SocketException(const string &message, bool inclSysMsg)
+ throw() : userMessage(message) {
+ if (inclSysMsg) {
+ userMessage.append(": ");
+ userMessage.append(strerror(errno));
+ }
+}
+
+SocketException::~SocketException() throw() {
+}
+
+const char *SocketException::what() const throw() {
+ return userMessage.c_str();
+}
+
+// Function to fill in address structure given an address and port
+static void fillAddr(const string &address, unsigned short port,
+ sockaddr_in &addr) {
+ memset(&addr, 0, sizeof(addr)); // Zero out address structure
+ addr.sin_family = AF_INET; // Internet address
+
+ hostent *host; // Resolve name
+ if ((host = gethostbyname(address.c_str())) == NULL) {
+ // strerror() will not work for gethostbyname() and hstrerror()
+ // is supposedly obsolete
+ throw SocketException("Failed to resolve name (gethostbyname())");
+ }
+ addr.sin_addr.s_addr = *((unsigned long *) host->h_addr_list[0]);
+
+ addr.sin_port = htons(port); // Assign port in network byte order
+}
+
+// Socket Code
+
+Socket::Socket(int type, int protocol) throw(SocketException) {
+ #ifdef WIN32
+ if (!initialized) {
+ WORD wVersionRequested;
+ WSADATA wsaData;
+
+ wVersionRequested = MAKEWORD(2, 0); // Request WinSock v2.0
+ if (WSAStartup(wVersionRequested, &wsaData) != 0) { // Load WinSock DLL
+ throw SocketException("Unable to load WinSock DLL");
+ }
+ initialized = true;
+ }
+ #endif
+
+ // Make a new socket
+ if ((sockDesc = socket(PF_INET, type, protocol)) < 0) {
+ throw SocketException("Socket creation failed (socket())", true);
+ }
+}
+
+Socket::Socket(int sockDesc) {
+ this->sockDesc = sockDesc;
+}
+
+Socket::~Socket() {
+ #ifdef WIN32
+ ::closesocket(sockDesc);
+ #else
+ ::close(sockDesc);
+ #endif
+ sockDesc = -1;
+}
+
+string Socket::getLocalAddress() throw(SocketException) {
+ sockaddr_in addr;
+ unsigned int addr_len = sizeof(addr);
+
+ if (getsockname(sockDesc, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) {
+ throw SocketException("Fetch of local address failed (getsockname())", true);
+ }
+ return inet_ntoa(addr.sin_addr);
+}
+
+unsigned short Socket::getLocalPort() throw(SocketException) {
+ sockaddr_in addr;
+ unsigned int addr_len = sizeof(addr);
+
+ if (getsockname(sockDesc, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) {
+ throw SocketException("Fetch of local port failed (getsockname())", true);
+ }
+ return ntohs(addr.sin_port);
+}
+
+void Socket::setLocalPort(unsigned short localPort) throw(SocketException) {
+ // Bind the socket to its port
+ sockaddr_in localAddr;
+ memset(&localAddr, 0, sizeof(localAddr));
+ localAddr.sin_family = AF_INET;
+ localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ localAddr.sin_port = htons(localPort);
+
+ if (bind(sockDesc, (sockaddr *) &localAddr, sizeof(sockaddr_in)) < 0) {
+ throw SocketException("Set of local port failed (bind())", true);
+ }
+}
+
+void Socket::setLocalAddressAndPort(const string &localAddress,
+ unsigned short localPort) throw(SocketException) {
+ // Get the address of the requested host
+ sockaddr_in localAddr;
+ fillAddr(localAddress, localPort, localAddr);
+
+ if (bind(sockDesc, (sockaddr *) &localAddr, sizeof(sockaddr_in)) < 0) {
+ throw SocketException("Set of local address and port failed (bind())", true);
+ }
+}
+
+void Socket::cleanUp() throw(SocketException) {
+ #ifdef WIN32
+ if (WSACleanup() != 0) {
+ throw SocketException("WSACleanup() failed");
+ }
+ #endif
+}
+
+unsigned short Socket::resolveService(const string &service,
+ const string &protocol) {
+ struct servent *serv; /* Structure containing service information */
+
+ if ((serv = getservbyname(service.c_str(), protocol.c_str())) == NULL)
+ return atoi(service.c_str()); /* Service is port number */
+ else
+ return ntohs(serv->s_port); /* Found port (network byte order) by name */
+}
+
+// CommunicatingSocket Code
+
+CommunicatingSocket::CommunicatingSocket(int type, int protocol)
+ throw(SocketException) : Socket(type, protocol) {
+}
+
+CommunicatingSocket::CommunicatingSocket(int newConnSD) : Socket(newConnSD) {
+}
+
+void CommunicatingSocket::connect(const string &foreignAddress,
+ unsigned short foreignPort) throw(SocketException) {
+ // Get the address of the requested host
+ sockaddr_in destAddr;
+ fillAddr(foreignAddress, foreignPort, destAddr);
+
+ // Try to connect to the given port
+ if (::connect(sockDesc, (sockaddr *) &destAddr, sizeof(destAddr)) < 0) {
+ throw SocketException("Connect failed (connect())", true);
+ }
+}
+
+void CommunicatingSocket::send(const void *buffer, int bufferLen)
+ throw(SocketException) {
+ if (::send(sockDesc, (raw_type *) buffer, bufferLen, 0) < 0) {
+ throw SocketException("Send failed (send())", true);
+ }
+}
+
+int CommunicatingSocket::recv(void *buffer, int bufferLen)
+ throw(SocketException) {
+ int rtn;
+ if ((rtn = ::recv(sockDesc, (raw_type *) buffer, bufferLen, 0)) < 0) {
+ throw SocketException("Received failed (recv())", true);
+ }
+
+ return rtn;
+}
+
+string CommunicatingSocket::getForeignAddress()
+ throw(SocketException) {
+ sockaddr_in addr;
+ unsigned int addr_len = sizeof(addr);
+
+ if (getpeername(sockDesc, (sockaddr *) &addr,(socklen_t *) &addr_len) < 0) {
+ throw SocketException("Fetch of foreign address failed (getpeername())", true);
+ }
+ return inet_ntoa(addr.sin_addr);
+}
+
+unsigned short CommunicatingSocket::getForeignPort() throw(SocketException) {
+ sockaddr_in addr;
+ unsigned int addr_len = sizeof(addr);
+
+ if (getpeername(sockDesc, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) {
+ throw SocketException("Fetch of foreign port failed (getpeername())", true);
+ }
+ return ntohs(addr.sin_port);
+}
+
+// TCPSocket Code
+
+TCPSocket::TCPSocket()
+ throw(SocketException) : CommunicatingSocket(SOCK_STREAM,
+ IPPROTO_TCP) {
+}
+
+TCPSocket::TCPSocket(const string &foreignAddress, unsigned short foreignPort)
+ throw(SocketException) : CommunicatingSocket(SOCK_STREAM, IPPROTO_TCP) {
+ connect(foreignAddress, foreignPort);
+}
+
+TCPSocket::TCPSocket(int newConnSD) : CommunicatingSocket(newConnSD) {
+}
+
+// TCPServerSocket Code
+
+TCPServerSocket::TCPServerSocket(unsigned short localPort, int queueLen)
+ throw(SocketException) : Socket(SOCK_STREAM, IPPROTO_TCP) {
+ setLocalPort(localPort);
+ setListen(queueLen);
+}
+
+TCPServerSocket::TCPServerSocket(const string &localAddress,
+ unsigned short localPort, int queueLen)
+ throw(SocketException) : Socket(SOCK_STREAM, IPPROTO_TCP) {
+ setLocalAddressAndPort(localAddress, localPort);
+ setListen(queueLen);
+}
+
+TCPSocket *TCPServerSocket::accept() throw(SocketException) {
+ int newConnSD;
+ if ((newConnSD = ::accept(sockDesc, NULL, 0)) < 0) {
+ throw SocketException("Accept failed (accept())", true);
+ }
+
+ return new TCPSocket(newConnSD);
+}
+
+void TCPServerSocket::setListen(int queueLen) throw(SocketException) {
+ if (listen(sockDesc, queueLen) < 0) {
+ throw SocketException("Set listening socket failed (listen())", true);
+ }
+}
+
+// UDPSocket Code
+
+UDPSocket::UDPSocket() throw(SocketException) : CommunicatingSocket(SOCK_DGRAM,
+ IPPROTO_UDP) {
+ setBroadcast();
+}
+
+UDPSocket::UDPSocket(unsigned short localPort) throw(SocketException) :
+ CommunicatingSocket(SOCK_DGRAM, IPPROTO_UDP) {
+ setLocalPort(localPort);
+ setBroadcast();
+}
+
+UDPSocket::UDPSocket(const string &localAddress, unsigned short localPort)
+ throw(SocketException) : CommunicatingSocket(SOCK_DGRAM, IPPROTO_UDP) {
+ setLocalAddressAndPort(localAddress, localPort);
+ setBroadcast();
+}
+
+void UDPSocket::setBroadcast() {
+ // If this fails, we'll hear about it when we try to send. This will allow
+ // system that cannot broadcast to continue if they don't plan to broadcast
+ int broadcastPermission = 1;
+ setsockopt(sockDesc, SOL_SOCKET, SO_BROADCAST,
+ (raw_type *) &broadcastPermission, sizeof(broadcastPermission));
+}
+
+void UDPSocket::disconnect() throw(SocketException) {
+ sockaddr_in nullAddr;
+ memset(&nullAddr, 0, sizeof(nullAddr));
+ nullAddr.sin_family = AF_UNSPEC;
+
+ // Try to disconnect
+ if (::connect(sockDesc, (sockaddr *) &nullAddr, sizeof(nullAddr)) < 0) {
+ #ifdef WIN32
+ if (errno != WSAEAFNOSUPPORT) {
+ #else
+ if (errno != EAFNOSUPPORT) {
+ #endif
+ throw SocketException("Disconnect failed (connect())", true);
+ }
+ }
+}
+
+void UDPSocket::sendTo(const void *buffer, int bufferLen,
+ const string &foreignAddress, unsigned short foreignPort)
+ throw(SocketException) {
+ sockaddr_in destAddr;
+ fillAddr(foreignAddress, foreignPort, destAddr);
+
+ // Write out the whole buffer as a single message.
+ if (sendto(sockDesc, (raw_type *) buffer, bufferLen, 0,
+ (sockaddr *) &destAddr, sizeof(destAddr)) != bufferLen) {
+ throw SocketException("Send failed (sendto())", true);
+ }
+}
+
+int UDPSocket::recvFrom(void *buffer, int bufferLen, string &sourceAddress,
+ unsigned short &sourcePort) throw(SocketException) {
+ sockaddr_in clntAddr;
+ socklen_t addrLen = sizeof(clntAddr);
+ int rtn;
+ if ((rtn = recvfrom(sockDesc, (raw_type *) buffer, bufferLen, 0,
+ (sockaddr *) &clntAddr, (socklen_t *) &addrLen)) < 0) {
+ throw SocketException("Receive failed (recvfrom())", true);
+ }
+ sourceAddress = inet_ntoa(clntAddr.sin_addr);
+ sourcePort = ntohs(clntAddr.sin_port);
+
+ return rtn;
+}
+
+void UDPSocket::setMulticastTTL(unsigned char multicastTTL) throw(SocketException) {
+ if (setsockopt(sockDesc, IPPROTO_IP, IP_MULTICAST_TTL,
+ (raw_type *) &multicastTTL, sizeof(multicastTTL)) < 0) {
+ throw SocketException("Multicast TTL set failed (setsockopt())", true);
+ }
+}
+
+void UDPSocket::joinGroup(const string &multicastGroup) throw(SocketException) {
+ struct ip_mreq multicastRequest;
+
+ multicastRequest.imr_multiaddr.s_addr = inet_addr(multicastGroup.c_str());
+ multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
+ if (setsockopt(sockDesc, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (raw_type *) &multicastRequest,
+ sizeof(multicastRequest)) < 0) {
+ throw SocketException("Multicast group join failed (setsockopt())", true);
+ }
+}
+
+void UDPSocket::leaveGroup(const string &multicastGroup) throw(SocketException) {
+ struct ip_mreq multicastRequest;
+
+ multicastRequest.imr_multiaddr.s_addr = inet_addr(multicastGroup.c_str());
+ multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
+ if (setsockopt(sockDesc, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ (raw_type *) &multicastRequest,
+ sizeof(multicastRequest)) < 0) {
+ throw SocketException("Multicast group leave failed (setsockopt())", true);
+ }
+}
--- /dev/null
+/*
+ * C++ sockets on Unix and Windows
+ * Copyright (C) 2002
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/practical/
+#ifndef __SOCKET_
+#define __SOCKET_
+
+#include <string> // For string
+#include <exception> // For exception class
+
+using namespace std;
+
+/**
+ * Signals a problem with the execution of a socket call.
+ */
+class SocketException : public exception {
+public:
+ /**
+ * Construct a SocketException with a explanatory message.
+ * @param message explanatory message
+ * @param incSysMsg true if system message (from strerror(errno))
+ * should be postfixed to the user provided message
+ */
+ SocketException(const string &message, bool inclSysMsg = false) throw();
+
+ /**
+ * Provided just to guarantee that no exceptions are thrown.
+ */
+ ~SocketException() throw();
+
+ /**
+ * Get the exception message
+ * @return exception message
+ */
+ const char *what() const throw();
+
+private:
+ string userMessage; // Exception message
+};
+
+/**
+ * Base class representing basic communication endpoint
+ */
+class Socket {
+public:
+ /**
+ * Close and deallocate this socket
+ */
+ ~Socket();
+
+ /**
+ * Get the local address
+ * @return local address of socket
+ * @exception SocketException thrown if fetch fails
+ */
+ string getLocalAddress() throw(SocketException);
+
+ /**
+ * Get the local port
+ * @return local port of socket
+ * @exception SocketException thrown if fetch fails
+ */
+ unsigned short getLocalPort() throw(SocketException);
+
+ /**
+ * Set the local port to the specified port and the local address
+ * to any interface
+ * @param localPort local port
+ * @exception SocketException thrown if setting local port fails
+ */
+ void setLocalPort(unsigned short localPort) throw(SocketException);
+
+ /**
+ * Set the local port to the specified port and the local address
+ * to the specified address. If you omit the port, a random port
+ * will be selected.
+ * @param localAddress local address
+ * @param localPort local port
+ * @exception SocketException thrown if setting local port or address fails
+ */
+ void setLocalAddressAndPort(const string &localAddress,
+ unsigned short localPort = 0) throw(SocketException);
+
+ /**
+ * If WinSock, unload the WinSock DLLs; otherwise do nothing. We ignore
+ * this in our sample client code but include it in the library for
+ * completeness. If you are running on Windows and you are concerned
+ * about DLL resource consumption, call this after you are done with all
+ * Socket instances. If you execute this on Windows while some instance of
+ * Socket exists, you are toast. For portability of client code, this is
+ * an empty function on non-Windows platforms so you can always include it.
+ * @param buffer buffer to receive the data
+ * @param bufferLen maximum number of bytes to read into buffer
+ * @return number of bytes read, 0 for EOF, and -1 for error
+ * @exception SocketException thrown WinSock clean up fails
+ */
+ static void cleanUp() throw(SocketException);
+
+ /**
+ * Resolve the specified service for the specified protocol to the
+ * corresponding port number in host byte order
+ * @param service service to resolve (e.g., "http")
+ * @param protocol protocol of service to resolve. Default is "tcp".
+ */
+ static unsigned short resolveService(const string &service,
+ const string &protocol = "tcp");
+
+private:
+ // Prevent the user from trying to use value semantics on this object
+ Socket(const Socket &sock);
+ void operator=(const Socket &sock);
+
+protected:
+ int sockDesc; // Socket descriptor
+ Socket(int type, int protocol) throw(SocketException);
+ Socket(int sockDesc);
+};
+
+/**
+ * Socket which is able to connect, send, and receive
+ */
+class CommunicatingSocket : public Socket {
+public:
+ /**
+ * Establish a socket connection with the given foreign
+ * address and port
+ * @param foreignAddress foreign address (IP address or name)
+ * @param foreignPort foreign port
+ * @exception SocketException thrown if unable to establish connection
+ */
+ void connect(const string &foreignAddress, unsigned short foreignPort)
+ throw(SocketException);
+
+ /**
+ * Write the given buffer to this socket. Call connect() before
+ * calling send()
+ * @param buffer buffer to be written
+ * @param bufferLen number of bytes from buffer to be written
+ * @exception SocketException thrown if unable to send data
+ */
+ void send(const void *buffer, int bufferLen) throw(SocketException);
+
+ /**
+ * Read into the given buffer up to bufferLen bytes data from this
+ * socket. Call connect() before calling recv()
+ * @param buffer buffer to receive the data
+ * @param bufferLen maximum number of bytes to read into buffer
+ * @return number of bytes read, 0 for EOF, and -1 for error
+ * @exception SocketException thrown if unable to receive data
+ */
+ int recv(void *buffer, int bufferLen) throw(SocketException);
+
+ /**
+ * Get the foreign address. Call connect() before calling recv()
+ * @return foreign address
+ * @exception SocketException thrown if unable to fetch foreign address
+ */
+ string getForeignAddress() throw(SocketException);
+
+ /**
+ * Get the foreign port. Call connect() before calling recv()
+ * @return foreign port
+ * @exception SocketException thrown if unable to fetch foreign port
+ */
+ unsigned short getForeignPort() throw(SocketException);
+
+protected:
+ CommunicatingSocket(int type, int protocol) throw(SocketException);
+ CommunicatingSocket(int newConnSD);
+};
+
+/**
+ * TCP socket for communication with other TCP sockets
+ */
+class TCPSocket : public CommunicatingSocket {
+public:
+ /**
+ * Construct a TCP socket with no connection
+ * @exception SocketException thrown if unable to create TCP socket
+ */
+ TCPSocket() throw(SocketException);
+
+ /**
+ * Construct a TCP socket with a connection to the given foreign address
+ * and port
+ * @param foreignAddress foreign address (IP address or name)
+ * @param foreignPort foreign port
+ * @exception SocketException thrown if unable to create TCP socket
+ */
+ TCPSocket(const string &foreignAddress, unsigned short foreignPort)
+ throw(SocketException);
+
+private:
+ // Access for TCPServerSocket::accept() connection creation
+ friend class TCPServerSocket;
+ TCPSocket(int newConnSD);
+};
+
+/**
+ * TCP socket class for servers
+ */
+class TCPServerSocket : public Socket {
+public:
+ /**
+ * Construct a TCP socket for use with a server, accepting connections
+ * on the specified port on any interface
+ * @param localPort local port of server socket, a value of zero will
+ * give a system-assigned unused port
+ * @param queueLen maximum queue length for outstanding
+ * connection requests (default 5)
+ * @exception SocketException thrown if unable to create TCP server socket
+ */
+ TCPServerSocket(unsigned short localPort, int queueLen = 5)
+ throw(SocketException);
+
+ /**
+ * Construct a TCP socket for use with a server, accepting connections
+ * on the specified port on the interface specified by the given address
+ * @param localAddress local interface (address) of server socket
+ * @param localPort local port of server socket
+ * @param queueLen maximum queue length for outstanding
+ * connection requests (default 5)
+ * @exception SocketException thrown if unable to create TCP server socket
+ */
+ TCPServerSocket(const string &localAddress, unsigned short localPort,
+ int queueLen = 5) throw(SocketException);
+
+ /**
+ * Blocks until a new connection is established on this socket or error
+ * @return new connection socket
+ * @exception SocketException thrown if attempt to accept a new connection fails
+ */
+ TCPSocket *accept() throw(SocketException);
+
+private:
+ void setListen(int queueLen) throw(SocketException);
+};
+
+/**
+ * UDP socket class
+ */
+class UDPSocket : public CommunicatingSocket {
+public:
+ /**
+ * Construct a UDP socket
+ * @exception SocketException thrown if unable to create UDP socket
+ */
+ UDPSocket() throw(SocketException);
+
+ /**
+ * Construct a UDP socket with the given local port
+ * @param localPort local port
+ * @exception SocketException thrown if unable to create UDP socket
+ */
+ UDPSocket(unsigned short localPort) throw(SocketException);
+
+ /**
+ * Construct a UDP socket with the given local port and address
+ * @param localAddress local address
+ * @param localPort local port
+ * @exception SocketException thrown if unable to create UDP socket
+ */
+ UDPSocket(const string &localAddress, unsigned short localPort)
+ throw(SocketException);
+
+ /**
+ * Unset foreign address and port
+ * @return true if disassociation is successful
+ * @exception SocketException thrown if unable to disconnect UDP socket
+ */
+ void disconnect() throw(SocketException);
+
+ /**
+ * Send the given buffer as a UDP datagram to the
+ * specified address/port
+ * @param buffer buffer to be written
+ * @param bufferLen number of bytes to write
+ * @param foreignAddress address (IP address or name) to send to
+ * @param foreignPort port number to send to
+ * @return true if send is successful
+ * @exception SocketException thrown if unable to send datagram
+ */
+ void sendTo(const void *buffer, int bufferLen, const string &foreignAddress,
+ unsigned short foreignPort) throw(SocketException);
+
+ /**
+ * Read read up to bufferLen bytes data from this socket. The given buffer
+ * is where the data will be placed
+ * @param buffer buffer to receive data
+ * @param bufferLen maximum number of bytes to receive
+ * @param sourceAddress address of datagram source
+ * @param sourcePort port of data source
+ * @return number of bytes received and -1 for error
+ * @exception SocketException thrown if unable to receive datagram
+ */
+ int recvFrom(void *buffer, int bufferLen, string &sourceAddress,
+ unsigned short &sourcePort) throw(SocketException);
+
+ /**
+ * Set the multicast TTL
+ * @param multicastTTL multicast TTL
+ * @exception SocketException thrown if unable to set TTL
+ */
+ void setMulticastTTL(unsigned char multicastTTL) throw(SocketException);
+
+ /**
+ * Join the specified multicast group
+ * @param multicastGroup multicast group address to join
+ * @exception SocketException thrown if unable to join group
+ */
+ void joinGroup(const string &multicastGroup) throw(SocketException);
+
+ /**
+ * Leave the specified multicast group
+ * @param multicastGroup multicast group address to leave
+ * @exception SocketException thrown if unable to leave group
+ */
+ void leaveGroup(const string &multicastGroup) throw(SocketException);
+
+private:
+ void setBroadcast();
+};
+
+#endif
* @param _isSrcPortWildCard Is this source port a wild card (=can change port number)?\r
* @param _isDstPortWildCard Is this destination port a wild card (=can change port number)?\r
*/\r
- protected IoTDeviceAddress(String _sAddress, int _iSrcPort, int _iDstPort, boolean _isSrcPortWildCard, \r
+ protected IoTDeviceAddress(String _sAddress, int _iSrcPort, int _iDstPort, boolean _isSrcPortWildCard,\r
+ //public IoTDeviceAddress(String _sAddress, int _iSrcPort, int _iDstPort, boolean _isSrcPortWildCard, \r
boolean _isDstPortWildCard) throws UnknownHostException {\r
\r
super(_sAddress);\r
* Class constructor (pass the reference to this immutable wrapper)
*/
protected IoTSet(Set<T> s) {
+ //public IoTSet(Set<T> s) {
set = s;
}