Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: C12832 EthernetInterface LM75B MMA7660 MQTT mbed-rtos mbed
Fork of IBMIoTClientEthernetExample by
main.cpp
00001 /******************************************************************************* 00002 * Copyright (c) 2014 IBM Corp. 00003 * 00004 * All rights reserved. This program and the accompanying materials 00005 * are made available under the terms of the Eclipse Public License v1.0 00006 * and Eclipse Distribution License v1.0 which accompany this distribution. 00007 * 00008 * The Eclipse Public License is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * and the Eclipse Distribution License is available at 00011 * http://www.eclipse.org/org/documents/edl-v10.php. 00012 * 00013 * Contributors: 00014 * Sam Danbury - initial implementation 00015 * Ian Craggs - refactoring to remove STL and other changes 00016 * Sam Grove - added check for Ethernet cable. 00017 * Chris Styles - Added additional menu screen for software revision 00018 * 00019 * To do : 00020 * Add magnetometer sensor output to IoT data stream 00021 * 00022 *******************************************************************************/ 00023 00024 #include "LM75B.h" 00025 #include "MMA7660.h" 00026 #include "MQTTClient.h" 00027 #include "MQTTEthernet.h" 00028 #include "C12832.h" 00029 #include "Arial12x12.h" 00030 #include "rtos.h" 00031 00032 // Update this to the next number *before* a commit 00033 #define __APP_SW_REVISION__ "10" 00034 00035 // Configuration values needed to connect to IBM IoT Cloud 00036 #define ORG "quickstart" // For a registered connection, replace with your org 00037 #define ID "" // For a registered connection, replace with your id 00038 #define AUTH_TOKEN "" // For a registered connection, replace with your auth-token 00039 #define TYPE DEFAULT_TYPE_NAME // For a registered connection, replace with your type 00040 00041 #define MQTT_PORT 1883 00042 #define MQTT_TLS_PORT 8883 00043 #define IBM_IOT_PORT MQTT_PORT 00044 00045 #define MQTT_MAX_PACKET_SIZE 250 00046 00047 #if defined(TARGET_UBLOX_C027) 00048 #warning "Compiling for mbed C027" 00049 #include "C027.h" 00050 #elif defined(TARGET_LPC1768) 00051 #warning "Compiling for mbed LPC1768" 00052 #include "LPC1768.h" 00053 #elif defined(TARGET_K64F) 00054 #warning "Compiling for mbed K64F" 00055 #include "K64F.h" 00056 #endif 00057 00058 bool quickstartMode = true; 00059 char org[11] = ORG; 00060 char type[30] = TYPE; 00061 char id[30] = ID; // mac without colons 00062 char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode 00063 00064 bool connected = false; 00065 char* joystickPos = "CENTRE"; 00066 int blink_interval = 0; 00067 00068 00069 void off() 00070 { 00071 r = g = b = 1.0; // 1 is off, 0 is full brightness 00072 } 00073 00074 void red() 00075 { 00076 r = 0.7; g = 1.0; b = 1.0; // 1 is off, 0 is full brightness 00077 } 00078 00079 void yellow() 00080 { 00081 r = 0.7; g = 0.7; b = 1.0; // 1 is off, 0 is full brightness 00082 } 00083 00084 void green() 00085 { 00086 r = 1.0; g = 0.7; b = 1.0; // 1 is off, 0 is full brightness 00087 } 00088 00089 00090 void flashing_yellow(void const *args) 00091 { 00092 bool on = false; 00093 while (!connected) // flashing yellow only while connecting 00094 { 00095 on = !on; 00096 if (on) 00097 yellow(); 00098 else 00099 off(); 00100 wait(0.5); 00101 } 00102 } 00103 00104 00105 void flashing_red(void const *args) // to be used when the connection is lost 00106 { 00107 bool on = false; 00108 while (!connected) 00109 { 00110 on = !on; 00111 if (on) 00112 red(); 00113 else 00114 off(); 00115 wait(2.0); 00116 } 00117 } 00118 00119 00120 void printMenu(int menuItem) 00121 { 00122 lcd.cls(); 00123 lcd.locate(0,0); 00124 switch (menuItem) 00125 { 00126 case 0: 00127 lcd.printf("IBM IoT Cloud"); 00128 lcd.locate(0,16); 00129 lcd.printf("Scroll with joystick"); 00130 break; 00131 case 1: 00132 lcd.printf("Go to:"); 00133 lcd.locate(0,16); 00134 lcd.printf("http://ibm.biz/iotqstart"); 00135 break; 00136 case 2: 00137 lcd.printf("Device Identity:"); 00138 lcd.locate(0,16); 00139 lcd.printf("%s", id); 00140 break; 00141 case 3: 00142 lcd.printf("Status:"); 00143 lcd.locate(0,16); 00144 lcd.printf(connected ? "Connected" : "Disconnected"); 00145 break; 00146 case 4: 00147 lcd.printf("App version:"); 00148 lcd.locate(0,16); 00149 lcd.printf("%s",__APP_SW_REVISION__); 00150 break; 00151 } 00152 } 00153 00154 00155 void setMenu() 00156 { 00157 static int menuItem = 0; 00158 if (Down) 00159 { 00160 joystickPos = "DOWN"; 00161 if (menuItem >= 0 && menuItem < 4) 00162 printMenu(++menuItem); 00163 } 00164 else if (Left) 00165 joystickPos = "LEFT"; 00166 else if (Click) 00167 joystickPos = "CLICK"; 00168 else if (Up) 00169 { 00170 joystickPos = "UP"; 00171 if (menuItem <= 4 && menuItem > 0) 00172 printMenu(--menuItem); 00173 } 00174 else if (Right) 00175 joystickPos = "RIGHT"; 00176 else 00177 joystickPos = "CENTRE"; 00178 } 00179 00180 00181 /** 00182 * Display a message on the LCD screen prefixed with IBM IoT Cloud 00183 */ 00184 void displayMessage(char* message) 00185 { 00186 lcd.cls(); 00187 lcd.locate(0,0); 00188 lcd.printf("IBM IoT Cloud"); 00189 lcd.locate(0,16); 00190 lcd.printf(message); 00191 } 00192 00193 00194 int connect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) 00195 { 00196 const char* iot_ibm = ".messaging.internetofthings.ibmcloud.com"; 00197 00198 char hostname[strlen(org) + strlen(iot_ibm) + 1]; 00199 sprintf(hostname, "%s%s", org, iot_ibm); 00200 DEBUG("hostname is %s\n", hostname); 00201 int rc = ipstack->connect(hostname, IBM_IOT_PORT); 00202 if (rc != 0) 00203 return rc; 00204 00205 // Construct clientId - d:org:type:id 00206 char clientId[strlen(org) + strlen(type) + strlen(id) + 5]; 00207 sprintf(clientId, "d:%s:%s:%s", org, type, id); 00208 DEBUG("clientid is %s\n", clientId); 00209 00210 // MQTT Connect 00211 MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 00212 data.MQTTVersion = 3; 00213 data.clientID.cstring = clientId; 00214 00215 if (!quickstartMode) 00216 { 00217 data.username.cstring = "use-token-auth"; 00218 data.password.cstring = auth_token; 00219 } 00220 00221 if ((rc = client->connect(data)) == 0) 00222 { 00223 connected = true; 00224 green(); 00225 displayMessage("Connected"); 00226 wait(2); 00227 displayMessage("Scroll with joystick"); 00228 } 00229 return rc; 00230 } 00231 00232 00233 int getConnTimeout(int attemptNumber) 00234 { // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute 00235 // after 20 attempts, retry every 10 minutes 00236 return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600; 00237 } 00238 00239 00240 void attemptConnect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) 00241 { 00242 int retryAttempt = 0; 00243 connected = false; 00244 00245 // make sure a cable is connected before starting to connect 00246 while (!linkStatus()) { 00247 wait(1.0f); 00248 WARN("Ethernet link not present. Check cable connection\n"); 00249 } 00250 00251 while (connect(client, ipstack) != 0) 00252 { 00253 #if defined(TARGET_K64F) 00254 red(); 00255 #else 00256 Thread red_thread(flashing_red); 00257 #endif 00258 int timeout = getConnTimeout(++retryAttempt); 00259 WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout); 00260 00261 // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed 00262 // or maybe just add the proper members to do this disconnect and call attemptConnect(...) 00263 00264 // this works - reset the system when the retry count gets to a threshold 00265 if (retryAttempt == 5) 00266 NVIC_SystemReset(); 00267 else 00268 wait(timeout); 00269 } 00270 } 00271 00272 00273 int publish(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) 00274 { 00275 MQTT::Message message; 00276 char* pubTopic = "iot-2/evt/status/fmt/json"; 00277 00278 char buf[250]; 00279 sprintf(buf, 00280 "{\"d\":{\"myName\":\"IoT mbed\",\"accelX\":%0.4f,\"accelY\":%0.4f,\"accelZ\":%0.4f,\"temp\":%0.4f,\"joystick\":\"%s\",\"potentiometer1\":%0.4f,\"potentiometer2\":%0.4f}}", 00281 MMA.x(), MMA.y(), MMA.z(), sensor.temp(), joystickPos, ain1.read(), ain2.read()); 00282 message.qos = MQTT::QOS0; 00283 message.retained = false; 00284 message.dup = false; 00285 message.payload = (void*)buf; 00286 message.payloadlen = strlen(buf); 00287 00288 LOG("Publishing %s\n", buf); 00289 return client->publish(pubTopic, message); 00290 } 00291 00292 00293 #if defined(TARGET_K64F) 00294 int getUUID48(char* buf, int buflen) 00295 { 00296 unsigned int UUID_LOC_WORD0 = 0x40048060; 00297 unsigned int UUID_LOC_WORD1 = 0x4004805C; 00298 00299 // Fetch word 0 00300 uint32_t word0 = *(uint32_t *)UUID_LOC_WORD0; 00301 00302 // Fetch word 1 00303 // we only want bottom 16 bits of word1 (MAC bits 32-47) 00304 // and bit 9 forced to 1, bit 8 forced to 0 00305 // Locally administered MAC, reduced conflicts 00306 // http://en.wikipedia.org/wiki/MAC_address 00307 uint32_t word1 = *(uint32_t *)UUID_LOC_WORD1; 00308 word1 |= 0x00000200; 00309 word1 &= 0x0000FEFF; 00310 00311 int rc = snprintf(buf, buflen, "%4x%08x", word1, word0); // Device id must be in lower case 00312 00313 return rc; 00314 } 00315 #else 00316 char* getMac(EthernetInterface& eth, char* buf, int buflen) // Obtain MAC address 00317 { 00318 strncpy(buf, eth.getMACAddress(), buflen); 00319 00320 char* pos; // Remove colons from mac address 00321 while ((pos = strchr(buf, ':')) != NULL) 00322 memmove(pos, pos + 1, strlen(pos) + 1); 00323 return buf; 00324 } 00325 #endif 00326 00327 00328 void messageArrived(MQTT::MessageData& md) 00329 { 00330 MQTT::Message &message = md.message; 00331 char topic[md.topicName.lenstring.len + 1]; 00332 00333 sprintf(topic, "%.*s", md.topicName.lenstring.len, md.topicName.lenstring.data); 00334 00335 LOG("Message arrived on topic %s: %.*s\n", topic, message.payloadlen, message.payload); 00336 00337 // Command topic: iot-2/cmd/blink/fmt/json - cmd is the string between cmd/ and /fmt/ 00338 char* start = strstr(topic, "/cmd/") + 5; 00339 int len = strstr(topic, "/fmt/") - start; 00340 00341 if (memcmp(start, "blink", len) == 0) 00342 { 00343 char payload[message.payloadlen + 1]; 00344 sprintf(payload, "%.*s", message.payloadlen, (char*)message.payload); 00345 00346 char* pos = strchr(payload, '}'); 00347 if (pos != NULL) 00348 { 00349 *pos = '\0'; 00350 if ((pos = strchr(payload, ':')) != NULL) 00351 { 00352 int blink_rate = atoi(pos + 1); 00353 blink_interval = (blink_rate <= 0) ? 0 : (blink_rate > 50 ? 1 : 50/blink_rate); 00354 } 00355 } 00356 } 00357 else 00358 WARN("Unsupported command: %.*s\n", len, start); 00359 } 00360 00361 00362 int main() 00363 { 00364 quickstartMode = (strcmp(org, "quickstart") == 0); 00365 00366 lcd.set_font((unsigned char*) Arial12x12); // Set a nice font for the LCD screen 00367 00368 led2 = LED2_OFF; // K64F: turn off the main board LED 00369 00370 displayMessage("Connecting"); 00371 #if defined(TARGET_K64F) 00372 yellow(); // Don't flash on the K64F, because starting a thread causes the EthernetInterface init call to hang 00373 #else 00374 Thread yellow_thread(flashing_yellow); 00375 #endif 00376 00377 MQTTEthernet ipstack; 00378 MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack); 00379 00380 if (quickstartMode) 00381 { 00382 #if defined(TARGET_K64F) 00383 getUUID48(id, sizeof(id)); // getMac doesn't work on the K64F 00384 #else 00385 getMac(ipstack.getEth(), id, sizeof(id)); 00386 #endif 00387 } 00388 00389 attemptConnect(&client, &ipstack); 00390 00391 if (!quickstartMode) 00392 { 00393 int rc = 0; 00394 if ((rc = client.subscribe("iot-2/cmd/+/fmt/json", MQTT::QOS1, messageArrived)) != 0) 00395 WARN("rc from MQTT subscribe is %d\n", rc); 00396 } 00397 00398 blink_interval = 0; 00399 int count = 0; 00400 while (true) 00401 { 00402 if (++count == 100) 00403 { // Publish a message every second 00404 if (publish(&client, &ipstack) != 0) 00405 attemptConnect(&client, &ipstack); // if we have lost the connection 00406 count = 0; 00407 } 00408 00409 if (blink_interval == 0) 00410 led2 = LED2_OFF; 00411 else if (count % blink_interval == 0) 00412 led2 = !led2; 00413 if (count % 20 == 0) 00414 setMenu(); 00415 client.yield(10); // allow the MQTT client to receive messages 00416 } 00417 }
Generated on Thu Jul 21 2022 15:37:24 by
1.7.2
