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:
sathipal
Date:
Mon Mar 20 10:07:49 2017 +0000
Revision:
4:7be77f2f6a71
Parent:
3:3d91bf839b49
Child:
5:ea9f483e0294
Modified descrption

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