aboutsummaryrefslogtreecommitdiffstats
path: root/arduino/libraries/Bluefruit52Lib/examples/Central
diff options
context:
space:
mode:
Diffstat (limited to 'arduino/libraries/Bluefruit52Lib/examples/Central')
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart/central_bleuart.ino207
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_bleuart_multi/central_bleuart_multi.ino318
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_custom_hrm/central_custom_hrm.ino205
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_hid/central_hid.ino226
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_scan/central_scan.ino73
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_scan_advanced/central_scan_advanced.ino218
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Central/central_ti_sensortag_optical/central_ti_sensortag_optical.ino309
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("");
+}