Connect through Wifi to IBM MQTT cloud https://quickstart.internetofthings.ibmcloud.com

Dependencies:   MQTT NetworkSocketAPI X_NUCLEO_IDW01M1v2 X_NUCLEO_IKS01A1 mbed NDefLib X_NUCLEO_NFC01A1

Fork of IDW01M1_Cloud_IBM by ST Expansion SW Team

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* SpwfInterface NetworkSocketAPI Example Program
00002  * Copyright (c) 2015 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "mbed.h"
00018 #include "SpwfInterface.h"
00019 #include "TCPSocket.h"
00020 #include "MQTTClient.h"
00021 #include "MQTTWiFi.h"
00022 #include <ctype.h>
00023 #include "x_nucleo_iks01a1.h"
00024 #include "X_NUCLEO_NFC01A1.h"
00025 #include "NDefLib/NDefNfcTag.h"
00026 #include "NDefLib/RecordType/RecordURI.h"
00027 
00028 //------------------------------------
00029 // Hyperterminal configuration
00030 // 9600 bauds, 8-bit data, no parity
00031 //------------------------------------
00032 Serial pc(SERIAL_TX, SERIAL_RX); 
00033 DigitalOut myled(LED1);
00034 bool quickstartMode = true;    
00035 
00036 #define ORG_QUICKSTART           // comment to connect to play.internetofthings.ibmcloud.com
00037 //#define SUBSCRIBE              // uncomment to subscribe to broker msgs (not to be used with IBM broker) 
00038 #define X_NUCLEO_NFC01A1_PRESENT // uncomment to add NFC support
00039     
00040 #define MQTT_MAX_PACKET_SIZE 250   
00041 #define MQTT_MAX_PAYLOAD_SIZE 300 
00042 
00043  // Configuration values needed to connect to IBM IoT Cloud
00044 #define BROKER_URL ".messaging.internetofthings.ibmcloud.com";     
00045 #ifdef ORG_QUICKSTART
00046 #define ORG "quickstart"     // connect to quickstart.internetofthings.ibmcloud.com/ For a registered connection, replace with your org 
00047 #define ID ""
00048 #define AUTH_TOKEN ""
00049 #define DEFAULT_TYPE_NAME "iotsample-mbed-Nucleo"
00050 #else   // not def ORG_QUICKSTART
00051 #define ORG "play"             // connect to play.internetofthings.ibmcloud.com/ For a registered connection, replace with your org
00052 #define ID ""       // For a registered connection, replace with your id
00053 #define AUTH_TOKEN ""// For a registered connection, replace with your auth-token
00054 #define DEFAULT_TYPE_NAME "sensor"
00055 #endif
00056 #define TOPIC  "iot-2/evt/status/fmt/json" 
00057 
00058 #define TYPE DEFAULT_TYPE_NAME       // For a registered connection, replace with your type
00059 #define MQTT_PORT 1883
00060 #define MQTT_TLS_PORT 8883
00061 #define IBM_IOT_PORT MQTT_PORT
00062 // WiFi network credential
00063 #define SSID   ""  // Network must be visible otherwise it can't connect
00064 #define PASSW  ""
00065 #warning "Wifi SSID & password empty"
00066     
00067 char id[30] = ID;                 // mac without colons  
00068 char org[12] = ORG;        
00069 int connack_rc = 0; // MQTT connack return code
00070 const char* ip_addr = "";
00071 char* host_addr = "";
00072 char type[30] = TYPE;
00073 char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode
00074 bool netConnecting = false;
00075 int connectTimeout = 1000;
00076 bool mqttConnecting = false;
00077 bool netConnected = false;
00078 bool connected = false;
00079 int retryAttempt = 0;
00080 char subscription_url[MQTT_MAX_PAYLOAD_SIZE];
00081 
00082 PressureSensor *pressure_sensor;
00083 HumiditySensor *humidity_sensor;
00084 TempSensor *temp_sensor1;
00085 
00086 MQTT::Message message;
00087 MQTTString TopicName={TOPIC};
00088 MQTT::MessageData MsgData(TopicName, message);
00089 
00090 void subscribe_cb(MQTT::MessageData & msgMQTT) {
00091     char msg[MQTT_MAX_PAYLOAD_SIZE];
00092     msg[0]='\0';
00093     strncat (msg, (char*)msgMQTT.message.payload, msgMQTT.message.payloadlen);
00094     printf ("--->>> subscribe_cb msg: %s\n\r", msg);
00095 }
00096 
00097 int subscribe(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack)
00098 {
00099     char* pubTopic = TOPIC;    
00100     return client->subscribe(pubTopic, MQTT::QOS1, subscribe_cb);
00101 }
00102 
00103 int connect(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack)
00104 { 
00105     const char* iot_ibm = BROKER_URL; 
00106 
00107     
00108     char hostname[strlen(org) + strlen(iot_ibm) + 1];
00109     sprintf(hostname, "%s%s", org, iot_ibm);
00110     SpwfSAInterface& WiFi = ipstack->getWiFi();
00111 //    ip_addr = WiFi.get_ip_address();
00112     // Construct clientId - d:org:type:id
00113     char clientId[strlen(org) + strlen(type) + strlen(id) + 5];  
00114     sprintf(clientId, "d:%s:%s:%s", org, type, id);  
00115     sprintf(subscription_url, "%s.%s/#/device/%s/sensor/", org, "internetofthings.ibmcloud.com",id);
00116 
00117     // Network debug statements 
00118     LOG("=====================================\n\r");
00119     LOG("Connecting WiFi.\n\r");
00120     LOG("Nucleo IP ADDRESS: %s\n\r", WiFi.get_ip_address());
00121     LOG("Nucleo MAC ADDRESS: %s\n\r", WiFi.get_mac_address());
00122     LOG("Server Hostname: %s port: %d\n\r", hostname, IBM_IOT_PORT);
00123 //    for(int i = 0; clientId[i]; i++){  // set lowercase mac
00124 //       clientId[i] = tolower(clientId[i]); 
00125 //    }    
00126     LOG("Client ID: %s\n\r", clientId);
00127     LOG("Topic: %s\n\r",TOPIC);
00128     LOG("Subscription URL: %s\n\r", subscription_url);
00129     LOG("=====================================\n\r");
00130     
00131     netConnecting = true;
00132     ipstack->open(&ipstack->getWiFi());
00133     int rc = ipstack->connect(hostname, IBM_IOT_PORT, connectTimeout);    
00134     if (rc != 0)
00135     {
00136         WARN("IP Stack connect returned: %d\n", rc);    
00137         return rc;
00138     }
00139     printf ("--->TCP Connected\n\r");
00140     netConnected = true;
00141     netConnecting = false;
00142 
00143     // MQTT Connect
00144     mqttConnecting = true;
00145     MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
00146     data.MQTTVersion = 4;
00147     data.struct_version=0;
00148     data.clientID.cstring = clientId;
00149  
00150     if (!quickstartMode) 
00151     {        
00152         data.username.cstring = "use-token-auth";
00153         data.password.cstring = auth_token;
00154     }   
00155     if ((rc = client->connect(data)) == 0) 
00156     {       
00157         connected = true;
00158         printf ("--->MQTT Connected\n\r");
00159 #ifdef SUBSCRIBE
00160         if (!subscribe(client, ipstack)) printf ("--->>>MQTT subscribed to: %s\n\r",TOPIC);
00161 #endif           
00162     }
00163     else {
00164         WARN("MQTT connect returned %d\n", rc);        
00165     }
00166     if (rc >= 0)
00167         connack_rc = rc;
00168     mqttConnecting = false;
00169     return rc;
00170 }
00171 
00172 int getConnTimeout(int attemptNumber)
00173 {  // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute
00174    // after 20 attempts, retry every 10 minutes
00175     return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600;
00176 }
00177 
00178 void attemptConnect(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack)
00179 {
00180     connected = false;
00181            
00182     while (connect(client, ipstack) != MQTT_CONNECTION_ACCEPTED) 
00183     {    
00184         if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) {
00185             printf ("File: %s, Line: %d Error: %d\n\r",__FILE__,__LINE__, connack_rc);        
00186             return; // don't reattempt to connect if credentials are wrong
00187         } 
00188         int timeout = getConnTimeout(++retryAttempt);
00189         WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout);
00190         
00191         // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed
00192         //  or maybe just add the proper members to do this disconnect and call attemptConnect(...)        
00193         // this works - reset the system when the retry count gets to a threshold
00194         if (retryAttempt == 5)
00195             NVIC_SystemReset();
00196         else
00197             wait(timeout);
00198     }
00199 }
00200 
00201 int publish(MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTWiFi* ipstack)
00202 {
00203     MQTT::Message message;
00204     char* pubTopic = TOPIC;
00205             
00206     char buf[MQTT_MAX_PAYLOAD_SIZE];
00207     float temp, press, hum;
00208     temp_sensor1->GetTemperature(&temp);
00209     pressure_sensor->GetPressure(&press);
00210     humidity_sensor->GetHumidity(&hum);
00211     sprintf(buf,
00212      "{\"d\":{\"ST\":\"Nucleo-IoT-mbed\",\"Temp\":%0.4f,\"Pressure\":%0.4f,\"Humidity\":%0.4f}}",
00213               temp, press, hum);
00214     message.qos = MQTT::QOS0;
00215     message.retained = false;
00216     message.dup = false;
00217     message.payload = (void*)buf;
00218     message.payloadlen = strlen(buf);
00219     
00220 //    LOG("Publishing %s\n\r", buf);
00221     printf("Publishing %s\n\r", buf);
00222     return client->publish(pubTopic, message);
00223 } 
00224     
00225 int main()
00226 {
00227     const char * ssid = SSID; // Network must be visible otherwise it can't connect
00228     const char * seckey = PASSW;
00229     SpwfSAInterface spwf(D8, D2, false);
00230     
00231 //    Timer tyeld;
00232     myled=0;
00233     DevI2C *i2c = new DevI2C(I2C_SDA, I2C_SCL);
00234     i2c->frequency(400000);    
00235     
00236     X_NUCLEO_IKS01A1 *mems_expansion_board = X_NUCLEO_IKS01A1::Instance(i2c);   
00237     pressure_sensor = mems_expansion_board->pt_sensor;
00238     temp_sensor1 = mems_expansion_board->ht_sensor;  
00239     humidity_sensor = mems_expansion_board->ht_sensor;  
00240     
00241     pc.printf("\r\nX-NUCLEO-IDW01M1 mbed Application\r\n");     
00242     pc.printf("\r\nconnecting to AP\r\n");            
00243 
00244    quickstartMode=false;
00245    if (strcmp(org, "quickstart") == 0){quickstartMode = true;}
00246    MQTTWiFi ipstack(spwf, ssid, seckey, NSAPI_SECURITY_WPA2);
00247    MQTT::Client<MQTTWiFi, Countdown, MQTT_MAX_PACKET_SIZE> client(ipstack);
00248    if (quickstartMode){
00249         char mac[50];  // remove all : from mac
00250         char *digit=NULL;
00251         sprintf (id,"%s", "");                
00252         sprintf (mac,"%s",ipstack.getWiFi().get_mac_address()); 
00253         digit = strtok (mac,":");
00254         while (digit != NULL)
00255         {
00256             strcat (id, digit);
00257             digit = strtok (NULL, ":");
00258         }     
00259    }
00260    attemptConnect(&client, &ipstack);
00261    if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD)    
00262    {
00263       while (true)
00264       wait(1.0); // Permanent failures - don't retry
00265    }
00266 #ifdef X_NUCLEO_NFC01A1_PRESENT      
00267    // program NFC with broker URL        
00268    X_NUCLEO_NFC01A1 *nfcNucleo = X_NUCLEO_NFC01A1::Instance(*i2c, NULL, X_NUCLEO_NFC01A1::DEFAULT_GPO_PIN, X_NUCLEO_NFC01A1::DEFAULT_RF_DISABLE_PIN, NC,NC,NC);  
00269    NDefLib::NDefNfcTag& tag = nfcNucleo->getM24SR().getNDefTag();
00270    printf("NFC Init done: !\r\n");
00271    //open the i2c session with the nfc chip
00272    if(tag.openSession()){
00273        //create the NDef message and record
00274        NDefLib::Message msg;
00275        NDefLib::RecordURI rUri(NDefLib::RecordURI::HTTPS, subscription_url);
00276        msg.addRecord(&rUri);
00277         //write the tag
00278         if(tag.write(msg)){
00279             printf("Tag writed \r\n");
00280         }
00281         //close the i2c session
00282         if(!tag.closeSession()){
00283             printf("Error Closing the session\r\n");
00284         }
00285     }else printf("Error open Session\r\n");             
00286 #endif    
00287    myled=1;         
00288    int count = 0;    
00289 //    tyeld.start();    
00290     while (true)
00291     {
00292         if (++count == 100)
00293         {               // Publish a message every second
00294             if (publish(&client, &ipstack) != 0) { 
00295                 myled=0;
00296                 attemptConnect(&client, &ipstack);   // if we have lost the connection                
00297             } else myled=1;
00298             count = 0;
00299         }        
00300 //        int start = tyeld.read_ms();
00301         client.yield(10);  // allow the MQTT client to receive messages
00302 //        printf ("tyeld: %d\n\r",tyeld.read_ms()-start);
00303     }
00304 }