aboutsummaryrefslogtreecommitdiffstats
path: root/arduino/libraries/Bluefruit52Lib/examples/Projects
diff options
context:
space:
mode:
authorClyne Sullivan <tullivan99@gmail.com>2019-02-28 17:04:22 -0500
committerClyne Sullivan <tullivan99@gmail.com>2019-02-28 17:04:22 -0500
commitd6869d1ec4bd24cd2c3eafa534f0849b25ec5607 (patch)
tree79e54ed27b39c31864895535d11399708d5a45c0 /arduino/libraries/Bluefruit52Lib/examples/Projects
parent614ee97bf3a2270c413527a7f35c54cbecd9e601 (diff)
added basic code
Diffstat (limited to 'arduino/libraries/Bluefruit52Lib/examples/Projects')
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Projects/homekit/homekit_lightbulb/homekit_lightbulb.ino189
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/README.md24
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_central/rssi_proximity_central.ino683
-rwxr-xr-xarduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_peripheral/rssi_proximity_peripheral.ino160
4 files changed, 1056 insertions, 0 deletions
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Projects/homekit/homekit_lightbulb/homekit_lightbulb.ino b/arduino/libraries/Bluefruit52Lib/examples/Projects/homekit/homekit_lightbulb/homekit_lightbulb.ino
new file mode 100755
index 0000000..798d98b
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Projects/homekit/homekit_lightbulb/homekit_lightbulb.ino
@@ -0,0 +1,189 @@
+/*********************************************************************
+ 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>
+#include <BLEHomekit.h>
+
+#include "crypto/crypto.h"
+
+#define CRYPTO_KEYFILE "/adafruit/homekit/key"
+
+BLEHomekit homekit;
+
+uint8_t test_keys[] =
+{
+ 0x55, 0x02, 0x29, 0x6A, 0x41, 0xB0, 0xF5, 0x35, 0x61, 0xFF, 0x82, 0x52, 0x2E, 0x77, 0xF0, 0xC6,
+ 0x1A, 0x2B, 0x6F, 0xD9, 0x4B, 0x48, 0x01, 0xCA, 0x37, 0xAF, 0x90, 0x74, 0x78, 0x07, 0xF8, 0xBE,
+ 0x58, 0xE8, 0xAD, 0x10, 0xB9, 0x69, 0xA3, 0x03, 0x0E, 0x42, 0x93, 0x2F, 0xF6, 0x3F, 0xE6, 0x40,
+ 0x71, 0x3F, 0x12, 0x63, 0x0B, 0x38, 0xEE, 0xF2, 0xDC, 0xCC, 0x1D, 0x24, 0x08, 0x70, 0xA3, 0xAD,
+ 0x8D, 0x16, 0xC0, 0x06, 0x24, 0x31, 0xCD, 0xB5, 0x34, 0xC8, 0x92, 0x3F, 0x3C, 0xF4, 0x43, 0x99,
+ 0xE1, 0x2B, 0x0C, 0x4B, 0xEE, 0xB6, 0xD9, 0xB6, 0xFD, 0x03, 0x43, 0xAD, 0x64, 0xB6, 0x6A, 0x19,
+ 0xDE, 0xA6, 0x34, 0x73, 0xC9, 0xB1, 0xB9, 0xBC, 0x5A, 0x09, 0xEF, 0x33, 0x1F, 0x32, 0xC9, 0xDD,
+ 0x71, 0xD3, 0xB7, 0x68, 0x89, 0xC6, 0x35, 0x36, 0x74, 0x9B, 0xE9, 0x84, 0x16, 0xF5, 0xAB, 0xCB,
+ 0x83, 0xA0, 0x77, 0x0E, 0xE2, 0x9A, 0x10, 0x36, 0xCC, 0xA9, 0xAE, 0xE3, 0x30, 0x8E, 0x24, 0x2F,
+ 0xCA, 0xC5, 0xAC, 0x37, 0x03, 0xF6, 0xEA, 0x1A, 0x22, 0x81, 0x61, 0x98, 0xCC, 0x76, 0x6D, 0x6E,
+ 0x46, 0x27, 0x50, 0x40, 0xD5, 0x15, 0xBB, 0xF3, 0x83, 0x08, 0x83, 0x3D, 0xDF, 0xED, 0x23, 0x20,
+ 0x70, 0x3B, 0xAB, 0xFD, 0x07, 0x0E, 0x92, 0x12, 0x10, 0xB0, 0xAE, 0x5F, 0xE2, 0x9E, 0x82, 0x33,
+ 0xD6, 0xE4, 0xA9, 0x70, 0x44, 0x6B, 0xE7, 0x7E, 0x4E, 0xA7, 0xF3, 0x63, 0xE3, 0x0F, 0xAB, 0x24,
+ 0xD4, 0xF4, 0x6A, 0xFC, 0x32, 0xDC, 0x4E, 0xA2, 0x4F, 0xBE, 0x25, 0x40, 0x49, 0xA7, 0xB1, 0x0F,
+ 0xF6, 0x4F, 0x1F, 0xFF, 0x08, 0x13, 0x46, 0x55, 0x45, 0x90, 0x6E, 0x09, 0xEA, 0x81, 0x60, 0x66,
+ 0x61, 0x49, 0x41, 0xC5, 0x23, 0xC6, 0xCE, 0xD8, 0xF4, 0xCB, 0x3D, 0x3B, 0xAC, 0x6E, 0x28, 0xDD,
+ 0x19, 0x58, 0x96, 0x3B, 0xC9, 0x39, 0x46, 0x46, 0xC4, 0x90, 0xCF, 0xFB, 0xAE, 0xFD, 0x30, 0xFB,
+ 0x36, 0x14, 0x36, 0xF4, 0x5E, 0xDD, 0x04, 0x2E, 0x3F, 0x5E, 0xCD, 0x71, 0x6B, 0x55, 0xD7, 0xF3,
+ 0x59, 0x24, 0x08, 0x58, 0x90, 0x71, 0x1F, 0x88, 0x53, 0xA0, 0xC1, 0xB8, 0x5F, 0x3D, 0x94, 0xF3,
+ 0xDB, 0xFC, 0x3F, 0x59, 0x41, 0xBF, 0x41, 0xC3, 0xC4, 0x70, 0x1A, 0x0C, 0x9C, 0x9A, 0x54, 0x5E,
+ 0xD3, 0xF0, 0x82, 0xD9, 0xF9, 0xCF, 0x0E, 0xC0, 0x53, 0xAD, 0x2E, 0xFA, 0x99, 0x1A, 0x57, 0x41,
+ 0x4F, 0x71, 0x2B, 0x47, 0x31, 0xB3, 0x18, 0xC4, 0xAE, 0xCD, 0xCC, 0xD4, 0x14, 0x75, 0x48, 0xB9,
+ 0x06, 0x81, 0xBA, 0xD9, 0x60, 0x63, 0xD4, 0x3A, 0x26, 0xE0, 0x64, 0xD1, 0xF7, 0xE4, 0x9A, 0xC1,
+ 0xC1, 0x06, 0xBC, 0x51, 0x85, 0xEC, 0x33, 0x63, 0xCD, 0x25, 0x34, 0x13, 0xBF, 0x5B, 0x65, 0x2D,
+ 0x6C, 0xCE, 0x6F, 0x22, 0x77, 0x12, 0x4C, 0x32, 0xFD, 0x72, 0x5C, 0x65, 0x5F, 0x28, 0x38, 0x6B,
+ 0x52, 0x87, 0x6A, 0xCF, 0x8A, 0x7F, 0xC1, 0x66, 0x03, 0x0C, 0x6F, 0x00, 0x82, 0xA7, 0xA8, 0x73,
+ 0x28, 0x17, 0x19, 0xD3, 0x26, 0x90, 0x70, 0xAF, 0x2B, 0x86, 0x34, 0x96, 0x91, 0xD3, 0xB7, 0x65,
+ 0x48, 0xB7, 0xCB, 0xEA, 0xC4, 0xB1, 0x78, 0x1C, 0x76, 0x51, 0x2F, 0x68, 0x89, 0x42, 0xCD, 0x89,
+ 0xA7, 0xE0, 0x8B, 0xD8, 0x8D, 0x1F, 0xDA, 0xA6, 0xCE, 0xD6, 0x71, 0x9E, 0x7D, 0x98, 0x59, 0x66,
+ 0xAD, 0x91, 0x68, 0xF5, 0xE2, 0xA0, 0x78, 0xB3, 0x69, 0x65, 0x00, 0x94, 0xDC, 0x44, 0x09, 0xA2,
+ 0x2B, 0x71, 0x15, 0x9E, 0x33, 0xE7, 0x8F, 0x72, 0x44, 0x83, 0xF6, 0xF4, 0x9C, 0xDE, 0xF0, 0xC1,
+ 0xAC, 0x60, 0x01, 0x79, 0x24, 0x9E, 0xC0, 0x82, 0x68, 0xA4, 0xE8, 0x70, 0xF0, 0xBD, 0x80, 0x99,
+ 0x1E, 0x5A, 0xB5, 0x08, 0x03, 0x62, 0xC7, 0x3D, 0xD1, 0xFE, 0x23, 0xA7, 0xF1, 0x01, 0x1A, 0x37,
+ 0x23, 0x27, 0x6D, 0x39, 0x63, 0x75, 0x35, 0x60, 0x6B, 0xD1, 0xD3, 0x77, 0xB1, 0xA2, 0xE4, 0x6A,
+ 0x0A, 0xD9, 0xD9, 0x42, 0x37, 0x97, 0x0C, 0x73, 0x97, 0x98, 0x55, 0xC2, 0x22, 0x5B, 0x62, 0x4E,
+ 0x1A, 0xBB, 0xFB, 0xAC, 0x91, 0xB0, 0x68, 0xAD, 0x78, 0x48, 0x45, 0x42, 0xEF, 0x80, 0xE7, 0xB0,
+ 0xC2, 0xA0, 0x03, 0x37, 0xBD, 0x12, 0xFD, 0x3A, 0x65, 0x76, 0xE6, 0xBC, 0xE7, 0x98, 0x79, 0x6F,
+ 0x18, 0x10, 0x9E, 0x67, 0x62, 0x3D, 0x1B, 0x41, 0x8E, 0x2D, 0x99, 0x87, 0x7D, 0x75, 0xBE, 0x49,
+ 0x6E, 0x43, 0xE2, 0x9F, 0x71, 0x29, 0x1F, 0x45, 0xB6, 0x2B, 0xAE, 0x3B, 0x78, 0xEF, 0x09, 0x4A,
+ 0xBD, 0x5F, 0xC1, 0x4C, 0xE5, 0x22, 0xD9, 0x17, 0x11, 0xCE, 0x39, 0xD7, 0x11, 0x3B, 0x13, 0xE8,
+ 0x9B, 0x8D, 0xDF, 0x9E, 0xCB, 0x96, 0xDD, 0xD7, 0xA8, 0x0D, 0x0F, 0xBE, 0x6F, 0xF2, 0xAC, 0xEF,
+ 0x0E, 0xA9, 0xFE, 0x0C, 0xC9, 0xF8, 0xC4, 0x55, 0x36, 0x3D, 0xEF, 0x30, 0xA7, 0x33, 0x7B, 0xB8,
+ 0x99, 0x05, 0xDE, 0xEF, 0xAA, 0xDA, 0xCB, 0xD7, 0x15, 0x30, 0xF4, 0xE3, 0xC8, 0x72, 0x25, 0x4A,
+ 0xBE, 0x1B, 0x35, 0x92, 0x92, 0xDD, 0x4B, 0x1C, 0xA0, 0x6F, 0x7C, 0xEF, 0x95, 0x12, 0x38, 0xFB,
+ 0xC8, 0x4E, 0x80, 0xB8, 0x06, 0xC6, 0x6F, 0xFC, 0x3A, 0xB4, 0x54, 0xCA, 0xC9, 0x8F, 0xE7, 0xB1,
+ 0xA3, 0x29, 0xEB, 0x06, 0xD7, 0xE8, 0xFB, 0x25, 0xD4, 0x30, 0x6A, 0x9C, 0xCC, 0x7C, 0xC7, 0x7E,
+ 0x1F, 0xA8, 0xA4, 0x23, 0x11, 0x9B, 0x9A, 0xBD, 0x9D, 0x2E, 0x8D, 0x5C, 0x67, 0x85, 0x5C, 0xBB,
+ 0xF5, 0x55, 0xC0, 0x11, 0x32, 0x67, 0x58, 0x2A, 0x24, 0xC2, 0xAA, 0x8E, 0x46, 0xC3, 0xDB, 0x5A,
+ 0xA7, 0x02, 0xA3, 0x3D, 0x76, 0x41, 0xED, 0xF4, 0x4C, 0x67, 0xC0, 0xB1, 0x8F, 0xDE, 0x27, 0x8A,
+ 0xF6, 0x53, 0x66, 0xA6, 0x7E, 0xF9, 0xB6, 0x8D, 0xAD, 0x63, 0xC8, 0x9C, 0x44, 0xA2, 0xD8, 0x22,
+ 0x26, 0x01, 0xD9, 0x2A, 0x7E, 0xA5, 0xE8, 0x73, 0xDB, 0x6C, 0xC0, 0xB6, 0xAC, 0x8F, 0xAC, 0x4B,
+ 0xC4, 0xD7, 0x98, 0xFF, 0x5A, 0x18, 0x4B, 0xCF, 0x38, 0xD1, 0x7E, 0x2D, 0xDB, 0xDD, 0x9C, 0x94,
+ 0x66, 0x72, 0x1A, 0xBA, 0x9A, 0x98, 0x92, 0x9B, 0x16, 0x32, 0x2E, 0xF1, 0x9A, 0x83, 0x62, 0x3E,
+ 0x2D, 0x17, 0x64, 0xBF, 0xA5, 0x27, 0xA1, 0xE7, 0xAF, 0xB5, 0xD4, 0x68, 0x3E, 0x06, 0x68, 0xDA,
+ 0xF6, 0x7C, 0x5E, 0x47, 0x0E, 0x50, 0x63, 0x70, 0xDE, 0xF4, 0x2F, 0x42, 0x22, 0x32, 0x2A, 0xF6,
+ 0x8A, 0xEE, 0x33, 0x43, 0x37, 0x46, 0x46, 0x39, 0x37, 0x32, 0x2D, 0x30, 0x34, 0x30, 0x45, 0x2D,
+ 0x34, 0x39, 0x31, 0x35, 0x2D, 0x41, 0x38, 0x33, 0x44, 0x2D, 0x41, 0x39, 0x36, 0x34, 0x36, 0x39,
+ 0x30, 0x44, 0x44, 0x43, 0x43, 0x38, 0x4B, 0xB6, 0xEA, 0x1E, 0x22, 0x3A, 0xEE, 0x83, 0x7E, 0xBE,
+ 0xA9, 0xA4, 0x26, 0x8C, 0x37, 0x00, 0xA1, 0x1A, 0xC4, 0xC1, 0xA1, 0x00, 0xF5, 0x8A, 0x7A, 0xFB,
+ 0x2B, 0x45, 0x70, 0xE4, 0xB5, 0x45, 0xAA, 0x00
+};
+
+void test_homekit(void)
+{
+ extern srp_keys_t srp;
+ extern crypto_keys_t crypto_keys;
+
+ return;
+
+ LOG_LV2_BUFFER("Private b", srp.b, 32);
+ LOG_LV2_BUFFER("Salt s", srp.salt, 16);
+ LOG_LV2_BUFFER("Verifier v", srp.v, 384);
+ LOG_LV2_BUFFER("Public B", srp.B, 384);
+
+ LOG_LV2_BUFFER("Sign Secret", crypto_keys.sign.secret, 64);
+
+ LOG_LV2_BUFFER("Client Name", crypto_keys.client.name, 36);
+ LOG_LV2_BUFFER("Client ltpk", crypto_keys.client.ltpk, 32);
+}
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Homekit Light Bulb Example");
+ Serial.println("--------------------------------------\n");
+
+ // Homekit uses a lot of characteristics so that default Attr Table size
+ // is not enough. Therefore we need to incresae the ATTR Table Size
+ // Note: All config***() function must be called before begin()
+ Bluefruit.configAttrTableSize(3000);
+
+ // Config the peripheral connection with maximum bandwidth
+ Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
+
+ Bluefruit.begin();
+
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+
+ //InternalFS.remove(CRYPTO_KEYFILE);
+ //File file(CRYPTO_KEYFILE, FILE_WRITE, InternalFS);
+ //file.write(&test_keys, sizeof(test_keys));
+ //file.close();
+
+ homekit.begin();
+
+ test_homekit();
+
+ // Set up and start advertising
+ startAdv();
+}
+
+void startAdv(void)
+{
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 30
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.setStopCallback(adv_stop_callback); // callback when adv is stopped
+
+ /* Homekit include advertising interval as part of its adv data
+ * - Therefore setInterval() must be call before setData(homekit).
+ * - Furthermore since Adverting Data (for homekit) changes when adv interval change
+ * from fast to slow. We do either way to stay consistence
+ * 1. Advertise with fixed interval (fast = slow)
+ * 2. Register stop callback for adv stop, then re-set the Advertising data to match
+ * the changed interval. Which is what this sketch does.
+ */
+ Bluefruit.Advertising.setData(homekit);
+
+ // Stop after 30 secconds
+ Bluefruit.Advertising.start(30);
+}
+
+void adv_stop_callback(void)
+{
+ // change interval to only slow since we alredy passed first 30 seconds
+ Bluefruit.Advertising.setInterval(244, 244);
+
+ // Reset advertising data for homekit.
+ Bluefruit.Advertising.clearData();
+ Bluefruit.Advertising.setData(homekit);
+
+ // Advertising indefintely.
+ Bluefruit.Advertising.start(0);
+}
+
+void loop()
+{
+ // Toggle both LEDs every 1 second
+ digitalToggle(LED_RED);
+ delay(1000);
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/README.md b/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/README.md
new file mode 100755
index 0000000..f6edc00
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/README.md
@@ -0,0 +1,24 @@
+# RSSI Proximity Project
+
+This project demonstrates how you can use a single Bluefruit nRF52 device
+running in Central mode to listen for a specific signature in the advertising
+packets of nearby Bluefruit nRF52 devices running in peripheral mode.
+
+The Central mode device will sort those devices with the matching signature by
+proximity based on their RSSI (relative signal strength) value.
+
+Most of the Central mode advertising API is used in this demo, making it an
+excellent place to start if you want to create your own custom Central based
+project(s).
+
+## Project Files
+
+This project consists of two parts:
+
+- `rssi_proximity_central`: This project should be run on one Bluefruit nRF52
+ board and will configure the board as a Central device, actively scanning
+ for any peripheral devices in listening range.
+- `rssi_proximity_peripheral`: This project should be run on one or more
+ Bluefruit nRF52 boards and will configure the boards as peripheral devices,
+ sending out a specifically formatted advertising packet at a regular
+ interval.
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_central/rssi_proximity_central.ino b/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_central/rssi_proximity_central.ino
new file mode 100755
index 0000000..c284268
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_central/rssi_proximity_central.ino
@@ -0,0 +1,683 @@
+/*********************************************************************
+ 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
+
+ Author: KTOWN (Kevin Townsend)
+ Copyright (C) Adafruit Industries 2017
+*********************************************************************/
+
+/* This example scans for advertising devices (peripherals) in range,
+ * looking for a specific UUID in the advertising packet. When this
+ * UUID is found, it will display an alert, sorting devices detected
+ * in range by their RSSI value, which is an approximate indicator of
+ * proximity (though highly dependent on environmental obstacles, etc.).
+ *
+ * A simple 'bubble sort' algorithm is used, along with a simple
+ * set of decisions about whether and where to insert new records
+ * in the record list.
+ *
+ * This example is intended to be used with multiple peripherals
+ * devices running the *_peripheral.ino version of this application.
+ *
+ * VERBOSE_OUTPUT
+ * --------------
+ * Verbose advertising packet analysis can be enabled for
+ * advertising packet contents to help debug issues with the
+ * advertising payloads, with fully parsed data displayed in the
+ * Serial Monitor.
+ *
+ * ARRAY_SIZE
+ * ----------
+ * The numbers of peripherals tracked and sorted can be set via the
+ * ARRAY_SIZE macro. Must be at least 2.
+ *
+ * TIMEOUT_MS
+ * ----------
+ * This value determines the number of milliseconds before a tracked
+ * peripheral has it's last sample 'invalidated', such as when a device
+ * is tracked and then goes out of range.
+ *
+ * ENABLE_TFT
+ * ----------
+ * An ILI9341 based TFT can optionally be used to display proximity
+ * alerts. The Adafruit TFT Feather Wing is recommended and is the only
+ * device tested with this functionality.
+ *
+ * ENABLE_OLED
+ * -----------
+ * An SSD1306 128x32 based OLED can optionally be used to display
+ * proximity alerts. The Adafruit OLED Feather Wing is recommended and
+ * is the only device tested with this functionality.
+ */
+
+#include <string.h>
+#include <bluefruit.h>
+#include <SPI.h>
+
+#define VERBOSE_OUTPUT (0) // Set this to 1 for verbose adv packet output to the serial monitor
+#define ARRAY_SIZE (4) // The number of RSSI values to store and compare
+#define TIMEOUT_MS (2500) // Number of milliseconds before a record is invalidated in the list
+#define ENABLE_TFT (0) // Set this to 1 to enable ILI9341 TFT display support
+#define ENABLE_OLED (0) // Set this to 1 to enable SSD1306 128x32 OLED display support
+
+#if (ARRAY_SIZE <= 1)
+ #error "ARRAY_SIZE must be at least 2"
+#endif
+#if (ENABLE_TFT) && (ENABLE_OLED)
+ #error "ENABLE_TFT and ENABLE_OLED can not both be set at the same time"
+#endif
+
+// Custom UUID used to differentiate this device.
+// Use any online UUID generator to generate a valid UUID.
+// Note that the byte order is reversed ... CUSTOM_UUID
+// below corresponds to the follow value:
+// df67ff1a-718f-11e7-8cf7-a6006ad3dba0
+const uint8_t CUSTOM_UUID[] =
+{
+ 0xA0, 0xDB, 0xD3, 0x6A, 0x00, 0xA6, 0xF7, 0x8C,
+ 0xE7, 0x11, 0x8F, 0x71, 0x1A, 0xFF, 0x67, 0xDF
+};
+
+BLEUuid uuid = BLEUuid(CUSTOM_UUID);
+
+/* TFT setup if the TFT display is available */
+#if (ENABLE_TFT)
+ #include <Adafruit_GFX.h>
+ #include <Adafruit_ILI9341.h>
+
+ /* Pin setup for the TFT display over SPI */
+ #ifdef ARDUINO_NRF52_FEATHER
+ #define TFT_DC 11
+ #define TFT_CS 31
+ #define STMPE_CS 30
+ #define SD_CS 27
+ #else
+ #error "Unknown target. Please make sure you are using an nRF52 Feather and BSP 0.6.5 or higher!"
+ #endif
+
+ Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
+#endif
+
+/* 128x32 OLED setup if the OLED display is available */
+#if (ENABLE_OLED)
+ #include <Wire.h>
+ #include <Adafruit_GFX.h>
+ #include <Adafruit_SSD1306.h>
+
+ /* Pin setup for the OLED display */
+ #ifdef ARDUINO_NRF52_FEATHER
+ #define BUTTON_A 31
+ #define BUTTON_B 30
+ #define BUTTON_C 27
+ #else
+ #error "Unknown target. Please make sure you are using an nRF52 Feather and BSP 0.6.5 or higher!"
+ #endif
+
+ Adafruit_SSD1306 oled = Adafruit_SSD1306();
+#endif
+
+/* This struct is used to track detected nodes */
+typedef struct node_record_s
+{
+ uint8_t addr[6]; // Six byte device address
+ int8_t rssi; // RSSI value
+ int32_t timestamp; // Timestamp for invalidation purposes
+ int8_t reserved; // Padding for word alignment
+} node_record_t;
+
+node_record_t records[ARRAY_SIZE];
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Central Proximity Example");
+ Serial.println("-------------------------------------\n");
+
+ /* Enable the TFT display if available */
+ #if ENABLE_TFT
+ tft.begin();
+ tft.fillScreen(ILI9341_BLACK);
+ tft.setCursor(40, 0);
+ tft.setTextColor(ILI9341_WHITE);
+ tft.setTextSize(2);
+ tft.println("DUNKIN");
+ #endif
+
+ /* Enable the OLED display if available */
+ #if ENABLE_OLED
+ oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
+ oled.display();
+ #endif
+
+ /* Clear the results list */
+ memset(records, 0, sizeof(records));
+ for (uint8_t i = 0; i<ARRAY_SIZE; i++)
+ {
+ // Set all RSSI values to lowest value for comparison purposes,
+ // since 0 would be higher than any valid RSSI value
+ records[i].rssi = -128;
+ }
+
+ /* Enable both peripheral and central modes */
+ err_t err = Bluefruit.begin(true, true);
+ if (err)
+ {
+ Serial.print("Unable to init Bluefruit (ERROR CODE: ");
+ Serial.print(err);
+ Serial.println(")");
+ while(1)
+ {
+ digitalToggle(LED_RED);
+ delay(100);
+ }
+ }
+ else
+ {
+ Serial.println("Bluefruit initialized (central mode)");
+ }
+
+ // 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); // Only invoke callback for devices with RSSI >= -80 dBm
+ Bluefruit.Scanner.filterUuid(uuid); // Only invoke callback if the target UUID was found
+ //Bluefruit.Scanner.filterMSD(0xFFFF); // Only invoke callback when MSD is present with the specified Company ID
+ 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 ...");
+}
+
+/* This callback handler is fired every time a valid advertising packet is detected */
+void scan_callback(ble_gap_evt_adv_report_t* report)
+{
+ node_record_t record;
+
+ /* Prepare the record to try to insert it into the existing record list */
+ memcpy(record.addr, report->peer_addr.addr, 6); /* Copy the 6-byte device ADDR */
+ record.rssi = report->rssi; /* Copy the RSSI value */
+ record.timestamp = millis(); /* Set the timestamp (approximate) */
+
+ /* Attempt to insert the record into the list */
+ if (insertRecord(&record) == 1) /* Returns 1 if the list was updated */
+ {
+ printRecordList(); /* The list was updated, print the new values */
+ Serial.println("");
+
+ /* Display the device list on the TFT if available */
+ #if ENABLE_TFT
+ renderResultsToTFT();
+ #endif
+
+ /* Display the device list on the OLED if available */
+ #if ENABLE_OLED
+ renderResultsToOLED();
+ #endif
+ }
+
+/* Fully parse and display the advertising packet to the Serial Monitor
+ * if verbose/debug output is requested */
+#if VERBOSE_OUTPUT
+ uint8_t len = 0;
+ uint8_t buffer[32];
+ memset(buffer, 0, sizeof(buffer));
+
+ /* Display the timestamp and device address */
+ if (report->scan_rsp)
+ {
+ 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.println("");
+
+ /* Raw buffer contents */
+ Serial.printf("%14s %d bytes\n", "PAYLOAD", report->dlen);
+ if (report->dlen)
+ {
+ Serial.printf("%15s", " ");
+ Serial.printBuffer(report->data, report->dlen, '-');
+ Serial.println();
+ }
+
+ /* RSSI value */
+ Serial.printf("%14s %d dBm\n", "RSSI", report->rssi);
+
+ /* Adv Type */
+ Serial.printf("%14s ", "ADV TYPE");
+ switch (report->type)
+ {
+ case BLE_GAP_ADV_TYPE_ADV_IND:
+ Serial.printf("Connectable undirected\n");
+ break;
+ case BLE_GAP_ADV_TYPE_ADV_DIRECT_IND:
+ Serial.printf("Connectable directed\n");
+ break;
+ case BLE_GAP_ADV_TYPE_ADV_SCAN_IND:
+ Serial.printf("Scannable undirected\n");
+ break;
+ case BLE_GAP_ADV_TYPE_ADV_NONCONN_IND:
+ Serial.printf("Non-connectable undirected\n");
+ break;
+ }
+
+ /* 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();
+#endif
+
+ // For Softdevice v6: after received a report, scanner will be paused
+ // We need to call Scanner resume() to continue scanning
+ Bluefruit.Scanner.resume();
+}
+
+#if ENABLE_TFT
+void renderResultsToTFT(void)
+{
+ tft.fillRect(0, 0, 240, ARRAY_SIZE*8, ILI9341_BLACK);
+ tft.setTextSize(1);
+ tft.setCursor(0, 0);
+
+ for (uint8_t i=0; i<ARRAY_SIZE; i++)
+ {
+ if (records[i].addr[0] <= 0xF) tft.print("0");
+ tft.print(records[i].addr[0], HEX);
+ tft.print(":");
+ if (records[i].addr[1] <= 0xF) tft.print("0");
+ tft.print(records[i].addr[1], HEX);
+ tft.print(":");
+ if (records[i].addr[2] <= 0xF) tft.print("0");
+ tft.print(records[i].addr[2], HEX);
+ tft.print(":");
+ if (records[i].addr[3] <= 0xF) tft.print("0");
+ tft.print(records[i].addr[3], HEX);
+ tft.print(":");
+ if (records[i].addr[4] <= 0xF) tft.print("0");
+ tft.print(records[i].addr[4], HEX);
+ tft.print(":");
+ if (records[i].addr[5] <= 0xF) tft.print("0");
+ tft.print(records[i].addr[5], HEX);
+ tft.print(" ");
+ tft.print(records[i].rssi);
+ tft.print(" [");
+ tft.print(records[i].timestamp);
+ tft.println("] ");
+ }
+}
+#endif
+
+#if ENABLE_OLED
+void renderResultsToOLED(void)
+{
+ oled.clearDisplay();
+ oled.setTextSize(1);
+ oled.setTextColor(WHITE);
+
+ for (uint8_t i=0; i<ARRAY_SIZE; i++)
+ {
+ if (i>=4)
+ {
+ /* We can only display four records on a 128x32 pixel display */
+ oled.display();
+ return;
+ }
+ if (records[i].rssi != -128)
+ {
+ oled.setCursor(0, i*8);
+ if (records[i].addr[0] <= 0xF) oled.print("0");
+ oled.print(records[i].addr[0], HEX);
+ oled.print(":");
+ if (records[i].addr[1] <= 0xF) oled.print("0");
+ oled.print(records[i].addr[1], HEX);
+ oled.print(":");
+ if (records[i].addr[2] <= 0xF) oled.print("0");
+ oled.print(records[i].addr[2], HEX);
+ oled.print(":");
+ if (records[i].addr[3] <= 0xF) oled.print("0");
+ oled.print(records[i].addr[3], HEX);
+ oled.print(":");
+ if (records[i].addr[4] <= 0xF) oled.print("0");
+ oled.print(records[i].addr[4], HEX);
+ oled.print(":");
+ if (records[i].addr[5] <= 0xF) oled.print("0");
+ oled.print(records[i].addr[5], HEX);
+ oled.print(" ");
+ oled.println(records[i].rssi);
+ }
+ }
+
+ oled.display();
+}
+#endif
+
+/* Prints a UUID16 list to the Serial Monitor */
+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();
+}
+
+/* Prints a UUID128 list to the Serial Monitor */
+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();
+}
+
+/* Prints the current record list to the Serial Monitor */
+void printRecordList(void)
+{
+ for (uint8_t i = 0; i<ARRAY_SIZE; i++)
+ {
+ Serial.printf("[%i] ", i);
+ Serial.printBuffer(records[i].addr, 6, ':');
+ Serial.printf(" %i (%u ms)\n", records[i].rssi, records[i].timestamp);
+ }
+}
+
+/* This function performs a simple bubble sort on the records array */
+/* It's slow, but relatively easy to understand */
+/* Sorts based on RSSI values, where the strongest signal appears highest in the list */
+void bubbleSort(void)
+{
+ int inner, outer;
+ node_record_t temp;
+
+ for(outer=0; outer<ARRAY_SIZE-1; outer++)
+ {
+ for(inner=outer+1; inner<ARRAY_SIZE; inner++)
+ {
+ if(records[outer].rssi < records[inner].rssi)
+ {
+ memcpy((void *)&temp, (void *)&records[outer], sizeof(node_record_t)); // temp=records[outer];
+ memcpy((void *)&records[outer], (void *)&records[inner], sizeof(node_record_t)); // records[outer] = records[inner];
+ memcpy((void *)&records[inner], (void *)&temp, sizeof(node_record_t)); // records[inner] = temp;
+ }
+ }
+ }
+}
+
+/* This function will check if any records in the list
+ * have expired and need to be invalidated, such as when
+ * a device goes out of range.
+ *
+ * Returns the number of invalidated records, or 0 if
+ * nothing was changed.
+ */
+int invalidateRecords(void)
+{
+ uint8_t i;
+ int match = 0;
+
+ /* Not enough time has elapsed to avoid an underflow error */
+ if (millis() <= TIMEOUT_MS)
+ {
+ return 0;
+ }
+
+ /* Check if any records have expired */
+ for (i=0; i<ARRAY_SIZE; i++)
+ {
+ if (records[i].timestamp) // Ignore zero"ed records
+ {
+ if (records[i].timestamp <= millis() - TIMEOUT_MS)
+ {
+ /* Record has expired, zero it out */
+ memset(&records[i], 0, sizeof(node_record_t));
+ records[i].rssi = -128;
+ match++;
+ }
+ }
+ }
+
+ /* Resort the list if something was zero'ed out */
+ if (match)
+ {
+ // Serial.printf("Invalidated %i records!\n", match);
+ bubbleSort();
+ }
+
+ return match;
+}
+
+/* This function attempts to insert the record if it is larger than the smallest valid RSSI entry */
+/* Returns 1 if a change was made, otherwise 0 */
+int insertRecord(node_record_t *record)
+{
+ uint8_t i;
+
+ /* Invalidate results older than n milliseconds */
+ invalidateRecords();
+
+ /* Record Insertion Workflow:
+ *
+ * START
+ * |
+ * \ /
+ * +-------------+
+ * 1. | BUBBLE SORT | // Put list in known state!
+ * +-------------+
+ * |
+ * _____\ /_____
+ * / ENTRY \ YES
+ * 2. < EXISTS W/THIS > ------------------+
+ * \ ADDRESS? / |
+ * ----------- |
+ * | NO |
+ * | |
+ * ______\ /______ |
+ * / IS \ YES |
+ * 3. < THERE A ZERO'ED >------------------+
+ * \ RECORD? / |
+ * ------------- |
+ * | NO |
+ * | |
+ * ______\ /________ |
+ * / IS THE \ YES |
+ * 4.< RECORD'S RSSI >= >----------------|
+ * \ THE LOWEST RSSI? / |
+ * ---------------- |
+ * | NO |
+ * | |
+ * \ / \ /
+ * +---------------+ +----------------+
+ * | IGNORE RECORD | | REPLACE RECORD |
+ * +---------------+ +----------------+
+ * | |
+ * | \ /
+ * \ / +----------------+
+ * EXIT <------------- | BUBBLE SORT |
+ * +----------------+
+ */
+
+ /* 1. Bubble Sort
+ * This puts the lists in a known state where we can make
+ * certain assumptions about the last record in the array. */
+ bubbleSort();
+
+ /* 2. Check for a match on existing device address */
+ /* Replace it if a match is found, then sort */
+ uint8_t match = 0;
+ for (i=0; i<ARRAY_SIZE; i++)
+ {
+ if (memcmp(records[i].addr, record->addr, 6) == 0)
+ {
+ match = 1;
+ }
+ if (match)
+ {
+ memcpy(&records[i], record, sizeof(node_record_t));
+ goto sort_then_exit;
+ }
+ }
+
+ /* 3. Check for zero'ed records */
+ /* Insert if a zero record is found, then sort */
+ for (i=0; i<ARRAY_SIZE; i++)
+ {
+ if (records[i].rssi == -128)
+ {
+ memcpy(&records[i], record, sizeof(node_record_t));
+ goto sort_then_exit;
+ }
+ }
+
+ /* 4. Check RSSI of the lowest record */
+ /* Replace if >=, then sort */
+ if (records[ARRAY_SIZE-1].rssi <= record->rssi)
+ {
+ memcpy(&records[ARRAY_SIZE-1], record, sizeof(node_record_t));
+ goto sort_then_exit;
+ }
+
+ /* Nothing to do ... RSSI is lower than the last value, exit and ignore */
+ return 0;
+
+sort_then_exit:
+ /* Bubble sort */
+ bubbleSort();
+ return 1;
+}
+
+void loop()
+{
+ /* Toggle red LED every second */
+ digitalToggle(LED_RED);
+
+ /* Invalidate old results once per second in addition
+ * to the invalidation in the callback handler. */
+ /* ToDo: Update to use a mutex or semaphore since this
+ * can lead to list corruption as-is if the scann results
+ * callback is fired in the middle of the invalidation
+ * function. */
+ if (invalidateRecords())
+ {
+ /* The list was updated, print the new values */
+ printRecordList();
+ Serial.println("");
+ /* Display the device list on the TFT if available */
+ #if ENABLE_TFT
+ renderResultsToTFT();
+ #endif
+ /* Display the device list on the OLED if available */
+ #if ENABLE_OLED
+ renderResultsToOLED();
+ #endif
+ }
+
+ delay(1000);
+}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_peripheral/rssi_proximity_peripheral.ino b/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_peripheral/rssi_proximity_peripheral.ino
new file mode 100755
index 0000000..1a39836
--- /dev/null
+++ b/arduino/libraries/Bluefruit52Lib/examples/Projects/rssi_proximity/rssi_proximity_peripheral/rssi_proximity_peripheral.ino
@@ -0,0 +1,160 @@
+/*********************************************************************
+ 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
+
+ Author: KTOWN (Kevin Townsend)
+ Copyright (C) Adafruit Industries 2017
+*********************************************************************/
+
+/* This example constantly advertises a custom 128-bit UUID, and is
+ * intended to be used in combination with a Central sketch that scans
+ * for this UUID, and then displays an alert message, sorting matching
+ * devices by their RSSI level which is an approximate indication of
+ * distance (although highly subject to environmental obstacles).
+ *
+ * By including a custom UUID in the advertising packet, we can easily
+ * filter the scan results on the Central device, rather than manually
+ * parsing the advertising packet(s) of every device in range.
+ *
+ * This example is intended to be run with the *_central.ino version
+ * of this application.
+ */
+
+#include <bluefruit.h>
+#include <ble_gap.h>
+
+// Software Timer for blinking RED LED
+SoftwareTimer blinkTimer;
+
+// Custom UUID used to differentiate this device.
+// Use any online UUID generator to generate a valid UUID.
+// Note that the byte order is reversed ... CUSTOM_UUID
+// below corresponds to the follow value:
+// df67ff1a-718f-11e7-8cf7-a6006ad3dba0
+const uint8_t CUSTOM_UUID[] =
+{
+ 0xA0, 0xDB, 0xD3, 0x6A, 0x00, 0xA6, 0xF7, 0x8C,
+ 0xE7, 0x11, 0x8F, 0x71, 0x1A, 0xFF, 0x67, 0xDF
+};
+
+BLEUuid uuid = BLEUuid(CUSTOM_UUID);
+
+void setup()
+{
+ Serial.begin(115200);
+ while ( !Serial ) delay(10); // for nrf52840 with native usb
+
+ Serial.println("Bluefruit52 Peripheral Proximity Example");
+ Serial.println("----------------------------------------\n");
+
+ // Initialize blinkTimer for 1000 ms and start it
+ blinkTimer.begin(1000, blink_timer_callback);
+ blinkTimer.start();
+
+ err_t err = Bluefruit.begin();
+ if (err)
+ {
+ Serial.print("Unable to init Bluefruit (ERROR CODE: ");
+ Serial.print(err);
+ Serial.println(")");
+ while(1)
+ {
+ digitalToggle(LED_RED);
+ delay(100);
+ }
+ }
+ else
+ {
+ Serial.println("Bluefruit initialized (peripheral mode)");
+ }
+
+ // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
+ Bluefruit.setTxPower(4);
+ Bluefruit.setName("Bluefruit52");
+
+ // Set up and start advertising
+ startAdv();
+
+ Serial.println("Advertising started");
+}
+
+void startAdv(void)
+{
+ // Note: The entire advertising packet is limited to 31 bytes!
+
+ // Advertising packet
+ Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
+ Bluefruit.Advertising.addTxPower();
+
+ // Preferred Solution: Add a custom UUID to the advertising payload, which
+ // we will look for on the Central side via Bluefruit.Scanner.filterUuid(uuid);
+ // A valid 128-bit UUID can be generated online with almost no chance of conflict
+ // with another device or etup
+ Bluefruit.Advertising.addUuid(uuid);
+
+ /*
+ // Alternative Solution: Manufacturer Specific Data (MSD)
+ // You could also send a custom MSD payload and filter for the 'Company ID'
+ // via 'Bluefruit.Scanner.filterMSD(CID);', although this does require a
+ // valid CID, which is why the UUID method above is more appropriate in
+ // most situations. For a complete list of valid company IDs see:
+ // https://www.bluetooth.com/specifications/assigned-numbers/company-identifiers
+ // For test purposes, 0xFFFF CAN be used, but according to the Bluetooth SIG:
+ // > "This value may be used in the internal and interoperability tests before a
+ // > Company ID has been assigned. This value shall not be used in shipping end
+ // > products."
+ uint8_t msd_payload[4]; // Two bytes are required for the CID, so we have 2 bytes user data, expand as needed
+ uint16_t msd_cid = 0xFFFF;
+ memset(msd_payload, 0, sizeof(msd_payload));
+ memcpy(msd_payload, (uint8_t*)&msd_cid, sizeof(msd_cid));
+ msd_payload[2] = 0x11;
+ msd_payload[3] = 0x22;
+ Bluefruit.Advertising.addData(BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, msd_payload, sizeof(msd_payload));
+ */
+
+ // Not enough room in the advertising packet for name
+ // so store it in the Scan Response instead
+ Bluefruit.ScanResponse.addName();
+
+ /* Start Advertising
+ * - Enable auto advertising if disconnected
+ * - Interval: fast mode = 20 ms, slow mode = 152.5 ms
+ * - Timeout for fast mode is 30 seconds
+ * - Start(timeout) with timeout = 0 will advertise forever (until connected)
+ *
+ * For recommended advertising interval
+ * https://developer.apple.com/library/content/qa/qa1931/_index.html
+ */
+ Bluefruit.Advertising.restartOnDisconnect(true);
+ Bluefruit.Advertising.setInterval(32, 244); // in units of 0.625 ms
+ Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
+ Bluefruit.Advertising.start();
+}
+
+void loop()
+{
+}
+
+/**
+ * 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;
+ digitalToggle(LED_RED);
+}
+