gatt status 147 error on Samsung Galaxy, won't display in Windows
Arduino IDE, ESP32 v2.0.18 core me: intermediate level programmer
Was using v1.4.3: -works fine with most devices -didn't work at all with Samsung Galaxy -displays on Win11 ble scan but won't connect
So, I upgraded to v2.3.2 (Arduino IDE) and tried my best.
With v2.3.2: -visible/connects on Samsung Galaxy phone, but gives gatt status 147 error -visible/connects on iOS 15.3 phone -doesn't display on my Win11 scan
My device is not a keyboard or mouse, it just exchanges UART data. However, it must be displayed during BLE scans, so I assume it should continue to be HID. Correct? When I do it without HID, it just disappears from my device BLE scans. It does show up properly using nRF, though. No encryption needed, but can if required.
What am I doing wrong?
#include <NimBLEDevice.h>
#include <NimBLEHIDDevice.h>
#include <NimBLEServer.h>
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
NimBLEServer* pServer = nullptr;
NimBLECharacteristic* pRxCharacteristic = nullptr;
NimBLECharacteristic* pTxCharacteristic = nullptr;
NimBLEHIDDevice* hidDevice = nullptr;
volatile bool newDataReady = false;
class MyCallbacks : public NimBLECharacteristicCallbacks {
void onWrite(NimBLECharacteristic* pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if (!rxValue.empty()) {
newDataReady = true;
Serial.print("Received: ");
Serial.println(rxValue.c_str());
}
}
};
void bluetooth_setup() {
NimBLEDevice::init("ESP32_UART_BLE");
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
pServer = NimBLEDevice::createServer();
// Add HID device to improve visibility across platforms
hidDevice = new NimBLEHIDDevice(pServer);
hidDevice->setManufacturer("OP");
hidDevice->setPnp(0x02, 0x5E4, 0x820A, 0x0210); // USB VID, PID, version
hidDevice->setHidInfo(0x00, 0x01); // HID version 1.0
// Create custom UART-like service
NimBLEService* pService = pServer->createService(SERVICE_UUID);
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
NIMBLE_PROPERTY::NOTIFY
);
pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
NIMBLE_PROPERTY::WRITE
);
pRxCharacteristic->setCallbacks(new MyCallbacks());
pService->start();
Serial.println("BLE service started!");
NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->addServiceUUID(hidDevice->getHidService()->getUUID());
pAdvertising->setAppearance(0x03C0); // Generic HID device
// Proper scan response data (name + manufacturer)
NimBLEAdvertisementData scanResponseData;
scanResponseData.setName("ESP32_UART_BLE");
scanResponseData.setManufacturerData("OP");
pAdvertising->setScanResponseData(scanResponseData);
pAdvertising->start();
Serial.println("Waiting for a client connection...");
}
void setup() {
Serial.begin(115200);
bluetooth_setup();
}
void loop() {
if (newDataReady) {
newDataReady = false;
std::string response = "OK\n";
pTxCharacteristic->setValue(response);
pTxCharacteristic->notify();
}
delay(10);
}
I realize now what's going on here. Samsung Galaxy, Windows, and iOS have made it a point to filter out all devices except their approved whitelisted devices from a BLE scan. No way around it. Tried guessing whitelisted characteristics without luck. HID kinda worked, but not good enough.
I'm open to ideas.
Custom apps can still scan and find my device on these devices. But, it'll require a lot more app programming and a lot of confused people...
As far as I know a custom app is all you can do.