ST Expansion SW Team / Mbed OS Cloud_IBM_MbedOS

Dependencies:   MQTT NDefLib X_NUCLEO_IKS01A2 X_NUCLEO_NFC01A1

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 "easy-connect.h"
00019 #include "MQTTClient.h"
00020 #include "XNucleoIKS01A2.h"
00021 #include "XNucleoNFC01A1.h"
00022 #include "NDefLib/NDefNfcTag.h"
00023 #include "NDefLib/RecordType/RecordURI.h"
00024 #include "MQTTNetwork.h"
00025 #include "MQTTmbed.h"
00026 
00027 
00028 //------------------------------------
00029 // Hyperterminal configuration
00030 // 9600 bauds, 8-bit data, no parity
00031 //------------------------------------
00032 static Serial pc(SERIAL_TX, SERIAL_RX); 
00033 static DigitalOut myled(LED1);
00034 static bool quickstartMode = true;      // set to false to connect with authentication tocken
00035 static bool BlueButtonToggle = false;  
00036 
00037 #define ORG_QUICKSTART           // comment to connect to play.internetofthings.ibmcloud.com
00038 //#define SUBSCRIBE              // uncomment to subscribe to broker msgs (not to be used with IBM broker) 
00039 //#define X_NUCLEO_NFC01A1_PRESENT // uncomment to add NFC support
00040     
00041 #define MQTT_MAX_PACKET_SIZE 400   
00042 #define MQTT_MAX_PAYLOAD_SIZE 300 
00043 
00044  // Configuration values needed to connect to IBM IoT Cloud
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 
00057 #define TYPE DEFAULT_TYPE_NAME       // For a registered connection, replace with your type
00058 #define IBM_IOT_PORT MQTT_PORT
00059     
00060 static char id[30] = ID;                 // mac without colons  
00061 static char org[12] = ORG;        
00062 static int connack_rc = 0; // MQTT connack return code
00063 static char type[30] = TYPE;
00064 static char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode
00065 static bool netConnecting = false;
00066 static int connectTimeout = 1000;
00067 static bool mqttConnecting = false;
00068 static bool netConnected = false;
00069 static bool connected = false;
00070 static int retryAttempt = 0;
00071 static char subscription_url[MQTT_MAX_PAYLOAD_SIZE];
00072 
00073 static LPS22HBSensor *pressure_sensor;
00074 static HTS221Sensor  *humidity_sensor;
00075 static HTS221Sensor  *temp_sensor1;
00076 
00077 #ifndef TARGET_SENSOR_TILE
00078 static void BlueButtonPressed ()
00079 {
00080     BlueButtonToggle = true;    
00081 }
00082 #endif
00083 
00084 #ifdef SUBSCRIBE
00085 void subscribe_cb(MQTT::MessageData & msgMQTT) {
00086     char msg[MQTT_MAX_PAYLOAD_SIZE];
00087     msg[0]='\0';
00088     strncat (msg, (char*)msgMQTT.message.payload, msgMQTT.message.payloadlen);
00089     printf ("--->>> subscribe_cb msg: %s\n\r", msg);
00090 }
00091 
00092 int subscribe(char *pubTopic, MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client)
00093 {
00094     return client->subscribe(pubTopic, MQTT::QOS1, subscribe_cb);
00095 }
00096 #endif
00097 
00098 int connect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network)
00099 {
00100     const char* iot_ibm = MQTT_BROKER_URL;     
00101     char hostname[strlen(org) + strlen(iot_ibm) + 1];
00102     
00103     sprintf(hostname, "%s%s", org, iot_ibm);
00104     // Construct clientId - d:org:type:id
00105     char clientId[strlen(org) + strlen(type) + strlen(id) + 5];  
00106     sprintf(clientId, "d:%s:%s:%s", org, type, id);  
00107     sprintf(subscription_url, "%s.%s/#/device/%s/sensor/", org, "internetofthings.ibmcloud.com",id);
00108 
00109     // Network debug statements 
00110     LOG("=====================================\n\r");
00111     LOG("Nucleo IP ADDRESS: %s\n\r", network->get_ip_address());
00112     LOG("Nucleo MAC ADDRESS: %s\n\r", network->get_mac_address());
00113     LOG("Server Hostname: %s port: %d\n\r", hostname, IBM_IOT_PORT);
00114 //    for(int i = 0; clientId[i]; i++){  // set lowercase mac
00115 //       clientId[i] = tolower(clientId[i]); 
00116 //    }    
00117     LOG("Client ID: %s\n\r", clientId);
00118     LOG("Topic: %s\n\r",MQTT_TOPIC);
00119     LOG("Subscription URL: %s\n\r", subscription_url);
00120     LOG("=====================================\n\r");    
00121     netConnecting = true;
00122     int rc = mqttNetwork->connect(hostname, IBM_IOT_PORT);
00123     if (rc != 0)
00124     {
00125         printf("rc from TCP connect is %d\r\n", rc);
00126         return rc;
00127     }
00128     
00129     printf ("--->TCP Connected\n\r");
00130     netConnected = true;
00131     netConnecting = false;      
00132         
00133     // MQTT Connect
00134     mqttConnecting = true;
00135     MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
00136     data.MQTTVersion = 4;
00137     data.struct_version=0;
00138     data.clientID.cstring = clientId; 
00139     data.keepAliveInterval = MQTT_KEEPALIVE;  // in Sec
00140     if (!quickstartMode) 
00141     {        
00142         data.username.cstring = "use-token-auth";
00143         data.password.cstring = auth_token;
00144     }   
00145     if ((rc = client->connect(data)) != 0) {
00146         printf("rc from MQTT connect is %d\r\n", rc);
00147         connack_rc = rc;
00148         return rc;
00149     }
00150     connected = true;
00151     printf ("--->MQTT Connected\n\r"); 
00152 #ifdef SUBSCRIBE
00153             int rc=0;
00154         if ((rc=subscribe(MQTT_TOPIC, client)) == 0) LOG ("--->>>MQTT subscribed to: %s\n\r",MQTT_TOPIC);
00155             else LOG ("--->>>ERROR MQTT subscribe : %s\n\r",MQTT_TOPIC);
00156 #endif    
00157     mqttConnecting = false;
00158     connack_rc = rc;
00159     return rc;       
00160 }
00161 
00162 
00163 int getConnTimeout(int attemptNumber)
00164 {  // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute
00165    // after 20 attempts, retry every 10 minutes
00166     return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600;
00167 }
00168 
00169 
00170 void attemptConnect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network) 
00171 {
00172     connected = false;
00173            
00174     while (connect(client, mqttNetwork, network) != MQTT_CONNECTION_ACCEPTED) 
00175     {    
00176         if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) {
00177             printf ("File: %s, Line: %d Error: %d\n\r",__FILE__,__LINE__, connack_rc);        
00178             return; // don't reattempt to connect if credentials are wrong
00179         } 
00180         int timeout = getConnTimeout(++retryAttempt);
00181         WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout);
00182         
00183         // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed
00184         //  or maybe just add the proper members to do this disconnect and call attemptConnect(...)        
00185         // this works - reset the system when the retry count gets to a threshold
00186         if (retryAttempt == 5)
00187             NVIC_SystemReset(); 
00188         else
00189             wait(timeout);
00190     }    
00191 }
00192 
00193 int publish(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client)
00194 {
00195     MQTT::Message message;
00196     const char* pubTopic = MQTT_TOPIC;
00197             
00198     char buf[MQTT_MAX_PAYLOAD_SIZE];
00199     float temp, press, hum;
00200 
00201     if (!client->isConnected()) { printf ("---> MQTT DISCONNECTED\n\r"); return MQTT::FAILURE; }
00202     temp_sensor1->get_temperature(&temp);
00203     pressure_sensor->get_pressure(&press);
00204     humidity_sensor->get_humidity(&hum);
00205     sprintf(buf,
00206      "{\"d\":{\"ST\":\"Nucleo-IoT-mbed\",\"Temp\":%0.4f,\"Pressure\":%0.4f,\"Humidity\":%0.4f}}",
00207               temp, press, hum);
00208     message.qos = MQTT::QOS0;
00209     message.retained = false;
00210     message.dup = false;
00211     message.payload = (void*)buf;
00212     message.payloadlen = strlen(buf);
00213 
00214     if( (message.payloadlen + strlen(pubTopic)+1) >= MQTT_MAX_PACKET_SIZE )
00215         printf("message too long!\r\n");
00216     
00217     LOG("Publishing %s\n\r", buf);
00218     return client->publish(pubTopic, message);    
00219 }
00220  
00221 int main()
00222 {   
00223    myled=0;
00224    DevI2C *i2c = new DevI2C(I2C_SDA, I2C_SCL);
00225    i2c->frequency(400000);    
00226     
00227    XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(i2c);   
00228    pressure_sensor = mems_expansion_board->pt_sensor;
00229    temp_sensor1 = mems_expansion_board->ht_sensor;  
00230    humidity_sensor = mems_expansion_board->ht_sensor; 
00231    pressure_sensor->enable();
00232    temp_sensor1->enable();
00233    humidity_sensor->enable();
00234     
00235 #if !defined (TARGET_SENSOR_TILE)
00236     InterruptIn BlueButton(USER_BUTTON);    
00237     BlueButton.fall(&BlueButtonPressed);
00238       BlueButtonToggle = false;
00239 #endif    
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    NetworkInterface* network = easy_connect(true);
00247    if (!network) {
00248        printf ("Error easy_connect\n\r");
00249        return -1;
00250    } 
00251    MQTTNetwork mqttNetwork(network);    
00252    MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE> client(mqttNetwork);
00253         
00254    if (quickstartMode){
00255        char mac[50];  // remove all : from mac
00256        char *digit=NULL;
00257        sprintf (id,"%s", "");                
00258        sprintf (mac,"%s",network->get_mac_address()); 
00259        digit = strtok (mac,":");
00260        while (digit != NULL)
00261        {
00262            strcat (id, digit);
00263            digit = strtok (NULL, ":");
00264        }     
00265    }
00266    printf ("ATTEMPT CONNECT\n\r");
00267    attemptConnect(&client, &mqttNetwork, network);
00268    if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD)    
00269    {
00270        printf ("---ERROR line : %d\n\r", __LINE__);
00271        while (true)
00272        wait(1.0); // Permanent failures - don't retry
00273    }
00274 #ifdef X_NUCLEO_NFC01A1_PRESENT      
00275    // program NFC with broker URL        
00276    XNucleoNFC01A1 *nfcNucleo = XNucleoNFC01A1::instance(*i2c, NULL, XNucleoNFC01A1::DEFAULT_GPO_PIN, XNucleoNFC01A1::DEFAULT_RF_DISABLE_PIN, NC,NC,NC);  
00277    NDefLib::NDefNfcTag& tag = nfcNucleo->get_M24SR().get_NDef_tag();
00278    printf("NFC Init done: !\r\n");
00279    //open the i2c session with the nfc chip
00280    if(tag.open_session()){
00281        //create the NDef message and record
00282        NDefLib::Message msg;
00283        NDefLib::RecordURI rUri(NDefLib::RecordURI::HTTPS, subscription_url);
00284        msg.add_record(&rUri);
00285        //write the tag
00286        if(tag.write(msg)){
00287            printf("Tag writed \r\n");
00288        }
00289        //close the i2c session
00290        if(!tag.close_session()){
00291            printf("Error Closing the session\r\n");
00292        }
00293    }else printf("Error open Session\r\n");             
00294 #endif    
00295    myled=1;         
00296    int count = 0;    
00297    while (true)
00298    {
00299          if (BlueButtonToggle == false && connected == true) {
00300        if (++count == 6)
00301        {               // Publish a message every 3 second
00302            if (publish(&client) != MQTT::SUCCESS) { 
00303                myled=0;
00304                count=0;
00305              client.disconnect();
00306              mqttNetwork.disconnect();             
00307                attemptConnect(&client, &mqttNetwork, network);   // if we have lost the connection                
00308            } else {                  
00309               myled=1;
00310               count=0;
00311                      }
00312        }        
00313        client.yield(500);  // allow the MQTT client to receive subscribe messages and manage keep alive
00314          } else if (BlueButtonToggle == true && connected == true){   // disconnect MQTT
00315              printf ("--->> Disconnect\n\r");
00316        connected = false;
00317              count = 0;
00318              BlueButtonToggle = false;
00319 #ifdef SUBSCRIBE             
00320   //             unsubscribe(const char* topicFilter);   // unsubscribe if subscribed
00321 #endif           
00322              client.disconnect();
00323              mqttNetwork.disconnect();
00324          } else if (BlueButtonToggle == true && connected == false) {
00325              connected = true;
00326              BlueButtonToggle = false;
00327      } else wait (0.5);
00328    }
00329 }
00330