Fixing 2 issues in LifxLightBulb driver: 1) Detached thread handling (need to pass...
authorrtrimana <rtrimana@uci.edu>
Wed, 11 Jan 2017 23:13:22 +0000 (15:13 -0800)
committerrtrimana <rtrimana@uci.edu>
Wed, 11 Jan 2017 23:13:22 +0000 (15:13 -0800)
benchmarks/drivers/Cpp/LifxLightBulb/LifxLightBulb.cpp
benchmarks/drivers/Cpp/LifxLightBulb/LifxLightBulb.hpp
iotjava/iotruntime/cpp/IoTUDP.hpp
iotjava/iotruntime/cpp/socket/Socket.cpp
iotjava/iotruntime/cpp/socket/Socket.hpp
iotjava/iotruntime/slave/IoTSlave.java

index 21b209c4f3955817724eca5bba5f6a35e1148dce..5a53d5e7b5f09d09de03dc6a3a61cda732d3e418 100644 (file)
@@ -1,24 +1,94 @@
 #include <iostream>
 #include <string>
+#include <thread>
+
+#include <pthread.h>
+
 #include "LifxLightBulb.hpp"
 #include "IoTSet.hpp"
 #include "IoTDeviceAddress.hpp"
 
 using namespace std;
 
+void run(LifxLightBulb *llb) {
+
+       llb->init();
+}
+
+
+void *prun(void *llb) {
+
+       ((LifxLightBulb*)llb)->init();
+}
+
+
+void onOff(LifxLightBulb *llb) {
+
+       for (int i = 0; i < 5; i++) {
+               llb->turnOff();
+               cout << "Turning off!" << endl;
+               this_thread::sleep_for (chrono::milliseconds(1000));
+               llb->turnOn();
+               cout << "Turning on!" << endl;
+               this_thread::sleep_for (chrono::milliseconds(1000));
+       }
+}
+
+
+void adjustTemp(LifxLightBulb *llb) {
+
+       for (int i = 2500; i < 9000; i += 100) {
+               cout << "Adjusting Temp: " << i << endl;
+               llb->setTemperature(i);
+               this_thread::sleep_for (chrono::milliseconds(100));
+       }
+       cout << "Adjusted temperature to 9000!" << endl;
+       for (int i = 9000; i > 2500; i -= 100) {
+               cout << "Adjusting Temp: " << i << endl;
+               llb->setTemperature(i);
+               this_thread::sleep_for (chrono::milliseconds(100));
+       }
+       cout << "Adjusted temperature to 2500!" << endl;
+}
+
+
+void adjustBright(LifxLightBulb *llb) {
+       for (int i = 100; i > 0; i -= 10) {
+               cout << "Adjusting Brightness: " << i << endl;
+               llb->setColor(llb->getHue(), llb->getSaturation(), i);
+               this_thread::sleep_for (chrono::milliseconds(100));
+       }
+       cout << "Adjusted brightness to 0!" << endl;
+       for (int i = 0; i < 100; i += 10) {
+               cout << "Adjusting Brightness: " << i << endl;
+               llb->setColor(llb->getHue(), llb->getSaturation(), i);
+               this_thread::sleep_for (chrono::milliseconds(100));
+       }
+       cout << "Adjusting brightness to 100!" << endl;
+}
+
+
 int main(int argc, char *argv[])
 {
        string macAddress = "D073D5128E300000";
+       //string macAddress = "D073D50241DA0000";
        string devIPAddress = "192.168.2.126";
-       IoTDeviceAddress devAddress(devIPAddress, 12345, 56700, false, false);
-       unordered_set<IoTDeviceAddress> myset = { devAddress };
+       //string devIPAddress = "192.168.2.232";
+       //IoTDeviceAddress devAddress(devIPAddress, 12345, 56700, false, false);
+       IoTDeviceAddress* devAddress = new IoTDeviceAddress(devIPAddress, 12345, 56700, false, false);
+       unordered_set<IoTDeviceAddress*> myset = { devAddress };
 
-       IoTSet<IoTDeviceAddress> setDevAddress(myset);
+       IoTSet<IoTDeviceAddress*> setDevAddress(myset);
        LifxLightBulb *llb = new LifxLightBulb(setDevAddress, macAddress);
        llb->init();
-
+       llb->turnOn();
        cout << "Generated LifxLightBulb object!" << endl;
+       onOff(llb);
+       adjustTemp(llb);
+       adjustBright(llb);
+       llb->turnOff();
 
+       delete devAddress;
        delete llb;
 
        return 0;
index 489fd54033b46894ec281af304b1b0d5daa9ae77..376e26d028a9afb846485ad3a3175bca6acf608f 100644 (file)
@@ -5,9 +5,11 @@
 #include <mutex>
 #include <thread>
 #include <chrono>
+#include <future>
 
 #include <string.h>
 #include <time.h>
+#include <pthread.h>
 
 #include "LightBulb.hpp"
 #include "Socket.hpp"
@@ -53,7 +55,6 @@ class LifxLightBulb //: public LightBulb
                //TODO:
                //static Semaphore socketMutex = new Semaphore(1);
                bool sendSocketFlag = false;
-               int64_t lastSentGetBulbVersionRequest = 0;      // time last request sent
 
                // Current Bulb Values
                int currentHue = 0;
@@ -87,7 +88,7 @@ class LifxLightBulb //: public LightBulb
                bool stateDidChange = false;
 
                // Device address
-               IoTSet<IoTDeviceAddress> lb_addresses;
+               IoTSet<IoTDeviceAddress*> lb_addresses;
 
        public:
 
@@ -120,7 +121,7 @@ class LifxLightBulb //: public LightBulb
                }
 
 
-               LifxLightBulb(IoTSet<IoTDeviceAddress> _devAddress, string macAddress) {
+               LifxLightBulb(IoTSet<IoTDeviceAddress*> _devAddress, string macAddress) {
 
                        // Initialize macAddress
                        char tmpMacAddress[16];
@@ -159,35 +160,47 @@ class LifxLightBulb //: public LightBulb
                        if (didAlreadyInit.exchange(true))
                                return;
 
-                       unordered_set<IoTDeviceAddress>::const_iterator itr = lb_addresses.begin();
-                       IoTDeviceAddress deviceAddress = *itr;
-                       cout << "Address: " << deviceAddress.getAddress() << endl;
+                       unordered_set<IoTDeviceAddress*>::const_iterator itr = lb_addresses.begin();
+                       IoTDeviceAddress* deviceAddress = *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.
-                       thread th1 (&LifxLightBulb::workerFunction, this);
-                       th1.join();
+                       //              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 turnOff() {
 
-                       lock_guard<mutex> guard(bulbStateMutex);
+                       //lock_guard<mutex> guard(bulbStateMutex);
+                       bulbStateMutex.lock();
                        bulbIsOn = false;
                        sendSetLightPowerPacket(0, 0);
                        stateDidChange = true;
-                       cout << "Turning off lightbulb!" << endl;
+                       bulbStateMutex.unlock();
                }
 
 
                void turnOn() {
 
-                       lock_guard<mutex> guard(bulbStateMutex);
+                       //lock_guard<mutex> guard(bulbStateMutex);
+                       bulbStateMutex.lock();
                        bulbIsOn = true;
                        sendSetLightPowerPacket(65535, 0);
                        stateDidChange = true;
+                       bulbStateMutex.unlock();
                }
 
 
@@ -361,13 +374,14 @@ class LifxLightBulb //: public LightBulb
                        recHeader.setFromBytes(headerBytes);
 
                        // load the payload bytes (strip away the header)
-                       char payloadBytes[recHeader.getSize()];
+                       //char payloadBytes[recHeader.getSize()];
+                       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;
+                       cout << "Received: " << type << endl;
 
                        DeviceStateService* dat = NULL;
                        switch (type) {
@@ -396,7 +410,8 @@ class LifxLightBulb //: public LightBulb
                                default:
                                        cout << "unknown packet Type" << endl;
                        }
-       
+                       // Avoid memory leaks
+                       delete payloadBytes;
                }
 
 
@@ -411,54 +426,54 @@ class LifxLightBulb //: public LightBulb
 
                // Worker function which runs the while loop for receiving data from the bulb.
                // Is blocking.
-               void workerFunction() {
-                       LifxHeader h;
+               void 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
-                       // TODO: Check if we can do this here!
-                       //communicationSocket.setSoTimeout(50);
+                       llb->communicationSocket->setTimeOut(50000);    // In milliseconds
 
-                       turnOff();
+                       llb->turnOff();
 
-                       while (true) {
+                       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 (!didGetBulbVersion) {
+                               if (!llb->didGetBulbVersion) {
                                        int64_t currentTime = (int64_t) time(NULL);
-                                       if ((currentTime - lastSentGetBulbVersionRequest) > GET_BULB_VERSION_RESEND_WAIT_SECONDS) {
+                                       if ((currentTime - lastSentGetBulbVersionRequest) > llb->GET_BULB_VERSION_RESEND_WAIT_SECONDS) {
                                                // Get the bulb version so we know what type of bulb this is.
-                                               sendGetVersionPacket();
+                                               cout << "Sending version packet! " << endl;
+                                               llb->sendGetVersionPacket();
                                                lastSentGetBulbVersionRequest = currentTime;
                                        }
                                }
 
                                // Communication resource is busy so try again later
-                               if (sendSocketFlag) {
+                               if (llb->sendSocketFlag) {
                                        continue;
                                }
 
-                               socketMutex.lock();
-
-                               char dat[1024];
-                               int ret = communicationSocket->receiveData(dat, 1024);
-
+                               llb->socketMutex.lock();
+                               int ret = llb->communicationSocket->receiveData(dat, 1024);
                                // Never forget to release!
-                               socketMutex.unlock();
+                               llb->socketMutex.unlock();
 
                                // A packed arrived
                                if (ret != -1) {
-                                       receivedPacket(dat);
+                                       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 (stateDidChange) {
-                                       sendGetLightStatePacket();
+                               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;
                        }
                }
 
@@ -1067,7 +1082,8 @@ class LifxLightBulb //: public LightBulb
                        for (int i = 0; i < 8; i++) {
                                colorData[i] = payloadData[i];
                        }
-                       BulbColor color(colorData);
+                       //BulbColor color(colorData);
+                       BulbColor* color = new BulbColor(colorData);
 
                        int power = ((payloadData[11] & 0xFF) << 8);
                        power |= (payloadData[10] & 0xFF);
@@ -1079,7 +1095,7 @@ class LifxLightBulb //: public LightBulb
                                labelArray[i] = payloadData[12 + i];
                        }
 
-                       return new LightState(&color, power, label);
+                       return new LightState(color, power, label);
                }
 
 
@@ -1146,6 +1162,11 @@ class LifxLightBulb //: public LightBulb
                        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);
@@ -1159,7 +1180,7 @@ class LifxLightBulb //: public LightBulb
                        if (bulbWrongColor) {
                                BulbColor* newColor = new BulbColor(currentHue, currentSaturation, currentBrightness, currentTemperature);
                                sendSetLightColorPacket(newColor, 250);
-                               // System.out.println("Failed Check 1");
+                               //cout << "Failed Check 1" << endl;
                        }
 
                        bulbStateMutex.lock();
@@ -1168,13 +1189,13 @@ class LifxLightBulb //: public LightBulb
 
                        if ((!bulbIsOnTmp) && (power != 0)) {
                                turnOff();
-                               // System.out.println("Failed Check 2:  " + Integer.toString(power));
+                               //cout << "Failed Check 2:  " << endl;
 
                        }
 
                        if (bulbIsOnTmp && (power < 65530)) {
                                turnOn();
-                               // System.out.println("Failed Check 3:  " + Integer.toString(power));
+                               //cout << "Failed Check 3:  " << endl;
 
                        }
                        // Avoid memory leak - delete object
index 1c46ffa599557a5e090fd6562424517b80fb3a23..d712d4b3e6e5494b67d846eaf3fbec444bde128a 100644 (file)
@@ -17,20 +17,22 @@ class IoTUDP
 {
        // IoTUDP class properties
        private:
+               UDPSocket *socket;
                string strHostAddress;
                int iSrcPort;
                int iDstPort;
-               UDPSocket *socket;
                bool didClose;
+               int timeOut;
 
        public:
 
                // Constructor
-               IoTUDP(IoTDeviceAddress iotDevAdd) {
+               IoTUDP(IoTDeviceAddress* iotDevAdd) {
 
-                       strHostAddress = iotDevAdd.getAddress();
-                       iSrcPort = iotDevAdd.getSourcePortNumber();
-                       iDstPort = iotDevAdd.getDestinationPortNumber();
+                       strHostAddress = iotDevAdd->getAddress();
+                       iSrcPort = iotDevAdd->getSourcePortNumber();
+                       iDstPort = iotDevAdd->getDestinationPortNumber();
+                       timeOut = 0;
 
                        socket = new UDPSocket(iSrcPort);
                        if (socket == NULL) {
@@ -50,19 +52,39 @@ class IoTUDP
                }
 
 
+               string getHostAddress() {
+                       return strHostAddress;
+               }
+
+
+               int getSourcePort() {
+                       return iSrcPort;
+               }
+
+
+               int getDestinationPort() {
+                       return iDstPort;
+               }
+
+
+               void setTimeOut(int interval) {
+
+                       timeOut = interval;
+               }
+
+
                // Send data packet
                void sendData(const void* buffer, int bufferLen) {
-
-                       unsigned short destinationPort = (unsigned short) iDstPort;             
+                       unsigned short destinationPort = (unsigned short) iDstPort;
                        socket->sendTo(buffer, bufferLen, strHostAddress, destinationPort);
                }
 
 
                // Receive data packet
                int receiveData(void* buffer, int iMaxDataLength) {
-
                        unsigned short destinationPort = (unsigned short) iDstPort;
-                       return socket->recvFrom(buffer, iMaxDataLength, strHostAddress, destinationPort);
+                       //return socket->recvFrom(buffer, iMaxDataLength, strHostAddress, destinationPort);
+                       return socket->recvFrom(buffer, iMaxDataLength, strHostAddress, destinationPort, timeOut);
                }
 };
 #endif 
index ceac82ba57198698af312ac5b45db1fd25e4221a..667411a207d8e8c5c444b02b87baca56a529d19f 100644 (file)
@@ -27,6 +27,7 @@
   typedef char raw_type;       // Type used for raw data on this platform
 #else
   #include <sys/types.h>       // For data types
+  #include <sys/select.h>      // For select() - non-blocking socket
   #include <sys/socket.h>      // For socket(), connect(), send(), and recv()
   #include <netdb.h>           // For gethostbyname()
   #include <arpa/inet.h>       // For inet_addr()
@@ -37,6 +38,7 @@
 
 #include <errno.h>             // For errno
 #include <string.h>            // For memset
+#include <fcntl.h>             // For fcntl
 
 using namespace std;
 
@@ -351,6 +353,38 @@ int UDPSocket::recvFrom(void *buffer, int bufferLen, string &sourceAddress,
   return rtn;
 }
 
+int UDPSocket::recvFrom(void *buffer, int bufferLen, string &sourceAddress,
+    unsigned short &sourcePort, int timeOut) throw(SocketException) {
+
+  if(!(fcntl(sockDesc, F_GETFL) & O_NONBLOCK)) {
+  // If not non-blocking then put it into non-blocking
+     if(fcntl(sockDesc, F_SETFL, fcntl(sockDesc, F_GETFL) | O_NONBLOCK) < 0) {
+        throw SocketException("Set non-blocking failed (recvfrom())", true);
+     }
+  }
+  fd_set readFds;  // FD
+  FD_ZERO(&readFds);
+  FD_SET(sockDesc, &readFds);
+  struct timeval to;   // timeout
+  to.tv_sec = 0;
+  to.tv_usec = timeOut;
+  sockaddr_in clntAddr;
+  socklen_t addrLen = sizeof(clntAddr);
+  
+  int rv = select(sockDesc+1 ,&readFds, NULL, NULL, &to);
+  int rtn = -1;        // Assuming receive failure
+  if (rv == 1) {
+        if ((rtn = recvfrom(sockDesc, (raw_type *) buffer, bufferLen, 0, 
+                         (sockaddr *) &clntAddr, (socklen_t *) &addrLen)) < 0) {
+        throw SocketException("Receive failed (recvfrom())", true);
+        }
+        sourceAddress = inet_ntoa(clntAddr.sin_addr);
+        sourcePort = ntohs(clntAddr.sin_port);
+  }
+
+  return rtn;
+}
+
 void UDPSocket::setMulticastTTL(unsigned char multicastTTL) throw(SocketException) {
   if (setsockopt(sockDesc, IPPROTO_IP, IP_MULTICAST_TTL, 
                  (raw_type *) &multicastTTL, sizeof(multicastTTL)) < 0) {
@@ -381,3 +415,14 @@ void UDPSocket::leaveGroup(const string &multicastGroup) throw(SocketException)
     throw SocketException("Multicast group leave failed (setsockopt())", true);
   }
 }
+
+void UDPSocket::setTimeOut(int interval) throw(SocketException) {
+
+  struct timeval timeout;
+  timeout.tv_sec = 0;
+  timeout.tv_usec = interval;
+  if (setsockopt(sockDesc, SOL_SOCKET, SO_RCVTIMEO, &timeout, 
+                 sizeof(timeout)) < 0) {
+    throw SocketException("Multicast group join failed (setsockopt())", true);
+  }
+}
index 9da627a9ce0b5ac73afc24dd89cfe9d9c355cd58..d01c9bb226a50a9d7ab4d46a040f9c0de34f392c 100644 (file)
@@ -86,7 +86,7 @@ public:
    */
   void setLocalPort(unsigned short localPort) throw(SocketException);
 
-  /**
+  /**  ADDED BY: Rahmadi Trimananda (rtrimana@uci.edu)
    *   Set the local port to the specified port and the local address
    *   to the specified address.  If you omit the port, a random port 
    *   will be selected.
@@ -301,7 +301,7 @@ public:
 
   /**
    *   Read read up to bufferLen bytes data from this socket.  The given buffer
-   *   is where the data will be placed
+   *   is where the data will be placed (this is a non-blocking version)
    *   @param buffer buffer to receive data
    *   @param bufferLen maximum number of bytes to receive
    *   @param sourceAddress address of datagram source
@@ -312,6 +312,20 @@ public:
   int recvFrom(void *buffer, int bufferLen, string &sourceAddress, 
                unsigned short &sourcePort) throw(SocketException);
 
+  /**
+   *   Read read up to bufferLen bytes data from this socket.  The given buffer
+   *   is where the data will be placed
+   *   @param buffer buffer to receive data
+   *   @param bufferLen maximum number of bytes to receive
+   *   @param sourceAddress address of datagram source
+   *   @param sourcePort port of data source
+   *   @param timeout interval
+   *   @return number of bytes received and -1 for error
+   *   @exception SocketException thrown if unable to receive datagram
+   */
+  int recvFrom(void *buffer, int bufferLen, string &sourceAddress, 
+               unsigned short &sourcePort, int timeout) throw(SocketException);
+
   /**
    *   Set the multicast TTL
    *   @param multicastTTL multicast TTL
@@ -333,6 +347,13 @@ public:
    */
   void leaveGroup(const string &multicastGroup) throw(SocketException);
 
+  /**  ADDED BY: Rahmadi Trimananda (rtrimana@uci.edu)
+   *   Set timeout for socket
+   *   @param timeout interval (in milliseconds)
+   *   @exception SocketException thrown if unable to set timeout
+   */
+  void setTimeOut(int interval) throw(SocketException);
+
 private:
   void setBroadcast();
 };
index 0adbefea2ca8e576f13aeddca970508278b828ca..dec974f433c8d27d47708339993b0ea57f5226c5 100644 (file)
@@ -694,11 +694,7 @@ public class IoTSlave {
 
                // TODO: DEBUG
                System.out.println("\n\nDEBUG: GET ZIGBEE DEVICE IOT SET OBJECT!!!");
-               System.out.println("DEBUG: sMessage host address: " + sMessage.getHostAddress());
-               System.out.println("DEBUG: sMessage source port: " + sMessage.getSourceDeviceDriverPort());
-               System.out.println("DEBUG: sMessage destination port: " + sMessage.getDestinationDeviceDriverPort());
-               System.out.println("DEBUG: sMessage source wild card: " + sMessage.isSourcePortWildCard());
-               System.out.println("DEBUG: sMessage desination wild card: " + sMessage.isDestinationPortWildCard() + "\n\n");
+               System.out.println("DEBUG: sMessage host address: " + sMessage.getHostAddress() + "\n\n");
 
                // Get IoTSet objects for IP address set on device driver/controller
                IoTZigbeeAddress objZBDevAddress = new IoTZigbeeAddress(sMessage.getHostAddress());
@@ -725,7 +721,7 @@ public class IoTSlave {
 
                // TODO: DEBUG
                System.out.println("\n\nDEBUG: GET ADD IOT SET OBJECT!!!");
-               System.out.println("DEBUG: sMessage host address: " + sMessage.getHostAddress() +);
+               System.out.println("DEBUG: sMessage host address: " + sMessage.getHostAddress() + "\n\n");
 
                // Get IoTSet objects for IP address set on device driver/controller
                IoTAddress objAddress = new IoTAddress(sMessage.getHostAddress());
@@ -746,7 +742,7 @@ public class IoTSlave {
        private void invokeInitMethod() throws IOException {
 
                // TODO: DEBUG
-               System.out.println("\n\nDEBUG: INVOKE INIT METHOD!!!");
+               System.out.println("\n\nDEBUG: INVOKE INIT METHOD!!!\n\n");
 
                new Thread() {
                        public void run() {