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!!!
Diff: main.cpp
- 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");