BLe Central Role. It can connect to a number of peripheral that use the same uart ble services

Dependencies:   BLE_API mbed nRF51822

main.cpp

Committer:
tanasaro10
Date:
2016-09-26
Revision:
4:59628fe57da0
Parent:
3:d6f80e11a7f4

File content as of revision 4:59628fe57da0:

#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"


#define NUMBER_OF_PERIPHERALS 1
#define TXRX_BUF_LEN                     20  /** For radio message transmission*/

BLE ble;
Serial pc(USBTX, USBRX);

// 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};
static const uint8_t uart_tx_uuid_rev[] =   {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 3, 0, 0x3D, 0x71};
static const uint8_t uart_rx_uuid_rev[] =   {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 2, 0, 0x3D, 0x71};

static uint8_t rx_buf[TXRX_BUF_LEN];
static uint8_t rx_len=0;
bool bReadingReady=false, bReadNow=false, bScanUartBLE[NUMBER_OF_PERIPHERALS] = {false,},bScanRqtBLE[NUMBER_OF_PERIPHERALS] = {false,};
bool bScanPending[NUMBER_OF_PERIPHERALS] = {false,},bFirstIn[NUMBER_OF_PERIPHERALS] = {false,};
uint8_t gNumOfClients=1, gNumOfDevConnected=0;
UUID serviceUUID(uart_base_uuid);
UUID accelTxUUID(uart_tx_uuid);
UUID accelRxUUID(uart_rx_uuid);
uint16_t gCounter=0;

Ticker periodicActions;
typedef struct {
    Gap::Handle_t   handle;
    Gap::Address_t  address;
    DiscoveredCharacteristic TxChar;
    DiscoveredCharacteristic RxChar;
    bool connected;
    bool active;
    uint8_t*    deviceName;
} peripheral_t;

static peripheral_t gs_peripheral[NUMBER_OF_PERIPHERALS];

uint8_t txPayload[TXRX_BUF_LEN] = {0,};
uint8_t rxPayload[TXRX_BUF_LEN] = {0,};

/* function to read from a registered client*/
void readFromClient(uint8_t clientNr){
    if (clientNr <gNumOfDevConnected){
        if(gs_peripheral[clientNr].connected){
            //ble.gattClient().read(gs_peripheral[clientNr].RxChar.getConnectionHandle(), gs_peripheral[clientNr].RxChar.getValueHandle(), 0);
            ble.gattClient().read(gs_peripheral[clientNr].handle, gs_peripheral[clientNr].RxChar.getValueHandle(), 0);
        }
    }
}
int8_t getClientIdFromHandle(Gap::Handle_t handle){
uint8_t i=0;
    while (i<gNumOfDevConnected){        
        if (memcmp(&handle,&gs_peripheral[i].handle,sizeof(Gap::Handle_t))==0){
            return i;
        }
        i++;         
    }
    return -1;
}

uint32_t ble_advdata_parser_all(uint8_t type, uint8_t advdata_len, uint8_t *p_advdata)
{
    uint8_t index=0,i,len;
    char myString[32];
    uint8_t my_field_data[32];
    uint8_t field_type;
    
    while(index<advdata_len)
    {
        len = p_advdata[index]-1;
        field_type   = p_advdata[index+1];
         {
            memcpy(my_field_data, &p_advdata[index+2], len);
            
            pc.printf("T:%x ",field_type);
            for (i=0;i<len;i++)
                pc.printf("%x",my_field_data[i]);            
            memcpy(myString,my_field_data, len);
            pc.printf(" %s\r\n",myString);
            memset(my_field_data,0,32);   
        }
        index += len + 2;
    }
    return NRF_SUCCESS;
}

uint32_t ble_advdata_parser(uint8_t type, uint8_t advdata_len, uint8_t *p_advdata, uint8_t *len, uint8_t *p_field_data)
{
    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;
        }
        index += field_length + 1;
    }
    return NRF_ERROR_NOT_FOUND;
}

void scanCallback(const Gap::AdvertisementCallbackParams_t *params) {
    uint8_t len;char myString[32];
    uint8_t adv_name[31];
    
    pc.printf("PeerAddr[%02x%02x%02x%02x%02x%02x], Rssi %d, isScanRsp %u, AdvType %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);
    
    ble_advdata_parser_all(BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME, params->advertisingDataLen, (uint8_t *)params->advertisingData);
   // if( NRF_SUCCESS == ble_advdata_parser(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME,
    if( NRF_SUCCESS == ble_advdata_parser(BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME,
                             params->advertisingDataLen,
                            (uint8_t *)params->advertisingData, &len, adv_name)){
        for(uint8_t i=0; i<gNumOfClients; i++){
            if(gs_peripheral[i].connected == false){
                memcpy(gs_peripheral[i].address, params->peerAddr, sizeof(params->peerAddr)); 
                memcpy(myString,adv_name,len);
                pc.printf("%s - %c\r\n",myString,gs_peripheral[i].address);
                gs_peripheral[i].deviceName = adv_name;
                gs_peripheral[i].active=false;
                ble.connect(params->peerAddr, BLEProtocol::AddressType::RANDOM_STATIC, NULL, NULL);
              //  break;
            } 
        }
        if (gNumOfDevConnected==gNumOfClients)
            ble.stopScan();
            pc.printf("Stop Scan\r\n");
    }
}

void serviceDiscoveryCallback(const DiscoveredService *service) {
    uint8_t buff[16];int16_t i=0;
        
    memcpy( buff,service->getUUID().getBaseUUID(),16);
    /* Check only  for the UART service*/
    if (memcmp(uart_base_uuid_rev,service->getUUID().getBaseUUID(),16)!=0)
        pc.printf("UART Serv Not Found\r\n",i);        
}

void characteristicRxTxDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
    //char buff[30],i=0;
    // Tx and Rx characteristic should be found !
    uint8_t idx=0;
    idx=getClientIdFromHandle(characteristicP->getConnectionHandle());
    
    if (memcmp(uart_tx_uuid_rev,characteristicP->getUUID().getBaseUUID(),characteristicP->getUUID().getLen())==0){        
        gs_peripheral[idx].TxChar = *characteristicP;
        pc.printf("C%c: Tx Service !\r\n",idx);
        
    } else if (memcmp(uart_rx_uuid_rev,characteristicP->getUUID().getBaseUUID(),characteristicP->getUUID().getLen())==0){
        gs_peripheral[idx].RxChar = *characteristicP;
        pc.printf("C%c: Rx Service !\r\n",idx);
    }
}

void connectionCallback(const Gap::ConnectionCallbackParams_t *params) {
    //pc.printf("GAP_EVT_CONNECTED\r\n");
    if (params->role == Gap::CENTRAL) {

        for(uint8_t i=0; i<gNumOfClients; i++){
            if(gs_peripheral[i].connected == false){
                gNumOfDevConnected++;
                gs_peripheral[i].handle = params->handle;
                gs_peripheral[i].connected = true;
                break;                
            }
       }                
      ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicRxTxDiscoveryCallback, serviceUUID);    
    }
}

void discoveryTerminationCallback(Gap::Handle_t connectionHandle) {
    pc.printf("terminated SD for handle %u\r\n", connectionHandle);
}

void triggerRead(const GattReadCallbackParams *response) {
    int idx; char msg[25]={'C',0,':',0}; 
    //uint16_t counter=0;
    static char pmsg[25];
    //pc.printf("triggerRead.....\r\n");
    //pc.printf("len: %d\r\n", response->len);
    idx = getClientIdFromHandle(response->connHandle);
    //pc.printf("trRead idx=%d",idx);
    const uint8_t *data = response->data;
    if (response->len>0){
        msg[1]='0'+idx;
        //pc.printf("C%c:", idx+'0');  
        memcpy(&msg[4],data,response->len);              
        if (bScanUartBLE[idx]==true){ 
            if(bScanRqtBLE[idx]==true){
                bFirstIn[idx] = true;
                gCounter ++;
                // stop condition
                bScanPending[idx] = true;                    
            //pc.printf("C%c:%x %d=%s\r\n",msg[1],msg[4],msg[5],&msg[6]);
            } else {
                //if (memcmp(msg,pmsg,25)!=0){    
                     pc.printf("C%d:%s\r\n",idx,&msg[4]);
                    memcpy(pmsg,msg,25);
                //}
            }
        } else{  
             //if (memcmp(msg,pmsg,25)!=0){    
                    pc.printf("C%d:%s\r\n",idx,&msg[4]);
                    memcpy(pmsg,msg,25);
              //  }        
             gs_peripheral[idx].active = false;            
        }            
    }
}

void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){
    uint8_t idx;
    pc.printf("disconnected\r\n");
    idx = getClientIdFromHandle(params->handle);
    
    if(gs_peripheral[idx].handle == params->handle){
        gs_peripheral[idx].connected = false;
        gs_peripheral[idx].handle = 0xFFFF;
        gs_peripheral[idx].active = false;
        gNumOfDevConnected --;
    }
    pc.printf("numOfDevConn %d",gNumOfDevConnected);
    wait(3.0);
    ble.gap().startScan(scanCallback);
}

void at_eachInstant(){
    for(uint8_t i=0; i<gNumOfDevConnected; i++){
        if (gs_peripheral[i].active == true){            
            if ((bScanRqtBLE[i]==true)&&(bFirstIn[i]==true)){
                if (bScanPending[i] == true){
                    bScanPending[i] = false;     
                } else {
                    bScanRqtBLE[i]=false;
                    pc.printf("gCounter %d",gCounter);
                }       
            }
            readFromClient(i);    
        }
    }
}
void decodeLocalCmd(uint8_t length,uint8_t * buffer){
switch (buffer[0]){
    case 's':{
        /*scan options*/
        if (buffer[1]=='0'){
            /*stop reading scan */
            bScanUartBLE[buffer[2]-'0'] = false;
            
        } else if (buffer[1]=='1'){
            /*start reading scan*/
            bScanUartBLE[buffer[2]-'0'] = true;
        } else if (buffer[1]=='2'){
            uint8_t rxBuff[5]={'x','f','4','\r','\n'};
            /*start reading scan*/
            gCounter =0;
            bScanUartBLE[buffer[2]-'0'] = true;            
            bScanRqtBLE[buffer[2]-'0'] = true;            
            gs_peripheral[buffer[2]-'0'].TxChar.write(5,rxBuff);   
            gs_peripheral[buffer[2]-'0'].active = true;
        } else {
            pc.printf("No existing cmd!\r\n");
        }
        break;
    }
    case 'r':{
        break;
    }
    case 'i':{
        break;
    }
    default:{
        pc.printf("No existing cmd!\r\n");
    }
}

}
void uartCB(void)
{    
    while(pc.readable()) {
        rx_buf[rx_len++] = pc.getc();
        if(rx_len>=20 || rx_buf[rx_len-1]=='\0' || rx_buf[rx_len-1]=='\n') {
            /* start with m then it is a command*/
            if (rx_buf[0]=='m')
            {
                if (rx_buf[1]=='l'){
                    /* local BLE = central BLE, a local command*/
                    decodeLocalCmd(rx_len-2,&rx_buf[2]);
                } else if ((rx_buf[1]>='0')&&(rx_buf[1]<('0'+NUMBER_OF_PERIPHERALS))){
                     /* send command to indicated client*/
                     gs_peripheral[rx_buf[1]-'0'].TxChar.write(rx_len-2,&rx_buf[2]);   
                     gs_peripheral[rx_buf[1]-'0'].active = true;
                     //bReadNow= true;
                } else {
                    pc.printf("Invalid Cmd ! No existing client %c\r\n",rx_buf[1]);
                }            
            }
            rx_len= 0;
            break;
        }
    }
}

int main(void) {
    pc.baud(19200);
    wait(5.0);
    
    pc.attach( uartCB , pc.RxIrq);
    ble.init();
    pc.printf("start\r\n");
    //ble.addService(uartService);
    ble.onConnection(connectionCallback);
    ble.onDisconnection(disconnectionCallback);
    //ble.onDataWritten(WrittenHandler);
    //ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
    ble.gattClient().onDataRead(triggerRead);
    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid));

    ble.gap().setScanParams(5, 5);
    ble.gap().startScan(scanCallback);
    // 100 msec
    periodicActions.attach_us(&at_eachInstant,1000u);        
    while (true) {
        ble.waitForEvent();
    }
}