new version for central test two peripherals
Dependencies: BLE_API mbed nRF51822
Fork of BLE_Nano_Central_Type3 by
main.cpp
- Committer:
- FranKP2138
- Date:
- 2016-06-02
- Revision:
- 5:68a31613f28a
- Parent:
- 4:722dfc6fe1de
- Child:
- 6:d37a6e3c17c4
File content as of revision 5:68a31613f28a:
/* * 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" #include "ble/DiscoveredService.h" #include "ble/GapScanningParams.h" #include "ble_radio_notification.h" #include "ble_gap.h" 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_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); // (1) this change in sensor PWM 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; // 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)); 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) ; //DiscoveredCharacteristic accelChar; //UUID serviceUUID(MPU6050_service_uuid); //UUID accelUUID(MPU6050_Accel_Characteristic_uuid); #define NUMBER_OF_PERIPHERALS 2 typedef struct { Gap::Handle_t handle; Gap::Address_t address; bool connected; uint8_t* deviceName; } peripheral_t; static peripheral_t gs_peripheral[NUMBER_OF_PERIPHERALS]; uint32_t ble_advdata_parser(uint8_t type, uint8_t advdata_len, uint8_t *p_advdata, uint8_t *len, uint8_t *p_field_data) { pc.printf("ble_advdata_parse \r\n"); uint8_t index=0; uint8_t field_length, field_type; while(index<advdata_len) { field_length = p_advdata[index]; field_type = p_advdata[index+1]; if(field_type == type) { memcpy(p_field_data, &p_advdata[index+2], (field_length-1)); *len = field_length - 1; return NRF_SUCCESS; } pc.printf("FOUND \r\n"); index += field_length + 1; } pc.printf("NRF_ERROR_NOT_FOUND \r\n"); return NRF_ERROR_NOT_FOUND; } 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. */ pc.printf("start discovery \r\n"); 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); uint8_t len; uint8_t adv_name[31]; if( NRF_SUCCESS == ble_advdata_parser(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, params->advertisingDataLen, (uint8_t *)params->advertisingData, &len, adv_name)){ // 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 // (2) Make set name peripheral with button if( memcmp("TXRX", adv_name, 4) == 0x00 ) { device_is_simple_peripheral = 1; } // (3) make set name peripheral with sensor if(memcmp("Nordic_HRM", adv_name, 10) == 0x00) { device_is_hrm = 1; } // end break; } } ble.stopScan(); } } /** @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 pc.printf("connectionCallBack \r\n"); 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"); pc.printf("Disconnected, start to scanning \r\n"); // 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<2; 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"); } /** @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; // (4) change serial.print -> println how make ? // 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); } } } // 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 } /** @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); } } /** @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 : ");*/ pc.printf("triggerRead.....\r\n"); pc.printf("len: %d\r\n", params->len); const uint8_t *data = params->data; pc.printf("data "); for(uint8_t index=0; index<params->len; index++) { //Serial.print( params->data[index], HEX); pc.printf("%f ", (float)data[index]); } pc.printf("\r\n"); //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); pc.printf("%f ", (float)params->data[index]); } // Serial.println(""); } // Option /*void triggerRead(const GattReadCallbackParams *response) { pc.printf("triggerRead.....\r\n"); pc.printf("len: %d\r\n", response->len); const uint8_t *data = response->data; pc.printf("data "); for(int i=0; i < response->len; i++){ pc.printf("%f ", (float)data[i]); } pc.printf("\r\n"); // Comment property //accelChar.read(); }*/ // is set before /*void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){ 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); }*/ int main(void) { pc.baud(9600); wait(8.0); pc.printf("start\r\n"); pc.printf("Avvio start\r\n"); ble.init(); 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) { pc.printf("while true\r\n"); ble.waitForEvent(); } } // Altenativa /*void loop() { // put your main code here, to run repeatedly: ble.waitForEvent(); }*/