ESP32-BLE-Keyboard icon indicating copy to clipboard operation
ESP32-BLE-Keyboard copied to clipboard

how to get the first possible moment to sent?

Open 3Dietrich opened this issue 3 years ago • 16 comments

I want to get a sign if BT is connected and thought a shortcut is a good way. But how to get the information that BT is connected? Sending directly doesn't work. I know that delay works but I don't want to wait longer than needed but a fast connection. I tried

void setup() {
  bleKeyboard.begin();
  while (!bleKeyboard) {;}  // wait for the BLE to become true
  sendMyShortCut();         // a keyboard shortcut (that e.g. triggers a gentle audio signal 
}

but this doesn't work. The same but with "BleKeyboard", I looked into the code and found 'isConnected' but while (!bleKeyboard.isConnected()) {;} doesn't work either.

Is there a possibility to get a bluetooth signal directly after its connection?

3Dietrich avatar Nov 13 '21 00:11 3Dietrich

The following code works fine for me:

#include <BleKeyboard.h>

BleKeyboard bleKeyboard;

void setup() {
    Serial.begin(115200);
    bleKeyboard.begin();
    Serial.println("Waiting for keyboard");
    while (!bleKeyboard.isConnected()) {
        Serial.print(".");
        delay(250);
    }
    Serial.println();
    Serial.println("Keyboard connected!");
}

void loop() {
}

https://user-images.githubusercontent.com/2558564/141608750-0e0f7f53-2d53-40d8-8d75-8cf42bee15a1.mp4

It works for new pairing (Windows & Android) and automatically reconnect to my windows computer. It looks like that Android does not automatically reconnect if the ESP was paired before and restarted. I think the issue is with the client device (phone / computer).

sivar2311 avatar Nov 13 '21 06:11 sivar2311

well.. you write "it works" but you didn't prove that. You do not send any BT, just write "connected" with the SerialMonitor, so you don't know if the BT is active directly. For me it also connects, but I want to use directly after init a shortcut sended to the computer (what plays a sound). I tried it (btw: on macOS) and it did not work. Even with delay(300) between 'isConnected' and the BT signal:

while (!bleKeyboard.isConnected()) {
    Serial.print(".");
    delay(100);
}
    delay(300);
    sendMyShortCut();

If I press approximately immediately after init process a button with e.g. the same shortcut) it works! Just the first automatic send signal ('sendMyShortCut()' sends shift+alt+F6) doesn't work in around 90% of starts (1 of 10 starts it worked)..

3Dietrich avatar Nov 14 '21 01:11 3Dietrich

Hi 3Dietrich! Please excuse the misunderstanding. I had understood that the function isConnected() does not work.

The problem is that if a BLE client is connected, it does not mean that it has subscribed to notifications.

The Arduino-NimBLE library provides a callback for this. So I was able to implement an isSubscribed() function which returns true when the client has subscribed.

Unfortunately, the standard BLE library does not have this callback and isSubscribed will always return false.

#include <BleKeyboard.h>

BleKeyboard bleKeyboard;

void setup() {
    Serial.begin(115200);
    bleKeyboard.begin();

    Serial.println("Waiting for client subscription");
    while (!bleKeyboard.isSubscribed()) {
        Serial.print(".");
        delay(250);
    }
    Serial.println();
    Serial.println("Client subscribed! sending message...");

    bleKeyboard.println("Hello!");
}

void loop() {
}

https://user-images.githubusercontent.com/2558564/141679359-406ee145-f669-4b98-8c01-3250b49ec489.mp4

Here is the modified version: BleKeyboard.zip

sivar2311 avatar Nov 14 '21 12:11 sivar2311

The Arduino-NimBLE library provides a callback for this. So I was able to implement an isSubscribed() function which returns true when the client has subscribed.

ok!

Unfortunately, the standard BLE library does not have this callback and isSubscribed will always return false.

If the "Nim" mode does it, I would call this a bug. Did you fix it in the attached .zip for the normal mode? I replaced the files in the lib with your attached code and used isSubscribed() like in your example but it didn't work. It kept printing "." Maybe I should try if NimBLE works*. I don't understand why BLE keyboard is offered when NimBLE keyboard contains all, with less memory and actually more functions..

*didn't work :(

3Dietrich avatar Nov 14 '21 13:11 3Dietrich

This time the misunderstanding is on your side ;)

There is no "NimBLE-Keyboard" library. But there are different BLE stacks (the standard one and "NimBLE-Arduino"). The BLE-KeyBoard library can be used with both BLE stacks. The NimBLE-Arduino stack requires less ram/rom and offers additional features (like the detection if a client has subscribed) To make the ZIP from my last comment working, you need to install NimBLE-Arduino.

sivar2311 avatar Nov 14 '21 13:11 sivar2311

This time the misunderstanding is on your side ;)

ok :) I got it, used your code with the NimBLE. It compiles fine but ..sorry.. it gets stuck in the while loop (isSubscribed() keeps = false).

3Dietrich avatar Nov 14 '21 13:11 3Dietrich

~~Hm... for me this works fine (see the video from above). Did you remove the ble device and make a new pairing?~~

Sorry, my mistake. Please edit BleKeyboard.h line 2: //define USE_NIMBLE should be #define USE_NIMBLE to enable the "NimBLE-Mode"

sivar2311 avatar Nov 14 '21 13:11 sivar2311

I did removing/new pairing as well as the change in BleKeyboard.h. and.. no, doesn't work. BUT: It not only also works when I comment out #define USE_NIMBLE, additionally I have a much faster pairing time (indicated by an LED). .. it only doesn't send the first auto shortcut

I got a bit tired to test all the possibilities whereas it worked well with delay(1000) So I suggest that we wait for other people who have the same issue or not and maybe write here there experiences.

3Dietrich avatar Nov 14 '21 14:11 3Dietrich

NimBLE stack is a bit faster than the standard BLE library. You should also have noticed the less RAM / ROM usage, which makes NimBLE so greatful. I'm sorry it doesn't work for you.

sivar2311 avatar Nov 14 '21 14:11 sivar2311

so.. it seems that with `#define USE_NIMBLE' or without it, it always uses Nimble mode..?

3Dietrich avatar Nov 14 '21 14:11 3Dietrich

If #define USE_NIMBLE is commented out, the normal BLE stack should be used.

sivar2311 avatar Nov 14 '21 14:11 sivar2311

correction: with the last changes both modes work faster but the first BT signal only arrives with delays. This also changes whether it is on the USB or not. If not, it's faster. This is my test result (USB not connected): // #define USE_NIMBLE: ~700ms (but I'm not sure, maybe lower) #define USE_NIMBLE: ~400ms

..and both modes use equal memory spcace:

Der Sketch verwendet 548154 Bytes (41%) des Programmspeicherplatzes. Das Maximum sind 1310720 Bytes.
Globale Variablen verwenden 27208 Bytes (8%) des dynamischen Speichers, 

3Dietrich avatar Nov 14 '21 14:11 3Dietrich

What do you mean by connected / not connected to USB?

Here is my comparison between standard BLE stack and NimBLE-Arduino: //#define USE_NIMBLE

Der Sketch verwendet 955413 Bytes (72%) des Programmspeicherplatzes. Das Maximum sind 1310720 Bytes.
Globale Variablen verwenden 22060 Bytes (6%) des dynamischen Speichers, 305620 Bytes für lokale Variablen verbleiben. 
Das Maximum sind 327680 Bytes.

#define USE_NIMBLE:

Der Sketch verwendet 552869 Bytes (42%) des Programmspeicherplatzes. Das Maximum sind 1310720 Bytes.
Globale Variablen verwenden 25516 Bytes (7%) des dynamischen Speichers, 302164 Bytes für lokale Variablen verbleiben. 
Das Maximum sind 327680 Bytes.

sivar2311 avatar Nov 14 '21 15:11 sivar2311

What do you mean by connected / not connected to USB?

connected: the ESP32 has an USB connector, which is connected with a USB cable to the computer. It happens usually when I upload a sketch to the esp32. not connected: ESP32 is powered by battery, USB is unconnected.

by //#define USE_NIMBLE I meant in the file mysketch.ino

// #define USE_NIMBLE
#include <BleKeyboard.h>

and result is: with or without // it uses always exact the same Memory.

Maybe this is the 3rd misunderstanding: Can it be that you mean the line 2 in file BleKeyboard.h ..? I have not changed this, it remained on #define USE_NIMBLE.

3Dietrich avatar Nov 14 '21 16:11 3Dietrich

Ah okay, got it. The difference being connected to USB / not connected may be a result from the print statements. Printing to serial takes some time (depending to the defined baudrate)

Yes, i meant the BleKeyboard.h. A few days ago i realized that a define before including the library doesn't work :( The define must be in BleKeyboard.h not in the main sketch.

sivar2311 avatar Nov 14 '21 16:11 sivar2311

Apologies for the thread resurrection but I'm having a similar challenge - when first connected to the bluetooth device the first keypress can be missed.

I've checked through the change history and can't find any reference to isSubscribed() - did this ever get added to the code?

Hi 3Dietrich! Please excuse the misunderstanding. I had understood that the function isConnected() does not work.

The problem is that if a BLE client is connected, it does not mean that it has subscribed to notifications.

The Arduino-NimBLE library provides a callback for this. So I was able to implement an isSubscribed() function which returns true when the client has subscribed.

Unfortunately, the standard BLE library does not have this callback and isSubscribed will always return false.

#include <BleKeyboard.h>

BleKeyboard bleKeyboard;

void setup() {
    Serial.begin(115200);
    bleKeyboard.begin();

    Serial.println("Waiting for client subscription");
    while (!bleKeyboard.isSubscribed()) {
        Serial.print(".");
        delay(250);
    }
    Serial.println();
    Serial.println("Client subscribed! sending message...");

    bleKeyboard.println("Hello!");
}

void loop() {
}

subscription.mp4 Here is the modified version: BleKeyboard.zip

skotl avatar Aug 17 '22 20:08 skotl