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