A program for IoT demonstration with mbed, EnOcean and MQTT.
Dependencies: C12832 EthernetInterface LM75B MMA7660 MQTT 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 00024 #include "MQTTClient.h" 00025 #include "MQTTEthernet.h" 00026 #include "C12832.h" 00027 #include "Arial12x12.h" 00028 #include "rtos.h" 00029 Serial device(p9, p10); 00030 00031 // Update this to the next number *before* a commit 00032 #define __APP_SW_REVISION__ "10" 00033 00034 // Configuration values needed to connect to IBM IoT Cloud 00035 #define ORG "CHANGE_THIS" // For a registered connection, replace with your org 00036 #define ID "CHANGE_THIS" // For a registered connection, replace with your id 00037 #define AUTH_TOKEN "CHANGE_THIS" // For a registered connection, replace with your auth-token 00038 #define TYPE "CHANGE_THIS" // For a registered connection, replace with your type 00039 00040 #define MQTT_PORT 1883 00041 #define MQTT_TLS_PORT 8883 00042 #define IBM_IOT_PORT MQTT_PORT 00043 00044 #define MQTT_MAX_PACKET_SIZE 250 00045 00046 #if defined(TARGET_UBLOX_C027) 00047 #warning "Compiling for mbed C027" 00048 #include "C027.h" 00049 #elif defined(TARGET_LPC1768) 00050 #warning "Compiling for mbed LPC1768" 00051 #include "LPC1768.h" 00052 #elif defined(TARGET_K64F) 00053 #warning "Compiling for mbed K64F" 00054 #include "K64F.h" 00055 #endif 00056 00057 bool quickstartMode = false; 00058 char org[11] = ORG; 00059 char type[30] = TYPE; 00060 char id[30] = ID; // mac without colons 00061 char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode 00062 00063 bool connected = false; 00064 char* joystickPos = "CENTRE"; 00065 int blink_interval = 0; 00066 00067 int sensor = 0; 00068 int humidity = 0; 00069 int temperature = 0; 00070 00071 uint8_t u8CRC8Table[256] = { 00072 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 00073 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, 00074 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 00075 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 00076 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 00077 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, 00078 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 00079 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, 00080 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 00081 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 00082 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 00083 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, 00084 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 00085 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, 00086 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 00087 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 00088 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 00089 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, 00090 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 00091 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, 00092 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 00093 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 00094 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 00095 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, 00096 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 00097 0x76, 0x71, 0x78, 0x7f, 0x6A, 0x6d, 0x64, 0x63, 00098 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 00099 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 00100 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 00101 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8D, 0x84, 0x83, 00102 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 00103 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 00104 }; 00105 00106 #define proccrc8(u8CRC, u8Data) (u8CRC8Table[u8CRC ^ u8Data]) 00107 00108 void off() 00109 { 00110 r = g = b = 1.0; // 1 is off, 0 is full brightness 00111 } 00112 00113 void red() 00114 { 00115 r = 0.7; g = 1.0; b = 1.0; // 1 is off, 0 is full brightness 00116 } 00117 00118 void yellow() 00119 { 00120 r = 0.7; g = 0.7; b = 1.0; // 1 is off, 0 is full brightness 00121 } 00122 00123 void green() 00124 { 00125 r = 1.0; g = 0.7; b = 1.0; // 1 is off, 0 is full brightness 00126 } 00127 00128 00129 void flashing_yellow(void const *args) 00130 { 00131 bool on = false; 00132 while (!connected) // flashing yellow only while connecting 00133 { 00134 on = !on; 00135 if (on) 00136 yellow(); 00137 else 00138 off(); 00139 wait(0.5); 00140 } 00141 } 00142 00143 00144 void flashing_red(void const *args) // to be used when the connection is lost 00145 { 00146 bool on = false; 00147 while (!connected) 00148 { 00149 on = !on; 00150 if (on) 00151 red(); 00152 else 00153 off(); 00154 wait(2.0); 00155 } 00156 } 00157 00158 /** 00159 * Display a message on the LCD screen prefixed with IBM IoT Cloud 00160 */ 00161 void displayMessage(char* message) 00162 { 00163 lcd.cls(); 00164 lcd.locate(0,0); 00165 lcd.printf("IBM IoT Cloud"); 00166 lcd.locate(0,16); 00167 lcd.printf(message); 00168 } 00169 00170 00171 int connect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) 00172 { 00173 const char* iot_ibm = ".messaging.internetofthings.ibmcloud.com"; 00174 00175 char hostname[strlen(org) + strlen(iot_ibm) + 1]; 00176 sprintf(hostname, "%s%s", org, iot_ibm); 00177 // DEBUG("hostname is %s\n", hostname); 00178 int rc = ipstack->connect(hostname, IBM_IOT_PORT); 00179 if (rc != 0) 00180 return rc; 00181 00182 // Construct clientId - d:org:type:id 00183 char clientId[strlen(org) + strlen(type) + strlen(id) + 5]; 00184 sprintf(clientId, "d:%s:%s:%s", org, type, id); 00185 // DEBUG("clientid is %s\n", clientId); 00186 00187 // MQTT Connect 00188 MQTTPacket_connectData data = MQTTPacket_connectData_initializer; 00189 data.MQTTVersion = 3; 00190 data.clientID.cstring = clientId; 00191 00192 if (!quickstartMode) 00193 { 00194 data.username.cstring = "use-token-auth"; 00195 data.password.cstring = auth_token; 00196 } 00197 00198 if ((rc = client->connect(data)) == 0) 00199 { 00200 connected = true; 00201 green(); 00202 displayMessage("Connected"); 00203 } 00204 return rc; 00205 } 00206 00207 00208 int getConnTimeout(int attemptNumber) 00209 { // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute 00210 // after 20 attempts, retry every 10 minutes 00211 return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600; 00212 } 00213 00214 00215 void attemptConnect(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) 00216 { 00217 int retryAttempt = 0; 00218 connected = false; 00219 00220 // make sure a cable is connected before starting to connect 00221 while (!linkStatus()) { 00222 wait(1.0f); 00223 WARN("Ethernet link not present. Check cable connection\n"); 00224 } 00225 00226 while (connect(client, ipstack) != 0) 00227 { 00228 #if defined(TARGET_K64F) 00229 red(); 00230 #else 00231 Thread red_thread(flashing_red); 00232 #endif 00233 int timeout = getConnTimeout(++retryAttempt); 00234 WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout); 00235 00236 // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed 00237 // or maybe just add the proper members to do this disconnect and call attemptConnect(...) 00238 00239 // this works - reset the system when the retry count gets to a threshold 00240 if (retryAttempt == 5) 00241 NVIC_SystemReset(); 00242 else 00243 wait(timeout); 00244 } 00245 } 00246 00247 00248 int publish(MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTEthernet* ipstack) 00249 { 00250 MQTT::Message message; 00251 char* pubTopic = "iot-2/evt/status/fmt/json"; 00252 00253 char buf[250]; 00254 // sprintf(buf, 00255 // "{\"d\":{\"myName\":\"IoT mbed\",\"accelX\":%0.4f,\"accelY\":%0.4f,\"accelZ\":%0.4f,\"temp\":%0.4f,\"joystick\":\"%s\",\"potentiometer1\":%0.4f,\"potentiometer2\":%0.4f}}", 00256 // MMA.x(), MMA.y(), MMA.z(), sensor.temp(), joystickPos, ain1.read(), ain2.read()); 00257 sprintf(buf, 00258 "{\"d\":{\"sensor\":\"%02X\",\"hum\":%3.1f,\"temp\":%2.2f}}", 00259 sensor, humidity*0.4, temperature*0.16); 00260 message.qos = MQTT::QOS0; 00261 message.retained = false; 00262 message.dup = false; 00263 message.payload = (void*)buf; 00264 message.payloadlen = strlen(buf); 00265 00266 LOG("Publishing %s\n", buf); 00267 return client->publish(pubTopic, message); 00268 } 00269 00270 void messageArrived(MQTT::MessageData& md) 00271 { 00272 MQTT::Message &message = md.message; 00273 char topic[md.topicName.lenstring.len + 1]; 00274 00275 sprintf(topic, "%.*s", md.topicName.lenstring.len, md.topicName.lenstring.data); 00276 00277 LOG("Message arrived on topic %s: %.*s\n", topic, message.payloadlen, message.payload); 00278 00279 // Command topic: iot-2/cmd/blink/fmt/json - cmd is the string between cmd/ and /fmt/ 00280 char* start = strstr(topic, "/cmd/") + 5; 00281 int len = strstr(topic, "/fmt/") - start; 00282 00283 if (memcmp(start, "blink", len) == 0) 00284 { 00285 char payload[message.payloadlen + 1]; 00286 sprintf(payload, "%.*s", message.payloadlen, (char*)message.payload); 00287 00288 char* pos = strchr(payload, '}'); 00289 if (pos != NULL) 00290 { 00291 *pos = '\0'; 00292 if ((pos = strchr(payload, ':')) != NULL) 00293 { 00294 int blink_rate = atoi(pos + 1); 00295 blink_interval = (blink_rate <= 0) ? 0 : (blink_rate > 50 ? 1 : 50/blink_rate); 00296 } 00297 } 00298 } 00299 else 00300 WARN("Unsupported command: %.*s\n", len, start); 00301 } 00302 00303 int main() 00304 { 00305 // quickstartMode = (strcmp(org, "quickstart") == 0); 00306 lcd.set_font((unsigned char*) Arial12x12); // Set a nice font for the LCD screen 00307 led2 = LED2_OFF; // K64F: turn off the main board LED 00308 displayMessage("Connecting"); 00309 00310 #if defined(TARGET_K64F) 00311 yellow(); // Don't flash on the K64F, because starting a thread causes the EthernetInterface init call to hang 00312 #else 00313 Thread yellow_thread(flashing_yellow); 00314 #endif 00315 00316 MQTTEthernet ipstack; 00317 MQTT::Client<MQTTEthernet, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack); 00318 /* 00319 if (quickstartMode) 00320 { 00321 #if defined(TARGET_K64F) 00322 getUUID48(id, sizeof(id)); // getMac doesn't work on the K64F 00323 #else 00324 getMac(ipstack.getEth(), id, sizeof(id)); 00325 #endif 00326 } 00327 */ 00328 attemptConnect(&client, &ipstack); 00329 00330 // if (!quickstartMode) 00331 // { 00332 int rc = 0; 00333 if ((rc = client.subscribe("iot-2/cmd/+/fmt/json", MQTT::QOS1, messageArrived)) != 0) 00334 WARN("rc from MQTT subscribe is %d\n", rc); 00335 // } 00336 00337 // USB400Serial usb400; 00338 device.baud(57600); 00339 00340 int i; 00341 int dataLength; 00342 int optionalLength; 00343 uint8_t c; 00344 uint8_t crc; 00345 00346 while (1) { 00347 if (device.readable()) { 00348 c = device.getc(); 00349 00350 if (c == 0x55) { 00351 crc = 0; 00352 00353 c = device.getc(); 00354 crc = proccrc8(crc, c); 00355 dataLength = c; 00356 00357 c = device.getc(); 00358 crc = proccrc8(crc, c); 00359 dataLength = (dataLength << 8) | c; 00360 00361 c = device.getc(); 00362 crc = proccrc8(crc, c); 00363 optionalLength = c; 00364 00365 c = device.getc(); 00366 crc = proccrc8(crc, c); // packet type 00367 00368 c = device.getc(); 00369 crc = proccrc8(crc, c); // CRC 00370 00371 if (crc == 0) { 00372 crc = 0; 00373 00374 for (i = 0; i < dataLength; i++) { 00375 c = device.getc(); 00376 crc = proccrc8(crc, c); 00377 00378 if (i == 4) { 00379 // printf("Sensor: %02X ", c); 00380 sensor = c; 00381 } 00382 //A5-04-01 00383 if (i == 6) { 00384 humidity = c; 00385 } 00386 if (i == 7) { 00387 temperature = c; 00388 } 00389 } 00390 // printf("hum:%3.1f%% temp:%2.2fC\r\n", humidity*0.4, temperature*0.16); 00391 00392 if (publish(&client, &ipstack) != 0) 00393 attemptConnect(&client, &ipstack); // if we have lost the connection 00394 00395 for (i = 0; i < optionalLength; i++) { 00396 c = device.getc(); 00397 crc = proccrc8(crc, c); 00398 } 00399 00400 c = device.getc(); 00401 crc = proccrc8(crc, c); 00402 00403 } 00404 } 00405 } 00406 } 00407 }
Generated on Thu Jul 14 2022 01:05:30 by 1.7.2