Lorenzo Invidia / Mbed OS ble-star-mbed

Dependencies:   MQTT target_st_bluenrg

Fork of ble-star-mbed by Lorenzo Invidia

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include <events/mbed_events.h>
00002 #include <mbed.h>
00003 #include "ble/BLE.h"
00004 #include "ble/DiscoveredCharacteristic.h"
00005 #include "ble/DiscoveredService.h"
00006 #include <UUID.h>
00007 #include <BleMasterService.h>
00008 #include <BleSlaveService.h>
00009 #include <string.h>
00010 #include "easy-connect.h"
00011 #include "MQTTClient.h"
00012 #include "MQTTmbed.h"
00013 #include "MQTTNetwork.h"
00014 
00015 /*----------------------------------------------------------------------------*/
00016 
00017 /* Enable/Disable WiFi (1 = WiFi Enabled, 0 = WiFi Disabled) */
00018 #define ENABLE_WIFI 1
00019 
00020 /****  System configuration define   ****/
00021 #define ORG_QUICKSTART           // comment to connect to play.internetofthings.ibmcloud.com
00022 #ifndef ORG_QUICKSTART
00023 //#define TLS_EN                   // uncomment to add TLS to NON quickstart connections
00024 #endif
00025 
00026 #ifdef TLS_EN     // Digicert Root Certificate in PEM format (from IBM website)
00027 const char SSL_CA_PEM[] ="-----BEGIN CERTIFICATE-----\n"
00028 "MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n"
00029 "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
00030 "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n"
00031 "QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n"
00032 "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
00033 "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n"
00034 "9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n"
00035 "CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n"
00036 "nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n"
00037 "43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n"
00038 "T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n"
00039 "gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n"
00040 "BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n"
00041 "TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n"
00042 "DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n"
00043 "hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n"
00044 "06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n"
00045 "PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n"
00046 "YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n"
00047 "CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n"
00048 "-----END CERTIFICATE-----\n";
00049 #endif
00050 
00051 
00052 
00053 static bool quickstartMode = true;      // set to false to connect with authentication tocken
00054 
00055 #define MQTT_MAX_PACKET_SIZE 400
00056 #define MQTT_MAX_PAYLOAD_SIZE 300
00057 
00058 
00059 
00060 // Configuration values needed to connect to IBM IoT Cloud
00061 #ifdef  ORG_QUICKSTART
00062 #define ORG "quickstart"     // connect to quickstart.internetofthings.ibmcloud.com/ For a registered connection, replace with your org
00063 #define ID ""
00064 #define AUTH_TOKEN ""
00065 #define DEFAULT_TYPE_NAME "sensor"
00066 #define DEFAULT_PORT  MQTT_PORT
00067 
00068 #else   // not def ORG_QUICKSTART
00069 #define ORG MQTT_ORG_ID            // connect to ORG.internetofthings.ibmcloud.com/ For a registered connection, replace with your org
00070 #define ID MQTT_DEVICE_ID          // For a registered connection is your device id
00071 #define AUTH_TOKEN  MQTT_DEVICE_PASSWORD  // For a registered connection is a device auth-token
00072 #define DEFAULT_TYPE_NAME  MQTT_DEVICE_TYPE  // For a registered connection is device type
00073 
00074 #ifdef  TLS_EN
00075 #define DEFAULT_PORT  MQTT_TLS_PORT
00076 #else
00077 #define DEFAULT_PORT  MQTT_PORT
00078 
00079 #endif
00080 #endif
00081 
00082 
00083 
00084 #define TYPE DEFAULT_TYPE_NAME       // For a registered connection, replace with your type
00085 #define IBM_IOT_PORT  DEFAULT_PORT
00086 
00087 #define MAXLEN_MBED_CONF_APP_WIFI_SSID       32  // same as WIFI_SSID_MAX_LEN in easy_connect
00088 #define MAXLEN_MBED_CONF_APP_WIFI_PASSWORD   64  // same as WIFI_PASSWORD_MAX_LEN
00089 
00090 static char     id[30] = ID;                 // mac without colons
00091 static char     org[12] = ORG;
00092 static int      connack_rc = 0; // MQTT connack return code
00093 static char     type[30] = TYPE;
00094 static char     auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode
00095 static bool     netConnecting = false;
00096 static bool     mqttConnecting = false;
00097 static bool     netConnected = false;
00098 static bool     connected = false;
00099 static int      retryAttempt = 0;
00100 static char     subscription_url[MQTT_MAX_PAYLOAD_SIZE];
00101 static char     ssid[MAXLEN_MBED_CONF_APP_WIFI_SSID];     // Network must be visible otherwise it can't connect
00102 static char     seckey[MAXLEN_MBED_CONF_APP_WIFI_PASSWORD];
00103 
00104 MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE> *pClient;
00105 
00106 const char NAME_BLESTAR1[] =    "BleStar1";
00107 
00108 uint8_t wifi_status;
00109 
00110 uint8_t wifi_data[256];
00111 uint8_t new_data = 0;
00112 uint8_t *data;
00113 uint8_t wifi_present;
00114 uint8_t start_bnrg;
00115 extern  PeripheralDevices_t perDevs;
00116 uint8_t json_buffer[512];
00117 
00118 /*----------------------------------------------------------------------------*/
00119 
00120 
00121 
00122 /* Prepare JSON packet with sensors data */
00123 void prepare_json_pkt (uint8_t * buffer){
00124   char tempbuff[256];
00125 
00126   strcpy((char *)buffer,"{\"d\":{\"ST\":\"BLEStar\"");     
00127   sprintf(tempbuff, ",%s", data);
00128   strcat((char *)buffer,tempbuff); 
00129   strcat((char *)buffer,"}}");
00130   
00131   return;
00132 }
00133 /*----------------------------------------------------------------------------*/
00134 
00135 
00136 
00137 /* Connect the broker - return the CONNACK*/
00138 int connect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE> * client, MQTTNetwork *mqttNetwork, NetworkInterface* network)
00139 {
00140     const char* iot_ibm = MQTT_BROKER_URL;
00141     char hostname[strlen(org) + strlen(iot_ibm) + 1];
00142 
00143     sprintf(hostname, "%s%s", org, iot_ibm);
00144     // Construct clientId - d:org:type:id
00145     char clientId[strlen(org) + strlen(type) + strlen(id) + 5];
00146     sprintf(clientId, "d:%s:%s:%s", org, type, id);
00147     sprintf(subscription_url, "%s.%s/#/device/%s/%s/", org, "internetofthings.ibmcloud.com", id, TYPE);
00148 
00149     // Network debug statements
00150     printf("\r\n=====================================");
00151     printf("\r\nNucleo IP ADDRESS: %s\n", network->get_ip_address());
00152     printf("\r\nNucleo MAC ADDRESS: %s\n", network->get_mac_address());
00153     printf("\r\nServer Hostname: %s port: %d\n", hostname, IBM_IOT_PORT);
00154     printf("\r\nClient ID: %s\n", clientId);
00155     printf("\r\nTopic: %s\n",MQTT_TOPIC);
00156     printf("\r\nSubscription URL: %s", subscription_url);
00157     printf("\r\n=====================================\r\n");
00158     netConnecting = true;
00159 
00160 
00161 
00162 #ifdef ORG_QUICKSTART
00163     int tls = TLS_OFF;
00164     const char * cert = NULL;
00165     unsigned int sizeof_cert = 0;
00166     
00167 #else  // if !QUICKSTART possible to connect with TLS or not
00168 #ifdef TLS_EN
00169     int tls = TLS_ON;
00170     const char * cert = SSL_CA_PEM;
00171     unsigned int sizeof_cert = sizeof(SSL_CA_PEM);
00172 
00173 #else
00174     int tls = TLS_OFF;
00175     const char * cert = 0;
00176     unsigned int sizeof_cert = 0;
00177 
00178 #endif
00179 #endif
00180 
00181 
00182     //Return code
00183     int rc = mqttNetwork->connect(hostname, IBM_IOT_PORT, tls, cert, sizeof_cert);
00184     if (rc != 0)
00185     {
00186         printf("\r\nrc from TCP connect is %d\n", rc);
00187         return rc;
00188     }
00189     netConnected = true;
00190     netConnecting = false;
00191 
00192 
00193     // MQTT Connect
00194     mqttConnecting = true;
00195     MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
00196     data.MQTTVersion = 4;
00197     data.struct_version=0;
00198     data.clientID.cstring = clientId;
00199     data.keepAliveInterval = 0; //MQTT_KEEPALIVE;  // in Sec
00200     if (!quickstartMode){
00201         data.username.cstring = "use-token-auth";
00202         data.password.cstring = auth_token;
00203         printf ("\r\nAutToken: %s\n", auth_token);
00204     }
00205     if ((rc = client->connect(data)) != MQTT::SUCCESS) {
00206         printf("\r\nrc from MQTT connect is %d\n", rc);
00207         connack_rc = rc;
00208         return rc;
00209     }
00210     connected = true;
00211     printf ("\r\n--->MQTT Connected\n");
00212 
00213     mqttConnecting = false;
00214     connack_rc = rc;
00215     return rc;
00216 }
00217 /*----------------------------------------------------------------------------*/
00218 
00219 
00220 
00221 int getConnTimeout(int attemptNumber)
00222 {  // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute
00223    // after 20 attempts, retry every 10 minutes
00224     return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600;
00225 }
00226 /*----------------------------------------------------------------------------*/
00227 
00228 
00229 
00230 void attemptConnect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network)
00231 {
00232     connected = false;
00233 
00234     while (connect(client, mqttNetwork, network) != MQTT_CONNECTION_ACCEPTED)
00235     {
00236         if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) {
00237             printf ("\r\nError MQTT_BAD_USERNAME_OR_PASSWORDFile: %s, Line: %d Error: %d \n",__FILE__,__LINE__, connack_rc);
00238             return; // don't reattempt to connect if credentials are wrong
00239         }
00240         int timeout = getConnTimeout(++retryAttempt);
00241         WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout);
00242 
00243         // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed
00244         //  or maybe just add the proper members to do this disconnect and call attemptConnect(...)
00245         // this works - reset the system when the retry count gets to a threshold
00246         if (retryAttempt == 5)
00247             NVIC_SystemReset();
00248         else
00249             wait(timeout);
00250     }
00251 }
00252 /*----------------------------------------------------------------------------*/
00253 
00254 
00255 /* Method to publish data to client (sending data to broker) */
00256 int publish(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client){
00257     //printf("\r\npublish");//DEBUG
00258 
00259     MQTT::Message message;
00260     const char* pubTopic = MQTT_TOPIC;
00261 
00262 
00263     if (!client->isConnected()){ 
00264         printf ("\r\npublish failed: MQTT disconnected\n"); 
00265         return MQTT::FAILURE; 
00266     }
00267     
00268             
00269     message.qos = MQTT::QOS0;               // quality of service 0 default
00270     message.retained = false;               // (false) new clients will not receive past data
00271     message.dup = false;                    // (false) no duplicated message
00272     message.payload = (void*)json_buffer;   // DATA to be sent
00273     message.payloadlen = strlen((const char *)(json_buffer));
00274 
00275 
00276     return client->publish(pubTopic, message);
00277 }
00278 /*----------------------------------------------------------------------------*/
00279 
00280 
00281 
00282 /* scheduleBleEventsProcessing */
00283 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
00284     BLE &ble = BLE::Instance();
00285     eventQ.call(Callback<void()>(&ble, &BLE::processEvents));
00286 }
00287 /*----------------------------------------------------------------------------*/
00288 
00289 
00290 
00291 
00292 /* Complete the initialization of ble module */
00293 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params){
00294   
00295   
00296     initProcess();
00297     ble_error_t a0, a1, a2, a3;
00298         
00299     BLE&        ble   = params->ble;
00300     ble_error_t error = params->error;
00301 
00302     if (error != BLE_ERROR_NONE) {
00303         /* In case of error, forward the error handling to onBleInitError */
00304         onBleInitError(ble, error);
00305         return;
00306     }
00307 
00308 
00309 
00310     /* Ensure that it is the default instance of BLE */
00311     if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
00312         return;
00313     }
00314     
00315     
00316     /* notification + attr writing */
00317     ble.gattServer().onDataWritten(AttributeModified_CB);
00318     /* data read */
00319     ble.gattClient().onDataRead(readCharacteristicCallback);
00320     /* when a peripheral node characteristics change */
00321     ble.gattClient().onHVX(onNotificationCallback);    
00322     /* when a peripheral descriptor is written */
00323     ble.gattClient().onDataWritten(perDescriptorWrittenCallback);
00324     
00325     
00326     /* disconnection */
00327     ble.gap().onDisconnection(disconnectionCallback);    
00328     /* connection */
00329     ble.gap().onConnection(connectionCallback);
00330     ble.gap().setScanParams(200, 200);    //(scanInterval,scanWindow)ms
00331     ble.gap().setScanTimeout(0x0004);     //stop scanning after N sec
00332     ble.gap().onTimeout(onStopScan);      //callback when scan stops
00333     
00334     
00335     
00336     
00337     /* Setup adv */
00338     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00339     a0 = ble.gap().accumulateScanResponse(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, manuf_data, sizeof(manuf_data));
00340     a1 = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::UNKNOWN);
00341     a2 = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)NAME_BLESTAR1, sizeof(NAME_BLESTAR1));
00342     ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); //Advertising_Event_Type
00343     ble.gap().setAdvertisingInterval(1000); //Adv_Interval
00344     a3 = ble.gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST); //Adv_Filter_Policy      
00345     if ((a0 != BLE_ERROR_NONE) || (a1 != BLE_ERROR_NONE) || (a2 != BLE_ERROR_NONE) || (a3 != BLE_ERROR_NONE)){
00346         printf("\r\nError setup ADV\n");
00347     }
00348     
00349     
00350     addAllServices();
00351     printMacAddress();
00352 
00353 }
00354 /*----------------------------------------------------------------------------*/
00355 
00356 
00357 
00358 void onBleInitError(BLE &ble, ble_error_t error){}
00359 /*----------------------------------------------------------------------------*/
00360 
00361 
00362 
00363 void mainFunc(void){
00364     
00365     if ((wifi_present) && (perDevs.status != NOTIFICATIONS_DATA_READ)){
00366         
00367         if((new_data)){
00368             prepare_json_pkt(json_buffer);
00369         }//if-new_data
00370         start_bnrg = 1;
00371         
00372     }else{
00373         start_bnrg = 1;
00374         if (perDevs.status != NOTIFICATIONS_DATA_READ) {
00375             HAL_Delay(1000);
00376         }
00377     }//if-else
00378     
00379     
00380     if (start_bnrg){
00381         eventQ.call(connectionProcess);
00382     }
00383 }
00384 /*----------------------------------------------------------------------------*/
00385 
00386 
00387 void MQTTpublish(){
00388     
00389     if((new_data)){
00390         /* publish every 5 seconds */
00391         publish(pClient);            
00392     }//if-new_data    
00393 }
00394 /*----------------------------------------------------------------------------*/
00395 
00396 
00397 
00398 int main()
00399 {
00400     printf("\r\n\n/*******************************************************\n");
00401     printf("\r*                                                      *\n");
00402     printf("\r*           BLESTAR1 MBED Expansion Software           *\n");
00403     printf("\r*                                                      *\n");
00404     printf("\r*******************************************************/\n\n\n");
00405   
00406   
00407 #if ENABLE_WIFI
00408     wifi_present = ENABLE_WIFI;
00409     printf("\r\nWi-Fi Enabled!\n");
00410     printf("\rTo edit SSID and/or Password please refer to mbed_app.json file\n");
00411 
00412     /* QUICK START MODE */
00413     quickstartMode=false;
00414     if (strcmp(org, "quickstart") == 0){
00415         quickstartMode = true;
00416     }
00417     
00418     /* Connect network */
00419     printf("\r\nConnecting to Access Point...\n\n");
00420     NetworkInterface * network = easy_connect(true); // SSID and pw in .jason
00421     if (!network){
00422         printf("\r\nError easy_connect\n");
00423     }
00424             
00425     /* MQTT CONFIG*/
00426     printf("\r\nConfiguring MQTT network...\n");
00427     MQTTNetwork mqttNetwork(network);
00428     MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE> client(mqttNetwork);
00429     pClient = &client;
00430     
00431     
00432     if (quickstartMode){
00433         char mac[50];  // remove all : from mac
00434         char *digit=NULL;
00435         sprintf (id,"%s", "");
00436         sprintf (mac,"%s",network->get_mac_address());
00437         digit = strtok (mac,":");
00438         while (digit != NULL)
00439         {
00440             strcat (id, digit);
00441             digit = strtok (NULL, ":");
00442         }
00443     }//if-quickstart
00444             
00445     /* Connect MQTT broker  */
00446     printf("\r\nConnecting MQTT broker...\n");
00447     attemptConnect(&client, &mqttNetwork, network);
00448     
00449 #else
00450     printf("\r\nWi-Fi Disabled!\n");    
00451 
00452 #endif  
00453   
00454     printf("\r\n\nStarting the BLE module...\n");
00455   
00456     /* Create the ble instance */
00457     BLE &ble = BLE::Instance();
00458     
00459     ble.onEventsToProcess(scheduleBleEventsProcessing);
00460     
00461     /* Uncomment to debug the status*/
00462     //eventQ.call_every(20000, checkStatus);
00463     
00464     ble.init(bleInitComplete);   
00465     
00466     /* Start main method */
00467     eventQ.call_every(100, mainFunc);
00468     eventQ.call_every(1000, MQTTpublish);
00469     
00470     //dispatch events
00471     eventQ.dispatch_forever();
00472 
00473     return 0;   
00474 }
00475 /*----------------------------------------------------------------------------*/
00476 
00477 
00478 
00479 
00480