diff --git a/README.md b/README.md index e7d7953..e08259d 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,13 @@ ble_keyboard: reconnect: true buttons: true use_default_libs: false + rssi: + name: "RSSI" + filters: + - filter_out: NAN + - sliding_window_moving_average: + window_size: 60 + send_every: 60 ``` * **id** (Optional, string): Component ID. Needed for action; @@ -75,6 +82,7 @@ ble_keyboard: * **reconnect** (Optional, bool): Automatic reconnect service after disconnecting the device. (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). +* **rssi** (Optional, [Sensor](https://esphome.io/components/sensor/index.html)): Adds a signal strength sensor configuration. Note that it updates every seconds, so it's best to add a filter to not spam Home Assistant. ### Actions diff --git a/components/ble_keyboard/__init__.py b/components/ble_keyboard/__init__.py index 2e79757..e00903e 100644 --- a/components/ble_keyboard/__init__.py +++ b/components/ble_keyboard/__init__.py @@ -8,7 +8,7 @@ import esphome.config_validation as cv from esphome import automation from esphome.automation import maybe_simple_id -from esphome.components import binary_sensor, button, number +from esphome.components import binary_sensor, button, number, sensor from esphome.const import ( CONF_BATTERY_LEVEL, CONF_CODE, @@ -44,14 +44,16 @@ CONF_RECONNECT, CONF_TEXT, CONF_USE_DEFAULT_LIBS, + CONF_RSSI, DOMAIN, LIBS_ADDITIONAL, LIBS_DEFAULT, NUMBERS, + RSSI_SENSOR_SCHEMA, ) CODEOWNERS: Final = ["@dmamontov"] -AUTO_LOAD: Final = ["binary_sensor", "number", "button"] +AUTO_LOAD: Final = ["binary_sensor", "number", "button", "sensor"] ble_keyboard_ns = cg.esphome_ns.namespace(DOMAIN) @@ -68,6 +70,7 @@ cv.Optional(CONF_RECONNECT, default=True): cv.boolean, cv.Optional(CONF_USE_DEFAULT_LIBS, default=False): cv.boolean, cv.Optional(CONF_BUTTONS, default=True): cv.boolean, + cv.Optional(CONF_RSSI): RSSI_SENSOR_SCHEMA, } ) @@ -96,6 +99,7 @@ async def to_code(config: dict) -> None: await adding_binary_sensors(var) await adding_numbers(var) + await adding_sensors(var, config) if config[CONF_BUTTONS]: await adding_buttons(var) @@ -157,6 +161,17 @@ async def adding_binary_sensors(var: MockObj) -> None: var.set_state_sensor(await binary_sensor.new_binary_sensor(BINARY_SENSOR_STATE)) ) +async def adding_sensors(var: MockObj, config: dict) -> None: + """Adding sensors + + :param var: MockObj + """ + + + if CONF_RSSI in config: + cg.add( + var.set_rssi_sensor(await sensor.new_sensor(config[CONF_RSSI])) + ) def adding_dependencies(use_default_libs: bool = True) -> None: """Adding dependencies diff --git a/components/ble_keyboard/ble_keyboard.cpp b/components/ble_keyboard/ble_keyboard.cpp index 178d316..eac9c57 100644 --- a/components/ble_keyboard/ble_keyboard.cpp +++ b/components/ble_keyboard/ble_keyboard.cpp @@ -50,7 +50,26 @@ void Esp32BleKeyboard::start() { pServer->startAdvertising(); } -void Esp32BleKeyboard::update() { state_sensor_->publish_state(bleKeyboard.isConnected()); } +void Esp32BleKeyboard::update() { + state_sensor_->publish_state(bleKeyboard.isConnected()); + if (rssi_sensor_ == nullptr) return; + if (bleKeyboard.isConnected()) { + std::vector ids = pServer->getPeerDevices(); + + for (uint16_t &id : ids) { + int8_t rssiValue = 0; + int rc = ble_gap_conn_rssi(id, &rssiValue); + if(rc != 0) { + ESP_LOGE(TAG, "Failed to read RSSI error code: %d (connection: %i)", + rc, id); + } else { + rssi_sensor_->publish_state(rssiValue); + } + } + } else { + rssi_sensor_->publish_state(NAN); + } +} bool Esp32BleKeyboard::is_connected() { if (!bleKeyboard.isConnected()) { diff --git a/components/ble_keyboard/ble_keyboard.h b/components/ble_keyboard/ble_keyboard.h index c575f1f..a4fb110 100644 --- a/components/ble_keyboard/ble_keyboard.h +++ b/components/ble_keyboard/ble_keyboard.h @@ -4,6 +4,7 @@ #include "esphome/core/component.h" #include "esphome/components/binary_sensor/binary_sensor.h" +#include "esphome/components/sensor/sensor.h" #include #include #include @@ -27,6 +28,7 @@ class Esp32BleKeyboard : public PollingComponent { void set_battery_level(uint8_t level = 100) { bleKeyboard.setBatteryLevel(level); }; void set_state_sensor(binary_sensor::BinarySensor *state_sensor) { state_sensor_ = state_sensor; } + void set_rssi_sensor(sensor::Sensor *rssi_sensor) { rssi_sensor_ = rssi_sensor; } void press(std::string message); void press(uint8_t key, bool with_timer = true); @@ -38,6 +40,7 @@ class Esp32BleKeyboard : public PollingComponent { protected: binary_sensor::BinarySensor *state_sensor_; + sensor::Sensor *rssi_sensor_{nullptr}; private: bool is_connected(); diff --git a/components/ble_keyboard/const.py b/components/ble_keyboard/const.py index 1f20b16..0d0f12a 100644 --- a/components/ble_keyboard/const.py +++ b/components/ble_keyboard/const.py @@ -7,12 +7,13 @@ from typing import Final import esphome.config_validation as cv -from esphome.components import binary_sensor +from esphome.components import binary_sensor, sensor from esphome.components.number import NumberMode from esphome.const import ( CONF_DEVICE_CLASS, CONF_DISABLED_BY_DEFAULT, CONF_ENTITY_CATEGORY, + CONF_FORCE_UPDATE, CONF_ICON, CONF_ID, CONF_INITIAL_VALUE, @@ -27,7 +28,11 @@ CONF_UNIT_OF_MEASUREMENT, CONF_VALUE, DEVICE_CLASS_CONNECTIVITY, + DEVICE_CLASS_SIGNAL_STRENGTH, ENTITY_CATEGORY_CONFIG, + ENTITY_CATEGORY_DIAGNOSTIC, + STATE_CLASS_MEASUREMENT, + UNIT_DECIBEL_MILLIWATT, UNIT_MILLISECOND, UNIT_PERCENT, ) @@ -39,6 +44,7 @@ CONF_RECONNECT: Final = "reconnect" CONF_BUTTONS: Final = "buttons" CONF_USE_DEFAULT_LIBS: Final = "use_default_libs" +CONF_RSSI: Final = "rssi" COMPONENT_CLASS: Final = "Esp32BleKeyboard" COMPONENT_NUMBER_CLASS: Final = "Esp32BleKeyboardNumber" @@ -79,6 +85,19 @@ CONF_DISABLED_BY_DEFAULT: False, } +"""Sensors""" +RSSI_SENSOR_SCHEMA: Final = sensor.sensor_schema( + accuracy_decimals=0, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + state_class=STATE_CLASS_MEASUREMENT, + device_class=DEVICE_CLASS_SIGNAL_STRENGTH, + unit_of_measurement=UNIT_DECIBEL_MILLIWATT, + ).extend( + { + cv.Optional(CONF_NAME, default="RSSI"): cv.string, + } + ) + """Numbers""" TYPE_PRESS: Final = 0 TYPE_RELEASE: Final = 1 diff --git a/examples/esp32.yaml b/examples/esp32.yaml index f1bffca..5bf31f0 100644 --- a/examples/esp32.yaml +++ b/examples/esp32.yaml @@ -64,6 +64,8 @@ ble_keyboard: reconnect: true battery_level: 50 buttons: true + rssi: + name: "RSSI" text_sensor: - platform: homeassistant diff --git a/examples/esp32c3.yaml b/examples/esp32c3.yaml index 9cd527f..eadea37 100644 --- a/examples/esp32c3.yaml +++ b/examples/esp32c3.yaml @@ -72,6 +72,8 @@ ble_keyboard: reconnect: true battery_level: 50 buttons: true + rssi: + name: "RSSI" text_sensor: - platform: homeassistant