![](/media/cache/profiles/profile2.jpg.50x50_q85.jpg)
This software setup a central node of a star topology network
Dependencies: MQTT target_st_bluenrg
Fork of ble-star-mbed by
Diff: source/main.cpp
- Revision:
- 4:4af40af2530e
- Parent:
- 3:3f35e80ed848
diff -r 3f35e80ed848 -r 4af40af2530e source/main.cpp --- a/source/main.cpp Tue Mar 13 16:31:07 2018 +0000 +++ b/source/main.cpp Sat Mar 31 15:10:54 2018 +0000 @@ -1,19 +1,3 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2015 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - #include <events/mbed_events.h> #include <mbed.h> #include "ble/BLE.h" @@ -22,13 +6,278 @@ #include <UUID.h> #include <BleMasterService.h> #include <BleSlaveService.h> +#include <string.h> +#include "easy-connect.h" +#include "MQTTClient.h" +#include "MQTTmbed.h" +#include "MQTTNetwork.h" + +/*----------------------------------------------------------------------------*/ + +/* Enable/Disable WiFi (1 = WiFi Enabled, 0 = WiFi Disabled) */ +#define ENABLE_WIFI 1 + +/**** System configuration define ****/ +#define ORG_QUICKSTART // comment to connect to play.internetofthings.ibmcloud.com +#ifndef ORG_QUICKSTART +//#define TLS_EN // uncomment to add TLS to NON quickstart connections +#endif + +#ifdef TLS_EN // Digicert Root Certificate in PEM format (from IBM website) +const char SSL_CA_PEM[] ="-----BEGIN CERTIFICATE-----\n" +"MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n" +"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" +"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" +"QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n" +"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" +"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n" +"9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n" +"CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n" +"nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n" +"43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n" +"T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n" +"gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n" +"BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n" +"TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n" +"DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n" +"hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n" +"06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n" +"PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n" +"YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n" +"CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n" +"-----END CERTIFICATE-----\n"; +#endif + + + +static bool quickstartMode = true; // set to false to connect with authentication tocken + +#define MQTT_MAX_PACKET_SIZE 400 +#define MQTT_MAX_PAYLOAD_SIZE 300 + + + +// Configuration values needed to connect to IBM IoT Cloud +#ifdef ORG_QUICKSTART +#define ORG "quickstart" // connect to quickstart.internetofthings.ibmcloud.com/ For a registered connection, replace with your org +#define ID "" +#define AUTH_TOKEN "" +#define DEFAULT_TYPE_NAME "sensor" +#define DEFAULT_PORT MQTT_PORT + +#else // not def ORG_QUICKSTART +#define ORG MQTT_ORG_ID // connect to ORG.internetofthings.ibmcloud.com/ For a registered connection, replace with your org +#define ID MQTT_DEVICE_ID // For a registered connection is your device id +#define AUTH_TOKEN MQTT_DEVICE_PASSWORD // For a registered connection is a device auth-token +#define DEFAULT_TYPE_NAME MQTT_DEVICE_TYPE // For a registered connection is device type + +#ifdef TLS_EN +#define DEFAULT_PORT MQTT_TLS_PORT +#else +#define DEFAULT_PORT MQTT_PORT + +#endif +#endif + + + +#define TYPE DEFAULT_TYPE_NAME // For a registered connection, replace with your type +#define IBM_IOT_PORT DEFAULT_PORT + +#define MAXLEN_MBED_CONF_APP_WIFI_SSID 32 // same as WIFI_SSID_MAX_LEN in easy_connect +#define MAXLEN_MBED_CONF_APP_WIFI_PASSWORD 64 // same as WIFI_PASSWORD_MAX_LEN + +static char id[30] = ID; // mac without colons +static char org[12] = ORG; +static int connack_rc = 0; // MQTT connack return code +static char type[30] = TYPE; +static char auth_token[30] = AUTH_TOKEN; // Auth_token is only used in non-quickstart mode +static bool netConnecting = false; +static bool mqttConnecting = false; +static bool netConnected = false; +static bool connected = false; +static int retryAttempt = 0; +static char subscription_url[MQTT_MAX_PAYLOAD_SIZE]; +static char ssid[MAXLEN_MBED_CONF_APP_WIFI_SSID]; // Network must be visible otherwise it can't connect +static char seckey[MAXLEN_MBED_CONF_APP_WIFI_PASSWORD]; + +MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE> *pClient; const char NAME_BLESTAR1[] = "BleStar1"; +uint8_t wifi_status; + +uint8_t wifi_data[256]; +uint8_t new_data = 0; +uint8_t *data; +uint8_t wifi_present; +uint8_t start_bnrg; +extern PeripheralDevices_t perDevs; +uint8_t json_buffer[512]; + +/*----------------------------------------------------------------------------*/ + + + +/* Prepare JSON packet with sensors data */ +void prepare_json_pkt (uint8_t * buffer){ + char tempbuff[256]; + + strcpy((char *)buffer,"{\"d\":{\"ST\":\"BLEStar\""); + sprintf(tempbuff, ",%s", data); + strcat((char *)buffer,tempbuff); + strcat((char *)buffer,"}}"); + + return; +} /*----------------------------------------------------------------------------*/ +/* Connect the broker - return the CONNACK*/ +int connect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE> * client, MQTTNetwork *mqttNetwork, NetworkInterface* network) +{ + const char* iot_ibm = MQTT_BROKER_URL; + char hostname[strlen(org) + strlen(iot_ibm) + 1]; + + sprintf(hostname, "%s%s", org, iot_ibm); + // Construct clientId - d:org:type:id + char clientId[strlen(org) + strlen(type) + strlen(id) + 5]; + sprintf(clientId, "d:%s:%s:%s", org, type, id); + sprintf(subscription_url, "%s.%s/#/device/%s/%s/", org, "internetofthings.ibmcloud.com", id, TYPE); + + // Network debug statements + printf("\r\n====================================="); + printf("\r\nNucleo IP ADDRESS: %s\n", network->get_ip_address()); + printf("\r\nNucleo MAC ADDRESS: %s\n", network->get_mac_address()); + printf("\r\nServer Hostname: %s port: %d\n", hostname, IBM_IOT_PORT); + printf("\r\nClient ID: %s\n", clientId); + printf("\r\nTopic: %s\n",MQTT_TOPIC); + printf("\r\nSubscription URL: %s", subscription_url); + printf("\r\n=====================================\r\n"); + netConnecting = true; + + + +#ifdef ORG_QUICKSTART + int tls = TLS_OFF; + const char * cert = NULL; + unsigned int sizeof_cert = 0; + +#else // if !QUICKSTART possible to connect with TLS or not +#ifdef TLS_EN + int tls = TLS_ON; + const char * cert = SSL_CA_PEM; + unsigned int sizeof_cert = sizeof(SSL_CA_PEM); + +#else + int tls = TLS_OFF; + const char * cert = 0; + unsigned int sizeof_cert = 0; + +#endif +#endif + + + //Return code + int rc = mqttNetwork->connect(hostname, IBM_IOT_PORT, tls, cert, sizeof_cert); + if (rc != 0) + { + printf("\r\nrc from TCP connect is %d\n", rc); + return rc; + } + netConnected = true; + netConnecting = false; + + + // MQTT Connect + mqttConnecting = true; + MQTTPacket_connectData data = MQTTPacket_connectData_initializer; + data.MQTTVersion = 4; + data.struct_version=0; + data.clientID.cstring = clientId; + data.keepAliveInterval = 0; //MQTT_KEEPALIVE; // in Sec + if (!quickstartMode){ + data.username.cstring = "use-token-auth"; + data.password.cstring = auth_token; + printf ("\r\nAutToken: %s\n", auth_token); + } + if ((rc = client->connect(data)) != MQTT::SUCCESS) { + printf("\r\nrc from MQTT connect is %d\n", rc); + connack_rc = rc; + return rc; + } + connected = true; + printf ("\r\n--->MQTT Connected\n"); + + mqttConnecting = false; + connack_rc = rc; + return rc; +} +/*----------------------------------------------------------------------------*/ + + + +int getConnTimeout(int attemptNumber) +{ // First 10 attempts try within 3 seconds, next 10 attempts retry after every 1 minute + // after 20 attempts, retry every 10 minutes + return (attemptNumber < 10) ? 3 : (attemptNumber < 20) ? 60 : 600; +} +/*----------------------------------------------------------------------------*/ + + + +void attemptConnect(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client, MQTTNetwork *mqttNetwork, NetworkInterface* network) +{ + connected = false; + + while (connect(client, mqttNetwork, network) != MQTT_CONNECTION_ACCEPTED) + { + if (connack_rc == MQTT_NOT_AUTHORIZED || connack_rc == MQTT_BAD_USERNAME_OR_PASSWORD) { + printf ("\r\nError MQTT_BAD_USERNAME_OR_PASSWORDFile: %s, Line: %d Error: %d \n",__FILE__,__LINE__, connack_rc); + return; // don't reattempt to connect if credentials are wrong + } + int timeout = getConnTimeout(++retryAttempt); + WARN("Retry attempt number %d waiting %d\n", retryAttempt, timeout); + + // if ipstack and client were on the heap we could deconstruct and goto a label where they are constructed + // or maybe just add the proper members to do this disconnect and call attemptConnect(...) + // this works - reset the system when the retry count gets to a threshold + if (retryAttempt == 5) + NVIC_SystemReset(); + else + wait(timeout); + } +} +/*----------------------------------------------------------------------------*/ + + +/* Method to publish data to client (sending data to broker) */ +int publish(MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE>* client){ + //printf("\r\npublish");//DEBUG + + MQTT::Message message; + const char* pubTopic = MQTT_TOPIC; + + + if (!client->isConnected()){ + printf ("\r\npublish failed: MQTT disconnected\n"); + return MQTT::FAILURE; + } + + + message.qos = MQTT::QOS0; // quality of service 0 default + message.retained = false; // (false) new clients will not receive past data + message.dup = false; // (false) no duplicated message + message.payload = (void*)json_buffer; // DATA to be sent + message.payloadlen = strlen((const char *)(json_buffer)); + + + return client->publish(pubTopic, message); +} +/*----------------------------------------------------------------------------*/ + + /* scheduleBleEventsProcessing */ void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) { @@ -36,6 +285,10 @@ eventQ.call(Callback<void()>(&ble, &BLE::processEvents)); } /*----------------------------------------------------------------------------*/ + + + + /* Complete the initialization of ble module */ void bleInitComplete(BLE::InitializationCompleteCallbackContext *params){ @@ -59,12 +312,6 @@ return; } - printf("\r\nBLE Init Completed\n"); - - - /* notification */ - //ble.gattServer().onUpdatesEnabled(onUpdatesEnabledCallback); - //ble.gattServer().onUpdatesDisabled(onUpdatesDisabledCallback); /* notification + attr writing */ ble.gattServer().onDataWritten(AttributeModified_CB); @@ -80,7 +327,7 @@ ble.gap().onDisconnection(disconnectionCallback); /* connection */ ble.gap().onConnection(connectionCallback); - ble.gap().setScanParams(400, 200); //(scanInterval,scanWindow)ms + ble.gap().setScanParams(200, 200); //(scanInterval,scanWindow)ms ble.gap().setScanTimeout(0x0004); //stop scanning after N sec ble.gap().onTimeout(onStopScan); //callback when scan stops @@ -102,20 +349,48 @@ addAllServices(); printMacAddress(); - - - /* Start connection, service/chars discovery and enable notification */ - connectionProcess(); - - /* Start advertising from this point */ - //setSlaveDiscoverable();//DEBUG_ONLY } /*----------------------------------------------------------------------------*/ -void onBleInitError(BLE &ble, ble_error_t error) {} +void onBleInitError(BLE &ble, ble_error_t error){} +/*----------------------------------------------------------------------------*/ + + + +void mainFunc(void){ + + if ((wifi_present) && (perDevs.status != NOTIFICATIONS_DATA_READ)){ + + if((new_data)){ + prepare_json_pkt(json_buffer); + }//if-new_data + start_bnrg = 1; + + }else{ + start_bnrg = 1; + if (perDevs.status != NOTIFICATIONS_DATA_READ) { + HAL_Delay(1000); + } + }//if-else + + + if (start_bnrg){ + eventQ.call(connectionProcess); + } +} +/*----------------------------------------------------------------------------*/ + + +void MQTTpublish(){ + + if((new_data)){ + /* publish every 5 seconds */ + publish(pClient); + }//if-new_data +} /*----------------------------------------------------------------------------*/ @@ -124,20 +399,73 @@ { printf("\r\n\n/*******************************************************\n"); printf("\r* *\n"); - printf("\r* FP-NET-BLESTAR1 (MBED) Expansion Software *\n"); + printf("\r* BLESTAR1 MBED Expansion Software *\n"); printf("\r* *\n"); printf("\r*******************************************************/\n\n\n"); + +#if ENABLE_WIFI + wifi_present = ENABLE_WIFI; + printf("\r\nWi-Fi Enabled!\n"); + printf("\rTo edit SSID and/or Password please refer to mbed_app.json file\n"); + + /* QUICK START MODE */ + quickstartMode=false; + if (strcmp(org, "quickstart") == 0){ + quickstartMode = true; + } + + /* Connect network */ + printf("\r\nConnecting to Access Point...\n\n"); + NetworkInterface * network = easy_connect(true); // SSID and pw in .jason + if (!network){ + printf("\r\nError easy_connect\n"); + } + + /* MQTT CONFIG*/ + printf("\r\nConfiguring MQTT network...\n"); + MQTTNetwork mqttNetwork(network); + MQTT::Client<MQTTNetwork, Countdown, MQTT_MAX_PACKET_SIZE> client(mqttNetwork); + pClient = &client; + + + if (quickstartMode){ + char mac[50]; // remove all : from mac + char *digit=NULL; + sprintf (id,"%s", ""); + sprintf (mac,"%s",network->get_mac_address()); + digit = strtok (mac,":"); + while (digit != NULL) + { + strcat (id, digit); + digit = strtok (NULL, ":"); + } + }//if-quickstart + + /* Connect MQTT broker */ + printf("\r\nConnecting MQTT broker...\n"); + attemptConnect(&client, &mqttNetwork, network); + +#else + printf("\r\nWi-Fi Disabled!\n"); + +#endif + + printf("\r\n\nStarting the BLE module...\n"); + /* Create the ble instance */ BLE &ble = BLE::Instance(); ble.onEventsToProcess(scheduleBleEventsProcessing); - /* Uncommenting to debug the status*/ + /* Uncomment to debug the status*/ //eventQ.call_every(20000, checkStatus); ble.init(bleInitComplete); + /* Start main method */ + eventQ.call_every(100, mainFunc); + eventQ.call_every(1000, MQTTpublish); //dispatch events eventQ.dispatch_forever();