new version for central test two peripherals

Dependencies:   BLE_API mbed nRF51822

Fork of BLE_Nano_Central_Type3 by Francesco Pavoni

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();
}*/