IoT based security system that detects suspicious movements through a motion detector and alerts the user on their gmail. In the presence of motion sensed between 7 to 9 times, the Grove PIR sensor sends an input to the board which is connected to internet via Ethernet. The board publishes the sensor data on IBM IoT foundation, which is known as IBM Watson. The data is then sent to IBM Bluemix which provides real time analysis and the remote time data management and monitoring. For more information : https://developer.ibm.com/recipes/tutorials/mbed-c-client-library-for-ibm-iot-foundation/

Dependencies:   C12832 EthernetInterface LM75B MMA7660 MQTT mbed-rtos mbed

Fork of IBMIoTClientEthernetExample by IBM Watson IoT

Committer:
icraggs
Date:
Wed Aug 12 20:50:56 2015 +0000
Revision:
18:94da9de96d54
Parent:
17:74801ec6a672
Child:
19:ee5e5c9573e5
Stop the display flashing unnecessarily

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samdanbury 6:37b6d0d56190 1 /*******************************************************************************
icraggs 16:2420bfbf5f1c 2 * Copyright (c) 2014, 2015 IBM Corp.
samdanbury 6:37b6d0d56190 3 *
samdanbury 6:37b6d0d56190 4 * All rights reserved. This program and the accompanying materials
samdanbury 6:37b6d0d56190 5 * are made available under the terms of the Eclipse Public License v1.0
samdanbury 6:37b6d0d56190 6 * and Eclipse Distribution License v1.0 which accompany this distribution.
samdanbury 6:37b6d0d56190 7 *
samdanbury 6:37b6d0d56190 8 * The Eclipse Public License is available at
samdanbury 6:37b6d0d56190 9 * http://www.eclipse.org/legal/epl-v10.html
samdanbury 6:37b6d0d56190 10 * and the Eclipse Distribution License is available at
samdanbury 6:37b6d0d56190 11 * http://www.eclipse.org/org/documents/edl-v10.php.
samdanbury 6:37b6d0d56190 12 *
samdanbury 6:37b6d0d56190 13 * Contributors:
samdanbury 6:37b6d0d56190 14 * Sam Danbury - initial implementation
samdanbury 6:37b6d0d56190 15 * Ian Craggs - refactoring to remove STL and other changes
icraggs 8:80d49dd91542 16 * Sam Grove - added check for Ethernet cable.
chris 10:0b5e0dfee08e 17 * Chris Styles - Added additional menu screen for software revision
icraggs 16:2420bfbf5f1c 18 * James Sutton - Mac fix and extra debug
icraggs 16:2420bfbf5f1c 19 * Ian Craggs - add not authorized messages
chris 10:0b5e0dfee08e 20 *
chris 10:0b5e0dfee08e 21 * To do :
chris 10:0b5e0dfee08e 22 * Add magnetometer sensor output to IoT data stream
chris 10:0b5e0dfee08e 23 *
samdanbury 6:37b6d0d56190 24 *******************************************************************************/
samdanbury 6:37b6d0d56190 25
samdanbury 6:37b6d0d56190 26 #include "LM75B.h"
samdanbury 6:37b6d0d56190 27 #include "MMA7660.h"
samdanbury 6:37b6d0d56190 28 #include "MQTTClient.h"
samdanbury 6:37b6d0d56190 29 #include "MQTTEthernet.h"
samdanbury 6:37b6d0d56190 30 #include "C12832.h"
samdanbury 6:37b6d0d56190 31 #include "Arial12x12.h"
samdanbury 6:37b6d0d56190 32 #include "rtos.h"
samdanbury 6:37b6d0d56190 33
chris 10:0b5e0dfee08e 34 // Update this to the next number *before* a commit
icraggs 18:94da9de96d54 35 #define __APP_SW_REVISION__ "18"
chris 10:0b5e0dfee08e 36
samdanbury 6:37b6d0d56190 37 // Configuration values needed to connect to IBM IoT Cloud
icraggs 8:80d49dd91542 38 #define ORG "quickstart" // For a registered connection, replace with your org
icraggs 8:80d49dd91542 39 #define ID "" // For a registered connection, replace with your id
icraggs 8:80d49dd91542 40 #define AUTH_TOKEN "" // For a registered connection, replace with your auth-token
icraggs 8:80d49dd91542 41 #define TYPE DEFAULT_TYPE_NAME // For a registered connection, replace with your type
samdanbury 6:37b6d0d56190 42
samdanbury 6:37b6d0d56190 43 #define MQTT_PORT 1883
samdanbury 6:37b6d0d56190 44 #define MQTT_TLS_PORT 8883
samdanbury 6:37b6d0d56190 45 #define IBM_IOT_PORT MQTT_PORT
samdanbury 6:37b6d0d56190 46
samdanbury 6:37b6d0d56190 47 #define MQTT_MAX_PACKET_SIZE 250
samdanbury 6:37b6d0d56190 48
mazgch 11:7a6df9a2dcdc 49 #if defined(TARGET_UBLOX_C027)
mazgch 11:7a6df9a2dcdc 50 #warning "Compiling for mbed C027"
mazgch 11:7a6df9a2dcdc 51 #include "C027.h"
mazgch 11:7a6df9a2dcdc 52 #elif defined(TARGET_LPC1768)
samdanbury 6:37b6d0d56190 53 #warning "Compiling for mbed LPC1768"
samdanbury 6:37b6d0d56190 54 #include "LPC1768.h"
samdanbury 6:37b6d0d56190 55 #elif defined(TARGET_K64F)
samdanbury 6:37b6d0d56190 56 #warning "Compiling for mbed K64F"
samdanbury 6:37b6d0d56190 57 #include "K64F.h"
samdanbury 6:37b6d0d56190 58 #endif
samdanbury 6:37b6d0d56190 59
jsutton 14:1f961d19f3cf 60
icraggs 8:80d49dd91542 61 bool quickstartMode = true;
samdanbury 6:37b6d0d56190 62 char org[11] = ORG;
samdanbury 6:37b6d0d56190 63 char type[30] = TYPE;
samdanbury 6:37b6d0d56190 64 char id[30] = ID; // mac without colons
samdanbury 6:37b6d0d56190 65 char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode
samdanbury 6:37b6d0d56190 66
samdanbury 6:37b6d0d56190 67 bool connected = false;
jsutton 14:1f961d19f3cf 68 bool mqttConnecting = false;
jsutton 14:1f961d19f3cf 69 bool netConnected = false;
jsutton 14:1f961d19f3cf 70 bool netConnecting = false;
jsutton 14:1f961d19f3cf 71 bool ethernetInitialising = true;
icraggs 16:2420bfbf5f1c 72 int connack_rc = 0; // MQTT connack return code
jsutton 14:1f961d19f3cf 73 int retryAttempt = 0;
jsutton 14:1f961d19f3cf 74 int menuItem = 0;
jsutton 14:1f961d19f3cf 75
samdanbury 6:37b6d0d56190 76 char* joystickPos = "CENTRE";
samdanbury 6:37b6d0d56190 77 int blink_interval = 0;
samdanbury 6:37b6d0d56190 78
jsutton 13:85801e3b83d3 79 char* ip_addr = "";
jsutton 13:85801e3b83d3 80 char* gateway_addr = "";
jsutton 14:1f961d19f3cf 81 char* host_addr = "";
jsutton 14:1f961d19f3cf 82 int connectTimeout = 1000;
jsutton 14:1f961d19f3cf 83
jsutton 14:1f961d19f3cf 84 // If we wanted to manually set the MAC address,
jsutton 14:1f961d19f3cf 85 // this is how to do it. In this example, we take
jsutton 14:1f961d19f3cf 86 // the original Mbed Set MAC address and combine it
jsutton 14:1f961d19f3cf 87 // with a prefix of our choosing.
jsutton 14:1f961d19f3cf 88 /*
jsutton 14:1f961d19f3cf 89 extern "C" void $Super$$mbed_mac_address(char *s);
jsutton 14:1f961d19f3cf 90 extern "C" void $Sub$$mbed_mac_address(char *s)
jsutton 14:1f961d19f3cf 91 {
jsutton 15:09458079f4bb 92 char originalMAC[6] = "";
jsutton 15:09458079f4bb 93 $Super$$mbed_mac_address(originalMAC);
jsutton 14:1f961d19f3cf 94
jsutton 14:1f961d19f3cf 95 char mac[6];
jsutton 14:1f961d19f3cf 96 mac[0] = 0x00;
jsutton 14:1f961d19f3cf 97 mac[1] = 0x08;
jsutton 14:1f961d19f3cf 98 mac[2] = 0xdc;
jsutton 15:09458079f4bb 99 mac[3] = originalMAC[3];
jsutton 15:09458079f4bb 100 mac[4] = originalMAC[4];
jsutton 15:09458079f4bb 101 mac[5] = originalMAC[5];
jsutton 14:1f961d19f3cf 102 memcpy(s, mac, 6);
jsutton 14:1f961d19f3cf 103 }
jsutton 14:1f961d19f3cf 104 */
jsutton 13:85801e3b83d3 105
samdanbury 6:37b6d0d56190 106
samdanbury 6:37b6d0d56190 107 void off()
samdanbury 6:37b6d0d56190 108 {
samdanbury 6:37b6d0d56190 109 r = g = b = 1.0; // 1 is off, 0 is full brightness
samdanbury 6:37b6d0d56190 110 }
samdanbury 6:37b6d0d56190 111
samdanbury 6:37b6d0d56190 112 void red()
samdanbury 6:37b6d0d56190 113 {
samdanbury 6:37b6d0d56190 114 r = 0.7; g = 1.0; b = 1.0; // 1 is off, 0 is full brightness
samdanbury 6:37b6d0d56190 115 }
samdanbury 6:37b6d0d56190 116
samdanbury 6:37b6d0d56190 117 void yellow()
samdanbury 6:37b6d0d56190 118 {
samdanbury 6:37b6d0d56190 119 r = 0.7; g = 0.7; b = 1.0; // 1 is off, 0 is full brightness
samdanbury 6:37b6d0d56190 120 }
samdanbury 6:37b6d0d56190 121
samdanbury 6:37b6d0d56190 122 void green()
samdanbury 6:37b6d0d56190 123 {
samdanbury 6:37b6d0d56190 124 r = 1.0; g = 0.7; b = 1.0; // 1 is off, 0 is full brightness
samdanbury 6:37b6d0d56190 125 }
samdanbury 6:37b6d0d56190 126
samdanbury 6:37b6d0d56190 127
samdanbury 6:37b6d0d56190 128 void flashing_yellow(void const *args)
samdanbury 6:37b6d0d56190 129 {
samdanbury 6:37b6d0d56190 130 bool on = false;
icraggs 16:2420bfbf5f1c 131 while (!connected && connack_rc != MQTT_NOT_AUTHORIZED && connack_rc != MQTT_BAD_USERNAME_OR_PASSWORD) // flashing yellow only while connecting
samdanbury 6:37b6d0d56190 132 {
samdanbury 6:37b6d0d56190 133 on = !on;
samdanbury 6:37b6d0d56190 134 if (on)
samdanbury 6:37b6d0d56190 135 yellow();
samdanbury 6:37b6d0d56190 136 else
samdanbury 6:37b6d0d56190 137 off();
samdanbury 6:37b6d0d56190 138 wait(0.5);
samdanbury 6:37b6d0d56190 139 }
samdanbury 6:37b6d0d56190 140 }
samdanbury 6:37b6d0d56190 141
samdanbury 6:37b6d0d56190 142
samdanbury 6:37b6d0d56190 143 void flashing_red(void const *args) // to be used when the connection is lost
samdanbury 6:37b6d0d56190 144 {
samdanbury 6:37b6d0d56190 145 bool on = false;
samdanbury 6:37b6d0d56190 146 while (!connected)
samdanbury 6:37b6d0d56190 147 {
samdanbury 6:37b6d0d56190 148 on = !on;
samdanbury 6:37b6d0d56190 149 if (on)
samdanbury 6:37b6d0d56190 150 red();
samdanbury 6:37b6d0d56190 151 else
samdanbury 6:37b6d0d56190 152 off();
samdanbury 6:37b6d0d56190 153 wait(2.0);
samdanbury 6:37b6d0d56190 154 }
samdanbury 6:37b6d0d56190 155 }
samdanbury 6:37b6d0d56190 156
samdanbury 6:37b6d0d56190 157
samdanbury 6:37b6d0d56190 158 void printMenu(int menuItem)
samdanbury 6:37b6d0d56190 159 {
icraggs 18:94da9de96d54 160 static char last_line1[30] = "", last_line2[30] = "";
icraggs 18:94da9de96d54 161 char line1[30] = "", line2[30] = "";
icraggs 18:94da9de96d54 162
samdanbury 6:37b6d0d56190 163 switch (menuItem)
samdanbury 6:37b6d0d56190 164 {
samdanbury 6:37b6d0d56190 165 case 0:
icraggs 18:94da9de96d54 166 sprintf(line1, "IBM IoT Cloud");
icraggs 18:94da9de96d54 167 sprintf(line2, "Scroll with joystick");
samdanbury 6:37b6d0d56190 168 break;
samdanbury 6:37b6d0d56190 169 case 1:
icraggs 18:94da9de96d54 170 sprintf(line1, "Go to:");
icraggs 18:94da9de96d54 171 sprintf(line2, "http://ibm.biz/iotqstart");
samdanbury 6:37b6d0d56190 172 break;
samdanbury 6:37b6d0d56190 173 case 2:
icraggs 18:94da9de96d54 174 sprintf(line1, "Device Identity:");
icraggs 18:94da9de96d54 175 sprintf(line2, "%s", id);
samdanbury 6:37b6d0d56190 176 break;
samdanbury 6:37b6d0d56190 177 case 3:
icraggs 18:94da9de96d54 178 sprintf(line1, "MQTT Status:");
icraggs 16:2420bfbf5f1c 179 if (mqttConnecting)
icraggs 18:94da9de96d54 180 sprintf(line2, "Connecting... %d/5", retryAttempt);
icraggs 16:2420bfbf5f1c 181 else
icraggs 16:2420bfbf5f1c 182 {
icraggs 16:2420bfbf5f1c 183 if (connected)
icraggs 18:94da9de96d54 184 sprintf(line2, "Connected");
icraggs 16:2420bfbf5f1c 185 else
icraggs 16:2420bfbf5f1c 186 {
icraggs 16:2420bfbf5f1c 187 switch (connack_rc)
icraggs 16:2420bfbf5f1c 188 {
icraggs 16:2420bfbf5f1c 189 case MQTT_CLIENTID_REJECTED:
icraggs 18:94da9de96d54 190 sprintf(line2, "Clientid rejected");
icraggs 16:2420bfbf5f1c 191 break;
icraggs 16:2420bfbf5f1c 192 case MQTT_BAD_USERNAME_OR_PASSWORD:
icraggs 18:94da9de96d54 193 sprintf(line2, "Invalid username or password");
icraggs 16:2420bfbf5f1c 194 break;
icraggs 16:2420bfbf5f1c 195 case MQTT_NOT_AUTHORIZED:
icraggs 18:94da9de96d54 196 sprintf(line2, "Not authorized");
icraggs 16:2420bfbf5f1c 197 break;
icraggs 16:2420bfbf5f1c 198 default:
icraggs 18:94da9de96d54 199 sprintf(line2, "Disconnected");
icraggs 16:2420bfbf5f1c 200 }
icraggs 16:2420bfbf5f1c 201 }
jsutton 14:1f961d19f3cf 202 }
samdanbury 6:37b6d0d56190 203 break;
chris 10:0b5e0dfee08e 204 case 4:
icraggs 18:94da9de96d54 205 sprintf(line1, "Ethernet State:");
icraggs 18:94da9de96d54 206 sprintf(line2, ethernetInitialising ? "Initializing..." : "Initialized");
jsutton 14:1f961d19f3cf 207 break;
jsutton 14:1f961d19f3cf 208 case 5:
icraggs 18:94da9de96d54 209 sprintf(line1, "Socket State:");
icraggs 16:2420bfbf5f1c 210 if (netConnecting)
icraggs 18:94da9de96d54 211 sprintf(line2, "Connecting... %d/5", retryAttempt);
icraggs 16:2420bfbf5f1c 212 else
icraggs 18:94da9de96d54 213 sprintf(line2, netConnected ? "Connected" : "Disconnected");
jsutton 13:85801e3b83d3 214 break;
jsutton 14:1f961d19f3cf 215 case 6:
icraggs 18:94da9de96d54 216 sprintf(line1, "IP Address:");
icraggs 18:94da9de96d54 217 sprintf(line2, "%s", ip_addr);
jsutton 13:85801e3b83d3 218 break;
jsutton 14:1f961d19f3cf 219 case 7:
icraggs 18:94da9de96d54 220 sprintf(line1, "Gateway:");
icraggs 18:94da9de96d54 221 sprintf(line2, "%s", gateway_addr);
jsutton 13:85801e3b83d3 222 break;
jsutton 14:1f961d19f3cf 223 case 8:
icraggs 18:94da9de96d54 224 sprintf(line1, "App version:");
icraggs 18:94da9de96d54 225 sprintf(line2, "%s", __APP_SW_REVISION__);
chris 10:0b5e0dfee08e 226 break;
jsutton 14:1f961d19f3cf 227 case 9:
icraggs 18:94da9de96d54 228 sprintf(line1, "Current Timeout:");
icraggs 18:94da9de96d54 229 sprintf(line2, "%d ms", connectTimeout);
jsutton 14:1f961d19f3cf 230 break;
samdanbury 6:37b6d0d56190 231 }
icraggs 18:94da9de96d54 232
icraggs 18:94da9de96d54 233 if (strcmp(line1, last_line1) != 0 || strcmp(line2, last_line2) != 0)
icraggs 18:94da9de96d54 234 {
icraggs 18:94da9de96d54 235 lcd.cls();
icraggs 18:94da9de96d54 236 lcd.locate(0, 0);
icraggs 18:94da9de96d54 237 lcd.printf(line1);
icraggs 18:94da9de96d54 238 strncpy(last_line1, line1, sizeof(last_line1));
icraggs 18:94da9de96d54 239
icraggs 18:94da9de96d54 240 lcd.locate(0,16);
icraggs 18:94da9de96d54 241 lcd.printf(line2);
icraggs 18:94da9de96d54 242 strncpy(last_line2, line2, sizeof(last_line2));
icraggs 18:94da9de96d54 243 }
samdanbury 6:37b6d0d56190 244 }
samdanbury 6:37b6d0d56190 245
samdanbury 6:37b6d0d56190 246
samdanbury 6:37b6d0d56190 247 void setMenu()
samdanbury 6:37b6d0d56190 248 {
jsutton 14:1f961d19f3cf 249
samdanbury 6:37b6d0d56190 250 if (Down)
samdanbury 6:37b6d0d56190 251 {
samdanbury 6:37b6d0d56190 252 joystickPos = "DOWN";
jsutton 14:1f961d19f3cf 253 if (menuItem >= 0 && menuItem < 9)
samdanbury 6:37b6d0d56190 254 printMenu(++menuItem);
samdanbury 6:37b6d0d56190 255 }
samdanbury 6:37b6d0d56190 256 else if (Left)
samdanbury 6:37b6d0d56190 257 joystickPos = "LEFT";
samdanbury 6:37b6d0d56190 258 else if (Click)
samdanbury 6:37b6d0d56190 259 joystickPos = "CLICK";
samdanbury 6:37b6d0d56190 260 else if (Up)
samdanbury 6:37b6d0d56190 261 {
samdanbury 6:37b6d0d56190 262 joystickPos = "UP";
jsutton 14:1f961d19f3cf 263 if (menuItem <= 9 && menuItem > 0)
samdanbury 6:37b6d0d56190 264 printMenu(--menuItem);
samdanbury 6:37b6d0d56190 265 }
samdanbury 6:37b6d0d56190 266 else if (Right)
samdanbury 6:37b6d0d56190 267 joystickPos = "RIGHT";
samdanbury 6:37b6d0d56190 268 else
samdanbury 6:37b6d0d56190 269 joystickPos = "CENTRE";
samdanbury 6:37b6d0d56190 270 }
samdanbury 6:37b6d0d56190 271
jsutton 13:85801e3b83d3 272 void menu_loop(void const *args)
jsutton 13:85801e3b83d3 273 {
jsutton 14:1f961d19f3cf 274 int count = 0;
icraggs 16:2420bfbf5f1c 275 while(true)
icraggs 16:2420bfbf5f1c 276 {
jsutton 13:85801e3b83d3 277 setMenu();
icraggs 16:2420bfbf5f1c 278 if (++count % 10 == 0)
jsutton 14:1f961d19f3cf 279 printMenu(menuItem);
jsutton 14:1f961d19f3cf 280 Thread::wait(100);
jsutton 13:85801e3b83d3 281 }
jsutton 13:85801e3b83d3 282 }
jsutton 13:85801e3b83d3 283
samdanbury 6:37b6d0d56190 284
samdanbury 6:37b6d0d56190 285 /**
samdanbury 6:37b6d0d56190 286 * Display a message on the LCD screen prefixed with IBM IoT Cloud
samdanbury 6:37b6d0d56190 287 */
samdanbury 6:37b6d0d56190 288 void displayMessage(char* message)
samdanbury 6:37b6d0d56190 289 {
samdanbury 6:37b6d0d56190 290 lcd.cls();
samdanbury 6:37b6d0d56190 291 lcd.locate(0,0);
samdanbury 6:37b6d0d56190 292 lcd.printf("IBM IoT Cloud");
samdanbury 6:37b6d0d56190 293 lcd.locate(0,16);
samdanbury 6:37b6d0d56190 294 lcd.printf(message);
samdanbury 6:37b6d0d56190 295 }
samdanbury 6:37b6d0d56190 296
samdanbury 6:37b6d0d56190 297
samdanbury 6:37b6d0d56190 298 int connect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack)
samdanbury 6:37b6d0d56190 299 {
samdanbury 6:37b6d0d56190 300 const char* iot_ibm = ".messaging.internetofthings.ibmcloud.com";
samdanbury 6:37b6d0d56190 301
samdanbury 6:37b6d0d56190 302 char hostname[strlen(org) + strlen(iot_ibm) + 1];
samdanbury 6:37b6d0d56190 303 sprintf(hostname, "%s%s", org, iot_ibm);
jsutton 13:85801e3b83d3 304 EthernetInterface& eth = ipstack->getEth();
jsutton 13:85801e3b83d3 305 ip_addr = eth.getIPAddress();
jsutton 13:85801e3b83d3 306 gateway_addr = eth.getGateway();
jsutton 14:1f961d19f3cf 307
jsutton 14:1f961d19f3cf 308 // Construct clientId - d:org:type:id
jsutton 14:1f961d19f3cf 309 char clientId[strlen(org) + strlen(type) + strlen(id) + 5];
jsutton 14:1f961d19f3cf 310 sprintf(clientId, "d:%s:%s:%s", org, type, id);
jsutton 14:1f961d19f3cf 311
icraggs 16:2420bfbf5f1c 312 // Network debug statements
jsutton 14:1f961d19f3cf 313 LOG("=====================================\n");
jsutton 14:1f961d19f3cf 314 LOG("Connecting Ethernet.\n");
jsutton 14:1f961d19f3cf 315 LOG("IP ADDRESS: %s\n", eth.getIPAddress());
jsutton 14:1f961d19f3cf 316 LOG("MAC ADDRESS: %s\n", eth.getMACAddress());
jsutton 14:1f961d19f3cf 317 LOG("Gateway: %s\n", eth.getGateway());
jsutton 14:1f961d19f3cf 318 LOG("Network Mask: %s\n", eth.getNetworkMask());
jsutton 14:1f961d19f3cf 319 LOG("Server Hostname: %s\n", hostname);
jsutton 14:1f961d19f3cf 320 LOG("Client ID: %s\n", clientId);
jsutton 14:1f961d19f3cf 321 LOG("=====================================\n");
jsutton 14:1f961d19f3cf 322
jsutton 14:1f961d19f3cf 323 netConnecting = true;
jsutton 14:1f961d19f3cf 324 int rc = ipstack->connect(hostname, IBM_IOT_PORT, connectTimeout);
icraggs 16:2420bfbf5f1c 325 if (rc != 0)
icraggs 16:2420bfbf5f1c 326 {
icraggs 18:94da9de96d54 327 WARN("IP Stack connect returned: %d\n", rc);
samdanbury 6:37b6d0d56190 328 return rc;
jsutton 13:85801e3b83d3 329 }
jsutton 13:85801e3b83d3 330 netConnected = true;
jsutton 14:1f961d19f3cf 331 netConnecting = false;
jsutton 14:1f961d19f3cf 332
samdanbury 6:37b6d0d56190 333 // MQTT Connect
jsutton 14:1f961d19f3cf 334 mqttConnecting = true;
samdanbury 6:37b6d0d56190 335 MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
samdanbury 6:37b6d0d56190 336 data.MQTTVersion = 3;
samdanbury 6:37b6d0d56190 337 data.clientID.cstring = clientId;
samdanbury 6:37b6d0d56190 338
samdanbury 6:37b6d0d56190 339 if (!quickstartMode)
samdanbury 6:37b6d0d56190 340 {
samdanbury 6:37b6d0d56190 341 data.username.cstring = "use-token-auth";
samdanbury 6:37b6d0d56190 342 data.password.cstring = auth_token;
samdanbury 6:37b6d0d56190 343 }
samdanbury 6:37b6d0d56190 344
icraggs 8:80d49dd91542 345 if ((rc = client->connect(data)) == 0)
samdanbury 6:37b6d0d56190 346 {
samdanbury 6:37b6d0d56190 347 connected = true;
samdanbury 6:37b6d0d56190 348 green();
samdanbury 6:37b6d0d56190 349 displayMessage("Connected");
jsutton 13:85801e3b83d3 350 wait(1);
samdanbury 6:37b6d0d56190 351 displayMessage("Scroll with joystick");
samdanbury 6:37b6d0d56190 352 }
icraggs 16:2420bfbf5f1c 353 else
icraggs 16:2420bfbf5f1c 354 WARN("MQTT connect returned %d\n", rc);
icraggs 16:2420bfbf5f1c 355 if (rc >= 0)
icraggs 16:2420bfbf5f1c 356 connack_rc = rc;
jsutton 14:1f961d19f3cf 357 mqttConnecting = false;
samdanbury 6:37b6d0d56190 358 return rc;
samdanbury 6:37b6d0d56190 359 }
samdanbury 6:37b6d0d56190 360
samdanbury 6:37b6d0d56190 361
samdanbury 6:37b6d0d56190 362 int getConnTimeout(int attemptNumber)
samdanbury 6:37b6d0d56190 363 { // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute
samdanbury 6:37b6d0d56190 364 // after 20 attempts, retry every 10 minutes
samdanbury 6:37b6d0d56190 365 return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600;
samdanbury 6:37b6d0d56190 366 }
samdanbury 6:37b6d0d56190 367
samdanbury 6:37b6d0d56190 368
samdanbury 6:37b6d0d56190 369 void attemptConnect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack)
samdanbury 6:37b6d0d56190 370 {
samdanbury 6:37b6d0d56190 371 connected = false;
icraggs 16:2420bfbf5f1c 372
icraggs 8:80d49dd91542 373 // make sure a cable is connected before starting to connect
icraggs 16:2420bfbf5f1c 374 while (!linkStatus())
icraggs 16:2420bfbf5f1c 375 {
icraggs 8:80d49dd91542 376 wait(1.0f);
icraggs 8:80d49dd91542 377 WARN("Ethernet link not present. Check cable connection\n");
icraggs 8:80d49dd91542 378 }
samdanbury 6:37b6d0d56190 379
icraggs 16:2420bfbf5f1c 380 while (connect(client, ipstack) != MQTT_CONNECTION_ACCEPTED)
samdanbury 6:37b6d0d56190 381 {
icraggs 16:2420bfbf5f1c 382 if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD)
icraggs 16:2420bfbf5f1c 383 return; // don't reattempt to connect if credentials are wrong
icraggs 16:2420bfbf5f1c 384
samdanbury 6:37b6d0d56190 385 Thread red_thread(flashing_red);
chris 12:8b480eb8a496 386
samdanbury 6:37b6d0d56190 387 int timeout = getConnTimeout(++retryAttempt);
samdanbury 6:37b6d0d56190 388 WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout);
icraggs 8:80d49dd91542 389
icraggs 8:80d49dd91542 390 // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed
icraggs 8:80d49dd91542 391 // or maybe just add the proper members to do this disconnect and call attemptConnect(...)
icraggs 8:80d49dd91542 392
icraggs 8:80d49dd91542 393 // this works - reset the system when the retry count gets to a threshold
icraggs 8:80d49dd91542 394 if (retryAttempt == 5)
icraggs 8:80d49dd91542 395 NVIC_SystemReset();
icraggs 8:80d49dd91542 396 else
icraggs 8:80d49dd91542 397 wait(timeout);
samdanbury 6:37b6d0d56190 398 }
samdanbury 6:37b6d0d56190 399 }
samdanbury 6:37b6d0d56190 400
samdanbury 6:37b6d0d56190 401
samdanbury 6:37b6d0d56190 402 int publish(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack)
samdanbury 6:37b6d0d56190 403 {
samdanbury 6:37b6d0d56190 404 MQTT::Message message;
samdanbury 6:37b6d0d56190 405 char* pubTopic = "iot-2/evt/status/fmt/json";
samdanbury 6:37b6d0d56190 406
samdanbury 6:37b6d0d56190 407 char buf[250];
samdanbury 6:37b6d0d56190 408 sprintf(buf,
samdanbury 6:37b6d0d56190 409 "{\"d\":{\"myName\":\"IoT mbed\",\"accelX\":%0.4f,\"accelY\":%0.4f,\"accelZ\":%0.4f,\"temp\":%0.4f,\"joystick\":\"%s\",\"potentiometer1\":%0.4f,\"potentiometer2\":%0.4f}}",
samdanbury 6:37b6d0d56190 410 MMA.x(), MMA.y(), MMA.z(), sensor.temp(), joystickPos, ain1.read(), ain2.read());
samdanbury 6:37b6d0d56190 411 message.qos = MQTT::QOS0;
samdanbury 6:37b6d0d56190 412 message.retained = false;
samdanbury 6:37b6d0d56190 413 message.dup = false;
samdanbury 6:37b6d0d56190 414 message.payload = (void*)buf;
samdanbury 6:37b6d0d56190 415 message.payloadlen = strlen(buf);
samdanbury 6:37b6d0d56190 416
samdanbury 6:37b6d0d56190 417 LOG("Publishing %s\n", buf);
icraggs 8:80d49dd91542 418 return client->publish(pubTopic, message);
samdanbury 6:37b6d0d56190 419 }
samdanbury 6:37b6d0d56190 420
samdanbury 6:37b6d0d56190 421
samdanbury 6:37b6d0d56190 422 char* getMac(EthernetInterface& eth, char* buf, int buflen) // Obtain MAC address
samdanbury 6:37b6d0d56190 423 {
samdanbury 6:37b6d0d56190 424 strncpy(buf, eth.getMACAddress(), buflen);
samdanbury 6:37b6d0d56190 425
samdanbury 6:37b6d0d56190 426 char* pos; // Remove colons from mac address
samdanbury 6:37b6d0d56190 427 while ((pos = strchr(buf, ':')) != NULL)
samdanbury 6:37b6d0d56190 428 memmove(pos, pos + 1, strlen(pos) + 1);
samdanbury 6:37b6d0d56190 429 return buf;
samdanbury 6:37b6d0d56190 430 }
chris 12:8b480eb8a496 431
samdanbury 6:37b6d0d56190 432
samdanbury 6:37b6d0d56190 433 void messageArrived(MQTT::MessageData& md)
samdanbury 6:37b6d0d56190 434 {
samdanbury 6:37b6d0d56190 435 MQTT::Message &message = md.message;
samdanbury 6:37b6d0d56190 436 char topic[md.topicName.lenstring.len + 1];
samdanbury 6:37b6d0d56190 437
samdanbury 6:37b6d0d56190 438 sprintf(topic, "%.*s", md.topicName.lenstring.len, md.topicName.lenstring.data);
samdanbury 6:37b6d0d56190 439
samdanbury 6:37b6d0d56190 440 LOG("Message arrived on topic %s: %.*s\n", topic, message.payloadlen, message.payload);
samdanbury 6:37b6d0d56190 441
samdanbury 6:37b6d0d56190 442 // Command topic: iot-2/cmd/blink/fmt/json - cmd is the string between cmd/ and /fmt/
samdanbury 6:37b6d0d56190 443 char* start = strstr(topic, "/cmd/") + 5;
samdanbury 6:37b6d0d56190 444 int len = strstr(topic, "/fmt/") - start;
samdanbury 6:37b6d0d56190 445
samdanbury 6:37b6d0d56190 446 if (memcmp(start, "blink", len) == 0)
samdanbury 6:37b6d0d56190 447 {
samdanbury 6:37b6d0d56190 448 char payload[message.payloadlen + 1];
samdanbury 6:37b6d0d56190 449 sprintf(payload, "%.*s", message.payloadlen, (char*)message.payload);
samdanbury 6:37b6d0d56190 450
samdanbury 6:37b6d0d56190 451 char* pos = strchr(payload, '}');
samdanbury 6:37b6d0d56190 452 if (pos != NULL)
samdanbury 6:37b6d0d56190 453 {
samdanbury 6:37b6d0d56190 454 *pos = '\0';
samdanbury 6:37b6d0d56190 455 if ((pos = strchr(payload, ':')) != NULL)
samdanbury 6:37b6d0d56190 456 {
samdanbury 6:37b6d0d56190 457 int blink_rate = atoi(pos + 1);
samdanbury 6:37b6d0d56190 458 blink_interval = (blink_rate <= 0) ? 0 : (blink_rate > 50 ? 1 : 50/blink_rate);
samdanbury 6:37b6d0d56190 459 }
samdanbury 6:37b6d0d56190 460 }
samdanbury 6:37b6d0d56190 461 }
samdanbury 6:37b6d0d56190 462 else
samdanbury 6:37b6d0d56190 463 WARN("Unsupported command: %.*s\n", len, start);
samdanbury 6:37b6d0d56190 464 }
samdanbury 6:37b6d0d56190 465
samdanbury 6:37b6d0d56190 466
samdanbury 6:37b6d0d56190 467 int main()
samdanbury 6:37b6d0d56190 468 {
icraggs 8:80d49dd91542 469 quickstartMode = (strcmp(org, "quickstart") == 0);
icraggs 8:80d49dd91542 470
samdanbury 6:37b6d0d56190 471 lcd.set_font((unsigned char*) Arial12x12); // Set a nice font for the LCD screen
samdanbury 6:37b6d0d56190 472
samdanbury 6:37b6d0d56190 473 led2 = LED2_OFF; // K64F: turn off the main board LED
samdanbury 6:37b6d0d56190 474
samdanbury 6:37b6d0d56190 475 displayMessage("Connecting");
jsutton 13:85801e3b83d3 476 Thread yellow_thread(flashing_yellow);
jsutton 13:85801e3b83d3 477 Thread menu_thread(menu_loop);
jsutton 13:85801e3b83d3 478
jsutton 14:1f961d19f3cf 479 LOG("***** IBM IoT Client Ethernet Example *****\n");
samdanbury 6:37b6d0d56190 480 MQTTEthernet ipstack;
jsutton 14:1f961d19f3cf 481 ethernetInitialising = false;
samdanbury 6:37b6d0d56190 482 MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack);
icraggs 18:94da9de96d54 483 LOG("Ethernet Initialized\n");
jsutton 13:85801e3b83d3 484
samdanbury 6:37b6d0d56190 485 if (quickstartMode)
icraggs 16:2420bfbf5f1c 486 getMac(ipstack.getEth(), id, sizeof(id));
icraggs 16:2420bfbf5f1c 487
icraggs 16:2420bfbf5f1c 488 attemptConnect(&client, &ipstack);
icraggs 16:2420bfbf5f1c 489
icraggs 16:2420bfbf5f1c 490 if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD)
samdanbury 6:37b6d0d56190 491 {
icraggs 16:2420bfbf5f1c 492 red();
icraggs 16:2420bfbf5f1c 493 while (true)
icraggs 16:2420bfbf5f1c 494 wait(1.0); // Permanent failures - don't retry
samdanbury 6:37b6d0d56190 495 }
icraggs 16:2420bfbf5f1c 496
samdanbury 6:37b6d0d56190 497 if (!quickstartMode)
samdanbury 6:37b6d0d56190 498 {
samdanbury 6:37b6d0d56190 499 int rc = 0;
samdanbury 6:37b6d0d56190 500 if ((rc = client.subscribe("iot-2/cmd/+/fmt/json", MQTT::QOS1, messageArrived)) != 0)
samdanbury 6:37b6d0d56190 501 WARN("rc from MQTT subscribe is %d\n", rc);
samdanbury 6:37b6d0d56190 502 }
samdanbury 6:37b6d0d56190 503
samdanbury 6:37b6d0d56190 504 blink_interval = 0;
samdanbury 6:37b6d0d56190 505 int count = 0;
samdanbury 6:37b6d0d56190 506 while (true)
samdanbury 6:37b6d0d56190 507 {
samdanbury 6:37b6d0d56190 508 if (++count == 100)
samdanbury 6:37b6d0d56190 509 { // Publish a message every second
samdanbury 6:37b6d0d56190 510 if (publish(&client, &ipstack) != 0)
samdanbury 6:37b6d0d56190 511 attemptConnect(&client, &ipstack); // if we have lost the connection
samdanbury 6:37b6d0d56190 512 count = 0;
samdanbury 6:37b6d0d56190 513 }
samdanbury 6:37b6d0d56190 514
samdanbury 6:37b6d0d56190 515 if (blink_interval == 0)
samdanbury 6:37b6d0d56190 516 led2 = LED2_OFF;
samdanbury 6:37b6d0d56190 517 else if (count % blink_interval == 0)
samdanbury 6:37b6d0d56190 518 led2 = !led2;
samdanbury 6:37b6d0d56190 519 client.yield(10); // allow the MQTT client to receive messages
samdanbury 6:37b6d0d56190 520 }
samdanbury 6:37b6d0d56190 521 }