Experimental BLE project showing how IO can be made with an App over BLE. Pointer to matching App will be added when ready, initially this works with: - Android App [nRF-Master Control Panel], supports Write,Read,Notify - Android Project [BluetoothLeGatt]

Dependencies:   BLE_API mbed nRF51822

This is an experimental project for BLE (Bluetooth LE == Bluetooth Low Energy == Bluetooth Smart).

  • It supports general IO over BLE with Read/Notify/Write support.
  • It is compatible with FOTA using Android App "nRF Master Control Panel" (20150126)
  • IO supported by:
    • Custom Android App is in the WIKI under: Android-App, developed from Android Sample "BluetoothLeGatt"
    • Android App: nRF-MCP (Master Control Panel)
    • iOS App LightBlue.
    • General HRM, HTM, Battery and similar apps should be able to access the matching services.
  • It includes combinations of code from other projects, alternative code included can be tried by moving comments (, //)
  • 20150126 bleIO r25: It compiles for both "Nordic nRF51822" and "Nordic nRF51822 FOTA" platforms
  • 20150126 The matching bleIO App (in wiki) doesn't support FOTA yet, use Android App "nRF Master Control Panel"

Feedback and ideas greatly appreciated!!!

Revision:
5:d36bbb315e31
Parent:
4:976394791d7a
Child:
6:5b6fb35b4450
--- a/main.cpp	Sun Dec 14 00:11:39 2014 +0000
+++ b/main.cpp	Sun Dec 14 01:06:16 2014 +0000
@@ -50,8 +50,9 @@
 #include "BatteryService.h"
 #include "DeviceInformationService.h"
 //#include "DFUService"                 //TODO: DFU and FOTA Support
-#include "HealthThermometerService.h"   //TODO: Temperature, #include "ble_hts.h"
+#include "HealthThermometerService.h"   
 #include "HeartRateService.h"
+#include "LinkLossService.h"            //TODO: How support this?
 //#include "UARTService.h"              //TODO: Add a UART Channel for streaming data like logs?
 
 //==========Debug Console==========
@@ -93,7 +94,7 @@
     GattService::UUID_BATTERY_SERVICE,                  //0x180F    //BatteryLevel
 //    GattService::UUID_HEALTH_THERMOMETER_SERVICE,       //0x1809    //HTM
     //x GattService::UUID_DFU,                          //0x1530 - See UARTServiceShortUUID in BLE_API:DFUService.cpp  //
-    //x GattService::UARTService,                       //0x0001 - See DFUServiceShortUUID  in BLE_API:UARTService.cpp //
+    //x GattService::UARTService,                       //0x0001~0x0003 - See DFUServiceShortUUID  in BLE_API:UARTService.cpp //
     //GattService::UUID_ALERT_NOTIFICATION_SERVICE,     = 0x1811,
     //GattService::UUID_CURRENT_TIME_SERVICE,           = 0x1805,
     //GattService::UUID_HUMAN_INTERFACE_DEVICE_SERVICE, = 0x1812,
@@ -102,13 +103,45 @@
     //GattService::UUID_PHONE_ALERT_STATUS_SERVICE,     = 0x180E,
     //GattService::UUID_REFERENCE_TIME_UPDATE_SERVICE,  = 0x1806,
     //GattService::UUID_SCAN_PARAMETERS_SERVICE,        = 0x1813,
- };
+};
+
+
+
+//build a 128bit UUID table  
+//   0000****-0000-1000-8000 00805F9B34FB == Base for 16bit IDs
+//static const 
+
+// The Nordic UART Service
+//static const uint8_t uart_base_uuid[] = {0x71, 0x3D, 0, 0, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
+//static const uint8_t uart_tx_uuid[]   = {0x71, 0x3D, 0, 3, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
+//static const uint8_t uart_rx_uuid[]   = {0x71, 0x3D, 0, 2, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
+//static const uint8_t uart_base_uuid_rev[] = {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 0, 0, 0x3D, 0x71};
+//const uint8_t  UARTServiceUUID[LENGTH_OF_LONG_UUID] = {          0x6E, 0x40, (uint8_t)(UARTServiceShortUUID >> 8), (uint8_t)(UARTServiceShortUUID & 0xFF), 0xB5, 0xA3, 0xF3, 0x93, 0xE0, 0xA9, 0xE5, 0x0E, 0x24, 0xDC,                                   0xCA,                                 0x9E,};
+//const uint8_t  UARTServiceUUID_reversed[LENGTH_OF_LONG_UUID] = { 0x9E, 0xCA, 0xDC,                                                                         0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, (uint8_t)(UARTServiceShortUUID & 0xFF), (uint8_t)(UARTServiceShortUUID >> 8), 0x40, 0x6E };
  
+// 20141213 From https://developer.bluetooth.org/community/lists/community%20discussion/flat.aspx?rootfolder=/community/lists/community+discussion/16+bit+uuid+vs.+128+uuid&folderctid=0x01200200e2f0e56e3d53004dba96bdf0c357551f
+// 16bit UUID reserved 128bit base = 32 hex digits: 0000****-0000-1000-8000 00805F9B34FB (Careful to use unsigned to avoid negatives and overflows)
+// 32bit UUID reserved 128bit base = 32 hex digits: ********-0000-1000-8000 00805F9B34FB (Careful to use unsigned to avoid negatives and overflows)
+ /*     All the custom GATT based services and characteristics must use a 128 bit UUID. 
+        The Bluetooth_Base_UUID is: 00000000-0000-1000-8000 00805F9B34FB. 
+            All the 16-bit Attribute UUIDs defined in the adopted specifications use the above base. 
+        Generating a 128 bit UUID for custom profiles: For the 128 bit UUID, please refer to The ITU-T Rec. X.667. 
+        You can download a free copy of ITU-T Rec. X.667 from http://www.itu.int/ITU-T/studygroups/com17/oid/X.667-E.pdf. 
+        In addition if you go to http://www.itu.int/ITU-T/asn1/uuid.html, you can generate a unique 128-bit UUID. 
+        Latency: Refer to Core Spec V4.0, Vol 3, Part F - 3.3.1, which is "Ready by Type Request". 
+        If you look at the PDU, you have to send 2 bytes UUID for adopted profiles and 16 bytes UUID for custom profiles. 
+        There is additional 14 extra bytes over head for the custom profiles for "Ready By Type Request Method" 
+        Note: All attribute types are effectively compared as 128-bit UUIDs, even if a 16-bit UUID is provided in this request or defined for an attribute. (See Section 3.2.1.) 
+        A suggestive alternative will be to use a notification method, (see 3.4.7.1), where you don't need the 128 bit UUID or the indication method (see 3.4.7.2) 
+ */
 //========== Prep UUID list (before main()) ==========
-// Adopted 2014Dec from http://developer.mbed.org/users/Bobty/code/BLE_ScoringDevice/
+// Adopted 2014Dec from PUCK and http://developer.mbed.org/users/Bobty/code/BLE_ScoringDevice/
 
 //TODO: Unfinished new code style from http://developer.mbed.org/users/Bobty/code/BLE_ScoringDevice/
 
+//const UUID IR_SERVICE_UUID = stringToUUID("hello           ");
+//const UUID COMMAND_UUID    = stringToUUID("hello command   ");
+
 //UUID List by Advertised 128bit UUID list (PartA, ToDo:)
 // Gatt characteristic and service UUIDs - Readable to UUID
 const UUID stringToUUID(const char* str) {
@@ -200,6 +233,7 @@
     uSentBLE=uSent;
     DEBUG("BLEi: SentI(%u)", uSent); //TODO: PR: Why uSent always "1", expected it to match sent bytes length
     bSent = true;
+    //PR: App nRF-MCP doesn't cause onDataSent(), while App nRF-ToolBox:HRM does cause onDataSent()
     //PR: onDataSent() maybe only occuring when confirmed receive by phone, as onDataSent() didn't happen when phone moved out of range.
 }
 
@@ -216,6 +250,12 @@
     DEBUG("\nBLEi: Callback_BLE_onUpdates(Handle:%d)\r\n", tHandle);
 }
 
+// Adopted 20141213 from http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_LinkLoss/file/440ee5e8595f/main.cpp
+void Callback_BLE_onLinkLoss(LinkLossService::AlertLevel_t level)
+{
+    printf("\nBLEi: Link loss alert[%d]\n", level);
+}
+
 //==========main==========
 int main(void)
 {
@@ -249,20 +289,26 @@
     HeartRateService            hrmService(ble, (uint8_t)111, HeartRateService::LOCATION_FINGER);
     DeviceInformationService    deviceInfo(ble, "Maker", pcDeviceName, "sn1234", "hw00", "fw00", "sw00");//(BLEDevice), pcManufacturer, pcModelNumber, pcSerialNumber, pcHWver, pcFWver, pcSWver
 
+    LinkLossService             linkLoss(ble, Callback_BLE_onLinkLoss, LinkLossService::HIGH_ALERT); //TODO: How to support this?
+
     //BLE3: Setup advertising
     DEBUG("BLE: Setup Advertising\n");
     ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000)); //PR: Advertise 1sec (1Hz)
     ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); //PR: TODO
     ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); //PR: BLE Only, Options(LE_GENERAL_DISCOVERABLE/LE_LIMITED_DISCOVERABLE)
 
-//UUID List by Advertised 16bit UUID list (PartB)
-    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); //PR: Might need to change for Custom Services/Characteristics
+//UUID List Advertised (PartB)
+    /* 16bit */ ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); //PR: Might need to change for Custom Services/Characteristics
+    ///* 128bit*/ ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
 
     ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);//PR: Add Heart Rate
     ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER);  //PR: Add Thermometer
     ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)pcDeviceName, sizeof(pcDeviceName));//PR: Product?
     //Thermometer: ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
     //Thermometer: ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
+
+    //Linkloss: ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); //Linkloss
+    //Linkloss: ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(1000)); //Linkloss /* 1second. */
     ble.startAdvertising();
 
     DEBUG("BLE: Main Loop\n");