lathoub / Arduino-BLE-MIDI

MIDI over Bluetooth Low Energy (BLE-MIDI) 1.0 for Arduino
MIT License
219 stars 33 forks source link

Bluetooth pairing for Arduino nano 33 BLE // auto connect with macOS #90

Closed nicolasvair closed 1 month ago

nicolasvair commented 1 month ago

Hi,

I would like to enable bluetooth pairing to benefit of auto connection on macos. Apple doc here

I looked at the code, the functionality it seems to be present in <hardware/BLEMIDI_ArduinoBLE.h> but I have no clue how to enable it and if it wouldn't break the rest of the code.

Any ideas ?

Thank you !

PS : attached is my BLE project (4 midi knobs and buttons with page selector). It was possible thanks to your work so a warm thank you from france ! 🙏💚

IMG_3165

We are using it in this project https://www.instagram.com/caos_808/

nicolasvair commented 1 month ago

A hint may be that I actually doesn't save bonding info in the flash memory... so maybe the pairing is ok but I just need to save the bonding info ?

nicolasvair commented 1 month ago

Allright, so I was able to bond/pair using the EncryptedBatteryMonitor.ino example in ArduinoBLE

It didn't auto connect with macOS but I guess it's because of non-standard UUID type and characteristics.

I'm now dumb-trying using the methods of EncryptedBatteryMonitor.ino into my BLE-MIDI code, for example this one :


// Callback function with confirmation code when new device is pairing.
  BLE.setDisplayCode([](uint32_t confirmCode){
    Serial.println("New device pairing request.");
    Serial.print("Confirm code matches pairing device: ");
    char code[6];
    sprintf(code, "%06d", confirmCode);
    Serial.println(code);
  });

But it seems that BLEMIDI_CREATE_DEFAULT_INSTANCE() isn't creating a BLE type object.. I'm now digging to find the name of the object created. (I'm guessing there is one created at one point ?)

Any ideas ?

Another path to auto-connect would be to act as central and not peripheral.. but it looks even more complicated

nicolasvair commented 1 month ago

Okay, well it wasn't easy but I was finally able to auto connect to macOS. It's working great now, very fast and very reliable.

If any newbie like me wants to replicate, here are the important points :

1 - PAIRING / BONDING : Bluetooth use services which encompasses characteristics. It was quite weird for me at first, but to enable pairing, you need to have one characteristic (inside a service) that is encrypted. It's not like you pair the connection and everything is then encrypted. macOS / iOS will reconnect only with BLE devices supporting pairing, so you need an encrypted characteristic. BLE-midi create a service (midiService) which have characteristic (midiChar), it seems you can't encrypt the midi characteristic (midiChar), so you have to add a new service which has an encrypted characteristic. I added a battery type service with a dummy characteristic, I don't use it but it is here just to enable pairing/bonding.

Here is my dirty code for this : BLE services and characteristics.h.zip

2 - COMPLYING WITH BT/APPLE RULES : Apple is expecting some services and characteristics for a Bluetooth Device. If you don't comply, you are ignored. Guidelines are here, page 227 for BLE devices. I didn't comply with everything but I added a "Device Information Service" with characteristics "Manufacturer Name String" and "Model Number String". That was my haha moment. With only these 2, I was able to pair and macOS now automatically reconnect. They are also mentioning a "20 ms" interval for advertising but I'm not sure it is so important.

3 - APPROPRIATE CALLBACKS : So for pairing you need some specific functions like showing a code, generate IRK and LTK and associate them with Mac address. I took them from "EncryptedBatteryMonitor" example. The one I used are there BLE pairing callbacks.h.zip I never understood where are they defined but probably in the ArduinoBLE lib. These are in my setup.

4 - STORING THE LTK : While the previous functions will create the code for pairing, they won't save it to non volatile memory. You have 2 options, simplest I just copy the Mac address, IRK and LTK, and put them directly into your Arduino code. Simple but if you ever delete / forget the Arduino in your bluetooth preferences, you have to edit your code to put the new pairing keys. The second option is to store to flash memory, took me an hour but it ended up working.

5 - CONNECT THROUGH LIGHTBLUE : Despite the fact that there is a encrypted characteristics, when I connect through "audio & midi settings" -> "Bluetooth configuration" I don't trigger the pairing, because ble-midi isn't connecting to the other services (so no connection to the encrypted one). I could probably connect through macOS bluetooth preferences if I'd spend more time complying with apple BT requisites. An easy solution is to connect through LightBlue App (on Mac), this will trigger the pairing/bonding between Arduino and the mac, store your Mac / IRK / LTK in your code, then enable the ble-midi connection and boom, you're paired, just turn it on and it will automatically connect to your computer.

It was very important to us because we were having bluetooth disconnection on stage. Not everywhere, not every time, but now that it reconnects, 5 seconds without bluetooth isn't a big issue anymore. Next step -> improving the bluetooth stability (higher TX power ?...)

nicolasvair commented 1 month ago

I close the "issue". It wasn't really one but I didn't know where to put those kind of questions.

lathoub commented 1 month ago

Hi @nicolasvair thanks for the investigation and reporting back - much appreciated. (Nice project and look good , good luck with it)