diff options
Diffstat (limited to 'arduino/libraries/Bluefruit52Lib/examples/Central')
7 files changed, 1556 insertions, 0 deletions
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart/central_bleuart.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart/central_bleuart.ino new file mode 100755 index 0000000..8c59162 --- /dev/null +++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart/central_bleuart.ino @@ -0,0 +1,207 @@ +/********************************************************************* + 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 demonstrate the central API(). A additional bluefruit + * that has bleuart as peripheral is required for the demo. + */ +#include <bluefruit.h> + +BLEClientBas clientBas; // battery client +BLEClientDis clientDis; // device information client +BLEClientUart clientUart; // bleuart client + +void setup() +{ + Serial.begin(115200); + while ( !Serial ) delay(10); // for nrf52840 with native usb + + Serial.println("Bluefruit52 Central BLEUART Example"); + Serial.println("-----------------------------------\n"); + + // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1 + // SRAM usage required by SoftDevice will increase dramatically with number of connections + Bluefruit.begin(0, 1); + + Bluefruit.setName("Bluefruit52 Central"); + + // Configure Battyer client + clientBas.begin(); + + // Configure DIS client + clientDis.begin(); + + // Init BLE Central Uart Serivce + clientUart.begin(); + clientUart.setRxCallback(bleuart_rx_callback); + + // Increase Blink rate to different from PrPh advertising mode + Bluefruit.setConnLedInterval(250); + + // Callbacks for Central + Bluefruit.Central.setConnectCallback(connect_callback); + Bluefruit.Central.setDisconnectCallback(disconnect_callback); + + /* Start Central Scanning + * - Enable auto scan if disconnected + * - Interval = 100 ms, window = 80 ms + * - Don't use active scan + * - Start(timeout) with timeout = 0 will scan forever (until connected) + */ + Bluefruit.Scanner.setRxCallback(scan_callback); + Bluefruit.Scanner.restartOnDisconnect(true); + Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms + Bluefruit.Scanner.useActiveScan(false); + Bluefruit.Scanner.start(0); // // 0 = Don't stop scanning after n seconds +} + +/** + * Callback invoked when scanner pick up an advertising data + * @param report Structural advertising data + */ +void scan_callback(ble_gap_evt_adv_report_t* report) +{ + // Check if advertising contain BleUart service + if ( Bluefruit.Scanner.checkReportForService(report, clientUart) ) + { + Serial.print("BLE UART service detected. Connecting ... "); + + // Connect to device with bleuart service in advertising + Bluefruit.Central.connect(report); + }else + { + // For Softdevice v6: after received a report, scanner will be paused + // We need to call Scanner resume() to continue scanning + Bluefruit.Scanner.resume(); + } +} + +/** + * Callback invoked when an connection is established + * @param conn_handle + */ +void connect_callback(uint16_t conn_handle) +{ + Serial.println("Connected"); + + Serial.print("Dicovering Device Information ... "); + if ( clientDis.discover(conn_handle) ) + { + Serial.println("Found it"); + char buffer[32+1]; + + // read and print out Manufacturer + memset(buffer, 0, sizeof(buffer)); + if ( clientDis.getManufacturer(buffer, sizeof(buffer)) ) + { + Serial.print("Manufacturer: "); + Serial.println(buffer); + } + + // read and print out Model Number + memset(buffer, 0, sizeof(buffer)); + if ( clientDis.getModel(buffer, sizeof(buffer)) ) + { + Serial.print("Model: "); + Serial.println(buffer); + } + + Serial.println(); + }else + { + Serial.println("Found NONE"); + } + + Serial.print("Dicovering Battery ... "); + if ( clientBas.discover(conn_handle) ) + { + Serial.println("Found it"); + Serial.print("Battery level: "); + Serial.print(clientBas.read()); + Serial.println("%"); + }else + { + Serial.println("Found NONE"); + } + + Serial.print("Discovering BLE Uart Service ... "); + if ( clientUart.discover(conn_handle) ) + { + Serial.println("Found it"); + + Serial.println("Enable TXD's notify"); + clientUart.enableTXD(); + + Serial.println("Ready to receive from peripheral"); + }else + { + Serial.println("Found NONE"); + + // disconect since we couldn't find bleuart service + Bluefruit.Central.disconnect(conn_handle); + } +} + +/** + * 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; + + Serial.println("Disconnected"); +} + +/** + * Callback invoked when uart received data + * @param uart_svc Reference object to the service where the data + * arrived. In this example it is clientUart + */ +void bleuart_rx_callback(BLEClientUart& uart_svc) +{ + Serial.print("[RX]: "); + + while ( uart_svc.available() ) + { + Serial.print( (char) uart_svc.read() ); + } + + Serial.println(); +} + +void loop() +{ + if ( Bluefruit.Central.connected() ) + { + // Not discovered yet + if ( clientUart.discovered() ) + { + // Discovered means in working state + // Get Serial input and send to Peripheral + if ( Serial.available() ) + { + delay(2); // delay a bit for all characters to arrive + + char str[20+1] = { 0 }; + Serial.readBytes(str, 20); + + clientUart.print( str ); + } + } + } +} diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart_multi/central_bleuart_multi.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart_multi/central_bleuart_multi.ino new file mode 100755 index 0000000..4796c4e --- /dev/null +++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart_multi/central_bleuart_multi.ino @@ -0,0 +1,318 @@ +/********************************************************************* + 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 <bluefruit.h> + +// 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; idx<BLE_CENTRAL_MAX_CONN; idx++) + { + // Invalid all connection handle + prphs[idx].conn_handle = BLE_CONN_HANDLE_INVALID; + + // All of BLE Central Uart Serivce + prphs[idx].bleuart.begin(); + prphs[idx].bleuart.setRxCallback(bleuart_rx_callback); + } + + // Callbacks for Central + Bluefruit.Central.setConnectCallback(connect_callback); + Bluefruit.Central.setDisconnectCallback(disconnect_callback); + + /* Start Central Scanning + * - Enable auto scan if disconnected + * - Interval = 100 ms, window = 80 ms + * - Filter only accept bleuart service in advertising + * - Don't use active scan (used to retrieve the optional scan response adv packet) + * - Start(0) = will scan forever since no timeout is given + */ + Bluefruit.Scanner.setRxCallback(scan_callback); + Bluefruit.Scanner.restartOnDisconnect(true); + Bluefruit.Scanner.setInterval(160, 80); // in units of 0.625 ms + Bluefruit.Scanner.filterUuid(BLEUART_UUID_SERVICE); + Bluefruit.Scanner.useActiveScan(false); // Don't request scan response data + Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds +} + +/** + * Callback invoked when scanner picks up an advertising packet + * @param report Structural advertising data + */ +void scan_callback(ble_gap_evt_adv_report_t* report) +{ + // Since we configure the scanner with filterUuid() + // Scan callback only invoked for device with bleuart service advertised + // Connect to the device with bleuart service in advertising packet + Bluefruit.Central.connect(report); +} + +/** + * Callback invoked when an connection is established + * @param conn_handle + */ +void connect_callback(uint16_t conn_handle) +{ + // Find an available ID to use + int id = findConnHandle(BLE_CONN_HANDLE_INVALID); + + // Eeek: Exceeded the number of connections !!! + if ( id < 0 ) return; + + prph_info_t* peer = &prphs[id]; + peer->conn_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<BLE_CENTRAL_MAX_CONN; id++) + { + if (conn_handle == prphs[id].conn_handle) + { + return id; + } + } + + return -1; +} + +/** + * Software Timer callback is invoked via a built-in FreeRTOS thread with + * minimal stack size. Therefore it should be as simple as possible. If + * a periodically heavy task is needed, please use Scheduler.startLoop() to + * create a dedicated task for it. + * + * More information http://www.freertos.org/RTOS-software-timer.html + */ +void blink_timer_callback(TimerHandle_t xTimerID) +{ + (void) xTimerID; + + // Period of sequence is 10 times (1 second). + // RED LED will toggle first 2*n times (on/off) and remain off for the rest of period + // Where n = number of connection + static uint8_t count = 0; + + if ( count < 2*connection_num ) digitalToggle(LED_RED); + if ( count % 2 && digitalRead(LED_RED)) digitalWrite(LED_RED, LOW); // issue #98 + + count++; + if (count >= 10) count = 0; +} diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_custom_hrm/central_custom_hrm.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_custom_hrm/central_custom_hrm.ino new file mode 100755 index 0000000..a0cef0c --- /dev/null +++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_custom_hrm/central_custom_hrm.ino @@ -0,0 +1,205 @@ +/********************************************************************* + 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 show how to use BLEClientService and BLEClientCharacteristic + * to implement a custom client that is used to talk with Gatt server on + * peripheral. + * + * Note: you will need another feather52 running peripheral/custom_HRM sketch + * to test with. + */ + +#include <bluefruit.h> + +/* HRM Service Definitions + * Heart Rate Monitor Service: 0x180D + * Heart Rate Measurement Char: 0x2A37 (Mandatory) + * Body Sensor Location Char: 0x2A38 (Optional) + */ + +BLEClientService hrms(UUID16_SVC_HEART_RATE); +BLEClientCharacteristic hrmc(UUID16_CHR_HEART_RATE_MEASUREMENT); +BLEClientCharacteristic bslc(UUID16_CHR_BODY_SENSOR_LOCATION); + +void setup() +{ + Serial.begin(115200); + while ( !Serial ) delay(10); // for nrf52840 with native usb + + Serial.println("Bluefruit52 Central Custom HRM Example"); + Serial.println("--------------------------------------\n"); + + // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1 + // SRAM usage required by SoftDevice will increase dramatically with number of connections + Bluefruit.begin(0, 1); + + Bluefruit.setName("Bluefruit52 Central"); + + // Initialize HRM client + hrms.begin(); + + // Initialize client characteristics of HRM. + // Note: Client Char will be added to the last service that is begin()ed. + bslc.begin(); + + // set up callback for receiving measurement + hrmc.setNotifyCallback(hrm_notify_callback); + hrmc.begin(); + + // Increase Blink rate to different from PrPh advertising mode + Bluefruit.setConnLedInterval(250); + + // Callbacks for Central + Bluefruit.Central.setDisconnectCallback(disconnect_callback); + Bluefruit.Central.setConnectCallback(connect_callback); + + /* Start Central Scanning + * - Enable auto scan if disconnected + * - Interval = 100 ms, window = 80 ms + * - Don't use active scan + * - Filter only accept HRM service + * - Start(timeout) with timeout = 0 will scan forever (until connected) + */ + Bluefruit.Scanner.setRxCallback(scan_callback); + Bluefruit.Scanner.restartOnDisconnect(true); + Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms + Bluefruit.Scanner.filterUuid(hrms.uuid); + Bluefruit.Scanner.useActiveScan(false); + Bluefruit.Scanner.start(0); // // 0 = Don't stop scanning after n seconds +} + +void loop() +{ + // do nothing +} + +/** + * Callback invoked when scanner pick up an advertising data + * @param report Structural advertising data + */ +void scan_callback(ble_gap_evt_adv_report_t* report) +{ + // Since we configure the scanner with filterUuid() + // Scan callback only invoked for device with hrm service advertised + // Connect to device with HRM service in advertising + Bluefruit.Central.connect(report); +} + +/** + * Callback invoked when an connection is established + * @param conn_handle + */ +void connect_callback(uint16_t conn_handle) +{ + Serial.println("Connected"); + Serial.print("Discovering HRM Service ... "); + + // If HRM is not found, disconnect and return + if ( !hrms.discover(conn_handle) ) + { + Serial.println("Found NONE"); + + // disconect since we couldn't find HRM service + Bluefruit.Central.disconnect(conn_handle); + + return; + } + + // Once HRM service is found, we continue to discover its characteristic + Serial.println("Found it"); + + Serial.print("Discovering Measurement characteristic ... "); + if ( !hrmc.discover() ) + { + // Measurement chr is mandatory, if it is not found (valid), then disconnect + Serial.println("not found !!!"); + Serial.println("Measurement characteristic is mandatory but not found"); + Bluefruit.Central.disconnect(conn_handle); + return; + } + Serial.println("Found it"); + + // Measurement is found, continue to look for option Body Sensor Location + // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.body_sensor_location.xml + // Body Sensor Location is optional, print out the location in text if present + Serial.print("Discovering Body Sensor Location characteristic ... "); + if ( bslc.discover() ) + { + Serial.println("Found it"); + + // Body sensor location value is 8 bit + const char* body_str[] = { "Other", "Chest", "Wrist", "Finger", "Hand", "Ear Lobe", "Foot" }; + + // Read 8-bit BSLC value from peripheral + uint8_t loc_value = bslc.read8(); + + Serial.print("Body Location Sensor: "); + Serial.println(body_str[loc_value]); + }else + { + Serial.println("Found NONE"); + } + + // Reaching here means we are ready to go, let's enable notification on measurement chr + if ( hrmc.enableNotify() ) + { + Serial.println("Ready to receive HRM Measurement value"); + }else + { + Serial.println("Couldn't enable notify for HRM Measurement. Increase DEBUG LEVEL for troubleshooting"); + } +} + +/** + * 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; + + Serial.println("Disconnected"); +} + + +/** + * Hooked callback that triggered when a measurement value is sent from peripheral + * @param chr Pointer client characteristic that even occurred, + * in this example it should be hrmc + * @param data Pointer to received data + * @param len Length of received data + */ +void hrm_notify_callback(BLEClientCharacteristic* chr, uint8_t* data, uint16_t len) +{ + // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.heart_rate_measurement.xml + // Measurement contains of control byte0 and measurement (8 or 16 bit) + optional field + // if byte0's bit0 is 0 --> measurement is 8 bit, otherwise 16 bit. + + Serial.print("HRM Measurement: "); + + if ( data[0] & bit(0) ) + { + uint16_t value; + memcpy(&value, data+1, 2); + + Serial.println(value); + } + else + { + Serial.println(data[1]); + } +} diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_hid/central_hid.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_hid/central_hid.ino new file mode 100755 index 0000000..c78d055 --- /dev/null +++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_hid/central_hid.ino @@ -0,0 +1,226 @@ +/********************************************************************* + 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 demonstrate the central API(). An additional bluefruit + * that has blehid as peripheral is required for the demo. + */ +#include <bluefruit.h> + +// Polling or callback implementation +#define POLLING 1 + +BLEClientHidAdafruit hid; + +// Last checked report, to detect if there is changes between reports +hid_keyboard_report_t last_kbd_report = { 0 }; +hid_mouse_report_t last_mse_report = { 0 }; + +void setup() +{ + Serial.begin(115200); + while ( !Serial ) delay(10); // for nrf52840 with native usb + + Serial.println("Bluefruit52 Central HID (Keyboard + Mouse) Example"); + Serial.println("--------------------------------------------------\n"); + + // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1 + // SRAM usage required by SoftDevice will increase dramatically with number of connections + Bluefruit.begin(0, 1); + + Bluefruit.setName("Bluefruit52 Central"); + + // Init BLE Central Uart Serivce + hid.begin(); + + #if POLLING == 0 + hid.setKeyboardReportCallback(keyboard_report_callback); + #endif + + // Increase Blink rate to different from PrPh advertising mode + Bluefruit.setConnLedInterval(250); + + // Callbacks for Central + Bluefruit.Central.setConnectCallback(connect_callback); + Bluefruit.Central.setDisconnectCallback(disconnect_callback); + + /* Start Central Scanning + * - Enable auto scan if disconnected + * - Interval = 100 ms, window = 80 ms + * - Don't use active scan + * - Filter only accept HID service in advertising + * - Start(timeout) with timeout = 0 will scan forever (until connected) + */ + Bluefruit.Scanner.setRxCallback(scan_callback); + Bluefruit.Scanner.restartOnDisconnect(true); + Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms + Bluefruit.Scanner.filterService(hid); // only report HID service + Bluefruit.Scanner.useActiveScan(false); + Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds +} + +/** + * Callback invoked when scanner pick up an advertising data + * @param report Structural advertising data + */ +void scan_callback(ble_gap_evt_adv_report_t* report) +{ + // Since we configure the scanner with filterUuid() + // Scan callback only invoked for device with hid service advertised + // Connect to the device with hid service in advertising packet + Bluefruit.Central.connect(report); +} + +/** + * Callback invoked when an connection is established + * @param conn_handle + */ +void connect_callback(uint16_t conn_handle) +{ + Serial.println("Connected"); + + Serial.print("Discovering HID Service ... "); + + if ( hid.discover(conn_handle) ) + { + Serial.println("Found it"); + + // HID device mostly require pairing/bonding + if ( !Bluefruit.Gap.requestPairing(conn_handle) ) + { + Serial.print("Failed to paired"); + return; + } + + // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.hid_information.xml + uint8_t hidInfo[4]; + hid.getHidInfo(hidInfo); + + Serial.printf("HID version: %d.%d\n", hidInfo[0], hidInfo[1]); + Serial.print("Country code: "); Serial.println(hidInfo[2]); + Serial.printf("HID Flags : 0x%02X\n", hidInfo[3]); + + // BLEClientHidAdafruit currently only suports Boot Protocol Mode + // for Keyboard and Mouse. Let's set the protocol mode on prph to Boot Mode + hid.setProtocolMode(HID_PROTOCOL_MODE_BOOT); + + // Enable Keyboard report notification if present on prph + if ( hid.keyboardPresent() ) hid.enableKeyboard(); + + // Enable Mouse report notification if present on prph + if ( hid.mousePresent() ) hid.enableMouse(); + + Serial.println("Ready to receive from peripheral"); + }else + { + Serial.println("Found NONE"); + + // disconect since we couldn't find bleuart service + Bluefruit.Central.disconnect(conn_handle); + } +} + +/** + * 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; + + Serial.println("Disconnected"); +} + +void loop() +{ + +#if POLLING == 1 + // nothing to do if hid not discovered + if ( !hid.discovered() ) return; + + /*------------- Polling Keyboard -------------*/ + hid_keyboard_report_t kbd_report; + + // Get latest report + hid.getKeyboardReport(&kbd_report); + + processKeyboardReport(&kbd_report); + + + // polling interval is 5 ms + delay(5); +#endif + +} + + +void keyboard_report_callback(hid_keyboard_report_t* report) +{ + processKeyboardReport(report); +} + +void processKeyboardReport(hid_keyboard_report_t* report) +{ + // Check with last report to see if there is any changes + if ( memcmp(&last_kbd_report, report, sizeof(hid_keyboard_report_t)) ) + { + bool shifted = false; + + if ( report->modifier ) + { + if ( report->modifier & (KEYBOARD_MODIFIER_LEFTCTRL | KEYBOARD_MODIFIER_RIGHTCTRL) ) + { + Serial.print("Ctrl "); + } + + if ( report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT) ) + { + Serial.print("Shift "); + + shifted = true; + } + + if ( report->modifier & (KEYBOARD_MODIFIER_LEFTALT | KEYBOARD_MODIFIER_RIGHTALT) ) + { + Serial.print("Alt "); + } + } + + for(uint8_t i=0; i<6; i++) + { + uint8_t kc = report->keycode[i]; + char ch = 0; + + if ( kc < 128 ) + { + ch = shifted ? HID_KEYCODE_TO_ASCII[kc].shifted : HID_KEYCODE_TO_ASCII[kc].ascii; + }else + { + // non-US keyboard !!?? + } + + // Printable + if (ch) + { + Serial.print(ch); + } + } + } + + // update last report + memcpy(&last_kbd_report, report, sizeof(hid_keyboard_report_t)); +} diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_scan/central_scan.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_scan/central_scan.ino new file mode 100755 index 0000000..191f978 --- /dev/null +++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_scan/central_scan.ino @@ -0,0 +1,73 @@ +/********************************************************************* + 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 +*********************************************************************/ + +#include <bluefruit.h> + +void setup() +{ + Serial.begin(115200); + while ( !Serial ) delay(10); // for nrf52840 with native usb + + Serial.println("Bluefruit52 Central Scan Example"); + Serial.println("--------------------------------\n"); + + // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1 + // SRAM usage required by SoftDevice will increase dramatically with number of connections + Bluefruit.begin(0, 1); + + // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4 + Bluefruit.setTxPower(4); + Bluefruit.setName("Bluefruit52"); + + // Start Central Scan + Bluefruit.setConnLedInterval(250); + Bluefruit.Scanner.setRxCallback(scan_callback); + Bluefruit.Scanner.start(0); + + Serial.println("Scanning ..."); +} + +void scan_callback(ble_gap_evt_adv_report_t* report) +{ + Serial.println("Timestamp Addr Rssi Data"); + + Serial.printf("%09d ", millis()); + + // MAC is in little endian --> print reverse + Serial.printBufferReverse(report->peer_addr.addr, 6, ':'); + Serial.print(" "); + + Serial.print(report->rssi); + Serial.print(" "); + + Serial.printBuffer(report->data.p_data, report->data.len, '-'); + Serial.println(); + + // Check if advertising contain BleUart service + if ( Bluefruit.Scanner.checkReportForUuid(report, BLEUART_UUID_SERVICE) ) + { + Serial.println(" BLE UART service detected"); + } + + Serial.println(); + + // For Softdevice v6: after received a report, scanner will be paused + // We need to call Scanner resume() to continue scanning + Bluefruit.Scanner.resume(); +} + +void loop() +{ + // nothing to do +} diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_scan_advanced/central_scan_advanced.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_scan_advanced/central_scan_advanced.ino new file mode 100755 index 0000000..3aab152 --- /dev/null +++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_scan_advanced/central_scan_advanced.ino @@ -0,0 +1,218 @@ +/********************************************************************* + 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 +*********************************************************************/ + +#include <bluefruit.h> + +/* For a list of EIR data types see: + * https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile + * Matching enum: cores/nRF5/SDK/components/softdevice/s132/headers/ble_gap.h */ + +void setup() +{ + Serial.begin(115200); + while ( !Serial ) delay(10); // for nrf52840 with native usb + + Serial.println("Bluefruit52 Central ADV Scan Example"); + Serial.println("------------------------------------\n"); + + // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1 + // SRAM usage required by SoftDevice will increase dramatically with number of connections + Bluefruit.begin(0, 1); + + // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4 + Bluefruit.setTxPower(4); + + /* Set the device name */ + Bluefruit.setName("Bluefruit52"); + + /* Set the LED interval for blinky pattern on BLUE LED */ + Bluefruit.setConnLedInterval(250); + + /* Start Central Scanning + * - Enable auto scan if disconnected + * - Filter out packet with a min rssi + * - Interval = 100 ms, window = 50 ms + * - Use active scan (used to retrieve the optional scan response adv packet) + * - Start(0) = will scan forever since no timeout is given + */ + Bluefruit.Scanner.setRxCallback(scan_callback); + Bluefruit.Scanner.restartOnDisconnect(true); + Bluefruit.Scanner.filterRssi(-80); + //Bluefruit.Scanner.filterUuid(BLEUART_UUID_SERVICE); // only invoke callback if detect bleuart service + Bluefruit.Scanner.setInterval(160, 80); // in units of 0.625 ms + Bluefruit.Scanner.useActiveScan(true); // Request scan response data + Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds + + Serial.println("Scanning ..."); +} + +void scan_callback(ble_gap_evt_adv_report_t* report) +{ + PRINT_LOCATION(); + uint8_t len = 0; + uint8_t buffer[32]; + memset(buffer, 0, sizeof(buffer)); + + /* Display the timestamp and device address */ + if (report->type.scan_response) + { + Serial.printf("[SR%10d] Packet received from ", millis()); + } + else + { + Serial.printf("[ADV%9d] Packet received from ", millis()); + } + // MAC is in little endian --> print reverse + Serial.printBufferReverse(report->peer_addr.addr, 6, ':'); + Serial.print("\n"); + + /* Raw buffer contents */ + Serial.printf("%14s %d bytes\n", "PAYLOAD", report->data.len); + if (report->data.len) + { + Serial.printf("%15s", " "); + Serial.printBuffer(report->data.p_data, report->data.len, '-'); + Serial.println(); + } + + /* RSSI value */ + Serial.printf("%14s %d dBm\n", "RSSI", report->rssi); + + /* Adv Type */ + Serial.printf("%14s ", "ADV TYPE"); + if ( report->type.connectable ) + { + Serial.print("Connectable "); + }else + { + Serial.print("Non-connectable "); + } + + if ( report->type.directed ) + { + Serial.println("directed"); + }else + { + Serial.println("undirected"); + } + + /* Shortened Local Name */ + if(Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME, buffer, sizeof(buffer))) + { + Serial.printf("%14s %s\n", "SHORT NAME", buffer); + memset(buffer, 0, sizeof(buffer)); + } + + /* Complete Local Name */ + if(Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, buffer, sizeof(buffer))) + { + Serial.printf("%14s %s\n", "COMPLETE NAME", buffer); + memset(buffer, 0, sizeof(buffer)); + } + + /* TX Power Level */ + if (Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_TX_POWER_LEVEL, buffer, sizeof(buffer))) + { + Serial.printf("%14s %i\n", "TX PWR LEVEL", buffer[0]); + memset(buffer, 0, sizeof(buffer)); + } + + /* Check for UUID16 Complete List */ + len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, buffer, sizeof(buffer)); + if ( len ) + { + printUuid16List(buffer, len); + } + + /* Check for UUID16 More Available List */ + len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, buffer, sizeof(buffer)); + if ( len ) + { + printUuid16List(buffer, len); + } + + /* Check for UUID128 Complete List */ + len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, buffer, sizeof(buffer)); + if ( len ) + { + printUuid128List(buffer, len); + } + + /* Check for UUID128 More Available List */ + len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE, buffer, sizeof(buffer)); + if ( len ) + { + printUuid128List(buffer, len); + } + + /* Check for BLE UART UUID */ + if ( Bluefruit.Scanner.checkReportForUuid(report, BLEUART_UUID_SERVICE) ) + { + Serial.printf("%14s %s\n", "BLE UART", "UUID Found!"); + } + + /* Check for DIS UUID */ + if ( Bluefruit.Scanner.checkReportForUuid(report, UUID16_SVC_DEVICE_INFORMATION) ) + { + Serial.printf("%14s %s\n", "DIS", "UUID Found!"); + } + + /* Check for Manufacturer Specific Data */ + len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, buffer, sizeof(buffer)); + if (len) + { + Serial.printf("%14s ", "MAN SPEC DATA"); + Serial.printBuffer(buffer, len, '-'); + Serial.println(); + memset(buffer, 0, sizeof(buffer)); + } + + Serial.println(); + + // For Softdevice v6: after received a report, scanner will be paused + // We need to call Scanner resume() to continue scanning + Bluefruit.Scanner.resume(); +} + +void printUuid16List(uint8_t* buffer, uint8_t len) +{ + Serial.printf("%14s %s", "16-Bit UUID"); + for(int i=0; i<len; i+=2) + { + uint16_t uuid16; + memcpy(&uuid16, buffer+i, 2); + Serial.printf("%04X ", uuid16); + } + Serial.println(); +} + +void printUuid128List(uint8_t* buffer, uint8_t len) +{ + (void) len; + Serial.printf("%14s %s", "128-Bit UUID"); + + // Print reversed order + for(int i=0; i<16; i++) + { + const char* fm = (i==4 || i==6 || i==8 || i==10) ? "-%02X" : "%02X"; + Serial.printf(fm, buffer[15-i]); + } + + Serial.println(); +} + +void loop() +{ + // nothing to do +} diff --git a/arduino/libraries/Bluefruit52Lib/examples/Central/central_ti_sensortag_optical/central_ti_sensortag_optical.ino b/arduino/libraries/Bluefruit52Lib/examples/Central/central_ti_sensortag_optical/central_ti_sensortag_optical.ino new file mode 100755 index 0000000..92d76af --- /dev/null +++ b/arduino/libraries/Bluefruit52Lib/examples/Central/central_ti_sensortag_optical/central_ti_sensortag_optical.ino @@ -0,0 +1,309 @@ +/********************************************************************* + 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 shows how to use BLEClientService and BLEClientCharacteristic + * to implement a custom client that is used to talk with Gatt server on + * the TI SensorTag peripheral device. + * + * Online uuid/hex converters + * https://yupana-engineering.com/online-uuid-to-c-array-converter + * https://www.scadacore.com/tools/programming-calculators/online-hex-converter/ + * https://codebeautify.org/string-hex-converter + * + * Adafruit Bluefruit Feather nRF52 + * https://learn.adafruit.com/bluefruit-nrf52-feather-learning-guide/blescanner + * + * Sensor Tag + * http://processors.wiki.ti.com/index.php/CC2650_SensorTag_User%27s_Guide#Optical_Sensor + * + * Scan Response (Extended Advertisement data retrieval) + * https://devzone.nordicsemi.com/tutorials/b/bluetooth-low-energy/posts/ble-advertising-a-beginners-tutorial + * + */ + + #include <bluefruit.h> + +/* TI Sensor Tag UUID Definitions + * Base SensorTag UUID pattern: F000-0000-0451-4000-B000-000000000000 + * Optical Service: 0xA070 + * Optical Characteristic: 0xAA71 + * Optical Data Collection Enabler: 0xAA72 + * Optical Measurement Period: 0xAA73 + * Local Name: "CC2650 SensorTag" + */ + + uint8_t SENSORTAG_OPTICAL_SERVICE_UUID[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x00,0x40,0x51,0x04,0x70,0xAA,0x00,0xF0}; + uint8_t SENSORTAG_OPTICAL_CHARACTERISTIC_UUID[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x00,0x40,0x51,0x04,0x71,0xAA,0x00,0xF0}; + uint8_t SENSORTAG_OPTICAL_ENABLE_CHARACTERISTIC_UUID[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x00,0x40,0x51,0x04,0x72,0xAA,0x00,0xF0}; + uint8_t SENSORTAG_OPTICAL_PERIOD_CHARACTERISTIC_UUID[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x00,0x40,0x51,0x04,0x73,0xAA,0x00,0xF0}; + uint8_t SENSORTAG_ADV_COMPLETE_LOCAL_NAME[] = {0x43,0x43,0x32,0x36,0x35,0x30,0x20,0x53,0x65,0x6e,0x73,0x6f,0x72,0x54,0x61,0x67}; + +BLEClientService sensorTagOpticalService(SENSORTAG_OPTICAL_SERVICE_UUID); +BLEClientCharacteristic sensorTagOpticalCharacteristic(SENSORTAG_OPTICAL_CHARACTERISTIC_UUID); +BLEClientCharacteristic opticalCharacteristicDataCollectionEnabler(SENSORTAG_OPTICAL_ENABLE_CHARACTERISTIC_UUID); +BLEClientCharacteristic opticalCharacteristicPeriod(SENSORTAG_OPTICAL_PERIOD_CHARACTERISTIC_UUID); + + +void setup() +{ + Serial.begin(115200); + while ( !Serial ) delay(10); // for nrf52840 with native usb + + Serial.println("Bluefruit52 Central TI Sensor Tag Example"); + Serial.println("-----------------------------------------\n"); + + // Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1 + // SRAM usage required by SoftDevice will increase dramatically with number of connections + Bluefruit.begin(0, 1); + + Bluefruit.setName("Bluefruit52 TI SensorTag Central"); + + // Initialize Service + sensorTagOpticalService.begin(); + + // set up callback for receiving measurement + sensorTagOpticalCharacteristic.setNotifyCallback(sensortag_optical_notify_callback); + sensorTagOpticalCharacteristic.begin(); + + // set up the characteristic to enable the optical component on the device + opticalCharacteristicDataCollectionEnabler.begin(); + + // set up the characteristic to adjust the measurement period + opticalCharacteristicPeriod.begin(); + + // Increase Blink rate to different from PrPh advertising mode + Bluefruit.setConnLedInterval(250); + + // Callbacks for Central + Bluefruit.Central.setDisconnectCallback(disconnect_callback); + Bluefruit.Central.setConnectCallback(connect_callback); + + /* Start Central Scanning + * - Enable auto scan if disconnected + * - Interval = 100 ms, window = 80 ms + * - No UUID Filter + * - Use active scan + * - Start(timeout) with timeout = 0 will scan forever (until connected) + */ + + Bluefruit.Scanner.setRxCallback(scan_callback); + Bluefruit.Scanner.restartOnDisconnect(true); + Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms + // Bluefruit.Scanner.filterUuid(); // do not not set anything here or Scan Response won't work + Bluefruit.Scanner.useActiveScan(true); // required for SensorTag to reveal the Local Name in the advertisement. + Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds +} + +void loop() +{ + // do nothing +} + +/** + * Callback invoked when scanner pick up an advertising data + * @param report Structural advertising data + */ +void scan_callback(ble_gap_evt_adv_report_t* report) +{ + Serial.println(""); + Serial.println("Scan Callback"); + printReport( report ); + + /* Choose a peripheral to connect with by searching for an advertisement packet with a + Complete Local Name matching our target device*/ + uint8_t buffer[BLE_GAP_ADV_SET_DATA_SIZE_MAX] = { 0 }; + + Serial.print("Parsing report for Local Name ... "); + if(Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, buffer, sizeof(buffer))) + { + Serial.println("Found Local Name"); + Serial.printf("%14s %s\n", "Local Name:", buffer); + + Serial.print(" Local Name data: "); + printHexList(buffer, BLE_GAP_ADV_SET_DATA_SIZE_MAX ); + + Serial.print("Determining Local Name Match ... "); + if ( !memcmp( buffer, SENSORTAG_ADV_COMPLETE_LOCAL_NAME, sizeof(SENSORTAG_ADV_COMPLETE_LOCAL_NAME)) ) + { + Serial.println("Local Name Match!"); + + Serial.println("Connecting to Peripheral ... "); + Bluefruit.Central.connect(report); + } + else + { + Serial.println("No Match"); + Bluefruit.Scanner.resume(); // continue scanning + } + } + else + { + Serial.println("Failed"); + + // For Softdevice v6: after received a report, scanner will be paused + // We need to call Scanner resume() to continue scanning + Bluefruit.Scanner.resume(); + } +} + +/** + * Callback invoked when an connection is established + * @param conn_handle + */ +void connect_callback(uint16_t conn_handle) +{ + Serial.println(""); + Serial.print("Connect Callback, conn_handle: "); + Serial.println( conn_handle ); + + /* Complete Local Name */ + uint8_t buffer[BLE_GAP_ADV_SET_DATA_SIZE_MAX] = { 0 }; + + // If Service is not found, disconnect and return + Serial.print("Discovering Optical Service ... "); + if ( !sensorTagOpticalService.discover(conn_handle) ) + { + Serial.println("No Service Found"); + + // disconect since we couldn't find service + Bluefruit.Central.disconnect(conn_handle); + + return; + } + Serial.println("Service Found"); + + // Once service is found, we continue to discover the primary characteristic + Serial.print("Discovering Optical Characteristic ... "); + if ( !sensorTagOpticalCharacteristic.discover() ) + { + // Measurement chr is mandatory, if it is not found (valid), then disconnect + Serial.println("No Characteristic Found. Characteristic is mandatory but not found. "); + Bluefruit.Central.disconnect(conn_handle); + return; + } + Serial.println("Characteristic Found"); + + // Data Collection Charactistic. Find and enable. + // You enable data collection on the Characteristic before the peripheral will start measuring values. + // This is different than setting the Notify descriptor, which is handled below. + Serial.print("Discovering Data Collection Configuration Characteristic ... "); + if ( !opticalCharacteristicDataCollectionEnabler.discover() ) + { + Serial.println("No Characteristic Found. Characteristic is mandatory but not found."); + Bluefruit.Central.disconnect(conn_handle); + return; + } + Serial.println("Characteristic Found"); + // Found it, now write 0x01 to turn on optical data collection + Serial.print("Enabling Data Collection, return value: "); + Serial.println( opticalCharacteristicDataCollectionEnabler.write8( 0x01 ) ); + + // Measurement Period Characteristic. Find and adjust. + Serial.print("Measurement Period Characteristic ... "); + if ( !opticalCharacteristicPeriod.discover() ) + { + Serial.println("No Characteristic Found, but not mandatory so not disconnecting"); + } + Serial.println("Characteristic Found"); + // Found it, now adjust it: + // Resolution 10 ms. Range 100 ms (0x0A) to 2.55 sec (0xFF). Default is 800 milliseconds (0x50). + // 19 is 250 + Serial.print("Adjusting Measurement Period, return value: "); + // Serial.println( opticalCharacteristicPeriod.write8( 0xFF ) ); // Slowest + Serial.println( opticalCharacteristicPeriod.write8( 0x0A ) ); // Fastest + + // Reaching here means we are ready to go, let's enable notification on measurement chr + Serial.print("Enabling Notify on the Characteristic ... "); + if ( sensorTagOpticalCharacteristic.enableNotify() ) + { + Serial.println("enableNotify success, now ready to receive Characteristic values"); + }else + { + Serial.println("Couldn't enable notify for Characteristic. Increase DEBUG LEVEL for troubleshooting"); + } +} + +/** + * 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; + + Serial.println("Disconnected"); +} + +/** + * Hooked callback that triggered when a measurement value is sent from peripheral + * @param chr Pointer client characteristic that even occurred, + * in this example it should be sensorTagOpticalCharacteristic + * @param data Pointer to received data + * @param len Length of received data + */ +void sensortag_optical_notify_callback(BLEClientCharacteristic* chr, uint8_t* data, uint16_t len) +{ + Serial.print("Optical data: "); + uint16_t tData = (uint16_t) ( ( data[0] & 0xFF ) | ( data[1] & 0xFF ) << 8 ); + Serial.print( sensorOpt3001Convert( tData ) ); + Serial.println( " Lux" ); +} + +/* + * Conversion to Lux. Algorithm from the TI Sensor Tag Wiki documentation page + */ +float sensorOpt3001Convert(uint16_t rawData) +{ + uint16_t e, m; + + m = rawData & 0x0FFF; + e = (rawData & 0xF000) >> 12; + + /** e on 4 bits stored in a 16 bit unsigned => it can store 2 << (e - 1) with e < 16 */ + e = (e == 0) ? 1 : 2 << (e - 1); + + return m * (0.01 * e); +} + +/* Prints a hex list to the Serial Monitor */ +void printHexList(uint8_t* buffer, uint8_t len) +{ + // print forward order + for(int i=0; i<len; i++) + { + Serial.printf("%02X-", buffer[i]); + } + Serial.println(); +} + +void printReport( const ble_gap_evt_adv_report_t* report ) +{ + Serial.print( " rssi: " ); + Serial.println( report->rssi ); + Serial.print( " scan_rsp: " ); + Serial.println( report->type.scan_response ); +// Serial.print( " type: " ); +// Serial.println( report->type ); + Serial.print( " dlen: " ); + Serial.println( report->data.len ); + Serial.print( " data: " ); + for( int i = 0; i < report->data.len; i+= sizeof(uint8_t) ) + { + Serial.printf( "%02X-", report->data.p_data[ i ] ); + } + Serial.println(""); +} |