From: Ali Younis Date: Sun, 23 Apr 2017 22:41:15 +0000 (-0700) Subject: Lightbulb benchmark X-Git-Url: http://plrg.eecs.uci.edu/git/?p=iotcloud.git;a=commitdiff_plain;h=d3f1a80e9e8f6c5192d88314f5619272c58a6c51 Lightbulb benchmark --- diff --git a/version2/src/java/light_fan_benchmark/BulbColor.java b/version2/src/java/light_fan_benchmark/BulbColor.java new file mode 100644 index 0000000..3463fc9 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/BulbColor.java @@ -0,0 +1,65 @@ +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; + } +} + + diff --git a/version2/src/java/light_fan_benchmark/BulbController.java b/version2/src/java/light_fan_benchmark/BulbController.java new file mode 100644 index 0000000..c1049d8 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/BulbController.java @@ -0,0 +1,61 @@ +import iotcloud.*; + +class BulbController { + public static void main(String[] args) throws Exception { + + + Table t1 = new Table("http://dc-6.calit2.uci.edu/test.iotcloud/", "reallysecret", 321, -1); + t1.initTable(); + + String a = "bulb"; + IoTString ia = new IoTString(a); + t1.createNewKey(ia, 321); + + + + + byte[] bulbMacAdd = new byte[8]; + bulbMacAdd[0] = (byte)0xD0; + bulbMacAdd[1] = (byte)0x73; + bulbMacAdd[2] = (byte)0xD5; + bulbMacAdd[3] = (byte)0x11; + bulbMacAdd[4] = (byte)0x42; + bulbMacAdd[5] = (byte)0xE5; + bulbMacAdd[6] = (byte)0x00; + bulbMacAdd[7] = (byte)0x00; + + + IoTDeviceAddress devAddr = new IoTDeviceAddress("192.168.1.5", 56700, 56700, false, false); + IoTUDP udp = new IoTUDP(devAddr); + LightBulb bulb = new LifxLightBulb(udp, bulbMacAdd); + + + String valueA = "on"; + IoTString iValueA = new IoTString(valueA); + + System.out.println("Starting System"); + + while (true) { + t1.update(); + Thread.sleep(1000); + + IoTString testValA1 = t1.getCommitted(ia); + if ((testValA1 != null) && (testValA1.equals(iValueA) == true)) { + bulb.turnOn(); + } else { + bulb.turnOff(); + } + } + + // for(int i = 0; i < 5;i++) + // { + // System.out.println(i); + // bulb.turnOff(); + // Thread.sleep(1000); + // bulb.turnOn(); + + // Thread.sleep(1000); + // } + } + +} \ No newline at end of file diff --git a/version2/src/java/light_fan_benchmark/BulbSwitch.java b/version2/src/java/light_fan_benchmark/BulbSwitch.java new file mode 100644 index 0000000..208482f --- /dev/null +++ b/version2/src/java/light_fan_benchmark/BulbSwitch.java @@ -0,0 +1,55 @@ + + +import java.util.Scanner; +import iotcloud.*; + +class BulbSwitch { + public static void main(String[] args) throws Exception { + + + System.out.println(Integer.parseInt(args[0])); + + Table t1 = new Table("http://dc-6.calit2.uci.edu/test.iotcloud/", "reallysecret", Integer.parseInt(args[0]), -1); + t1.update(); + + + String a = "bulb"; + IoTString ia = new IoTString(a); + t1.createNewKey(ia, 321); + + + String valueA = "on"; + IoTString iValueA = new IoTString(valueA); + + + String valueB = "off"; + IoTString iValueB = new IoTString(valueB); + + System.out.println("Starting System"); + + Scanner keyboard = new Scanner(System.in); + + + while (true) { + + + System.out.println("Enter 0 for off, 1 for on"); + int myint = keyboard.nextInt(); + + if (myint == 0) { + t1.update(); + t1.startTransaction(); + t1.addKV(ia, iValueB); + t1.commitTransaction(); + + } else { + t1.update(); + t1.startTransaction(); + t1.addKV(ia, iValueA); + t1.commitTransaction(); + + } + + } + } +} \ No newline at end of file diff --git a/version2/src/java/light_fan_benchmark/DeviceStateGroup.java b/version2/src/java/light_fan_benchmark/DeviceStateGroup.java new file mode 100644 index 0000000..2ff3af7 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/DeviceStateGroup.java @@ -0,0 +1,23 @@ +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; + } +} diff --git a/version2/src/java/light_fan_benchmark/DeviceStateHostFirmware.java b/version2/src/java/light_fan_benchmark/DeviceStateHostFirmware.java new file mode 100644 index 0000000..d64483a --- /dev/null +++ b/version2/src/java/light_fan_benchmark/DeviceStateHostFirmware.java @@ -0,0 +1,19 @@ +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; + } +} diff --git a/version2/src/java/light_fan_benchmark/DeviceStateHostInfo.java b/version2/src/java/light_fan_benchmark/DeviceStateHostInfo.java new file mode 100644 index 0000000..cb45cdd --- /dev/null +++ b/version2/src/java/light_fan_benchmark/DeviceStateHostInfo.java @@ -0,0 +1,25 @@ + + +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; + } +} diff --git a/version2/src/java/light_fan_benchmark/DeviceStateInfo.java b/version2/src/java/light_fan_benchmark/DeviceStateInfo.java new file mode 100644 index 0000000..ba4330f --- /dev/null +++ b/version2/src/java/light_fan_benchmark/DeviceStateInfo.java @@ -0,0 +1,26 @@ + + +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; + } +} diff --git a/version2/src/java/light_fan_benchmark/DeviceStateLocation.java b/version2/src/java/light_fan_benchmark/DeviceStateLocation.java new file mode 100644 index 0000000..fc04980 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/DeviceStateLocation.java @@ -0,0 +1,25 @@ + + +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; + } +} diff --git a/version2/src/java/light_fan_benchmark/DeviceStateService.java b/version2/src/java/light_fan_benchmark/DeviceStateService.java new file mode 100644 index 0000000..ec89595 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/DeviceStateService.java @@ -0,0 +1,19 @@ + + +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; + } +} diff --git a/version2/src/java/light_fan_benchmark/DeviceStateVersion.java b/version2/src/java/light_fan_benchmark/DeviceStateVersion.java new file mode 100644 index 0000000..e4f7c88 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/DeviceStateVersion.java @@ -0,0 +1,25 @@ + + +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; + } +} diff --git a/version2/src/java/light_fan_benchmark/DeviceStateWifiFirmware.java b/version2/src/java/light_fan_benchmark/DeviceStateWifiFirmware.java new file mode 100644 index 0000000..5e49867 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/DeviceStateWifiFirmware.java @@ -0,0 +1,21 @@ + + +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; + } +} diff --git a/version2/src/java/light_fan_benchmark/DeviceStateWifiInfo.java b/version2/src/java/light_fan_benchmark/DeviceStateWifiInfo.java new file mode 100644 index 0000000..8c84103 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/DeviceStateWifiInfo.java @@ -0,0 +1,25 @@ + + +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; + } +} diff --git a/version2/src/java/light_fan_benchmark/IoTAddress.java b/version2/src/java/light_fan_benchmark/IoTAddress.java new file mode 100644 index 0000000..5f15330 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/IoTAddress.java @@ -0,0 +1,77 @@ + +// Java packages +import java.net.Socket; +import java.net.ServerSocket; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** Class IoTAddress is a wrapper class to pass + * IoTSet of any addresses from master to slave + * + * @author Rahmadi Trimananda + * @version 1.0 + * @since 2016-04-22 + */ +public class IoTAddress { + + /** + * IoTDeviceAddress class properties + */ + protected final InetAddress inetAddress; + + /** + * Class constructor + * + * @param sAddress String address + */ + protected IoTAddress(String sAddress) throws UnknownHostException { + + inetAddress = InetAddress.getByName(sAddress); + } + + /** + * getHostAddress() method + * + * @return String + */ + public String getHostAddress() { + + return inetAddress.getHostAddress(); + + } + + /** + * getHostName() method + * + * @return String + */ + public String getHostName() { + + return inetAddress.getHostName(); + + } + + /** + * getUrl() method + * + * @return String + */ + public String getURL(String strURLComplete) { + + //e.g. http:// + inetAddress.getHostAddress() + strURLComplete + // http://192.168.2.254/cgi-bin/mjpg/video.cgi? + return "http://" + inetAddress.getHostAddress() + strURLComplete; + + } + + /** + * getCompleteAddress() method + * + * @return String + */ + public String getCompleteAddress() { + + return inetAddress.toString(); + + } +} diff --git a/version2/src/java/light_fan_benchmark/IoTDeviceAddress.java b/version2/src/java/light_fan_benchmark/IoTDeviceAddress.java new file mode 100644 index 0000000..0642439 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/IoTDeviceAddress.java @@ -0,0 +1,137 @@ +// Java packages +import java.net.Socket; +import java.net.ServerSocket; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** Class IoTDeviceAddress is a wrapper class to pass + * IoTSet of device addresses from master to slave + * + * @author Rahmadi Trimananda + * @version 1.0 + * @since 2016-02-18 + */ +public class IoTDeviceAddress extends IoTAddress { + + /** + * IoTDeviceAddress class properties + */ + private int iSrcPort; + private int iDstPort; + private final String sAddress; + + // the wildcard status of this address + private final boolean isSrcPortWildCard; + private final boolean isDstPortWildCard; + + + /** + * Class constructor + * + * @param sAddress String address + * @param _iSrcPort Source port number + * @param _iDstPort Destination port number + * @param _isSrcPortWildCard Is this source port a wild card (=can change port number)? + * @param _isDstPortWildCard Is this destination port a wild card (=can change port number)? + */ + protected IoTDeviceAddress(String _sAddress, int _iSrcPort, int _iDstPort, boolean _isSrcPortWildCard, + boolean _isDstPortWildCard) throws UnknownHostException { + + super(_sAddress); + sAddress = _sAddress; + iSrcPort = _iSrcPort; + iDstPort = _iDstPort; + + isSrcPortWildCard = _isSrcPortWildCard; + isDstPortWildCard = _isDstPortWildCard; + } + + /** + * getSourcePortNumber() method + * + * @return int + */ + public int getSourcePortNumber() { + + return iSrcPort; + + } + + /** + * getDestinationPortNumber() method + * + * @return int + */ + public int getDestinationPortNumber() { + + return iDstPort; + + } + + /** + * setSrcPort() method + * + * @param port Port number + * @return void + */ + public void setSrcPort(int port) { + if (isSrcPortWildCard) { + iSrcPort = port; + } + } + + /** + * setDstPort() method + * + * @param port Port number + * @return void + */ + public void setDstPort(int port) { + if (isDstPortWildCard) { + iDstPort = port; + } + } + + /** + * getAddress() method + * + * @return String + */ + public String getAddress() { + return sAddress; + } + + /** + * getHostAddress() method + * + * @return String + */ + public static String getLocalHostAddress() { + + String strLocalHostAddress = null; + try { + strLocalHostAddress = InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException ex) { + ex.printStackTrace(); + } + return strLocalHostAddress; + } + + /** + * getIsSrcPortWildcard() method + * + * @return boolean + */ + public boolean getIsSrcPortWildcard() { + return isSrcPortWildCard; + } + + /** + * getIsDstPortWildcard() method + * + * @return boolean + */ + public boolean getIsDstPortWildcard() { + return isDstPortWildCard; + } +} diff --git a/version2/src/java/light_fan_benchmark/IoTHTTP.java b/version2/src/java/light_fan_benchmark/IoTHTTP.java new file mode 100644 index 0000000..5d9d2b7 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/IoTHTTP.java @@ -0,0 +1,149 @@ + +// Java packages +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.UnknownHostException; +import java.net.URL; +import java.net.ProtocolException; + + +/** Class IoTHTTP is a wrapper class that provides + * minimum interfaces for user to interact with IoT + * devices in our system + * + * @author Rahmadi Trimananda + * @version 1.0 + * @since 2016-02-18 + */ +public class IoTHTTP { + + /** + * IoTHTTP class properties + */ + private IoTDeviceAddress iotDevAdd; + private URL url; + private HttpURLConnection httpConnection; + + /** + * Class constructor + */ + public IoTHTTP(IoTDeviceAddress _iotDevAdd) { + + iotDevAdd = _iotDevAdd; + url = null; + httpConnection = null; + } + + /** + * setURL() method + * + * @param strUrlComplete String to complete the URL + * @return void + */ + public void setURL(String strUrlComplete) throws MalformedURLException { + + url = new URL(iotDevAdd.getURL(strUrlComplete)); + + } + + /** + * openConnection() method + */ + public void openConnection() throws IOException { + + httpConnection = (HttpURLConnection) url.openConnection(); + + } + + /** + * setDoInput() method inherited from HttpURLConnection class + * + * @param bSetDoInput + * @return void + */ + public void setDoInput(boolean bSetDoInput) { + + httpConnection.setDoInput(bSetDoInput); + + } + + /** + * setRequestProperty() method inherited from HttpURLConnection class + * + * @param strProperty String property + * @param strHttpAuthCredentials String HTTP authentication credentials + * @return void + */ + public void setRequestProperty(String strProperty, String strHttpAuthCredentials) { + + httpConnection.setRequestProperty(strProperty, strHttpAuthCredentials); + + } + + /** + * setRequestMethod() method inherited from HttpURLConnection class + * + * @param strMethod String method + * @return void + */ + public void setRequestMethod(String strMethod) throws ProtocolException { + + httpConnection.setRequestMethod(strMethod); + + } + + /** + * setDoOutput() method inherited from HttpURLConnection class + * + * @param doOut + * @return void + */ + public void setDoOutput(boolean doOut) { + + httpConnection.setDoOutput(doOut); + + } + + /** + * getOutputStream() method inherited from HttpURLConnection class + * + * @return OutputStream + */ + public OutputStream getOutputStream() throws IOException { + + return httpConnection.getOutputStream(); + + } + + /** + * getInputStream() method inherited from HttpURLConnection class + * + * @return InputStream + */ + public InputStream getInputStream() throws IOException { + + return httpConnection.getInputStream(); + + } + + /** + * connect() method inherited from HttpURLConnection class + */ + public void connect() throws IOException { + + httpConnection.connect(); + + } + + /** + * disconnect() method inherited from HttpURLConnection class + */ + public void disconnect() throws IOException { + + httpConnection.disconnect(); + + } +} diff --git a/version2/src/java/light_fan_benchmark/IoTSet.java b/version2/src/java/light_fan_benchmark/IoTSet.java new file mode 100644 index 0000000..ccf8543 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/IoTSet.java @@ -0,0 +1,79 @@ +import java.lang.UnsupportedOperationException; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import java.util.Spliterator; + + +/** Class IoTSet is the actual implementation of @config IoTSet<...>. + * Upon extracting DB information, SetInstrumenter class will use + * this class to actually instantiate the Set as IoTSet that uses + * Java Set to implement; we don't provide interfaces to modify + * the contents, but we do provide means to read them out + * + * @author Rahmadi Trimananda + * @version 1.0 + * @since 2015-12-01 + */ +public final class IoTSet { + + /** + * Reference to an object Set + */ + private Set set; + + /** + * Class constructor (pass the reference to this immutable wrapper) + */ + protected IoTSet(Set s) { + + set = s; + } + + /** + * contains() method inherited from Set interface + */ + public boolean contains(T o) { + + return set.contains(o); + + } + + /** + * isEmpty() method inherited from Set interface + */ + public boolean isEmpty() { + + return set.isEmpty(); + + } + + /** + * iterator() method inherited from Set interface + */ + public Iterator iterator() { + + return new HashSet(set).iterator(); + + } + + /** + * size() method inherited from Set interface + */ + public int size() { + + return set.size(); + + } + + /** + * values() method to return Set object values for easy iteration + */ + public Set values() { + + return new HashSet(set); + + } +} diff --git a/version2/src/java/light_fan_benchmark/IoTUDP.java b/version2/src/java/light_fan_benchmark/IoTUDP.java new file mode 100644 index 0000000..e8966e8 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/IoTUDP.java @@ -0,0 +1,133 @@ + +// Java packages +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketException; +import java.net.UnknownHostException; + + +/** Class IoTUDP is a wrapper class that provides + * minimum interfaces for user to interact with IoT + * devices in our system - adapted from my colleague's + * work (Ali Younis - ayounis @ uci.edu) + * + * @author Rahmadi Trimananda + * @version 1.0 + * @since 2016-02-20 + */ +public class IoTUDP { + + /** + * IoTUDP class properties + */ + private final String strHostAddress; + private final int iSrcPort; + private final int iDstPort; + private DatagramSocket socket; // the socket interface that we are guarding + private boolean didClose; // make sure that the clean up was done correctly + + /** + * Class constructor + */ + public IoTUDP(IoTDeviceAddress iotDevAdd) throws SocketException, IOException { + + strHostAddress = iotDevAdd.getHostAddress(); + iSrcPort = iotDevAdd.getSourcePortNumber(); + iDstPort = iotDevAdd.getDestinationPortNumber(); + + socket = new DatagramSocket(iSrcPort); + didClose = false; + } + + /** + * sendData() method + * + * @param bData Byte type that passes the data to be sent + * @return void + */ + public void sendData(byte[] bData) throws UnknownHostException, IOException { + + DatagramPacket dpSendPacket = new DatagramPacket(bData, bData.length, InetAddress.getByName(strHostAddress), iDstPort); + socket.send(dpSendPacket); + } + + /** + * recieveData() method + * + * @param iMaxDataLength Integer maximum data length as reference + * @return byte[] + */ + public byte[] recieveData(int iMaxDataLength) throws IOException { + + byte[] bReceiveData = new byte[iMaxDataLength]; + DatagramPacket dpReceivePacket = new DatagramPacket(bReceiveData, bReceiveData.length); + socket.receive(dpReceivePacket); + + return dpReceivePacket.getData(); + } + + /** + * setSoTimeout() method + * + * @param iTimeout Integer timeout time + */ + public void setSoTimeout(int iTimeout) throws SocketException { + + socket.setSoTimeout(iTimeout); + + } + + /** + * setSendBufferSize() method + * + * @param iSize Integer buffer size + */ + public void setSendBufferSize(int iSize) throws SocketException { + + socket.setSendBufferSize(iSize); + + } + + /** + * setReceiveBufferSize() method + * + * @param iSize Integer buffer size + */ + public void setReceiveBufferSize(int iSize) throws SocketException { + + socket.setReceiveBufferSize(iSize); + + } + + /** + * setReuseAddress(boolean on) method + */ + public void setReuseAddress(boolean on) throws SocketException { + + socket.setReuseAddress(on); + } + + /** + * close() method + */ + public void close() { + + socket.close(); + didClose = true; + + } + + /** + * close() called by the garbage collector right before trashing object + */ + public void finalize() throws SocketException { + + if (!didClose) { + close(); + throw new SocketException("Socket not closed before object destruction, must call close method."); + } + + } +} diff --git a/version2/src/java/light_fan_benchmark/LifxHeader.java b/version2/src/java/light_fan_benchmark/LifxHeader.java new file mode 100644 index 0000000..b90422e --- /dev/null +++ b/version2/src/java/light_fan_benchmark/LifxHeader.java @@ -0,0 +1,263 @@ + + +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); + } +} diff --git a/version2/src/java/light_fan_benchmark/LifxLightBulb.java b/version2/src/java/light_fan_benchmark/LifxLightBulb.java new file mode 100644 index 0000000..400ee08 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/LifxLightBulb.java @@ -0,0 +1,1209 @@ + + +// 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.*; + +// 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. + private IoTSet 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(); + + } +} + + + + + + + + + + + + + + + + + + + + diff --git a/version2/src/java/light_fan_benchmark/LightBulb.java b/version2/src/java/light_fan_benchmark/LightBulb.java new file mode 100644 index 0000000..8d7f6a5 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/LightBulb.java @@ -0,0 +1,159 @@ +/** Class LightBulb interface for the light bulb devices. + * + * @author Ali Younis + * @version 1.0 + * @since 2016-01-27 + */ + + +public interface LightBulb { + + /** Method to turn the light bulb on (Physically illuminate the area). + * + * @param None. + * + * @return [void] None. + */ + + public void turnOff(); + + /** Method to turn the light bulb off. + * + * @return [void] None. + */ + public void turnOn(); + + + /** Method to get the current on/off state of the light bulb. + * + * @return [boolean] True means bulb on. + */ + public boolean getState(); + + + /** Method to set the light bulb color using Standard Hue, Saturation and Brightness + * conventions. See "http://www.tydac.ch/color/" for reference. + * + * @param _hue [double]: Hue value (in degrees). + * @param _saturation [double]: Saturation value (percentage). + * @param _brightness [double]: Brightness value (percentage). + * + * @return [void] None. + */ + public void setColor(double _hue, double _saturation, double _brightness); + + + /** Method to set the color temperature. + * + * @param _temperature [int]: Color temperature in degrees kelvin. + * + * @return [void] None. + */ + public void setTemperature(int _temperature); + + + /** Method to get the current hue value of the bulb. + * + * @return [double] Current hue value of the bulb in degrees. + */ + public double getHue(); + + + /** Method to get the current saturation value of the bulb. + * + * @return [double] Current saturation value of the bulb as a percentage. + */ + public double getSaturation(); + + + /** Method to get the current brightness value of the bulb. + * + * @return [double] Current brightness value of the bulb as a percentage. + */ + public double getBrightness(); + + + /** Method to get the current color temperature value of the bulb. + * + * @return [double] Current color temperature value of the bulb in kelvin. + */ + public int getTemperature(); + + + /** Method to get the hue range lower bound supported by the bulb. + * + * @return [double] Hue lower bound in degrees. + */ + public double getHueRangeLowerBound(); + + + /** Method to get the hue range upper bound supported by the bulb. + * + * @return [double] Hue upper bound in degrees. + */ + public double getHueRangeUpperBound(); + + + /** Method to get the saturation range lower bound supported by the bulb. + * + * @return [double] Saturation lower bound as a percentage. + */ + public double getSaturationRangeLowerBound(); + + + /** Method to get the saturation range upper bound supported by the bulb. + * + * @return [double] Saturation upper bound as a percentage. + */ + public double getSaturationRangeUpperBound(); + + + /** Method to get the brightness range lower bound supported by the bulb. + * + * @return [double] Brightness lower bound as a percentage. + */ + public double getBrightnessRangeLowerBound(); + + + /** Method to get the brightness range upper bound supported by the bulb. + * + * @return [double] Brightness upper bound as a percentage. + */ + public double getBrightnessRangeUpperBound(); + + + /** Method to get the temperature range lower bound supported by the bulb. + * + * @return [int] Temperature lower bound as a percentage. + */ + public int getTemperatureRangeLowerBound(); + + + /** Method to get the temperature range upper bound supported by the bulb. + * + * @return [int] Temperature upper bound as a percentage. + */ + public int getTemperatureRangeUpperBound(); + + + /** Method to initialize the bulb, if the bulb needs to be initialized. + * + * @return [void] None. + */ + public void init(); + +} + + + + + + + + + + + + + + diff --git a/version2/src/java/light_fan_benchmark/LightState.java b/version2/src/java/light_fan_benchmark/LightState.java new file mode 100644 index 0000000..80bc77c --- /dev/null +++ b/version2/src/java/light_fan_benchmark/LightState.java @@ -0,0 +1,25 @@ + + +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; + } +} diff --git a/version2/src/java/light_fan_benchmark/README.txt b/version2/src/java/light_fan_benchmark/README.txt new file mode 100644 index 0000000..fa590be --- /dev/null +++ b/version2/src/java/light_fan_benchmark/README.txt @@ -0,0 +1,13 @@ +First build using: + ./build.bash + +To run this example run: + + # Starts the light bulb controller + ./run1.bash + + # For each lightbulb switch you need to run + ./run2.bash + + +Dont forget to clear the server directory \ No newline at end of file diff --git a/version2/src/java/light_fan_benchmark/Wemo.java b/version2/src/java/light_fan_benchmark/Wemo.java new file mode 100644 index 0000000..d020b75 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/Wemo.java @@ -0,0 +1,108 @@ +// IoT Packages + +//import iotcode.annotation.*; + +// Native Java Packages +import java.util.Iterator; +import javax.xml.parsers.*; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import org.w3c.dom.*; +import org.xml.sax.SAXException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.Semaphore; +import java.util.List; +import java.util.ArrayList; + +public class Wemo { + + private IoTDeviceAddress deviceAddress = null; + + public Wemo(IoTDeviceAddress _deviceAddress) { + deviceAddress = _deviceAddress; + + } + + + + + public void turnOff() throws IOException { + IoTHTTP httpConnection = null; + try { + httpConnection = new IoTHTTP(deviceAddress); + httpConnection.setURL("/upnp/control/basicevent1"); + + httpConnection.openConnection(); + httpConnection.setDoOutput(true); + httpConnection.setRequestMethod("POST"); + httpConnection.setRequestProperty("Content-type", "text/xml; charset=\"utf-8\""); + httpConnection.setRequestProperty("SOAPACTION", "\"urn:Belkin:service:basicevent:1#SetBinaryState\""); + httpConnection.setRequestProperty("Accept", ""); + + String reqXML = "0\n"; + + OutputStream reqStream = httpConnection.getOutputStream(); + reqStream.write(reqXML.getBytes()); + + InputStream resStream = httpConnection.getInputStream(); + byte[] byteBuf = new byte[10240]; + int len = resStream.read(byteBuf); + + reqStream.close(); + resStream.close(); + + + } finally { + if (httpConnection != null) { + try { + httpConnection.disconnect(); + + } catch (Exception e) { + e.printStackTrace(); + + } + } + } + + } + + public void turnOn() throws IOException { + IoTHTTP httpConnection = null; + try { + httpConnection = new IoTHTTP(deviceAddress); + httpConnection.setURL("/upnp/control/basicevent1"); + + httpConnection.openConnection(); + httpConnection.setDoOutput(true); + httpConnection.setRequestMethod("POST"); + httpConnection.setRequestProperty("Content-type", "text/xml; charset=\"utf-8\""); + httpConnection.setRequestProperty("SOAPACTION", "\"urn:Belkin:service:basicevent:1#SetBinaryState\""); + httpConnection.setRequestProperty("Accept", ""); + + String reqXML = "1\n"; + + OutputStream reqStream = httpConnection.getOutputStream(); + reqStream.write(reqXML.getBytes()); + + InputStream resStream = httpConnection.getInputStream(); + byte[] byteBuf = new byte[10240]; + int len = resStream.read(byteBuf); + + reqStream.close(); + resStream.close(); + + } finally { + if (httpConnection != null) { + try { + httpConnection.disconnect(); + + } catch (Exception e) { + e.printStackTrace(); + + } + } + } + } +} \ No newline at end of file diff --git a/version2/src/java/light_fan_benchmark/build.bash b/version2/src/java/light_fan_benchmark/build.bash new file mode 100755 index 0000000..dbce681 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/build.bash @@ -0,0 +1 @@ +javac -cp .:/Users/Ali/Desktop/iotcloud/version2/src/java/iotcloud/bin *.java \ No newline at end of file diff --git a/version2/src/java/light_fan_benchmark/run1.bash b/version2/src/java/light_fan_benchmark/run1.bash new file mode 100755 index 0000000..b85a630 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/run1.bash @@ -0,0 +1 @@ +java -cp .:/Users/Ali/Desktop/iotcloud/version2/src/java/iotcloud/bin BulbController \ No newline at end of file diff --git a/version2/src/java/light_fan_benchmark/run2.bash b/version2/src/java/light_fan_benchmark/run2.bash new file mode 100755 index 0000000..24b3362 --- /dev/null +++ b/version2/src/java/light_fan_benchmark/run2.bash @@ -0,0 +1,3 @@ +#!/bin/sh + +java -cp .:/Users/Ali/Desktop/iotcloud/version2/src/java/iotcloud/bin BulbSwitch "$1" \ No newline at end of file