0

I want to scan continuously for other Bluetooth devices with my ESP32 using BLE. The scan method only accepts integers larger than 0, such as scan->start(1, false). However I want the results to be more "responsive" and a 1-second scanning duration is too long. This is my sample code:

#include <Arduino.h>
#include <BLEAdvertisedDevice.h>
#include <BLEDevice.h>
#include <BLEScan.h>
#include <string>
#include <iostream>

const int PIN = 2; const int CUTOFF = -40; BLEScan* scan;

#define SERVICE_UUID "f5aeb701-4395-4387-b8d4-e1f542b05151" #define CHARACTERISTIC_UUID "b2bd617f-6f78-45e7-bfdd-3edf29a5661a"

void setup() { pinMode(PIN, OUTPUT); BLEDevice::init("ESP32 GrooveBrick"); Serial.begin(9600); BLEServer pServer = BLEDevice::createServer(); BLEService pService = pServer->createService(SERVICE_UUID); BLECharacteristic pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE); pService->start(); BLEAdvertising pAdvertising = BLEDevice::getAdvertising(); pAdvertising->addServiceUUID(SERVICE_UUID); pAdvertising->setScanResponse(true); pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue pAdvertising->setMinPreferred(0x12); scan = BLEDevice::getScan(); scan->setActiveScan(true); /!< Scan interval. This is defined as the time interval from when the Controller started its last LE scan until it begins the subsequent LE scan. Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms) Time = N 0.625 msec Time Range: 2.5 msec to 10.24 seconds/ scan->setInterval(100); //interval (how often there is a scan) /!< Scan window. The duration of the LE scan. LE_Scan_Window shall be less than or equal to LE_Scan_Interval Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms) Time = N * 0.625 msec Time Range: 2.5 msec to 10240 msec */ scan->setWindow(99); // window (how long the scans are) must be <= interval BLEDevice::startAdvertising(); }

void loop() { BLEScanResults results = scan->start(1, true); int best = CUTOFF;

std::cout << "Scanning!" << "\n"; for (int i = 0; i < results.getCount(); i++) { BLEAdvertisedDevice device = results.getDevice(i); std::cout << "Found BT-device: " << device.getName() << " RSSI: " << std::to_string(device.getRSSI()) << "\n"; int rssi = device.getRSSI(); if (rssi > best) { best = rssi; } } digitalWrite(PIN, best > CUTOFF ? HIGH : LOW); scan->clearResults(); // delete results fromBLEScan buffer to release memory }

dda
  • 1,595
  • 1
  • 12
  • 17
Philipp
  • 109
  • 3

2 Answers2

2

You can't using the callback from that function, but what you can do is add you own callback that will receive every new radio event.

Add this to your init code:

BLEDevice::setCustomGapHandler(custom_handler);

and this before it:

static void it_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
    switch (event)
    {
        case ESP_GAP_BLE_SCAN_RESULT_EVT:
            if (param->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT)
            {
                // This event is triggered every time a new device is found, and contains the advertised data.
                // We should avoid processing or printing anything here to avoid hardware congestion
                // log_i("ESP_GAP_BLE_SCAN_RESULT_EVT");
            if (param-&gt;scan_rst.ble_adv != NULL)
            {
                //this makes sure that there is data to be processed
            }
        }
        break;
    default:
        // log_i(&quot;Event %d unhandled&quot;, event);
        break;
}

}

ocrdu
  • 1,795
  • 3
  • 12
  • 24
0

the simplest solution is this: add this line:

BLEDevice::getScan()->stop();

Example:

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <Arduino.h>

class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) { // Hole die Service-Daten vom beworbenen Gerät //std::string serviceData = advertisedDevice.getServiceData(); std::string deviceName = advertisedDevice.getName(); if (!deviceName.empty() && deviceName.find("Drone_") != std::string::npos) { // Verwende .empty() anstelle von ! Serial.println("Scan-Ergebnis gefunden:");

// Ausgabe des Gerätetyps und der RSSI-Signalstärke
Serial.print(&quot;Gerätename: &quot;);
Serial.println(advertisedDevice.getName().c_str());
Serial.print(&quot;Signalstärke (RSSI): &quot;);
Serial.println(advertisedDevice.getRSSI());
}

BLEDevice::getScan()-&gt;stop();

} };

void setup() { Serial.begin(115200); delay(3000); // 1 Sekunde warten Serial.println("Startet kontinuierlichen BLE-Scan...");

// BLE initialisieren BLEDevice::init("");

// BLE-Scan konfigurieren BLEScan* pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); pBLEScan->setActiveScan(true); // Aktives Scannen für genauere RSSI-Werte pBLEScan->setInterval(32); // Scan-Intervall in 0.625ms-Einheiten pBLEScan->setWindow(32); // Scan-Fenster in 0.625ms-Einheiten

}

void loop() { // Starte den Scan ohne zeitliche Begrenzung und bereinige die Ergebnisse direkt danach BLEDevice::getScan()->start(0.1, true); // kurzer Scan, um wiederholte Ergebnisse zu ermöglichen

//int deviceCount = BLEDevice::getScan()->getResults().getCount(); //Serial.print("Anzahl gefundener Geräte: "); //Serial.println(deviceCount);

BLEDevice::getScan()->clearResults(); // Bereinige die Ergebnisse sofort für den nächsten Scan }