#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)
#include <esp_log.h>
#include <esp_err.h>
#include <map>
#include "BLEAdvertisedDevice.h"
#include "BLEScan.h"
#include "BLEUtils.h"
#include "GeneralUtils.h"
#ifdef ARDUINO_ARCH_ESP32
#include "esp32-hal-log.h"
#endif
static const char* LOG_TAG = "BLEScan";
BLEScan::BLEScan() {
m_scan_params.scan_type = BLE_SCAN_TYPE_PASSIVE;
m_scan_params.own_addr_type = BLE_ADDR_TYPE_PUBLIC;
m_scan_params.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL;
m_pAdvertisedDeviceCallbacks = nullptr;
m_stopped = true;
m_wantDuplicates = false;
setInterval(100);
setWindow(100);
}
void BLEScan::handleGAPEvent(
esp_gap_ble_cb_event_t event,
esp_ble_gap_cb_param_t* param) {
switch(event) {
case ESP_GAP_BLE_SCAN_RESULT_EVT: {
switch(param->scan_rst.search_evt) {
case ESP_GAP_SEARCH_INQ_CMPL_EVT: {
m_stopped = true;
m_semaphoreScanEnd.give();
break;
}
case ESP_GAP_SEARCH_INQ_RES_EVT: {
if (m_stopped) {
break;
}
BLEAddress advertisedAddress(param->scan_rst.bda);
bool found = false;
for (int i=0; i<m_scanResults.getCount(); i++) {
if (m_scanResults.getDevice(i).getAddress().equals(advertisedAddress)) {
found = true;
break;
}
}
if (found && !m_wantDuplicates) {
ESP_LOGD(LOG_TAG, "Ignoring %s, already seen it.", advertisedAddress.toString().c_str());
break;
}
BLEAdvertisedDevice advertisedDevice;
advertisedDevice.setAddress(advertisedAddress);
advertisedDevice.setRSSI(param->scan_rst.rssi);
advertisedDevice.setAdFlag(param->scan_rst.flag);
advertisedDevice.parseAdvertisement((uint8_t*)param->scan_rst.ble_adv);
advertisedDevice.setScan(this);
if (m_pAdvertisedDeviceCallbacks) {
m_pAdvertisedDeviceCallbacks->onResult(advertisedDevice);
}
if (!found) {
m_scanResults.m_vectorAdvertisedDevices.push_back(advertisedDevice);
}
break;
}
default: {
break;
}
}
break;
}
default: {
break;
}
}
}
void BLEScan::setActiveScan(bool active) {
if (active) {
m_scan_params.scan_type = BLE_SCAN_TYPE_ACTIVE;
} else {
m_scan_params.scan_type = BLE_SCAN_TYPE_PASSIVE;
}
}
void BLEScan::setAdvertisedDeviceCallbacks(BLEAdvertisedDeviceCallbacks* pAdvertisedDeviceCallbacks, bool wantDuplicates) {
m_wantDuplicates = wantDuplicates;
m_pAdvertisedDeviceCallbacks = pAdvertisedDeviceCallbacks;
}
void BLEScan::setInterval(uint16_t intervalMSecs) {
m_scan_params.scan_interval = intervalMSecs / 0.625;
}
void BLEScan::setWindow(uint16_t windowMSecs) {
m_scan_params.scan_window = windowMSecs / 0.625;
}
BLEScanResults BLEScan::start(uint32_t duration) {
ESP_LOGD(LOG_TAG, ">> start(duration=%d)", duration);
m_semaphoreScanEnd.take(std::string("start"));
m_scanResults.m_vectorAdvertisedDevices.clear();
esp_err_t errRc = ::esp_ble_gap_set_scan_params(&m_scan_params);
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "esp_ble_gap_set_scan_params: err: %d, text: %s", errRc, GeneralUtils::errorToString(errRc));
m_semaphoreScanEnd.give();
return m_scanResults;
}
errRc = ::esp_ble_gap_start_scanning(duration);
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "esp_ble_gap_start_scanning: err: %d, text: %s", errRc, GeneralUtils::errorToString(errRc));
m_semaphoreScanEnd.give();
return m_scanResults;
}
m_stopped = false;
m_semaphoreScanEnd.wait("start");
ESP_LOGD(LOG_TAG, "<< start()");
return m_scanResults;
}
void BLEScan::stop() {
ESP_LOGD(LOG_TAG, ">> stop()");
esp_err_t errRc = ::esp_ble_gap_stop_scanning();
m_stopped = true;
if (errRc != ESP_OK) {
ESP_LOGE(LOG_TAG, "esp_ble_gap_stop_scanning: err: %d, text: %s", errRc, GeneralUtils::errorToString(errRc));
return;
}
m_semaphoreScanEnd.give();
ESP_LOGD(LOG_TAG, "<< stop()");
}
void BLEScanResults::dump() {
ESP_LOGD(LOG_TAG, ">> Dump scan results:");
for (int i=0; i<getCount(); i++) {
ESP_LOGD(LOG_TAG, "- %s", getDevice(i).toString().c_str());
}
}
int BLEScanResults::getCount() {
return m_vectorAdvertisedDevices.size();
}
BLEAdvertisedDevice BLEScanResults::getDevice(uint32_t i) {
return m_vectorAdvertisedDevices.at(i);
}
#endif