Initial version of Lifx lightbulb controller in C++ for Fidelius
authorrtrimana <rtrimana@uci.edu>
Wed, 9 May 2018 02:04:01 +0000 (19:04 -0700)
committerrtrimana <rtrimana@uci.edu>
Wed, 9 May 2018 02:04:01 +0000 (19:04 -0700)
24 files changed:
version2/src/RPi/BulbColor.h [new file with mode: 0644]
version2/src/RPi/DeviceStateGroup.h [new file with mode: 0644]
version2/src/RPi/DeviceStateHostFirmware.h [new file with mode: 0644]
version2/src/RPi/DeviceStateHostInfo.h [new file with mode: 0644]
version2/src/RPi/DeviceStateInfo.h [new file with mode: 0644]
version2/src/RPi/DeviceStateLocation.h [new file with mode: 0644]
version2/src/RPi/DeviceStateService.h [new file with mode: 0644]
version2/src/RPi/DeviceStateVersion.h [new file with mode: 0644]
version2/src/RPi/DeviceStateWifiFirmware.h [new file with mode: 0644]
version2/src/RPi/DeviceStateWifiInfo.h [new file with mode: 0644]
version2/src/RPi/IoTAddress.h [new file with mode: 0644]
version2/src/RPi/IoTDeviceAddress.h [new file with mode: 0644]
version2/src/RPi/IoTSet.h [new file with mode: 0644]
version2/src/RPi/IoTUDP.h [new file with mode: 0644]
version2/src/RPi/LifxHeader.h [new file with mode: 0644]
version2/src/RPi/LifxLightBulb.cpp [new file with mode: 0644]
version2/src/RPi/LifxLightBulb.h [new file with mode: 0644]
version2/src/RPi/LightBulb.h [new file with mode: 0644]
version2/src/RPi/LightState.h [new file with mode: 0644]
version2/src/RPi/LightsController.ino [new file with mode: 0644]
version2/src/RPi/Makefile [new file with mode: 0644]
version2/src/RPi/README.txt [new file with mode: 0644]
version2/src/RPi/common.mk [new file with mode: 0644]
version2/src/RPi/gmon.out [new file with mode: 0644]

diff --git a/version2/src/RPi/BulbColor.h b/version2/src/RPi/BulbColor.h
new file mode 100644 (file)
index 0000000..329d060
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef _BULBCOLOR_H__
+#define _BULBCOLOR_H__
+#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
diff --git a/version2/src/RPi/DeviceStateGroup.h b/version2/src/RPi/DeviceStateGroup.h
new file mode 100644 (file)
index 0000000..c54bce0
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _DEVICESTATEGROUP_H__
+#define _DEVICESTATEGROUP_H__
+#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
diff --git a/version2/src/RPi/DeviceStateHostFirmware.h b/version2/src/RPi/DeviceStateHostFirmware.h
new file mode 100644 (file)
index 0000000..b2dd88a
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _DEVICESTATEHOSTFIRMWARE_H__
+#define _DEVICESTATEHOSTFIRMWARE_H__
+#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
diff --git a/version2/src/RPi/DeviceStateHostInfo.h b/version2/src/RPi/DeviceStateHostInfo.h
new file mode 100644 (file)
index 0000000..081f6b9
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef _DEVICESTATEHOSTINFO_H__
+#define _DEVICESTATEHOSTINFO_H__
+#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
diff --git a/version2/src/RPi/DeviceStateInfo.h b/version2/src/RPi/DeviceStateInfo.h
new file mode 100644 (file)
index 0000000..68d4bd5
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef _DEVICESTATEINFO_H__
+#define _DEVICESTATEINFO_H__
+#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
diff --git a/version2/src/RPi/DeviceStateLocation.h b/version2/src/RPi/DeviceStateLocation.h
new file mode 100644 (file)
index 0000000..70f9bab
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _DEVICESTATELOCATION_H__
+#define _DEVICESTATELOCATION_H__
+#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
diff --git a/version2/src/RPi/DeviceStateService.h b/version2/src/RPi/DeviceStateService.h
new file mode 100644 (file)
index 0000000..784cc3f
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef _DEVICESTATESERVICE_H__
+#define _DEVICESTATESERVICE_H__
+#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
diff --git a/version2/src/RPi/DeviceStateVersion.h b/version2/src/RPi/DeviceStateVersion.h
new file mode 100644 (file)
index 0000000..2e40d03
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef _DEVICESTATEVERSION_H__
+#define _DEVICESTATEVERSION_H__
+#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
diff --git a/version2/src/RPi/DeviceStateWifiFirmware.h b/version2/src/RPi/DeviceStateWifiFirmware.h
new file mode 100644 (file)
index 0000000..28c1d26
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _DEVICESTATEWIFIFIRMWARE_H__
+#define _DEVICESTATEWIFIFIRMWARE_H__
+#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
diff --git a/version2/src/RPi/DeviceStateWifiInfo.h b/version2/src/RPi/DeviceStateWifiInfo.h
new file mode 100644 (file)
index 0000000..7bbc83b
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef _DEVICESTATEWIFIINFO_H__
+#define _DEVICESTATEWIFIINFO_H__
+#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
diff --git a/version2/src/RPi/IoTAddress.h b/version2/src/RPi/IoTAddress.h
new file mode 100644 (file)
index 0000000..a057d3d
--- /dev/null
@@ -0,0 +1,59 @@
+#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(uint8_t* _sAddress) {
+
+                       inetAddress = _sAddress;
+               }
+
+
+               // Constructor
+               IoTAddress() {
+               }
+
+
+               ~IoTAddress() {
+               }
+
+
+               uint8_t* 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:
+               uint8_t* inetAddress;
+};
+#endif 
diff --git a/version2/src/RPi/IoTDeviceAddress.h b/version2/src/RPi/IoTDeviceAddress.h
new file mode 100644 (file)
index 0000000..c9c2828
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef _IOTDEVICEADDRESS_H__
+#define _IOTDEVICEADDRESS_H__
+#include <iostream>
+
+#include "IoTAddress.h"
+
+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 final : public IoTAddress
+{
+
+       public:
+
+               // Constructor
+               IoTDeviceAddress(uint8_t* _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 
diff --git a/version2/src/RPi/IoTSet.h b/version2/src/RPi/IoTSet.h
new file mode 100644 (file)
index 0000000..0104809
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef _IOTSET_H__
+#define _IOTSET_H__
+#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 final {
+       private:
+               const unordered_set<T>* set;
+       public:
+               IoTSet();
+               IoTSet(const unordered_set<T>* 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() {
+
+}
+
+
+/**
+ * Find the object k in the set
+ */
+template <class T>
+typename unordered_set<T>::const_iterator IoTSet<T>::find(const T& k) {
+
+       return (new unordered_set<T>(*set))->find(k);
+}
+
+
+/**
+ * Return the "begin" iterator
+ */
+template <class T>
+typename unordered_set<T>::const_iterator IoTSet<T>::begin() {
+
+       return (new unordered_set<T>(*set))->begin();
+}
+
+
+/**
+ * Return the "end" iterator
+ */
+template <class T>
+typename unordered_set<T>::const_iterator IoTSet<T>::end() {
+
+       return (new unordered_set<T>(*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
+
diff --git a/version2/src/RPi/IoTUDP.h b/version2/src/RPi/IoTUDP.h
new file mode 100644 (file)
index 0000000..e9f50ca
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef _IOTUDP_H__
+#define _IOTUDP_H__
+#include <iostream>
+
+#include "IoTDeviceAddress.h"
+#include "application.h"
+
+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 final
+{
+       // IoTUDP class properties
+       private:
+               //UDPSocket *socket;
+               UDP socket;
+               uint8_t* strHostAddress;
+               int iSrcPort;
+               int iDstPort;
+               bool didClose;
+               int timeOut;
+
+       public:
+
+               // Constructor
+               IoTUDP(IoTDeviceAddress* iotDevAdd) {
+
+                       strHostAddress = iotDevAdd->getAddress();
+                       iSrcPort = iotDevAdd->getSourcePortNumber();
+                       iDstPort = iotDevAdd->getDestinationPortNumber();
+                       timeOut = 0;
+
+                       //socket = new UDPSocket(iSrcPort);
+                       socket.begin(iSrcPort);
+                       didClose = false;
+               }
+
+
+               ~IoTUDP() {
+               }
+
+
+               uint8_t* getHostAddress() {
+                       return strHostAddress;
+               }
+
+
+               int getSourcePort() {
+                       return iSrcPort;
+               }
+
+
+               int getDestinationPort() {
+                       return iDstPort;
+               }
+
+
+               void setTimeOut(int interval) {
+
+                       timeOut = interval;
+               }
+
+
+               // Send data packet
+               void sendData(const char* buffer, int bufferLen) {
+               //void sendData(const void* buffer, int bufferLen) {
+                       unsigned short destinationPort = (unsigned short) iDstPort;
+                       IPAddress ipFromBytes = strHostAddress;
+                       socket.sendPacket(buffer, bufferLen, ipFromBytes, destinationPort);
+                       //socket->sendTo(buffer, bufferLen, strHostAddress, destinationPort);
+               }
+
+
+               // Receive data packet
+               int receiveData(char* buffer, int iMaxDataLength) {
+               //int receiveData(void* buffer, int iMaxDataLength) {
+                       //unsigned short destinationPort = (unsigned short) iDstPort;
+                       return socket.receivePacket(buffer, iMaxDataLength);                    
+                       //return socket->recvFrom(buffer, iMaxDataLength, strHostAddress, destinationPort);
+               }
+};
+#endif 
diff --git a/version2/src/RPi/LifxHeader.h b/version2/src/RPi/LifxHeader.h
new file mode 100644 (file)
index 0000000..6d4fbe5
--- /dev/null
@@ -0,0 +1,287 @@
+#ifndef _LIFXHEADER_H__
+#define _LIFXHEADER_H__
+#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
diff --git a/version2/src/RPi/LifxLightBulb.cpp b/version2/src/RPi/LifxLightBulb.cpp
new file mode 100644 (file)
index 0000000..aff004f
--- /dev/null
@@ -0,0 +1,1187 @@
+#include <iostream>
+#include <string>
+#include <thread>
+
+#include <pthread.h>
+
+#include "LifxLightBulb.h"
+#include "IoTSet.h"
+#include "IoTDeviceAddress.h"
+
+using namespace std;
+
+/* TODO: Uncomment this to do normal C++ (g++)
+int main(int argc, char *argv[])
+{
+       string macAddress1 = "D073D5128E300000";
+       //string macAddress1 = "D073D50241DA0000";
+       string devIPAddress1 = "192.168.1.126";
+       //string devIPAddress1 = "192.168.1.232";
+       LifxLightBulb *llb1 = new LifxLightBulb(devIPAddress1, macAddress1, 12345);
+
+       llb1->init();
+       for(int i=0; i < 1; i++) {
+               llb1->turnOff();
+               this_thread::sleep_for (chrono::milliseconds(1000));
+               cout << "Turn off" << endl;
+               llb1->turnOn();
+               this_thread::sleep_for (chrono::milliseconds(1000));
+               cout << "Turn on" << endl;
+       }
+
+
+       //delete setDevAddress1;
+       delete llb1;
+
+       return 0;
+}*/
+
+
+// Constructor
+LifxLightBulb::LifxLightBulb() { 
+       // LB1 macAddress: d0:73:d5:12:8e:30
+       // LB2 macAddress: d0:73:d5:02:41:da
+       string macAddress = "D073D5128E300000";
+       //string macAddress = "D073D50241DA0000";
+       /*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());
+       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);
+       }
+}
+
+
+// Constructor
+LifxLightBulb::LifxLightBulb(uint8_t* ipAddress, string macAddress, int srcPort) { 
+
+       // 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: ";
+
+       // Initialize device address
+       // Port 56700 is the default port for Lifx
+       IoTDeviceAddress* devAddress = new IoTDeviceAddress(ipAddress, srcPort, 56700, false, false);
+       unordered_set<void*>* myset1 = new unordered_set<void*>();
+       myset1->insert(devAddress);
+       IoTSet<void*>* setDevAddress = new IoTSet<void*>(myset1);
+       lb_addresses = setDevAddress;
+       //cout << "Device address is set! " << endl;
+
+}
+
+
+// Driver constructor always gets a pointer to device address, trailed by class arguments of generic type
+LifxLightBulb::LifxLightBulb(IoTSet<void*>* _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: ";
+
+       // Initialize device address
+       lb_addresses = _devAddress;
+       //cout << "Device address is set! " << endl;
+}
+
+
+LifxLightBulb::~LifxLightBulb() {
+
+       // Clean up
+       if (communicationSocket != NULL) {
+
+               delete communicationSocket;
+               communicationSocket = NULL;             
+       }
+       for(void* dev : *lb_addresses) {
+               IoTDeviceAddress* dv = (IoTDeviceAddress*) dev;
+               delete dv;
+               dv = NULL;
+       }
+       if (lb_addresses != NULL) {
+
+               delete lb_addresses;
+               lb_addresses = NULL;            
+       }
+}
+
+
+// PUBLIC METHODS
+// Initialize the lightbulb
+void LifxLightBulb::init() {
+
+       //if (didAlreadyInit.exchange(true))
+       if (didAlreadyInit)
+               return;
+       // Set to true if not yet
+       didAlreadyInit = true;
+
+       unordered_set<void*>::const_iterator itr = lb_addresses->begin();
+       IoTDeviceAddress* deviceAddress = (IoTDeviceAddress*) *itr;
+       //cout << "Address: " << deviceAddress->getAddress() << endl;
+
+       // Create IoTUDP socket
+       communicationSocket = new IoTUDP(deviceAddress);
+
+       //cout << "Host address: " << communicationSocket->getHostAddress() << endl;
+       //cout << "Source port: " << communicationSocket->getSourcePort() << endl;
+       //cout << "Destination port: " << communicationSocket->getDestinationPort() << endl << endl;
+
+       // Launch the worker function in a separate thread.
+       //              NOTE: "this" pointer is passed into the detached thread because it does not belong
+       //                      to this object anymore so if it executes certain methods of "this" object, then it needs
+       //                      the correct references to stuff
+       thread th1 (&LifxLightBulb::workerFunction, this, this);
+       th1.detach();
+
+       //cout << "Initialized LifxLightBulb!" << endl;
+}
+
+
+void LifxLightBulb::turnOff() {
+
+       //lock_guard<mutex> guard(bulbStateMutex);
+       bulbStateMutex.lock();
+       bulbIsOn = false;
+       sendSetLightPowerPacket(0, 0);
+       stateDidChange = true;
+       bulbStateMutex.unlock();
+}
+
+
+void LifxLightBulb::turnOn() {
+
+       //lock_guard<mutex> guard(bulbStateMutex);
+       bulbStateMutex.lock();
+       bulbIsOn = true;
+       sendSetLightPowerPacket(65535, 0);
+       stateDidChange = true;
+       bulbStateMutex.unlock();
+}
+
+
+double LifxLightBulb::getHue() {
+       double tmp = 0;
+       settingBulbColorMutex.lock();
+       tmp = ((double)currentHue / 65535.0) * 360.0;
+       settingBulbColorMutex.unlock();
+
+       return tmp;
+}
+
+
+double LifxLightBulb::getSaturation() {
+       double tmp = 0;
+       settingBulbColorMutex.lock();
+       tmp = ((double)currentSaturation / 65535.0) * 360.0;
+       settingBulbColorMutex.unlock();
+
+       return tmp;
+}
+
+
+double LifxLightBulb::getBrightness() {
+       double tmp = 0;
+       settingBulbColorMutex.lock();
+       tmp = ((double)currentBrightness / 65535.0) * 360.0;
+       settingBulbColorMutex.unlock();
+
+       return tmp;
+}
+
+
+int LifxLightBulb::getTemperature() {
+
+       int tmp = 0;
+       settingBulbTemperatureMutex.lock();
+       tmp = currentTemperature;
+       settingBulbTemperatureMutex.unlock();
+
+       return tmp;
+}
+
+
+double LifxLightBulb::getHueRangeLowerBound() {
+       if (!didGetBulbVersion) {
+               return -1;
+       }
+       return ((double)hueLowerBound / 65535.0) * 360.0;
+}
+
+
+double LifxLightBulb::getHueRangeUpperBound() {
+       if (!didGetBulbVersion) {
+               return -1;
+       }
+       return ((double)hueUpperBound / 65535.0) * 360.0;
+}
+
+
+double LifxLightBulb::getSaturationRangeLowerBound() {
+       if (!didGetBulbVersion) {
+               return -1;
+       }
+       return ((double)saturationLowerBound / 65535.0) * 100.0;
+}
+
+
+double LifxLightBulb::getSaturationRangeUpperBound() {
+       if (!didGetBulbVersion) {
+               return -1;
+       }
+       return ((double)saturationUpperBound / 65535.0) * 100.0;
+}
+
+
+double LifxLightBulb::getBrightnessRangeLowerBound() {
+       if (!didGetBulbVersion) {
+               return -1;
+       }
+       return ((double)brightnessLowerBound / 65535.0) * 100.0;
+}
+
+
+double LifxLightBulb::getBrightnessRangeUpperBound() {
+       if (!didGetBulbVersion) {
+               return -1;
+       }
+       return ((double)brightnessUpperBound / 65535.0) * 100.0;
+}
+
+
+int LifxLightBulb::getTemperatureRangeLowerBound() {
+       if (!didGetBulbVersion) {
+               return -1;
+       }
+       return temperatureLowerBound;
+}
+
+
+int LifxLightBulb::getTemperatureRangeUpperBound() {
+       if (!didGetBulbVersion) {
+               return -1;
+       }
+       return temperatureUpperBound;
+}
+
+
+void LifxLightBulb::setTemperature(int _temperature) {
+
+       settingBulbTemperatureMutex.lock();
+
+       BulbColor* newColor = new BulbColor(currentHue, currentSaturation, currentBrightness, _temperature);
+       sendSetLightColorPacket(newColor, 250);
+
+       currentTemperature = _temperature;
+       stateDidChange = true;
+
+       settingBulbTemperatureMutex.unlock();
+}
+
+
+void LifxLightBulb::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 LifxLightBulb::getState() {
+
+       bool tmp = false;
+
+       bulbStateMutex.lock();
+       tmp = bulbIsOn;
+       bulbStateMutex.unlock();
+
+       return tmp;
+}
+
+
+// PRIVATE METHODS
+// Communication helpers
+void LifxLightBulb::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 = new char[recHeader.getSize()];
+       for (int i = 36; i < recHeader.getSize(); i++) {
+               payloadBytes[i - 36] = packetData[i];
+       }
+
+       int type = recHeader.getType();
+       //cout << "Received: " << type << endl;
+
+       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:
+                       break;
+                       //cout << "unknown packet Type" << endl;
+       }
+       // Avoid memory leaks
+       delete payloadBytes;
+}
+
+
+void LifxLightBulb::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 LifxLightBulb::workerFunction(LifxLightBulb* llb) {
+
+       // Need timeout on receives since we are not sure if a packet will be available
+       // for processing so don't block waiting
+       llb->communicationSocket->setTimeOut(50000);    // In milliseconds
+       llb->turnOff();
+
+       int64_t lastSentGetBulbVersionRequest = 0;      // time last request sent
+       char dat[1024];
+
+       while (true) {
+               // Check if we got the bulb version yet
+               // could have requested it but message could have gotten lost (UDP)
+               if (!llb->didGetBulbVersion) {
+                       int64_t currentTime = (int64_t) time(NULL);
+                       if ((currentTime - lastSentGetBulbVersionRequest) > llb->GET_BULB_VERSION_RESEND_WAIT_SECONDS) {
+                               // Get the bulb version so we know what type of bulb this is.
+                               //cout << "Sending version packet! " << endl;
+                               llb->sendGetVersionPacket();
+                               lastSentGetBulbVersionRequest = currentTime;
+                       }
+               }
+
+               // Communication resource is busy so try again later
+               if (llb->sendSocketFlag) {
+                       continue;
+               }
+
+               llb->socketMutex.lock();
+               int ret = llb->communicationSocket->receiveData(dat, 1024);
+               // Never forget to release!
+               llb->socketMutex.unlock();
+
+               // A packed arrived
+               if (ret != -1) {
+                       llb->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 (llb->stateDidChange) {
+                       llb->sendGetLightStatePacket();
+               }
+
+               // Wait a bit as to not tie up system resources
+               this_thread::sleep_for (chrono::milliseconds(100));
+               //cout << endl << "Sleep and wake up!" << endl;
+       }
+}
+
+
+//  Sending
+//  Device Messages
+void LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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 LifxLightBulb::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* LifxLightBulb::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* LifxLightBulb::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* LifxLightBulb::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* LifxLightBulb::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* LifxLightBulb::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 LifxLightBulb::parseStatePowerMessage(char* payloadData) {
+       int level = ((payloadData[1] & 0xFF) << 8);
+       level |= (payloadData[0] & 0xFF);
+       return level;
+}
+
+
+DeviceStateVersion* LifxLightBulb::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* LifxLightBulb::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* LifxLightBulb::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* LifxLightBulb::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* LifxLightBulb::parseLightStateMessage(char* payloadData) {
+
+       char colorData[8];
+       for (int i = 0; i < 8; i++) {
+               colorData[i] = payloadData[i];
+       }
+       //BulbColor color(colorData);
+       BulbColor* color = new BulbColor(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 LifxLightBulb::parseLightStatePowerMessage(char* payloadData) {
+       int level = ((payloadData[1] & 0xFF) << 8);
+       level |= (payloadData[0] & 0xFF);
+       return level;
+}
+
+
+// Private Handlers
+void LifxLightBulb::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);
+       didGetBulbVersion = true;
+       // Avoid memory leak - delete this object
+       delete deviceState;
+}
+
+
+void LifxLightBulb::handleLightStateMessageReceived(char* payloadData) {
+       LightState* lightState = parseLightStateMessage(payloadData);
+
+       BulbColor* color = lightState->getColor();
+       int power = lightState->getPower();
+
+       //cout << "color->getHue(): " << color->getHue() << " - currentHue: " << currentHue << endl;
+       //cout << "color->getSaturation(): " << color->getSaturation() << " - currentSaturation: " << currentSaturation << endl;
+       //cout << "color->getBrightness(): " << color->getBrightness() << " - currentBrightness: " << currentBrightness << endl;
+       //cout << "color->getKelvin(): " << color->getKelvin() << " - currentTemperature: " << currentTemperature << endl;
+
+       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);
+               //cout << "Failed Check 1" << endl;
+       }
+
+       bulbStateMutex.lock();
+       bool bulbIsOnTmp = bulbIsOn;
+       bulbStateMutex.unlock();
+
+       if ((!bulbIsOnTmp) && (power != 0)) {
+               turnOff();
+               //cout << "Failed Check 2:  " << endl;
+
+       }
+
+       if (bulbIsOnTmp && (power < 65530)) {
+               turnOn();
+               //cout << "Failed Check 3:  " << endl;
+
+       }
+       // Avoid memory leak - delete object
+       delete lightState;
+       delete color;
+}
+
diff --git a/version2/src/RPi/LifxLightBulb.h b/version2/src/RPi/LifxLightBulb.h
new file mode 100644 (file)
index 0000000..216a47a
--- /dev/null
@@ -0,0 +1,173 @@
+#ifndef _LIFXLIGHTBULB_H__
+#define _LIFXLIGHTBULB_H__
+#include <iostream>
+#include <fstream>
+#include <atomic>
+#include <mutex>
+#include <thread>
+#include <chrono>
+
+#include <string.h>
+#include <time.h>
+
+#include "LightBulb.h"
+//#include "Socket.h"
+#include "IoTSet.h"
+#include "IoTUDP.h"
+#include "IoTDeviceAddress.h"
+
+// Helper classes for LifxLightBulb
+#include "LifxHeader.h"
+#include "BulbColor.h"
+#include "DeviceStateGroup.h"
+#include "DeviceStateHostFirmware.h"
+#include "DeviceStateHostInfo.h"
+#include "DeviceStateInfo.h"
+#include "DeviceStateLocation.h"
+#include "DeviceStateService.h"
+#include "DeviceStateVersion.h"
+#include "DeviceStateWifiFirmware.h"
+#include "DeviceStateWifiInfo.h"
+#include "LightState.h"
+
+
+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;
+
+               // Current Bulb Values
+               int currentHue = 0;
+               int currentSaturation = 0;
+               int currentBrightness = 65535;
+               int currentTemperature = 9000;
+               bool bulbIsOn = false;
+
+               //std::atomic
+               //atomic<bool> didAlreadyInit;
+               bool didAlreadyInit;
+               //atomic<bool> didGetBulbVersion;
+               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<void*>* lb_addresses;    // IoTSet<IoTDeviceAddress*>* lb_addresses
+
+               // Logging
+               ofstream log;
+       public:
+
+               // Constructor
+               LifxLightBulb();
+               LifxLightBulb(uint8_t* ipAddress, string macAddress, int srcPort);
+               //LifxLightBulb(IoTSet<IoTDeviceAddress*>* _devAddress, string macAddress);
+               LifxLightBulb(IoTSet<void*>* _devAddress, string macAddress);
+               ~LifxLightBulb();
+               // Initialize the lightbulb
+               void init();
+               void turnOff();
+               void turnOn();
+               double getHue();
+               double getSaturation();
+               double getBrightness();
+               int getTemperature();
+               double getHueRangeLowerBound();
+               double getHueRangeUpperBound();
+               double getSaturationRangeLowerBound();
+               double getSaturationRangeUpperBound();
+               double getBrightnessRangeLowerBound();
+               double getBrightnessRangeUpperBound();
+               int getTemperatureRangeLowerBound();
+               int getTemperatureRangeUpperBound();
+               void setTemperature(int _temperature);
+               void setColor(double _hue, double _saturation, double _brightness);
+               bool getState();
+
+       private:
+               // Private functions
+               // Communication helpers
+               void receivedPacket(char* packetData);
+               void sendPacket(char* packetData, int len);
+               // Worker function which runs the while loop for receiving data from the bulb.
+               // Is blocking.
+               void workerFunction(LifxLightBulb* llb);
+               //  Sending
+               //  Device Messages
+               void sendGetServicePacket();
+               void sendGetHostInfoPacket();
+               void sendGetHostFirmwarePacket();
+               void sendGetWifiInfoPacket();
+               void sendGetWifiFirmwarePacket();
+               void sendGetPowerPacket();
+               void sendSetPowerPacket(int level);
+               void sendGetLabelPacket();
+               void sendSetLabelPacket(string label);
+               void sendGetVersionPacket();
+               void sendGetInfoPacket();
+               void sendGetLocationPacket();
+               void sendGetGroupPacket();
+               //  Sending
+               //  Light Messages
+               void sendGetLightStatePacket();
+               void sendSetLightColorPacket(BulbColor* bulbColor, long duration);
+               void sendGetLightPowerPacket();
+               void sendSetLightPowerPacket(int level, long duration);
+               void sendEchoRequestPacket(char data[64]);
+               // Receiving
+               // Device Messages
+               DeviceStateService* parseDeviceStateServiceMessage(char* payloadData);
+               DeviceStateHostInfo* parseDeviceStateHostInfoMessage(char* payloadData);
+               DeviceStateHostFirmware* parseDeviceStateHostFirmwareMessage(char* payloadData);
+               DeviceStateWifiInfo* parseDeviceStateWifiInfoMessage(char* payloadData);
+               DeviceStateWifiFirmware* parseDeviceStateWifiFirmwareMessage(char* payloadData);
+               int parseStatePowerMessage(char* payloadData);
+               DeviceStateVersion* parseDeviceStateVersionMessage(char* payloadData);
+               DeviceStateInfo* parseDeviceStateInfoMessage(char* payloadData);
+               DeviceStateLocation* parseDeviceStateLocationMessage(char* payloadData);
+               DeviceStateGroup* parseDeviceStateGroupMessage(char* payloadData);
+               // Receiving
+               // Light Messages
+               LightState* parseLightStateMessage(char* payloadData);
+               int parseLightStatePowerMessage(char* payloadData);
+               // Private Handlers
+               void handleStateVersionMessageReceived(char* payloadData);
+               void handleLightStateMessageReceived(char* payloadData);
+};
+
+#endif
diff --git a/version2/src/RPi/LightBulb.h b/version2/src/RPi/LightBulb.h
new file mode 100644 (file)
index 0000000..90f9df8
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _LIGHTBULB_H__
+#define _LIGHTBULB_H__
+#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
diff --git a/version2/src/RPi/LightState.h b/version2/src/RPi/LightState.h
new file mode 100644 (file)
index 0000000..ba350e3
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _LIGHTSTATE_H__
+#define _LIGHTSTATE_H__
+#include <iostream>
+
+#include "BulbColor.h"
+
+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
diff --git a/version2/src/RPi/LightsController.ino b/version2/src/RPi/LightsController.ino
new file mode 100644 (file)
index 0000000..9ffe162
--- /dev/null
@@ -0,0 +1,72 @@
+// ------------------------------------------------
+// Controlling LifxLightBulb through Particle Cloud
+// @author Rahmadi Trimananda - UC Irvine
+// ------------------------------------------------
+
+#include "LifxLightBulb.h"
+
+LifxLightBulb *llb1;
+LifxLightBulb *llb2;
+
+void setup()
+{
+       // Bulb 1
+       string macAddress1 = "D073D5128E300000";
+       uint8_t devIPAddress1[] = { 192, 168, 1, 126 };
+       llb1 = new LifxLightBulb(devIPAddress1, macAddress1, 12345);
+       llb1->init();
+       
+       // Bulb 2
+       string macAddress2 = "D073D50241DA0000";
+       uint8_t devIPAddress2[] = { 192, 168, 1, 232 };
+       llb2 = new LifxLightBulb(devIPAddress2, macAddress2, 12346);
+       llb2->init();
+       
+    Particle.function("lifx1",lifx1Toggle);
+    Particle.function("lifx2",lifx2Toggle);
+}
+
+
+void loop()
+{
+    // Nothing to do here
+       for(int i=0; i < 3; i++) {
+               llb1->turnOff();
+               delay(1000);
+               llb1->turnOn();
+               delay(1000);
+       }
+}
+
+
+// Toggling Lifx light bulb 1
+int lifx1Toggle(String command) {
+
+    if (command=="on") {
+        llb1->turnOn();
+        return 1;
+    }
+    else if (command=="off") {
+        llb1->turnOff();
+        return 0;
+    }
+    else {
+        return -1;
+    }
+}
+
+// Toggling Lifx light bulb 2
+int lifx2Toggle(String command) {
+
+    if (command=="on") {
+        llb2->turnOn();
+        return 1;
+    }
+    else if (command=="off") {
+        llb2->turnOff();
+        return 0;
+    }
+    else {
+        return -1;
+    }
+}
diff --git a/version2/src/RPi/Makefile b/version2/src/RPi/Makefile
new file mode 100644 (file)
index 0000000..276d090
--- /dev/null
@@ -0,0 +1,38 @@
+include common.mk
+
+all: compile
+
+# To run Particle, we need to install Particle CLI
+# Please see: 
+#      https://docs.particle.io/guide/getting-started/connect/photon/#install-the-particle-cli
+monitor:
+       sudo chmod 666 /dev/ttyACM0
+       particle serial monitor
+
+compile-c:
+       #g++ -c LifxLightBulb.cpp -o ./LifxLightBulb.o -Wall -O3 -g -I. -Wno-unused-variable -std=c++11 -pthread -pg
+       g++ ./LifxLightBulb.cpp ./socket/Socket.cpp -o ./LifxLightBulb.o -Wall -Wno-unused-variable --std=c++11 -pthread -pg -I. -I./socket
+
+compile:
+       rm -f *.bin
+       particle compile raspberry-pi
+       
+flash:
+       particle flash Pi-3 raspberry-pi*.bin
+
+PHONY += clean
+clean:
+       rm -f *.bin
+
+PHONY += mrclean
+mrclean: clean
+       rm -rf ../docs
+
+tabbing:
+       uncrustify -c C.cfg --no-backup *.cpp
+       uncrustify -c C.cfg --no-backup *.h
+
+wc:
+       wc *.cpp *.h
+
+.PHONY: $(PHONY)
diff --git a/version2/src/RPi/README.txt b/version2/src/RPi/README.txt
new file mode 100644 (file)
index 0000000..b1ac1ff
--- /dev/null
@@ -0,0 +1,4 @@
+
+This is a RaspberryPi C++ implementation of Lifx light bulb controller.
+
+Created as a part of our testbed that will include smart home devices that will use Particle cloud.
diff --git a/version2/src/RPi/common.mk b/version2/src/RPi/common.mk
new file mode 100644 (file)
index 0000000..479a31c
--- /dev/null
@@ -0,0 +1,16 @@
+# A few common Makefile items
+
+CC := gcc
+CXX := g++
+
+UNAME := $(shell uname)
+
+LIB_NAME := iotcloud
+LIB_SO := lib_$(LIB_NAME).so
+
+CPPFLAGS += -Wall -g -O0
+
+# Mac OSX options
+ifeq ($(UNAME), Darwin)
+CPPFLAGS += -D_XOPEN_SOURCE -DMAC
+endif
diff --git a/version2/src/RPi/gmon.out b/version2/src/RPi/gmon.out
new file mode 100644 (file)
index 0000000..69b5434
Binary files /dev/null and b/version2/src/RPi/gmon.out differ