NimBLE-Arduino: BLE working in Android, but not showing up in iOS
The below code (refactored BLE_server_multiconnect example with added security) works great on both Android 8.1 and Android 11 phones. No problems.
However, iPhone 10 and iPhone 11 phones aren’t even detecting the existence of NimBLE.
What am I doing wrong here?
#include <NimBLEDevice.h>
BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
uint8_t txValue = 0;
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
/** None of these are required as they will be handled by the library with defaults. **
** Remove as you see fit for your needs */
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
BLEDevice::startAdvertising();//adding this line allows for multiple simultaneous BLE connections
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
}
/***************** New - Security handled here ********************
****** Note: these are the same return values as defaults ********/
uint32_t onPassKeyRequest(){
Serial.println("Server PassKeyRequest");
return 123456;
}
void onPassKeyNotify(uint32_t passkey) {
Serial.println("Passkey Notify");
}
bool onConfirmPIN(uint32_t pass_key){
Serial.print("The passkey YES/NO number: ");Serial.println(pass_key);
return true;
}
void onAuthenticationComplete(ble_gap_conn_desc* desc) {
if(desc->sec_state.encrypted){
if(!desc->sec_state.encrypted) {
Serial.println("Encrypt connection failed - disconnecting");
/** Find the client with the connection handle provided in desc */
NimBLEDevice::getClientByID(desc->conn_handle)->disconnect();
vTaskDelay(5000);//bruteforce protection, 5s
return;
}
}
}
/*******************************************************************/
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
Serial.print("Received Value: ");
for (int i = 0; i < rxValue.length(); i++)
Serial.print(rxValue[i]);
if(rxValue.find("F") != -1)
Serial.println("do stuff");
}
}
};
void setup() {
Serial.begin(115200);
// Create the BLE Device
NimBLEDevice::init("NimBLE");
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
NimBLEDevice::setSecurityAuth(true, true, true);
NimBLEDevice::setSecurityPasskey(123456);
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
// Create the BLE Server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create a BLE Characteristic
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
NIMBLE_PROPERTY::NOTIFY
);
BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
NIMBLE_PROPERTY::WRITE
);
pRxCharacteristic->setCallbacks(new MyCallbacks());
// Start the service
pService->start();
// Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
if (deviceConnected) {
pTxCharacteristic->setValue('c'); // Sending bluetooth message
pTxCharacteristic->notify();
delay(500);
}
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 34 (16 by maintainers)
iOS seems to only show classic bluetooth capable devices. NimBLE is BLE only so iOS does not show it natively. The original library has both functionalities which is why it would show up then.
Turns out the iOS app was caching BLE improperly. So, problem solved.
The solution was to add this single line:
pAdvertising->addServiceUUID((uint16_t)0x1101);From my understanding it’s only the iOS built in BT scanner that ignores BLE devices and that was intentional as to connect to BLE devices it is expected that there would be a separate app to perform that function. Which makes sense because many BLE devices only advertise data and the iOS scanner will not report this, instead it only shows it in a list. So that leaves it up to the app developers to deal with BLE at the app level, which makes sense because every BLE device is different and could be non-standard while classic bluetooth services are more defined and easily supported by the OS.
As the name NimBLE implies, there is not and probably should not be any support for classic bluetooth, however you might be able to play with the advertised flags to fake BR/EDR capability.