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

Dependencies:   MQTT

Committer:
lamell
Date:
Mon Sep 14 18:32:15 2020 -0400
Revision:
29:40cc05c6c14b
Parent:
27:3806829a0247
No changes

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