mirror of
https://github.com/esphome/esphome.git
synced 2025-09-27 07:32:22 +01:00
[esp32_ble_server] Create custom services, characteristics and descriptors (#7009)
Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
from esphome import automation
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import binary_sensor, esp32_ble_server, output
|
||||
from esphome.components import binary_sensor, output
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID, CONF_ON_STATE, CONF_TRIGGER_ID
|
||||
|
||||
@@ -24,9 +24,7 @@ Error = improv_ns.enum("Error")
|
||||
State = improv_ns.enum("State")
|
||||
|
||||
esp32_improv_ns = cg.esphome_ns.namespace("esp32_improv")
|
||||
ESP32ImprovComponent = esp32_improv_ns.class_(
|
||||
"ESP32ImprovComponent", cg.Component, esp32_ble_server.BLEServiceComponent
|
||||
)
|
||||
ESP32ImprovComponent = esp32_improv_ns.class_("ESP32ImprovComponent", cg.Component)
|
||||
ESP32ImprovProvisionedTrigger = esp32_improv_ns.class_(
|
||||
"ESP32ImprovProvisionedTrigger", automation.Trigger.template()
|
||||
)
|
||||
@@ -47,7 +45,6 @@ ESP32ImprovStoppedTrigger = esp32_improv_ns.class_(
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(ESP32ImprovComponent),
|
||||
cv.GenerateID(CONF_BLE_SERVER_ID): cv.use_id(esp32_ble_server.BLEServer),
|
||||
cv.Required(CONF_AUTHORIZER): cv.Any(
|
||||
cv.none, cv.use_id(binary_sensor.BinarySensor)
|
||||
),
|
||||
@@ -100,9 +97,6 @@ async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
|
||||
ble_server = await cg.get_variable(config[CONF_BLE_SERVER_ID])
|
||||
cg.add(ble_server.register_service_component(var))
|
||||
|
||||
cg.add_define("USE_IMPROV")
|
||||
cg.add_library("improv/Improv", "1.2.4")
|
||||
|
||||
|
@@ -4,12 +4,15 @@
|
||||
#include "esphome/components/esp32_ble_server/ble_2902.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/components/bytebuffer/bytebuffer.h"
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
namespace esphome {
|
||||
namespace esp32_improv {
|
||||
|
||||
using namespace bytebuffer;
|
||||
|
||||
static const char *const TAG = "esp32_improv.component";
|
||||
static const char *const ESPHOME_MY_LINK = "https://my.home-assistant.io/redirect/config_flow_start?domain=esphome";
|
||||
|
||||
@@ -26,6 +29,8 @@ void ESP32ImprovComponent::setup() {
|
||||
});
|
||||
}
|
||||
#endif
|
||||
global_ble_server->on(BLEServerEvt::EmptyEvt::ON_DISCONNECT,
|
||||
[this](uint16_t conn_id) { this->set_error_(improv::ERROR_NONE); });
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::setup_characteristics() {
|
||||
@@ -40,11 +45,12 @@ void ESP32ImprovComponent::setup_characteristics() {
|
||||
this->error_->add_descriptor(error_descriptor);
|
||||
|
||||
this->rpc_ = this->service_->create_characteristic(improv::RPC_COMMAND_UUID, BLECharacteristic::PROPERTY_WRITE);
|
||||
this->rpc_->on_write([this](const std::vector<uint8_t> &data) {
|
||||
if (!data.empty()) {
|
||||
this->incoming_data_.insert(this->incoming_data_.end(), data.begin(), data.end());
|
||||
}
|
||||
});
|
||||
this->rpc_->EventEmitter<BLECharacteristicEvt::VectorEvt, std::vector<uint8_t>, uint16_t>::on(
|
||||
BLECharacteristicEvt::VectorEvt::ON_WRITE, [this](const std::vector<uint8_t> &data, uint16_t id) {
|
||||
if (!data.empty()) {
|
||||
this->incoming_data_.insert(this->incoming_data_.end(), data.begin(), data.end());
|
||||
}
|
||||
});
|
||||
BLEDescriptor *rpc_descriptor = new BLE2902();
|
||||
this->rpc_->add_descriptor(rpc_descriptor);
|
||||
|
||||
@@ -62,7 +68,7 @@ void ESP32ImprovComponent::setup_characteristics() {
|
||||
if (this->status_indicator_ != nullptr)
|
||||
capabilities |= improv::CAPABILITY_IDENTIFY;
|
||||
#endif
|
||||
this->capabilities_->set_value(capabilities);
|
||||
this->capabilities_->set_value(ByteBuffer::wrap(capabilities));
|
||||
this->setup_complete_ = true;
|
||||
}
|
||||
|
||||
@@ -80,8 +86,7 @@ void ESP32ImprovComponent::loop() {
|
||||
if (this->service_ == nullptr) {
|
||||
// Setup the service
|
||||
ESP_LOGD(TAG, "Creating Improv service");
|
||||
global_ble_server->create_service(ESPBTUUID::from_raw(improv::SERVICE_UUID), true);
|
||||
this->service_ = global_ble_server->get_service(ESPBTUUID::from_raw(improv::SERVICE_UUID));
|
||||
this->service_ = global_ble_server->create_service(ESPBTUUID::from_raw(improv::SERVICE_UUID), true);
|
||||
this->setup_characteristics();
|
||||
}
|
||||
|
||||
@@ -93,15 +98,15 @@ void ESP32ImprovComponent::loop() {
|
||||
case improv::STATE_STOPPED:
|
||||
this->set_status_indicator_state_(false);
|
||||
|
||||
if (this->service_->is_created() && this->should_start_ && this->setup_complete_) {
|
||||
if (this->service_->is_running()) {
|
||||
if (this->should_start_ && this->setup_complete_) {
|
||||
if (this->service_->is_created()) {
|
||||
this->service_->start();
|
||||
} else if (this->service_->is_running()) {
|
||||
esp32_ble::global_ble->advertising_start();
|
||||
|
||||
this->set_state_(improv::STATE_AWAITING_AUTHORIZATION);
|
||||
this->set_error_(improv::ERROR_NONE);
|
||||
ESP_LOGD(TAG, "Service started!");
|
||||
} else {
|
||||
this->service_->start();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -199,8 +204,7 @@ void ESP32ImprovComponent::set_state_(improv::State state) {
|
||||
ESP_LOGV(TAG, "Setting state: %d", state);
|
||||
this->state_ = state;
|
||||
if (this->status_->get_value().empty() || this->status_->get_value()[0] != state) {
|
||||
uint8_t data[1]{state};
|
||||
this->status_->set_value(data, 1);
|
||||
this->status_->set_value(ByteBuffer::wrap(static_cast<uint8_t>(state)));
|
||||
if (state != improv::STATE_STOPPED)
|
||||
this->status_->notify();
|
||||
}
|
||||
@@ -232,15 +236,14 @@ void ESP32ImprovComponent::set_error_(improv::Error error) {
|
||||
ESP_LOGE(TAG, "Error: %d", error);
|
||||
}
|
||||
if (this->error_->get_value().empty() || this->error_->get_value()[0] != error) {
|
||||
uint8_t data[1]{error};
|
||||
this->error_->set_value(data, 1);
|
||||
this->error_->set_value(ByteBuffer::wrap(static_cast<uint8_t>(error)));
|
||||
if (this->state_ != improv::STATE_STOPPED)
|
||||
this->error_->notify();
|
||||
}
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::send_response_(std::vector<uint8_t> &response) {
|
||||
this->rpc_response_->set_value(response);
|
||||
this->rpc_response_->set_value(ByteBuffer::wrap(response));
|
||||
if (this->state_ != improv::STATE_STOPPED)
|
||||
this->rpc_response_->notify();
|
||||
}
|
||||
@@ -339,8 +342,6 @@ void ESP32ImprovComponent::on_wifi_connect_timeout_() {
|
||||
wifi::global_wifi_component->clear_sta();
|
||||
}
|
||||
|
||||
void ESP32ImprovComponent::on_client_disconnect() { this->set_error_(improv::ERROR_NONE); };
|
||||
|
||||
ESP32ImprovComponent *global_improv_component = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
} // namespace esp32_improv
|
||||
|
@@ -32,18 +32,17 @@ namespace esp32_improv {
|
||||
|
||||
using namespace esp32_ble_server;
|
||||
|
||||
class ESP32ImprovComponent : public Component, public BLEServiceComponent {
|
||||
class ESP32ImprovComponent : public Component {
|
||||
public:
|
||||
ESP32ImprovComponent();
|
||||
void dump_config() override;
|
||||
void loop() override;
|
||||
void setup() override;
|
||||
void setup_characteristics();
|
||||
void on_client_disconnect() override;
|
||||
|
||||
float get_setup_priority() const override;
|
||||
void start() override;
|
||||
void stop() override;
|
||||
void start();
|
||||
void stop();
|
||||
bool is_active() const { return this->state_ != improv::STATE_STOPPED; }
|
||||
|
||||
#ifdef USE_ESP32_IMPROV_STATE_CALLBACK
|
||||
|
Reference in New Issue
Block a user