new version for central test two peripherals
Dependencies: BLE_API mbed nRF51822
Fork of BLE_Nano_Central_Type3 by
Diff: main.cpp
- Revision:
- 4:722dfc6fe1de
- Parent:
- 3:d6f80e11a7f4
- Child:
- 5:68a31613f28a
diff -r d6f80e11a7f4 -r 722dfc6fe1de main.cpp --- a/main.cpp Wed Mar 30 11:21:50 2016 +0000 +++ b/main.cpp Wed Jun 01 15:18:25 2016 +0000 @@ -1,3 +1,23 @@ +/* + * Copyright (c) 2016 RedBear + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +/** + * @brief This example is used to demonstrate central functions. + * Device with this application will try to connect to example "BLE_HRM" or "BLE_simplePeripheral" + * If connecting to "BLE_HRM", will get heart rate + * If connecting to "BLE_simplePeripheral, will discovery all services and characteristics + */ #include "mbed.h" #include "ble/BLE.h" #include "ble/DiscoveredCharacteristic.h" @@ -9,19 +29,43 @@ BLE ble; Serial pc(USBTX, USBRX); -const uint8_t MPU6050_service_uuid[] = { - 0x45,0x35,0x56,0x80,0x0F,0xD8,0x5F,0xB5,0x51,0x48,0x30,0x27,0x06,0x9B,0x3F,0xD9 -}; +//const uint8_t MPU6050_service_uuid[] = {0x45,0x35,0x56,0x80,0x0F,0xD8,0x5F,0xB5,0x51,0x48,0x30,0x27,0x06,0x9B,0x3F,0xD9}; +//const uint8_t MPU6050_Accel_Characteristic_uuid[] = {0x45,0x35,0x56,0x81,0x0F,0xD8,0x5F,0xB5,0x51,0x48,0x30,0x27,0x06,0x9B,0x3F,0xD9}; + +static uint8_t service1_uuid[] = {0x71, 0x3D, 0, 0, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E}; +static uint8_t service1_chars1[] = {0x71, 0x3D, 0, 2, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E}; +static uint8_t service1_chars2[] = {0x71, 0x3D, 0, 3, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E}; +static uint8_t service1_chars3[] = {0x71, 0x3D, 0, 4, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E}; + + +UUID service_uuid(0x180D); +UUID chars_uuid1(0x2A37); +UUID chars_uuid2(service1_chars2); +UUID chars_uuid3(service1_chars3); + +static uint8_t device_is_hrm = 0; +static uint8_t device_is_simple_peripheral = 0; -const uint8_t MPU6050_Accel_Characteristic_uuid[] = { - 0x45,0x35,0x56,0x81,0x0F,0xD8,0x5F,0xB5,0x51,0x48,0x30,0x27,0x06,0x9B,0x3F,0xD9 -}; +// When found the match characteristic, set 1. +static uint8_t characteristic_is_fond = 0; +// When found the match descriptor, set 1. +static uint8_t descriptor_is_found = 0; +// To save the hrm characteristic and descriptor +static DiscoveredCharacteristic chars_hrm; +static DiscoveredCharacteristicDescriptor desc_of_chars_hrm(NULL,GattAttribute::INVALID_HANDLE,GattAttribute::INVALID_HANDLE,UUID::ShortUUIDBytes_t(0)); -DiscoveredCharacteristic accelChar; -UUID serviceUUID(MPU6050_service_uuid); -UUID accelUUID(MPU6050_Accel_Characteristic_uuid); +static void scanCallback(const Gap::AdvertisementCallbackParams_t *params); +static void discoveredServiceCallBack(const DiscoveredService *service); +static void discoveredCharacteristicCallBack(const DiscoveredCharacteristic *chars); +static void discoveryTerminationCallBack(Gap::Handle_t connectionHandle); +static void discoveredCharsDescriptorCallBack(const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t *params); +static void discoveredDescTerminationCallBack(const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t *params) ; -#define NUMBER_OF_PERIPHERALS 3 +//DiscoveredCharacteristic accelChar; +//UUID serviceUUID(MPU6050_service_uuid); +//UUID accelUUID(MPU6050_Accel_Characteristic_uuid); + +#define NUMBER_OF_PERIPHERALS 2 typedef struct { Gap::Handle_t handle; @@ -52,7 +96,54 @@ return NRF_ERROR_NOT_FOUND; } -void scanCallback(const Gap::AdvertisementCallbackParams_t *params) { + +void startDiscovery(uint16_t handle) { + /** + * Launch service discovery. Once launched, application callbacks will beinvoked for matching services or characteristics. + * isServiceDiscoveryActive() can be used to determine status, and a termination callback (if one was set up)will be invoked at the end. + * Service discovery can be terminated prematurely,if needed, using terminateServiceDiscovery(). + * + * @param[in] connectionHandle Handle for the connection with the peer. + * @param[in] sc This is the application callback for a matching service. Taken as NULL by default. + * Note: service discovery may still be active when this callback is issued; + * calling asynchronous BLE-stack APIs from within this application callback might cause the stack to abort service discovery. + * If this becomes an issue, it may be better to make a local copy of the discoveredService and wait for service discovery to terminate before operating on the service. + * @param[in] cc This is the application callback for a matching characteristic.Taken as NULL by default. + * Note: service discovery may still be active when this callback is issued; + * calling asynchronous BLE-stack APIs from within this application callback might cause the stack to abort service discovery. + * If this becomes an issue, it may be better to make a local copy of the discoveredCharacteristic and wait for service discovery to terminate before operating on the characteristic. + * @param[in] matchingServiceUUID UUID-based filter for specifying a service in which the application is interested. + * By default it is set as the wildcard UUID_UNKNOWN, in which case it matches all services. + * @param[in] matchingCharacteristicUUIDIn UUID-based filter for specifying characteristic in which the application is interested. + * By default it is set as the wildcard UUID_UKNOWN to match against any characteristic. + * + * @note Using wildcard values for both service-UUID and characteristic-UUID will result in complete service discovery: + * callbacks being called for every service and characteristic. + * + * @note Providing NULL for the characteristic callback will result in characteristic discovery being skipped for each matching service. + * This allows for an inexpensive method to discover only services. + * + * @return BLE_ERROR_NONE if service discovery is launched successfully; else an appropriate error. + */ + if(device_is_hrm) + ble.gattClient().launchServiceDiscovery(handle, discoveredServiceCallBack, discoveredCharacteristicCallBack, service_uuid, chars_uuid1); + if(device_is_simple_peripheral) + ble.gattClient().launchServiceDiscovery(handle, discoveredServiceCallBack, discoveredCharacteristicCallBack); +} + +/** + * @brief Callback handle for scanning device + * + * @param[in] *params params->peerAddr The peer's BLE address + * params->rssi The advertisement packet RSSI value + * params->isScanResponse Whether this packet is the response to a scan request + * params->type The type of advertisement + * (enum from 0 ADV_CONNECTABLE_UNDIRECTED,ADV_CONNECTABLE_DIRECTED,ADV_SCANNABLE_UNDIRECTED,ADV_NON_CONNECTABLE_UNDIRECTED) + * params->advertisingDataLen Length of the advertisement data + * params->advertisingData Pointer to the advertisement packet's data + */ + + void scanCallback(const Gap::AdvertisementCallbackParams_t *params) { pc.printf("adv peerAddr[%02x %02x %02x %02x %02x %02x] rssi %d, isScanResponse %u, AdvertisementType %u\r\n", params->peerAddr[5], params->peerAddr[4], params->peerAddr[3], params->peerAddr[2], params->peerAddr[1], params->peerAddr[0], params->rssi, params->isScanResponse, params->type); @@ -63,11 +154,21 @@ params->advertisingDataLen, (uint8_t *)params->advertisingData, &len, adv_name)){ - for(uint8_t i=0; i<3; i++){ +// Cycle fo rconnect two peripheral + for(uint8_t i=0; i<2; i++){ if(gs_peripheral[i].connected == false){ memcpy(gs_peripheral[i].address, params->peerAddr, sizeof(params->peerAddr)); gs_peripheral[i].deviceName = adv_name; ble.connect(params->peerAddr, BLEProtocol::AddressType::RANDOM_STATIC, NULL, NULL); + // new edit add FP + if( memcmp("TXRX", adv_name, 4) == 0x00 ) { + device_is_simple_peripheral = 1; + } + if(memcmp("Nordic_HRM", adv_name, 10) == 0x00) { + device_is_hrm = 1; + } + // end + break; } } @@ -75,16 +176,145 @@ } } -void serviceDiscoveryCallback(const DiscoveredService *service) { +/** @brief Connection callback handle + * + * @param[in] *params params->handle : The ID for this connection + * params->role : PERIPHERAL = 0x1, // Peripheral Role + * CENTRAL = 0x2, // Central Role. + * params->peerAddrType : The peer's BLE address type + * params->peerAddr : The peer's BLE address + * params->ownAddrType : This device's BLE address type + * params->ownAddr : This devices's BLE address + * params->connectionParams->minConnectionInterval + * params->connectionParams->maxConnectionInterval + * params->connectionParams->slaveLatency + * params->connectionParams->connectionSupervisionTimeout + */ +// Comment 1 +void connectionCallBack( const Gap::ConnectionCallbackParams_t *params ) { + /* + uint8_t index; + + Serial.print("The conn handle : "); + Serial.println(params->handle, HEX); + Serial.print(" The peerAddr : "); + for(index=0; index<6; index++) { + Serial.print(params->peerAddr[index], HEX); + Serial.print(" "); + } + Serial.println(" ");*/ + + // start to discovery + // Attention Comment + // this state is set in startDiscovery + /* + pc.printf("GAP_EVT_CONNECTED\r\n"); + if (params->role == Gap::CENTRAL) { + + for(uint8_t i=0; i<2; i++){ + if(gs_peripheral[i].connected == false){ + gs_peripheral[i].handle = params->handle; + gs_peripheral[i].connected = true; + break; + } + } + ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, serviceUUID, accelUUID); + //ble.gattClient().launchServiceDiscovery(params->handle, discoveredServiceCallBack, discoveredCharacteristicCallBack, service_uuid(0x180D)); + + }*/ + + + //Comment 3 + // check is set Ok + startDiscovery(params->handle); +} + +/** @brief Disconnect callback handle + * + * @param[in] *params params->handle : connect handle + * params->reason : CONNECTION_TIMEOUT = 0x08, + * REMOTE_USER_TERMINATED_CONNECTION = 0x13, + * REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES = 0x14, // Remote device terminated connection due to low resources. + * REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF = 0x15, // Remote device terminated connection due to power off. + * LOCAL_HOST_TERMINATED_CONNECTION = 0x16, + * CONN_INTERVAL_UNACCEPTABLE = 0x3B, + */ + // Comment 2 + +void disconnectionCallBack(const Gap::DisconnectionCallbackParams_t *params) { + // Serial.println("Disconnected, start to scanning"); + + // New edit FP + device_is_simple_peripheral = 0; + device_is_hrm = 0; + characteristic_is_fond = 0; + descriptor_is_found = 0; + ble.startScan(scanCallback); // scanCallback + // end + + pc.printf("disconnected\r\n"); + + for(uint8_t i=0; i<3; i++){ + if(gs_peripheral[i].handle == params->handle){ + gs_peripheral[i].connected = false; + gs_peripheral[i].handle = 0xFFFF; + } + } + wait(8.0); + ble.gap().startScan(scanCallback); +} + +/** @brief Discovered service callback handle + * + * @param[in] *service service->getUUID() The UUID of service + * service->getStartHandle() + * service->getEndHandle() + */ + +static void discoveredServiceCallBack(const DiscoveredService *service) { pc.printf("service found...\r\n"); } -void characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) { +/** @brief Discovered characteristics callback handle + * + * @param[in] *chars chars->getUUID() The UUID of service + * chars->getProperties() broadcast() : Check if broadcasting is permitted. True is permited. + * read() : Check reading is permitted. + * writeWoResp() : Check if writing with Write Command is permitted + * write() : Check if writing with Write Request is permitted. + * notify() : Check notifications are permitted. + * indicate() : Check if indications are permitted. + * authSignedWrite() : Check if writing with Signed Write Command is permitted. + * chars->getDeclHandle() characteristic's declaration attribute handle + * chars->getValueHandle() characteristic's value attribute handle + * chars->getLastHandle() characteristic's last attribute handle + */ +static void discoveredCharacteristicCallBack(const DiscoveredCharacteristic *characteristicP) { pc.printf("characteristicDiscoveryCallback\r\n"); - accelChar = *characteristicP; + //accelChar = *characteristicP; - for(uint8_t i=0; i<3; i++){ + // New edit FP + if(characteristicP->getUUID().shortOrLong() == UUID::UUID_TYPE_SHORT) { + //Serial.println(chars->getUUID().getShortUUID(), HEX); + if(characteristicP->getUUID().getShortUUID() == 0x2A37) { + //Serial.println("Found HRM characteristic "); + characteristic_is_fond = 1; + chars_hrm = *characteristicP; + } + } else { + uint8_t index; + const uint8_t *uuid = characteristicP->getUUID().getBaseUUID(); + for(index=0; index<16; index++) { + // Serial.print(uuid[index], HEX); + //Serial.print(" "); + } + //Serial.println(" "); + } + // end + + + for(uint8_t i=0; i<2; i++){ if(gs_peripheral[i].connected){ ble.gattClient().read(characteristicP->getConnectionHandle(), characteristicP->getValueHandle(), 0); } @@ -92,25 +322,120 @@ } -void connectionCallback(const Gap::ConnectionCallbackParams_t *params) { - pc.printf("GAP_EVT_CONNECTED\r\n"); - if (params->role == Gap::CENTRAL) { + +// Coomet 4 +static void discoveryTerminationCallBack(Gap::Handle_t connectionHandle) { + pc.printf("terminated SD for handle %u\r\n", connectionHandle); + + // New edit FP + if(characteristic_is_fond == 1) { + ble.gattClient().discoverCharacteristicDescriptors(chars_hrm, discoveredCharsDescriptorCallBack, discoveredDescTerminationCallBack); + } + // end +} + - for(uint8_t i=0; i<3; i++){ - if(gs_peripheral[i].connected == false){ - gs_peripheral[i].handle = params->handle; - gs_peripheral[i].connected = true; - break; - } - } - - ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, serviceUUID, accelUUID); - - } +/** @brief Discovered descriptor of characteristic callback handle + * + * @param[in] *params params->characteristic DiscoveredCharacteristic + * params->descriptor descriptor.getUUID() : The uuid of descriptor atrribute + * descriptor.getConnectionHandle() + * descriptor.getAttributeHandle() : Arrtibute handle + */ + static void discoveredCharsDescriptorCallBack(const CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t *params) { + //Serial.println("\r\n----discovered descriptor"); + //Serial.print("Desriptor UUID : "); + //Serial.println(params->descriptor.getUUID().getShortUUID(), HEX); + if(params->descriptor.getUUID().getShortUUID() == 0x2902) { + // Save characteristic info + descriptor_is_found = 1; + desc_of_chars_hrm = params->descriptor; + } + //Serial.print("connectionHandle : "); + //Serial.println(params->descriptor.getConnectionHandle(), HEX); + //Serial.print("descriptor Handle : "); + //Serial.println(params->descriptor.getAttributeHandle(), HEX); +} + +/** @brief Discovered descriptor of characteristic termination callback handle + * + * @param[in] *params params->characteristic DiscoveredCharacteristic + * params->status Status of the discovery operation + */ + static void discoveredDescTerminationCallBack(const CharacteristicDescriptorDiscovery::TerminationCallbackParams_t *params) { + // Serial.println("\r\n----discovery descriptor Termination"); + if(descriptor_is_found) { + // Serial.println("Open HRM notify"); + uint16_t value = 0x0001; + ble.gattClient().write(GattClient::GATT_OP_WRITE_REQ, chars_hrm.getConnectionHandle(), desc_of_chars_hrm.getAttributeHandle(), 2, (uint8_t *)&value); + } } -void discoveryTerminationCallback(Gap::Handle_t connectionHandle) { - pc.printf("terminated SD for handle %u\r\n", connectionHandle); +/** @brief write callback handle + * + * @param[in] *params params->connHandle : The handle of the connection that triggered the event + * params->handle : Attribute Handle to which the write operation applies + * params->writeOp : OP_INVALID = 0x00, // Invalid operation. + * OP_WRITE_REQ = 0x01, // Write request. + * OP_WRITE_CMD = 0x02, // Write command. + * OP_SIGN_WRITE_CMD = 0x03, // Signed write command. + * OP_PREP_WRITE_REQ = 0x04, // Prepare write request. + * OP_EXEC_WRITE_REQ_CANCEL = 0x05, // Execute write request: cancel all prepared writes. + * OP_EXEC_WRITE_REQ_NOW = 0x06, // Execute write request: immediately execute all prepared writes. + * params->offset : Offset for the write operation + * params->len : Length (in bytes) of the data to write + * params->data : Pointer to the data to write + */ + // Attention + void onDataWriteCallBack(const GattWriteCallbackParams *params) { + //Serial.println("GattClient write call back "); +} + + /** @brief read callback handle + * + * @param[in] *params params->connHandle : The handle of the connection that triggered the event + * params->handle : Attribute Handle to which the write operation applies + * params->offset : Offset for the write operation + * params->len : Length (in bytes) of the data to write + * params->data : Pointer to the data to write + */ + + // Attention +void onDataReadCallBack(const GattReadCallbackParams *params) { + // delete comment + /* Serial.println("GattClient read call back "); + Serial.print("The handle : "); + Serial.println(params->handle, HEX); + Serial.print("The offset : "); + Serial.println(params->offset, DEC); + Serial.print("The len : "); + Serial.println(params->len, DEC); + Serial.print("The data : "); + for(uint8_t index=0; index<params->len; index++) { + Serial.print( params->data[index], HEX); + } + Serial.println("");*/ +} + +/** @brief hvx callback handle + * + * @param[in] *params params->connHandle : The handle of the connection that triggered the event + * params->handle : Attribute Handle to which the write operation applies + * params->type : BLE_HVX_NOTIFICATION = 0x01 + * BLE_HVX_INDICATION = 0x02 + * params->len : Length (in bytes) of the data to write + * params->data : Pointer to the data to write + */ + // Attention +void hvxCallBack(const GattHVXCallbackParams *params) { + // delete Cooment + /* Serial.println("GattClient notify call back "); + Serial.print("The len : "); + Serial.println(params->len, DEC); + for(unsigned char index=0; index<params->len; index++) { + Serial.print(params->data[index], HEX); + } + Serial.println("");*/ } void triggerRead(const GattReadCallbackParams *response) { @@ -123,10 +448,12 @@ pc.printf("%f ", (float)data[i]); } pc.printf("\r\n"); - accelChar.read(); + // Comment property + //accelChar.read(); } -void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){ +// is set before +/*void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){ pc.printf("disconnected\r\n"); for(uint8_t i=0; i<3; i++){ @@ -137,7 +464,7 @@ } wait(8.0); ble.gap().startScan(scanCallback); -} +}*/ int main(void) { pc.baud(9600); @@ -146,16 +473,43 @@ ble.init(); - ble.onConnection(connectionCallback); - ble.onDisconnection(disconnectionCallback); - ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback); - ble.gattClient().onDataRead(triggerRead); + ble.onConnection(connectionCallBack); + ble.onDisconnection(disconnectionCallBack); + + // New edit FP + ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallBack); + ble.gattClient().onHVX(hvxCallBack); + ble.gattClient().onDataWrite(onDataWriteCallBack); + ble.gattClient().onDataRead(onDataReadCallBack); + // scan interval : in milliseconds, valid values lie between 2.5ms and 10.24s + // scan window :in milliseconds, valid values lie between 2.5ms and 10.24s + // timeout : in seconds, between 0x0001 and 0xFFFF, 0x0000 disables timeout + // activeScanning : true or false + // end + + + // Original + //ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback); + //ble.gattClient().onDataRead(triggerRead); //ble.gattClient().onDataWrite(triggerToggledWrite); ble.gap().setScanParams(500, 400); ble.gap().startScan(scanCallback); + + // Or + /* + ble.setScanParams(1000, 200, 0, false); + // start scanning + ble.startScan(scanCallBack); + */ while (true) { ble.waitForEvent(); } +} + +// Altenativa +void loop() { + // put your main code here, to run repeatedly: + ble.waitForEvent(); } \ No newline at end of file