pro_client_device
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 | } |