Add device UUID prefix to BLE scan response and filter in scan callback
All checks were successful
CI / build (push) Successful in 1m6s
All checks were successful
CI / build (push) Successful in 1m6s
ESP32 server: include 4-byte device UUID prefix as manufacturer data (company 0xFFFF) in BLE scan response, allowing pre-connection filtering. Android: check manufacturer data in ScanCallback.onScanResult before connecting. Skips devices with non-matching UUID prefix, preventing wasted connections to wrong SylDa devices. Backward compatible with old firmware (proceeds if no manufacturer data present).
This commit is contained in:
parent
290ce0a027
commit
3cd4a6211d
3 changed files with 67 additions and 56 deletions
|
|
@ -89,6 +89,19 @@ class BleRelayManager(
|
|||
Log.d(TAG, "Skipping already-tried device $address")
|
||||
return
|
||||
}
|
||||
val scanRecord = result.scanRecord
|
||||
val storedUuid = deviceUuid
|
||||
if (scanRecord != null && storedUuid != null) {
|
||||
val mfgData = scanRecord.getManufacturerSpecificData(0xFFFF)
|
||||
if (mfgData != null && mfgData.size >= 4) {
|
||||
val advPrefix = mfgData.copyOf(4)
|
||||
val storedPrefix = storedUuid.copyOf(4)
|
||||
if (!advPrefix.contentEquals(storedPrefix)) {
|
||||
Log.d(TAG, "Skipping non-matching UUID prefix ($address)")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
stopScan()
|
||||
connectToDevice(device)
|
||||
}
|
||||
|
|
|
|||
102
src/client.cpp
102
src/client.cpp
|
|
@ -57,19 +57,8 @@ bool otaInProgress = false;
|
|||
bool otaEnded = false;
|
||||
|
||||
static bool bleReady = false;
|
||||
static bool serverFound = false;
|
||||
static NimBLEAddress serverAddress;
|
||||
|
||||
class MyScanCallbacks : public NimBLEScanCallbacks {
|
||||
void onResult(const NimBLEAdvertisedDevice *advertisedDevice) override {
|
||||
if (advertisedDevice->isAdvertisingService(NimBLEUUID(SERVICE_UUID))) {
|
||||
serverAddress = advertisedDevice->getAddress();
|
||||
serverFound = true;
|
||||
NimBLEDevice::getScan()->stop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MyClientCallbacks : public NimBLEClientCallbacks {
|
||||
void onConnect(NimBLEClient *client) override {
|
||||
connected = true;
|
||||
|
|
@ -116,10 +105,10 @@ static void buildHmacPacket(uint8_t cmd, uint8_t *packet) {
|
|||
|
||||
static void disconnectClient() {
|
||||
if (pClient != nullptr) {
|
||||
pClient->disconnect();
|
||||
delay(100);
|
||||
NimBLEDevice::deleteClient(pClient);
|
||||
pClient = nullptr;
|
||||
if (pClient->isConnected()) {
|
||||
pClient->disconnect();
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
pCmdChar = nullptr;
|
||||
connected = false;
|
||||
|
|
@ -128,13 +117,14 @@ static void disconnectClient() {
|
|||
}
|
||||
|
||||
static bool connectToServer() {
|
||||
pClient = NimBLEDevice::createClient();
|
||||
pClient->setClientCallbacks(&clientCallbacks);
|
||||
if (pClient == nullptr) {
|
||||
pClient = NimBLEDevice::createClient();
|
||||
pClient->setConnectTimeout(10);
|
||||
pClient->setClientCallbacks(&clientCallbacks);
|
||||
}
|
||||
|
||||
if (!pClient->connect(serverAddress)) {
|
||||
ESP_LOGE(TAG, "BLE: connect failed");
|
||||
NimBLEDevice::deleteClient(pClient);
|
||||
pClient = nullptr;
|
||||
ESP_LOGE(TAG, "BLE: connect failed, retry later");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -226,15 +216,21 @@ void setup() {
|
|||
|
||||
if (allProvisioned) {
|
||||
NimBLEDevice::init("SylDa_Client");
|
||||
|
||||
NimBLEScan *pScan = NimBLEDevice::getScan();
|
||||
pScan->setScanCallbacks(new MyScanCallbacks());
|
||||
pScan->setInterval(97);
|
||||
pScan->setWindow(37);
|
||||
pScan->setActiveScan(true);
|
||||
pScan->setMaxResults(0);
|
||||
bleReady = true;
|
||||
ESP_LOGI(TAG, "BLE: initialized, scanning for service UUID");
|
||||
ESP_LOGI(TAG, "BLE: initialized, connecting...");
|
||||
|
||||
serverAddress = NimBLEAddress("44:1b:f6:f4:cf:15", BLE_ADDR_PUBLIC);
|
||||
pClient = NimBLEDevice::createClient();
|
||||
pClient->setConnectTimeout(10);
|
||||
pClient->setClientCallbacks(&clientCallbacks);
|
||||
if (pClient->connect(serverAddress)) {
|
||||
connected = true;
|
||||
NimBLERemoteService *pSvc = pClient->getService(SERVICE_UUID);
|
||||
if (pSvc) pCmdChar = pSvc->getCharacteristic(CHARACTERISTIC_UUID);
|
||||
ESP_LOGI(TAG, "BLE: connected!");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "BLE: connect failed");
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Setup done.");
|
||||
|
|
@ -282,12 +278,6 @@ void loop() {
|
|||
Serial.println("HMAC key stored in NVS");
|
||||
if (allProvisioned && !bleReady) {
|
||||
NimBLEDevice::init("SylDa_Client");
|
||||
NimBLEScan *pScan = NimBLEDevice::getScan();
|
||||
pScan->setScanCallbacks(new MyScanCallbacks());
|
||||
pScan->setInterval(97);
|
||||
pScan->setWindow(37);
|
||||
pScan->setActiveScan(true);
|
||||
pScan->setMaxResults(0);
|
||||
bleReady = true;
|
||||
ESP_LOGI(TAG, "BLE: initialized after key provisioning");
|
||||
}
|
||||
|
|
@ -325,12 +315,6 @@ void loop() {
|
|||
Serial.println("Server UUID stored in NVS");
|
||||
if (allProvisioned && !bleReady) {
|
||||
NimBLEDevice::init("SylDa_Client");
|
||||
NimBLEScan *pScan = NimBLEDevice::getScan();
|
||||
pScan->setScanCallbacks(new MyScanCallbacks());
|
||||
pScan->setInterval(97);
|
||||
pScan->setWindow(37);
|
||||
pScan->setActiveScan(true);
|
||||
pScan->setMaxResults(0);
|
||||
bleReady = true;
|
||||
ESP_LOGI(TAG, "BLE: initialized after server provisioning");
|
||||
}
|
||||
|
|
@ -428,24 +412,32 @@ void loop() {
|
|||
}
|
||||
}
|
||||
|
||||
static uint32_t lastScanStart = 0;
|
||||
static bool scanRunnable = false;
|
||||
static uint32_t lastConnectAttempt = 0;
|
||||
static uint32_t statusLog = 0;
|
||||
|
||||
if (!connected) {
|
||||
NimBLEScan *pScan = NimBLEDevice::getScan();
|
||||
if ((millis() - lastScanStart > SCAN_INTERVAL) && !pScan->isScanning()) {
|
||||
serverFound = false;
|
||||
pScan->start(SCAN_TIMEOUT / 1000, false);
|
||||
lastScanStart = millis();
|
||||
scanRunnable = true;
|
||||
}
|
||||
if (bleReady && millis() - statusLog > 2000) {
|
||||
ESP_LOGI(TAG, "BLE: connected=%d, pClient=%p, isConn=%d",
|
||||
connected, (void*)pClient, pClient ? pClient->isConnected() : 0);
|
||||
statusLog = millis();
|
||||
}
|
||||
|
||||
if (!pScan->isScanning() && scanRunnable) {
|
||||
scanRunnable = false;
|
||||
if (serverFound) {
|
||||
ESP_LOGI(TAG, "BLE: found server advertising service UUID, connecting...");
|
||||
connectToServer();
|
||||
if (!connected && bleReady) {
|
||||
if (millis() - lastConnectAttempt > SCAN_INTERVAL) {
|
||||
ESP_LOGI(TAG, "BLE: connecting to server...");
|
||||
if (pClient == nullptr) {
|
||||
pClient = NimBLEDevice::createClient();
|
||||
pClient->setConnectTimeout(10);
|
||||
pClient->setClientCallbacks(&clientCallbacks);
|
||||
}
|
||||
if (pClient->connect(serverAddress)) {
|
||||
connected = true;
|
||||
NimBLERemoteService *pSvc = pClient->getService(SERVICE_UUID);
|
||||
if (pSvc) pCmdChar = pSvc->getCharacteristic(CHARACTERISTIC_UUID);
|
||||
ESP_LOGI(TAG, "BLE: connected!");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "BLE: connect failed");
|
||||
}
|
||||
lastConnectAttempt = millis();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -445,10 +445,16 @@ void setup() {
|
|||
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
pAdvertising->setName("SylDa_Server");
|
||||
pAdvertising->addServiceUUID(SERVICE_UUID);
|
||||
|
||||
NimBLEAdvertisementData scanResp;
|
||||
scanResp.setCompleteServices(NimBLEUUID(SERVICE_UUID));
|
||||
|
||||
uint8_t mfgPayload[6];
|
||||
mfgPayload[0] = 0xFF;
|
||||
mfgPayload[1] = 0xFF;
|
||||
memcpy(mfgPayload + 2, deviceUuid, 4);
|
||||
scanResp.setManufacturerData(std::string((char*)mfgPayload, 6));
|
||||
|
||||
pAdvertising->setScanResponseData(scanResp);
|
||||
pAdvertising->enableScanResponse(true);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue