diff --git a/README.md b/README.md index e7d7953..6a6af81 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,9 +74,53 @@ 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). +#### 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: |- + return id(keyboard_enabled); + return true; + } else { + return false; + } + turn_on_action: + - ble_keyboard.start: le_keyboard + - globals.set: + id: keyboard_enabled + value: "true" + id(keyboard_enabled) = true; + turn_off_action: + - ble_keyboard.stop: le_keyboard + - globals.set: + id: keyboard_enabled + value: "false" + 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 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 178d316..b93e3f3 100644 --- a/components/ble_keyboard/ble_keyboard.cpp +++ b/components/ble_keyboard/ble_keyboard.cpp @@ -15,19 +15,39 @@ 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_LOGCONFIG(TAG, "advertiseOnDisconnect(%s)", this->reconnect_ ? "true" : "false"); pServer->advertiseOnDisconnect(this->reconnect_); + if (!this->advertise_on_start_) { + 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() { + 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); } @@ -43,7 +63,13 @@ 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)"); pServer->advertiseOnDisconnect(true); } @@ -68,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) { @@ -84,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(); @@ -94,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(); @@ -103,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(); @@ -111,4 +153,4 @@ void Esp32BleKeyboard::release() { } // namespace ble_keyboard } // namespace esphome -#endif \ No newline at end of file +#endif diff --git a/components/ble_keyboard/ble_keyboard.h b/components/ble_keyboard/ble_keyboard.h index c575f1f..d3580ce 100644 --- a/components/ble_keyboard/ble_keyboard.h +++ b/components/ble_keyboard/ble_keyboard.h @@ -12,9 +12,11 @@ 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; @@ -46,7 +48,9 @@ class Esp32BleKeyboard : public PollingComponent { BLEServer *pServer; BleKeyboard bleKeyboard; + bool setup_{false}; 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"