Unverified Commit b88a70a0 authored by Christian Ferbar's avatar Christian Ferbar Committed by GitHub

Allow BluetoothSerial::connect() with specified channel and more options (#6380)

* BTAddress const, add bool()

* BTAdvertisedDevice: const functions

* BluetoothSerial: add: getChannels, add isClosed, add read/peek timeout, add connect with channel#

* BluetoothSerial: add sec_mask, role in ::connect

* BluetoothSerial add discover and connect with channel number example

* DiscoverConnect: add SPP_ENABLED check

* DiscoverConnect: disable on esp32s3
parent f3bdfb31
/**
* Bluetooth Classic Example
* Scan for devices - asyncronously, 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 aduino 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 %d\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 workin 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);
}
......@@ -29,6 +29,9 @@ 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
......@@ -64,13 +67,20 @@ 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() {
return &m_address;
esp_bd_addr_t *BTAddress::getNative() const {
return const_cast<esp_bd_addr_t *>(&m_address);
} // getNative
......@@ -85,7 +95,7 @@ esp_bd_addr_t *BTAddress::getNative() {
*
* @return The string representation of the address.
*/
std::string BTAddress::toString() {
std::string BTAddress::toString() const {
auto size = 18;
char *res = (char*)malloc(size);
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]);
......
......@@ -22,11 +22,14 @@
*/
class BTAddress {
public:
BTAddress();
BTAddress(esp_bd_addr_t address);
BTAddress(std::string stringAddress);
bool equals(BTAddress otherAddress);
esp_bd_addr_t* getNative();
std::string toString();
operator bool () const;
esp_bd_addr_t* getNative() const;
std::string toString() const;
private:
esp_bd_addr_t m_address;
......
......@@ -16,14 +16,14 @@ public:
virtual ~BTAdvertisedDevice() = default;
virtual BTAddress getAddress();
virtual uint32_t getCOD();
virtual std::string getName();
virtual int8_t getRSSI();
virtual uint32_t getCOD() const;
virtual std::string getName() const;
virtual int8_t getRSSI() const;
virtual bool haveCOD();
virtual bool haveName();
virtual bool haveRSSI();
virtual bool haveCOD() const;
virtual bool haveName() const;
virtual bool haveRSSI() const;
virtual std::string toString();
};
......@@ -35,14 +35,14 @@ public:
BTAddress getAddress();
uint32_t getCOD();
std::string getName();
int8_t getRSSI();
uint32_t getCOD() const;
std::string getName() const;
int8_t getRSSI() const;
bool haveCOD();
bool haveName();
bool haveRSSI();
bool haveCOD() const;
bool haveName() const;
bool haveRSSI() const;
std::string toString();
......@@ -62,4 +62,4 @@ public:
int8_t m_rssi;
};
#endif
\ No newline at end of file
#endif
......@@ -25,14 +25,14 @@ BTAdvertisedDeviceSet::BTAdvertisedDeviceSet() {
} // BTAdvertisedDeviceSet
BTAddress BTAdvertisedDeviceSet::getAddress() { return m_address; }
uint32_t BTAdvertisedDeviceSet::getCOD() { return m_cod; }
std::string BTAdvertisedDeviceSet::getName() { return m_name; }
int8_t BTAdvertisedDeviceSet::getRSSI() { return m_rssi; }
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() { return m_haveCOD; }
bool BTAdvertisedDeviceSet::haveName() { return m_haveName; }
bool BTAdvertisedDeviceSet::haveRSSI() { return m_haveRSSI; }
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.
......
......@@ -24,6 +24,7 @@
#include <esp_gap_bt_api.h>
#include <esp_spp_api.h>
#include <functional>
#include <map>
#include "BTScan.h"
typedef std::function<void(const uint8_t *buffer, size_t size)> BluetoothSerialDataCb;
......@@ -50,6 +51,7 @@ class BluetoothSerial: public Stream
size_t write(const uint8_t *buffer, size_t size);
void flush();
void end(void);
void setTimeout(int timeoutMS);
void onData(BluetoothSerialDataCb cb);
esp_err_t register_callback(esp_spp_cb_t * callback);
......@@ -60,9 +62,12 @@ class BluetoothSerial: public Stream
void enableSSP();
bool setPin(const char *pin);
bool connect(String remoteName);
bool connect(uint8_t remoteAddress[]);
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[]);
......@@ -73,6 +78,8 @@ class BluetoothSerial: public Stream
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);
......@@ -80,7 +87,7 @@ class BluetoothSerial: public Stream
operator bool() const;
private:
String local_name;
int timeoutTicks=0;
};
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment