A library that simplifies interactions with the IBM Internet of Things Foundation

Dependencies:   MQTT

Dependents:   IBMIoTClientLibrarySamplefinal IBMWIoTPSecureClientSample IBMIoTClientLibrarySample

Introduction

Use the mBed C++ client library to easily connect mBed devices, such as LPC1768 or FRDM-K64F, to the IBM Watson™ IoT Platform service.

Although the library uses C++, it still avoids dynamic memory allocations and the use of STL functions, because the mBed devices sometimes have idiosyncratic memory models that make porting difficult. In any case, the library allows you to make memory use as predictable as possible.

Dependencies

DependencyDescription
Eclipse Paho MQTT libraryProvides an MQTT client library for mBed devices. For more information, see Embedded MQTT C/C++ client libraries
mbed-osARM mbed OS

How to use the library

Use the mBed compiler to create your applications when you use the mBed C++ IBMIoTF client library. The mBed compiler provides a lightweight online C/C++ IDE that is configured for writing, compiling, and downloading programs to run on your mBed microcontroller.

Note: You don't have to install or set up anything to get running with mBed.

For information on how to connect an ARM mBed NXP LPC 1768 microcontroller to the Watson IoT Platform, see the mBed C++ client library for IBM Watson IoT Platform recipe.

Supported Features

FeatureSupported?
Device connectivityYes
Event publishYes
Command receiptYes
SSL/TLSYes
Device ManagementNo

License

This library is shipped under License Eclipse Public License - v 1.0 and Eclipse Distribution License v1.0

For more information about the Eclipse Public License - v 1.0, refer this page. Also, for more information about the Eclipse Distribution License v1.0, refer this page.

Contributor License Agreement

Version 1.0.0 January 14, 2014

In order for You (as defined below) to make intellectual property Contributions (as defined below) now or in the future to IBM repositories, You must agree to this Contributor License Agreement ("CLA").

Please read this CLA carefully before accepting its terms. By accepting the CLA, You are agreeing to be bound by its terms. If You submit a Pull Request against this repository You must include in the Pull Request a statement of Your acceptance of this CLA.

As used in this CLA: (i) "You" (or "Your") shall mean the entity that is making this Agreement with IBM; (ii)"Contribution" shall mean any original work of authorship, including any modifications or additions to an existing work, that is submitted by You to IBM for inclusion in, or documentation of, any of the IBM repositories; (iii) "Submit" (or "Submitted") means any form of communication sent to IBM (e.g. the content You post in the Issue or submit as part of a Pull Request).

This agreement applies to all Contributions You Submit.

This CLA, and the license(s) associated with the particular IBM repositories You are contributing to, provides a license to Your Contributions to IBM and downstream consumers, but You still own Your Contributions, and except for the licenses provided for in this CLA, You reserve all right, title and interest in Your Contributions.

IBM requires that each Contribution You Submit now or in the future comply with the following four commitments.

1) You will only Submit Contributions where You have authored 100% of the content. 2) You will only Submit Contributions to which You have the necessary rights. This means that if You are employed You have received the necessary permissions from Your employer to make the Contributions. 3) Whatever content You Contribute will be provided under the license(s) associated with the particular IBM repository You are contributing to. 4) You understand and agree that IBM repositories and Your contributions are public, and that a record of the contribution (including all personal information You submit with it) is maintained indefinitely and may be redistributed consistent with the license(s) involved. You will promptly notify the Eclipse Foundation if You become aware of any facts or circumstances that would make these commitments inaccurate in any way. To do so, please create an Issue in the appropriate repository.

Committer:
lokeshhk
Date:
Tue May 30 06:36:04 2017 +0000
Revision:
6:5f037f24ce29
Parent:
5:ea9f483e0294
Added mbed-os and mqtt dependencies for the library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sathipal 0:f86732d81998 1 /*******************************************************************************
sathipal 0:f86732d81998 2 * Copyright (c) 2015 IBM Corp.
sathipal 0:f86732d81998 3 *
sathipal 0:f86732d81998 4 * All rights reserved. This program and the accompanying materials
sathipal 0:f86732d81998 5 * are made available under the terms of the Eclipse Public License v1.0
sathipal 0:f86732d81998 6 * and Eclipse Distribution License v1.0 which accompany this distribution.
sathipal 0:f86732d81998 7 *
sathipal 0:f86732d81998 8 * The Eclipse Public License is available at
sathipal 0:f86732d81998 9 * http://www.eclipse.org/legal/epl-v10.html
sathipal 0:f86732d81998 10 * and the Eclipse Distribution License is available at
sathipal 0:f86732d81998 11 * http://www.eclipse.org/org/documents/edl-v10.php.
sathipal 0:f86732d81998 12 *
sathipal 0:f86732d81998 13 * Contributors:
sathipal 0:f86732d81998 14 * Sathisumar Palaniappan - initial implementation
sathipal 3:3d91bf839b49 15 * Sathisumar Palaniappan - added reconnect logic and isConnected() method
lokeshhk 5:ea9f483e0294 16 * Lokesh K Haralakatta - Port to mbed OS 5 support
lokeshhk 5:ea9f483e0294 17 * Lokesh K Haralakatta - Added SSL/TLS Support
sathipal 0:f86732d81998 18 *******************************************************************************/
sathipal 0:f86732d81998 19 #include "MQTTClient.h"
sathipal 0:f86732d81998 20 #include "DeviceClient.h"
sathipal 0:f86732d81998 21
sathipal 3:3d91bf839b49 22 // need a wrapper since K64F and LPC1768 wont have the same name for mii read methods
sathipal 3:3d91bf839b49 23 #if defined(TARGET_UBLOX_C027) || defined(TARGET_K64F)
sathipal 3:3d91bf839b49 24
sathipal 3:3d91bf839b49 25 static uint32_t linkStatus(void)
sathipal 3:3d91bf839b49 26 {
sathipal 3:3d91bf839b49 27 return (1);
sathipal 3:3d91bf839b49 28 }
sathipal 3:3d91bf839b49 29 #elif defined(TARGET_LPC1768)
sathipal 3:3d91bf839b49 30 #include "lpc_phy.h"
sathipal 3:3d91bf839b49 31
sathipal 3:3d91bf839b49 32 static uint32_t linkStatus(void)
sathipal 3:3d91bf839b49 33 {
sathipal 3:3d91bf839b49 34 return (lpc_mii_read_data() & 1);
sathipal 3:3d91bf839b49 35 }
sathipal 3:3d91bf839b49 36 #endif
sathipal 0:f86732d81998 37 using namespace IoTF;
sathipal 0:f86732d81998 38
sathipal 0:f86732d81998 39 CommandHandler handler = NULL;
sathipal 0:f86732d81998 40 void msgArrived(MQTT::MessageData& md);
sathipal 0:f86732d81998 41
sathipal 0:f86732d81998 42 /**
sathipal 0:f86732d81998 43 * A client, used by device, that handles connections with the IBM Internet of Things Foundation.
sathipal 0:f86732d81998 44 * This class allows device to publish events and receive commands to/from IBM IoT Foundation wtih simple function calls.
sathipal 0:f86732d81998 45 */
sathipal 2:199ddea804cd 46 DeviceClient::DeviceClient():org(NULL),deviceType(NULL),deviceId(NULL),
lokeshhk 5:ea9f483e0294 47 authMethod(NULL),authToken(NULL),mqttNetwork(NULL),mqttClient(NULL),connected(false),port(0)
sathipal 2:199ddea804cd 48 {
lokeshhk 5:ea9f483e0294 49 LOG("Constructor#1 called::\r\n");
sathipal 0:f86732d81998 50 }
sathipal 0:f86732d81998 51
lokeshhk 5:ea9f483e0294 52 DeviceClient::DeviceClient(char *orgId, char *typeId, char *id, int port):org(orgId),deviceType(typeId),
lokeshhk 5:ea9f483e0294 53 deviceId(id),authMethod(NULL),authToken(NULL),connected(false), port(port)
sathipal 2:199ddea804cd 54 {
lokeshhk 5:ea9f483e0294 55 LOG("Constructor#2 called:: org=%s, type=%s, id=%s\r\n", (org==NULL)?"NULL":org,
sathipal 0:f86732d81998 56 (deviceType==NULL)?"NULL":deviceType, (deviceId==NULL)?"NULL":deviceId);
lokeshhk 5:ea9f483e0294 57
sathipal 0:f86732d81998 58 if(strcmp(this->org, QUICKSTART) != 0) {
lokeshhk 5:ea9f483e0294 59 WARN("Registered flow must provide valid token\r\n");
sathipal 0:f86732d81998 60 }
lokeshhk 5:ea9f483e0294 61
lokeshhk 5:ea9f483e0294 62 mqttNetwork = new MQTTNetwork();
lokeshhk 5:ea9f483e0294 63 mqttClient = new MQTT::Client<MQTTNetwork, Countdown>(*mqttNetwork);
lokeshhk 5:ea9f483e0294 64
sathipal 0:f86732d81998 65 }
sathipal 0:f86732d81998 66
lokeshhk 5:ea9f483e0294 67 DeviceClient::DeviceClient(char *orgId, char *typeId,char *id, char *method, char *token, int port):org(orgId),
lokeshhk 5:ea9f483e0294 68 deviceType(typeId),deviceId(id),authMethod(method),authToken(token),connected(false), port(port)
sathipal 2:199ddea804cd 69 {
sathipal 0:f86732d81998 70 // Don't print token for security reasons
lokeshhk 5:ea9f483e0294 71 LOG("Constructor#3 called:: org=%s, type=%s, id=%s\r\n", (org==NULL)?"NULL":org,
sathipal 0:f86732d81998 72 (deviceType==NULL)?"NULL":deviceType, (deviceId==NULL)?"NULL":deviceId);
lokeshhk 5:ea9f483e0294 73
lokeshhk 5:ea9f483e0294 74 mqttNetwork = new MQTTNetwork();
lokeshhk 5:ea9f483e0294 75 mqttClient = new MQTT::Client<MQTTNetwork, Countdown>(*mqttNetwork);
sathipal 0:f86732d81998 76 }
sathipal 0:f86732d81998 77
sathipal 0:f86732d81998 78 /**
sathipal 0:f86732d81998 79 * Connect to the IBM Internet of Things Foundation
lokeshhk 5:ea9f483e0294 80 */
sathipal 0:f86732d81998 81 bool DeviceClient::connect()
lokeshhk 5:ea9f483e0294 82 {
sathipal 0:f86732d81998 83 char *organizationName, *typeId, *id;
lokeshhk 5:ea9f483e0294 84 bool rc = false;
sathipal 0:f86732d81998 85 // Check if any organization is set
lokeshhk 5:ea9f483e0294 86 if(this->org == NULL || (strcmp("", this->org) == 0))
sathipal 3:3d91bf839b49 87 {
sathipal 0:f86732d81998 88 organizationName = QUICKSTART;
sathipal 0:f86732d81998 89 } else {
sathipal 0:f86732d81998 90 organizationName = this->org;
sathipal 0:f86732d81998 91 }
lokeshhk 5:ea9f483e0294 92
sathipal 0:f86732d81998 93 // Check if device type is already mentioned
lokeshhk 5:ea9f483e0294 94 if(this->deviceType == NULL || (strcmp("", this->deviceType) == 0))
sathipal 3:3d91bf839b49 95 {
sathipal 0:f86732d81998 96 typeId = "iotsample-mbed";
sathipal 0:f86732d81998 97 } else {
sathipal 0:f86732d81998 98 typeId = this->deviceType;
sathipal 0:f86732d81998 99 }
lokeshhk 5:ea9f483e0294 100
sathipal 0:f86732d81998 101 char hostname[strlen(organizationName) + strlen(IBM_IOT_MESSAGING) + 1];
sathipal 0:f86732d81998 102 sprintf(hostname, "%s%s", organizationName, IBM_IOT_MESSAGING);
lokeshhk 5:ea9f483e0294 103
lokeshhk 5:ea9f483e0294 104 NetworkInterface* net = mqttNetwork->getEth();
lokeshhk 5:ea9f483e0294 105 const char* ip = net->get_ip_address();
sathipal 0:f86732d81998 106
sathipal 0:f86732d81998 107 // Get devices MAC address if deviceId is not set already
lokeshhk 5:ea9f483e0294 108 if(this->deviceId == NULL || (strcmp("", this->deviceId) == 0))
sathipal 3:3d91bf839b49 109 {
sathipal 0:f86732d81998 110 char tmpBuf[50];
sathipal 0:f86732d81998 111 id = getMac(tmpBuf, sizeof(tmpBuf));
sathipal 0:f86732d81998 112 } else {
sathipal 0:f86732d81998 113 id = this->deviceId;
sathipal 0:f86732d81998 114 }
lokeshhk 5:ea9f483e0294 115
sathipal 0:f86732d81998 116 // Construct clientId - d:org:type:id
sathipal 0:f86732d81998 117 char clientId[strlen(organizationName) + strlen(typeId) + strlen(id) + 5];
sathipal 0:f86732d81998 118 sprintf(clientId, "d:%s:%s:%s", organizationName, typeId, id);
lokeshhk 5:ea9f483e0294 119
sathipal 0:f86732d81998 120 // Initialize MQTT Connect
sathipal 0:f86732d81998 121 MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
sathipal 0:f86732d81998 122 data.MQTTVersion = 4;
sathipal 0:f86732d81998 123 data.clientID.cstring = clientId;
lokeshhk 5:ea9f483e0294 124
sathipal 0:f86732d81998 125 int quickstartMode = (strcmp(organizationName, QUICKSTART) == 0);
lokeshhk 5:ea9f483e0294 126
lokeshhk 5:ea9f483e0294 127 if (!quickstartMode)
lokeshhk 5:ea9f483e0294 128 {
sathipal 0:f86732d81998 129 data.username.cstring = "use-token-auth";
sathipal 0:f86732d81998 130 data.password.cstring = this->authToken;
lokeshhk 5:ea9f483e0294 131
lokeshhk 5:ea9f483e0294 132 //Check and initialize appropriate port
lokeshhk 5:ea9f483e0294 133 if(port == 1883)
lokeshhk 5:ea9f483e0294 134 port = MQTT_TLS_PORT;
sathipal 0:f86732d81998 135 }
lokeshhk 5:ea9f483e0294 136
lokeshhk 5:ea9f483e0294 137 logData(net, hostname, clientId);
lokeshhk 5:ea9f483e0294 138
lokeshhk 5:ea9f483e0294 139 if(ip){
lokeshhk 5:ea9f483e0294 140 rc = tryConnect(hostname, data);
lokeshhk 5:ea9f483e0294 141 // By default subscribe to commands if we are in registered flow
lokeshhk 5:ea9f483e0294 142 if(rc == true && !quickstartMode)
lokeshhk 5:ea9f483e0294 143 {
lokeshhk 5:ea9f483e0294 144 subscribeToCommands();
lokeshhk 5:ea9f483e0294 145 }
lokeshhk 5:ea9f483e0294 146 if(rc == true)
lokeshhk 5:ea9f483e0294 147 {
lokeshhk 5:ea9f483e0294 148 connected = true;
lokeshhk 5:ea9f483e0294 149 LOG("Device Client Connected to %s:%d\r\n",hostname,port);
lokeshhk 5:ea9f483e0294 150 }
sathipal 3:3d91bf839b49 151 }
lokeshhk 5:ea9f483e0294 152 else
lokeshhk 5:ea9f483e0294 153 LOG("No IP Assigned to Network Interface...\r\n");
lokeshhk 5:ea9f483e0294 154
sathipal 0:f86732d81998 155 return rc;
sathipal 0:f86732d81998 156 }
sathipal 0:f86732d81998 157
sathipal 3:3d91bf839b49 158 /**
sathipal 3:3d91bf839b49 159 * Reconnect when the connection is lost. This method disconnects the active connection if any
lokeshhk 5:ea9f483e0294 160 * and tries to initiate a fresh connection.
sathipal 3:3d91bf839b49 161 * This method uses the Ethernet Link status wherever applicable while reconnecting. i.e, tries to
sathipal 3:3d91bf839b49 162 * initiate the connection only when the Ethernet cable is plugged in.
sathipal 3:3d91bf839b49 163 */
lokeshhk 5:ea9f483e0294 164 bool DeviceClient::reConnect()
sathipal 3:3d91bf839b49 165 {
lokeshhk 5:ea9f483e0294 166 LOG("DeviceClient::reConnect() entry and connected = %s\r\n",(connected == true)?"true":"false");
sathipal 3:3d91bf839b49 167 if(connected == true)
sathipal 3:3d91bf839b49 168 {
sathipal 3:3d91bf839b49 169 disconnect();
sathipal 3:3d91bf839b49 170 }
sathipal 3:3d91bf839b49 171
sathipal 3:3d91bf839b49 172 if(linkStatus())
sathipal 3:3d91bf839b49 173 {
lokeshhk 5:ea9f483e0294 174 NetworkInterface* net = mqttNetwork->getEth();
lokeshhk 5:ea9f483e0294 175 if(net->connect() == 0)
sathipal 3:3d91bf839b49 176 {
sathipal 3:3d91bf839b49 177 bool status = connect();
lokeshhk 5:ea9f483e0294 178 if(status == false)
sathipal 3:3d91bf839b49 179 {
lokeshhk 5:ea9f483e0294 180 net->disconnect();
sathipal 3:3d91bf839b49 181 }
sathipal 3:3d91bf839b49 182 return status;
sathipal 3:3d91bf839b49 183 }
sathipal 3:3d91bf839b49 184 }
sathipal 3:3d91bf839b49 185 return false;
sathipal 3:3d91bf839b49 186 }
sathipal 3:3d91bf839b49 187
lokeshhk 5:ea9f483e0294 188 bool DeviceClient::tryConnect(char *hostname, MQTTPacket_connectData &data)
sathipal 2:199ddea804cd 189 {
sathipal 0:f86732d81998 190 int rc = -1;
sathipal 0:f86732d81998 191 int retryAttempt = 0;
lokeshhk 5:ea9f483e0294 192 do {
lokeshhk 5:ea9f483e0294 193 rc = mqttNetwork->connect(hostname, port);
lokeshhk 5:ea9f483e0294 194 if (rc != 0)
sathipal 3:3d91bf839b49 195 {
lokeshhk 5:ea9f483e0294 196 WARN("mqttNetwork connect returned: %d\r\n", rc);
sathipal 0:f86732d81998 197 }
sathipal 0:f86732d81998 198
lokeshhk 5:ea9f483e0294 199 // MQTT connect
lokeshhk 5:ea9f483e0294 200 if (rc == 0 && (rc = mqttClient->connect(data)) != 0)
sathipal 3:3d91bf839b49 201 {
lokeshhk 5:ea9f483e0294 202 WARN("MQTT connect returned %d\r\n", rc);
sathipal 0:f86732d81998 203 if (rc == MQTT_NOT_AUTHORIZED || rc == MQTT_BAD_USERNAME_OR_PASSWORD)
sathipal 0:f86732d81998 204 return false; // don't reattempt to connect if credentials are wrong
sathipal 0:f86732d81998 205 } else if (rc == MQTT_CONNECTION_ACCEPTED) {
sathipal 0:f86732d81998 206 return true;
sathipal 0:f86732d81998 207 }
lokeshhk 5:ea9f483e0294 208
sathipal 0:f86732d81998 209 int timeout = getConnTimeout(++retryAttempt);
lokeshhk 5:ea9f483e0294 210
lokeshhk 5:ea9f483e0294 211 WARN("Retry attempt number %d waiting %d\r\n", retryAttempt, timeout);
lokeshhk 5:ea9f483e0294 212
sathipal 2:199ddea804cd 213 // enough retry is done - return to application
sathipal 0:f86732d81998 214 if (retryAttempt == 5)
sathipal 2:199ddea804cd 215 return false;
sathipal 0:f86732d81998 216 else
sathipal 0:f86732d81998 217 wait(timeout);
sathipal 0:f86732d81998 218 } while(true);
sathipal 0:f86732d81998 219 }
sathipal 0:f86732d81998 220
lokeshhk 5:ea9f483e0294 221 void DeviceClient::logData(NetworkInterface* net, char *hostname, char *clientId)
sathipal 2:199ddea804cd 222 {
lokeshhk 5:ea9f483e0294 223 // Network debug statements
lokeshhk 5:ea9f483e0294 224 LOG("=====================================\r\n");
lokeshhk 5:ea9f483e0294 225 LOG("Connection Config Details:\r\n");
lokeshhk 5:ea9f483e0294 226 LOG("IP ADDRESS: %s\r\n", net->get_ip_address());
lokeshhk 5:ea9f483e0294 227 LOG("MAC ADDRESS: %s\r\n", net->get_mac_address());
lokeshhk 5:ea9f483e0294 228 LOG("Gateway: %s\r\n", net->get_gateway());
lokeshhk 5:ea9f483e0294 229 LOG("Network Mask: %s\r\n", net->get_netmask());
lokeshhk 5:ea9f483e0294 230 LOG("Server Hostname: %s\r\n", hostname);
lokeshhk 5:ea9f483e0294 231 LOG("Server Port: %d\r\n", port);
lokeshhk 5:ea9f483e0294 232 LOG("Client ID: %s\r\n", clientId);
lokeshhk 5:ea9f483e0294 233 LOG("=====================================\r\n");
sathipal 0:f86732d81998 234 }
sathipal 0:f86732d81998 235
sathipal 0:f86732d81998 236 int DeviceClient::getConnTimeout(int attemptNumber)
sathipal 0:f86732d81998 237 {
sathipal 0:f86732d81998 238 // Try to increase the timeout every time
sathipal 0:f86732d81998 239 return (attemptNumber * attemptNumber * 5);
sathipal 0:f86732d81998 240 }
sathipal 0:f86732d81998 241
sathipal 3:3d91bf839b49 242 /**
sathipal 3:3d91bf839b49 243 * Returns the connection status, connected or disconnected.
sathipal 3:3d91bf839b49 244 */
sathipal 3:3d91bf839b49 245 bool DeviceClient::isConnected() {
lokeshhk 5:ea9f483e0294 246 return mqttClient->isConnected();
sathipal 3:3d91bf839b49 247 }
sathipal 0:f86732d81998 248
sathipal 0:f86732d81998 249 /**
lokeshhk 5:ea9f483e0294 250 * Publish data to the IBM Internet of Things Foundation. Note that data is published
lokeshhk 5:ea9f483e0294 251 * by default at Quality of Service (QoS) 0, which means that a successful send
sathipal 0:f86732d81998 252 * does not guarantee receipt even if the publish has been successful.
sathipal 0:f86732d81998 253 */
sathipal 0:f86732d81998 254 bool DeviceClient::publishEvent(char *eventName, char *data, MQTT::QoS qos)
sathipal 0:f86732d81998 255 {
lokeshhk 5:ea9f483e0294 256 if(!mqttClient->isConnected())
sathipal 3:3d91bf839b49 257 {
lokeshhk 5:ea9f483e0294 258 WARN("Client is not connected \r\n");
sathipal 0:f86732d81998 259 return false;
sathipal 0:f86732d81998 260 }
lokeshhk 5:ea9f483e0294 261
sathipal 0:f86732d81998 262 MQTT::Message message;
sathipal 0:f86732d81998 263 /* Topic format must be iot-2/evt/<eventName>/fmt/json (let us stick to json format for now)
sathipal 0:f86732d81998 264 *
sathipal 0:f86732d81998 265 * So length must be 10 + strlen(eventName) + 9 + 1
sathipal 0:f86732d81998 266 * iot-2/evt/ = 10
sathipal 0:f86732d81998 267 * /fmt/json = 9
sathipal 0:f86732d81998 268 * NULL char = 1
sathipal 0:f86732d81998 269 */
lokeshhk 5:ea9f483e0294 270
sathipal 0:f86732d81998 271 char topic[10 + strlen(eventName) + 9 + 1];
sathipal 0:f86732d81998 272 sprintf(topic, "%s%s%s", "iot-2/evt/", eventName, "/fmt/json");
lokeshhk 5:ea9f483e0294 273
sathipal 0:f86732d81998 274 message.qos = qos;
sathipal 0:f86732d81998 275 message.retained = false;
sathipal 0:f86732d81998 276 message.dup = false;
sathipal 0:f86732d81998 277 message.payload = (void*)data;
sathipal 0:f86732d81998 278 message.payloadlen = strlen(data);
lokeshhk 5:ea9f483e0294 279
lokeshhk 5:ea9f483e0294 280 LOG("Publishing %s\r\n", data);
lokeshhk 5:ea9f483e0294 281 int rc = mqttClient->publish(topic, message);
sathipal 0:f86732d81998 282 return rc == 0;
sathipal 0:f86732d81998 283 }
sathipal 0:f86732d81998 284
lokeshhk 5:ea9f483e0294 285 void DeviceClient::setCommandCallback(CommandHandler callbackFunc)
sathipal 2:199ddea804cd 286 {
sathipal 0:f86732d81998 287 handler = callbackFunc;
sathipal 0:f86732d81998 288 }
sathipal 0:f86732d81998 289 /**
sathipal 0:f86732d81998 290 * Subscribe to commands from the application. This will be executed only for
sathipal 0:f86732d81998 291 * registered flow (quickstart flow does not support command publish)
sathipal 0:f86732d81998 292 */
lokeshhk 5:ea9f483e0294 293 int DeviceClient::subscribeToCommands()
sathipal 2:199ddea804cd 294 {
sathipal 0:f86732d81998 295 int rc = 0;
sathipal 0:f86732d81998 296 // iot-2/cmd/+/fmt/+
lokeshhk 5:ea9f483e0294 297 if ((rc = mqttClient->subscribe("iot-2/cmd/+/fmt/+", MQTT::QOS2, msgArrived)) != 0)
lokeshhk 5:ea9f483e0294 298 WARN("rc from MQTT subscribe is %d\r\n", rc);
sathipal 0:f86732d81998 299 return rc;
sathipal 0:f86732d81998 300 }
sathipal 0:f86732d81998 301
sathipal 0:f86732d81998 302 /**
lokeshhk 5:ea9f483e0294 303 * Callback method to be registered with MQTT::Client. MQTT::Client calls whenever
sathipal 0:f86732d81998 304 * any command is published to the topic subscribed earlier.
sathipal 0:f86732d81998 305 */
sathipal 0:f86732d81998 306 void msgArrived(MQTT::MessageData& md)
sathipal 0:f86732d81998 307 {
sathipal 0:f86732d81998 308 // check whether callback is registered by the client code
lokeshhk 5:ea9f483e0294 309 if(handler == NULL)
sathipal 3:3d91bf839b49 310 {
sathipal 0:f86732d81998 311 return;
sathipal 0:f86732d81998 312 }
lokeshhk 5:ea9f483e0294 313
sathipal 0:f86732d81998 314 MQTT::Message &message = md.message;
sathipal 0:f86732d81998 315 char topic[md.topicName.lenstring.len + 1];
lokeshhk 5:ea9f483e0294 316
sathipal 0:f86732d81998 317 sprintf(topic, "%.*s", md.topicName.lenstring.len, md.topicName.lenstring.data);
lokeshhk 5:ea9f483e0294 318
lokeshhk 5:ea9f483e0294 319 LOG("Message arrived on topic %s: %.*s\r\n", topic, message.payloadlen, message.payload);
lokeshhk 5:ea9f483e0294 320
sathipal 0:f86732d81998 321 // Command topic: iot-2/cmd/blink/fmt/json - cmd is the string between cmd/ and /fmt/
sathipal 0:f86732d81998 322 char* start = strstr(topic, "/cmd/") + 5;
sathipal 0:f86732d81998 323 int len = strstr(topic, "/fmt/") - start;
sathipal 0:f86732d81998 324
sathipal 0:f86732d81998 325 char name[len + 1];
lokeshhk 5:ea9f483e0294 326
sathipal 0:f86732d81998 327 memcpy(name, start, len);
sathipal 0:f86732d81998 328 name[len] = NULL;
lokeshhk 5:ea9f483e0294 329
sathipal 0:f86732d81998 330 start = strstr(topic, "/fmt/") + 5;
lokeshhk 5:ea9f483e0294 331
sathipal 0:f86732d81998 332 char format[20]; // ToDO: need to find the length of the format
sathipal 0:f86732d81998 333 strcpy(format, start);
lokeshhk 5:ea9f483e0294 334
sathipal 0:f86732d81998 335 char payload[message.payloadlen + 1];
sathipal 0:f86732d81998 336 sprintf(payload, "%.*s", message.payloadlen, (char*)message.payload);
lokeshhk 5:ea9f483e0294 337
sathipal 0:f86732d81998 338 IoTF::Command cmd(name, format, payload);
sathipal 0:f86732d81998 339 (*handler)(cmd);
sathipal 0:f86732d81998 340 }
sathipal 0:f86732d81998 341
sathipal 3:3d91bf839b49 342 /**
sathipal 3:3d91bf839b49 343 * Disconnects the connection in order.
sathipal 3:3d91bf839b49 344 */
lokeshhk 5:ea9f483e0294 345 bool DeviceClient::disconnect()
sathipal 2:199ddea804cd 346 {
sathipal 3:3d91bf839b49 347 int rc = 0;
lokeshhk 5:ea9f483e0294 348 if(mqttClient->isConnected())
sathipal 3:3d91bf839b49 349 {
lokeshhk 5:ea9f483e0294 350 rc = mqttClient->disconnect();
sathipal 0:f86732d81998 351 }
lokeshhk 5:ea9f483e0294 352
lokeshhk 5:ea9f483e0294 353 NetworkInterface* net = mqttNetwork->getEth();
lokeshhk 5:ea9f483e0294 354 mqttNetwork->disconnect();
lokeshhk 5:ea9f483e0294 355 net->disconnect();
sathipal 3:3d91bf839b49 356 connected = false;
sathipal 3:3d91bf839b49 357 return rc == 0;
sathipal 0:f86732d81998 358 }
sathipal 0:f86732d81998 359
sathipal 0:f86732d81998 360 // Yield to allow MQTT client to process the command
lokeshhk 5:ea9f483e0294 361 void DeviceClient::yield(int ms)
sathipal 2:199ddea804cd 362 {
lokeshhk 5:ea9f483e0294 363 if(mqttClient->isConnected())
sathipal 3:3d91bf839b49 364 {
lokeshhk 5:ea9f483e0294 365 mqttClient->yield(ms);
sathipal 0:f86732d81998 366 }
sathipal 0:f86732d81998 367 }
sathipal 0:f86732d81998 368
sathipal 2:199ddea804cd 369 // Obtain DeviceId address
lokeshhk 5:ea9f483e0294 370 char* DeviceClient::getDeviceId(char* buf, int buflen)
lokeshhk 5:ea9f483e0294 371 {
lokeshhk 5:ea9f483e0294 372 if(this->deviceId == NULL || (strcmp("", this->deviceId) == 0))
sathipal 3:3d91bf839b49 373 {
sathipal 2:199ddea804cd 374 return getMac(buf, buflen);
sathipal 2:199ddea804cd 375 } else {
sathipal 2:199ddea804cd 376 return strncpy(buf, this->deviceId, buflen);
sathipal 2:199ddea804cd 377 }
sathipal 2:199ddea804cd 378 }
sathipal 0:f86732d81998 379 // Obtain MAC address
lokeshhk 5:ea9f483e0294 380 char* DeviceClient::getMac(char* buf, int buflen)
lokeshhk 5:ea9f483e0294 381 {
lokeshhk 5:ea9f483e0294 382 NetworkInterface* net = mqttNetwork->getEth();
lokeshhk 5:ea9f483e0294 383 strncpy(buf, net->get_mac_address(), buflen);
sathipal 0:f86732d81998 384
sathipal 0:f86732d81998 385 char* pos; // Remove colons from mac address
sathipal 0:f86732d81998 386 while ((pos = strchr(buf, ':')) != NULL)
sathipal 0:f86732d81998 387 memmove(pos, pos + 1, strlen(pos) + 1);
sathipal 0:f86732d81998 388 return buf;
lokeshhk 5:ea9f483e0294 389 }