a modified code based on the IoTClientEthernet code
Dependencies: C12832 EthernetInterface LM75B MMA7660 MQTT mbed-rtos mbed
Fork of IoTClientEthernet by
main.cpp
00001 /******************************************************************************* 00002 * Copyright (c) 2014, 2015 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 * James Sutton - Mac fix and extra debug 00019 * Ian Craggs - add not authorized messages 00020 * 00021 * To do : 00022 * Add magnetometer sensor output to IoT data stream 00023 * 00024 *******************************************************************************/ 00025 00026 #include "LM75B.h" 00027 #include "MMA7660.h" 00028 #include "MQTTClient.h" 00029 #include "MQTTEthernet.h" 00030 #include "C12832.h" 00031 #include "Arial12x12.h" 00032 #include "rtos.h" 00033 00034 // Update this to the next number *before* a commit 00035 #define __APP_SW_REVISION__ "18" 00036 00037 // Configuration values needed to connect to IBM IoT Cloud 00038 #define ORG "quickstart" // For a registered connection, replace with your org 00039 #define ID "" // For a registered connection, replace with your id 00040 #define AUTH_TOKEN "" // For a registered connection, replace with your auth-token 00041 #define TYPE DEFAULT_TYPE_NAME // For a registered connection, replace with your type 00042 00043 #define MQTT_PORT 1883 00044 #define MQTT_TLS_PORT 8883 00045 #define IBM_IOT_PORT MQTT_PORT 00046 00047 #define MQTT_MAX_PACKET_SIZE 250 00048 00049 #if defined(TARGET_UBLOX_C027) 00050 #warning "Compiling for mbed C027" 00051 #include "C027.h" 00052 #elif defined(TARGET_LPC1768) 00053 #warning "Compiling for mbed LPC1768" 00054 #include "LPC1768.h" 00055 #elif defined(TARGET_K64F) 00056 #warning "Compiling for mbed K64F" 00057 #include "K64F.h" 00058 #endif 00059 00060 00061 bool quickstartMode = true; 00062 char org[11] = ORG; 00063 char type[30] = TYPE; 00064 char id[30] = ID; // mac without colons 00065 char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode 00066 bool connected = false; 00067 bool mqttConnecting = false; 00068 bool netConnected = false; 00069 bool netConnecting = false; 00070 bool ethernetInitialising = true; 00071 int connack_rc = 0; // MQTT connack return code 00072 int retryAttempt = 0; 00073 int menuItem = 0; 00074 char* joystickPos = "CENTRE"; 00075 int blink_interval = 0; 00076 char* ip_addr = ""; 00077 char* gateway_addr = ""; 00078 char* host_addr = ""; 00079 int connectTimeout = 1000; 00080 // If we wanted to manually set the MAC address, 00081 // this is how to do it. In this example, we take 00082 // the original Mbed Set MAC address and combine it 00083 // with a prefix of our choosing. 00084 extern "C" void $Super$$mbed_mac_address(char *s); 00085 extern "C" void $Sub$$mbed_mac_address(char *s) 00086 { 00087 // define your own MAC Address 00088 s[0] = 0x68; 00089 s[1] = 0xf7; 00090 s[2] = 0x28; 00091 s[3] = 0x06; 00092 s[4] = 0x02; 00093 s[5] = 0x63; 00094 } 00095 00096 00097 //---------------------------functions to flash the LED in different colours---------- 00098 void off() 00099 { 00100 r = g = b = 1.0; // 1 is off, 0 is full brightness 00101 } 00102 00103 void red() 00104 { 00105 r = 0.7; g = 1.0; b = 1.0; // 1 is off, 0 is full brightness 00106 } 00107 00108 void yellow() 00109 { 00110 r = 0.7; g = 0.7; b = 1.0; // 1 is off, 0 is full brightness 00111 } 00112 00113 void green() 00114 { 00115 r = 1.0; g = 0.7; b = 1.0; // 1 is off, 0 is full brightness 00116 } 00117 00118 //---------------------------------------------------------------------------------------- 00119 void flashing_yellow(void const *args) 00120 { bool on = false; 00121 // flashing yellow only while connecting 00122 while (!connected && connack_rc != MQTT_NOT_AUTHORIZED && connack_rc != MQTT_BAD_USERNAME_OR_PASSWORD) 00123 { 00124 on = !on; 00125 if (on) 00126 yellow(); 00127 else 00128 off(); 00129 wait(0.5); 00130 } 00131 } 00132 00133 00134 void flashing_red(void const *args) // to be used when the connection is lost 00135 { 00136 bool on = false; 00137 while (!connected) 00138 { 00139 on = !on; 00140 if (on) 00141 red(); 00142 else 00143 off(); 00144 wait(2.0); 00145 } 00146 } 00147 00148 00149 void printMenu(int menuItem) 00150 { 00151 static char last_line1[60] = "", last_line2[60] = ""; 00152 char line1[60] = "", line2[60] = ""; 00153 00154 switch (menuItem) 00155 { 00156 case 0: 00157 sprintf(line1, "IBM IoT Cloud"); 00158 sprintf(line2, "Scroll with joystick"); 00159 break; 00160 case 1: 00161 sprintf(line1, "Go to:"); 00162 sprintf(line2, "http://ibm.biz/iotqstart"); 00163 break; 00164 case 2: 00165 sprintf(line1, "Device Identity:"); 00166 sprintf(line2, "%s", id); 00167 break; 00168 case 3: 00169 sprintf(line1, "MQTT Status:"); 00170 if (mqttConnecting) 00171 sprintf(line2, "Connecting... %d/5", retryAttempt); 00172 else 00173 { 00174 if (connected) 00175 sprintf(line2, "Connected"); 00176 else 00177 { 00178 switch (connack_rc) 00179 { 00180 case MQTT_CLIENTID_REJECTED: 00181 sprintf(line2, "Clientid rejected"); 00182 break; 00183 case MQTT_BAD_USERNAME_OR_PASSWORD: 00184 sprintf(line2, "Invalid username or password"); 00185 break; 00186 case MQTT_NOT_AUTHORIZED: 00187 sprintf(line2, "Not authorized"); 00188 break; 00189 default: 00190 sprintf(line2, "Disconnected"); 00191 } 00192 } 00193 } 00194 break; 00195 case 4: 00196 sprintf(line1, "Ethernet State:"); 00197 sprintf(line2, ethernetInitialising ? "Initializing..." : "Initialized"); 00198 break; 00199 case 5: 00200 sprintf(line1, "Socket State:"); 00201 if (netConnecting) 00202 sprintf(line2, "Connecting... %d/5", retryAttempt); 00203 else 00204 sprintf(line2, netConnected ? "Connected" : "Disconnected"); 00205 break; 00206 case 6: 00207 sprintf(line1, "IP Address:"); 00208 sprintf(line2, "%s", ip_addr); 00209 break; 00210 case 7: 00211 sprintf(line1, "Gateway:"); 00212 sprintf(line2, "%s", gateway_addr); 00213 break; 00214 case 8: 00215 sprintf(line1, "App version:"); 00216 sprintf(line2, "%s", __APP_SW_REVISION__); 00217 break; 00218 case 9: 00219 sprintf(line1, "Current Timeout:"); 00220 sprintf(line2, "%d ms", connectTimeout); 00221 break; 00222 case 10: //prints out the temperature on the LCD, after the joystick is scrolled down 10 times 00223 sprintf(line1, "Temperature"); 00224 sprintf(line2, "%0.4f degrees C", sensor.temp()); 00225 break; 00226 case 11: //prints out the accelerometer output on the LCD, after the joystick is scrolled down 11 times 00227 sprintf(line1, "accelX accelY accelZ"); 00228 sprintf(line2, "%0.4f, %0.4f, %0.4f", MMA.x(), MMA.y(), MMA.z()); 00229 break; 00230 case 12: //prints out the potentiometer values on the LCD, after the joystick is scrolled down 12 times 00231 sprintf(line1, "Pot1 Pot2"); 00232 sprintf(line2, "%0.4f, %0.4f", ain1.read(), ain2.read()); 00233 break; 00234 } 00235 00236 if (strcmp(line1, last_line1) != 0 || strcmp(line2, last_line2) != 0) 00237 { 00238 lcd.cls(); 00239 lcd.locate(0, 0); 00240 lcd.printf(line1); 00241 strncpy(last_line1, line1, sizeof(last_line1)); 00242 00243 lcd.locate(0,16); 00244 lcd.printf(line2); 00245 strncpy(last_line2, line2, sizeof(last_line2)); 00246 } 00247 } 00248 void setMenu() 00249 { 00250 00251 if (Down) 00252 { 00253 joystickPos = "DOWN"; 00254 if (menuItem >= 0 && menuItem < 12) 00255 printMenu(++menuItem); 00256 } 00257 else if (Left) 00258 joystickPos = "LEFT"; 00259 else if (Click) 00260 joystickPos = "CLICK"; 00261 else if (Up) 00262 { 00263 joystickPos = "UP"; 00264 if (menuItem <= 12 && menuItem > 0) 00265 printMenu(--menuItem); 00266 } 00267 else if (Right) 00268 joystickPos = "RIGHT"; 00269 else 00270 joystickPos = "CENTRE"; 00271 } 00272 00273 void menu_loop(void const *args) 00274 { 00275 int count = 0; 00276 while(true) 00277 { 00278 setMenu(); 00279 if (++count % 10 == 0) 00280 printMenu(menuItem); 00281 Thread::wait(100); 00282 } 00283 } 00284 /* Display a message on the LCD screen prefixed with IBM IoT Cloud*/ 00285 void displayMessage(char* message) 00286 { 00287 lcd.cls(); 00288 lcd.locate(0,0); 00289 lcd.printf("IBM IoT Cloud"); 00290 lcd.locate(0,16); 00291 lcd.printf(message); 00292 } 00293 int connect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) 00294 { 00295 const char* iot_ibm = ".messaging.internetofthings.ibmcloud.com"; 00296 00297 char hostname[strlen(org) + strlen(iot_ibm) + 1]; 00298 sprintf(hostname, "%s%s", org, iot_ibm); 00299 EthernetInterface& eth = ipstack->getEth(); 00300 ip_addr = eth.getIPAddress(); 00301 gateway_addr = eth.getGateway(); 00302 00303 // Construct clientId - d:org:type:id 00304 char clientId[strlen(org) + strlen(type) + strlen(id) + 5]; 00305 sprintf(clientId, "d:%s:%s:%s", org, type, id); 00306 00307 // Network debug statements 00308 LOG("=====================================\n"); 00309 LOG("Connecting Ethernet.\n"); 00310 LOG("IP ADDRESS: %s\n", eth.getIPAddress()); 00311 LOG("MAC ADDRESS: %s\n", eth.getMACAddress()); 00312 LOG("Gateway: %s\n", eth.getGateway()); 00313 LOG("Network Mask: %s\n", eth.getNetworkMask()); 00314 LOG("Server Hostname: %s\n", hostname); 00315 LOG("Client ID: %s\n", clientId); 00316 LOG("=====================================\n"); 00317 00318 netConnecting = true; 00319 int rc = ipstack->connect(hostname, IBM_IOT_PORT, connectTimeout); 00320 if (rc != 0) 00321 { 00322 WARN("IP Stack connect returned: %d\n", rc); 00323 return rc; 00324 } 00325 netConnected = true; 00326 netConnecting = false; 00327 00328 // MQTT Connect 00329 mqttConnecting = true; 00330 MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 00331 data.MQTTVersion = 3; 00332 data.clientID.cstring = clientId; 00333 00334 if (!quickstartMode) 00335 { 00336 data.username.cstring = "use-token-auth"; 00337 data.password.cstring = auth_token; 00338 } 00339 00340 if ((rc = client->connect(data)) == 0) 00341 { 00342 connected = true; 00343 green(); 00344 displayMessage("Connected"); 00345 wait(1); 00346 displayMessage("Scroll with joystick"); 00347 } 00348 else 00349 WARN("MQTT connect returned %d\n", rc); 00350 if (rc >= 0) 00351 connack_rc = rc; 00352 mqttConnecting = false; 00353 return rc; 00354 } 00355 00356 00357 int getConnTimeout(int attemptNumber) 00358 { // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute 00359 // after 20 attempts, retry every 10 minutes 00360 return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600; 00361 } 00362 00363 00364 void attemptConnect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) 00365 { 00366 connected = false; 00367 00368 // make sure a cable is connected before starting to connect 00369 while (!linkStatus()) 00370 { 00371 wait(1.0f); 00372 WARN("Ethernet link not present. Check cable connection\n"); 00373 } 00374 00375 while (connect(client, ipstack) != MQTT_CONNECTION_ACCEPTED) 00376 { 00377 if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) 00378 return; // don't reattempt to connect if credentials are wrong 00379 00380 Thread red_thread(flashing_red); 00381 00382 int timeout = getConnTimeout(++retryAttempt); 00383 WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout); 00384 00385 // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed 00386 // or maybe just add the proper members to do this disconnect and call attemptConnect(...) 00387 00388 // this works - reset the system when the retry count gets to a threshold 00389 if (retryAttempt == 5) 00390 NVIC_SystemReset(); 00391 else 00392 wait(timeout); 00393 } 00394 } 00395 00396 00397 int publish(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) 00398 { 00399 MQTT::Message message; 00400 char* pubTopic = "iot-2/evt/status/fmt/json"; 00401 00402 char buf[250]; 00403 //sends data from accelerator, temperature sensor, 00404 // joystick and potentiometers to the IBM quickstart page 00405 sprintf(buf, 00406 "{\"d\":{\"myName\":\"IoT mbed\",\"accelX\":%0.4f,\"accelY\":%0.4f,\"accelZ\":%0.4f,\"temp\ 00407 ":%0.4f,\"joystick\":\"%s\",\"potentiometer1\":%0.4f,\"potentiometer2\":%0.4f}}", 00408 MMA.x(), MMA.y(), MMA.z(), sensor.temp(), joystickPos, ain1.read(), ain2.read()); 00409 message.qos = MQTT::QOS0; 00410 message.retained = false; 00411 message.dup = false; 00412 message.payload = (void*)buf; 00413 message.payloadlen = strlen(buf); 00414 00415 LOG("Publishing %s\n", buf); 00416 return client->publish(pubTopic, message); 00417 } 00418 00419 00420 char* getMac(EthernetInterface& eth, char* buf, int buflen) // Obtain MAC address 00421 { 00422 strncpy(buf, eth.getMACAddress(), buflen); 00423 00424 char* pos; // Remove colons from mac address 00425 while ((pos = strchr(buf, ':')) != NULL) 00426 memmove(pos, pos + 1, strlen(pos) + 1); 00427 return buf; 00428 } 00429 00430 00431 void messageArrived(MQTT::MessageData& md) 00432 { 00433 MQTT::Message &message = md.message; 00434 char topic[md.topicName.lenstring.len + 1]; 00435 00436 sprintf(topic, "%.*s", md.topicName.lenstring.len, md.topicName.lenstring.data); 00437 00438 LOG("Message arrived on topic %s: %.*s\n", topic, message.payloadlen, message.payload); 00439 00440 // Command topic: iot-2/cmd/blink/fmt/json - cmd is the string between cmd/ and /fmt/ 00441 char* start = strstr(topic, "/cmd/") + 5; 00442 int len = strstr(topic, "/fmt/") - start; 00443 00444 if (memcmp(start, "blink", len) == 0) 00445 { 00446 char payload[message.payloadlen + 1]; 00447 sprintf(payload, "%.*s", message.payloadlen, (char*)message.payload); 00448 00449 char* pos = strchr(payload, '}'); 00450 if (pos != NULL) 00451 { 00452 *pos = '\0'; 00453 if ((pos = strchr(payload, ':')) != NULL) 00454 { 00455 int blink_rate = atoi(pos + 1); 00456 blink_interval = (blink_rate <= 0) ? 0 : (blink_rate > 50 ? 1 : 50/blink_rate); 00457 } 00458 } 00459 } 00460 else 00461 WARN("Unsupported command: %.*s\n", len, start); 00462 } 00463 00464 PwmOut spkr(D6); //defines D6 as a PWM pin 00465 DigitalOut redled(LED_RED); //defines LED_RED as digital output pin 00466 DigitalOut greenled(LED_GREEN); //defines LED_GREEN as digital output pin 00467 int main() 00468 { //if temperature is not within the set threshld, the the speaker gives 00469 //alarm, which is set by PWM, also red LED of FRDM board turns on 00470 if (sensor.temp()>23 || sensor.temp()<20) //sets temperature threshold 00471 {spkr.period(0.010); // set PWM period to 10 ms 00472 spkr=0.5; // set duty cycle to 50% 00473 greenled=!greenled; //turns green LED off and red LED on 00474 } 00475 // if temperature is within the threshold set, the the speaker will be turned 00476 //off and will not give an alarm, also the green LED of the FRDM board will turn on 00477 if (sensor.temp()<23 && sensor.temp()>20) 00478 { 00479 spkr=0.0; // set duty cycle to 50% 00480 redled=!redled; //turns red LED off and green LED on 00481 } 00482 quickstartMode = (strcmp(org, "quickstart") == 0); 00483 00484 lcd.set_font((unsigned char*) Arial12x12); // Set a nice font for the LCD screen 00485 00486 led2 = LED2_OFF; // K64F: turn off the main board LED 00487 displayMessage("Connecting"); 00488 Thread yellow_thread(flashing_yellow); 00489 Thread menu_thread(menu_loop); 00490 00491 LOG("***** IBM IoT Client Ethernet Example *****\n"); 00492 MQTTEthernet ipstack; 00493 ethernetInitialising = false; 00494 MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack); 00495 LOG("Ethernet Initialized\n"); 00496 00497 if (quickstartMode) 00498 getMac(ipstack.getEth(), id, sizeof(id)); 00499 00500 attemptConnect(&client, &ipstack); 00501 00502 if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) 00503 { 00504 red(); 00505 while (true) 00506 wait(1.0); // Permanent failures - don't retry 00507 } 00508 00509 if (!quickstartMode) 00510 { 00511 int rc = 0; 00512 if ((rc = client.subscribe("iot-2/cmd/+/fmt/json", MQTT::QOS1, messageArrived)) != 0) 00513 WARN("rc from MQTT subscribe is %d\n", rc); 00514 } 00515 00516 blink_interval = 0; 00517 int count = 0; 00518 while (true) 00519 { 00520 if (++count == 100) 00521 { // Publish a message every second 00522 if (publish(&client, &ipstack) != 0) 00523 attemptConnect(&client, &ipstack); // if we have lost the connection 00524 count = 0; 00525 } 00526 00527 if (blink_interval == 0) 00528 led2 = LED2_OFF; 00529 else if (count % blink_interval == 0) 00530 led2 = !led2; 00531 client.yield(10); // allow the MQTT client to receive messages 00532 } 00533 } 00534
Generated on Thu Jul 14 2022 01:35:33 by 1.7.2