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
main.cpp@1:1f187285667c, 2014-07-18 (annotated)
- Committer:
- samdanbury
- Date:
- Fri Jul 18 07:57:45 2014 +0000
- Revision:
- 1:1f187285667c
- Parent:
- 0:cae064bcbe5e
- Child:
- 2:d8fddda78c38
Add reconnect logic, LCD menu that scrolls and lights to show MQTT connectivity status
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
samdanbury | 0:cae064bcbe5e | 1 | /******************************************************************************* |
samdanbury | 0:cae064bcbe5e | 2 | * Copyright (c) 2014 IBM Corporation and other Contributors. |
samdanbury | 0:cae064bcbe5e | 3 | * |
samdanbury | 0:cae064bcbe5e | 4 | * All rights reserved. This program and the accompanying materials |
samdanbury | 0:cae064bcbe5e | 5 | * are made available under the terms of the Eclipse Public License v1.0 |
samdanbury | 0:cae064bcbe5e | 6 | * which accompanies this distribution, and is available at |
samdanbury | 0:cae064bcbe5e | 7 | * http://www.eclipse.org/legal/epl-v10.html |
samdanbury | 0:cae064bcbe5e | 8 | * |
samdanbury | 0:cae064bcbe5e | 9 | * Contributors: Sam Danbury |
samdanbury | 0:cae064bcbe5e | 10 | * IBM - Initial Contribution |
samdanbury | 0:cae064bcbe5e | 11 | *******************************************************************************/ |
samdanbury | 0:cae064bcbe5e | 12 | |
samdanbury | 0:cae064bcbe5e | 13 | #include "stdio.h" |
samdanbury | 0:cae064bcbe5e | 14 | #include "mbed.h" |
samdanbury | 0:cae064bcbe5e | 15 | #include "rtos.h" |
samdanbury | 0:cae064bcbe5e | 16 | #include "C12832.h" |
samdanbury | 0:cae064bcbe5e | 17 | #include "LM75B.h" |
samdanbury | 0:cae064bcbe5e | 18 | #include "MMA7660.h" |
samdanbury | 0:cae064bcbe5e | 19 | #include "C12832.h" |
samdanbury | 0:cae064bcbe5e | 20 | #include "MQTTEthernetIoT.h" |
samdanbury | 0:cae064bcbe5e | 21 | #include "MQTTClient.h" |
samdanbury | 0:cae064bcbe5e | 22 | #include "ConfigFile.h" |
samdanbury | 1:1f187285667c | 23 | #include "Arial12x12.h" |
samdanbury | 0:cae064bcbe5e | 24 | |
samdanbury | 0:cae064bcbe5e | 25 | #include <string> |
samdanbury | 0:cae064bcbe5e | 26 | #include <sstream> |
samdanbury | 0:cae064bcbe5e | 27 | #include <algorithm> |
samdanbury | 0:cae064bcbe5e | 28 | |
samdanbury | 0:cae064bcbe5e | 29 | using namespace std; |
samdanbury | 0:cae064bcbe5e | 30 | |
samdanbury | 0:cae064bcbe5e | 31 | #ifdef TARGET_LPC1768 |
samdanbury | 0:cae064bcbe5e | 32 | |
samdanbury | 0:cae064bcbe5e | 33 | #warning "Compiling for mbed LPC1768" |
samdanbury | 0:cae064bcbe5e | 34 | |
samdanbury | 0:cae064bcbe5e | 35 | LocalFileSystem local("local"); |
samdanbury | 0:cae064bcbe5e | 36 | C12832 lcd(p5, p7, p6, p8, p11); |
samdanbury | 0:cae064bcbe5e | 37 | DigitalOut led2(LED2); |
samdanbury | 1:1f187285667c | 38 | PwmOut r (p23); |
samdanbury | 1:1f187285667c | 39 | PwmOut g (p24); |
samdanbury | 1:1f187285667c | 40 | PwmOut b (p25); |
samdanbury | 0:cae064bcbe5e | 41 | MMA7660 MMA(p28, p27); |
samdanbury | 0:cae064bcbe5e | 42 | LM75B sensor(p28, p27); |
samdanbury | 0:cae064bcbe5e | 43 | DigitalIn Down(p12); |
samdanbury | 0:cae064bcbe5e | 44 | DigitalIn Left(p13); |
samdanbury | 0:cae064bcbe5e | 45 | DigitalIn Click(p14); |
samdanbury | 0:cae064bcbe5e | 46 | DigitalIn Up(p15); |
samdanbury | 0:cae064bcbe5e | 47 | DigitalIn Right(p16); |
samdanbury | 0:cae064bcbe5e | 48 | AnalogIn ain1(p19); |
samdanbury | 0:cae064bcbe5e | 49 | AnalogIn ain2(p20); |
samdanbury | 0:cae064bcbe5e | 50 | |
samdanbury | 0:cae064bcbe5e | 51 | #elif TARGET_K64F |
samdanbury | 0:cae064bcbe5e | 52 | |
samdanbury | 0:cae064bcbe5e | 53 | #warning "Compiling for mbed K64F" |
samdanbury | 0:cae064bcbe5e | 54 | |
samdanbury | 0:cae064bcbe5e | 55 | //#define ORGANISATION "<org>"; |
samdanbury | 0:cae064bcbe5e | 56 | //#define TYPE "<type>"; |
samdanbury | 0:cae064bcbe5e | 57 | //#define ID "<id>"; |
samdanbury | 0:cae064bcbe5e | 58 | //#define AUTHMETHOD "<auth-method>"; |
samdanbury | 0:cae064bcbe5e | 59 | //#define AUTHTOKEN "<auth-token>"; |
samdanbury | 0:cae064bcbe5e | 60 | |
samdanbury | 0:cae064bcbe5e | 61 | C12832 lcd(D11, D13, D12, D7, D10); |
samdanbury | 1:1f187285667c | 62 | PwmOut r (D5); |
samdanbury | 1:1f187285667c | 63 | PwmOut g (D8); |
samdanbury | 1:1f187285667c | 64 | PwmOut b (D9); |
samdanbury | 1:1f187285667c | 65 | DigitalOut led2(LED2); |
samdanbury | 0:cae064bcbe5e | 66 | MMA7660 MMA(PTE25, PTE24); |
samdanbury | 0:cae064bcbe5e | 67 | LM75B sensor(PTE25, PTE24); |
samdanbury | 0:cae064bcbe5e | 68 | DigitalIn Up(A2); |
samdanbury | 0:cae064bcbe5e | 69 | DigitalIn Down(A3); |
samdanbury | 0:cae064bcbe5e | 70 | DigitalIn Right(A4); |
samdanbury | 0:cae064bcbe5e | 71 | DigitalIn Left(A5); |
samdanbury | 0:cae064bcbe5e | 72 | DigitalIn Click(D4); |
samdanbury | 0:cae064bcbe5e | 73 | AnalogIn ain1(A0); |
samdanbury | 0:cae064bcbe5e | 74 | AnalogIn ain2(A1); |
samdanbury | 0:cae064bcbe5e | 75 | |
samdanbury | 0:cae064bcbe5e | 76 | #else |
samdanbury | 0:cae064bcbe5e | 77 | |
samdanbury | 0:cae064bcbe5e | 78 | LocalFileSystem local("local"); |
samdanbury | 0:cae064bcbe5e | 79 | C12832 lcd(D11, D13, D12, D7, D10); |
samdanbury | 0:cae064bcbe5e | 80 | DigitalOut led1(LED1); |
samdanbury | 0:cae064bcbe5e | 81 | DigitalOut led2(LED2); |
samdanbury | 0:cae064bcbe5e | 82 | DigitalOut led3(LED3); |
samdanbury | 0:cae064bcbe5e | 83 | MMA7660 MMA(D14, D15); |
samdanbury | 0:cae064bcbe5e | 84 | LM75B sensor(D14,D15); |
samdanbury | 0:cae064bcbe5e | 85 | DigitalIn Up(A2); |
samdanbury | 0:cae064bcbe5e | 86 | DigitalIn Down(A3); |
samdanbury | 0:cae064bcbe5e | 87 | DigitalIn Left(A4); |
samdanbury | 0:cae064bcbe5e | 88 | DigitalIn Right(A5); |
samdanbury | 0:cae064bcbe5e | 89 | DigitalIn Click(D4); |
samdanbury | 0:cae064bcbe5e | 90 | AnalogIn ain1 (A0); |
samdanbury | 0:cae064bcbe5e | 91 | AnalogIn ain2 (A1); |
samdanbury | 0:cae064bcbe5e | 92 | |
samdanbury | 0:cae064bcbe5e | 93 | #endif |
samdanbury | 0:cae064bcbe5e | 94 | |
samdanbury | 0:cae064bcbe5e | 95 | //Joystick |
samdanbury | 0:cae064bcbe5e | 96 | string joystickPos; |
samdanbury | 0:cae064bcbe5e | 97 | void joystickThread(void const *args); |
samdanbury | 0:cae064bcbe5e | 98 | |
samdanbury | 0:cae064bcbe5e | 99 | //Commands |
samdanbury | 0:cae064bcbe5e | 100 | enum command { |
samdanbury | 0:cae064bcbe5e | 101 | blink |
samdanbury | 0:cae064bcbe5e | 102 | }; |
samdanbury | 0:cae064bcbe5e | 103 | command getCommand (std::string const& command); |
samdanbury | 0:cae064bcbe5e | 104 | void messageArrived(MQTT::MessageData& md); |
samdanbury | 1:1f187285667c | 105 | |
samdanbury | 1:1f187285667c | 106 | //MQTT |
samdanbury | 1:1f187285667c | 107 | void connect(); |
samdanbury | 1:1f187285667c | 108 | void attemptConnect(); |
samdanbury | 1:1f187285667c | 109 | int getConnTimeout(int attemptNumber); |
samdanbury | 1:1f187285667c | 110 | void subscribe(); |
samdanbury | 0:cae064bcbe5e | 111 | |
samdanbury | 0:cae064bcbe5e | 112 | //Config |
samdanbury | 0:cae064bcbe5e | 113 | void parseConfig(); |
samdanbury | 0:cae064bcbe5e | 114 | bool quickstartMode = true; |
samdanbury | 0:cae064bcbe5e | 115 | string org = ""; |
samdanbury | 0:cae064bcbe5e | 116 | string type = ""; |
samdanbury | 0:cae064bcbe5e | 117 | string id = ""; |
samdanbury | 0:cae064bcbe5e | 118 | string auth_method = ""; |
samdanbury | 0:cae064bcbe5e | 119 | string auth_token = ""; |
samdanbury | 0:cae064bcbe5e | 120 | string mac = ""; |
samdanbury | 0:cae064bcbe5e | 121 | |
samdanbury | 1:1f187285667c | 122 | //LCD menu |
samdanbury | 1:1f187285667c | 123 | bool connected = false; |
samdanbury | 1:1f187285667c | 124 | bool menuActivated = false; |
samdanbury | 1:1f187285667c | 125 | int menu = 0; |
samdanbury | 1:1f187285667c | 126 | void printMenu(); |
samdanbury | 1:1f187285667c | 127 | |
samdanbury | 1:1f187285667c | 128 | int interval; |
samdanbury | 1:1f187285667c | 129 | string getUUID48(); |
samdanbury | 1:1f187285667c | 130 | |
samdanbury | 1:1f187285667c | 131 | MQTTSocket ipstack; |
samdanbury | 1:1f187285667c | 132 | MQTT::Client<MQTTSocket, Countdown, 250>* client; |
samdanbury | 0:cae064bcbe5e | 133 | |
samdanbury | 0:cae064bcbe5e | 134 | void parseConfig() { |
samdanbury | 0:cae064bcbe5e | 135 | |
samdanbury | 0:cae064bcbe5e | 136 | ConfigFile cfg; |
samdanbury | 0:cae064bcbe5e | 137 | |
samdanbury | 0:cae064bcbe5e | 138 | char value[30]; |
samdanbury | 0:cae064bcbe5e | 139 | char value1[30]; |
samdanbury | 0:cae064bcbe5e | 140 | char value2[30]; |
samdanbury | 0:cae064bcbe5e | 141 | char value3[30]; |
samdanbury | 0:cae064bcbe5e | 142 | |
samdanbury | 0:cae064bcbe5e | 143 | if (cfg.read("/local/device.cfg")) { |
samdanbury | 0:cae064bcbe5e | 144 | quickstartMode = false; |
samdanbury | 0:cae064bcbe5e | 145 | |
samdanbury | 0:cae064bcbe5e | 146 | if (cfg.getValue("org", value, sizeof(value))) { |
samdanbury | 0:cae064bcbe5e | 147 | stringstream ss(value); |
samdanbury | 0:cae064bcbe5e | 148 | ss >> org; |
samdanbury | 0:cae064bcbe5e | 149 | } |
samdanbury | 0:cae064bcbe5e | 150 | if (cfg.getValue("type", value1, sizeof(value1))) { |
samdanbury | 0:cae064bcbe5e | 151 | stringstream ss(value1); |
samdanbury | 0:cae064bcbe5e | 152 | ss >> type; |
samdanbury | 1:1f187285667c | 153 | } |
samdanbury | 0:cae064bcbe5e | 154 | if (cfg.getValue("id", value2, sizeof(value2))) { |
samdanbury | 0:cae064bcbe5e | 155 | stringstream ss(value2); |
samdanbury | 0:cae064bcbe5e | 156 | ss >> id; |
samdanbury | 0:cae064bcbe5e | 157 | } |
samdanbury | 0:cae064bcbe5e | 158 | if (cfg.getValue("auth-token", value3, sizeof(value3))) { |
samdanbury | 0:cae064bcbe5e | 159 | stringstream ss(value3); |
samdanbury | 0:cae064bcbe5e | 160 | ss >> auth_token; |
samdanbury | 0:cae064bcbe5e | 161 | } |
samdanbury | 0:cae064bcbe5e | 162 | |
samdanbury | 0:cae064bcbe5e | 163 | } else { |
samdanbury | 0:cae064bcbe5e | 164 | quickstartMode = true; |
samdanbury | 0:cae064bcbe5e | 165 | org = "quickstart"; |
samdanbury | 0:cae064bcbe5e | 166 | type = "iotsample-mbed-lpc1768"; |
samdanbury | 0:cae064bcbe5e | 167 | id = mac; |
samdanbury | 0:cae064bcbe5e | 168 | } |
samdanbury | 0:cae064bcbe5e | 169 | |
samdanbury | 0:cae064bcbe5e | 170 | #ifdef TARGET_K64F |
samdanbury | 0:cae064bcbe5e | 171 | #ifdef ORGANISATION |
samdanbury | 0:cae064bcbe5e | 172 | quickstartMode = false; |
samdanbury | 0:cae064bcbe5e | 173 | org = ORGANISATION; |
samdanbury | 0:cae064bcbe5e | 174 | |
samdanbury | 0:cae064bcbe5e | 175 | #ifdef TYPE |
samdanbury | 0:cae064bcbe5e | 176 | type = TYPE; |
samdanbury | 0:cae064bcbe5e | 177 | #else |
samdanbury | 0:cae064bcbe5e | 178 | lcd.printf("Type is not defined"); |
samdanbury | 0:cae064bcbe5e | 179 | #endif |
samdanbury | 0:cae064bcbe5e | 180 | |
samdanbury | 0:cae064bcbe5e | 181 | #ifdef ID |
samdanbury | 0:cae064bcbe5e | 182 | id = ID; |
samdanbury | 0:cae064bcbe5e | 183 | #else |
samdanbury | 0:cae064bcbe5e | 184 | lcd.printf("ID is not defined"); |
samdanbury | 0:cae064bcbe5e | 185 | #endif |
samdanbury | 0:cae064bcbe5e | 186 | |
samdanbury | 0:cae064bcbe5e | 187 | #ifdef AUTHMETHOD |
samdanbury | 0:cae064bcbe5e | 188 | auth_method = AUTHMETHOD; |
samdanbury | 0:cae064bcbe5e | 189 | #else |
samdanbury | 0:cae064bcbe5e | 190 | lcd.printf("Auth method is not defined"); |
samdanbury | 0:cae064bcbe5e | 191 | #endif |
samdanbury | 0:cae064bcbe5e | 192 | |
samdanbury | 0:cae064bcbe5e | 193 | #ifdef AUTHTOKEN |
samdanbury | 0:cae064bcbe5e | 194 | auth_token = AUTHTOKEN; |
samdanbury | 0:cae064bcbe5e | 195 | #else |
samdanbury | 0:cae064bcbe5e | 196 | lcd.printf("Auth token is not defined"); |
samdanbury | 0:cae064bcbe5e | 197 | #endif |
samdanbury | 0:cae064bcbe5e | 198 | #endif |
samdanbury | 0:cae064bcbe5e | 199 | #endif |
samdanbury | 0:cae064bcbe5e | 200 | } |
samdanbury | 0:cae064bcbe5e | 201 | |
samdanbury | 0:cae064bcbe5e | 202 | int main() |
samdanbury | 0:cae064bcbe5e | 203 | { |
samdanbury | 1:1f187285667c | 204 | //RGB: yellow |
samdanbury | 1:1f187285667c | 205 | r = 0; |
samdanbury | 1:1f187285667c | 206 | g = 0; |
samdanbury | 1:1f187285667c | 207 | b = 1; |
samdanbury | 1:1f187285667c | 208 | |
samdanbury | 1:1f187285667c | 209 | lcd.cls(); |
samdanbury | 1:1f187285667c | 210 | lcd.set_font((unsigned char*) Arial12x12); |
samdanbury | 1:1f187285667c | 211 | lcd.locate(0,0); |
samdanbury | 1:1f187285667c | 212 | lcd.printf("IBM IoT Cloud"); |
samdanbury | 1:1f187285667c | 213 | lcd.locate(0,16); |
samdanbury | 1:1f187285667c | 214 | lcd.printf("Connecting"); |
samdanbury | 0:cae064bcbe5e | 215 | |
samdanbury | 0:cae064bcbe5e | 216 | //Connect to network |
samdanbury | 1:1f187285667c | 217 | EthernetInterface eth; |
samdanbury | 1:1f187285667c | 218 | eth.init(); |
samdanbury | 1:1f187285667c | 219 | eth.connect(); |
samdanbury | 0:cae064bcbe5e | 220 | |
samdanbury | 0:cae064bcbe5e | 221 | //Obtain mac address of mbed |
samdanbury | 0:cae064bcbe5e | 222 | #ifdef TARGET_K64F |
samdanbury | 0:cae064bcbe5e | 223 | mac = getUUID48(); |
samdanbury | 0:cae064bcbe5e | 224 | #else |
samdanbury | 1:1f187285667c | 225 | mac = eth.getMACAddress(); |
samdanbury | 0:cae064bcbe5e | 226 | |
samdanbury | 0:cae064bcbe5e | 227 | //Remove colons from mac address |
samdanbury | 0:cae064bcbe5e | 228 | mac.erase(remove(mac.begin(), mac.end(), ':'), mac.end()); |
samdanbury | 0:cae064bcbe5e | 229 | #endif |
samdanbury | 0:cae064bcbe5e | 230 | |
samdanbury | 0:cae064bcbe5e | 231 | //Parse config file if present |
samdanbury | 0:cae064bcbe5e | 232 | parseConfig(); |
samdanbury | 0:cae064bcbe5e | 233 | |
samdanbury | 1:1f187285667c | 234 | attemptConnect(); |
samdanbury | 0:cae064bcbe5e | 235 | |
samdanbury | 0:cae064bcbe5e | 236 | if (!quickstartMode) { |
samdanbury | 1:1f187285667c | 237 | subscribe(); |
samdanbury | 0:cae064bcbe5e | 238 | } |
samdanbury | 0:cae064bcbe5e | 239 | |
samdanbury | 0:cae064bcbe5e | 240 | //Start thread to read data from joystick |
samdanbury | 0:cae064bcbe5e | 241 | joystickPos = "CENTRE"; |
samdanbury | 0:cae064bcbe5e | 242 | Thread jThd(joystickThread); |
samdanbury | 0:cae064bcbe5e | 243 | |
samdanbury | 0:cae064bcbe5e | 244 | interval = 0; |
samdanbury | 0:cae064bcbe5e | 245 | int i = 0; |
samdanbury | 0:cae064bcbe5e | 246 | |
samdanbury | 0:cae064bcbe5e | 247 | while(1) |
samdanbury | 0:cae064bcbe5e | 248 | { |
samdanbury | 0:cae064bcbe5e | 249 | //Message published every second |
samdanbury | 0:cae064bcbe5e | 250 | if (i == 100) { |
samdanbury | 0:cae064bcbe5e | 251 | //MQTT Publish |
samdanbury | 0:cae064bcbe5e | 252 | MQTT::Message message; |
samdanbury | 0:cae064bcbe5e | 253 | char* pubTopic = "iot-2/evt/status/fmt/json"; |
samdanbury | 0:cae064bcbe5e | 254 | |
samdanbury | 0:cae064bcbe5e | 255 | char buf[250]; |
samdanbury | 0:cae064bcbe5e | 256 | sprintf(buf, |
samdanbury | 0:cae064bcbe5e | 257 | "{\"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 | 0:cae064bcbe5e | 258 | MMA.x(), MMA.y(), MMA.z(), |
samdanbury | 0:cae064bcbe5e | 259 | sensor.temp(), |
samdanbury | 0:cae064bcbe5e | 260 | joystickPos, |
samdanbury | 0:cae064bcbe5e | 261 | ain1.read(), |
samdanbury | 0:cae064bcbe5e | 262 | ain2.read()); |
samdanbury | 0:cae064bcbe5e | 263 | message.qos = MQTT::QOS0; |
samdanbury | 0:cae064bcbe5e | 264 | message.retained = false; |
samdanbury | 0:cae064bcbe5e | 265 | message.dup = false; |
samdanbury | 0:cae064bcbe5e | 266 | message.payload = (void*)buf; |
samdanbury | 0:cae064bcbe5e | 267 | message.payloadlen = strlen(buf); |
samdanbury | 0:cae064bcbe5e | 268 | |
samdanbury | 1:1f187285667c | 269 | int rc = 0; |
samdanbury | 1:1f187285667c | 270 | if ((rc = client->publish(pubTopic, &message)) != 0) { |
samdanbury | 1:1f187285667c | 271 | connected = false; |
samdanbury | 1:1f187285667c | 272 | attemptConnect(); |
samdanbury | 1:1f187285667c | 273 | } |
samdanbury | 0:cae064bcbe5e | 274 | |
samdanbury | 0:cae064bcbe5e | 275 | i = 0; |
samdanbury | 0:cae064bcbe5e | 276 | } |
samdanbury | 0:cae064bcbe5e | 277 | |
samdanbury | 0:cae064bcbe5e | 278 | if (interval == 0) { |
samdanbury | 1:1f187285667c | 279 | //led2 = 0; |
samdanbury | 0:cae064bcbe5e | 280 | } else { |
samdanbury | 0:cae064bcbe5e | 281 | if (i%(interval)==0) { |
samdanbury | 1:1f187285667c | 282 | //led2 = !led2; |
samdanbury | 0:cae064bcbe5e | 283 | } |
samdanbury | 0:cae064bcbe5e | 284 | } |
samdanbury | 0:cae064bcbe5e | 285 | |
samdanbury | 0:cae064bcbe5e | 286 | wait(0.01); |
samdanbury | 0:cae064bcbe5e | 287 | i++; |
samdanbury | 1:1f187285667c | 288 | client->yield(1); |
samdanbury | 1:1f187285667c | 289 | } |
samdanbury | 1:1f187285667c | 290 | } |
samdanbury | 1:1f187285667c | 291 | |
samdanbury | 1:1f187285667c | 292 | void attemptConnect() { |
samdanbury | 1:1f187285667c | 293 | int retryAttempt = 0; |
samdanbury | 1:1f187285667c | 294 | menuActivated = false; |
samdanbury | 1:1f187285667c | 295 | |
samdanbury | 1:1f187285667c | 296 | //RGB: yellow |
samdanbury | 1:1f187285667c | 297 | r = 0; |
samdanbury | 1:1f187285667c | 298 | g = 0; |
samdanbury | 1:1f187285667c | 299 | b = 1; |
samdanbury | 1:1f187285667c | 300 | |
samdanbury | 1:1f187285667c | 301 | lcd.cls(); |
samdanbury | 1:1f187285667c | 302 | lcd.locate(0,0); |
samdanbury | 1:1f187285667c | 303 | lcd.printf("IBM IoT Cloud"); |
samdanbury | 1:1f187285667c | 304 | lcd.locate(0,16); |
samdanbury | 1:1f187285667c | 305 | lcd.printf("Connecting"); |
samdanbury | 1:1f187285667c | 306 | |
samdanbury | 1:1f187285667c | 307 | while (!connected) { |
samdanbury | 1:1f187285667c | 308 | |
samdanbury | 1:1f187285667c | 309 | int connTimeout = getConnTimeout(++retryAttempt); |
samdanbury | 1:1f187285667c | 310 | |
samdanbury | 1:1f187285667c | 311 | connect(); |
samdanbury | 1:1f187285667c | 312 | |
samdanbury | 1:1f187285667c | 313 | if (!connected) { |
samdanbury | 1:1f187285667c | 314 | wait(connTimeout); |
samdanbury | 1:1f187285667c | 315 | } else { |
samdanbury | 1:1f187285667c | 316 | break; |
samdanbury | 1:1f187285667c | 317 | } |
samdanbury | 1:1f187285667c | 318 | } |
samdanbury | 1:1f187285667c | 319 | } |
samdanbury | 1:1f187285667c | 320 | |
samdanbury | 1:1f187285667c | 321 | int getConnTimeout(int attemptNumber) { |
samdanbury | 1:1f187285667c | 322 | if (attemptNumber < 10) { |
samdanbury | 1:1f187285667c | 323 | return 3; //First 10 attempts try within 3 seconds |
samdanbury | 1:1f187285667c | 324 | } else if (attemptNumber < 20) { |
samdanbury | 1:1f187285667c | 325 | return 60; //Next 10 attempts retry after every 1 minute |
samdanbury | 1:1f187285667c | 326 | } else { |
samdanbury | 1:1f187285667c | 327 | return 600; //After 20 attempts, retry every 10 minutes |
samdanbury | 0:cae064bcbe5e | 328 | } |
samdanbury | 0:cae064bcbe5e | 329 | } |
samdanbury | 0:cae064bcbe5e | 330 | |
samdanbury | 1:1f187285667c | 331 | void connect() { |
samdanbury | 1:1f187285667c | 332 | ipstack = MQTTSocket(); |
samdanbury | 1:1f187285667c | 333 | client = new MQTT::Client<MQTTSocket, Countdown, 250>(ipstack); |
samdanbury | 1:1f187285667c | 334 | |
samdanbury | 1:1f187285667c | 335 | //TCP Connect |
samdanbury | 1:1f187285667c | 336 | string ip = org + ".messaging.internetofthings.ibmcloud.com"; |
samdanbury | 1:1f187285667c | 337 | |
samdanbury | 1:1f187285667c | 338 | char* hostname = new char[ip.length() + 1]; |
samdanbury | 1:1f187285667c | 339 | strcpy(hostname, ip.c_str()); |
samdanbury | 1:1f187285667c | 340 | |
samdanbury | 1:1f187285667c | 341 | int port = 1883; |
samdanbury | 1:1f187285667c | 342 | int rc = ipstack.connect(hostname, port); |
samdanbury | 1:1f187285667c | 343 | if (rc != 0) { |
samdanbury | 1:1f187285667c | 344 | lcd.printf("TCP connect failed"); |
samdanbury | 1:1f187285667c | 345 | } |
samdanbury | 1:1f187285667c | 346 | |
samdanbury | 1:1f187285667c | 347 | //Construct clientId based on config |
samdanbury | 1:1f187285667c | 348 | string str = string("d:") + org + ":" + type + ":" + id; |
samdanbury | 1:1f187285667c | 349 | char clientId[str.size()]; |
samdanbury | 1:1f187285667c | 350 | memcpy(clientId, str.c_str(), str.size() + 1); |
samdanbury | 1:1f187285667c | 351 | |
samdanbury | 1:1f187285667c | 352 | //MQTT Connect |
samdanbury | 1:1f187285667c | 353 | MQTTPacket_connectData data = MQTTPacket_connectData_initializer; |
samdanbury | 1:1f187285667c | 354 | data.MQTTVersion = 3; |
samdanbury | 1:1f187285667c | 355 | data.clientID.cstring = clientId; |
samdanbury | 1:1f187285667c | 356 | |
samdanbury | 1:1f187285667c | 357 | if (!quickstartMode) { |
samdanbury | 1:1f187285667c | 358 | char* password = new char[auth_token.length() + 1]; |
samdanbury | 1:1f187285667c | 359 | strcpy(password, auth_token.c_str()); |
samdanbury | 1:1f187285667c | 360 | |
samdanbury | 1:1f187285667c | 361 | data.username.cstring = "use-token-auth"; |
samdanbury | 1:1f187285667c | 362 | data.password.cstring = password; |
samdanbury | 1:1f187285667c | 363 | } |
samdanbury | 1:1f187285667c | 364 | |
samdanbury | 1:1f187285667c | 365 | if ((rc = client->connect(&data)) != 0) { |
samdanbury | 1:1f187285667c | 366 | lcd.printf("rc from MQTT connect is %d\n", rc); |
samdanbury | 1:1f187285667c | 367 | } else { |
samdanbury | 1:1f187285667c | 368 | connected = true; |
samdanbury | 1:1f187285667c | 369 | |
samdanbury | 1:1f187285667c | 370 | //RGB: green |
samdanbury | 1:1f187285667c | 371 | r = 1; |
samdanbury | 1:1f187285667c | 372 | g = 0; |
samdanbury | 1:1f187285667c | 373 | b = 1; |
samdanbury | 1:1f187285667c | 374 | |
samdanbury | 1:1f187285667c | 375 | lcd.locate(0,0); |
samdanbury | 1:1f187285667c | 376 | lcd.printf("IBM IoT Cloud"); |
samdanbury | 1:1f187285667c | 377 | lcd.locate(0,16); |
samdanbury | 1:1f187285667c | 378 | lcd.printf("Connected"); |
samdanbury | 1:1f187285667c | 379 | |
samdanbury | 1:1f187285667c | 380 | wait(2); |
samdanbury | 1:1f187285667c | 381 | |
samdanbury | 1:1f187285667c | 382 | lcd.locate(0,0); |
samdanbury | 1:1f187285667c | 383 | lcd.printf("IBM IoT Cloud"); |
samdanbury | 1:1f187285667c | 384 | lcd.locate(0,16); |
samdanbury | 1:1f187285667c | 385 | lcd.printf("Scroll with joystick"); |
samdanbury | 1:1f187285667c | 386 | |
samdanbury | 1:1f187285667c | 387 | menuActivated = true; |
samdanbury | 1:1f187285667c | 388 | } |
samdanbury | 1:1f187285667c | 389 | } |
samdanbury | 1:1f187285667c | 390 | |
samdanbury | 1:1f187285667c | 391 | void subscribe() { |
samdanbury | 1:1f187285667c | 392 | char* subTopic = "iot-2/cmd/+/fmt/json"; |
samdanbury | 1:1f187285667c | 393 | int rc = 0; |
samdanbury | 1:1f187285667c | 394 | if ((rc = client->subscribe(subTopic, MQTT::QOS1, messageArrived)) != 0) |
samdanbury | 1:1f187285667c | 395 | lcd.printf("rc from MQTT subscribe is %d\n", rc); |
samdanbury | 1:1f187285667c | 396 | } |
samdanbury | 1:1f187285667c | 397 | |
samdanbury | 0:cae064bcbe5e | 398 | void messageArrived(MQTT::MessageData& md) { |
samdanbury | 0:cae064bcbe5e | 399 | MQTT::Message &message = md.message; |
samdanbury | 0:cae064bcbe5e | 400 | |
samdanbury | 0:cae064bcbe5e | 401 | char* topic = new char[md.topicName.lenstring.len + 1]; |
samdanbury | 0:cae064bcbe5e | 402 | sprintf(topic, "%.*s", md.topicName.lenstring.len, md.topicName.lenstring.data); |
samdanbury | 0:cae064bcbe5e | 403 | |
samdanbury | 0:cae064bcbe5e | 404 | char* payload = new char[message.payloadlen + 1]; |
samdanbury | 0:cae064bcbe5e | 405 | sprintf(payload, "%.*s", message.payloadlen, (char*)message.payload); |
samdanbury | 0:cae064bcbe5e | 406 | |
samdanbury | 0:cae064bcbe5e | 407 | string topicStr = topic; |
samdanbury | 0:cae064bcbe5e | 408 | string payloadStr = payload; |
samdanbury | 0:cae064bcbe5e | 409 | |
samdanbury | 0:cae064bcbe5e | 410 | //Command topic: iot-2/cmd/blink/fmt/json |
samdanbury | 0:cae064bcbe5e | 411 | string cmd = topicStr.substr(10, topicStr.find("/fmt/") - 10); |
samdanbury | 0:cae064bcbe5e | 412 | |
samdanbury | 0:cae064bcbe5e | 413 | switch(getCommand(cmd)) { |
samdanbury | 0:cae064bcbe5e | 414 | case blink: { |
samdanbury | 0:cae064bcbe5e | 415 | string str = payloadStr.substr(8, payloadStr.find("}") - 8); |
samdanbury | 0:cae064bcbe5e | 416 | int rate = atoi(str.c_str()); |
samdanbury | 0:cae064bcbe5e | 417 | |
samdanbury | 0:cae064bcbe5e | 418 | if (rate == 0) { |
samdanbury | 0:cae064bcbe5e | 419 | interval = 0; |
samdanbury | 0:cae064bcbe5e | 420 | } else if (rate > 50) { |
samdanbury | 0:cae064bcbe5e | 421 | interval = 1; |
samdanbury | 0:cae064bcbe5e | 422 | } else if (rate > 0) { |
samdanbury | 0:cae064bcbe5e | 423 | interval = 50/rate; |
samdanbury | 0:cae064bcbe5e | 424 | } |
samdanbury | 0:cae064bcbe5e | 425 | |
samdanbury | 0:cae064bcbe5e | 426 | break; |
samdanbury | 0:cae064bcbe5e | 427 | } |
samdanbury | 0:cae064bcbe5e | 428 | default: |
samdanbury | 0:cae064bcbe5e | 429 | lcd.printf("Unsupported command: %s\n", cmd); |
samdanbury | 0:cae064bcbe5e | 430 | } |
samdanbury | 0:cae064bcbe5e | 431 | |
samdanbury | 0:cae064bcbe5e | 432 | if (topic) { |
samdanbury | 0:cae064bcbe5e | 433 | delete[] topic; |
samdanbury | 0:cae064bcbe5e | 434 | } |
samdanbury | 0:cae064bcbe5e | 435 | if (payload) { |
samdanbury | 0:cae064bcbe5e | 436 | delete[] payload; |
samdanbury | 0:cae064bcbe5e | 437 | } |
samdanbury | 0:cae064bcbe5e | 438 | |
samdanbury | 0:cae064bcbe5e | 439 | } |
samdanbury | 0:cae064bcbe5e | 440 | |
samdanbury | 0:cae064bcbe5e | 441 | command getCommand (string const& command) { |
samdanbury | 0:cae064bcbe5e | 442 | if (command == "blink") |
samdanbury | 0:cae064bcbe5e | 443 | return blink; |
samdanbury | 0:cae064bcbe5e | 444 | } |
samdanbury | 0:cae064bcbe5e | 445 | |
samdanbury | 0:cae064bcbe5e | 446 | void joystickThread(void const *args) { |
samdanbury | 0:cae064bcbe5e | 447 | while (true) { |
samdanbury | 1:1f187285667c | 448 | |
samdanbury | 1:1f187285667c | 449 | if (!menuActivated) { |
samdanbury | 1:1f187285667c | 450 | menu = 0; |
samdanbury | 1:1f187285667c | 451 | } |
samdanbury | 1:1f187285667c | 452 | |
samdanbury | 1:1f187285667c | 453 | if (Down) { |
samdanbury | 0:cae064bcbe5e | 454 | joystickPos = "DOWN"; |
samdanbury | 1:1f187285667c | 455 | if (menu >= 0 && menu < 3) { |
samdanbury | 1:1f187285667c | 456 | menu++; |
samdanbury | 1:1f187285667c | 457 | printMenu(); |
samdanbury | 1:1f187285667c | 458 | } |
samdanbury | 1:1f187285667c | 459 | } else if (Left) { |
samdanbury | 0:cae064bcbe5e | 460 | joystickPos = "LEFT"; |
samdanbury | 1:1f187285667c | 461 | } else if (Click) { |
samdanbury | 0:cae064bcbe5e | 462 | joystickPos = "CLICK"; |
samdanbury | 1:1f187285667c | 463 | } else if (Up) { |
samdanbury | 0:cae064bcbe5e | 464 | joystickPos = "UP"; |
samdanbury | 1:1f187285667c | 465 | if (menu <= 3 && menu > 0) { |
samdanbury | 1:1f187285667c | 466 | menu--; |
samdanbury | 1:1f187285667c | 467 | printMenu(); |
samdanbury | 1:1f187285667c | 468 | } |
samdanbury | 1:1f187285667c | 469 | } else if (Right) { |
samdanbury | 0:cae064bcbe5e | 470 | joystickPos = "RIGHT"; |
samdanbury | 1:1f187285667c | 471 | } else { |
samdanbury | 0:cae064bcbe5e | 472 | joystickPos = "CENTRE"; |
samdanbury | 1:1f187285667c | 473 | } |
samdanbury | 1:1f187285667c | 474 | wait(0.2); |
samdanbury | 1:1f187285667c | 475 | } |
samdanbury | 1:1f187285667c | 476 | } |
samdanbury | 1:1f187285667c | 477 | |
samdanbury | 1:1f187285667c | 478 | void printMenu() { |
samdanbury | 1:1f187285667c | 479 | if (menuActivated) { |
samdanbury | 1:1f187285667c | 480 | lcd.cls(); |
samdanbury | 1:1f187285667c | 481 | lcd.locate(0,0); |
samdanbury | 1:1f187285667c | 482 | |
samdanbury | 1:1f187285667c | 483 | switch(menu) { |
samdanbury | 1:1f187285667c | 484 | case 0: |
samdanbury | 1:1f187285667c | 485 | lcd.printf("IBM IoT Cloud"); |
samdanbury | 1:1f187285667c | 486 | lcd.locate(0,16); |
samdanbury | 1:1f187285667c | 487 | lcd.printf("Scroll with joystick"); |
samdanbury | 1:1f187285667c | 488 | break; |
samdanbury | 1:1f187285667c | 489 | case 1: |
samdanbury | 1:1f187285667c | 490 | lcd.printf("Go to:"); |
samdanbury | 1:1f187285667c | 491 | lcd.locate(0,16); |
samdanbury | 1:1f187285667c | 492 | lcd.printf("http://ibm.biz/iotqstart"); |
samdanbury | 1:1f187285667c | 493 | break; |
samdanbury | 1:1f187285667c | 494 | case 2: |
samdanbury | 1:1f187285667c | 495 | lcd.printf("Device Identity:"); |
samdanbury | 1:1f187285667c | 496 | lcd.locate(0,16); |
samdanbury | 1:1f187285667c | 497 | lcd.printf("%s", mac); |
samdanbury | 1:1f187285667c | 498 | break; |
samdanbury | 1:1f187285667c | 499 | case 3: |
samdanbury | 1:1f187285667c | 500 | lcd.printf("Status:"); |
samdanbury | 1:1f187285667c | 501 | lcd.locate(0,16); |
samdanbury | 1:1f187285667c | 502 | lcd.printf("Connected"); |
samdanbury | 1:1f187285667c | 503 | break; |
samdanbury | 1:1f187285667c | 504 | } |
samdanbury | 1:1f187285667c | 505 | } else { |
samdanbury | 1:1f187285667c | 506 | menu = 0; |
samdanbury | 0:cae064bcbe5e | 507 | } |
samdanbury | 0:cae064bcbe5e | 508 | } |
samdanbury | 0:cae064bcbe5e | 509 | |
samdanbury | 0:cae064bcbe5e | 510 | string getUUID48 () { |
samdanbury | 0:cae064bcbe5e | 511 | |
samdanbury | 0:cae064bcbe5e | 512 | unsigned int UUID_LOC_WORD0 = 0x40048060; |
samdanbury | 0:cae064bcbe5e | 513 | unsigned int UUID_LOC_WORD1 = 0x4004805C; |
samdanbury | 0:cae064bcbe5e | 514 | |
samdanbury | 0:cae064bcbe5e | 515 | // Fetch word 0 |
samdanbury | 0:cae064bcbe5e | 516 | uint32_t Word0 = *(uint32_t *)UUID_LOC_WORD0; |
samdanbury | 0:cae064bcbe5e | 517 | |
samdanbury | 0:cae064bcbe5e | 518 | // Fetch word 1 |
samdanbury | 0:cae064bcbe5e | 519 | // we only want bottom 16 bits of word1 (MAC bits 32-47) |
samdanbury | 0:cae064bcbe5e | 520 | // and bit 9 forced to 1, bit 8 forced to 0 |
samdanbury | 0:cae064bcbe5e | 521 | // Locally administered MAC, reduced conflicts |
samdanbury | 0:cae064bcbe5e | 522 | // http://en.wikipedia.org/wiki/MAC_address |
samdanbury | 0:cae064bcbe5e | 523 | uint32_t Word1 = *(uint32_t *)UUID_LOC_WORD1; |
samdanbury | 0:cae064bcbe5e | 524 | Word1 |= 0x00000200; |
samdanbury | 0:cae064bcbe5e | 525 | Word1 &= 0x0000FEFF; |
samdanbury | 0:cae064bcbe5e | 526 | |
samdanbury | 0:cae064bcbe5e | 527 | string sd; |
samdanbury | 0:cae064bcbe5e | 528 | char stemp[100] = ""; |
samdanbury | 0:cae064bcbe5e | 529 | snprintf(stemp, 100, "%4X%08X", Word1,Word0); // I use the safer version of sprintf() -- snprintf() |
samdanbury | 0:cae064bcbe5e | 530 | sd = stemp; // the contents of sd are now "This is a string!" |
samdanbury | 0:cae064bcbe5e | 531 | |
samdanbury | 0:cae064bcbe5e | 532 | return (sd); |
samdanbury | 0:cae064bcbe5e | 533 | } |