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

Dependencies:   BLE_API mbed nRF51822

Files at this revision

API Documentation at this revision

Comitter:
tanasaro10
Date:
Mon Sep 26 20:02:00 2016 +0000
Parent:
3:d6f80e11a7f4
Commit message:
Central Role sample, it can connect to a number of peripheral that use serial ble services.

Changed in this revision

BLE_API.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
nRF51822.lib Show annotated file Show diff for this revision Revisions of this file
diff -r d6f80e11a7f4 -r 59628fe57da0 BLE_API.lib
--- a/BLE_API.lib	Wed Mar 30 11:21:50 2016 +0000
+++ b/BLE_API.lib	Mon Sep 26 20:02:00 2016 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#ff83f0020480
+http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#66159681aa21
diff -r d6f80e11a7f4 -r 59628fe57da0 main.cpp
--- a/main.cpp	Wed Mar 30 11:21:50 2016 +0000
+++ b/main.cpp	Mon Sep 26 20:02:00 2016 +0000
@@ -6,32 +6,93 @@
 #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);
 
-const uint8_t MPU6050_service_uuid[] = {
-    0x45,0x35,0x56,0x80,0x0F,0xD8,0x5F,0xB5,0x51,0x48,0x30,0x27,0x06,0x9B,0x3F,0xD9
-};
+// 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};
 
-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 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;
 
-DiscoveredCharacteristic accelChar;
-UUID serviceUUID(MPU6050_service_uuid);
-UUID accelUUID(MPU6050_Accel_Characteristic_uuid);
-
-#define NUMBER_OF_PERIPHERALS 3
-
+Ticker periodicActions;
 typedef struct {
     Gap::Handle_t   handle;
     Gap::Address_t  address;
-    bool    connected;
+    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;
@@ -53,59 +114,73 @@
 }
 
 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",
+    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);
     
-    uint8_t len;
-    uint8_t adv_name[31];
-    if( NRF_SUCCESS == ble_advdata_parser(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME,
+    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<3; i++){
+        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;
-            }
+              //  break;
+            } 
         }
-        ble.stopScan();
+        if (gNumOfDevConnected==gNumOfClients)
+            ble.stopScan();
+            pc.printf("Stop Scan\r\n");
     }
 }
 
 void serviceDiscoveryCallback(const DiscoveredService *service) {
-    pc.printf("service found...\r\n");    
+    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 characteristicDiscoveryCallback(const DiscoveredCharacteristic *characteristicP) {
-    pc.printf("characteristicDiscoveryCallback\r\n");
-    
-    accelChar = *characteristicP;
+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());
     
-    for(uint8_t i=0; i<3; i++){
-        if(gs_peripheral[i].connected){
-            ble.gattClient().read(characteristicP->getConnectionHandle(), characteristicP->getValueHandle(), 0);
-        }
+    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");
+    //pc.printf("GAP_EVT_CONNECTED\r\n");
     if (params->role == Gap::CENTRAL) {
 
-        for(uint8_t i=0; i<3; i++){
+        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;
+                break;                
             }
-        }
-                
-        ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicDiscoveryCallback, serviceUUID, accelUUID);
-        
+       }                
+      ble.gattClient().launchServiceDiscovery(params->handle, serviceDiscoveryCallback, characteristicRxTxDiscoveryCallback, serviceUUID);    
     }
 }
 
@@ -114,47 +189,153 @@
 }
 
 void triggerRead(const GattReadCallbackParams *response) {
-    pc.printf("triggerRead.....\r\n");
-    
-    pc.printf("len: %d\r\n", response->len);
+    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;
-    pc.printf("data ");
-    for(int i=0; i < response->len; i++){
-        pc.printf("%f ", (float)data[i]);  
+    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;            
+        }            
     }
-    pc.printf("\r\n");
-    accelChar.read();
 }
 
 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){
+    uint8_t idx;
     pc.printf("disconnected\r\n");
+    idx = getClientIdFromHandle(params->handle);
     
-    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;
+    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);    
         }
     }
-    wait(8.0);
-    ble.gap().startScan(scanCallback);
+}
+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(9600);
-    wait(8.0);
+    pc.baud(19200);
+    wait(5.0);
+    
+    pc.attach( uartCB , pc.RxIrq);
+    ble.init();
     pc.printf("start\r\n");
-
-    ble.init();
-
+    //ble.addService(uartService);
     ble.onConnection(connectionCallback);
     ble.onDisconnection(disconnectionCallback);
-    ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
+    //ble.onDataWritten(WrittenHandler);
+    //ble.gattClient().onServiceDiscoveryTermination(discoveryTerminationCallback);
     ble.gattClient().onDataRead(triggerRead);
-    //ble.gattClient().onDataWrite(triggerToggledWrite);
+    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid));
 
-    ble.gap().setScanParams(500, 400);
+    ble.gap().setScanParams(5, 5);
     ble.gap().startScan(scanCallback);
-
+    // 100 msec
+    periodicActions.attach_us(&at_eachInstant,1000u);        
     while (true) {
         ble.waitForEvent();
     }
diff -r d6f80e11a7f4 -r 59628fe57da0 mbed.bld
--- a/mbed.bld	Wed Mar 30 11:21:50 2016 +0000
+++ b/mbed.bld	Mon Sep 26 20:02:00 2016 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/c0f6e94411f5
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/b0220dba8be7
\ No newline at end of file
diff -r d6f80e11a7f4 -r 59628fe57da0 nRF51822.lib
--- a/nRF51822.lib	Wed Mar 30 11:21:50 2016 +0000
+++ b/nRF51822.lib	Mon Sep 26 20:02:00 2016 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#1751e2e2637a
+http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#f7faad332abc