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