From 4c38b6d7429244e260e534202c112751f4140ea6 Mon Sep 17 00:00:00 2001 From: Rudd-O Date: Sun, 12 Mar 2023 20:00:11 +0000 Subject: [PATCH 1/7] Add logging for start / stop / advertise on disconnect. --- components/ble_keyboard/ble_keyboard.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/ble_keyboard/ble_keyboard.cpp b/components/ble_keyboard/ble_keyboard.cpp index 178d316..68ebddc 100644 --- a/components/ble_keyboard/ble_keyboard.cpp +++ b/components/ble_keyboard/ble_keyboard.cpp @@ -21,13 +21,16 @@ void Esp32BleKeyboard::setup() { pServer = BLEDevice::getServer(); + ESP_LOGI("ble", "advertiseOnDisconnect(%s)", this->reconnect_ ? "true" : "false"); pServer->advertiseOnDisconnect(this->reconnect_); bleKeyboard.releaseAll(); } void Esp32BleKeyboard::stop() { + ESP_LOGI("ble", "stop()"); if (this->reconnect_) { + ESP_LOGI("ble", "advertiseOnDisconnect(false)"); pServer->advertiseOnDisconnect(false); } @@ -43,7 +46,9 @@ void Esp32BleKeyboard::stop() { } void Esp32BleKeyboard::start() { + ESP_LOGI("ble", "start()"); if (this->reconnect_) { + ESP_LOGI("ble", "advertiseOnDisconnect(true)"); pServer->advertiseOnDisconnect(true); } @@ -111,4 +116,4 @@ void Esp32BleKeyboard::release() { } // namespace ble_keyboard } // namespace esphome -#endif \ No newline at end of file +#endif From 483880a906bf363145436127447ada77d465b53e Mon Sep 17 00:00:00 2001 From: "Manuel Amador (Rudd-O)" Date: Sun, 12 Mar 2023 20:23:50 +0000 Subject: [PATCH 2/7] Add advertise on start option. --- README.md | 2 ++ components/ble_keyboard/__init__.py | 3 +++ components/ble_keyboard/ble_keyboard.cpp | 15 ++++++++++----- components/ble_keyboard/ble_keyboard.h | 4 +++- components/ble_keyboard/const.py | 1 + 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e7d7953..9c876dd 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ ble_keyboard: manufacturer_id: "MamonTech" battery_level: 50 reconnect: true + advertise_on_start: true buttons: true use_default_libs: false ``` @@ -73,6 +74,7 @@ ble_keyboard: * **manufacturer_id** (Optional, string): Keyboard manufacturer (default: Esp32BleKeyboard); * **battery_level** (Optional, int): Keyboard battery level (default: 100); * **reconnect** (Optional, bool): Automatic reconnect service after disconnecting the device. (default: true); +* **advertise_on_start** (Optional, bool): Automatic advertisement when the ESP device starts. (default: true); * **buttons** (Optional, bool): Whether to add separate buttons for [keys](https://github.com/dmamontov/esphome-blekeyboard/wiki/Keys) (default: true); * **use_default_libs** (Optional, bool): Whether to use the arduino standard library. (default: false). diff --git a/components/ble_keyboard/__init__.py b/components/ble_keyboard/__init__.py index 2e79757..8ff8419 100644 --- a/components/ble_keyboard/__init__.py +++ b/components/ble_keyboard/__init__.py @@ -42,6 +42,7 @@ CONF_BUTTONS, CONF_KEYS, CONF_RECONNECT, + CONF_ADVERTISE_ON_START, CONF_TEXT, CONF_USE_DEFAULT_LIBS, DOMAIN, @@ -66,6 +67,7 @@ cv.Optional(CONF_MANUFACTURER_ID, default=COMPONENT_CLASS): cv.Length(min=1), cv.Optional(CONF_BATTERY_LEVEL, default=100): cv.int_range(min=0, max=100), cv.Optional(CONF_RECONNECT, default=True): cv.boolean, + cv.Optional(CONF_ADVERTISE_ON_START, default=True): cv.boolean, cv.Optional(CONF_USE_DEFAULT_LIBS, default=False): cv.boolean, cv.Optional(CONF_BUTTONS, default=True): cv.boolean, } @@ -90,6 +92,7 @@ async def to_code(config: dict) -> None: config[CONF_MANUFACTURER_ID], config[CONF_BATTERY_LEVEL], config[CONF_RECONNECT], + config[CONF_ADVERTISE_ON_START], ) await cg.register_component(var, config) diff --git a/components/ble_keyboard/ble_keyboard.cpp b/components/ble_keyboard/ble_keyboard.cpp index 68ebddc..d2de64e 100644 --- a/components/ble_keyboard/ble_keyboard.cpp +++ b/components/ble_keyboard/ble_keyboard.cpp @@ -21,16 +21,21 @@ void Esp32BleKeyboard::setup() { pServer = BLEDevice::getServer(); - ESP_LOGI("ble", "advertiseOnDisconnect(%s)", this->reconnect_ ? "true" : "false"); + ESP_LOGD(TAG, "advertiseOnDisconnect(%s)", this->reconnect_ ? "true" : "false"); pServer->advertiseOnDisconnect(this->reconnect_); + if (!this->advertise_on_start_) { + ESP_LOGD(TAG, "stopAdvertising()"); + pServer->stopAdvertising(); + } + bleKeyboard.releaseAll(); } void Esp32BleKeyboard::stop() { - ESP_LOGI("ble", "stop()"); + ESP_LOGD("ble", "stop()"); if (this->reconnect_) { - ESP_LOGI("ble", "advertiseOnDisconnect(false)"); + ESP_LOGD(TAG, "advertiseOnDisconnect(false)"); pServer->advertiseOnDisconnect(false); } @@ -46,9 +51,9 @@ void Esp32BleKeyboard::stop() { } void Esp32BleKeyboard::start() { - ESP_LOGI("ble", "start()"); + ESP_LOGD(TAG, "start()"); if (this->reconnect_) { - ESP_LOGI("ble", "advertiseOnDisconnect(true)"); + ESP_LOGD(TAG, "advertiseOnDisconnect(true)"); pServer->advertiseOnDisconnect(true); } diff --git a/components/ble_keyboard/ble_keyboard.h b/components/ble_keyboard/ble_keyboard.h index c575f1f..08bee4b 100644 --- a/components/ble_keyboard/ble_keyboard.h +++ b/components/ble_keyboard/ble_keyboard.h @@ -12,9 +12,10 @@ namespace esphome { namespace ble_keyboard { class Esp32BleKeyboard : public PollingComponent { public: - Esp32BleKeyboard(std::string name, std::string manufacturer_id, uint8_t battery_level, bool reconnect) + Esp32BleKeyboard(std::string name, std::string manufacturer_id, uint8_t battery_level, bool reconnect, bool advertise_on_start) : PollingComponent(1000), bleKeyboard(name, manufacturer_id, battery_level) { reconnect_ = reconnect; + advertise_on_start_ = advertise_on_start; } void setup() override; @@ -47,6 +48,7 @@ class Esp32BleKeyboard : public PollingComponent { BleKeyboard bleKeyboard; bool reconnect_{true}; + bool advertise_on_start_{true}; uint32_t default_delay_{100}; uint32_t release_delay_{8}; }; diff --git a/components/ble_keyboard/const.py b/components/ble_keyboard/const.py index 1f20b16..53e9fc8 100644 --- a/components/ble_keyboard/const.py +++ b/components/ble_keyboard/const.py @@ -37,6 +37,7 @@ CONF_TEXT: Final = "text" CONF_KEYS: Final = "keys" CONF_RECONNECT: Final = "reconnect" +CONF_ADVERTISE_ON_START: Final = "advertise_on_start" CONF_BUTTONS: Final = "buttons" CONF_USE_DEFAULT_LIBS: Final = "use_default_libs" From 0afb63ea85413996331c4d2c614c0632f0728f65 Mon Sep 17 00:00:00 2001 From: "Manuel Amador (Rudd-O)" Date: Sun, 12 Mar 2023 20:35:21 +0000 Subject: [PATCH 3/7] Document option. --- README.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/README.md b/README.md index 9c876dd..7d1d03c 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,45 @@ ble_keyboard: * **buttons** (Optional, bool): Whether to add separate buttons for [keys](https://github.com/dmamontov/esphome-blekeyboard/wiki/Keys) (default: true); * **use_default_libs** (Optional, bool): Whether to use the arduino standard library. (default: false). +#### Controlling keyboard availability when `advertise_on_start` is `False` + +By default, the keyboard advertises its existence on start. You can turn +this off, but this creates a problem — how to ensure that the keyboard +is available on demand? + +In your ESP description, you can create a switch that does exactly that: + +``` +globals: + - id: keyboard_enabled + type: bool + restore_value: no + initial_value: "false" + +switch: + - platform: template + name: Enabled + icon: mdi:power + lambda: |- + if (id(keyboard_enabled)) { + return true; + } else { + return false; + } + turn_on_action: + - ble_keyboard.start: le_keyboard + - lambda: |- + id(keyboard_enabled) = true; + turn_off_action: + - ble_keyboard.stop: le_keyboard + - lambda: |- + id(keyboard_enabled) = false; +``` + +When toggled on, the switch will start the keyboard and begin advertising +it. When toggled off, the keyboard will disconnect all clients and stop +advertising — ensuring clients cannot reconnect. + ### Actions #### ble_keyboard.print From 8040eecdddeb55073cc98240da980fba380b5919 Mon Sep 17 00:00:00 2001 From: "Manuel Amador (Rudd-O)" Date: Wed, 2 Aug 2023 23:08:20 +0000 Subject: [PATCH 4/7] Work around issue with ESPHome 2023.7.0. Fixed in 2023.7.1. --- components/ble_keyboard/ble_keyboard.cpp | 40 +++++++++++++++++++++--- components/ble_keyboard/ble_keyboard.h | 4 ++- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/components/ble_keyboard/ble_keyboard.cpp b/components/ble_keyboard/ble_keyboard.cpp index d2de64e..b93e3f3 100644 --- a/components/ble_keyboard/ble_keyboard.cpp +++ b/components/ble_keyboard/ble_keyboard.cpp @@ -15,25 +15,37 @@ namespace ble_keyboard { static const char *const TAG = "ble_keyboard"; void Esp32BleKeyboard::setup() { - ESP_LOGI(TAG, "Setting up..."); + if (this->setup_) { + ESP_LOGW(TAG, "BLE keyboard already setup."); + return; + } + + ESP_LOGCONFIG(TAG, "Setting up BLE keyboard..."); bleKeyboard.begin(); pServer = BLEDevice::getServer(); - ESP_LOGD(TAG, "advertiseOnDisconnect(%s)", this->reconnect_ ? "true" : "false"); + ESP_LOGCONFIG(TAG, "advertiseOnDisconnect(%s)", this->reconnect_ ? "true" : "false"); pServer->advertiseOnDisconnect(this->reconnect_); if (!this->advertise_on_start_) { - ESP_LOGD(TAG, "stopAdvertising()"); + ESP_LOGCONFIG(TAG, "stopAdvertising() because advertise_on_start is false"); pServer->stopAdvertising(); } bleKeyboard.releaseAll(); + this->setup_ = true; + ESP_LOGCONFIG(TAG, "Finished setting up up BLE keyboard."); } void Esp32BleKeyboard::stop() { - ESP_LOGD("ble", "stop()"); + if (!this->setup_) { + ESP_LOGW(TAG, "Attempting to use without setup. Not doing anything."); + return; + } + + ESP_LOGD(TAG, "stop()"); if (this->reconnect_) { ESP_LOGD(TAG, "advertiseOnDisconnect(false)"); pServer->advertiseOnDisconnect(false); @@ -51,6 +63,10 @@ void Esp32BleKeyboard::stop() { } void Esp32BleKeyboard::start() { + if (!this->setup_) { + ESP_LOGW(TAG, "Attempting to use without setup. Not doing anything."); + return; + } ESP_LOGD(TAG, "start()"); if (this->reconnect_) { ESP_LOGD(TAG, "advertiseOnDisconnect(true)"); @@ -78,6 +94,10 @@ void Esp32BleKeyboard::update_timer() { } void Esp32BleKeyboard::press(std::string message) { + if (!this->setup_) { + ESP_LOGW(TAG, "Attempting to use without setup. Not doing anything."); + return; + } if (this->is_connected()) { if (message.length() >= 5) { for (unsigned i = 0; i < message.length(); i += 5) { @@ -94,6 +114,10 @@ void Esp32BleKeyboard::press(std::string message) { } void Esp32BleKeyboard::press(uint8_t key, bool with_timer) { + if (!this->setup_) { + ESP_LOGW(TAG, "Attempting to use without setup. Not doing anything."); + return; + } if (this->is_connected()) { if (with_timer) { this->update_timer(); @@ -104,6 +128,10 @@ void Esp32BleKeyboard::press(uint8_t key, bool with_timer) { } void Esp32BleKeyboard::press(MediaKeyReport key, bool with_timer) { + if (!this->setup_) { + ESP_LOGW(TAG, "Attempting to use without setup. Not doing anything."); + return; + } if (this->is_connected()) { if (with_timer) { this->update_timer(); @@ -113,6 +141,10 @@ void Esp32BleKeyboard::press(MediaKeyReport key, bool with_timer) { } void Esp32BleKeyboard::release() { + if (!this->setup_) { + ESP_LOGW(TAG, "Attempting to use without setup. Not doing anything."); + return; + } if (this->is_connected()) { this->cancel_timeout((const std::string) TAG); bleKeyboard.releaseAll(); diff --git a/components/ble_keyboard/ble_keyboard.h b/components/ble_keyboard/ble_keyboard.h index 08bee4b..d3580ce 100644 --- a/components/ble_keyboard/ble_keyboard.h +++ b/components/ble_keyboard/ble_keyboard.h @@ -12,7 +12,8 @@ namespace esphome { namespace ble_keyboard { class Esp32BleKeyboard : public PollingComponent { public: - Esp32BleKeyboard(std::string name, std::string manufacturer_id, uint8_t battery_level, bool reconnect, bool advertise_on_start) + Esp32BleKeyboard(std::string name, std::string manufacturer_id, uint8_t battery_level, bool reconnect, + bool advertise_on_start) : PollingComponent(1000), bleKeyboard(name, manufacturer_id, battery_level) { reconnect_ = reconnect; advertise_on_start_ = advertise_on_start; @@ -47,6 +48,7 @@ class Esp32BleKeyboard : public PollingComponent { BLEServer *pServer; BleKeyboard bleKeyboard; + bool setup_{false}; bool reconnect_{true}; bool advertise_on_start_{true}; uint32_t default_delay_{100}; From b598b36b4942fef49020948c4742bf35a637cfa2 Mon Sep 17 00:00:00 2001 From: Rudd-O Date: Fri, 23 Feb 2024 03:22:36 +0000 Subject: [PATCH 5/7] Globals set in README Co-authored-by: Johannes Dilli --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d1d03c..ac4b745 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,9 @@ switch: id(keyboard_enabled) = true; turn_off_action: - ble_keyboard.stop: le_keyboard - - lambda: |- + - globals.set: + id: keyboard_enabled + value: "false" id(keyboard_enabled) = false; ``` From 66618877012899e87ad7ba07ddaf20e9d2467f2d Mon Sep 17 00:00:00 2001 From: Rudd-O Date: Fri, 23 Feb 2024 03:22:44 +0000 Subject: [PATCH 6/7] Globals set in README Co-authored-by: Johannes Dilli --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ac4b745..e8edbcf 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,9 @@ switch: } turn_on_action: - ble_keyboard.start: le_keyboard - - lambda: |- + - globals.set: + id: keyboard_enabled + value: "true" id(keyboard_enabled) = true; turn_off_action: - ble_keyboard.stop: le_keyboard From b81ddd0175f468b314e58aa7e21942ab1c1604ea Mon Sep 17 00:00:00 2001 From: Rudd-O Date: Fri, 23 Feb 2024 03:23:09 +0000 Subject: [PATCH 7/7] Simplify lambda in README Co-authored-by: Johannes Dilli --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e8edbcf..6a6af81 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ switch: name: Enabled icon: mdi:power lambda: |- - if (id(keyboard_enabled)) { + return id(keyboard_enabled); return true; } else { return false;