Merge bugfix branch into master

This commit is contained in:
h2zero 2020-04-13 19:13:51 -06:00
parent 359d2885e1
commit 3327a32341
13 changed files with 225 additions and 161 deletions

View file

@ -1,9 +1,9 @@
# *** UPDATE ***
Server now handles long reads and writes, still work to do on client.
This library is now ready with (mostly) all original BLE library compatiblity.
Check the examples and API_DIFFERENCES document for details of using this library.
3 simultaneous connections tested stable so far on both client and server.
NEW Client callback created - ```bool onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params)```
Called when the server wants to change the connection parameters, return true to accept them or false if not.
Check NimBLE_Client.ino example for a demonstration.
# esp-nimble-cpp

View file

@ -24,8 +24,8 @@
NimBLE2902::NimBLE2902(NimBLECharacteristic* pCharacterisitic)
: NimBLEDescriptor(NimBLEUUID((uint16_t) 0x2902),
BLE_GATT_CHR_PROP_READ |
BLE_GATT_CHR_PROP_WRITE,
BLE_GATT_CHR_F_READ |
BLE_GATT_CHR_F_WRITE,
2, pCharacterisitic)
{
uint8_t data[2] = { 0, 0 };

View file

@ -39,7 +39,7 @@ NimBLEAdvertising::NimBLEAdvertising() {
m_advData.name_len = strlen(name);
m_advData.name_is_complete = 1;
m_scanData.tx_pwr_lvl_is_present = 1;
m_scanData.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
m_scanData.tx_pwr_lvl = NimBLEDevice::getPower();
m_advData.flags = (BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP);
m_advData.appearance = 0;
m_advData.appearance_is_present = 0;
@ -228,11 +228,6 @@ void NimBLEAdvertising::start() {
&m_serviceUUIDs[i].getNative()->u16.value, sizeof(uint16_t));
m_advData.uuids16[m_advData.num_uuids16].u.type = BLE_UUID_TYPE_16;
/*
char buf[BLE_UUID_STR_LEN];
ble_uuid_to_str(&m_advData.uuids16[m_advData.num_uuids16].u, buf);
NIMBLE_LOGI(LOG_TAG, "Advertising UUID: %s", buf);
*/
m_advData.uuids16_is_complete = 1;
m_advData.num_uuids16++;
}
@ -254,11 +249,6 @@ void NimBLEAdvertising::start() {
&m_serviceUUIDs[i].getNative()->u32.value, sizeof(uint32_t));
m_advData.uuids32[m_advData.num_uuids32].u.type = BLE_UUID_TYPE_32;
/*
char buf[BLE_UUID_STR_LEN];
ble_uuid_to_str(&m_advData.uuids32[m_advData.num_uuids32].u, buf);
NIMBLE_LOGI(LOG_TAG, "Advertising UUID: %s", buf);
*/
m_advData.uuids32_is_complete = 1;
m_advData.num_uuids32++;
}
@ -279,11 +269,6 @@ void NimBLEAdvertising::start() {
&m_serviceUUIDs[i].getNative()->u128.value, 16);
m_advData.uuids128[m_advData.num_uuids128].u.type = BLE_UUID_TYPE_128;
/*
char buf[BLE_UUID_STR_LEN];
ble_uuid_to_str(&m_advData.uuids128[m_advData.num_uuids128].u, buf);
NIMBLE_LOGI(LOG_TAG, "Advertising UUID: %s", buf);
*/
m_advData.uuids128_is_complete = 1;
m_advData.num_uuids128++;
}
@ -331,7 +316,7 @@ void NimBLEAdvertising::start() {
// throw the tx power data into the advertisment
} else if (payloadLen < 29) {
m_advData.tx_pwr_lvl_is_present = 1;
m_advData.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
m_advData.tx_pwr_lvl = NimBLEDevice::getPower();
}
rc = ble_gap_adv_set_fields(&m_advData);
@ -394,11 +379,15 @@ void NimBLEAdvertising::stop() {
NIMBLE_LOGD(LOG_TAG, "<< stop");
} // stop
/*
void NimBLEAdvertising::onHostReset() {
// m_advSvcsSet = false;
}
/**
* Host reset seems to clear advertising data,
* we need clear the flag so it reloads it.
*/
void NimBLEAdvertising::onHostReset() {
m_advSvcsSet = false;
}
/**
* @brief Add data to the payload to be advertised.

View file

@ -90,7 +90,7 @@ public:
private:
friend class NimBLEDevice;
// void onHostReset();
void onHostReset();
ble_hs_adv_fields m_advData;
ble_hs_adv_fields m_scanData;
ble_gap_adv_params m_advParams;

View file

@ -102,7 +102,16 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint3
NimBLEDescriptor* NimBLECharacteristic::createDescriptor(NimBLEUUID uuid, uint32_t properties, uint16_t max_len) {
NimBLEDescriptor* pDescriptor = nullptr;
if(uuid.equals(NimBLEUUID((uint16_t)0x2902))) {
if(!(m_properties & BLE_GATT_CHR_F_NOTIFY) && !(m_properties & BLE_GATT_CHR_F_INDICATE)) {
assert(0 && "Cannot create 2902 descriptior without characteristic notification or indication property set");
}
// We cannot have more than one 2902 descriptor, if it's already been created just return a pointer to it.
pDescriptor = m_descriptorMap.getByUUID(uuid);
if(pDescriptor == nullptr) {
pDescriptor = new NimBLE2902(this);
} else {
return pDescriptor;
}
} else if (uuid.equals(NimBLEUUID((uint16_t)0x2904))) {
pDescriptor = new NimBLE2904(this);
@ -204,18 +213,34 @@ int NimBLECharacteristic::handleGapEvent(uint16_t conn_handle, uint16_t attr_han
if(ble_uuid_cmp(uuid, &pCharacteristic->getUUID().getNative()->u) == 0){
switch(ctxt->op) {
case BLE_GATT_ACCESS_OP_READ_CHR: {
//NIMBLE_LOGD(LOG_TAG, "read char pkthdr len:%d flags:%d", ctxt->om->om_pkthdr_len, ctxt->om->om_flags);
// If the packet header is only 8 bytes this is a follow up of a long read
// so we don't want to call the onRead() callback again.
if(ctxt->om->om_pkthdr_len > 8) {
pCharacteristic->m_pCallbacks->onRead(pCharacteristic);
}
rc = os_mbuf_append(ctxt->om, pCharacteristic->getData(), pCharacteristic->m_value.getLength());
return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
case BLE_GATT_ACCESS_OP_WRITE_CHR: {
//NIMBLE_LOGD(LOG_TAG, "write char pkthdr len:%d datalen:%d", ctxt->om->om_pkthdr_len, ctxt->om->om_len);
if (ctxt->om->om_len > BLE_ATT_ATTR_MAX_LEN) {
return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
}
pCharacteristic->setValue(ctxt->om->om_data, ctxt->om->om_len);
//pCharacteristic->setValue(ctxt->om->om_data, ctxt->om->om_len);
pCharacteristic->m_value.addPart(ctxt->om->om_data, ctxt->om->om_len);
os_mbuf *next;
next = SLIST_NEXT(ctxt->om, om_next);
while(next != NULL){
//NIMBLE_LOGD(LOG_TAG, "Found long write data, len:%d", next->om_len);
pCharacteristic->m_value.addPart(next->om_data, next->om_len);
next = SLIST_NEXT(next, om_next);
}
pCharacteristic->m_value.commit();
pCharacteristic->m_pCallbacks->onWrite(pCharacteristic);
return 0;
}
default:

View file

@ -53,7 +53,15 @@ NimBLEClient::NimBLEClient()
m_haveServices = false;
m_isConnected = false;
m_connectTimeout = 30000;
m_pConnParams = nullptr;
m_pConnParams.scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default)
m_pConnParams.scan_window = 16; // Scan window in 0.625ms units (NimBLE Default)
m_pConnParams.itvl_min = BLE_GAP_INITIAL_CONN_ITVL_MIN; // min_int = 0x10*1.25ms = 20ms
m_pConnParams.itvl_max = BLE_GAP_INITIAL_CONN_ITVL_MAX; // max_int = 0x20*1.25ms = 40ms
m_pConnParams.latency = BLE_GAP_INITIAL_CONN_LATENCY; // number of packets allowed to skip (extends max interval)
m_pConnParams.supervision_timeout = BLE_GAP_INITIAL_SUPERVISION_TIMEOUT; // timeout = 400*10ms = 4000ms
m_pConnParams.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN; // Minimum length of connection event in 0.625ms units
m_pConnParams.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN; // Maximum length of connection event in 0.625ms units
} // NimBLEClient
@ -70,9 +78,6 @@ NimBLEClient::~NimBLEClient() {
delete m_pClientCallbacks;
}
if(m_pConnParams != nullptr) {
free(m_pConnParams);
}
} // ~NimBLEClient
@ -134,24 +139,27 @@ bool NimBLEClient::connect(NimBLEAddress address, uint8_t type, bool refreshServ
ble_addr_t peerAddrt;
memcpy(&peerAddrt.val, address.getNative(),6);
peerAddrt.type = type;
NIMBLE_LOGE(LOG_TAG, "taking connect semaphore");
m_semaphoreOpenEvt.take("connect");
NIMBLE_LOGE(LOG_TAG, "taken");
/** Try to connect the the advertiser. Allow 30 seconds (30000 ms) for
* timeout (default value of m_connectTimeout).
* Loop on BLE_HS_EBUSY if the scan hasn't stopped yet.
*/
do{
rc = ble_gap_connect(BLE_OWN_ADDR_PUBLIC, &peerAddrt, m_connectTimeout, m_pConnParams,
rc = ble_gap_connect(BLE_OWN_ADDR_PUBLIC, &peerAddrt, m_connectTimeout, &m_pConnParams,
NimBLEClient::handleGapEvent, this);
if(rc == BLE_HS_EBUSY) {
vTaskDelay(1);
}
}while(rc == BLE_HS_EBUSY);
if (rc != 0) {
if (rc != 0 && rc != BLE_HS_EDONE) {
NIMBLE_LOGE(LOG_TAG, "Error: Failed to connect to device; addr_type=%d "
"addr=%s, rc=%d; %s",
type,
m_peerAddress.toString().c_str(),
rc, NimBLEUtils::returnCodeToString(BLE_HS_ATT_ERR(rc)));
rc, NimBLEUtils::returnCodeToString(rc));
m_semaphoreOpenEvt.give();
m_waitingToConnect = false;
@ -225,12 +233,16 @@ int NimBLEClient::disconnect(uint8_t reason) {
m_isConnected = false; // flag the disconnect now so no calls are performed after
rc = ble_gap_terminate(m_conn_id, reason);
if(rc != 0){
NIMBLE_LOGE(LOG_TAG, "ble_gap_terminate failed: rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
NIMBLE_LOGE(LOG_TAG, "ble_gap_terminate failed: rc=%d %s", rc,
NimBLEUtils::returnCodeToString(rc));
}
// Sometimes a disconnect event is not sent so we need to make sure
// the device can be found again.
NimBLEDevice::removeIgnored(m_peerAddress);
}
return rc;
NIMBLE_LOGD(LOG_TAG, "<< disconnect()");
return rc;
} // disconnect
@ -239,34 +251,23 @@ int NimBLEClient::disconnect(uint8_t reason) {
*/
void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterval,
uint16_t latency, uint16_t timeout,
uint16_t minConnTime, uint16_t maxConnTime)
uint16_t scanInterval, uint16_t scanWindow)/*,
uint16_t minConnTime, uint16_t maxConnTime)*/
{
if(m_pConnParams == nullptr) {
m_pConnParams = (ble_gap_conn_params*)calloc(1, sizeof(ble_gap_conn_params));
if(m_pConnParams == nullptr) {
NIMBLE_LOGE(LOG_TAG, "setConnectionParams: Error No Mem");
return;
}
}else if(0 == (minInterval | maxInterval | latency | timeout)) {
free(m_pConnParams);
m_pConnParams = nullptr;
return;
}
m_pConnParams->scan_itvl = 16; // Scan interval in 0.625ms units (NimBLE Default)
m_pConnParams->scan_window = 16; // Scan window in 0.625ms units (NimBLE Default)
m_pConnParams->itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms
m_pConnParams->itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms
m_pConnParams->latency = latency; // number of packets allowed to skip (extends max interval)
m_pConnParams->supervision_timeout = timeout; // timeout = 400*10ms = 4000ms
m_pConnParams->min_ce_len = minConnTime; // Minimum length of connection event in 0.625ms units
m_pConnParams->max_ce_len = maxConnTime; // Maximum length of connection event in 0.625ms units
int rc = NimBLEUtils::checkConnParams(m_pConnParams);
if(rc != 0) {
NIMBLE_LOGE(LOG_TAG,"setConnectionParams : %s", NimBLEUtils::returnCodeToString(rc));
free(m_pConnParams);
m_pConnParams = nullptr;
}
m_pConnParams.scan_itvl = scanInterval; // Scan interval in 0.625ms units
m_pConnParams.scan_window = scanWindow; // Scan window in 0.625ms units
m_pConnParams.itvl_min = minInterval; // min_int = 0x10*1.25ms = 20ms
m_pConnParams.itvl_max = maxInterval; // max_int = 0x20*1.25ms = 40ms
m_pConnParams.latency = latency; // number of packets allowed to skip (extends max interval)
m_pConnParams.supervision_timeout = timeout; // timeout = 400*10ms = 4000ms
// These are not used by NimBLE at this time - Must leave at defaults
//m_pConnParams->min_ce_len = minConnTime; // Minimum length of connection event in 0.625ms units
//m_pConnParams->max_ce_len = maxConnTime; // Maximum length of connection event in 0.625ms units
int rc = NimBLEUtils::checkConnParams(&m_pConnParams);
assert(rc == 0 && "Invalid Connection parameters");
}
@ -274,21 +275,17 @@ void NimBLEClient::setConnectionParams(uint16_t minInterval, uint16_t maxInterva
* Update connection parameters can be called only after connection has been established
*/
void NimBLEClient::updateConnParams(uint16_t minInterval, uint16_t maxInterval,
uint16_t latency, uint16_t timeout,
uint16_t minConnTime, uint16_t maxConnTime)
uint16_t latency, uint16_t timeout)
{
if(m_pConnParams == nullptr) {
setConnectionParams(minInterval, maxInterval, latency, timeout, minConnTime, maxConnTime);
}
ble_gap_upd_params params;
params.latency = latency;
params.itvl_max = maxInterval;
params.itvl_min = minInterval;
params.supervision_timeout = timeout;
params.min_ce_len = minConnTime;
params.max_ce_len = maxConnTime;
// These are not used by NimBLE at this time - Must leave at defaults
params.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN;
params.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN;
int rc = ble_gap_update_params(m_conn_id, &params);
if(rc != 0) {
@ -331,7 +328,7 @@ NimBLEAddress NimBLEClient::getPeerAddress() {
int NimBLEClient::getRssi() {
NIMBLE_LOGD(LOG_TAG, ">> getRssi()");
if (!isConnected()) {
NIMBLE_LOGD(LOG_TAG, "<< getRssi(): Not connected");
NIMBLE_LOGE(LOG_TAG, "<< getRssi(): Not connected");
return 0;
}
@ -466,13 +463,12 @@ int NimBLEClient::serviceDiscoveredCB(
// Found a service - add it to the map
NimBLERemoteService* pRemoteService = new NimBLERemoteService(peer, service);
peer->m_servicesMap.insert(std::pair<std::string, NimBLERemoteService*>(pRemoteService->getUUID().toString(), pRemoteService));
break;
}
case BLE_HS_EDONE:{
// All services discovered; start discovering characteristics.
NIMBLE_LOGD(LOG_TAG,"Giving search semaphore - completed");
//NIMBLE_LOGD(LOG_TAG,"Giving search semaphore - completed");
peer->m_semaphoreSearchCmplEvt.give(0);
rc = 0;
break;
@ -576,6 +572,8 @@ uint16_t NimBLEClient::getMTU() {
client->m_isConnected = false;
client->m_waitingToConnect=false;
// Remove the device from ignore list so we will scan it again
NimBLEDevice::removeIgnored(client->m_peerAddress);
NIMBLE_LOGI(LOG_TAG, "disconnect; reason=%d, %s", event->disconnect.reason,
NimBLEUtils::returnCodeToString(event->disconnect.reason));
@ -604,8 +602,6 @@ uint16_t NimBLEClient::getMTU() {
client->m_semaphoreSearchCmplEvt.give(1);
client->m_semeaphoreSecEvt.give(1);
// Remove the device from ignore list so we will scan it again
NimBLEDevice::removeIgnored(client->m_peerAddress);
client->m_pClientCallbacks->onDisconnect(client);
return 0;
@ -633,7 +629,6 @@ uint16_t NimBLEClient::getMTU() {
// print_conn_desc(&desc);
// MODLOG_DFLT(INFO, "\n");
//client->m_pClientCallbacks->onConnect(client);
// In the case of a multiconnecting device we ignore this device when
// scanning since we are already connected to it
@ -645,18 +640,14 @@ uint16_t NimBLEClient::getMTU() {
NimBLEUtils::returnCodeToString(rc));
// if error getting mtu indicate a connection error.
client->m_semaphoreOpenEvt.give(rc);
} /*else {
client->m_semaphoreOpenEvt.give(0);
}*/
}
} else {
// Connection attempt failed
NIMBLE_LOGE(LOG_TAG, "Error: Connection failed; status=%d %s",
event->connect.status,
NimBLEUtils::returnCodeToString(event->connect.status));
client->m_semaphoreOpenEvt.give(event->connect.status);
}
client->m_semaphoreOpenEvt.give(event->connect.status);
return 0;
} // BLE_GAP_EVENT_CONNECT
@ -702,22 +693,19 @@ uint16_t NimBLEClient::getMTU() {
event->conn_update_req.peer_params->itvl_max,
event->conn_update_req.peer_params->latency,
event->conn_update_req.peer_params->supervision_timeout);
rc = 0;
// if we set connection params and the peer is asking for new ones, reject them.
if(client->m_pConnParams != nullptr) {
if(event->conn_update_req.peer_params->itvl_min != client->m_pConnParams->itvl_min ||
event->conn_update_req.peer_params->itvl_max != client->m_pConnParams->itvl_max ||
event->conn_update_req.peer_params->latency != client->m_pConnParams->latency ||
event->conn_update_req.peer_params->supervision_timeout != client->m_pConnParams->supervision_timeout)
{
//event->conn_update_req.self_params->itvl_min = 6;//client->m_pConnParams->itvl_min;
rc = BLE_ERR_CONN_PARMS;
}
}
if(rc != 0) {
NIMBLE_LOGD(LOG_TAG, "Rejected peer params");
rc = client->m_pClientCallbacks->onConnParamsUpdateRequest(client,
event->conn_update_req.peer_params) ? 0 : BLE_ERR_CONN_PARMS;
if(!rc && event->type == BLE_GAP_EVENT_CONN_UPDATE_REQ ) {
event->conn_update_req.self_params->itvl_min = client->m_pConnParams.itvl_min;
event->conn_update_req.self_params->itvl_max = client->m_pConnParams.itvl_max;
event->conn_update_req.self_params->latency = client->m_pConnParams.latency;
event->conn_update_req.self_params->supervision_timeout = client->m_pConnParams.supervision_timeout;
}
NIMBLE_LOGD(LOG_TAG, "%s peer params", (rc == 0) ? "Accepted" : "Rejected");
return rc;
} // BLE_GAP_EVENT_CONN_UPDATE_REQ, BLE_GAP_EVENT_L2CAP_UPDATE_REQ
@ -876,6 +864,11 @@ void NimBLEClientCallbacks::onDisconnect(NimBLEClient *pClient) {
NIMBLE_LOGD("NimBLEClientCallbacks", "onDisconnect: default");
}
bool NimBLEClientCallbacks::onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params) {
NIMBLE_LOGD("NimBLEClientCallbacks", "onConnParamsUpdateRequest: default");
return true;
}
uint32_t NimBLEClientCallbacks::onPassKeyRequest(){
NIMBLE_LOGD("NimBLEClientCallbacks", "onPassKeyRequest: default: 123456");
return 123456;
@ -889,7 +882,7 @@ bool NimBLEClientCallbacks::onSecurityRequest(){
NIMBLE_LOGD("NimBLEClientCallbacks", "onSecurityRequest: default: true");
return true;
}
void NimBLEClientCallbacks::onAuthenticationComplete(ble_gap_conn_desc*){
void NimBLEClientCallbacks::onAuthenticationComplete(ble_gap_conn_desc* desc){
NIMBLE_LOGD("NimBLEClientCallbacks", "onAuthenticationComplete: default");
}
bool NimBLEClientCallbacks::onConfirmPIN(uint32_t pin){

View file

@ -52,12 +52,9 @@ public:
void setConnectTimeout(uint8_t timeout);
void setConnectionParams(uint16_t minInterval, uint16_t maxInterval,
uint16_t latency, uint16_t timeout,
uint16_t minConnTime=16, uint16_t maxConnTime=768);
uint16_t scanInterval=16, uint16_t scanWindow=16); // NimBLE default scan settings
void updateConnParams(uint16_t minInterval, uint16_t maxInterval,
uint16_t latency, uint16_t timeout,
uint16_t minConnTime=16, uint16_t maxConnTime=768);
uint16_t latency, uint16_t timeout);
private:
@ -79,10 +76,8 @@ private:
bool m_waitingToConnect =false;
bool m_deleteCallbacks = true;
int32_t m_connectTimeout;
ble_gap_conn_params* m_pConnParams;
//uint16_t m_mtu = 23;
NimBLEClientCallbacks* m_pClientCallbacks = nullptr;
FreeRTOS::Semaphore m_semaphoreOpenEvt = FreeRTOS::Semaphore("OpenEvt");
@ -91,6 +86,10 @@ private:
std::map<std::string, NimBLERemoteService*> m_servicesMap;
private:
friend class NimBLEClientCallbacks;
ble_gap_conn_params m_pConnParams;
}; // class NimBLEClient
@ -100,13 +99,14 @@ private:
class NimBLEClientCallbacks {
public:
virtual ~NimBLEClientCallbacks() {};
virtual void onConnect(NimBLEClient *pClient); // = 0;
virtual void onDisconnect(NimBLEClient *pClient); // = 0;
virtual uint32_t onPassKeyRequest(); //{return 0;}
virtual void onPassKeyNotify(uint32_t pass_key); //{}
virtual bool onSecurityRequest(); //{return false;}
virtual void onAuthenticationComplete(ble_gap_conn_desc*); //{};
virtual bool onConfirmPIN(uint32_t pin); //{return false;}
virtual void onConnect(NimBLEClient* pClient);
virtual void onDisconnect(NimBLEClient* pClient);
virtual bool onConnParamsUpdateRequest(NimBLEClient* pClient, const ble_gap_upd_params* params);
virtual uint32_t onPassKeyRequest();
virtual void onPassKeyNotify(uint32_t pass_key);
virtual bool onSecurityRequest();
virtual void onAuthenticationComplete(ble_gap_conn_desc* desc);
virtual bool onConfirmPIN(uint32_t pin);
};
#endif // CONFIG_BT_ENABLED

View file

@ -239,17 +239,41 @@ void NimBLEDevice::stopAdvertising() {
* * ESP_PWR_LVL_P9 = 7, !< Corresponding to +9dbm
* @param [in] powerLevel.
*/
/* STATIC */ void NimBLEDevice::setPower(esp_power_level_t powerLevel) {
NIMBLE_LOGD(LOG_TAG, ">> setPower: %d", powerLevel);
esp_err_t errRc = ::esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, powerLevel);
/* STATIC */ void NimBLEDevice::setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType) {
NIMBLE_LOGD(LOG_TAG, ">> setPower: %d (type: %d)", powerLevel, powerType);
esp_err_t errRc = esp_ble_tx_power_set(powerType, powerLevel);
if (errRc != ESP_OK) {
//NIMBLE_LOGE(LOG_TAG, "esp_ble_tx_power_set: rc=%d %s", errRc, GeneralUtils::errorToString(errRc));
NIMBLE_LOGE(LOG_TAG, "esp_ble_tx_power_set: rc=%d", errRc);
};
}
NIMBLE_LOGD(LOG_TAG, "<< setPower");
} // setPower
/* STATIC */ int NimBLEDevice::getPower(esp_ble_power_type_t powerType) {
switch(esp_ble_tx_power_get(powerType)) {
case ESP_PWR_LVL_N12:
return -12;
case ESP_PWR_LVL_N9:
return -9;
case ESP_PWR_LVL_N6:
return -6;
case ESP_PWR_LVL_N3:
return -6;
case ESP_PWR_LVL_N0:
return 0;
case ESP_PWR_LVL_P3:
return 3;
case ESP_PWR_LVL_P6:
return 6;
case ESP_PWR_LVL_P9:
return 9;
default:
return BLE_HS_ADV_TX_PWR_LVL_AUTO;
}
} // setPower
/**
* @brief Get our device address.
* @return A NimBLEAddress object of our public address if we have one,
@ -327,11 +351,11 @@ void NimBLEDevice::stopAdvertising() {
for(auto it = m_cList.cbegin(); it != m_cList.cend(); ++it) {
(*it)->onHostReset();
}
*/
if(m_bleAdvertising != nullptr) {
m_bleAdvertising->onHostReset();
}
*/
NIMBLE_LOGC(LOG_TAG, "Resetting state; reason=%d, %s", reason,
NimBLEUtils::returnCodeToString(reason));
} // onReset
@ -414,7 +438,7 @@ void NimBLEDevice::stopAdvertising() {
ble_hs_cfg.sync_cb = NimBLEDevice::onSync;
// Set initial security capabilities
ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_NO_IO;
ble_hs_cfg.sm_io_cap = BLE_HS_IO_NO_INPUT_OUTPUT;
ble_hs_cfg.sm_bonding = 0;
ble_hs_cfg.sm_mitm = 0;
ble_hs_cfg.sm_sc = 1;

View file

@ -59,7 +59,11 @@
#define BLEEddystoneTLM NimBLEEddystoneTLM
#define BLEEddystoneURL NimBLEEddystoneURL
#ifdef CONFIG_BT_NIMBLE_MAX_CONNECTIONS
#define NIMBLE_MAX_CONNECTIONS CONFIG_BT_NIMBLE_MAX_CONNECTIONS
#else
#define NIMBLE_MAX_CONNECTIONS CONFIG_NIMBLE_MAX_CONNECTIONS
#endif
/**
* @brief BLE functions.
@ -81,7 +85,8 @@ public:
static NimBLEClient* createClient();
static NimBLEServer* createServer();
static bool deleteClient(NimBLEClient* pClient);
static void setPower(esp_power_level_t powerLevel);
static void setPower(esp_power_level_t powerLevel, esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT);
static int getPower(esp_ble_power_type_t powerType=ESP_BLE_PWR_TYPE_DEFAULT);
static void setCustomGapHandler(gap_event_handler handler);
static void setSecurityAuth(bool bonding, bool mitm, bool sc);
static void setSecurityAuth(uint8_t auth_req);
@ -110,6 +115,7 @@ private:
friend class NimBLEClient;
friend class NimBLEScan;
friend class NimBLEAdvertising;
friend class NimBLECharacteristic;
static void onReset(int reason);
static void onSync(void);

View file

@ -18,6 +18,9 @@
// Note: because CONFIG_LOG_DEFAULT_LEVEL is set at ERROR in Arduino we must use MODLOG_DFLT(ERROR
// otherwise no messages will be printed above that level.
#ifdef ARDUINO_ARCH_ESP32
#ifndef CORE_DEBUG_LEVEL
#define CORE_DEBUG_LEVEL CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL
#endif
#if CORE_DEBUG_LEVEL >= 4
#define NIMBLE_LOGD( tag, format, ... ) MODLOG_DFLT(ERROR, "D %s: "#format"\n",tag,##__VA_ARGS__)

View file

@ -16,8 +16,6 @@
#if defined(CONFIG_BT_ENABLED)
#include "NimBLERemoteCharacteristic.h"
#include <esp_err.h>
#include "NimBLEUtils.h"
#include "NimBLELog.h"
@ -321,6 +319,7 @@ std::string NimBLERemoteCharacteristic::readValue() {
int rc = 0;
int retryCount = 1;
NimBLEClient* pClient = getRemoteService()->getClient();
// Check to see that we are connected.
@ -334,15 +333,18 @@ std::string NimBLERemoteCharacteristic::readValue() {
rc = ble_gattc_read(pClient->getConnId(), m_handle,
NimBLERemoteCharacteristic::onReadCB, this);
// long read experiment
/* rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0,
NimBLERemoteCharacteristic::onReadCB, this);
*/
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Error: Failed to read characteristic; rc=%d", rc);
//goto err;
m_semaphoreReadCharEvt.give();
return "";
}
rc = m_semaphoreReadCharEvt.wait("readValue");
switch(rc){
case 0:
break;
@ -377,8 +379,13 @@ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle,
if(characteristic->getRemoteService()->getClient()->getConnId() != conn_handle){
return 0;
}
NIMBLE_LOGI(LOG_TAG, "Read complete; status=%d conn_handle=%d", error->status, conn_handle);
// long read experiment
/* if(attr && (attr->om->om_len >= (ble_att_mtu(characteristic->getRemoteService()->getClient()->getConnId()) - 1))){
return 0;
}
*/
if(characteristic->m_rawData != nullptr) {
free(characteristic->m_rawData);
@ -386,16 +393,17 @@ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle,
if (error->status == 0) {
characteristic->m_value = std::string((char*) attr->om->om_data, attr->om->om_len);
characteristic->m_semaphoreReadCharEvt.give(0);
characteristic->m_rawData = (uint8_t*) calloc(attr->om->om_len, sizeof(uint8_t));
memcpy(characteristic->m_rawData, attr->om->om_data, attr->om->om_len);
characteristic->m_semaphoreReadCharEvt.give(0);
} else {
characteristic->m_rawData = nullptr;
characteristic->m_value = "";
characteristic->m_semaphoreReadCharEvt.give(error->status);
}
return 0;
// characteristic->m_semaphoreReadCharEvt.give(error->status);
return 0; //1
}
@ -515,6 +523,7 @@ bool NimBLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool r
NimBLEClient* pClient = getRemoteService()->getClient();
int rc = 0;
int retryCount = 1;
// uint16_t mtu;
// Check to see that we are connected.
if (!pClient->isConnected()) {
@ -522,18 +531,29 @@ bool NimBLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool r
return false;
}
if(!response) {
// mtu = ble_att_mtu(pClient->getConnId()) - 3;
if(/*!length > mtu &&*/ !response) {
rc = ble_gattc_write_no_rsp_flat(pClient->getConnId(), m_handle, data, length);
return (rc==0);
}
do {
m_semaphoreWriteCharEvt.take("writeValue");
// long write experiment
/* if(length > mtu) {
NIMBLE_LOGD(LOG_TAG,"long write");
os_mbuf *om = ble_hs_mbuf_from_flat(data, length);
rc = ble_gattc_write_long(pClient->getConnId(), m_handle, 0, om,
NimBLERemoteCharacteristic::onWriteCB,
this);
} else {
*/
rc = ble_gattc_write_flat(pClient->getConnId(), m_handle,
data, length,
NimBLERemoteCharacteristic::onWriteCB,
this);;
this);
// }
if (rc != 0) {
NIMBLE_LOGE(LOG_TAG, "Error: Failed to write characteristic; rc=%d", rc);
m_semaphoreWriteCharEvt.give();
@ -558,7 +578,7 @@ bool NimBLERemoteCharacteristic::writeValue(uint8_t* data, size_t length, bool r
} while(rc != 0 && retryCount--);
NIMBLE_LOGD(LOG_TAG, "<< writeValue, rc: %d",rc);
return (rc == 0); //true;
return (rc == 0);
} // writeValue
@ -587,7 +607,7 @@ int NimBLERemoteCharacteristic::onWriteCB(uint16_t conn_handle,
characteristic->m_semaphoreWriteCharEvt.give(error->status);
}
return error->status;
return 0;
}

View file

@ -231,6 +231,11 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
return false;
}
if(ble_gap_conn_active()) {
NIMBLE_LOGE(LOG_TAG, "Connection in progress - must wait.");
return false;
}
// If we are already scanning don't start again or we will get stuck on the semaphore.
if(!m_stopped || ble_gap_disc_active()) { // double check - can cause host reset.
NIMBLE_LOGE(LOG_TAG, "Scan already in progress");
@ -238,7 +243,6 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
}
m_stopped = false;
m_semaphoreScanEnd.take("start");
// Save the callback to be invoked when the scan completes.
@ -261,13 +265,15 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
}
int rc = 0;
do{
rc = ble_gap_disc(m_own_addr_type, duration, &m_scan_params,
NimBLEScan::handleGapEvent, this);
if(rc == BLE_HS_EBUSY) {
vTaskDelay(2);
}
} while(rc == BLE_HS_EBUSY);
if (rc != 0) {
if (rc != 0 && rc != BLE_HS_EDONE) {
NIMBLE_LOGE(LOG_TAG, "Error initiating GAP discovery procedure; rc=%d, %s",
rc, NimBLEUtils::returnCodeToString(rc));
m_stopped = true;
@ -275,8 +281,6 @@ bool NimBLEScan::start(uint32_t duration, void (*scanCompleteCB)(NimBLEScanResul
return false;
}
// m_stopped = false;
NIMBLE_LOGD(LOG_TAG, "<< start()");
return true;
} // start

View file

@ -137,7 +137,7 @@ void NimBLEServer::start() {
abort();
}
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || ARDUHAL_LOG_LEVEL_INFO > 3
#if CONFIG_LOG_DEFAULT_LEVEL > 3 || (ARDUINO_ARCH_ESP32 && CORE_DEBUG_LEVEL >= 4)
ble_gatts_show_local();
#endif