Had to fork with a different name, because of some incompatibility issues.

Dependencies:   MQTT

Revision:
5:ea9f483e0294
Parent:
3:3d91bf839b49
Child:
7:b14763b63562
--- a/DeviceClient.cpp	Mon Mar 20 10:07:49 2017 +0000
+++ b/DeviceClient.cpp	Tue May 30 06:24:06 2017 +0000
@@ -13,6 +13,8 @@
  * Contributors:
  *    Sathisumar Palaniappan - initial implementation
  *    Sathisumar Palaniappan - added reconnect logic and isConnected() method
+ *    Lokesh K Haralakatta - Port to mbed OS 5 support
+ *    Lokesh K Haralakatta - Added SSL/TLS Support
  *******************************************************************************/
 #include "MQTTClient.h"
 #include "DeviceClient.h"
@@ -42,109 +44,126 @@
  * This class allows device to publish events and receive commands to/from IBM IoT Foundation wtih simple function calls.
  */
 DeviceClient::DeviceClient():org(NULL),deviceType(NULL),deviceId(NULL),
-              authMethod(NULL),authToken(NULL),mqttClient(ipstack),connected(false)
+        authMethod(NULL),authToken(NULL),mqttNetwork(NULL),mqttClient(NULL),connected(false),port(0)
 {
-    LOG("Constructor#1 called::\n");
+    LOG("Constructor#1 called::\r\n");
 }
 
-DeviceClient::DeviceClient(char *orgId, char *typeId, char *id)
-             :org(orgId),deviceType(typeId),deviceId(id),authMethod(NULL),
-             authToken(NULL),mqttClient(ipstack),connected(false)
+DeviceClient::DeviceClient(char *orgId, char *typeId, char *id, int port):org(orgId),deviceType(typeId),
+        deviceId(id),authMethod(NULL),authToken(NULL),connected(false), port(port)
 {
-    LOG("Constructor#2 called:: org=%s, type=%s, id=%s", (org==NULL)?"NULL":org,
+    LOG("Constructor#2 called:: org=%s, type=%s, id=%s\r\n", (org==NULL)?"NULL":org,
                     (deviceType==NULL)?"NULL":deviceType, (deviceId==NULL)?"NULL":deviceId);
- 
+
     if(strcmp(this->org, QUICKSTART) != 0) {
-        WARN("Registered flow must provide valid token");
+        WARN("Registered flow must provide valid token\r\n");
     }
+
+    mqttNetwork = new MQTTNetwork();
+    mqttClient = new MQTT::Client<MQTTNetwork, Countdown>(*mqttNetwork);
+
 }
 
-DeviceClient::DeviceClient(char *orgId, char *typeId, 
-            char *id, char *method, char *token)
-            :org(orgId),deviceType(typeId),deviceId(id),authMethod(method),
-            authToken(token),mqttClient(ipstack),connected(false)
+DeviceClient::DeviceClient(char *orgId, char *typeId,char *id, char *method, char *token, int port):org(orgId),
+        deviceType(typeId),deviceId(id),authMethod(method),authToken(token),connected(false), port(port)
 {
     // Don't print token for security reasons
-    LOG("Constructor#3 called:: org=%s, type=%s, id=%s", (org==NULL)?"NULL":org,
+    LOG("Constructor#3 called:: org=%s, type=%s, id=%s\r\n", (org==NULL)?"NULL":org,
                     (deviceType==NULL)?"NULL":deviceType, (deviceId==NULL)?"NULL":deviceId);
+
+    mqttNetwork = new MQTTNetwork();
+    mqttClient = new MQTT::Client<MQTTNetwork, Countdown>(*mqttNetwork);
 }
 
 /**
  * Connect to the IBM Internet of Things Foundation
- */ 
+ */
 bool DeviceClient::connect()
-{   
+{
     char *organizationName, *typeId, *id;
+    bool rc = false;
     // Check if any organization is set
-    if(this->org == NULL || (strcmp("", this->org) == 0)) 
+    if(this->org == NULL || (strcmp("", this->org) == 0))
     {
         organizationName = QUICKSTART;
     } else {
         organizationName = this->org;
     }
-    
+
     // Check if device type is already mentioned
-    if(this->deviceType == NULL || (strcmp("", this->deviceType) == 0)) 
+    if(this->deviceType == NULL || (strcmp("", this->deviceType) == 0))
     {
         typeId = "iotsample-mbed";
     } else {
         typeId = this->deviceType;
     }
-    
+
     char hostname[strlen(organizationName) + strlen(IBM_IOT_MESSAGING) + 1];
     sprintf(hostname, "%s%s", organizationName, IBM_IOT_MESSAGING);
-    
-    EthernetInterface& eth = ipstack.getEth();
+
+    NetworkInterface* net = mqttNetwork->getEth();
+    const char* ip = net->get_ip_address();
 
     // Get devices MAC address if deviceId is not set already
-    if(this->deviceId == NULL || (strcmp("", this->deviceId) == 0)) 
+    if(this->deviceId == NULL || (strcmp("", this->deviceId) == 0))
     {
         char tmpBuf[50];
         id = getMac(tmpBuf, sizeof(tmpBuf));
     } else {
         id = this->deviceId;
     }
-    
+
     // Construct clientId - d:org:type:id
     char clientId[strlen(organizationName) + strlen(typeId) + strlen(id) + 5];
     sprintf(clientId, "d:%s:%s:%s", organizationName, typeId, id);
-    
-    logData(eth, hostname, clientId);
-    
+
     // Initialize MQTT Connect
     MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
     data.MQTTVersion = 4;
     data.clientID.cstring = clientId;
-    
+
     int quickstartMode = (strcmp(organizationName, QUICKSTART) == 0);
-    
-    if (!quickstartMode) 
-    {        
+
+    if (!quickstartMode)
+    {
         data.username.cstring = "use-token-auth";
         data.password.cstring = this->authToken;
-    } 
-    bool rc = tryConnect(hostname, data);
-    // By default subscribe to commands if we are in registered flow
-    if(rc == true && !quickstartMode) 
-    {
-        subscribeToCommands();
+
+        //Check and initialize appropriate port
+        if(port == 1883)
+            port = MQTT_TLS_PORT;
     }
-    if(rc == true) 
-    {
-        connected = true;
+
+    logData(net, hostname, clientId);
+
+    if(ip){
+       rc = tryConnect(hostname, data);
+       // By default subscribe to commands if we are in registered flow
+       if(rc == true && !quickstartMode)
+       {
+           subscribeToCommands();
+       }
+       if(rc == true)
+       {
+          connected = true;
+          LOG("Device Client Connected to %s:%d\r\n",hostname,port);
+        }
     }
+    else
+       LOG("No IP Assigned to Network Interface...\r\n");
+
     return rc;
 }
 
 /**
  * Reconnect when the connection is lost. This method disconnects the active connection if any
- * and tries to initiate a fresh connection. 
+ * and tries to initiate a fresh connection.
  * This method uses the Ethernet Link status wherever applicable while reconnecting. i.e, tries to
  * initiate the connection only when the Ethernet cable is plugged in.
  */
-bool DeviceClient::reConnect() 
+bool DeviceClient::reConnect()
 {
-    LOG("DeviceClient::reConnect() entry and connected = %s\n",(connected == true)?"true":"false");
+    LOG("DeviceClient::reConnect() entry and connected = %s\r\n",(connected == true)?"true":"false");
     if(connected == true)
     {
         disconnect();
@@ -152,13 +171,13 @@
 
     if(linkStatus())
     {
-        EthernetInterface& eth = ipstack.getEth();
-        if(eth.connect() == 0) 
+        NetworkInterface* net = mqttNetwork->getEth();
+        if(net->connect() == 0)
         {
             bool status = connect();
-            if(status == false) 
+            if(status == false)
             {
-                eth.disconnect();
+                net->disconnect();
             }
             return status;
         }
@@ -166,31 +185,31 @@
     return false;
 }
 
-bool DeviceClient::tryConnect(char *hostname, MQTTPacket_connectData &data) 
+bool DeviceClient::tryConnect(char *hostname, MQTTPacket_connectData &data)
 {
     int rc = -1;
     int retryAttempt = 0;
-    do {    
-        rc = ipstack.connect(hostname, IBM_IOT_PORT, CONNECT_TIMEOUT);
-        if (rc != 0) 
+    do {
+        rc = mqttNetwork->connect(hostname, port);
+        if (rc != 0)
         {
-            WARN("IP Stack connect returned: %d\n", rc);    
+            WARN("mqttNetwork connect returned: %d\r\n", rc);
         }
 
-        // MQTT connect        
-        if (rc == 0 && (rc = mqttClient.connect(data)) != 0) 
+        // MQTT connect
+        if (rc == 0 && (rc = mqttClient->connect(data)) != 0)
         {
-            WARN("MQTT connect returned %d\n", rc);
+            WARN("MQTT connect returned %d\r\n", rc);
             if (rc == MQTT_NOT_AUTHORIZED || rc == MQTT_BAD_USERNAME_OR_PASSWORD)
                 return false; // don't reattempt to connect if credentials are wrong
         } else if (rc == MQTT_CONNECTION_ACCEPTED) {
             return true;
         }
-   
+
         int timeout = getConnTimeout(++retryAttempt);
-        
-        WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout);
-        
+
+        WARN("Retry attempt number %d waiting %d\r\n", retryAttempt, timeout);
+
         // enough retry is done - return to application
         if (retryAttempt == 5)
             return false;
@@ -199,18 +218,19 @@
     } while(true);
 }
 
-void DeviceClient::logData(EthernetInterface& eth, char *hostname, char *clientId) 
+void DeviceClient::logData(NetworkInterface* net, char *hostname, char *clientId)
 {
-    // Network debug statements 
-    LOG("=====================================\n");
-    LOG("Connecting Ethernet.\n");
-    LOG("IP ADDRESS: %s\n", eth.getIPAddress());
-    LOG("MAC ADDRESS: %s\n", eth.getMACAddress());
-    LOG("Gateway: %s\n", eth.getGateway());
-    LOG("Network Mask: %s\n", eth.getNetworkMask());
-    LOG("Server Hostname: %s\n", hostname);
-    LOG("Client ID: %s\n", clientId);
-    LOG("=====================================\n");
+    // Network debug statements
+    LOG("=====================================\r\n");
+    LOG("Connection Config Details:\r\n");
+    LOG("IP ADDRESS: %s\r\n", net->get_ip_address());
+    LOG("MAC ADDRESS: %s\r\n", net->get_mac_address());
+    LOG("Gateway: %s\r\n", net->get_gateway());
+    LOG("Network Mask: %s\r\n", net->get_netmask());
+    LOG("Server Hostname: %s\r\n", hostname);
+    LOG("Server Port: %d\r\n", port);
+    LOG("Client ID: %s\r\n", clientId);
+    LOG("=====================================\r\n");
 }
 
 int DeviceClient::getConnTimeout(int attemptNumber)
@@ -223,22 +243,22 @@
  * Returns the connection status, connected or disconnected.
  */
 bool DeviceClient::isConnected() {
-    return mqttClient.isConnected();
+    return mqttClient->isConnected();
 }
 
 /**
- * Publish data to the IBM Internet of Things Foundation. Note that data is published 
- * by default at Quality of Service (QoS) 0, which means that a successful send 
+ * Publish data to the IBM Internet of Things Foundation. Note that data is published
+ * by default at Quality of Service (QoS) 0, which means that a successful send
  * does not guarantee receipt even if the publish has been successful.
  */
 bool DeviceClient::publishEvent(char *eventName, char *data, MQTT::QoS qos)
 {
-    if(!mqttClient.isConnected()) 
+    if(!mqttClient->isConnected())
     {
-        WARN("Client is not connected \n");
+        WARN("Client is not connected \r\n");
         return false;
     }
-    
+
     MQTT::Message message;
     /* Topic format must be iot-2/evt/<eventName>/fmt/json (let us stick to json format for now)
      *
@@ -247,22 +267,22 @@
      * /fmt/json = 9
      * NULL char = 1
      */
-    
+
     char topic[10 + strlen(eventName) + 9 + 1];
     sprintf(topic, "%s%s%s", "iot-2/evt/", eventName, "/fmt/json");
-            
+
     message.qos = qos;
     message.retained = false;
     message.dup = false;
     message.payload = (void*)data;
     message.payloadlen = strlen(data);
-    
-    LOG("Publishing %s\n", data);
-    int rc = mqttClient.publish(topic, message);
+
+    LOG("Publishing %s\r\n", data);
+    int rc = mqttClient->publish(topic, message);
     return rc == 0;
 }
 
-void DeviceClient::setCommandCallback(CommandHandler callbackFunc) 
+void DeviceClient::setCommandCallback(CommandHandler callbackFunc)
 {
     handler = callbackFunc;
 }
@@ -270,51 +290,51 @@
  * Subscribe to commands from the application. This will be executed only for
  * registered flow (quickstart flow does not support command publish)
  */
-int DeviceClient::subscribeToCommands() 
+int DeviceClient::subscribeToCommands()
 {
     int rc = 0;
     // iot-2/cmd/+/fmt/+
-    if ((rc = mqttClient.subscribe("iot-2/cmd/+/fmt/+", MQTT::QOS2, msgArrived)) != 0)
-        WARN("rc from MQTT subscribe is %d\n", rc); 
+    if ((rc = mqttClient->subscribe("iot-2/cmd/+/fmt/+", MQTT::QOS2, msgArrived)) != 0)
+        WARN("rc from MQTT subscribe is %d\r\n", rc);
     return rc;
 }
 
 /**
- * Callback method to be registered with MQTT::Client. MQTT::Client calls whenever 
+ * Callback method to be registered with MQTT::Client. MQTT::Client calls whenever
  * any command is published to the topic subscribed earlier.
  */
 void msgArrived(MQTT::MessageData& md)
 {
     // check whether callback is registered by the client code
-    if(handler == NULL) 
+    if(handler == NULL)
     {
         return;
     }
-    
+
     MQTT::Message &message = md.message;
     char topic[md.topicName.lenstring.len + 1];
-    
+
     sprintf(topic, "%.*s", md.topicName.lenstring.len, md.topicName.lenstring.data);
-    
-    LOG("Message arrived on topic %s: %.*s\n",  topic, message.payloadlen, message.payload);
-          
+
+    LOG("Message arrived on topic %s: %.*s\r\n",  topic, message.payloadlen, message.payload);
+
     // Command topic: iot-2/cmd/blink/fmt/json - cmd is the string between cmd/ and /fmt/
     char* start = strstr(topic, "/cmd/") + 5;
     int len = strstr(topic, "/fmt/") - start;
 
     char name[len + 1];
-    
+
     memcpy(name, start, len);
     name[len] = NULL;
-    
+
     start = strstr(topic, "/fmt/") + 5;
-      
+
     char format[20];  // ToDO: need to find the length of the format
     strcpy(format, start);
-    
+
     char payload[message.payloadlen + 1];
     sprintf(payload, "%.*s", message.payloadlen, (char*)message.payload);
-    
+
     IoTF::Command cmd(name, format, payload);
     (*handler)(cmd);
 }
@@ -322,34 +342,34 @@
 /**
  * Disconnects the connection in order.
  */
-bool DeviceClient::disconnect() 
+bool DeviceClient::disconnect()
 {
     int rc = 0;
-    if(mqttClient.isConnected())
+    if(mqttClient->isConnected())
     {
-        rc = mqttClient.disconnect();
+        rc = mqttClient->disconnect();
     }
-    
-    EthernetInterface& eth = ipstack.getEth();
-    ipstack.disconnect();
-    eth.disconnect();
+
+    NetworkInterface* net = mqttNetwork->getEth();
+    mqttNetwork->disconnect();
+    net->disconnect();
     connected = false;
     return rc == 0;
 }
 
 // Yield to allow MQTT client to process the command
-void DeviceClient::yield(int ms) 
+void DeviceClient::yield(int ms)
 {
-    if(mqttClient.isConnected()) 
+    if(mqttClient->isConnected())
     {
-        mqttClient.yield(ms);
+        mqttClient->yield(ms);
     }
 }
 
 // Obtain DeviceId address
-char* DeviceClient::getDeviceId(char* buf, int buflen) 
-{   
-    if(this->deviceId == NULL || (strcmp("", this->deviceId) == 0)) 
+char* DeviceClient::getDeviceId(char* buf, int buflen)
+{
+    if(this->deviceId == NULL || (strcmp("", this->deviceId) == 0))
     {
         return getMac(buf, buflen);
     } else {
@@ -357,13 +377,13 @@
     }
 }
 // Obtain MAC address
-char* DeviceClient::getMac(char* buf, int buflen)    
-{   
-    EthernetInterface& eth = ipstack.getEth();
-    strncpy(buf, eth.getMACAddress(), buflen);
+char* DeviceClient::getMac(char* buf, int buflen)
+{
+    NetworkInterface* net = mqttNetwork->getEth();
+    strncpy(buf, net->get_mac_address(), buflen);
 
     char* pos;                                                 // Remove colons from mac address
     while ((pos = strchr(buf, ':')) != NULL)
         memmove(pos, pos + 1, strlen(pos) + 1);
     return buf;
-}
\ No newline at end of file
+}