Open KlausMu opened 3 months ago
This should now be resolved in the master branch, use the new onIdentity
client and server callback to know when you can store the ID address and add it to the whitelist.
@h2zero Thanks for the hint that the new onIdentity
callback was introduced.
Could you please give me some advice on how to use this new callback?
I pair the ESP32 as a HID to a client, let's say a Windows machine. My server callback onIdentity
and also the default callback (if I don't provide my own one) is never called. That's because the event BLE_GAP_EVENT_IDENTITY_RESOLVED
never fires.
But even if it fired, what should I do in the callback? My problem is, that if a client connects for the first time, it is automatically added to the list of bonded peers. And whenever I start advertising again (with a whitelist), the whitelist is not used if an already bonded client connects. The whitelist only works for not already bonded clients. How does the new callback help here?
The use case for this callback is when bonding with devices that use a random resolvable address and you want to add the id address to the whitelist. The onAuthenticationComplete callback did not provide the correct identity address so adding it to the whitelist there wouldn't have the desired effect.
To answer your question though, it doesn't help your case please ignore my previous comment as I thought this was a different issue and didn't read it again.
Have you tried clearing the whitelist and then adding the device you want? Alternatively you could try using directed advertising.
Directed advertising sounds good. I tried this:
advertising->setAdvertisementType(BLE_GAP_CONN_MODE_DIR);
When doing so, a bonded client does not reconnect at all. No matter if I use a whitelist or not.
How do I tell the directed advertising to which client the advertising should be sent?
BTW, clearing the whitelist of course would work, but this is not want I need. I need two clients bonded at the same time. I need to switch the connection between these two bonded clients at runtime. I can successfully bond two clients. I simply power off the first one while the second one gets bonded. When starting advertising with two bonded clients, it is random which one connects first. I need to control which of the two bonded clients connects to the server.
What I meant was you could just change the whitelist before advertising to have one or the other device in it instead of both.
Directed advertising sadly does not have an API but you can use custom data like so:
// 0x17 = public address, change to 0x18 for random, 0x11 - 0x66 = address
char directedAdv[8] = {0x17, 0x06, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
NimBLEAdvertisementData data;
data.addData(directedAdv, sizeof(directedAdv));
advertising->setAdvertisementData(data);
advertising->setAdvertisementType(BLE_GAP_CONN_MODE_DIR);
advertising->start();
Thanks for the snippet. I tried it, with the following result:
D NimBLEAdvertising: >> Advertising start: customAdvData: 1, customScanResponseData: 0
primary service
uuid 0x1800
handle 1
end_handle 5
characteristic
uuid 0x2a00
...
E NimBLEAdvertising: Unable to advertise - Duration too long
D NimBLEAdvertising: << Advertising start
I think the Unable to advertise - Duration too long should not be there. At least the already bonded client does not reconnect. Do you have any idea what could have gone wrong?
I think the duration is limited to 2 seconds for directed advertising, so you would have to restart it every time it ends with that duration.
Got it working. But not with your snippet. I think it cannot work.
Unable to advertise - Duration too long
is misleading. This is not the reason. The message appears immediatly, no waiting time at all.
Why it is not working: when calling NimBLEAdvertising::start()
, this line is called. In the next line, since dirAddr == nullptr
, peerAddr
will be NULL when calling ble_gap_adv_start
In ble_gap_adv_start
this line is executed, with direct_addr
being NULL.
In ble_gap_adv_validate
, because of this line, the result is BLE_HS_EINVAL
.
So for directed advertising to work, you must provide the peer address when calling NimBLEAdvertising::start()
, like in this example:
// either public address
NimBLEAddress directedAddress = NimBLEAddress("11:22:33.44:55:66", BLE_ADDR_PUBLIC);
// or in case of a random address
//NimBLEAddress directedAddress = NimBLEAddress("11:22:33.44:55:66", BLE_ADDR_RANDOM);
advertising->setAdvertisementType(BLE_GAP_CONN_MODE_DIR);
advertising->start(BLE_HS_FOREVER, nullptr, &directedAddress);
So thanks for your support, for me this is now working. I tested it with public and random addresses. I can connect and bond several devices - one after each other, turning the already bonded devices off while bonding the next one. With directed advertising I can connect exactly to the device I want to connect to. Switching the connection is very fast.
Glad you got it working, I completely forgot about that parameter being added to advertising start call 👍
Hi, first of all thanks a lot for this library! So much better than the bluedroid based library. Solved a lot of issues.
I want an ESP32 to act as a server, to be precise as an HID bluetooth keyboard.
I need to connect to different clients (in my case a FireTV and an AppleTV) and to switch the connection to them at runtime. Only one should be connected at the same time.
I am able to pair and bond both of them. One after the other. In the list of bonded peers I have two peers afterwards.
Remark: It is possible to connect both of them at the same time, if advertising is not stopped after the first connect. But it does not make sense because both devices would receive the same keyboard keys. I cannot force certain keys to be send to a certain peer.
So to achieve switching between the two peers, I tried to:
NimBLEDevice::getServer()->disconnect(...)
// the currently connected peeradvertising->setScanFilter(true, true);
The whitelist filter works in principle (bonding is only possible based on the whitelist). But if a client is already bonded, it can reconnect no matter if there is a whitelist set in advertising or not.
So how can I force only a certain bonded client to connect to the NimBLEServer?
I tried to pair the HID without bonding,
NimBLEDevice::setSecurityAuth(false, false, false);
, but when doing so, reconnects completely fail. It seems that keyboards always need to be bonded, not only to be paired.