BLE loop use (#1882)

This commit is contained in:
Jesse Hills 2021-06-10 14:04:39 +12:00
parent 139db58a66
commit 0db4815f3d
No known key found for this signature in database
GPG Key ID: BEAAE804EFD8E83A
14 changed files with 272 additions and 165 deletions

View File

@ -20,14 +20,13 @@ void ESP32BLE::setup() {
global_ble = this;
ESP_LOGCONFIG(TAG, "Setting up BLE...");
xTaskCreatePinnedToCore(ESP32BLE::ble_core_task_,
"ble_task", // name
10000, // stack size
nullptr, // input params
1, // priority
nullptr, // handle, not needed
0 // core
);
if (!ble_setup_()) {
ESP_LOGE(TAG, "BLE could not be set up");
this->mark_failed();
return;
}
ESP_LOGD(TAG, "BLE setup complete");
}
void ESP32BLE::mark_failed() {
@ -37,23 +36,6 @@ void ESP32BLE::mark_failed() {
}
}
bool ESP32BLE::can_proceed() { return this->ready_; }
void ESP32BLE::ble_core_task_(void *params) {
if (!ble_setup_()) {
ESP_LOGE(TAG, "BLE could not be set up");
global_ble->mark_failed();
return;
}
global_ble->ready_ = true;
ESP_LOGD(TAG, "BLE Setup complete");
while (true) {
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
bool ESP32BLE::ble_setup_() {
esp_err_t err = nvs_flash_init();
if (err != ESP_OK) {
@ -84,7 +66,7 @@ bool ESP32BLE::ble_setup_() {
return false;
}
if (global_ble->has_server()) {
if (this->has_server()) {
err = esp_ble_gatts_register_callback(ESP32BLE::gatts_event_handler);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ble_gatts_register_callback failed: %d", err);
@ -92,7 +74,7 @@ bool ESP32BLE::ble_setup_() {
}
}
if (global_ble->has_client()) {
if (this->has_client()) {
err = esp_ble_gattc_register_callback(ESP32BLE::gattc_event_handler);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ble_gattc_register_callback failed: %d", err);
@ -119,27 +101,28 @@ bool ESP32BLE::ble_setup_() {
return true;
}
// void ESP32BLE::loop() {
// BLEEvent *ble_event = this->ble_events_.pop();
// while (ble_event != nullptr) {
// switch (ble_event->type_) {
// case ble_event->GATTS:
// this->real_gatts_event_handler_(ble_event->event_.gatts.gatts_event, ble_event->event_.gatts.gatts_if,
// &ble_event->event_.gatts.gatts_param);
// break;
// case ble_event->GAP:
// this->real_gap_event_handler_(ble_event->event_.gap.gap_event, &ble_event->event_.gap.gap_param);
// break;
// default:
// break;
// }
// delete ble_event;
// ble_event = this->ble_events_.pop();
// }
// }
void ESP32BLE::loop() {
BLEEvent *ble_event = this->ble_events_.pop();
while (ble_event != nullptr) {
switch (ble_event->type_) {
case ble_event->GATTS:
this->real_gatts_event_handler_(ble_event->event_.gatts.gatts_event, ble_event->event_.gatts.gatts_if,
&ble_event->event_.gatts.gatts_param);
break;
case ble_event->GAP:
this->real_gap_event_handler_(ble_event->event_.gap.gap_event, &ble_event->event_.gap.gap_param);
break;
default:
break;
}
delete ble_event;
ble_event = this->ble_events_.pop();
}
}
void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
global_ble->real_gap_event_handler_(event, param);
BLEEvent *new_event = new BLEEvent(event, param);
global_ble->ble_events_.push(new_event);
}
void ESP32BLE::real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) {
@ -152,7 +135,8 @@ void ESP32BLE::real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap
void ESP32BLE::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
esp_ble_gatts_cb_param_t *param) {
global_ble->real_gatts_event_handler_(event, gatts_if, param);
BLEEvent *new_event = new BLEEvent(event, gatts_if, param);
global_ble->ble_events_.push(new_event);
}
void ESP32BLE::real_gatts_event_handler_(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,

View File

@ -23,17 +23,14 @@ typedef struct {
class ESP32BLE : public Component {
public:
void setup() override;
// void loop() override;
void loop() override;
void dump_config() override;
float get_setup_priority() const override;
void mark_failed() override;
bool can_proceed() override;
bool has_server() { return this->server_ != nullptr; }
bool has_client() { return false; }
bool is_ready() { return this->ready_; }
void set_server(BLEServer *server) { this->server_ = server; }
protected:
@ -45,10 +42,7 @@ class ESP32BLE : public Component {
void real_gattc_event_handler_(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
void real_gap_event_handler_(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
static void ble_core_task_(void *params);
static bool ble_setup_();
bool ready_{false};
bool ble_setup_();
BLEServer *server_{nullptr};
Queue<BLEEvent> ble_events_;

View File

@ -13,10 +13,8 @@ static const char *TAG = "esp32_ble.characteristic";
BLECharacteristic::BLECharacteristic(const ESPBTUUID uuid, uint32_t properties) : uuid_(uuid) {
this->set_value_lock_ = xSemaphoreCreateBinary();
this->create_lock_ = xSemaphoreCreateBinary();
xSemaphoreGive(this->set_value_lock_);
xSemaphoreGive(this->create_lock_);
this->properties_ = (esp_gatt_char_prop_t) 0;
this->set_broadcast_property((properties & PROPERTY_BROADCAST) != 0);
@ -100,12 +98,11 @@ void BLECharacteristic::notify(bool notification) {
void BLECharacteristic::add_descriptor(BLEDescriptor *descriptor) { this->descriptors_.push_back(descriptor); }
bool BLECharacteristic::do_create(BLEService *service) {
void BLECharacteristic::do_create(BLEService *service) {
this->service_ = service;
esp_attr_control_t control;
control.auto_rsp = ESP_GATT_RSP_BY_APP;
xSemaphoreTake(this->create_lock_, portMAX_DELAY);
ESP_LOGV(TAG, "Creating characteristic - %s", this->uuid_.to_string().c_str());
esp_bt_uuid_t uuid = this->uuid_.get_uuid();
@ -114,15 +111,39 @@ bool BLECharacteristic::do_create(BLEService *service) {
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ble_gatts_add_char failed: %d", err);
return;
}
this->state_ = CREATING;
}
bool BLECharacteristic::is_created() {
if (this->state_ == CREATED)
return true;
if (this->state_ != CREATING_DEPENDENTS)
return false;
}
xSemaphoreWait(this->create_lock_, portMAX_DELAY);
bool created = true;
for (auto *descriptor : this->descriptors_) {
descriptor->do_create(this);
created &= descriptor->is_created();
}
return true;
if (created)
this->state_ = CREATED;
return this->state_ == CREATED;
}
bool BLECharacteristic::is_failed() {
if (this->state_ == FAILED)
return true;
bool failed = false;
for (auto *descriptor : this->descriptors_) {
failed |= descriptor->is_failed();
}
if (failed)
this->state_ = FAILED;
return this->state_ == FAILED;
}
void BLECharacteristic::set_broadcast_property(bool value) {
@ -168,7 +189,12 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
case ESP_GATTS_ADD_CHAR_EVT: {
if (this->uuid_ == ESPBTUUID::from_uuid(param->add_char.char_uuid)) {
this->handle_ = param->add_char.attr_handle;
xSemaphoreGive(this->create_lock_);
for (auto *descriptor : this->descriptors_) {
descriptor->do_create(this);
}
this->state_ = CREATING_DEPENDENTS;
}
break;
}

View File

@ -42,10 +42,10 @@ class BLECharacteristic {
void notify(bool notification = true);
bool do_create(BLEService *service);
void do_create(BLEService *service);
void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
void on_write(const std::function<void(const std::vector<uint8_t> &)> &func) { this->on_write_ = func; }
void on_write(const std::function<void(const std::vector<uint8_t> &)> &&func) { this->on_write_ = std::move(func); }
void add_descriptor(BLEDescriptor *descriptor);
@ -60,6 +60,9 @@ class BLECharacteristic {
static const uint32_t PROPERTY_INDICATE = 1 << 4;
static const uint32_t PROPERTY_WRITE_NR = 1 << 5;
bool is_created();
bool is_failed();
protected:
bool write_event_{false};
BLEService *service_;
@ -70,13 +73,20 @@ class BLECharacteristic {
uint16_t value_read_offset_{0};
std::vector<uint8_t> value_;
SemaphoreHandle_t set_value_lock_;
SemaphoreHandle_t create_lock_;
std::vector<BLEDescriptor *> descriptors_;
std::function<void(const std::vector<uint8_t> &)> on_write_;
esp_gatt_perm_t permissions_ = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE;
enum State : uint8_t {
FAILED = 0x00,
INIT,
CREATING,
CREATING_DEPENDENTS,
CREATED,
} state_{INIT};
};
} // namespace esp32_ble

View File

@ -16,30 +16,25 @@ BLEDescriptor::BLEDescriptor(ESPBTUUID uuid, uint16_t max_len) {
this->value_.attr_len = 0;
this->value_.attr_max_len = max_len;
this->value_.attr_value = (uint8_t *) malloc(max_len);
this->create_lock_ = xSemaphoreCreateBinary();
xSemaphoreGive(this->create_lock_);
}
BLEDescriptor::~BLEDescriptor() { free(this->value_.attr_value); }
bool BLEDescriptor::do_create(BLECharacteristic *characteristic) {
void BLEDescriptor::do_create(BLECharacteristic *characteristic) {
this->characteristic_ = characteristic;
esp_attr_control_t control;
control.auto_rsp = ESP_GATT_AUTO_RSP;
xSemaphoreTake(this->create_lock_, portMAX_DELAY);
ESP_LOGV(TAG, "Creating descriptor - %s", this->uuid_.to_string().c_str());
esp_bt_uuid_t uuid = this->uuid_.get_uuid();
esp_err_t err = esp_ble_gatts_add_char_descr(this->characteristic_->get_service()->get_handle(), &uuid,
this->permissions_, &this->value_, &control);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ble_gatts_add_char_descr failed: %d", err);
return false;
this->state_ = FAILED;
return;
}
xSemaphoreWait(this->create_lock_, portMAX_DELAY);
return true;
this->state_ = CREATING;
}
void BLEDescriptor::set_value(const std::string &value) { this->set_value((uint8_t *) value.data(), value.length()); }
@ -60,7 +55,7 @@ void BLEDescriptor::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_
this->characteristic_->get_service()->get_handle() == param->add_char_descr.service_handle &&
this->characteristic_ == this->characteristic_->get_service()->get_last_created_characteristic()) {
this->handle_ = param->add_char_descr.attr_handle;
xSemaphoreGive(this->create_lock_);
this->state_ = CREATED;
}
break;
}

View File

@ -16,22 +16,31 @@ class BLEDescriptor {
public:
BLEDescriptor(ESPBTUUID uuid, uint16_t max_len = 100);
virtual ~BLEDescriptor();
bool do_create(BLECharacteristic *characteristic);
void do_create(BLECharacteristic *characteristic);
void set_value(const std::string &value);
void set_value(const uint8_t *data, size_t length);
void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
bool is_created() { return this->state_ == CREATED; }
bool is_failed() { return this->state_ == FAILED; }
protected:
BLECharacteristic *characteristic_{nullptr};
ESPBTUUID uuid_;
uint16_t handle_{0xFFFF};
SemaphoreHandle_t create_lock_;
esp_attr_value_t value_;
esp_gatt_perm_t permissions_ = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE;
enum State : uint8_t {
FAILED = 0x00,
INIT,
CREATING,
CREATED,
} state_{INIT};
};
} // namespace esp32_ble

View File

@ -18,7 +18,7 @@ namespace esp32_ble {
static const char *TAG = "esp32_ble.server";
static const uint16_t DEVICE_INFORMATION_SERVICE_UUID = 0x180A;
static const uint16_t device_information_service__UUID = 0x180A;
static const uint16_t MODEL_UUID = 0x2A24;
static const uint16_t VERSION_UUID = 0x2A26;
static const uint16_t MANUFACTURER_UUID = 0x2A29;
@ -32,59 +32,78 @@ void BLEServer::setup() {
ESP_LOGD(TAG, "Setting up BLE Server...");
global_ble_server = this;
this->register_lock_ = xSemaphoreCreateBinary();
xSemaphoreGive(this->register_lock_);
this->advertising_ = new BLEAdvertising();
this->setup_server_();
for (auto *component : this->service_components_) {
component->setup_service();
}
ESP_LOGD(TAG, "BLE Server set up complete...");
}
void BLEServer::setup_server_() {
xSemaphoreTake(this->register_lock_, portMAX_DELAY);
esp_err_t err = esp_ble_gatts_app_register(0);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ble_gatts_app_register failed: %d", err);
this->mark_failed();
return;
void BLEServer::loop() {
switch (this->state_) {
case RUNNING:
return;
case INIT: {
esp_err_t err = esp_ble_gatts_app_register(0);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ble_gatts_app_register failed: %d", err);
this->mark_failed();
return;
}
this->state_ = REGISTERING;
break;
}
case REGISTERING: {
if (this->registered_) {
this->device_information_service_ = this->create_service(device_information_service__UUID);
this->create_device_characteristics_();
this->advertising_->set_scan_response(true);
this->advertising_->set_min_preferred_interval(0x06);
this->advertising_->start();
this->state_ = STARTING_SERVICE;
}
break;
}
case STARTING_SERVICE: {
if (this->device_information_service_->is_running()) {
for (auto *component : this->service_components_) {
component->setup_service();
}
this->state_ = SETTING_UP_COMPONENT_SERVICES;
} else if (!this->device_information_service_->is_starting()) {
this->device_information_service_->start();
}
break;
}
case SETTING_UP_COMPONENT_SERVICES: {
this->state_ = RUNNING;
this->can_proceed_ = true;
ESP_LOGD(TAG, "BLE server setup successfully");
break;
}
}
xSemaphoreWait(this->register_lock_, portMAX_DELAY);
this->device_information_service = this->create_service(DEVICE_INFORMATION_SERVICE_UUID);
this->create_device_characteristics_();
this->advertising_->set_scan_response(true);
this->advertising_->set_min_preferred_interval(0x06);
this->advertising_->start();
this->device_information_service->start();
}
bool BLEServer::create_device_characteristics_() {
if (this->model_.has_value()) {
BLECharacteristic *model =
this->device_information_service->create_characteristic(MODEL_UUID, BLECharacteristic::PROPERTY_READ);
this->device_information_service_->create_characteristic(MODEL_UUID, BLECharacteristic::PROPERTY_READ);
model->set_value(this->model_.value());
} else {
#ifdef ARDUINO_BOARD
BLECharacteristic *model =
this->device_information_service->create_characteristic(MODEL_UUID, BLECharacteristic::PROPERTY_READ);
this->device_information_service_->create_characteristic(MODEL_UUID, BLECharacteristic::PROPERTY_READ);
model->set_value(ARDUINO_BOARD);
#endif
}
BLECharacteristic *version =
this->device_information_service->create_characteristic(VERSION_UUID, BLECharacteristic::PROPERTY_READ);
this->device_information_service_->create_characteristic(VERSION_UUID, BLECharacteristic::PROPERTY_READ);
version->set_value("ESPHome " ESPHOME_VERSION);
BLECharacteristic *manufacturer =
this->device_information_service->create_characteristic(MANUFACTURER_UUID, BLECharacteristic::PROPERTY_READ);
this->device_information_service_->create_characteristic(MANUFACTURER_UUID, BLECharacteristic::PROPERTY_READ);
manufacturer->set_value(this->manufacturer_);
return true;
@ -134,7 +153,7 @@ void BLEServer::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t ga
}
case ESP_GATTS_REG_EVT: {
this->gatts_if_ = gatts_if;
xSemaphoreGive(this->register_lock_);
this->registered_ = true;
break;
}
default:

View File

@ -24,13 +24,17 @@ class BLEServiceComponent {
virtual void setup_service();
virtual void on_client_connect(){};
virtual void on_client_disconnect(){};
virtual void start();
virtual void stop();
};
class BLEServer : public Component {
public:
void setup() override;
void loop() override;
void dump_config() override;
float get_setup_priority() const override;
bool can_proceed() override { return this->can_proceed_; }
void teardown();
@ -53,27 +57,35 @@ class BLEServer : public Component {
protected:
bool create_device_characteristics_();
void setup_server_();
void add_client_(uint16_t conn_id, void *client) {
this->clients_.insert(std::pair<uint16_t, void *>(conn_id, client));
}
bool remove_client_(uint16_t conn_id) { return this->clients_.erase(conn_id) > 0; }
bool can_proceed_{false};
std::string manufacturer_;
optional<std::string> model_;
esp_gatt_if_t gatts_if_{0};
bool registered_{false};
BLEAdvertising *advertising_;
uint32_t connected_clients_{0};
std::map<uint16_t, void *> clients_;
std::vector<BLEService *> services_;
BLEService *device_information_service;
BLEService *device_information_service_;
std::vector<BLEServiceComponent *> service_components_;
SemaphoreHandle_t register_lock_;
enum State : uint8_t {
INIT = 0x00,
REGISTERING,
STARTING_SERVICE,
SETTING_UP_COMPONENT_SERVICES,
RUNNING,
} state_{INIT};
};
extern BLEServer *global_ble_server;

View File

@ -10,15 +10,7 @@ namespace esp32_ble {
static const char *TAG = "esp32_ble.service";
BLEService::BLEService(ESPBTUUID uuid, uint16_t num_handles, uint8_t inst_id)
: uuid_(uuid), num_handles_(num_handles), inst_id_(inst_id) {
this->create_lock_ = xSemaphoreCreateBinary();
this->start_lock_ = xSemaphoreCreateBinary();
this->stop_lock_ = xSemaphoreCreateBinary();
xSemaphoreGive(this->create_lock_);
xSemaphoreGive(this->start_lock_);
xSemaphoreGive(this->stop_lock_);
}
: uuid_(uuid), num_handles_(num_handles), inst_id_(inst_id) {}
BLEService::~BLEService() {
for (auto &chr : this->characteristics_)
@ -47,10 +39,9 @@ BLECharacteristic *BLEService::create_characteristic(ESPBTUUID uuid, esp_gatt_ch
return characteristic;
}
bool BLEService::do_create(BLEServer *server) {
void BLEService::do_create(BLEServer *server) {
this->server_ = server;
xSemaphoreTake(this->create_lock_, portMAX_DELAY);
esp_gatt_srvc_id_t srvc_id;
srvc_id.is_primary = true;
srvc_id.id.inst_id = this->inst_id_;
@ -59,36 +50,58 @@ bool BLEService::do_create(BLEServer *server) {
esp_err_t err = esp_ble_gatts_create_service(server->get_gatts_if(), &srvc_id, this->num_handles_);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ble_gatts_create_service failed: %d", err);
return false;
this->init_state_ = FAILED;
return;
}
xSemaphoreWait(this->create_lock_, portMAX_DELAY);
this->init_state_ = CREATING;
}
bool BLEService::do_create_characteristics_() {
if (this->created_characteristic_count_ >= this->characteristics_.size() &&
(this->last_created_characteristic_ == nullptr || this->last_created_characteristic_->is_created()))
return false; // Signifies there are no characteristics, or they are all finished being created.
if (this->last_created_characteristic_ != nullptr && !this->last_created_characteristic_->is_created())
return true; // Signifies that the previous characteristic is still being created.
auto *characteristic = this->characteristics_[this->created_characteristic_count_++];
this->last_created_characteristic_ = characteristic;
characteristic->do_create(this);
return true;
}
void BLEService::start() {
for (auto *characteristic : this->characteristics_) {
this->last_created_characteristic_ = characteristic;
characteristic->do_create(this);
}
if (this->do_create_characteristics_())
return;
xSemaphoreTake(this->start_lock_, portMAX_DELAY);
esp_err_t err = esp_ble_gatts_start_service(this->handle_);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ble_gatts_start_service failed: %d", err);
return;
}
xSemaphoreWait(this->start_lock_, portMAX_DELAY);
this->running_state_ = STARTING;
}
void BLEService::stop() {
xSemaphoreTake(this->stop_lock_, portMAX_DELAY);
esp_err_t err = esp_ble_gatts_stop_service(this->handle_);
if (err != ESP_OK) {
ESP_LOGE(TAG, "esp_ble_gatts_stop_service failed: %d", err);
return;
}
xSemaphoreWait(this->stop_lock_, portMAX_DELAY);
this->running_state_ = STOPPING;
}
bool BLEService::is_created() { return this->init_state_ == CREATED; }
bool BLEService::is_failed() {
if (this->init_state_ == FAILED)
return true;
bool failed = false;
for (auto *characteristic : this->characteristics_)
failed |= characteristic->is_failed();
if (failed)
this->init_state_ = FAILED;
return this->init_state_ == FAILED;
}
void BLEService::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,
@ -98,19 +111,19 @@ void BLEService::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t g
if (this->uuid_ == ESPBTUUID::from_uuid(param->create.service_id.id.uuid) &&
this->inst_id_ == param->create.service_id.id.inst_id) {
this->handle_ = param->create.service_handle;
xSemaphoreGive(this->create_lock_);
this->init_state_ = CREATED;
}
break;
}
case ESP_GATTS_START_EVT: {
if (param->start.service_handle == this->handle_) {
xSemaphoreGive(this->start_lock_);
this->running_state_ = RUNNING;
}
break;
}
case ESP_GATTS_STOP_EVT: {
if (param->start.service_handle == this->handle_) {
xSemaphoreGive(this->stop_lock_);
this->running_state_ = STOPPED;
}
break;
}

View File

@ -33,26 +33,44 @@ class BLEService {
BLEServer *get_server() { return this->server_; }
bool do_create(BLEServer *server);
void do_create(BLEServer *server);
void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
void start();
void stop();
protected:
bool errored_{false};
bool is_created();
bool is_failed();
bool is_running() { return this->running_state_ == RUNNING; }
bool is_starting() { return this->running_state_ == STARTING; }
protected:
std::vector<BLECharacteristic *> characteristics_;
BLECharacteristic *last_created_characteristic_{nullptr};
uint32_t created_characteristic_count_{0};
BLEServer *server_;
ESPBTUUID uuid_;
uint16_t num_handles_;
uint16_t handle_{0xFFFF};
uint8_t inst_id_;
SemaphoreHandle_t create_lock_;
SemaphoreHandle_t start_lock_;
SemaphoreHandle_t stop_lock_;
bool do_create_characteristics_();
enum InitState : uint8_t {
FAILED = 0x00,
INIT,
CREATING,
CREATING_DEPENDENTS,
CREATED,
} init_state_{INIT};
enum RunningState : uint8_t {
STARTING,
RUNNING,
STOPPING,
STOPPED,
} running_state_{STOPPED};
};
} // namespace esp32_ble

View File

@ -53,7 +53,7 @@ template<class T> class Queue {
SemaphoreHandle_t m;
};
// Received GAP and GATTC events are only queued, and get processed in the main loop().
// Received GAP, GATTC and GATTS events are only queued, and get processed in the main loop().
// This class stores each event in a single type.
class BLEEvent {
public:
@ -68,9 +68,18 @@ class BLEEvent {
this->event_.gattc.gattc_if = i;
memcpy(&this->event_.gattc.gattc_param, p, sizeof(esp_ble_gattc_cb_param_t));
// Need to also make a copy of notify event data.
if (e == ESP_GATTC_NOTIFY_EVT) {
memcpy(this->event_.gattc.notify_data, p->notify.value, p->notify.value_len);
this->event_.gattc.gattc_param.notify.value = this->event_.gattc.notify_data;
switch (e) {
case ESP_GATTC_NOTIFY_EVT:
memcpy(this->event_.gattc.data, p->notify.value, p->notify.value_len);
this->event_.gattc.gattc_param.notify.value = this->event_.gattc.data;
break;
case ESP_GATTC_READ_CHAR_EVT:
case ESP_GATTC_READ_DESCR_EVT:
memcpy(this->event_.gattc.data, p->read.value, p->read.value_len);
this->event_.gattc.gattc_param.read.value = this->event_.gattc.data;
break;
default:
break;
}
this->type_ = GATTC;
};
@ -79,6 +88,15 @@ class BLEEvent {
this->event_.gatts.gatts_event = e;
this->event_.gatts.gatts_if = i;
memcpy(&this->event_.gatts.gatts_param, p, sizeof(esp_ble_gatts_cb_param_t));
// Need to also make a copy of write data.
switch (e) {
case ESP_GATTS_WRITE_EVT:
memcpy(this->event_.gatts.data, p->write.value, p->write.len);
this->event_.gatts.gatts_param.write.value = this->event_.gatts.data;
break;
default:
break;
}
this->type_ = GATTS;
};
@ -92,13 +110,14 @@ class BLEEvent {
esp_gattc_cb_event_t gattc_event;
esp_gatt_if_t gattc_if;
esp_ble_gattc_cb_param_t gattc_param;
uint8_t notify_data[64];
uint8_t data[64];
} gattc;
struct gatts_event {
esp_gatts_cb_event_t gatts_event;
esp_gatt_if_t gatts_if;
esp_ble_gatts_cb_param_t gatts_param;
uint8_t data[64];
} gatts;
} event_;
enum ble_event_t : uint8_t {

View File

@ -14,7 +14,9 @@ ESP32ImprovComponent::ESP32ImprovComponent() { global_improv_component = this; }
void ESP32ImprovComponent::setup_service() {
this->service_ = esp32_ble::global_ble_server->create_service(improv::SERVICE_UUID, true);
}
void ESP32ImprovComponent::setup_characteristics() {
this->status_ = this->service_->create_characteristic(
improv::STATUS_UUID, esp32_ble::BLECharacteristic::PROPERTY_READ | esp32_ble::BLECharacteristic::PROPERTY_NOTIFY);
esp32_ble::BLEDescriptor *status_descriptor = new esp32_ble::BLE2902();
@ -62,16 +64,21 @@ void ESP32ImprovComponent::loop() {
if (this->status_indicator_ != nullptr)
this->status_indicator_->turn_off();
if (this->service_->is_created() && !this->setup_complete_) {
this->setup_characteristics();
}
if (this->should_start_ && this->setup_complete_) {
ESP_LOGD(TAG, "Starting Improv service...");
if (this->service_->is_running()) {
this->service_->get_server()->get_advertising()->start();
this->service_->start();
this->service_->get_server()->get_advertising()->start();
this->set_state_(improv::STATE_AWAITING_AUTHORIZATION);
this->set_error_(improv::ERROR_NONE);
this->should_start_ = false;
ESP_LOGD(TAG, "Service started!");
this->set_state_(improv::STATE_AWAITING_AUTHORIZATION);
this->set_error_(improv::ERROR_NONE);
this->should_start_ = false;
ESP_LOGD(TAG, "Service started!");
} else {
this->service_->start();
}
}
break;
case improv::STATE_AWAITING_AUTHORIZATION: {
@ -191,7 +198,7 @@ void ESP32ImprovComponent::start() {
this->should_start_ = true;
}
void ESP32ImprovComponent::end() {
void ESP32ImprovComponent::stop() {
this->set_timeout("end-service", 1000, [this] {
this->service_->stop();
this->set_state_(improv::STATE_STOPPED);

View File

@ -21,11 +21,12 @@ class ESP32ImprovComponent : public Component, public esp32_ble::BLEServiceCompo
void dump_config() override;
void loop() override;
void setup_service() override;
void setup_characteristics();
void on_client_disconnect() override;
float get_setup_priority() const override;
void start();
void end();
void start() override;
void stop() override;
bool is_active() const { return this->state_ != improv::STATE_STOPPED; }
void set_authorizer(binary_sensor::BinarySensor *authorizer) { this->authorizer_ = authorizer; }

View File

@ -508,7 +508,7 @@ void WiFiComponent::check_connecting_finished() {
}
#ifdef USE_IMPROV
if (this->is_esp32_improv_active_()) {
esp32_improv::global_improv_component->end();
esp32_improv::global_improv_component->stop();
}
#endif