3.3.7
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
## Bluetooth Serial Library
|
||||
|
||||
A simple Serial compatible library using ESP32 classical Bluetooth Serial Port Profile (SPP)
|
||||
|
||||
Note: Since version 3.0.0 this library does not support legacy pairing (using fixed PIN consisting of 4 digits).
|
||||
|
||||
### How to use it?
|
||||
|
||||
There are 3 basic use cases: phone, other ESP32 or any MCU with a Bluetooth serial module
|
||||
|
||||
#### Phone
|
||||
|
||||
- Download one of the Bluetooth terminal apps to your smartphone
|
||||
|
||||
- For [Android](https://play.google.com/store/apps/details?id=de.kai_morich.serial_bluetooth_terminal)
|
||||
- For [iOS](https://itunes.apple.com/us/app/hm10-bluetooth-serial-lite/id1030454675)
|
||||
|
||||
- Flash an example sketch to your ESP32
|
||||
|
||||
- Scan and pair the device to your smartphone
|
||||
|
||||
- Open the Bluetooth terminal app and connect
|
||||
|
||||
- Enjoy
|
||||
|
||||
#### ESP32
|
||||
|
||||
You can flash one of the ESP32 with the example [`SerialToSerialBTM`](https://github.com/espressif/arduino-esp32/blob/master/libraries/BluetoothSerial/examples/SerialToSerialBTM/SerialToSerialBTM.ino) (the Master) and another ESP32 with [`SerialToSerialBT`](https://github.com/espressif/arduino-esp32/blob/master/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino) (the Slave).
|
||||
Those examples are preset to work out-of-the-box but they should be scalable to connect multiple Slaves to the Master.
|
||||
|
||||
#### 3rd party Serial Bluetooth module
|
||||
|
||||
Using a 3rd party Serial Bluetooth module will require to study the documentation of the particular module in order to make it work, however, one side can utilize the mentioned [`SerialToSerialBTM`](https://github.com/espressif/arduino-esp32/blob/master/libraries/BluetoothSerial/examples/SerialToSerialBTM/SerialToSerialBTM.ino) (the Master) or [`SerialToSerialBT`](https://github.com/espressif/arduino-esp32/blob/master/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino) (the Slave).
|
||||
|
||||
### Pairing options
|
||||
|
||||
There are two easy options and one difficult.
|
||||
|
||||
The easy options can be used as usual. These offer pairing with and without Secure Simple Pairing (SSP).
|
||||
|
||||
The difficult option offers legacy pairing (using fixed PIN) however this must be compiled with Arduino as an IDF component with disabled sdkconfig option `CONFIG_BT_SSP_ENABLED`.
|
||||
|
||||
#### Without SSP
|
||||
|
||||
This method will authenticate automatically any attempt to pair and should not be used if security is a concern! This option is used for the examples [`SerialToSerialBTM`](https://github.com/espressif/arduino-esp32/blob/master/libraries/BluetoothSerial/examples/SerialToSerialBTM/SerialToSerialBTM.ino) and [`SerialToSerialBT`](https://github.com/espressif/arduino-esp32/blob/master/libraries/BluetoothSerial/examples/SerialToSerialBT/SerialToSerialBT.ino).
|
||||
|
||||
### With SSP
|
||||
|
||||
The usage of SSP provides a secure connection. This option is demonstrated in the example `SerialToSerialBT_SSP``](https://github.com/espressif/arduino-esp32/blob/master/libraries/BluetoothSerial/examples/SerialToSerialBT_SSP/SerialToSerialBT_SSP.ino)
|
||||
|
||||
The Secure Simple Pairing is enabled by calling method `enableSSP` which has two variants - one is backward compatible without parameter `enableSSP()` and second with parameters `enableSSP(bool inputCapability, bool outputCapability)`. Similarly, the SSP can be disabled by calling `disableSSP()`.
|
||||
|
||||
Both options must be called before `begin()` or if it is called after `begin()` the driver needs to be restarted (call `end()` followed by `begin()`) in order to take in effect enabling or disabling the SSP.
|
||||
|
||||
#### The parameters define the method of authentication:
|
||||
|
||||
**inputCapability** - Defines if ESP32 device has input method (Serial terminal, keyboard or similar)
|
||||
|
||||
**outputCapability** - Defines if ESP32 device has output method (Serial terminal, display or similar)
|
||||
|
||||
* **inputCapability=true and outputCapability=true**
|
||||
* Both devices display randomly generated code and if they match the user will authenticate pairing on both devices.
|
||||
* This must be implemented by registering a callback via `onConfirmRequest()` and in this callback the user will input the response and call `confirmReply(true)` if the authenticated, otherwise call `confirmReply(false)` to reject the pairing.
|
||||
* **inputCapability=false and outputCapability=false**
|
||||
* Only the other device authenticates pairing without any pin.
|
||||
* **inputCapability=false and outputCapability=true**
|
||||
* Only the other device authenticates pairing without any pin.
|
||||
* **inputCapability=true and outputCapability=false**
|
||||
* The user will be required to input the passkey to the ESP32 device to authenticate.
|
||||
* This must be implemented by registering a callback via `onKeyRequest`()` and in this callback the entered passkey will be responded via `respondPasskey(passkey)`
|
||||
|
||||
### Legacy Pairing (IDF component)
|
||||
|
||||
To use Legacy pairing you will have to use [Arduino as an IDF component](https://espressif-docs.readthedocs-hosted.com/projects/arduino-esp32/en/latest/esp-idf_component.html) and disable option `CONFIG_BT_SSP_ENABLED`.
|
||||
Please refer to the documentation on how to setup Arduino as an IDF component and when you are done, run `idf.py menuconfig` navigate to `Component Config -> Bluetooth -> Bluedroid -> [ ] Secure Simple Pairing` and disable it.
|
||||
While in the menuconfig you will also need to change the partition scheme `Partition Table -> Partition Table -> (X) Single Factory app (large), no OTA`.
|
||||
After these changes save & quit menuconfig and you are ready to go: `idf.py monitor flash`.
|
||||
Please note that to use the PIN in smartphones and computers you need to use characters `SerialBT.setPin("1234", 4);` not a number `SerialBT.setPin(1234, 4);` . Numbers CAN be used if the other side uses them too, but phones and computers use characters.
|
||||
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Bluetooth Classic Example
|
||||
* Scan for devices - asynchronously, print device as soon as found
|
||||
* query devices for SPP - SDP profile
|
||||
* connect to first device offering a SPP connection
|
||||
*
|
||||
* Example python server:
|
||||
* source: https://gist.github.com/ukBaz/217875c83c2535d22a16ba38fc8f2a91
|
||||
*
|
||||
* Tested with Raspberry Pi onboard Wifi/BT, USB BT 4.0 dongles, USB BT 1.1 dongles,
|
||||
* 202202: does NOT work with USB BT 2.0 dongles when esp32 arduino lib is compiled with SSP support!
|
||||
* see https://github.com/espressif/esp-idf/issues/8394
|
||||
*
|
||||
* use ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE in connect() if remote side requests 'RequireAuthentication': dbus.Boolean(True),
|
||||
* use ESP_SPP_SEC_NONE or ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE in connect() if remote side has Authentication: False
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <BluetoothSerial.h>
|
||||
|
||||
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
|
||||
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_BT_SPP_ENABLED)
|
||||
#error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
|
||||
#endif
|
||||
|
||||
BluetoothSerial SerialBT;
|
||||
|
||||
#define BT_DISCOVER_TIME 10000
|
||||
esp_spp_sec_t sec_mask = ESP_SPP_SEC_NONE; // or ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE to request pincode confirmation
|
||||
esp_spp_role_t role = ESP_SPP_ROLE_SLAVE; // or ESP_SPP_ROLE_MASTER
|
||||
|
||||
// std::map<BTAddress, BTAdvertisedDeviceSet> btDeviceList;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
if (!SerialBT.begin("ESP32test", true)) {
|
||||
Serial.println("========== serialBT failed!");
|
||||
abort();
|
||||
}
|
||||
// SerialBT.setPin("1234"); // doesn't seem to change anything
|
||||
// SerialBT.enableSSP(); // doesn't seem to change anything
|
||||
|
||||
Serial.println("Starting discoverAsync...");
|
||||
BTScanResults *btDeviceList = SerialBT.getScanResults(); // maybe accessing from different threads!
|
||||
if (SerialBT.discoverAsync([](BTAdvertisedDevice *pDevice) {
|
||||
// BTAdvertisedDeviceSet*set = reinterpret_cast<BTAdvertisedDeviceSet*>(pDevice);
|
||||
// btDeviceList[pDevice->getAddress()] = * set;
|
||||
Serial.printf(">>>>>>>>>>>Found a new device asynchronously: %s\n", pDevice->toString().c_str());
|
||||
})) {
|
||||
delay(BT_DISCOVER_TIME);
|
||||
Serial.print("Stopping discoverAsync... ");
|
||||
SerialBT.discoverAsyncStop();
|
||||
Serial.println("discoverAsync stopped");
|
||||
delay(5000);
|
||||
if (btDeviceList->getCount() > 0) {
|
||||
BTAddress addr;
|
||||
int channel = 0;
|
||||
Serial.println("Found devices:");
|
||||
for (int i = 0; i < btDeviceList->getCount(); i++) {
|
||||
BTAdvertisedDevice *device = btDeviceList->getDevice(i);
|
||||
Serial.printf(" ----- %s %s %d\n", device->getAddress().toString().c_str(), device->getName().c_str(), device->getRSSI());
|
||||
std::map<int, std::string> channels = SerialBT.getChannels(device->getAddress());
|
||||
Serial.printf("scanned for services, found %zu\n", channels.size());
|
||||
for (auto const &entry : channels) {
|
||||
Serial.printf(" channel %d (%s)\n", entry.first, entry.second.c_str());
|
||||
}
|
||||
if (channels.size() > 0) {
|
||||
addr = device->getAddress();
|
||||
channel = channels.begin()->first;
|
||||
}
|
||||
}
|
||||
if (addr) {
|
||||
Serial.printf("connecting to %s - %d\n", addr.toString().c_str(), channel);
|
||||
SerialBT.connect(addr, channel, sec_mask, role);
|
||||
}
|
||||
} else {
|
||||
Serial.println("Didn't find any devices");
|
||||
}
|
||||
} else {
|
||||
Serial.println("Error on discoverAsync f.e. not working after a \"connect\"");
|
||||
}
|
||||
}
|
||||
|
||||
String sendData = "Hi from esp32!\n";
|
||||
|
||||
void loop() {
|
||||
if (!SerialBT.isClosed() && SerialBT.connected()) {
|
||||
if (SerialBT.write((const uint8_t *)sendData.c_str(), sendData.length()) != sendData.length()) {
|
||||
Serial.println("tx: error");
|
||||
} else {
|
||||
Serial.printf("tx: %s", sendData.c_str());
|
||||
}
|
||||
if (SerialBT.available()) {
|
||||
Serial.print("rx: ");
|
||||
while (SerialBT.available()) {
|
||||
int c = SerialBT.read();
|
||||
if (c >= 0) {
|
||||
Serial.print((char)c);
|
||||
}
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
} else {
|
||||
Serial.println("not connected");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
fqbn_append: PartitionScheme=huge_app
|
||||
|
||||
requires:
|
||||
- CONFIG_BT_SPP_ENABLED=y
|
||||
@@ -0,0 +1,49 @@
|
||||
// This example demonstrates usage of BluetoothSerial method to retrieve MAC address of local BT device in various formats.
|
||||
// By Tomas Pilny - 2023
|
||||
|
||||
#include "BluetoothSerial.h"
|
||||
|
||||
String device_name = "ESP32-example";
|
||||
|
||||
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
|
||||
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_BT_SPP_ENABLED)
|
||||
#error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
|
||||
#endif
|
||||
|
||||
BluetoothSerial SerialBT;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
SerialBT.begin(device_name); //Bluetooth device name
|
||||
|
||||
uint8_t mac_arr[6]; // Byte array to hold the MAC address from getBtAddress()
|
||||
BTAddress mac_obj; // Object holding instance of BTAddress with the MAC (for more details see libraries/BluetoothSerial/src/BTAddress.h)
|
||||
String mac_str; // String holding the text version of MAC in format AA:BB:CC:DD:EE:FF
|
||||
|
||||
SerialBT.getBtAddress(mac_arr); // Fill in the array
|
||||
mac_obj = SerialBT.getBtAddressObject(); // Instantiate the object
|
||||
mac_str = SerialBT.getBtAddressString(); // Copy the string
|
||||
|
||||
Serial.print("This device is instantiated with name ");
|
||||
Serial.println(device_name);
|
||||
|
||||
Serial.print("The mac address using byte array: ");
|
||||
for (int i = 0; i < ESP_BD_ADDR_LEN - 1; i++) {
|
||||
Serial.print(mac_arr[i], HEX);
|
||||
Serial.print(":");
|
||||
}
|
||||
Serial.println(mac_arr[ESP_BD_ADDR_LEN - 1], HEX);
|
||||
|
||||
Serial.print("The mac address using BTAddress object using default method `toString()`: ");
|
||||
Serial.println(mac_obj.toString().c_str());
|
||||
Serial.print("The mac address using BTAddress object using method `toString(true)`\n\twhich prints the MAC with capital letters: ");
|
||||
Serial.println(mac_obj.toString(true).c_str()); // This actually what is used inside the getBtAddressString()
|
||||
|
||||
Serial.print("The mac address using string: ");
|
||||
Serial.println(mac_str.c_str());
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
@@ -0,0 +1,4 @@
|
||||
fqbn_append: PartitionScheme=huge_app
|
||||
|
||||
requires:
|
||||
- CONFIG_BT_SPP_ENABLED=y
|
||||
@@ -0,0 +1,39 @@
|
||||
// This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
// By Evandro Copercini - 2018
|
||||
//
|
||||
// This example creates a bridge between Serial and Classical Bluetooth (SPP)
|
||||
// and also demonstrate that SerialBT have the same functionalities of a normal Serial
|
||||
// Note: Pairing is authenticated automatically by this device
|
||||
|
||||
#include "BluetoothSerial.h"
|
||||
|
||||
String device_name = "ESP32-BT-Slave";
|
||||
|
||||
// Check if Bluetooth is available
|
||||
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
|
||||
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
|
||||
#endif
|
||||
|
||||
// Check Serial Port Profile
|
||||
#if !defined(CONFIG_BT_SPP_ENABLED)
|
||||
#error Serial Port Profile for Bluetooth is not available or not enabled. It is only available for the ESP32 chip.
|
||||
#endif
|
||||
|
||||
BluetoothSerial SerialBT;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
SerialBT.begin(device_name); //Bluetooth device name
|
||||
//SerialBT.deleteAllBondedDevices(); // Uncomment this to delete paired devices; Must be called after begin
|
||||
Serial.printf("The device with name \"%s\" is started.\nNow you can pair it with Bluetooth!\n", device_name.c_str());
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (Serial.available()) {
|
||||
SerialBT.write(Serial.read());
|
||||
}
|
||||
if (SerialBT.available()) {
|
||||
Serial.write(SerialBT.read());
|
||||
}
|
||||
delay(20);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
fqbn_append: PartitionScheme=huge_app
|
||||
|
||||
requires:
|
||||
- CONFIG_BT_SPP_ENABLED=y
|
||||
@@ -0,0 +1,97 @@
|
||||
// This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
// By Victor Tchistiak - 2019
|
||||
//
|
||||
// This example demonstrates master mode Bluetooth connection to a slave BT device
|
||||
// defined either by String "slaveName" by default "ESP32-BT-Slave" or by MAC address
|
||||
//
|
||||
// This example creates a bridge between Serial and Classical Bluetooth (SPP)
|
||||
// This is an extension of the SerialToSerialBT example by Evandro Copercini - 2018
|
||||
//
|
||||
// DO NOT try to connect to phone or laptop - they are master
|
||||
// devices, same as the ESP using this code - you will be able
|
||||
// to pair, but the serial communication will NOT work!
|
||||
//
|
||||
// You can try to flash a second ESP32 with the example SerialToSerialBT - it should
|
||||
// automatically pair with ESP32 running this code
|
||||
// Note: Pairing is authenticated automatically by this device
|
||||
|
||||
#include "BluetoothSerial.h"
|
||||
|
||||
#define USE_NAME // Comment this to use MAC address instead of a slaveName
|
||||
|
||||
// Check if Bluetooth is available
|
||||
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
|
||||
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
|
||||
#endif
|
||||
|
||||
// Check Serial Port Profile
|
||||
#if !defined(CONFIG_BT_SPP_ENABLED)
|
||||
#error Serial Port Profile for Bluetooth is not available or not enabled. It is only available for the ESP32 chip.
|
||||
#endif
|
||||
BluetoothSerial SerialBT;
|
||||
|
||||
#ifdef USE_NAME
|
||||
String slaveName = "ESP32-BT-Slave"; // Change this to reflect the real name of your slave BT device
|
||||
#else
|
||||
String MACadd = "AA:BB:CC:11:22:33"; // This only for printing
|
||||
uint8_t address[6] = {0xAA, 0xBB, 0xCC, 0x11, 0x22, 0x33}; // Change this to reflect real MAC address of your slave BT device
|
||||
#endif
|
||||
|
||||
String myName = "ESP32-BT-Master";
|
||||
|
||||
void setup() {
|
||||
bool connected;
|
||||
Serial.begin(115200);
|
||||
|
||||
SerialBT.begin(myName, true);
|
||||
//SerialBT.deleteAllBondedDevices(); // Uncomment this to delete paired devices; Must be called after begin
|
||||
Serial.printf("The device \"%s\" started in master mode, make sure slave BT device is on!\n", myName.c_str());
|
||||
|
||||
#ifndef USE_NAME
|
||||
SerialBT.setPin(pin);
|
||||
Serial.println("Using PIN");
|
||||
#endif
|
||||
|
||||
// connect(address) is fast (up to 10 secs max), connect(slaveName) is slow (up to 30 secs max) as it needs
|
||||
// to resolve slaveName to address first, but it allows to connect to different devices with the same name.
|
||||
// Set CoreDebugLevel to Info to view devices Bluetooth address and device names
|
||||
#ifdef USE_NAME
|
||||
connected = SerialBT.connect(slaveName);
|
||||
Serial.printf("Connecting to slave BT device named \"%s\"\n", slaveName.c_str());
|
||||
#else
|
||||
connected = SerialBT.connect(address);
|
||||
Serial.print("Connecting to slave BT device with MAC ");
|
||||
Serial.println(MACadd);
|
||||
#endif
|
||||
|
||||
if (connected) {
|
||||
Serial.println("Connected Successfully!");
|
||||
} else {
|
||||
while (!SerialBT.connected(10000)) {
|
||||
Serial.println("Failed to connect. Make sure remote device is available and in range, then restart app.");
|
||||
}
|
||||
}
|
||||
// Disconnect() may take up to 10 secs max
|
||||
if (SerialBT.disconnect()) {
|
||||
Serial.println("Disconnected Successfully!");
|
||||
}
|
||||
// This would reconnect to the slaveName(will use address, if resolved) or address used with connect(slaveName/address).
|
||||
SerialBT.connect();
|
||||
if (connected) {
|
||||
Serial.println("Reconnected Successfully!");
|
||||
} else {
|
||||
while (!SerialBT.connected(10000)) {
|
||||
Serial.println("Failed to reconnect. Make sure remote device is available and in range, then restart app.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (Serial.available()) {
|
||||
SerialBT.write(Serial.read());
|
||||
}
|
||||
if (SerialBT.available()) {
|
||||
Serial.write(SerialBT.read());
|
||||
}
|
||||
delay(20);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
fqbn_append: PartitionScheme=huge_app
|
||||
|
||||
requires:
|
||||
- CONFIG_BT_SPP_ENABLED=y
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
// This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
//
|
||||
// This example creates a bridge between Serial and Classical Bluetooth (SPP with authentication)
|
||||
// and also demonstrate that SerialBT have the same functionalities of a normal Serial
|
||||
// Legacy pairing TODO
|
||||
// Must be run as idf component ... todo
|
||||
|
||||
#include "BluetoothSerial.h"
|
||||
|
||||
// Check if Bluetooth is available
|
||||
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
|
||||
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
|
||||
#endif
|
||||
|
||||
// Check Serial Port Profile
|
||||
#if !defined(CONFIG_BT_SPP_ENABLED)
|
||||
#error Serial Port Profile for Bluetooth is not available or not enabled. It is only available for the ESP32 chip.
|
||||
#endif
|
||||
|
||||
const char *deviceName = "ESP32_Legacy_example";
|
||||
|
||||
BluetoothSerial SerialBT;
|
||||
bool confirmRequestDone = false;
|
||||
|
||||
void BTAuthCompleteCallback(boolean success) {
|
||||
if (success) {
|
||||
confirmRequestDone = true;
|
||||
Serial.println("Pairing success!!");
|
||||
} else {
|
||||
Serial.println("Pairing failed, rejected by user!!");
|
||||
}
|
||||
}
|
||||
|
||||
void serial_response() {
|
||||
if (Serial.available()) {
|
||||
SerialBT.write(Serial.read());
|
||||
}
|
||||
if (SerialBT.available()) {
|
||||
Serial.write(SerialBT.read());
|
||||
}
|
||||
delay(20);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
SerialBT.onAuthComplete(BTAuthCompleteCallback);
|
||||
SerialBT.begin(deviceName); // Initiate Bluetooth device with name in parameter
|
||||
SerialBT.setPin("1234", 4);
|
||||
Serial.printf("The device started with name \"%s\", now you can pair it with Bluetooth!\n", deviceName);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (confirmRequestDone) {
|
||||
serial_response();
|
||||
} else {
|
||||
delay(1); // Feed the watchdog
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
fqbn_append: PartitionScheme=huge_app
|
||||
|
||||
requires:
|
||||
- CONFIG_BT_SPP_ENABLED=y
|
||||
@@ -0,0 +1,131 @@
|
||||
// This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
// By Richard Li - 2020
|
||||
//
|
||||
// This example creates a bridge between Serial and Classical Bluetooth (SPP with authentication)
|
||||
// and also demonstrate that SerialBT have the same functionalities of a normal Serial
|
||||
// SSP - Simple Secure Pairing - The device (ESP32) will display random number and the user is responsible of comparing it to the number
|
||||
// displayed on the other device (for example phone).
|
||||
// If the numbers match the user authenticates the pairing on both devices - on phone simply press "Pair" and in terminal for the sketch send 'Y' or 'y' to confirm.
|
||||
// Alternatively uncomment AUTO_PAIR to skip the terminal confirmation.
|
||||
|
||||
#include "BluetoothSerial.h"
|
||||
|
||||
//#define AUTO_PAIR // Uncomment to automatically authenticate ESP32 side
|
||||
|
||||
// Check if Bluetooth is available
|
||||
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
|
||||
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
|
||||
#endif
|
||||
|
||||
// Check Serial Port Profile
|
||||
#if !defined(CONFIG_BT_SPP_ENABLED)
|
||||
#error Serial Port Profile for Bluetooth is not available or not enabled. It is only available for the ESP32 chip.
|
||||
#endif
|
||||
|
||||
const char *deviceName = "ESP32_SSP_example";
|
||||
|
||||
// The following lines defines the method of pairing
|
||||
// When both Input and Output are false only the other device authenticates pairing without any pin.
|
||||
// When Output is true and Input is false only the other device authenticates pairing without any pin.
|
||||
// When both Input and Output are true both devices display randomly generated code and if they match authenticate pairing on both devices
|
||||
// - This must be implemented by registering callback via onConfirmRequest() and in this callback request user input and call confirmReply(true); if the authenticated
|
||||
// otherwise call `confirmReply(false)` to reject the pairing.
|
||||
// When Input is true and Output is false User will be required to input the passkey to the ESP32 device to authenticate.
|
||||
// - This must be implemented by registering callback via onKeyRequest() and in this callback the entered passkey will be responded via respondPasskey(passkey);
|
||||
const bool INPUT_CAPABILITY = false; // Defines if ESP32 device has input method (Serial terminal, keyboard or similar)
|
||||
const bool OUTPUT_CAPABILITY = true; // Defines if ESP32 device has output method (Serial terminal, display or similar)
|
||||
|
||||
BluetoothSerial SerialBT;
|
||||
bool confirmRequestDone = false;
|
||||
|
||||
void BTConfirmRequestCallback(uint32_t numVal) {
|
||||
confirmRequestDone = false;
|
||||
#ifndef AUTO_PAIR
|
||||
Serial.printf(
|
||||
"The PIN is: %06lu. If it matches number displayed on the other device write \'Y\' or \'y\':\n", numVal
|
||||
); // Note the formatting "%06lu" - PIN can start with zero(s) which would be ignored with simple "%lu"
|
||||
while (!Serial.available()) {
|
||||
delay(1); // Feed the watchdog
|
||||
// Wait until data is available on the Serial port.
|
||||
}
|
||||
Serial.printf("Oh you sent %d Bytes, lets see...", Serial.available());
|
||||
int dat = Serial.read();
|
||||
if (dat == 'Y' || dat == 'y') {
|
||||
SerialBT.confirmReply(true);
|
||||
} else {
|
||||
SerialBT.confirmReply(false);
|
||||
}
|
||||
#else
|
||||
SerialBT.confirmReply(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void BTKeyRequestCallback() {
|
||||
Serial.println("BTKeyRequestCallback"); // debug
|
||||
char buffer[7] = {0}; // 6 bytes for number, one for termination '0'
|
||||
while (1) {
|
||||
Serial.print("Enter the passkey displayed on the other device: ");
|
||||
while (!Serial.available()) {
|
||||
delay(1); // Feed the watchdog
|
||||
// Wait until data is available on the Serial port.
|
||||
}
|
||||
size_t len = Serial.readBytesUntil('\n', buffer, sizeof(buffer) - 1);
|
||||
buffer[len] = '\0'; // Null-terminate the string.
|
||||
try {
|
||||
uint32_t passkey = std::stoi(buffer);
|
||||
Serial.printf("Entered PIN: %lu\n", passkey);
|
||||
SerialBT.respondPasskey(passkey);
|
||||
return;
|
||||
} catch (...) {
|
||||
Serial.print("Wrong PIN! Try again.");
|
||||
} // try
|
||||
} // while(1)
|
||||
}
|
||||
|
||||
void BTAuthCompleteCallback(boolean success) {
|
||||
if (success) {
|
||||
confirmRequestDone = true;
|
||||
Serial.println("Pairing success!!");
|
||||
} else {
|
||||
Serial.println("Pairing failed, rejected by user!!");
|
||||
}
|
||||
}
|
||||
|
||||
void serial_response() {
|
||||
if (Serial.available()) {
|
||||
SerialBT.write(Serial.read());
|
||||
}
|
||||
if (SerialBT.available()) {
|
||||
Serial.write(SerialBT.read());
|
||||
}
|
||||
delay(20);
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
SerialBT.enableSSP(INPUT_CAPABILITY, OUTPUT_CAPABILITY); // Must be called before begin
|
||||
SerialBT.onConfirmRequest(BTConfirmRequestCallback);
|
||||
SerialBT.onKeyRequest(BTKeyRequestCallback);
|
||||
SerialBT.onAuthComplete(BTAuthCompleteCallback);
|
||||
SerialBT.begin(deviceName); // Initiate Bluetooth device with name in parameter
|
||||
//SerialBT.deleteAllBondedDevices(); // Uncomment this to delete paired devices; Must be called after begin
|
||||
Serial.printf("The device started with name \"%s\", now you can pair it with Bluetooth!\n", deviceName);
|
||||
if (INPUT_CAPABILITY and OUTPUT_CAPABILITY) {
|
||||
Serial.println("Both devices will display randomly generated code and if they match authenticate pairing on both devices");
|
||||
} else if (not INPUT_CAPABILITY and not OUTPUT_CAPABILITY) {
|
||||
Serial.println("Authenticate pairing on the other device. No PIN is used");
|
||||
} else if (not INPUT_CAPABILITY and OUTPUT_CAPABILITY) {
|
||||
Serial.println("Authenticate pairing on the other device. No PIN is used");
|
||||
} else if (INPUT_CAPABILITY and not OUTPUT_CAPABILITY) {
|
||||
Serial.println("After pairing is initiated you will be required to enter the passkey to the ESP32 device to authenticate\n > The Passkey will displayed on "
|
||||
"the other device");
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (confirmRequestDone) {
|
||||
serial_response();
|
||||
} else {
|
||||
delay(1); // Feed the watchdog
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
fqbn_append: PartitionScheme=huge_app
|
||||
|
||||
requires:
|
||||
- CONFIG_BT_SPP_ENABLED=y
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
#include <BluetoothSerial.h>
|
||||
|
||||
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
|
||||
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_BT_SPP_ENABLED)
|
||||
#error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
|
||||
#endif
|
||||
|
||||
BluetoothSerial SerialBT;
|
||||
|
||||
#define BT_DISCOVER_TIME 10000
|
||||
|
||||
static bool btScanAsync = true;
|
||||
static bool btScanSync = true;
|
||||
|
||||
void btAdvertisedDeviceFound(BTAdvertisedDevice *pDevice) {
|
||||
Serial.printf("Found a device asynchronously: %s\n", pDevice->toString().c_str());
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
SerialBT.begin("ESP32test"); //Bluetooth device name
|
||||
Serial.println("The device started, now you can pair it with bluetooth!");
|
||||
|
||||
if (btScanAsync) {
|
||||
Serial.print("Starting asynchronous discovery... ");
|
||||
if (SerialBT.discoverAsync(btAdvertisedDeviceFound)) {
|
||||
Serial.println("Findings will be reported in \"btAdvertisedDeviceFound\"");
|
||||
delay(10000);
|
||||
Serial.print("Stopping discoverAsync... ");
|
||||
SerialBT.discoverAsyncStop();
|
||||
Serial.println("stopped");
|
||||
} else {
|
||||
Serial.println("Error on discoverAsync f.e. not working after a \"connect\"");
|
||||
}
|
||||
}
|
||||
|
||||
if (btScanSync) {
|
||||
Serial.println("Starting synchronous discovery... ");
|
||||
BTScanResults *pResults = SerialBT.discover(BT_DISCOVER_TIME);
|
||||
if (pResults) {
|
||||
pResults->dump(&Serial);
|
||||
} else {
|
||||
Serial.println("Error on BT Scan, no result!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
delay(100);
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
fqbn_append: PartitionScheme=huge_app
|
||||
|
||||
requires:
|
||||
- CONFIG_BT_SPP_ENABLED=y
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
// This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
// Originally by Victor Tchistiak - 2019
|
||||
// Rewritten with new API by Tomas Pilny - 2023
|
||||
//
|
||||
// This example demonstrates reading and removing paired devices stored on the ESP32 flash memory
|
||||
// Sometimes you may find your ESP32 device could not connect to the remote device despite
|
||||
// many successful connections earlier. This is most likely a result of client replacing your paired
|
||||
// device info with new one from other device. The BT clients store connection info for paired devices,
|
||||
// but it is limited to a few devices only. When new device pairs and number of stored devices is exceeded,
|
||||
// one of the previously paired devices would be replaced with new one.
|
||||
// The only remedy is to delete this saved bound device from your device flash memory
|
||||
// and pair with the other device again.
|
||||
|
||||
#include "BluetoothSerial.h"
|
||||
//#include "esp_bt_device.h"
|
||||
|
||||
#if !defined(CONFIG_BT_SPP_ENABLED)
|
||||
#error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
|
||||
#endif
|
||||
|
||||
#define REMOVE_BONDED_DEVICES true // <- Set to `false` to view all bonded devices addresses, set to `true` to remove
|
||||
#define PAIR_MAX_DEVICES 20
|
||||
BluetoothSerial SerialBT;
|
||||
|
||||
char *bda2str(const uint8_t *bda, char *str, size_t size) {
|
||||
if (bda == NULL || str == NULL || size < 18) {
|
||||
return NULL;
|
||||
}
|
||||
sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
|
||||
return str;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
char bda_str[18];
|
||||
uint8_t pairedDeviceBtAddr[PAIR_MAX_DEVICES][6];
|
||||
Serial.begin(115200);
|
||||
|
||||
SerialBT.begin();
|
||||
Serial.printf("ESP32 bluetooth address: %s\n", SerialBT.getBtAddressString().c_str());
|
||||
// SerialBT.deleteAllBondedDevices(); // If you want just delete all, this is the way
|
||||
// Get the numbers of bonded/paired devices in the BT module
|
||||
int count = SerialBT.getNumberOfBondedDevices();
|
||||
if (!count) {
|
||||
Serial.println("No bonded devices found.");
|
||||
} else {
|
||||
Serial.printf("Bonded device count: %d\n", count);
|
||||
if (PAIR_MAX_DEVICES < count) {
|
||||
count = PAIR_MAX_DEVICES;
|
||||
Serial.printf("Reset %d bonded devices\n", count);
|
||||
}
|
||||
count = SerialBT.getBondedDevices(count, pairedDeviceBtAddr);
|
||||
char rmt_name[ESP_BT_GAP_MAX_BDNAME_LEN + 1];
|
||||
if (count > 0) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
SerialBT.requestRemoteName(pairedDeviceBtAddr[i]);
|
||||
while (!SerialBT.readRemoteName(rmt_name)) {
|
||||
delay(1); // Wait for response with the device name
|
||||
}
|
||||
Serial.printf("Found bonded device #%d BDA:%s; Name:\"%s\"\n", i, bda2str(pairedDeviceBtAddr[i], bda_str, 18), rmt_name);
|
||||
SerialBT.invalidateRemoteName(); // Allows waiting for next reading
|
||||
if (REMOVE_BONDED_DEVICES) {
|
||||
if (SerialBT.deleteBondedDevice(pairedDeviceBtAddr[i])) {
|
||||
Serial.printf("Removed bonded device # %d\n", i);
|
||||
} else {
|
||||
Serial.printf("Failed to remove bonded device # %d", i);
|
||||
} // if(ESP_OK == tError)
|
||||
} // if(REMOVE_BONDED_DEVICES)
|
||||
} // for(int i = 0; i < count; i++)
|
||||
} // if(ESP_OK == tError)
|
||||
} // if(!count)
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
@@ -0,0 +1,4 @@
|
||||
fqbn_append: PartitionScheme=huge_app
|
||||
|
||||
requires:
|
||||
- CONFIG_BT_SPP_ENABLED=y
|
||||
@@ -0,0 +1,26 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For BluetoothSerial
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Library (KEYWORD3)
|
||||
#######################################
|
||||
|
||||
BluetoothSerial KEYWORD3
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
BluetoothSerial KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
SerialBT KEYWORD2
|
||||
hasClient KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
@@ -0,0 +1,9 @@
|
||||
name=BluetoothSerial
|
||||
version=3.3.7
|
||||
author=Evandro Copercini
|
||||
maintainer=Evandro Copercini
|
||||
sentence=Simple UART to Classical Bluetooth bridge for ESP32
|
||||
paragraph=
|
||||
category=Communication
|
||||
url=
|
||||
architectures=esp32
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* BTAddress.cpp
|
||||
*
|
||||
* Created on: Jul 2, 2017
|
||||
* Author: kolban
|
||||
* Ported on: Feb 5, 2021
|
||||
* Author: Thomas M. (ArcticSnowSky)
|
||||
*/
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_BT_SUPPORTED && defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
|
||||
|
||||
#include "BTAddress.h"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include "esp32-hal-log.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Create an address from the native ESP32 representation.
|
||||
* @param [in] address The native representation.
|
||||
*/
|
||||
BTAddress::BTAddress(esp_bd_addr_t address) {
|
||||
memcpy(m_address, address, ESP_BD_ADDR_LEN);
|
||||
} // BTAddress
|
||||
|
||||
BTAddress::BTAddress() {
|
||||
bzero(m_address, ESP_BD_ADDR_LEN);
|
||||
} // BTAddress
|
||||
|
||||
/**
|
||||
* @brief Create an address from a hex string
|
||||
*
|
||||
* A hex string is of the format:
|
||||
* ```
|
||||
* 00:00:00:00:00:00
|
||||
* ```
|
||||
* which is 17 characters in length.
|
||||
*
|
||||
* @param [in] stringAddress The hex representation of the address.
|
||||
*/
|
||||
BTAddress::BTAddress(String stringAddress) {
|
||||
if (stringAddress.length() != 17) {
|
||||
return;
|
||||
}
|
||||
|
||||
int data[6];
|
||||
sscanf(stringAddress.c_str(), "%x:%x:%x:%x:%x:%x", &data[0], &data[1], &data[2], &data[3], &data[4], &data[5]);
|
||||
m_address[0] = (uint8_t)data[0];
|
||||
m_address[1] = (uint8_t)data[1];
|
||||
m_address[2] = (uint8_t)data[2];
|
||||
m_address[3] = (uint8_t)data[3];
|
||||
m_address[4] = (uint8_t)data[4];
|
||||
m_address[5] = (uint8_t)data[5];
|
||||
} // BTAddress
|
||||
|
||||
/**
|
||||
* @brief Determine if this address equals another.
|
||||
* @param [in] otherAddress The other address to compare against.
|
||||
* @return True if the addresses are equal.
|
||||
*/
|
||||
bool BTAddress::equals(BTAddress otherAddress) {
|
||||
return memcmp(otherAddress.getNative(), m_address, 6) == 0;
|
||||
} // equals
|
||||
|
||||
BTAddress::operator bool() const {
|
||||
for (int i = 0; i < ESP_BD_ADDR_LEN; i++) {
|
||||
if (this->m_address[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} // operator ()
|
||||
|
||||
/**
|
||||
* @brief Return the native representation of the address.
|
||||
* @return The native representation of the address.
|
||||
*/
|
||||
esp_bd_addr_t *BTAddress::getNative() const {
|
||||
return const_cast<esp_bd_addr_t *>(&m_address);
|
||||
} // getNative
|
||||
|
||||
/**
|
||||
* @brief Convert a BT address to a string.
|
||||
* @param [in] capital changes the letter size
|
||||
* By default the parameter `capital` == false and the string representation of an address is in the format:
|
||||
* ```
|
||||
* xx:xx:xx:xx:xx:xx
|
||||
* ```
|
||||
* When the parameter `capital` == true the format uses capital letters:
|
||||
* ```
|
||||
* XX:XX:XX:XX:XX:XX
|
||||
* ```
|
||||
* @return The string representation of the address.
|
||||
*/
|
||||
String BTAddress::toString(bool capital) const {
|
||||
auto size = 18;
|
||||
char *res = (char *)malloc(size);
|
||||
if (capital) {
|
||||
snprintf(res, size, "%02X:%02X:%02X:%02X:%02X:%02X", m_address[0], m_address[1], m_address[2], m_address[3], m_address[4], m_address[5]);
|
||||
} else {
|
||||
snprintf(res, size, "%02x:%02x:%02x:%02x:%02x:%02x", m_address[0], m_address[1], m_address[2], m_address[3], m_address[4], m_address[5]);
|
||||
}
|
||||
String ret(res);
|
||||
free(res);
|
||||
return ret;
|
||||
} // toString
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* BTAddress.h
|
||||
*
|
||||
* Created on: Jul 2, 2017
|
||||
* Author: kolban
|
||||
* Ported on: Feb 5, 2021
|
||||
* Author: Thomas M. (ArcticSnowSky)
|
||||
*/
|
||||
|
||||
#ifndef COMPONENTS_CPP_UTILS_BTADDRESS_H_
|
||||
#define COMPONENTS_CPP_UTILS_BTADDRESS_H_
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_BT_SUPPORTED && defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
|
||||
#include <esp_gap_bt_api.h> // ESP32 BT
|
||||
#include <Arduino.h>
|
||||
|
||||
/**
|
||||
* @brief A %BT device address.
|
||||
*
|
||||
* Every %BT device has a unique address which can be used to identify it and form connections.
|
||||
*/
|
||||
class BTAddress {
|
||||
public:
|
||||
BTAddress();
|
||||
BTAddress(esp_bd_addr_t address);
|
||||
BTAddress(String stringAddress);
|
||||
bool equals(BTAddress otherAddress);
|
||||
operator bool() const;
|
||||
|
||||
esp_bd_addr_t *getNative() const;
|
||||
String toString(bool capital = false) const;
|
||||
|
||||
private:
|
||||
esp_bd_addr_t m_address;
|
||||
};
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
#endif /* COMPONENTS_CPP_UTILS_BTADDRESS_H_ */
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* BTAdvertisedDevice.h
|
||||
*
|
||||
* Created on: Feb 5, 2021
|
||||
* Author: Thomas M. (ArcticSnowSky)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_BT_SUPPORTED && defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
|
||||
#include "BTAddress.h"
|
||||
#include <string>
|
||||
|
||||
class BTAdvertisedDevice {
|
||||
public:
|
||||
virtual ~BTAdvertisedDevice() = default;
|
||||
|
||||
virtual BTAddress getAddress() = 0;
|
||||
virtual uint32_t getCOD() const = 0;
|
||||
virtual std::string getName() const = 0;
|
||||
virtual int8_t getRSSI() const = 0;
|
||||
|
||||
virtual bool haveCOD() const = 0;
|
||||
virtual bool haveName() const = 0;
|
||||
virtual bool haveRSSI() const = 0;
|
||||
|
||||
virtual std::string toString() = 0;
|
||||
};
|
||||
|
||||
class BTAdvertisedDeviceSet : public virtual BTAdvertisedDevice {
|
||||
public:
|
||||
BTAdvertisedDeviceSet();
|
||||
//~BTAdvertisedDeviceSet() = default;
|
||||
|
||||
BTAddress getAddress();
|
||||
uint32_t getCOD() const;
|
||||
std::string getName() const;
|
||||
int8_t getRSSI() const;
|
||||
|
||||
bool haveCOD() const;
|
||||
bool haveName() const;
|
||||
bool haveRSSI() const;
|
||||
|
||||
std::string toString();
|
||||
|
||||
void setAddress(BTAddress address);
|
||||
void setCOD(uint32_t cod);
|
||||
void setName(std::string name);
|
||||
void setRSSI(int8_t rssi);
|
||||
|
||||
bool m_haveCOD;
|
||||
bool m_haveName;
|
||||
bool m_haveRSSI;
|
||||
|
||||
BTAddress m_address = BTAddress((uint8_t *)"\0\0\0\0\0\0");
|
||||
uint32_t m_cod;
|
||||
std::string m_name;
|
||||
int8_t m_rssi;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* BTAdvertisedDeviceSet.cpp
|
||||
*
|
||||
* Created on: Feb 5, 2021
|
||||
* Author: Thomas M. (ArcticSnowSky)
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_BT_SUPPORTED && defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
|
||||
|
||||
//#include <map>
|
||||
|
||||
#include "BTAdvertisedDevice.h"
|
||||
//#include "BTScan.h"
|
||||
|
||||
BTAdvertisedDeviceSet::BTAdvertisedDeviceSet() {
|
||||
m_cod = 0;
|
||||
m_name = "";
|
||||
m_rssi = 0;
|
||||
|
||||
m_haveCOD = false;
|
||||
m_haveName = false;
|
||||
m_haveRSSI = false;
|
||||
} // BTAdvertisedDeviceSet
|
||||
|
||||
BTAddress BTAdvertisedDeviceSet::getAddress() {
|
||||
return m_address;
|
||||
}
|
||||
uint32_t BTAdvertisedDeviceSet::getCOD() const {
|
||||
return m_cod;
|
||||
}
|
||||
std::string BTAdvertisedDeviceSet::getName() const {
|
||||
return m_name;
|
||||
}
|
||||
int8_t BTAdvertisedDeviceSet::getRSSI() const {
|
||||
return m_rssi;
|
||||
}
|
||||
|
||||
bool BTAdvertisedDeviceSet::haveCOD() const {
|
||||
return m_haveCOD;
|
||||
}
|
||||
bool BTAdvertisedDeviceSet::haveName() const {
|
||||
return m_haveName;
|
||||
}
|
||||
bool BTAdvertisedDeviceSet::haveRSSI() const {
|
||||
return m_haveRSSI;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a string representation of this device.
|
||||
* @return A string representation of this device.
|
||||
*/
|
||||
std::string BTAdvertisedDeviceSet::toString() {
|
||||
std::string res = "Name: " + getName() + ", Address: " + std::string(getAddress().toString().c_str(), getAddress().toString().length());
|
||||
if (haveCOD()) {
|
||||
char val[7]; //6 hex digits + null
|
||||
snprintf(val, sizeof(val), "%06lx", getCOD() & 0xFFFFFF);
|
||||
res += ", cod: 0x";
|
||||
res += val;
|
||||
}
|
||||
if (haveRSSI()) {
|
||||
char val[6];
|
||||
snprintf(val, sizeof(val), "%d", (int8_t)getRSSI());
|
||||
res += ", rssi: ";
|
||||
res += val;
|
||||
}
|
||||
return res;
|
||||
} // toString
|
||||
|
||||
void BTAdvertisedDeviceSet::setAddress(BTAddress address) {
|
||||
m_address = address;
|
||||
}
|
||||
|
||||
void BTAdvertisedDeviceSet::setCOD(uint32_t cod) {
|
||||
m_cod = cod;
|
||||
m_haveCOD = true;
|
||||
}
|
||||
|
||||
void BTAdvertisedDeviceSet::setName(std::string name) {
|
||||
m_name = name;
|
||||
m_haveName = true;
|
||||
}
|
||||
|
||||
void BTAdvertisedDeviceSet::setRSSI(int8_t rssi) {
|
||||
m_rssi = rssi;
|
||||
m_haveRSSI = true;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* BTScan.h
|
||||
*
|
||||
* Created on: Feb 5, 2021
|
||||
* Author: Thomas M. (ArcticSnowSky)
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_BT_SUPPORTED && defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <Print.h>
|
||||
#include "BTAddress.h"
|
||||
#include "BTAdvertisedDevice.h"
|
||||
|
||||
class BTAdvertisedDevice;
|
||||
class BTAdvertisedDeviceSet;
|
||||
|
||||
class BTScanResults {
|
||||
public:
|
||||
virtual ~BTScanResults() = default;
|
||||
|
||||
virtual void dump(Print *print = nullptr) = 0;
|
||||
virtual int getCount() = 0;
|
||||
virtual BTAdvertisedDevice *getDevice(int i) = 0;
|
||||
};
|
||||
|
||||
class BTScanResultsSet : public BTScanResults {
|
||||
public:
|
||||
void dump(Print *print = nullptr);
|
||||
int getCount();
|
||||
BTAdvertisedDevice *getDevice(int i);
|
||||
|
||||
bool add(BTAdvertisedDeviceSet advertisedDevice, bool unique = true);
|
||||
void clear();
|
||||
|
||||
std::map<std::string, BTAdvertisedDeviceSet> m_vectorAdvertisedDevices;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* BTScanResultsSet.cpp
|
||||
*
|
||||
* Created on: Feb 5, 2021
|
||||
* Author: Thomas M. (ArcticSnowSky)
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_BT_SUPPORTED && defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
|
||||
|
||||
#include <esp_err.h>
|
||||
|
||||
#include "BTAdvertisedDevice.h"
|
||||
#include "BTScan.h"
|
||||
//#include "GeneralUtils.h"
|
||||
#include "esp32-hal-log.h"
|
||||
|
||||
class BTAdvertisedDevice;
|
||||
|
||||
/**
|
||||
* @brief Dump the scan results to the log.
|
||||
*/
|
||||
void BTScanResultsSet::dump(Print *print) {
|
||||
int cnt = getCount();
|
||||
if (print == nullptr) {
|
||||
log_v(">> Dump scan results : %d", cnt);
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
BTAdvertisedDevice *dev = getDevice(i);
|
||||
if (dev) {
|
||||
log_d("- %d: %s\n", i + 1, dev->toString().c_str());
|
||||
} else {
|
||||
log_d("- %d is null\n", i + 1);
|
||||
}
|
||||
}
|
||||
log_v("-- dump finished --");
|
||||
} else {
|
||||
print->printf(">> Dump scan results: %d\n", cnt);
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
BTAdvertisedDevice *dev = getDevice(i);
|
||||
if (dev) {
|
||||
print->printf("- %d: %s\n", i + 1, dev->toString().c_str());
|
||||
} else {
|
||||
print->printf("- %d is null\n", i + 1);
|
||||
}
|
||||
}
|
||||
print->println("-- Dump finished --");
|
||||
}
|
||||
} // dump
|
||||
|
||||
/**
|
||||
* @brief Return the count of devices found in the last scan.
|
||||
* @return The number of devices found in the last scan.
|
||||
*/
|
||||
int BTScanResultsSet::getCount() {
|
||||
return m_vectorAdvertisedDevices.size();
|
||||
} // getCount
|
||||
|
||||
/**
|
||||
* @brief Return the specified device at the given index.
|
||||
* The index should be between 0 and getCount()-1.
|
||||
* @param [in] i The index of the device.
|
||||
* @return The device at the specified index.
|
||||
*/
|
||||
BTAdvertisedDevice *BTScanResultsSet::getDevice(int i) {
|
||||
if (i < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int x = 0;
|
||||
BTAdvertisedDeviceSet *pDev = &m_vectorAdvertisedDevices.begin()->second;
|
||||
for (auto it = m_vectorAdvertisedDevices.begin(); it != m_vectorAdvertisedDevices.end(); it++) {
|
||||
pDev = &it->second;
|
||||
if (x == i) {
|
||||
break;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
return x == i ? pDev : nullptr;
|
||||
}
|
||||
|
||||
void BTScanResultsSet::clear() {
|
||||
//for(auto _dev : m_vectorAdvertisedDevices)
|
||||
// delete _dev.second;
|
||||
m_vectorAdvertisedDevices.clear();
|
||||
}
|
||||
|
||||
bool BTScanResultsSet::add(BTAdvertisedDeviceSet advertisedDevice, bool unique) {
|
||||
std::string key = std::string(advertisedDevice.getAddress().toString().c_str(), advertisedDevice.getAddress().toString().length());
|
||||
if (!unique || m_vectorAdvertisedDevices.count(key) == 0) {
|
||||
m_vectorAdvertisedDevices.insert(std::pair<std::string, BTAdvertisedDeviceSet>(key, advertisedDevice));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,120 @@
|
||||
// Copyright 2018 Evandro Luis Copercini
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _BLUETOOTH_SERIAL_H_
|
||||
#define _BLUETOOTH_SERIAL_H_
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_BT_SUPPORTED && defined(CONFIG_BT_ENABLED) && defined(CONFIG_BLUEDROID_ENABLED)
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Stream.h"
|
||||
#include <esp_gap_bt_api.h>
|
||||
#include <esp_spp_api.h>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include "BTScan.h"
|
||||
#include "BTAdvertisedDevice.h"
|
||||
|
||||
typedef std::function<void(const uint8_t *buffer, size_t size)> BluetoothSerialDataCb;
|
||||
typedef std::function<void(uint32_t num_val)> ConfirmRequestCb;
|
||||
typedef std::function<void()> KeyRequestCb;
|
||||
typedef std::function<void(boolean success)> AuthCompleteCb;
|
||||
typedef std::function<void(BTAdvertisedDevice *pAdvertisedDevice)> BTAdvertisedDeviceCb;
|
||||
|
||||
class [[deprecated("BluetoothSerial won't be supported in version 4.0.0 by default")]] BluetoothSerial : public Stream {
|
||||
public:
|
||||
BluetoothSerial(void);
|
||||
~BluetoothSerial(void);
|
||||
|
||||
bool begin(String localName = String(), bool isMaster = false, bool disableBLE = false);
|
||||
bool begin(unsigned long baud) { //compatibility
|
||||
return begin();
|
||||
}
|
||||
int available(void);
|
||||
int peek(void);
|
||||
bool hasClient(void);
|
||||
int read(void);
|
||||
size_t write(uint8_t c);
|
||||
size_t write(const uint8_t *buffer, size_t size);
|
||||
void flush();
|
||||
void end(void);
|
||||
void memrelease();
|
||||
void setTimeout(int timeoutMS);
|
||||
void onData(BluetoothSerialDataCb cb);
|
||||
esp_err_t register_callback(esp_spp_cb_t callback);
|
||||
|
||||
void onConfirmRequest(ConfirmRequestCb cb);
|
||||
void onKeyRequest(KeyRequestCb cb);
|
||||
void respondPasskey(uint32_t passkey);
|
||||
void onAuthComplete(AuthCompleteCb cb);
|
||||
void confirmReply(boolean confirm);
|
||||
|
||||
void enableSSP();
|
||||
void enableSSP(bool inputCapability, bool outputCapability);
|
||||
void disableSSP();
|
||||
bool setPin(const char *pin, uint8_t pin_code_len);
|
||||
bool connect(String remoteName);
|
||||
bool connect(
|
||||
uint8_t remoteAddress[], int channel = 0, esp_spp_sec_t sec_mask = (ESP_SPP_SEC_ENCRYPT | ESP_SPP_SEC_AUTHENTICATE),
|
||||
esp_spp_role_t role = ESP_SPP_ROLE_MASTER
|
||||
);
|
||||
bool connect(
|
||||
const BTAddress &remoteAddress, int channel = 0, esp_spp_sec_t sec_mask = (ESP_SPP_SEC_ENCRYPT | ESP_SPP_SEC_AUTHENTICATE),
|
||||
esp_spp_role_t role = ESP_SPP_ROLE_MASTER
|
||||
) {
|
||||
return connect(*remoteAddress.getNative(), channel, sec_mask);
|
||||
};
|
||||
bool connect();
|
||||
bool connected(int timeout = 0);
|
||||
bool isClosed();
|
||||
bool isReady(bool checkMaster = false, int timeout = 0);
|
||||
bool disconnect();
|
||||
bool unpairDevice(uint8_t remoteAddress[]);
|
||||
|
||||
BTScanResults *discover(int timeout = 0x30 * 1280);
|
||||
bool discoverAsync(BTAdvertisedDeviceCb cb, int timeout = 0x30 * 1280);
|
||||
void discoverAsyncStop();
|
||||
void discoverClear();
|
||||
BTScanResults *getScanResults();
|
||||
|
||||
std::map<int, std::string> getChannels(const BTAddress &remoteAddress);
|
||||
|
||||
const int INQ_TIME = 1280; // Inquire Time unit 1280 ms
|
||||
const int MIN_INQ_TIME = (ESP_BT_GAP_MIN_INQ_LEN * INQ_TIME);
|
||||
const int MAX_INQ_TIME = (ESP_BT_GAP_MAX_INQ_LEN * INQ_TIME);
|
||||
|
||||
operator bool() const;
|
||||
void getBtAddress(uint8_t *mac);
|
||||
BTAddress getBtAddressObject();
|
||||
String getBtAddressString();
|
||||
//void dropCache(); // To be replaced
|
||||
void requestRemoteName(uint8_t *remoteAddress);
|
||||
bool readRemoteName(char rmt_name[ESP_BT_GAP_MAX_BDNAME_LEN + 1]);
|
||||
void invalidateRemoteName();
|
||||
int getNumberOfBondedDevices();
|
||||
int getBondedDevices(uint dev_num, esp_bd_addr_t *dev_list);
|
||||
bool deleteBondedDevice(uint8_t *remoteAddress);
|
||||
void deleteAllBondedDevices();
|
||||
|
||||
private:
|
||||
String local_name;
|
||||
int timeoutTicks = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user