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:
jsutton
Date:
Mon Jul 27 09:03:30 2015 +0000
Revision:
15:09458079f4bb
Parent:
14:1f961d19f3cf
Child:
16:2420bfbf5f1c
Fixing comment

Who changed what in which revision?

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