BLe Central Role. It can connect to a number of peripheral that use the same uart ble services
Dependencies: BLE_API mbed nRF51822
Revision 4:59628fe57da0, committed 2016-09-26
- 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
--- 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
--- 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(); }
--- 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
--- 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