mirror of
https://github.com/esphome/esphome.git
synced 2024-11-10 09:17:46 +01:00
Add ble RSSI sensor for connected devices (#3860)
This commit is contained in:
parent
19900b004b
commit
9f9980e338
6 changed files with 197 additions and 25 deletions
|
@ -64,6 +64,13 @@ void BLEClient::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t es
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BLEClient::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
|
||||||
|
BLEClientBase::gap_event_handler(event, param);
|
||||||
|
|
||||||
|
for (auto *node : this->nodes_)
|
||||||
|
node->gap_event_handler(event, param);
|
||||||
|
}
|
||||||
|
|
||||||
void BLEClient::set_state(espbt::ClientState state) {
|
void BLEClient::set_state(espbt::ClientState state) {
|
||||||
BLEClientBase::set_state(state);
|
BLEClientBase::set_state(state);
|
||||||
for (auto &node : nodes_)
|
for (auto &node : nodes_)
|
||||||
|
|
|
@ -27,7 +27,8 @@ class BLEClientNode {
|
||||||
public:
|
public:
|
||||||
virtual void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
|
virtual void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
|
||||||
esp_ble_gattc_cb_param_t *param) = 0;
|
esp_ble_gattc_cb_param_t *param) = 0;
|
||||||
virtual void loop(){};
|
virtual void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {}
|
||||||
|
virtual void loop() {}
|
||||||
void set_address(uint64_t address) { address_ = address; }
|
void set_address(uint64_t address) { address_ = address; }
|
||||||
espbt::ESPBTClient *client;
|
espbt::ESPBTClient *client;
|
||||||
// This should be transitioned to Established once the node no longer needs
|
// This should be transitioned to Established once the node no longer needs
|
||||||
|
@ -51,6 +52,8 @@ class BLEClient : public BLEClientBase {
|
||||||
|
|
||||||
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
|
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
|
||||||
esp_ble_gattc_cb_param_t *param) override;
|
esp_ble_gattc_cb_param_t *param) override;
|
||||||
|
|
||||||
|
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override;
|
||||||
bool parse_device(const espbt::ESPBTDevice &device) override;
|
bool parse_device(const espbt::ESPBTDevice &device) override;
|
||||||
|
|
||||||
void set_enabled(bool enabled);
|
void set_enabled(bool enabled);
|
||||||
|
|
|
@ -5,7 +5,11 @@ from esphome.const import (
|
||||||
CONF_CHARACTERISTIC_UUID,
|
CONF_CHARACTERISTIC_UUID,
|
||||||
CONF_LAMBDA,
|
CONF_LAMBDA,
|
||||||
CONF_TRIGGER_ID,
|
CONF_TRIGGER_ID,
|
||||||
|
CONF_TYPE,
|
||||||
CONF_SERVICE_UUID,
|
CONF_SERVICE_UUID,
|
||||||
|
DEVICE_CLASS_SIGNAL_STRENGTH,
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
UNIT_DECIBEL_MILLIWATT,
|
||||||
)
|
)
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
from .. import ble_client_ns
|
from .. import ble_client_ns
|
||||||
|
@ -16,6 +20,8 @@ CONF_DESCRIPTOR_UUID = "descriptor_uuid"
|
||||||
|
|
||||||
CONF_NOTIFY = "notify"
|
CONF_NOTIFY = "notify"
|
||||||
CONF_ON_NOTIFY = "on_notify"
|
CONF_ON_NOTIFY = "on_notify"
|
||||||
|
TYPE_CHARACTERISTIC = "characteristic"
|
||||||
|
TYPE_RSSI = "rssi"
|
||||||
|
|
||||||
adv_data_t = cg.std_vector.template(cg.uint8)
|
adv_data_t = cg.std_vector.template(cg.uint8)
|
||||||
adv_data_t_const_ref = adv_data_t.operator("ref").operator("const")
|
adv_data_t_const_ref = adv_data_t.operator("ref").operator("const")
|
||||||
|
@ -27,33 +33,67 @@ BLESensorNotifyTrigger = ble_client_ns.class_(
|
||||||
"BLESensorNotifyTrigger", automation.Trigger.template(cg.float_)
|
"BLESensorNotifyTrigger", automation.Trigger.template(cg.float_)
|
||||||
)
|
)
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.All(
|
BLEClientRssiSensor = ble_client_ns.class_(
|
||||||
sensor.sensor_schema(
|
"BLEClientRSSISensor", sensor.Sensor, cg.PollingComponent, ble_client.BLEClientNode
|
||||||
BLESensor,
|
|
||||||
accuracy_decimals=0,
|
|
||||||
)
|
|
||||||
.extend(
|
|
||||||
{
|
|
||||||
cv.Required(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid,
|
|
||||||
cv.Required(CONF_CHARACTERISTIC_UUID): esp32_ble_tracker.bt_uuid,
|
|
||||||
cv.Optional(CONF_DESCRIPTOR_UUID): esp32_ble_tracker.bt_uuid,
|
|
||||||
cv.Optional(CONF_LAMBDA): cv.returning_lambda,
|
|
||||||
cv.Optional(CONF_NOTIFY, default=False): cv.boolean,
|
|
||||||
cv.Optional(CONF_ON_NOTIFY): automation.validate_automation(
|
|
||||||
{
|
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
|
||||||
BLESensorNotifyTrigger
|
|
||||||
),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.extend(cv.polling_component_schema("60s"))
|
|
||||||
.extend(ble_client.BLE_CLIENT_SCHEMA)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def to_code(config):
|
def checkType(value):
|
||||||
|
if CONF_TYPE not in value and CONF_SERVICE_UUID in value:
|
||||||
|
raise cv.Invalid(
|
||||||
|
"Looks like you're trying to create a ble characteristic sensor. Please add `type: characteristic` to your sensor config."
|
||||||
|
)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.All(
|
||||||
|
checkType,
|
||||||
|
cv.typed_schema(
|
||||||
|
{
|
||||||
|
TYPE_CHARACTERISTIC: sensor.sensor_schema(
|
||||||
|
BLESensor,
|
||||||
|
accuracy_decimals=0,
|
||||||
|
)
|
||||||
|
.extend(cv.polling_component_schema("60s"))
|
||||||
|
.extend(ble_client.BLE_CLIENT_SCHEMA)
|
||||||
|
.extend(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid,
|
||||||
|
cv.Required(CONF_CHARACTERISTIC_UUID): esp32_ble_tracker.bt_uuid,
|
||||||
|
cv.Optional(CONF_DESCRIPTOR_UUID): esp32_ble_tracker.bt_uuid,
|
||||||
|
cv.Optional(CONF_LAMBDA): cv.returning_lambda,
|
||||||
|
cv.Optional(CONF_NOTIFY, default=False): cv.boolean,
|
||||||
|
cv.Optional(CONF_ON_NOTIFY): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||||
|
BLESensorNotifyTrigger
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
TYPE_RSSI: sensor.sensor_schema(
|
||||||
|
BLEClientRssiSensor,
|
||||||
|
accuracy_decimals=0,
|
||||||
|
unit_of_measurement=UNIT_DECIBEL_MILLIWATT,
|
||||||
|
device_class=DEVICE_CLASS_SIGNAL_STRENGTH,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
)
|
||||||
|
.extend(cv.polling_component_schema("60s"))
|
||||||
|
.extend(ble_client.BLE_CLIENT_SCHEMA),
|
||||||
|
},
|
||||||
|
lower=True,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def rssi_sensor_to_code(config):
|
||||||
|
var = await sensor.new_sensor(config)
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await ble_client.register_ble_node(var, config)
|
||||||
|
|
||||||
|
|
||||||
|
async def characteristic_sensor_to_code(config):
|
||||||
var = await sensor.new_sensor(config)
|
var = await sensor.new_sensor(config)
|
||||||
if len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid16_format):
|
if len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid16_format):
|
||||||
cg.add(
|
cg.add(
|
||||||
|
@ -125,3 +165,10 @@ async def to_code(config):
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
await ble_client.register_ble_node(trigger, config)
|
await ble_client.register_ble_node(trigger, config)
|
||||||
await automation.build_automation(trigger, [(float, "x")], conf)
|
await automation.build_automation(trigger, [(float, "x")], conf)
|
||||||
|
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
if config[CONF_TYPE] == TYPE_RSSI:
|
||||||
|
await rssi_sensor_to_code(config)
|
||||||
|
elif config[CONF_TYPE] == TYPE_CHARACTERISTIC:
|
||||||
|
await characteristic_sensor_to_code(config)
|
||||||
|
|
78
esphome/components/ble_client/sensor/ble_rssi_sensor.cpp
Normal file
78
esphome/components/ble_client/sensor/ble_rssi_sensor.cpp
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
#include "ble_rssi_sensor.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include "esphome/core/application.h"
|
||||||
|
#include "esphome/core/helpers.h"
|
||||||
|
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
|
||||||
|
|
||||||
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ble_client {
|
||||||
|
|
||||||
|
static const char *const TAG = "ble_rssi_sensor";
|
||||||
|
|
||||||
|
void BLEClientRSSISensor::loop() {}
|
||||||
|
|
||||||
|
void BLEClientRSSISensor::dump_config() {
|
||||||
|
LOG_SENSOR("", "BLE Client RSSI Sensor", this);
|
||||||
|
ESP_LOGCONFIG(TAG, " MAC address : %s", this->parent()->address_str().c_str());
|
||||||
|
LOG_UPDATE_INTERVAL(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BLEClientRSSISensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
|
||||||
|
esp_ble_gattc_cb_param_t *param) {
|
||||||
|
switch (event) {
|
||||||
|
case ESP_GATTC_OPEN_EVT: {
|
||||||
|
if (param->open.status == ESP_GATT_OK) {
|
||||||
|
ESP_LOGI(TAG, "[%s] Connected successfully!", this->get_name().c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ESP_GATTC_DISCONNECT_EVT: {
|
||||||
|
ESP_LOGW(TAG, "[%s] Disconnected!", this->get_name().c_str());
|
||||||
|
this->status_set_warning();
|
||||||
|
this->publish_state(NAN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ESP_GATTC_SEARCH_CMPL_EVT:
|
||||||
|
this->node_state = espbt::ClientState::ESTABLISHED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BLEClientRSSISensor::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
|
||||||
|
switch (event) {
|
||||||
|
// server response on RSSI request:
|
||||||
|
case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT:
|
||||||
|
if (param->read_rssi_cmpl.status == ESP_BT_STATUS_SUCCESS) {
|
||||||
|
int8_t rssi = param->read_rssi_cmpl.rssi;
|
||||||
|
ESP_LOGI(TAG, "ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT RSSI: %d", rssi);
|
||||||
|
this->publish_state(rssi);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BLEClientRSSISensor::update() {
|
||||||
|
if (this->node_state != espbt::ClientState::ESTABLISHED) {
|
||||||
|
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGV(TAG, "requesting rssi from %s", this->parent()->address_str().c_str());
|
||||||
|
auto status = esp_ble_gap_read_rssi(this->parent()->get_remote_bda());
|
||||||
|
if (status != ESP_OK) {
|
||||||
|
ESP_LOGW(TAG, "esp_ble_gap_read_rssi error, address=%s, status=%d", this->parent()->address_str().c_str(), status);
|
||||||
|
this->status_set_warning();
|
||||||
|
this->publish_state(NAN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ble_client
|
||||||
|
} // namespace esphome
|
||||||
|
#endif
|
31
esphome/components/ble_client/sensor/ble_rssi_sensor.h
Normal file
31
esphome/components/ble_client/sensor/ble_rssi_sensor.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/ble_client/ble_client.h"
|
||||||
|
#include "esphome/components/esp32_ble_tracker/esp32_ble_tracker.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
|
||||||
|
#ifdef USE_ESP32
|
||||||
|
#include <esp_gattc_api.h>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace ble_client {
|
||||||
|
|
||||||
|
namespace espbt = esphome::esp32_ble_tracker;
|
||||||
|
|
||||||
|
class BLEClientRSSISensor : public sensor::Sensor, public PollingComponent, public BLEClientNode {
|
||||||
|
public:
|
||||||
|
void loop() override;
|
||||||
|
void update() override;
|
||||||
|
void dump_config() override;
|
||||||
|
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||||
|
|
||||||
|
void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override;
|
||||||
|
|
||||||
|
void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if,
|
||||||
|
esp_ble_gattc_cb_param_t *param) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ble_client
|
||||||
|
} // namespace esphome
|
||||||
|
#endif
|
|
@ -321,6 +321,7 @@ mcp23s17:
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
- platform: ble_client
|
- platform: ble_client
|
||||||
|
type: characteristic
|
||||||
ble_client_id: ble_foo
|
ble_client_id: ble_foo
|
||||||
name: Green iTag btn
|
name: Green iTag btn
|
||||||
service_uuid: ffe0
|
service_uuid: ffe0
|
||||||
|
@ -335,6 +336,11 @@ sensor:
|
||||||
then:
|
then:
|
||||||
- lambda: |-
|
- lambda: |-
|
||||||
ESP_LOGD("green_btn", "Button was pressed, val%f", x);
|
ESP_LOGD("green_btn", "Button was pressed, val%f", x);
|
||||||
|
- platform: ble_client
|
||||||
|
type: rssi
|
||||||
|
ble_client_id: ble_foo
|
||||||
|
name: Green iTag RSSI
|
||||||
|
update_interval: 15s
|
||||||
- platform: adc
|
- platform: adc
|
||||||
pin: A0
|
pin: A0
|
||||||
name: Living Room Brightness
|
name: Living Room Brightness
|
||||||
|
|
Loading…
Reference in a new issue