/********************************************************************* This is an example for our nRF52 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ /* This sketch demonstrates the central API() that allows you to connect * to multiple peripherals boards (Bluefruit nRF52 in peripheral mode, or * any Bluefruit nRF51 boards). * * One or more Bluefruit boards, configured as a peripheral with the * bleuart service running are required for this demo. * * This sketch will: * - Read data from the HW serial port (normally USB serial, accessible * via the Serial Monitor for example), and send any incoming data to * all other peripherals connected to the central device. * - Forward any incoming bleuart messages from a peripheral to all of * the other connected devices. * * It is recommended to give each peripheral board a distinct name in order * to more easily distinguish the individual devices. * * Connection Handle Explanation * ----------------------------- * The total number of connections is BLE_MAX_CONN = BLE_PRPH_MAX_CONN + BLE_CENTRAL_MAX_CONN. * * The 'connection handle' is an integer number assigned by the SoftDevice * (Nordic's proprietary BLE stack). Each connection will receive it's own * numeric 'handle' starting from 0 to BLE_MAX_CONN-1, depending on the order * of connection(s). * * - E.g If our Central board connects to a mobile phone first (running as a peripheral), * then afterwards connects to another Bluefruit board running in peripheral mode, then * the connection handle of mobile phone is 0, and the handle for the Bluefruit * board is 1, and so on. */ /* LED PATTERNS * ------------ * LED_RED - Blinks pattern changes based on the number of connections. * LED_BLUE - Blinks constantly when scanning */ #include // Struct containing peripheral info typedef struct { char name[32]; uint16_t conn_handle; // Each prph need its own bleuart client service BLEClientUart bleuart; } prph_info_t; /* Peripheral info array (one per peripheral device) * * There are 'BLE_CENTRAL_MAX_CONN' central connections, but the * the connection handle can be numerically larger (for example if * the peripheral role is also used, such as connecting to a mobile * device). As such, we need to convert connection handles <-> the array * index where appropriate to prevent out of array accesses. * * Note: One can simply declares the array with BLE_MAX_CONN and use connection * handle as index directly with the expense of SRAM. */ prph_info_t prphs[BLE_CENTRAL_MAX_CONN]; // Software Timer for blinking the RED LED SoftwareTimer blinkTimer; uint8_t connection_num = 0; // for blink pattern void setup() { Serial.begin(115200); while ( !Serial ) delay(10); // for nrf52840 with native usb // Initialize blinkTimer for 100 ms and start it blinkTimer.begin(100, blink_timer_callback); blinkTimer.start(); Serial.println("Bluefruit52 Central Multi BLEUART Example"); Serial.println("-----------------------------------------\n"); // Initialize Bluefruit with max concurrent connections as Peripheral = 1, Central = 1 // SRAM usage required by SoftDevice will increase with number of connections Bluefruit.begin(0, 4); // Set Name Bluefruit.setName("Bluefruit52 Central"); // Init peripheral pool for (uint8_t idx=0; idxconn_handle = conn_handle; Bluefruit.Gap.getPeerName(conn_handle, peer->name, 32); Serial.print("Connected to "); Serial.println(peer->name); Serial.print("Discovering BLE UART service ... "); if ( peer->bleuart.discover(conn_handle) ) { Serial.println("Found it"); Serial.println("Enabling TXD characteristic's CCCD notify bit"); peer->bleuart.enableTXD(); Serial.println("Continue scanning for more peripherals"); Bluefruit.Scanner.start(0); Serial.println("Enter some text in the Serial Monitor to send it to all connected peripherals:"); } else { Serial.println("Found ... NOTHING!"); // disconect since we couldn't find bleuart service Bluefruit.Central.disconnect(conn_handle); } connection_num++; } /** * Callback invoked when a connection is dropped * @param conn_handle * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h */ void disconnect_callback(uint16_t conn_handle, uint8_t reason) { (void) conn_handle; (void) reason; connection_num--; // Mark the ID as invalid int id = findConnHandle(conn_handle); // Non-existant connection, something went wrong, DBG !!! if ( id < 0 ) return; // Mark conn handle as invalid prphs[id].conn_handle = BLE_CONN_HANDLE_INVALID; Serial.print(prphs[id].name); Serial.println(" disconnected!"); } /** * Callback invoked when BLE UART data is received * @param uart_svc Reference object to the service where the data * arrived. */ void bleuart_rx_callback(BLEClientUart& uart_svc) { // uart_svc is prphs[conn_handle].bleuart uint16_t conn_handle = uart_svc.connHandle(); int id = findConnHandle(conn_handle); prph_info_t* peer = &prphs[id]; // Print sender's name Serial.printf("[From %s]: ", peer->name); // Read then forward to all peripherals while ( uart_svc.available() ) { // default MTU with an extra byte for string terminator char buf[20+1] = { 0 }; if ( uart_svc.read(buf,sizeof(buf)-1) ) { Serial.println(buf); sendAll(buf); } } } /** * Helper function to send a string to all connected peripherals */ void sendAll(const char* str) { Serial.print("[Send to All]: "); Serial.println(str); for(uint8_t id=0; id < BLE_CENTRAL_MAX_CONN; id++) { prph_info_t* peer = &prphs[id]; if ( peer->bleuart.discovered() ) { peer->bleuart.print(str); } } } void loop() { // First check if we are connected to any peripherals if ( Bluefruit.Central.connected() ) { // default MTU with an extra byte for string terminator char buf[20+1] = { 0 }; // Read from HW Serial (normally USB Serial) and send to all peripherals if ( Serial.readBytes(buf, sizeof(buf)-1) ) { sendAll(buf); } } } /** * Find the connection handle in the peripheral array * @param conn_handle Connection handle * @return array index if found, otherwise -1 */ int findConnHandle(uint16_t conn_handle) { for(int id=0; id= 10) count = 0; }