mirror of
https://github.com/esphome/esphome.git
synced 2024-11-27 17:27:59 +01:00
Add connect, disconnect and fix notify
This commit is contained in:
parent
b422fda8bf
commit
c3b29fbfab
12 changed files with 143 additions and 84 deletions
|
@ -11,6 +11,8 @@ from esphome.const import (
|
|||
CONF_SERVICES,
|
||||
CONF_VALUE,
|
||||
CONF_NOTIFY,
|
||||
CONF_ON_CONNECT,
|
||||
CONF_ON_DISCONNECT,
|
||||
)
|
||||
from esphome.core import CORE
|
||||
|
||||
|
@ -142,7 +144,7 @@ def create_description_cud(char_config):
|
|||
|
||||
|
||||
def create_notify_cccd(char_config):
|
||||
if not char_config[CONF_NOTIFY]:
|
||||
if not char_config[CONF_NOTIFY] and not char_config[CONF_INDICATE]:
|
||||
return char_config
|
||||
# If the CCCD descriptor is already present, return the config
|
||||
for desc in char_config[CONF_DESCRIPTORS]:
|
||||
|
@ -206,9 +208,7 @@ DESCRIPTOR_SCHEMA = cv.Schema(
|
|||
cv.Required(CONF_UUID): cv.Any(bt_uuid, cv.hex_uint32_t),
|
||||
cv.Optional(CONF_READ, default=True): cv.boolean,
|
||||
cv.Optional(CONF_WRITE, default=True): cv.boolean,
|
||||
cv.Optional(CONF_ON_WRITE): automation.validate_automation(
|
||||
{cv.GenerateID(): cv.declare_id(BLEDescriptor)}, single=True
|
||||
),
|
||||
cv.Optional(CONF_ON_WRITE): automation.validate_automation(single=True),
|
||||
cv.Required(CONF_VALUE): VALUE_SCHEMA,
|
||||
},
|
||||
extra_schemas=[validate_descritor_value_length, validate_desc_on_write],
|
||||
|
@ -226,9 +226,7 @@ SERVICE_CHARACTERISTIC_SCHEMA = (
|
|||
cv.Optional(CONF_DESCRIPTORS, default=[]): cv.ensure_list(
|
||||
DESCRIPTOR_SCHEMA
|
||||
),
|
||||
cv.Optional(CONF_ON_WRITE): automation.validate_automation(
|
||||
{cv.GenerateID(): cv.declare_id(BLECharacteristic)}, single=True
|
||||
),
|
||||
cv.Optional(CONF_ON_WRITE): automation.validate_automation(single=True),
|
||||
cv.Optional(CONF_DESCRIPTION): cv.string,
|
||||
cv.GenerateID(CONF_CUD_ID_): cv.declare_id(BLEDescriptor),
|
||||
cv.GenerateID(CONF_CUD_VALUE_BUFFER_): cv.declare_id(ByteBuffer),
|
||||
|
@ -264,6 +262,8 @@ CONFIG_SCHEMA = cv.Schema(
|
|||
cv.Optional(CONF_MANUFACTURER_DATA): cv.Schema([cv.uint8_t]),
|
||||
cv.Optional(CONF_MODEL): cv.string,
|
||||
cv.Optional(CONF_SERVICES, default=[]): cv.ensure_list(SERVICE_SCHEMA),
|
||||
cv.Optional(CONF_ON_CONNECT): automation.validate_automation(single=True),
|
||||
cv.Optional(CONF_ON_DISCONNECT): automation.validate_automation(single=True),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
@ -380,7 +380,7 @@ async def to_code_descriptor(descriptor_conf, char_var):
|
|||
on_write_conf = descriptor_conf[CONF_ON_WRITE]
|
||||
await automation.build_automation(
|
||||
BLETriggers_ns.create_descriptor_on_write_trigger(desc_var),
|
||||
[(cg.std_vector.template(cg.uint8), "x")],
|
||||
[(cg.std_vector.template(cg.uint8), "x"), (cg.uint16, "id")],
|
||||
on_write_conf,
|
||||
)
|
||||
|
||||
|
@ -397,7 +397,7 @@ async def to_code_characteristic(service_var, char_conf):
|
|||
on_write_conf = char_conf[CONF_ON_WRITE]
|
||||
await automation.build_automation(
|
||||
BLETriggers_ns.create_characteristic_on_write_trigger(char_var),
|
||||
[(cg.std_vector.template(cg.uint8), "x")],
|
||||
[(cg.std_vector.template(cg.uint8), "x"), (cg.uint16, "id")],
|
||||
on_write_conf,
|
||||
)
|
||||
if CONF_VALUE in char_conf:
|
||||
|
@ -447,6 +447,18 @@ async def to_code(config):
|
|||
for char_conf in service_config[CONF_CHARACTERISTICS]:
|
||||
await to_code_characteristic(service_var, char_conf)
|
||||
cg.add(var.enqueue_start_service(service_var))
|
||||
if CONF_ON_CONNECT in config:
|
||||
await automation.build_automation(
|
||||
BLETriggers_ns.create_server_on_connect_trigger(var),
|
||||
[(cg.uint16, "id")],
|
||||
config[CONF_ON_CONNECT],
|
||||
)
|
||||
if CONF_ON_DISCONNECT in config:
|
||||
await automation.build_automation(
|
||||
BLETriggers_ns.create_server_on_disconnect_trigger(var),
|
||||
[(cg.uint16, "id")],
|
||||
config[CONF_ON_DISCONNECT],
|
||||
)
|
||||
cg.add_define("USE_ESP32_BLE_SERVER")
|
||||
if CORE.using_esp_idf:
|
||||
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
|
||||
|
|
|
@ -38,19 +38,25 @@ void BLECharacteristic::set_value(ByteBuffer buffer) {
|
|||
xSemaphoreGive(this->set_value_lock_);
|
||||
}
|
||||
|
||||
void BLECharacteristic::notify(bool require_ack) {
|
||||
if (require_ack) {
|
||||
ESP_LOGW(TAG, "require_ack=true is not yet supported (i.e. INDICATE is not yet supported)");
|
||||
// TODO: Handle when require_ack=true
|
||||
}
|
||||
void BLECharacteristic::notify() {
|
||||
if (this->service_ == nullptr || this->service_->get_server() == nullptr ||
|
||||
this->service_->get_server()->get_connected_client_count() == 0)
|
||||
return;
|
||||
|
||||
for (auto &client : this->service_->get_server()->get_clients()) {
|
||||
size_t length = this->value_.size();
|
||||
esp_err_t err = esp_ble_gatts_send_indicate(this->service_->get_server()->get_gatts_if(), client.first,
|
||||
this->handle_, length, this->value_.data(), false);
|
||||
// If the client is not in the list of clients to notify, skip it
|
||||
if (this->clients_to_notify_.count(client) == 0)
|
||||
continue;
|
||||
// If the client is in the list of clients to notify, check if it requires an ack (i.e. INDICATE)
|
||||
bool require_ack = this->clients_to_notify_[client];
|
||||
// TODO: Remove this block when INDICATE acknowledgment is supported
|
||||
if (require_ack) {
|
||||
ESP_LOGW(TAG, "INDICATE acknowledgment is not yet supported (i.e. it works as a NOTIFY)");
|
||||
require_ack = false;
|
||||
}
|
||||
esp_err_t err = esp_ble_gatts_send_indicate(this->service_->get_server()->get_gatts_if(), client,
|
||||
this->handle_, length, this->value_.data(), require_ack);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_ble_gatts_send_indicate failed %d", err);
|
||||
return;
|
||||
|
@ -58,7 +64,27 @@ void BLECharacteristic::notify(bool require_ack) {
|
|||
}
|
||||
}
|
||||
|
||||
void BLECharacteristic::add_descriptor(BLEDescriptor *descriptor) { this->descriptors_.push_back(descriptor); }
|
||||
void BLECharacteristic::add_descriptor(BLEDescriptor *descriptor) {
|
||||
// If the descriptor is the CCCD descriptor, listen to its write event to know if the client wants to be notified
|
||||
if (descriptor->get_uuid() == ESPBTUUID::from_uint16(ESP_GATT_UUID_CHAR_CLIENT_CONFIG)) {
|
||||
descriptor->on(
|
||||
BLEDescriptorEvt::VectorEvt::ON_WRITE,
|
||||
[this](const std::vector<uint8_t> &value, uint16_t conn_id) {
|
||||
if (value.size() != 2)
|
||||
return;
|
||||
uint16_t cccd = (value[1] << 8) | value[0];
|
||||
bool notify = (cccd & 1) != 0;
|
||||
bool indicate = (cccd & 2) != 0;
|
||||
if (notify || indicate) {
|
||||
this->clients_to_notify_[conn_id] = indicate;
|
||||
} else {
|
||||
this->clients_to_notify_.erase(conn_id);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
this->descriptors_.push_back(descriptor);
|
||||
}
|
||||
|
||||
void BLECharacteristic::remove_descriptor(BLEDescriptor *descriptor) {
|
||||
this->descriptors_.erase(std::remove(this->descriptors_.begin(), this->descriptors_.end(), descriptor),
|
||||
|
@ -178,7 +204,8 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
|
|||
if (!param->read.need_rsp)
|
||||
break; // For some reason you can request a read but not want a response
|
||||
|
||||
this->EventEmitter<BLECharacteristicEvt::EmptyEvt>::emit_(BLECharacteristicEvt::EmptyEvt::ON_READ);
|
||||
this->EventEmitter<BLECharacteristicEvt::EmptyEvt, uint16_t>::emit_(
|
||||
BLECharacteristicEvt::EmptyEvt::ON_READ, param->read.conn_id);
|
||||
|
||||
uint16_t max_offset = 22;
|
||||
|
||||
|
@ -246,8 +273,8 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
|
|||
}
|
||||
|
||||
if (!param->write.is_prep) {
|
||||
this->EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>>::emit_(
|
||||
BLECharacteristicEvt::VectorEvt::ON_WRITE, this->value_);
|
||||
this->EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>, uint16_t>::emit_(
|
||||
BLECharacteristicEvt::VectorEvt::ON_WRITE, this->value_, param->write.conn_id);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -258,8 +285,8 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
|
|||
break;
|
||||
this->write_event_ = false;
|
||||
if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) {
|
||||
this->EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>>::emit_(
|
||||
BLECharacteristicEvt::VectorEvt::ON_WRITE, this->value_);
|
||||
this->EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>, uint16_t>::emit_(
|
||||
BLECharacteristicEvt::VectorEvt::ON_WRITE, this->value_, param->exec_write.conn_id);
|
||||
}
|
||||
esp_err_t err =
|
||||
esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, nullptr);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "esphome/core/bytebuffer.h"
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
|
@ -34,8 +35,8 @@ enum EmptyEvt {
|
|||
};
|
||||
} // namespace BLECharacteristicEvt
|
||||
|
||||
class BLECharacteristic : public EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>>,
|
||||
public EventEmitter<BLECharacteristicEvt::EmptyEvt> {
|
||||
class BLECharacteristic : public EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>, uint16_t>,
|
||||
public EventEmitter<BLECharacteristicEvt::EmptyEvt, uint16_t> {
|
||||
public:
|
||||
BLECharacteristic(ESPBTUUID uuid, uint32_t properties);
|
||||
~BLECharacteristic();
|
||||
|
@ -49,10 +50,10 @@ class BLECharacteristic : public EventEmitter<BLECharacteristicEvt::VectorEvt, s
|
|||
void set_write_property(bool value);
|
||||
void set_write_no_response_property(bool value);
|
||||
|
||||
void indicate() { this->notify(true); }
|
||||
void notify(bool require_ack = false);
|
||||
void notify();
|
||||
|
||||
void do_create(BLEService *service);
|
||||
void do_delete() { this->clients_to_notify_.clear(); }
|
||||
void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
|
||||
|
||||
void add_descriptor(BLEDescriptor *descriptor);
|
||||
|
@ -84,6 +85,7 @@ class BLECharacteristic : public EventEmitter<BLECharacteristicEvt::VectorEvt, s
|
|||
SemaphoreHandle_t set_value_lock_;
|
||||
|
||||
std::vector<BLEDescriptor *> descriptors_;
|
||||
std::unordered_map<uint16_t, bool> clients_to_notify_;
|
||||
|
||||
esp_gatt_perm_t permissions_ = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE;
|
||||
|
||||
|
|
|
@ -72,9 +72,10 @@ void BLEDescriptor::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_
|
|||
break;
|
||||
this->value_.attr_len = param->write.len;
|
||||
memcpy(this->value_.attr_value, param->write.value, param->write.len);
|
||||
this->EventEmitter<BLEDescriptorEvt::VectorEvt, std::vector<uint8_t>>::emit_(
|
||||
this->emit_(
|
||||
BLEDescriptorEvt::VectorEvt::ON_WRITE,
|
||||
std::vector<uint8_t>(param->write.value, param->write.value + param->write.len)
|
||||
std::vector<uint8_t>(param->write.value, param->write.value + param->write.len),
|
||||
param->write.conn_id
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -20,13 +20,14 @@ namespace BLEDescriptorEvt {
|
|||
enum VectorEvt {
|
||||
ON_WRITE,
|
||||
};
|
||||
} // namespace BLECharacteristicEvt
|
||||
} // namespace BLEDescriptorEvt
|
||||
|
||||
class BLEDescriptor : public EventEmitter<BLEDescriptorEvt::VectorEvt, std::vector<uint8_t>> {
|
||||
class BLEDescriptor : public EventEmitter<BLEDescriptorEvt::VectorEvt, std::vector<uint8_t>, uint16_t> {
|
||||
public:
|
||||
BLEDescriptor(ESPBTUUID uuid, uint16_t max_len = 100, bool read = true, bool write = true);
|
||||
virtual ~BLEDescriptor();
|
||||
void do_create(BLECharacteristic *characteristic);
|
||||
ESPBTUUID get_uuid() const { return this->uuid_; }
|
||||
|
||||
void set_value(ByteBuffer buffer);
|
||||
|
||||
|
|
|
@ -182,21 +182,15 @@ void BLEServer::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t ga
|
|||
switch (event) {
|
||||
case ESP_GATTS_CONNECT_EVT: {
|
||||
ESP_LOGD(TAG, "BLE Client connected");
|
||||
this->add_client_(param->connect.conn_id, (void *) this);
|
||||
this->connected_clients_++;
|
||||
for (auto &pair : this->services_) {
|
||||
pair.second->emit_client_connect(param->connect.conn_id);
|
||||
}
|
||||
this->add_client_(param->connect.conn_id);
|
||||
this->emit_(BLEServerEvt::EmptyEvt::ON_CONNECT, param->connect.conn_id);
|
||||
break;
|
||||
}
|
||||
case ESP_GATTS_DISCONNECT_EVT: {
|
||||
ESP_LOGD(TAG, "BLE Client disconnected");
|
||||
if (this->remove_client_(param->disconnect.conn_id))
|
||||
this->connected_clients_--;
|
||||
this->remove_client_(param->disconnect.conn_id);
|
||||
this->parent_->advertising_start();
|
||||
for (auto &pair : this->services_) {
|
||||
pair.second->emit_client_disconnect(param->disconnect.conn_id);
|
||||
}
|
||||
this->emit_(BLEServerEvt::EmptyEvt::ON_DISCONNECT, param->disconnect.conn_id);
|
||||
break;
|
||||
}
|
||||
case ESP_GATTS_REG_EVT: {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
|
@ -26,7 +27,15 @@ namespace esp32_ble_server {
|
|||
|
||||
using namespace esp32_ble;
|
||||
|
||||
class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEventHandler, public Parented<ESP32BLE> {
|
||||
namespace BLEServerEvt {
|
||||
enum EmptyEvt {
|
||||
ON_CONNECT,
|
||||
ON_DISCONNECT,
|
||||
};
|
||||
} // namespace BLEServerEvt
|
||||
|
||||
class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEventHandler,
|
||||
public Parented<ESP32BLE>, public EventEmitter<BLEServerEvt::EmptyEvt, uint16_t> {
|
||||
public:
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
|
@ -50,8 +59,8 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv
|
|||
void enqueue_start_service(BLEService *service) { this->services_to_start_.push_back(service); }
|
||||
|
||||
esp_gatt_if_t get_gatts_if() { return this->gatts_if_; }
|
||||
uint32_t get_connected_client_count() { return this->connected_clients_; }
|
||||
const std::unordered_map<uint16_t, void *> &get_clients() { return this->clients_; }
|
||||
uint32_t get_connected_client_count() { return this->clients_.size(); }
|
||||
const std::unordered_set<uint16_t> &get_clients() { return this->clients_; }
|
||||
|
||||
void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
|
||||
esp_ble_gatts_cb_param_t *param) override;
|
||||
|
@ -63,8 +72,8 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv
|
|||
bool create_device_characteristics_();
|
||||
void restart_advertising_();
|
||||
|
||||
void add_client_(uint16_t conn_id, void *client) { this->clients_.emplace(conn_id, client); }
|
||||
bool remove_client_(uint16_t conn_id) { return this->clients_.erase(conn_id) > 0; }
|
||||
void add_client_(uint16_t conn_id) { this->clients_.insert(conn_id); }
|
||||
void remove_client_(uint16_t conn_id) { this->clients_.erase(conn_id); }
|
||||
|
||||
std::string manufacturer_;
|
||||
optional<std::string> model_;
|
||||
|
@ -72,8 +81,7 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv
|
|||
esp_gatt_if_t gatts_if_{0};
|
||||
bool registered_{false};
|
||||
|
||||
uint32_t connected_clients_{0};
|
||||
std::unordered_map<uint16_t, void *> clients_;
|
||||
std::unordered_set<uint16_t> clients_;
|
||||
std::unordered_map<std::string, BLEService *> services_;
|
||||
std::vector<BLEService *> services_to_start_;
|
||||
BLEService *device_information_service_;
|
||||
|
|
|
@ -9,24 +9,36 @@ namespace esp32_ble_server_automations {
|
|||
|
||||
using namespace esp32_ble;
|
||||
|
||||
Trigger<std::vector<uint8_t>> *BLETriggers::create_characteristic_on_write_trigger(BLECharacteristic *characteristic) {
|
||||
Trigger<std::vector<uint8_t>> *on_write_trigger = // NOLINT(cppcoreguidelines-owning-memory)
|
||||
new Trigger<std::vector<uint8_t>>();
|
||||
characteristic->EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>>::on(
|
||||
Trigger<std::vector<uint8_t>, uint16_t> *BLETriggers::create_characteristic_on_write_trigger(BLECharacteristic *characteristic) {
|
||||
Trigger<std::vector<uint8_t>, uint16_t> *on_write_trigger = // NOLINT(cppcoreguidelines-owning-memory)
|
||||
new Trigger<std::vector<uint8_t>, uint16_t>();
|
||||
characteristic->EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>, uint16_t>::on(
|
||||
BLECharacteristicEvt::VectorEvt::ON_WRITE,
|
||||
[on_write_trigger](const std::vector<uint8_t> &data) { on_write_trigger->trigger(data); });
|
||||
[on_write_trigger](const std::vector<uint8_t> &data, uint16_t id) { on_write_trigger->trigger(data, id); });
|
||||
return on_write_trigger;
|
||||
}
|
||||
|
||||
Trigger<std::vector<uint8_t>> *BLETriggers::create_descriptor_on_write_trigger(BLEDescriptor *descriptor) {
|
||||
Trigger<std::vector<uint8_t>> *on_write_trigger = // NOLINT(cppcoreguidelines-owning-memory)
|
||||
new Trigger<std::vector<uint8_t>>();
|
||||
descriptor->EventEmitter<BLEDescriptorEvt::VectorEvt, std::vector<uint8_t>>::on(
|
||||
Trigger<std::vector<uint8_t>, uint16_t> *BLETriggers::create_descriptor_on_write_trigger(BLEDescriptor *descriptor) {
|
||||
Trigger<std::vector<uint8_t>, uint16_t> *on_write_trigger = // NOLINT(cppcoreguidelines-owning-memory)
|
||||
new Trigger<std::vector<uint8_t>, uint16_t>();
|
||||
descriptor->on(
|
||||
BLEDescriptorEvt::VectorEvt::ON_WRITE,
|
||||
[on_write_trigger](const std::vector<uint8_t> &data) { on_write_trigger->trigger(data); });
|
||||
[on_write_trigger](const std::vector<uint8_t> &data, uint16_t id) { on_write_trigger->trigger(data, id); });
|
||||
return on_write_trigger;
|
||||
}
|
||||
|
||||
Trigger<uint16_t> *BLETriggers::create_server_on_connect_trigger(BLEServer *server) {
|
||||
Trigger<uint16_t> *on_connect_trigger = new Trigger<uint16_t>(); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
server->on(BLEServerEvt::EmptyEvt::ON_CONNECT, [on_connect_trigger](uint16_t conn_id) { on_connect_trigger->trigger(conn_id); });
|
||||
return on_connect_trigger;
|
||||
}
|
||||
|
||||
Trigger<uint16_t> *BLETriggers::create_server_on_disconnect_trigger(BLEServer *server) {
|
||||
Trigger<uint16_t> *on_disconnect_trigger = new Trigger<uint16_t>(); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
server->on(BLEServerEvt::EmptyEvt::ON_DISCONNECT, [on_disconnect_trigger](uint16_t conn_id) { on_disconnect_trigger->trigger(conn_id); });
|
||||
return on_disconnect_trigger;
|
||||
}
|
||||
|
||||
void BLECharacteristicSetValueActionManager::set_listener(BLECharacteristic *characteristic,
|
||||
EventEmitterListenerID listener_id,
|
||||
const std::function<void()> &pre_notify_listener) {
|
||||
|
@ -37,7 +49,7 @@ void BLECharacteristicSetValueActionManager::set_listener(BLECharacteristic *cha
|
|||
EventEmitterListenerID old_listener_id = listener_pairs.first;
|
||||
EventEmitterListenerID old_pre_notify_listener_id = listener_pairs.second;
|
||||
// Remove the previous listener
|
||||
characteristic->EventEmitter<BLECharacteristicEvt::EmptyEvt>::off(BLECharacteristicEvt::EmptyEvt::ON_READ,
|
||||
characteristic->EventEmitter<BLECharacteristicEvt::EmptyEvt, uint16_t>::off(BLECharacteristicEvt::EmptyEvt::ON_READ,
|
||||
old_listener_id);
|
||||
// Remove the pre-notify listener
|
||||
this->off(BLECharacteristicSetValueActionEvt::PRE_NOTIFY, old_pre_notify_listener_id);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "ble_server.h"
|
||||
#include "ble_characteristic.h"
|
||||
#include "ble_descriptor.h"
|
||||
|
||||
#include "esphome/core/event_emitter.h"
|
||||
#include "esphome/core/automation.h"
|
||||
|
@ -21,8 +23,10 @@ using namespace esp32_ble;
|
|||
|
||||
class BLETriggers {
|
||||
public:
|
||||
static Trigger<std::vector<uint8_t>> *create_characteristic_on_write_trigger(BLECharacteristic *characteristic);
|
||||
static Trigger<std::vector<uint8_t>> *create_descriptor_on_write_trigger(BLEDescriptor *descriptor);
|
||||
static Trigger<std::vector<uint8_t>, uint16_t> *create_characteristic_on_write_trigger(BLECharacteristic *characteristic);
|
||||
static Trigger<std::vector<uint8_t>, uint16_t> *create_descriptor_on_write_trigger(BLEDescriptor *descriptor);
|
||||
static Trigger<uint16_t> *create_server_on_connect_trigger(BLEServer *server);
|
||||
static Trigger<uint16_t> *create_server_on_disconnect_trigger(BLEServer *server);
|
||||
};
|
||||
|
||||
enum BLECharacteristicSetValueActionEvt {
|
||||
|
@ -62,8 +66,8 @@ template<typename... Ts> class BLECharacteristicSetValueAction : public Action<T
|
|||
// Set initial value
|
||||
this->parent_->set_value(this->buffer_.value(x...));
|
||||
// Set the listener for read events
|
||||
this->listener_id_ = this->parent_->EventEmitter<BLECharacteristicEvt::EmptyEvt>::on(
|
||||
BLECharacteristicEvt::EmptyEvt::ON_READ, [this, x...]() {
|
||||
this->listener_id_ = this->parent_->EventEmitter<BLECharacteristicEvt::EmptyEvt, uint16_t>::on(
|
||||
BLECharacteristicEvt::EmptyEvt::ON_READ, [this, x...](uint16_t id) {
|
||||
// Set the value of the characteristic every time it is read
|
||||
this->parent_->set_value(this->buffer_.value(x...));
|
||||
});
|
||||
|
|
|
@ -58,22 +58,15 @@ void BLEService::do_create(BLEServer *server) {
|
|||
this->state_ = CREATING;
|
||||
}
|
||||
|
||||
void BLEService::emit_client_connect(const uint16_t conn_id) {
|
||||
if (this->on_client_connect_ && this->is_running())
|
||||
this->on_client_connect_(conn_id);
|
||||
}
|
||||
|
||||
void BLEService::emit_client_disconnect(const uint16_t conn_id) {
|
||||
if (this->on_client_disconnect_ && this->is_running())
|
||||
this->on_client_disconnect_(conn_id);
|
||||
}
|
||||
|
||||
void BLEService::do_delete() {
|
||||
if (this->state_ == DELETING || this->state_ == DELETED)
|
||||
return;
|
||||
this->state_ = DELETING;
|
||||
this->created_characteristic_count_ = 0;
|
||||
this->last_created_characteristic_ = nullptr;
|
||||
// Call all characteristics to delete
|
||||
for (auto *characteristic : this->characteristics_)
|
||||
characteristic->do_delete();
|
||||
this->stop_();
|
||||
esp_err_t err = esp_ble_gatts_delete_service(this->handle_);
|
||||
if (err != ESP_OK) {
|
||||
|
|
|
@ -50,10 +50,6 @@ class BLEService {
|
|||
bool is_running() { return this->state_ == RUNNING; }
|
||||
bool is_starting() { return this->state_ == STARTING; }
|
||||
bool is_deleted() { return this->state_ == DELETED; }
|
||||
void on_client_connect(const std::function<void(const uint16_t)> &&func) { this->on_client_connect_ = func; }
|
||||
void on_client_disconnect(const std::function<void(const uint16_t)> &&func) { this->on_client_disconnect_ = func; }
|
||||
void emit_client_connect(uint16_t conn_id);
|
||||
void emit_client_disconnect(uint16_t conn_id);
|
||||
|
||||
protected:
|
||||
std::vector<BLECharacteristic *> characteristics_;
|
||||
|
@ -66,8 +62,6 @@ class BLEService {
|
|||
uint8_t inst_id_;
|
||||
bool advertise_{false};
|
||||
bool should_start_{false};
|
||||
std::function<void(const uint16_t)> on_client_connect_;
|
||||
std::function<void(const uint16_t)> on_client_disconnect_;
|
||||
|
||||
bool do_create_characteristics_();
|
||||
void stop_();
|
||||
|
|
|
@ -3,15 +3,22 @@ esp32_ble_server:
|
|||
manufacturer_data: [0x72, 0x4, 0x00, 0x23]
|
||||
manufacturer: ESPHome
|
||||
model: Test
|
||||
on_connect:
|
||||
- lambda: |-
|
||||
ESP_LOGD("BLE", "Connection from %d", id);
|
||||
on_disconnect:
|
||||
- lambda: |-
|
||||
ESP_LOGD("BLE", "Disconnection from %d", id);
|
||||
services:
|
||||
- uuid: 2a24b789-7aab-4535-af3e-ee76a35cc42d
|
||||
- uuid: 2a24b789-7aab-4535-af3e-ee76a35cc12d
|
||||
advertise: false
|
||||
characteristics:
|
||||
- id: test_notify_characteristic
|
||||
description: "Notify characteristic"
|
||||
uuid: cad48e28-7fbe-41cf-bae9-d77a6c233423
|
||||
read: true
|
||||
notify: true
|
||||
value: [0, 1, 2]
|
||||
value: [9, 9, 9]
|
||||
descriptors:
|
||||
- uuid: cad48e28-7fbe-41cf-bae9-d77a6c111111
|
||||
value: 123.1
|
||||
|
@ -20,18 +27,22 @@ esp32_ble_server:
|
|||
advertise: false
|
||||
characteristics:
|
||||
- id: test_change_characteristic
|
||||
uuid: 2a24b789-7a1b-4535-af3e-ee76a35cc11d
|
||||
uuid: 2a24b789-7a1b-4535-af3e-ee76a35cc11c
|
||||
read: true
|
||||
value: "Initial"
|
||||
description: "Change characteristic"
|
||||
descriptors:
|
||||
- uuid: cad48e28-7fbe-41cf-bae9-d77a6c111111
|
||||
- uuid: 0x2312
|
||||
value: 0x12
|
||||
- uuid: 2a24b789-7a1b-4535-af3e-ee76a35cc12d
|
||||
on_write:
|
||||
- lambda: |-
|
||||
ESP_LOGD("BLE", "Descriptor received: %s from %d", std::string(x.begin(), x.end()).c_str(), id);
|
||||
- uuid: 2a24b789-7a1b-4535-af3e-ee76a35cc99a
|
||||
write: true
|
||||
on_write:
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD("BLE", "Received: %s", std::string(x.begin(), x.end()).c_str());
|
||||
ESP_LOGD("BLE", "Characteristic received: %s from %d", std::string(x.begin(), x.end()).c_str(), id);
|
||||
- ble_server.characteristic.set_value:
|
||||
id: test_change_characteristic
|
||||
value: !lambda 'return ByteBuffer::wrap({0x00, 0x01, 0x02});'
|
||||
|
|
Loading…
Reference in a new issue