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:
Fri Nov 06 09:01:29 2015 +0000
Revision:
1:31c93319bbd8
Parent:
0:f86732d81998
Added a GetDeviceId() method and hidden getMac()

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