mina gilada / Mbed 2 deprecated MinaFinalProject

Dependencies:   C12832 EthernetInterface LM75B MMA7660 MQTT mbed-rtos mbed

Fork of IoTClientEthernet by Zhengguo Sheng

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

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