mirror of
https://github.com/0xFEEDC0DE64/arduino-esp32.git
synced 2025-07-03 05:46:32 +02:00
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
This commit is contained in:
@ -0,0 +1,114 @@
|
|||||||
|
/**
|
||||||
|
* 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);
|
memcpy(m_address, address, ESP_BD_ADDR_LEN);
|
||||||
} // BTAddress
|
} // BTAddress
|
||||||
|
|
||||||
|
BTAddress::BTAddress() {
|
||||||
|
bzero(m_address, ESP_BD_ADDR_LEN);
|
||||||
|
} // BTAddress
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create an address from a hex string
|
* @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;
|
return memcmp(otherAddress.getNative(), m_address, 6) == 0;
|
||||||
} // equals
|
} // 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.
|
* @brief Return the native representation of the address.
|
||||||
* @return The native representation of the address.
|
* @return The native representation of the address.
|
||||||
*/
|
*/
|
||||||
esp_bd_addr_t *BTAddress::getNative() {
|
esp_bd_addr_t *BTAddress::getNative() const {
|
||||||
return &m_address;
|
return const_cast<esp_bd_addr_t *>(&m_address);
|
||||||
} // getNative
|
} // getNative
|
||||||
|
|
||||||
|
|
||||||
@ -85,7 +95,7 @@ esp_bd_addr_t *BTAddress::getNative() {
|
|||||||
*
|
*
|
||||||
* @return The string representation of the address.
|
* @return The string representation of the address.
|
||||||
*/
|
*/
|
||||||
std::string BTAddress::toString() {
|
std::string BTAddress::toString() const {
|
||||||
auto size = 18;
|
auto size = 18;
|
||||||
char *res = (char*)malloc(size);
|
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]);
|
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 {
|
class BTAddress {
|
||||||
public:
|
public:
|
||||||
|
BTAddress();
|
||||||
BTAddress(esp_bd_addr_t address);
|
BTAddress(esp_bd_addr_t address);
|
||||||
BTAddress(std::string stringAddress);
|
BTAddress(std::string stringAddress);
|
||||||
bool equals(BTAddress otherAddress);
|
bool equals(BTAddress otherAddress);
|
||||||
esp_bd_addr_t* getNative();
|
operator bool () const;
|
||||||
std::string toString();
|
|
||||||
|
esp_bd_addr_t* getNative() const;
|
||||||
|
std::string toString() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
esp_bd_addr_t m_address;
|
esp_bd_addr_t m_address;
|
||||||
|
@ -16,14 +16,14 @@ public:
|
|||||||
virtual ~BTAdvertisedDevice() = default;
|
virtual ~BTAdvertisedDevice() = default;
|
||||||
|
|
||||||
virtual BTAddress getAddress();
|
virtual BTAddress getAddress();
|
||||||
virtual uint32_t getCOD();
|
virtual uint32_t getCOD() const;
|
||||||
virtual std::string getName();
|
virtual std::string getName() const;
|
||||||
virtual int8_t getRSSI();
|
virtual int8_t getRSSI() const;
|
||||||
|
|
||||||
|
|
||||||
virtual bool haveCOD();
|
virtual bool haveCOD() const;
|
||||||
virtual bool haveName();
|
virtual bool haveName() const;
|
||||||
virtual bool haveRSSI();
|
virtual bool haveRSSI() const;
|
||||||
|
|
||||||
virtual std::string toString();
|
virtual std::string toString();
|
||||||
};
|
};
|
||||||
@ -35,14 +35,14 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
BTAddress getAddress();
|
BTAddress getAddress();
|
||||||
uint32_t getCOD();
|
uint32_t getCOD() const;
|
||||||
std::string getName();
|
std::string getName() const;
|
||||||
int8_t getRSSI();
|
int8_t getRSSI() const;
|
||||||
|
|
||||||
|
|
||||||
bool haveCOD();
|
bool haveCOD() const;
|
||||||
bool haveName();
|
bool haveName() const;
|
||||||
bool haveRSSI();
|
bool haveRSSI() const;
|
||||||
|
|
||||||
std::string toString();
|
std::string toString();
|
||||||
|
|
||||||
|
@ -25,14 +25,14 @@ BTAdvertisedDeviceSet::BTAdvertisedDeviceSet() {
|
|||||||
} // BTAdvertisedDeviceSet
|
} // BTAdvertisedDeviceSet
|
||||||
|
|
||||||
BTAddress BTAdvertisedDeviceSet::getAddress() { return m_address; }
|
BTAddress BTAdvertisedDeviceSet::getAddress() { return m_address; }
|
||||||
uint32_t BTAdvertisedDeviceSet::getCOD() { return m_cod; }
|
uint32_t BTAdvertisedDeviceSet::getCOD() const { return m_cod; }
|
||||||
std::string BTAdvertisedDeviceSet::getName() { return m_name; }
|
std::string BTAdvertisedDeviceSet::getName() const { return m_name; }
|
||||||
int8_t BTAdvertisedDeviceSet::getRSSI() { return m_rssi; }
|
int8_t BTAdvertisedDeviceSet::getRSSI() const { return m_rssi; }
|
||||||
|
|
||||||
|
|
||||||
bool BTAdvertisedDeviceSet::haveCOD() { return m_haveCOD; }
|
bool BTAdvertisedDeviceSet::haveCOD() const { return m_haveCOD; }
|
||||||
bool BTAdvertisedDeviceSet::haveName() { return m_haveName; }
|
bool BTAdvertisedDeviceSet::haveName() const { return m_haveName; }
|
||||||
bool BTAdvertisedDeviceSet::haveRSSI() { return m_haveRSSI; }
|
bool BTAdvertisedDeviceSet::haveRSSI() const { return m_haveRSSI; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a string representation of this device.
|
* @brief Create a string representation of this device.
|
||||||
|
@ -72,18 +72,30 @@ static esp_bt_pin_code_t _pin_code;
|
|||||||
static int _pin_len;
|
static int _pin_len;
|
||||||
static bool _isPinSet;
|
static bool _isPinSet;
|
||||||
static bool _enableSSP;
|
static bool _enableSSP;
|
||||||
|
static esp_spp_sec_t _sec_mask;
|
||||||
|
static esp_spp_role_t _role;
|
||||||
|
// start connect on ESP_SPP_DISCOVERY_COMP_EVT or save entry for getChannels
|
||||||
|
static bool _doConnect;
|
||||||
|
static std::map <int, std::string> sdpRecords;
|
||||||
|
|
||||||
static BTScanResultsSet scanResults;
|
static BTScanResultsSet scanResults;
|
||||||
static BTAdvertisedDeviceCb advertisedDeviceCb = nullptr;
|
static BTAdvertisedDeviceCb advertisedDeviceCb = nullptr;
|
||||||
|
|
||||||
|
// _spp_event_group
|
||||||
#define SPP_RUNNING 0x01
|
#define SPP_RUNNING 0x01
|
||||||
#define SPP_CONNECTED 0x02
|
#define SPP_CONNECTED 0x02
|
||||||
#define SPP_CONGESTED 0x04
|
#define SPP_CONGESTED 0x04
|
||||||
|
// true until OPEN successful, changes to false on CLOSE
|
||||||
#define SPP_DISCONNECTED 0x08
|
#define SPP_DISCONNECTED 0x08
|
||||||
|
// true until connect(), changes to true on CLOSE
|
||||||
|
#define SPP_CLOSED 0x10
|
||||||
|
|
||||||
|
// _bt_event_group
|
||||||
#define BT_DISCOVERY_RUNNING 0x01
|
#define BT_DISCOVERY_RUNNING 0x01
|
||||||
#define BT_DISCOVERY_COMPLETED 0x02
|
#define BT_DISCOVERY_COMPLETED 0x02
|
||||||
|
|
||||||
|
#define BT_SDP_RUNNING 0x04
|
||||||
|
#define BT_SDP_COMPLETED 0x08
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t len;
|
size_t len;
|
||||||
@ -98,7 +110,7 @@ static char *bda2str(esp_bd_addr_t bda, char *str, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *p = bda;
|
uint8_t *p = bda;
|
||||||
sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
|
snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
p[0], p[1], p[2], p[3], p[4], p[5]);
|
p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
@ -280,13 +292,15 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
|||||||
|
|
||||||
case ESP_SPP_CLOSE_EVT://Client connection closed
|
case ESP_SPP_CLOSE_EVT://Client connection closed
|
||||||
if ((param->close.async == false && param->close.status == ESP_SPP_SUCCESS) || param->close.async) {
|
if ((param->close.async == false && param->close.status == ESP_SPP_SUCCESS) || param->close.async) {
|
||||||
log_i("ESP_SPP_CLOSE_EVT: %u", secondConnectionAttempt);
|
log_i("ESP_SPP_CLOSE_EVT status:%d handle:%d close_by_remote:%d attempt %u", param->close.status,
|
||||||
|
param->close.handle, param->close.async, secondConnectionAttempt);
|
||||||
if(secondConnectionAttempt) {
|
if(secondConnectionAttempt) {
|
||||||
secondConnectionAttempt = false;
|
secondConnectionAttempt = false;
|
||||||
} else {
|
} else {
|
||||||
_spp_client = 0;
|
_spp_client = 0;
|
||||||
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED);
|
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED);
|
||||||
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
|
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
|
||||||
|
xEventGroupSetBits(_spp_event_group, SPP_CLOSED);
|
||||||
}
|
}
|
||||||
xEventGroupClearBits(_spp_event_group, SPP_CONNECTED);
|
xEventGroupClearBits(_spp_event_group, SPP_CONNECTED);
|
||||||
} else {
|
} else {
|
||||||
@ -333,13 +347,37 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ESP_SPP_DISCOVERY_COMP_EVT://discovery complete
|
case ESP_SPP_DISCOVERY_COMP_EVT://discovery complete
|
||||||
log_i("ESP_SPP_DISCOVERY_COMP_EVT");
|
log_i("ESP_SPP_DISCOVERY_COMP_EVT num=%d", param->disc_comp.scn_num);
|
||||||
if (param->disc_comp.status == ESP_SPP_SUCCESS) {
|
if (param->disc_comp.status == ESP_SPP_SUCCESS) {
|
||||||
log_i("ESP_SPP_DISCOVERY_COMP_EVT: spp connect to remote");
|
for(int i=0; i < param->disc_comp.scn_num; i++) {
|
||||||
esp_spp_connect(ESP_SPP_SEC_AUTHENTICATE, ESP_SPP_ROLE_MASTER, param->disc_comp.scn[0], _peer_bd_addr);
|
log_d("ESP_SPP_DISCOVERY_COMP_EVT: spp [%d] channel: %d service name:%s", i, param->disc_comp.scn[i], param->disc_comp.service_name[0]);
|
||||||
|
}
|
||||||
|
if(_doConnect) {
|
||||||
|
if(param->disc_comp.scn_num > 0) {
|
||||||
|
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)
|
||||||
|
char bda_str[18];
|
||||||
|
log_i("ESP_SPP_DISCOVERY_COMP_EVT: spp connect to remote %s channel %d",
|
||||||
|
bda2str(_peer_bd_addr, bda_str, sizeof(bda_str)),
|
||||||
|
param->disc_comp.scn[0]);
|
||||||
|
#endif
|
||||||
|
xEventGroupClearBits(_spp_event_group, SPP_CLOSED);
|
||||||
|
if(esp_spp_connect(_sec_mask, _role, param->disc_comp.scn[0], _peer_bd_addr) != ESP_OK) {
|
||||||
|
log_e("ESP_SPP_DISCOVERY_COMP_EVT connect failed");
|
||||||
|
xEventGroupSetBits(_spp_event_group, SPP_CLOSED);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log_e("ESP_SPP_DISCOVERY_COMP_EVT remote doesn't offer an SPP channel");
|
||||||
|
xEventGroupSetBits(_spp_event_group, SPP_CLOSED);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(int i=0; i < param->disc_comp.scn_num; i++) {
|
||||||
|
sdpRecords[param->disc_comp.scn[i]] = param->disc_comp.service_name[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log_e("ESP_SPP_DISCOVERY_COMP_EVT failed!, status:%d", param->disc_comp.status);
|
log_e("ESP_SPP_DISCOVERY_COMP_EVT failed!, status:%d", param->disc_comp.status);
|
||||||
}
|
}
|
||||||
|
xEventGroupSetBits(_bt_event_group, BT_SDP_COMPLETED);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESP_SPP_OPEN_EVT://Client connection open
|
case ESP_SPP_OPEN_EVT://Client connection open
|
||||||
@ -360,10 +398,15 @@ static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ESP_SPP_CL_INIT_EVT://client initiated a connection
|
case ESP_SPP_CL_INIT_EVT://client initiated a connection
|
||||||
log_i("ESP_SPP_CL_INIT_EVT");
|
if (param->cl_init.status == ESP_SPP_SUCCESS) {
|
||||||
|
log_i("ESP_SPP_CL_INIT_EVT handle:%d sec_id:%d", param->cl_init.handle, param->cl_init.sec_id);
|
||||||
|
} else {
|
||||||
|
log_i("ESP_SPP_CL_INIT_EVT status:%d", param->cl_init.status);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
log_i("ESP_SPP_* event unhandled %d", event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(custom_spp_callback)(*custom_spp_callback)(event, param);
|
if(custom_spp_callback)(*custom_spp_callback)(event, param);
|
||||||
@ -377,7 +420,7 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
|
|||||||
{
|
{
|
||||||
switch(event){
|
switch(event){
|
||||||
case ESP_BT_GAP_DISC_RES_EVT: {
|
case ESP_BT_GAP_DISC_RES_EVT: {
|
||||||
log_i("ESP_BT_GAP_DISC_RES_EVT");
|
log_i("ESP_BT_GAP_DISC_RES_EVT properties=%d", param->disc_res.num_prop);
|
||||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)
|
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)
|
||||||
char bda_str[18];
|
char bda_str[18];
|
||||||
log_i("Scanned device: %s", bda2str(param->disc_res.bda, bda_str, 18));
|
log_i("Scanned device: %s", bda2str(param->disc_res.bda, bda_str, 18));
|
||||||
@ -417,28 +460,29 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ESP_BT_GAP_DEV_PROP_COD:
|
case ESP_BT_GAP_DEV_PROP_COD:
|
||||||
log_d("ESP_BT_GAP_DEV_PROP_COD");
|
|
||||||
if (param->disc_res.prop[i].len <= sizeof(int)) {
|
if (param->disc_res.prop[i].len <= sizeof(int)) {
|
||||||
uint32_t cod = 0;
|
uint32_t cod = 0;
|
||||||
memcpy(&cod, param->disc_res.prop[i].val, param->disc_res.prop[i].len);
|
memcpy(&cod, param->disc_res.prop[i].val, param->disc_res.prop[i].len);
|
||||||
advertisedDevice.setCOD(cod);
|
advertisedDevice.setCOD(cod);
|
||||||
|
log_d("ESP_BT_GAP_DEV_PROP_COD 0x%x", cod);
|
||||||
} else {
|
} else {
|
||||||
log_d("Value size larger than integer");
|
log_d("ESP_BT_GAP_DEV_PROP_COD invalid COD: Value size larger than integer");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESP_BT_GAP_DEV_PROP_RSSI:
|
case ESP_BT_GAP_DEV_PROP_RSSI:
|
||||||
log_d("ESP_BT_GAP_DEV_PROP_RSSI");
|
|
||||||
if (param->disc_res.prop[i].len <= sizeof(int)) {
|
if (param->disc_res.prop[i].len <= sizeof(int)) {
|
||||||
uint8_t rssi = 0;
|
uint8_t rssi = 0;
|
||||||
memcpy(&rssi, param->disc_res.prop[i].val, param->disc_res.prop[i].len);
|
memcpy(&rssi, param->disc_res.prop[i].val, param->disc_res.prop[i].len);
|
||||||
|
log_d("ESP_BT_GAP_DEV_PROP_RSSI %d", rssi);
|
||||||
advertisedDevice.setRSSI(rssi);
|
advertisedDevice.setRSSI(rssi);
|
||||||
} else {
|
} else {
|
||||||
log_d("Value size larger than integer");
|
log_d("ESP_BT_GAP_DEV_PROP_RSSI invalid RSSI: Value size larger than integer");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
log_i("ESP_BT_GAP_DISC_RES_EVT unknown property [%d]:type:%d", i, param->disc_res.prop[i].type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (_isRemoteAddressSet)
|
if (_isRemoteAddressSet)
|
||||||
@ -455,11 +499,12 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ESP_BT_GAP_DISC_STATE_CHANGED_EVT:
|
case ESP_BT_GAP_DISC_STATE_CHANGED_EVT:
|
||||||
log_i("ESP_BT_GAP_DISC_STATE_CHANGED_EVT");
|
|
||||||
if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED) {
|
if (param->disc_st_chg.state == ESP_BT_GAP_DISCOVERY_STOPPED) {
|
||||||
|
log_i("ESP_BT_GAP_DISC_STATE_CHANGED_EVT stopped");
|
||||||
xEventGroupClearBits(_bt_event_group, BT_DISCOVERY_RUNNING);
|
xEventGroupClearBits(_bt_event_group, BT_DISCOVERY_RUNNING);
|
||||||
xEventGroupSetBits(_bt_event_group, BT_DISCOVERY_COMPLETED);
|
xEventGroupSetBits(_bt_event_group, BT_DISCOVERY_COMPLETED);
|
||||||
} else { // ESP_BT_GAP_DISCOVERY_STARTED
|
} else { // ESP_BT_GAP_DISCOVERY_STARTED
|
||||||
|
log_i("ESP_BT_GAP_DISC_STATE_CHANGED_EVT started");
|
||||||
xEventGroupClearBits(_bt_event_group, BT_DISCOVERY_COMPLETED);
|
xEventGroupClearBits(_bt_event_group, BT_DISCOVERY_COMPLETED);
|
||||||
xEventGroupSetBits(_bt_event_group, BT_DISCOVERY_RUNNING);
|
xEventGroupSetBits(_bt_event_group, BT_DISCOVERY_RUNNING);
|
||||||
}
|
}
|
||||||
@ -522,7 +567,24 @@ static void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *pa
|
|||||||
log_i("ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!");
|
log_i("ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ESP_BT_GAP_CONFIG_EIR_DATA_EVT:
|
||||||
|
log_i("ESP_BT_GAP_CONFIG_EIR_DATA_EVT: stat:%d num:%d", param->config_eir_data.stat, param->config_eir_data.eir_type_num);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESP_BT_GAP_READ_REMOTE_NAME_EVT:
|
||||||
|
if (param->read_rmt_name.stat == ESP_BT_STATUS_SUCCESS ) {
|
||||||
|
log_i("ESP_BT_GAP_READ_REMOTE_NAME_EVT: %s", param->read_rmt_name.rmt_name);
|
||||||
|
} else {
|
||||||
|
log_i("ESP_BT_GAP_READ_REMOTE_NAME_EVT: no success stat:%d", param->read_rmt_name.stat);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ESP_BT_GAP_MODE_CHG_EVT:
|
||||||
|
log_i("ESP_BT_GAP_MODE_CHG_EVT: mode: %d", param->mode_chg.mode);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
log_i("ESP-BT_GAP_* unknown message: %d", event);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -546,6 +608,7 @@ static bool _init_bt(const char *deviceName)
|
|||||||
xEventGroupClearBits(_spp_event_group, 0xFFFFFF);
|
xEventGroupClearBits(_spp_event_group, 0xFFFFFF);
|
||||||
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
|
xEventGroupSetBits(_spp_event_group, SPP_CONGESTED);
|
||||||
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED);
|
xEventGroupSetBits(_spp_event_group, SPP_DISCONNECTED);
|
||||||
|
xEventGroupSetBits(_spp_event_group, SPP_CLOSED);
|
||||||
}
|
}
|
||||||
if (_spp_rx_queue == NULL){
|
if (_spp_rx_queue == NULL){
|
||||||
_spp_rx_queue = xQueueCreate(RX_QUEUE_SIZE, sizeof(uint8_t)); //initialize the queue
|
_spp_rx_queue = xQueueCreate(RX_QUEUE_SIZE, sizeof(uint8_t)); //initialize the queue
|
||||||
@ -623,6 +686,7 @@ static bool _init_bt(const char *deviceName)
|
|||||||
esp_bt_dev_set_device_name(deviceName);
|
esp_bt_dev_set_device_name(deviceName);
|
||||||
|
|
||||||
if (_isPinSet) {
|
if (_isPinSet) {
|
||||||
|
log_i("pin set");
|
||||||
btSetPin();
|
btSetPin();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,7 +754,16 @@ static bool _stop_bt()
|
|||||||
|
|
||||||
static bool waitForConnect(int timeout) {
|
static bool waitForConnect(int timeout) {
|
||||||
TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS;
|
TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS;
|
||||||
return (xEventGroupWaitBits(_spp_event_group, SPP_CONNECTED, pdFALSE, pdTRUE, xTicksToWait) & SPP_CONNECTED) != 0;
|
// wait for connected or closed
|
||||||
|
EventBits_t rc = xEventGroupWaitBits(_spp_event_group, SPP_CONNECTED | SPP_CLOSED, pdFALSE, pdFALSE, xTicksToWait);
|
||||||
|
if((rc & SPP_CONNECTED) != 0)
|
||||||
|
return true;
|
||||||
|
else if((rc & SPP_CLOSED) != 0) {
|
||||||
|
log_d("connection closed!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
log_d("timeout");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool waitForDiscovered(int timeout) {
|
static bool waitForDiscovered(int timeout) {
|
||||||
@ -698,6 +771,11 @@ static bool waitForDiscovered(int timeout) {
|
|||||||
return (xEventGroupWaitBits(_spp_event_group, BT_DISCOVERY_COMPLETED, pdFALSE, pdTRUE, xTicksToWait) & BT_DISCOVERY_COMPLETED) != 0;
|
return (xEventGroupWaitBits(_spp_event_group, BT_DISCOVERY_COMPLETED, pdFALSE, pdTRUE, xTicksToWait) & BT_DISCOVERY_COMPLETED) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool waitForSDPRecord(int timeout) {
|
||||||
|
TickType_t xTicksToWait = timeout / portTICK_PERIOD_MS;
|
||||||
|
return (xEventGroupWaitBits(_bt_event_group, BT_SDP_COMPLETED, pdFALSE, pdTRUE, xTicksToWait) & BT_SDP_COMPLETED) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Serial Bluetooth Arduino
|
* Serial Bluetooth Arduino
|
||||||
*
|
*
|
||||||
@ -713,6 +791,9 @@ BluetoothSerial::~BluetoothSerial(void)
|
|||||||
_stop_bt();
|
_stop_bt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Param isMaster set to true if you want to connect to an other device
|
||||||
|
*/
|
||||||
bool BluetoothSerial::begin(String localName, bool isMaster)
|
bool BluetoothSerial::begin(String localName, bool isMaster)
|
||||||
{
|
{
|
||||||
_isMaster = isMaster;
|
_isMaster = isMaster;
|
||||||
@ -733,7 +814,7 @@ int BluetoothSerial::available(void)
|
|||||||
int BluetoothSerial::peek(void)
|
int BluetoothSerial::peek(void)
|
||||||
{
|
{
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
if (_spp_rx_queue && xQueuePeek(_spp_rx_queue, &c, 0)){
|
if (_spp_rx_queue && xQueuePeek(_spp_rx_queue, &c, this->timeoutTicks)){
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@ -744,16 +825,24 @@ bool BluetoothSerial::hasClient(void)
|
|||||||
return _spp_client > 0;
|
return _spp_client > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BluetoothSerial::read(void)
|
int BluetoothSerial::read()
|
||||||
{
|
{
|
||||||
|
|
||||||
uint8_t c = 0;
|
uint8_t c = 0;
|
||||||
if (_spp_rx_queue && xQueueReceive(_spp_rx_queue, &c, 0)){
|
if (_spp_rx_queue && xQueueReceive(_spp_rx_queue, &c, this->timeoutTicks)){
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set timeout for read / peek
|
||||||
|
*/
|
||||||
|
void BluetoothSerial::setTimeout(int timeoutMS)
|
||||||
|
{
|
||||||
|
this->timeoutTicks=timeoutMS / portTICK_PERIOD_MS;
|
||||||
|
}
|
||||||
|
|
||||||
size_t BluetoothSerial::write(uint8_t c)
|
size_t BluetoothSerial::write(uint8_t c)
|
||||||
{
|
{
|
||||||
return write(&c, 1);
|
return write(&c, 1);
|
||||||
@ -812,6 +901,7 @@ void BluetoothSerial::enableSSP() {
|
|||||||
* Use fixed pin code
|
* Use fixed pin code
|
||||||
*/
|
*/
|
||||||
bool BluetoothSerial::setPin(const char *pin) {
|
bool BluetoothSerial::setPin(const char *pin) {
|
||||||
|
log_i("pin: %s", pin);
|
||||||
bool isEmpty = !(pin && *pin);
|
bool isEmpty = !(pin && *pin);
|
||||||
if (isEmpty && !_isPinSet) {
|
if (isEmpty && !_isPinSet) {
|
||||||
return true; // nothing to do
|
return true; // nothing to do
|
||||||
@ -837,7 +927,10 @@ bool BluetoothSerial::connect(String remoteName)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
disconnect();
|
disconnect();
|
||||||
|
_doConnect = true;
|
||||||
_isRemoteAddressSet = false;
|
_isRemoteAddressSet = false;
|
||||||
|
_sec_mask = ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE;
|
||||||
|
_role = ESP_SPP_ROLE_MASTER;
|
||||||
strncpy(_remote_name, remoteName.c_str(), ESP_BT_GAP_MAX_BDNAME_LEN);
|
strncpy(_remote_name, remoteName.c_str(), ESP_BT_GAP_MAX_BDNAME_LEN);
|
||||||
_remote_name[ESP_BT_GAP_MAX_BDNAME_LEN] = 0;
|
_remote_name[ESP_BT_GAP_MAX_BDNAME_LEN] = 0;
|
||||||
log_i("master : remoteName");
|
log_i("master : remoteName");
|
||||||
@ -847,13 +940,23 @@ bool BluetoothSerial::connect(String remoteName)
|
|||||||
#else
|
#else
|
||||||
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
|
||||||
#endif
|
#endif
|
||||||
|
xEventGroupClearBits(_spp_event_group, SPP_CLOSED);
|
||||||
if (esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, INQ_LEN, INQ_NUM_RSPS) == ESP_OK) {
|
if (esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, INQ_LEN, INQ_NUM_RSPS) == ESP_OK) {
|
||||||
return waitForConnect(SCAN_TIMEOUT);
|
return waitForConnect(SCAN_TIMEOUT);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BluetoothSerial::connect(uint8_t remoteAddress[])
|
/**
|
||||||
|
* @Param channel: specify channel or 0 for auto-detect
|
||||||
|
* @Param sec_mask:
|
||||||
|
* ESP_SPP_SEC_ENCRYPT|ESP_SPP_SEC_AUTHENTICATE
|
||||||
|
* ESP_SPP_SEC_NONE
|
||||||
|
* @Param role:
|
||||||
|
* ESP_SPP_ROLE_MASTER master can handle up to 7 connections to slaves
|
||||||
|
* ESP_SPP_ROLE_SLAVE can only have one connection to a master
|
||||||
|
*/
|
||||||
|
bool BluetoothSerial::connect(uint8_t remoteAddress[], int channel, esp_spp_sec_t sec_mask, esp_spp_role_t role)
|
||||||
{
|
{
|
||||||
if (!isReady(true, READY_TIMEOUT)) return false;
|
if (!isReady(true, READY_TIMEOUT)) return false;
|
||||||
if (!remoteAddress) {
|
if (!remoteAddress) {
|
||||||
@ -861,10 +964,35 @@ bool BluetoothSerial::connect(uint8_t remoteAddress[])
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
disconnect();
|
disconnect();
|
||||||
|
_doConnect = true;
|
||||||
_remote_name[0] = 0;
|
_remote_name[0] = 0;
|
||||||
_isRemoteAddressSet = true;
|
_isRemoteAddressSet = true;
|
||||||
|
_sec_mask = sec_mask;
|
||||||
|
_role = role;
|
||||||
memcpy(_peer_bd_addr, remoteAddress, ESP_BD_ADDR_LEN);
|
memcpy(_peer_bd_addr, remoteAddress, ESP_BD_ADDR_LEN);
|
||||||
log_i("master : remoteAddress");
|
log_i("master : remoteAddress");
|
||||||
|
xEventGroupClearBits(_spp_event_group, SPP_CLOSED);
|
||||||
|
if (channel > 0) {
|
||||||
|
char bda_str[18];
|
||||||
|
log_i("spp connect to remote %s channel %d",
|
||||||
|
bda2str(_peer_bd_addr, bda_str, sizeof(bda_str)),
|
||||||
|
channel);
|
||||||
|
if(esp_spp_connect(sec_mask, role, channel, _peer_bd_addr) != ESP_OK ) {
|
||||||
|
log_e("spp connect failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool rc=waitForConnect(READY_TIMEOUT);
|
||||||
|
if(rc) {
|
||||||
|
log_i("connected");
|
||||||
|
} else {
|
||||||
|
if(this->isClosed()) {
|
||||||
|
log_e("connect failed");
|
||||||
|
} else {
|
||||||
|
log_e("connect timed out after %dms", READY_TIMEOUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
if (esp_spp_start_discovery(_peer_bd_addr) == ESP_OK) {
|
if (esp_spp_start_discovery(_peer_bd_addr) == ESP_OK) {
|
||||||
return waitForConnect(READY_TIMEOUT);
|
return waitForConnect(READY_TIMEOUT);
|
||||||
}
|
}
|
||||||
@ -874,6 +1002,7 @@ bool BluetoothSerial::connect(uint8_t remoteAddress[])
|
|||||||
bool BluetoothSerial::connect()
|
bool BluetoothSerial::connect()
|
||||||
{
|
{
|
||||||
if (!isReady(true, READY_TIMEOUT)) return false;
|
if (!isReady(true, READY_TIMEOUT)) return false;
|
||||||
|
_doConnect = true;
|
||||||
if (_isRemoteAddressSet){
|
if (_isRemoteAddressSet){
|
||||||
disconnect();
|
disconnect();
|
||||||
// use resolved or set address first
|
// use resolved or set address first
|
||||||
@ -924,6 +1053,13 @@ bool BluetoothSerial::connected(int timeout) {
|
|||||||
return waitForConnect(timeout);
|
return waitForConnect(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* true if a connection terminated or a connection attempt failed
|
||||||
|
*/
|
||||||
|
bool BluetoothSerial::isClosed() {
|
||||||
|
return xEventGroupGetBits(_spp_event_group) & SPP_CLOSED;
|
||||||
|
}
|
||||||
|
|
||||||
bool BluetoothSerial::isReady(bool checkMaster, int timeout) {
|
bool BluetoothSerial::isReady(bool checkMaster, int timeout) {
|
||||||
if (checkMaster && !_isMaster) {
|
if (checkMaster && !_isMaster) {
|
||||||
log_e("Master mode is not active. Call begin(localName, true) to enable Master mode");
|
log_e("Master mode is not active. Call begin(localName, true) to enable Master mode");
|
||||||
@ -956,6 +1092,7 @@ BTScanResults* BluetoothSerial::discover(int timeoutMs) {
|
|||||||
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
|
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
|
||||||
if (esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, timeout, 0) == ESP_OK) {
|
if (esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, timeout, 0) == ESP_OK) {
|
||||||
waitForDiscovered(timeoutMs);
|
waitForDiscovered(timeoutMs);
|
||||||
|
log_i("gap_cancel_discovery()");
|
||||||
esp_bt_gap_cancel_discovery();
|
esp_bt_gap_cancel_discovery();
|
||||||
}
|
}
|
||||||
return &scanResults;
|
return &scanResults;
|
||||||
@ -1008,4 +1145,31 @@ BluetoothSerial::operator bool() const
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SDP scan address
|
||||||
|
* esp_spp_start_discovery doesn't tell us the btAddress in the callback, so we have to wait until it's finished
|
||||||
|
*/
|
||||||
|
std::map<int, std::string> BluetoothSerial::getChannels(const BTAddress &remoteAddress) {
|
||||||
|
if(xEventGroupGetBits(_bt_event_group) & BT_SDP_RUNNING) {
|
||||||
|
log_e("getChannels failed - already running");
|
||||||
|
}
|
||||||
|
xEventGroupSetBits(_bt_event_group, BT_SDP_RUNNING);
|
||||||
|
xEventGroupClearBits(_bt_event_group, BT_SDP_COMPLETED);
|
||||||
|
_doConnect = false;
|
||||||
|
sdpRecords.clear();
|
||||||
|
log_d("esp_spp_start_discovery");
|
||||||
|
if (esp_spp_start_discovery(*remoteAddress.getNative()) != ESP_OK) {
|
||||||
|
log_e("esp_spp_start_discovery failed");
|
||||||
|
} else {
|
||||||
|
if(! waitForSDPRecord(READY_TIMEOUT)) {
|
||||||
|
log_e("getChannels failed timeout");
|
||||||
|
}
|
||||||
|
log_d("esp_spp_start_discovery wait for BT_SDP_COMPLETED done (%dms)", READY_TIMEOUT);
|
||||||
|
}
|
||||||
|
log_d("esp_spp_start_discovery done, found %d services", sdpRecords.size());
|
||||||
|
xEventGroupClearBits(_bt_event_group, BT_SDP_RUNNING);
|
||||||
|
return sdpRecords;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <esp_gap_bt_api.h>
|
#include <esp_gap_bt_api.h>
|
||||||
#include <esp_spp_api.h>
|
#include <esp_spp_api.h>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
#include "BTScan.h"
|
#include "BTScan.h"
|
||||||
|
|
||||||
typedef std::function<void(const uint8_t *buffer, size_t size)> BluetoothSerialDataCb;
|
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);
|
size_t write(const uint8_t *buffer, size_t size);
|
||||||
void flush();
|
void flush();
|
||||||
void end(void);
|
void end(void);
|
||||||
|
void setTimeout(int timeoutMS);
|
||||||
void onData(BluetoothSerialDataCb cb);
|
void onData(BluetoothSerialDataCb cb);
|
||||||
esp_err_t register_callback(esp_spp_cb_t * callback);
|
esp_err_t register_callback(esp_spp_cb_t * callback);
|
||||||
|
|
||||||
@ -60,9 +62,12 @@ class BluetoothSerial: public Stream
|
|||||||
void enableSSP();
|
void enableSSP();
|
||||||
bool setPin(const char *pin);
|
bool setPin(const char *pin);
|
||||||
bool connect(String remoteName);
|
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 connect();
|
||||||
bool connected(int timeout=0);
|
bool connected(int timeout=0);
|
||||||
|
bool isClosed();
|
||||||
bool isReady(bool checkMaster=false, int timeout=0);
|
bool isReady(bool checkMaster=false, int timeout=0);
|
||||||
bool disconnect();
|
bool disconnect();
|
||||||
bool unpairDevice(uint8_t remoteAddress[]);
|
bool unpairDevice(uint8_t remoteAddress[]);
|
||||||
@ -73,6 +78,8 @@ class BluetoothSerial: public Stream
|
|||||||
void discoverClear();
|
void discoverClear();
|
||||||
BTScanResults* getScanResults();
|
BTScanResults* getScanResults();
|
||||||
|
|
||||||
|
std::map<int, std::string> getChannels(const BTAddress &remoteAddress);
|
||||||
|
|
||||||
const int INQ_TIME = 1280; // Inquire Time unit 1280 ms
|
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 MIN_INQ_TIME = (ESP_BT_GAP_MIN_INQ_LEN * INQ_TIME);
|
||||||
const int MAX_INQ_TIME = (ESP_BT_GAP_MAX_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;
|
operator bool() const;
|
||||||
private:
|
private:
|
||||||
String local_name;
|
String local_name;
|
||||||
|
int timeoutTicks=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user