From 38efb0fa425fe829c9f9f4468b56078ab3f4a80b Mon Sep 17 00:00:00 2001 From: Mikhail Diatchenko Date: Sat, 25 Feb 2023 11:42:24 +1300 Subject: [PATCH 1/6] Added RSSI sensor --- components/ble_keyboard/__init__.py | 15 +++++++++++++-- components/ble_keyboard/ble_keyboard.cpp | 19 ++++++++++++++++++- components/ble_keyboard/ble_keyboard.h | 3 +++ components/ble_keyboard/const.py | 13 ++++++++++++- 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/components/ble_keyboard/__init__.py b/components/ble_keyboard/__init__.py index 2e79757..a814d5b 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, @@ -34,6 +34,7 @@ ACTION_START_CLASS, ACTION_STOP_CLASS, BINARY_SENSOR_STATE, + RSSI_SENSOR_STATE, BUILD_FLAGS, BUTTONS_KEY, COMPONENT_BUTTON_CLASS, @@ -51,7 +52,7 @@ ) 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) @@ -96,6 +97,7 @@ async def to_code(config: dict) -> None: await adding_binary_sensors(var) await adding_numbers(var) + await adding_sensors(var) if config[CONF_BUTTONS]: await adding_buttons(var) @@ -157,6 +159,15 @@ 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) -> None: + """Adding sensor + + :param var: MockObj + """ + + cg.add( + var.set_rssi_sensor(await sensor.new_sensor(RSSI_SENSOR_STATE)) + ) 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..9f5bb27 100644 --- a/components/ble_keyboard/ble_keyboard.cpp +++ b/components/ble_keyboard/ble_keyboard.cpp @@ -50,7 +50,24 @@ void Esp32BleKeyboard::start() { pServer->startAdvertising(); } -void Esp32BleKeyboard::update() { state_sensor_->publish_state(bleKeyboard.isConnected()); } +void Esp32BleKeyboard::update() { state_sensor_->publish_state(bleKeyboard.isConnected()); + 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..f7c72e0 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_; private: bool is_connected(); diff --git a/components/ble_keyboard/const.py b/components/ble_keyboard/const.py index 1f20b16..214405c 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,6 +28,7 @@ CONF_UNIT_OF_MEASUREMENT, CONF_VALUE, DEVICE_CLASS_CONNECTIVITY, + DEVICE_CLASS_SIGNAL_STRENGTH, ENTITY_CATEGORY_CONFIG, UNIT_MILLISECOND, UNIT_PERCENT, @@ -79,6 +81,15 @@ CONF_DISABLED_BY_DEFAULT: False, } +"""Sensors""" +RSSI_SENSOR_STATE: Final = { + CONF_ID: cv.declare_id(sensor.Sensor)("rssi"), + CONF_NAME: "RSSI", + CONF_DEVICE_CLASS: DEVICE_CLASS_SIGNAL_STRENGTH, + CONF_DISABLED_BY_DEFAULT: True, + CONF_FORCE_UPDATE: False, +} + """Numbers""" TYPE_PRESS: Final = 0 TYPE_RELEASE: Final = 1 From 7830275fa468830809d47b22bf93b3052bff4e4b Mon Sep 17 00:00:00 2001 From: Mikhail Diatchenko Date: Sat, 25 Feb 2023 12:49:04 +1300 Subject: [PATCH 2/6] Added configuration for the rssi sensor --- components/ble_keyboard/__init__.py | 21 +++++++++++++++------ components/ble_keyboard/const.py | 19 ++++++++++++++++++- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/components/ble_keyboard/__init__.py b/components/ble_keyboard/__init__.py index a814d5b..527a3f7 100644 --- a/components/ble_keyboard/__init__.py +++ b/components/ble_keyboard/__init__.py @@ -45,10 +45,12 @@ CONF_RECONNECT, CONF_TEXT, CONF_USE_DEFAULT_LIBS, + CONF_RSSI, DOMAIN, LIBS_ADDITIONAL, LIBS_DEFAULT, NUMBERS, + RSSI_SENSOR_SCHEMA, ) CODEOWNERS: Final = ["@dmamontov"] @@ -69,6 +71,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, } ) @@ -97,7 +100,7 @@ async def to_code(config: dict) -> None: await adding_binary_sensors(var) await adding_numbers(var) - await adding_sensors(var) + await adding_sensors(var, config) if config[CONF_BUTTONS]: await adding_buttons(var) @@ -159,15 +162,21 @@ 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) -> None: - """Adding sensor +async def adding_sensors(var: MockObj, config: dict) -> None: + """Adding sensors :param var: MockObj """ - cg.add( - var.set_rssi_sensor(await sensor.new_sensor(RSSI_SENSOR_STATE)) - ) + + if CONF_RSSI in config: + cg.add( + var.set_rssi_sensor(await sensor.new_sensor(config[CONF_RSSI])) + ) + else: + cg.add( + var.set_rssi_sensor(await sensor.new_sensor(RSSI_SENSOR_STATE)) + ) def adding_dependencies(use_default_libs: bool = True) -> None: """Adding dependencies diff --git a/components/ble_keyboard/const.py b/components/ble_keyboard/const.py index 214405c..ab975ff 100644 --- a/components/ble_keyboard/const.py +++ b/components/ble_keyboard/const.py @@ -30,6 +30,9 @@ DEVICE_CLASS_CONNECTIVITY, DEVICE_CLASS_SIGNAL_STRENGTH, ENTITY_CATEGORY_CONFIG, + ENTITY_CATEGORY_DIAGNOSTIC, + STATE_CLASS_MEASUREMENT, + UNIT_DECIBEL_MILLIWATT, UNIT_MILLISECOND, UNIT_PERCENT, ) @@ -41,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" @@ -82,8 +86,21 @@ } """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, + cv.Optional(CONF_DISABLED_BY_DEFAULT, default=True): cv.boolean, + } + ) + RSSI_SENSOR_STATE: Final = { - CONF_ID: cv.declare_id(sensor.Sensor)("rssi"), + CONF_ID: cv.declare_id(sensor.Sensor)(CONF_RSSI), CONF_NAME: "RSSI", CONF_DEVICE_CLASS: DEVICE_CLASS_SIGNAL_STRENGTH, CONF_DISABLED_BY_DEFAULT: True, From 2867a86ce08711732f1c5f12723116033f315bb7 Mon Sep 17 00:00:00 2001 From: Mikhail Diatchenko Date: Sat, 25 Feb 2023 13:06:58 +1300 Subject: [PATCH 3/6] Removed default rssi sensor --- components/ble_keyboard/__init__.py | 5 ----- components/ble_keyboard/ble_keyboard.cpp | 4 +++- components/ble_keyboard/ble_keyboard.h | 2 +- components/ble_keyboard/const.py | 8 -------- 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/components/ble_keyboard/__init__.py b/components/ble_keyboard/__init__.py index 527a3f7..e00903e 100644 --- a/components/ble_keyboard/__init__.py +++ b/components/ble_keyboard/__init__.py @@ -34,7 +34,6 @@ ACTION_START_CLASS, ACTION_STOP_CLASS, BINARY_SENSOR_STATE, - RSSI_SENSOR_STATE, BUILD_FLAGS, BUTTONS_KEY, COMPONENT_BUTTON_CLASS, @@ -173,10 +172,6 @@ async def adding_sensors(var: MockObj, config: dict) -> None: cg.add( var.set_rssi_sensor(await sensor.new_sensor(config[CONF_RSSI])) ) - else: - cg.add( - var.set_rssi_sensor(await sensor.new_sensor(RSSI_SENSOR_STATE)) - ) 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 9f5bb27..eac9c57 100644 --- a/components/ble_keyboard/ble_keyboard.cpp +++ b/components/ble_keyboard/ble_keyboard.cpp @@ -50,7 +50,9 @@ 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(); diff --git a/components/ble_keyboard/ble_keyboard.h b/components/ble_keyboard/ble_keyboard.h index f7c72e0..a4fb110 100644 --- a/components/ble_keyboard/ble_keyboard.h +++ b/components/ble_keyboard/ble_keyboard.h @@ -40,7 +40,7 @@ class Esp32BleKeyboard : public PollingComponent { protected: binary_sensor::BinarySensor *state_sensor_; - sensor::Sensor *rssi_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 ab975ff..b37c860 100644 --- a/components/ble_keyboard/const.py +++ b/components/ble_keyboard/const.py @@ -99,14 +99,6 @@ } ) -RSSI_SENSOR_STATE: Final = { - CONF_ID: cv.declare_id(sensor.Sensor)(CONF_RSSI), - CONF_NAME: "RSSI", - CONF_DEVICE_CLASS: DEVICE_CLASS_SIGNAL_STRENGTH, - CONF_DISABLED_BY_DEFAULT: True, - CONF_FORCE_UPDATE: False, -} - """Numbers""" TYPE_PRESS: Final = 0 TYPE_RELEASE: Final = 1 From 9d4149003daafba94c8ce6e3962695be1e49b518 Mon Sep 17 00:00:00 2001 From: Mikhail Diatchenko Date: Sat, 25 Feb 2023 13:07:14 +1300 Subject: [PATCH 4/6] Added rssi sensor documentation --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) 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 From dcff1c8fe78ea89901d93030a673e8936643eb96 Mon Sep 17 00:00:00 2001 From: Mikhail Diatchenko Date: Sat, 25 Feb 2023 13:18:53 +1300 Subject: [PATCH 5/6] Not disabling rssi sensor by default (since the sensor needs to be explicitly added to be exposed) --- components/ble_keyboard/const.py | 1 - 1 file changed, 1 deletion(-) diff --git a/components/ble_keyboard/const.py b/components/ble_keyboard/const.py index b37c860..0d0f12a 100644 --- a/components/ble_keyboard/const.py +++ b/components/ble_keyboard/const.py @@ -95,7 +95,6 @@ ).extend( { cv.Optional(CONF_NAME, default="RSSI"): cv.string, - cv.Optional(CONF_DISABLED_BY_DEFAULT, default=True): cv.boolean, } ) From 1882de17ed43587f1eaca3b8db9ceaa13f3ac352 Mon Sep 17 00:00:00 2001 From: Mikhail Diatchenko Date: Sat, 25 Feb 2023 13:23:08 +1300 Subject: [PATCH 6/6] Added rssi to examples --- examples/esp32.yaml | 2 ++ examples/esp32c3.yaml | 2 ++ 2 files changed, 4 insertions(+) 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