![](/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
source/main.cpp
- Committer:
- lorevee
- Date:
- 2018-03-31
- Revision:
- 4:4af40af2530e
- Parent:
- 3:3f35e80ed848
File content as of revision 4:4af40af2530e:
#include <events/mbed_events.h> #include <mbed.h> #include "ble/BLE.h" #include "ble/DiscoveredCharacteristic.h" #include "ble/DiscoveredService.h" #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) { BLE &ble = BLE::Instance(); eventQ.call(Callback<void()>(&ble, &BLE::processEvents)); } /*----------------------------------------------------------------------------*/ /* Complete the initialization of ble module */ void bleInitComplete(BLE::InitializationCompleteCallbackContext *params){ initProcess(); ble_error_t a0, a1, a2, a3; BLE& ble = params->ble; ble_error_t error = params->error; if (error != BLE_ERROR_NONE) { /* In case of error, forward the error handling to onBleInitError */ onBleInitError(ble, error); return; } /* Ensure that it is the default instance of BLE */ if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { return; } /* notification + attr writing */ ble.gattServer().onDataWritten(AttributeModified_CB); /* data read */ ble.gattClient().onDataRead(readCharacteristicCallback); /* when a peripheral node characteristics change */ ble.gattClient().onHVX(onNotificationCallback); /* when a peripheral descriptor is written */ ble.gattClient().onDataWritten(perDescriptorWrittenCallback); /* disconnection */ ble.gap().onDisconnection(disconnectionCallback); /* connection */ ble.gap().onConnection(connectionCallback); 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 /* Setup adv */ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); a0 = ble.gap().accumulateScanResponse(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, manuf_data, sizeof(manuf_data)); a1 = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::UNKNOWN); a2 = ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)NAME_BLESTAR1, sizeof(NAME_BLESTAR1)); ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); //Advertising_Event_Type ble.gap().setAdvertisingInterval(1000); //Adv_Interval a3 = ble.gap().setAdvertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST); //Adv_Filter_Policy if ((a0 != BLE_ERROR_NONE) || (a1 != BLE_ERROR_NONE) || (a2 != BLE_ERROR_NONE) || (a3 != BLE_ERROR_NONE)){ printf("\r\nError setup ADV\n"); } addAllServices(); printMacAddress(); } /*----------------------------------------------------------------------------*/ 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 } /*----------------------------------------------------------------------------*/ int main() { printf("\r\n\n/*******************************************************\n"); printf("\r* *\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); /* 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(); return 0; } /*----------------------------------------------------------------------------*/