ESP32 BLE и Android-телефоны(ы) — обнаружение присутствия

#android #bluetooth-lowenergy #esp32 #sniffer

Вопрос:

Есть ли возможность «преодолеть» рандомизацию MAC-адресов BLE и обнаружить присутствие моего собственного телефона(телефонов) Android?

Я ищу решение, как определить присутствие моего телефона в непосредственной близости от ESP32, не устанавливая что-то вроде приложения iBeacon, которое разрядило бы мою батарею.

  • Я начал с примера для BLE sniffer, который хорошо работает, но с рандомизацией MAC на Android это бесполезно.
  • Затем я перешел к решению, используя эмуляцию скрытой клавиатуры. После сопряжения он легко подключается, когда телефон входит в зону действия. Как только он подключен, я могу вызвать необходимое действие, а затем отключить Bluetooth ESP32, чтобы он не был подключен все время. Когда мне нужно снова проверить телефон, я просто могу снова включить сервер. Это было бы хорошим решением, но… Мне нужно проверить еще (по крайней мере, два) телефона. Я пытался дублировать блесерверы, чтобы переключаться или запускать два simoutinasly, но безуспешно — либо это невозможно, либо это превышает мои знания об этой магии рекламы/сопряжения/подключения.
  • Третьим решением было бы иметь отдельный ESP для каждого телефона — выполнимо, но только в крайнем случае

Кто-нибудь уже как — то решил такую задачу?

Для решения с клавиатурой я использую этот код, найденный в Интернете:

 #include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include "BLE2902.h"
#include "BLEHIDDevice.h"
#include "HIDTypes.h"
#include "HIDKeyboardTypes.h"
#include <driver/adc.h>

BLEHIDDevice* hid;
BLECharacteristic* input;
BLECharacteristic* output;
BLEAdvertising *pAdvertising;
BLEServer *pServer;

bool connected = false;
bool restart = false;

class MyCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer* pServer){
    connected = true;
    Serial.println("Connected");
    BLE2902* desc = (BLE2902*)input->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
    desc->setNotifications(true);
    // NEEDED ACTIONS
  }

  void onDisconnect(BLEServer* pServer){
    connected = false;
    Serial.println("DisConnected");
    BLE2902* desc = (BLE2902*)input->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
    desc->setNotifications(false);
    restart = true;
  }
};

void setup() {
  Serial.begin(115200);
  Serial.println("Starting BLE work!");
  BLEDevice::init("Backpack-MeowMeow");
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyCallbacks());
  pServer->getPeerDevices(true);

  hid = new BLEHIDDevice(pServer);
  input = hid->inputReport(1); // <-- input REPORTID from report map
  output = hid->outputReport(1); // <-- output REPORTID from report map

  std::string name = "ElectronicCats";
  hid->manufacturer()->setValue(name);

  hid->pnp(0x02, 0xe502, 0xa111, 0x0210);
  hid->hidInfo(0x00,0x02);

  BLESecurity *pSecurity = new BLESecurity();
  //  pSecurity->setKeySize();
    pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND);

    hid->startServices();

    pAdvertising = pServer->getAdvertising();
    pAdvertising->setAppearance(HID_BARCODE);
    pAdvertising->addServiceUUID(hid->hidService()->getUUID());
    pAdvertising->start();
    hid->setBatteryLevel(7);

    //ESP_LOGD(LOG_TAG, "Advertising started!");
    //delay(portMAX_DELAY);
}

void loop() {
  
  if(connected){
    delay(10);
  }
  if (restart) {
    restart = false;
    pAdvertising->start();
  }
  delay(50);
}
 

Комментарии:

1. Вы хотите отслеживать все телефоны Android вокруг вас или только определенный набор, который вы контролируете?

2. Только некоторые из них. Поэтому сопряжение не является проблемой. Сначала я начал с обнюхивания, потому что не хочу устанавливать приложения, которые разряжали бы батарею, но, похоже, это невозможно.

3. Еще одна проблема с нюханием: не каждый телефон Android рекламирует через BLE, и вы найдете только устройства, которые рекламируют.

4. BLE может быть очень энергоэффективным, если вы регулируете рекламный интервал. В зависимости от вашего варианта использования вы можете размещать рекламу только каждые 10 секунд или даже меньше. Это замедляет обнаружение на вашем esp32 (который должен сканироваться непрерывно), но экономит энергию на вашем мобильном устройстве

5. На самом деле мне нужно проверять наличие только несколько раз в день. Так что с рекламой все должно быть не так уж плохо. 95% времени esp32 будет выключен.