Fix linting issues

This commit is contained in:
Rapsssito 2024-06-29 12:16:25 +02:00
parent 15852a3cfe
commit c72bb488f2
9 changed files with 126 additions and 72 deletions

View file

@ -1,7 +1,14 @@
from esphome import automation from esphome import automation
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_MODEL, CONF_UUID, CONF_SERVICES, CONF_VALUE, CONF_MAX_LENGTH, CONF_ON_CLIENT_CONNECTED, CONF_ON_CLIENT_DISCONNECTED from esphome.const import (
CONF_ID,
CONF_MODEL,
CONF_UUID,
CONF_SERVICES,
CONF_VALUE,
CONF_MAX_LENGTH
)
from esphome.components import esp32_ble from esphome.components import esp32_ble
from esphome.core import CORE from esphome.core import CORE
from esphome.components.esp32 import add_idf_sdkconfig_option from esphome.components.esp32 import add_idf_sdkconfig_option
@ -29,11 +36,15 @@ BLEServer = esp32_ble_server_ns.class_(
esp32_ble.GATTsEventHandler, esp32_ble.GATTsEventHandler,
cg.Parented.template(esp32_ble.ESP32BLE), cg.Parented.template(esp32_ble.ESP32BLE),
) )
BLEServerAutomationInterface = esp32_ble_server_ns.namespace("BLEServerAutomationInterface") BLEServerAutomationInterface = esp32_ble_server_ns.namespace(
"BLEServerAutomationInterface"
)
BLEDescriptor = esp32_ble_server_ns.class_("BLEDescriptor") BLEDescriptor = esp32_ble_server_ns.class_("BLEDescriptor")
BLECharacteristic = esp32_ble_server_ns.class_("BLECharacteristic") BLECharacteristic = esp32_ble_server_ns.class_("BLECharacteristic")
BLEService = esp32_ble_server_ns.class_("BLEService") BLEService = esp32_ble_server_ns.class_("BLEService")
BLECharacteristicSetValueAction = BLEServerAutomationInterface.class_("BLECharacteristicSetValueAction", automation.Action) BLECharacteristicSetValueAction = BLEServerAutomationInterface.class_(
"BLECharacteristicSetValueAction", automation.Action
)
def validate_uuid(value): def validate_uuid(value):
@ -42,17 +53,18 @@ def validate_uuid(value):
return value return value
# Define a schema for the properties
PROPERTIES_SCHEMA = cv.All( PROPERTIES_SCHEMA = cv.All(
cv.ensure_list(cv.one_of( cv.ensure_list(
"READ", cv.one_of(
"WRITE", "READ",
"NOTIFY", "WRITE",
"BROADCAST", "NOTIFY",
"INDICATE", "BROADCAST",
"WRITE_NR", "INDICATE",
upper=True, "WRITE_NR",
)), upper=True,
)
),
cv.Length(min=1) cv.Length(min=1)
) )
@ -84,8 +96,12 @@ SERVICE_CHARACTERISTIC_SCHEMA = cv.Schema(
cv.Required(CONF_UUID): UUID_SCHEMA, cv.Required(CONF_UUID): UUID_SCHEMA,
cv.Required(CONF_PROPERTIES): PROPERTIES_SCHEMA, cv.Required(CONF_PROPERTIES): PROPERTIES_SCHEMA,
cv.Optional(CONF_VALUE): CHARACTERISTIC_VALUE_SCHEMA, cv.Optional(CONF_VALUE): CHARACTERISTIC_VALUE_SCHEMA,
cv.Optional(CONF_DESCRIPTORS, default=[]): cv.ensure_list(SERVICE_CHARACTERISTIC_DESCRIPTOR_SCHEMA), cv.Optional(CONF_DESCRIPTORS, default=[]): cv.ensure_list(
cv.Optional(CONF_ON_WRITE): automation.validate_automation({cv.GenerateID(): cv.declare_id(BLECharacteristic)}, single=True), SERVICE_CHARACTERISTIC_DESCRIPTOR_SCHEMA
),
cv.Optional(CONF_ON_WRITE): automation.validate_automation(
{cv.GenerateID(): cv.declare_id(BLECharacteristic)}, single=True
),
} }
) )
@ -95,7 +111,9 @@ SERVICE_SCHEMA = cv.Schema(
cv.Required(CONF_UUID): UUID_SCHEMA, cv.Required(CONF_UUID): UUID_SCHEMA,
cv.Optional(CONF_ADVERTISE, default=False): cv.boolean, cv.Optional(CONF_ADVERTISE, default=False): cv.boolean,
cv.Optional(CONF_NUM_HANDLES, default=0): cv.int_, cv.Optional(CONF_NUM_HANDLES, default=0): cv.int_,
cv.Optional(CONF_CHARACTERISTICS, default=[]): cv.ensure_list(SERVICE_CHARACTERISTIC_SCHEMA), cv.Optional(CONF_CHARACTERISTICS, default=[]): cv.ensure_list(
SERVICE_CHARACTERISTIC_SCHEMA
),
} }
) )
@ -117,17 +135,18 @@ def parse_properties(properties):
if prop == "READ": if prop == "READ":
result = result | BLECharacteristic_ns.PROPERTY_READ result = result | BLECharacteristic_ns.PROPERTY_READ
elif prop == "WRITE": elif prop == "WRITE":
result = result | BLECharacteristic_ns.PROPERTY_WRITE result = result | BLECharacteristic_ns.PROPERTY_WRITE
elif prop == "NOTIFY": elif prop == "NOTIFY":
result = result | BLECharacteristic_ns.PROPERTY_NOTIFY result = result | BLECharacteristic_ns.PROPERTY_NOTIFY
elif prop == "BROADCAST": elif prop == "BROADCAST":
result = result | BLECharacteristic_ns.PROPERTY_BROADCAST result = result | BLECharacteristic_ns.PROPERTY_BROADCAST
elif prop == "INDICATE": elif prop == "INDICATE":
result = result | BLECharacteristic_ns.PROPERTY_INDICATE result = result | BLECharacteristic_ns.PROPERTY_INDICATE
elif prop == "WRITE_NR": elif prop == "WRITE_NR":
result = result | BLECharacteristic_ns.PROPERTY_WRITE_NR result = result | BLECharacteristic_ns.PROPERTY_WRITE_NR
return result return result
def parse_uuid(uuid): def parse_uuid(uuid):
# If the UUID is a string, use from_raw # If the UUID is a string, use from_raw
if isinstance(uuid, str): if isinstance(uuid, str):
@ -135,11 +154,13 @@ def parse_uuid(uuid):
# Otherwise, use from_uint32 # Otherwise, use from_uint32
return ESPBTUUID_ns.from_uint32(uuid) return ESPBTUUID_ns.from_uint32(uuid)
def parse_value(value): def parse_value(value):
if isinstance(value, list): if isinstance(value, list):
return cg.std_vector.template(cg.uint8)(value) return cg.std_vector.template(cg.uint8)(value)
return value return value
def calculate_num_handles(service_config): def calculate_num_handles(service_config):
total = 1 total = 1
for char_conf in service_config[CONF_CHARACTERISTICS]: for char_conf in service_config[CONF_CHARACTERISTICS]:
@ -148,6 +169,7 @@ def calculate_num_handles(service_config):
total += 1 total += 1
return total return total
async def to_code(config): async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID]) var = cg.new_Pvariable(config[CONF_ID])
@ -167,21 +189,31 @@ async def to_code(config):
# If num_handles is 0, calculate the optimal number of handles based on the number of characteristics and descriptors # If num_handles is 0, calculate the optimal number of handles based on the number of characteristics and descriptors
if num_handles == 0: if num_handles == 0:
num_handles = calculate_num_handles(service_config) num_handles = calculate_num_handles(service_config)
service_var = cg.Pvariable(service_config[CONF_ID], var.create_service( service_var = cg.Pvariable(
parse_uuid(service_config[CONF_UUID]), service_config[CONF_ID],
service_config[CONF_ADVERTISE], var.create_service(
num_handles, parse_uuid(service_config[CONF_UUID]),
)) service_config[CONF_ADVERTISE],
num_handles,
),
)
for char_conf in service_config[CONF_CHARACTERISTICS]: for char_conf in service_config[CONF_CHARACTERISTICS]:
char_var = cg.Pvariable(char_conf[CONF_ID], service_var.create_characteristic( char_var = cg.Pvariable(
parse_uuid(char_conf[CONF_UUID]), char_conf[CONF_ID],
parse_properties(char_conf[CONF_PROPERTIES]) service_var.create_characteristic(
)) parse_uuid(char_conf[CONF_UUID]),
parse_properties(char_conf[CONF_PROPERTIES])
),
)
if CONF_ON_WRITE in char_conf: if CONF_ON_WRITE in char_conf:
on_write_conf = char_conf[CONF_ON_WRITE] on_write_conf = char_conf[CONF_ON_WRITE]
if "WRITE" not in char_conf[CONF_PROPERTIES]: if "WRITE" not in char_conf[CONF_PROPERTIES]:
raise cv.Invalid("on_write requires the WRITE property") raise cv.Invalid("on_write requires the WRITE property")
await automation.build_automation(BLEServerAutomationInterface.create_on_write_trigger(char_var), [(cg.std_string, "x")], on_write_conf) await automation.build_automation(
BLEServerAutomationInterface.create_on_write_trigger(char_var),
[(cg.std_string, "x")],
on_write_conf,
)
if CONF_VALUE in char_conf: if CONF_VALUE in char_conf:
cg.add(char_var.set_value(parse_value(char_conf[CONF_VALUE]))) cg.add(char_var.set_value(parse_value(char_conf[CONF_VALUE])))
for descriptor_conf in char_conf[CONF_DESCRIPTORS]: for descriptor_conf in char_conf[CONF_DESCRIPTORS]:
@ -189,7 +221,11 @@ async def to_code(config):
# If max_length is 0, calculate the optimal length based on the value # If max_length is 0, calculate the optimal length based on the value
if max_length == 0: if max_length == 0:
max_length = len(parse_value(descriptor_conf[CONF_VALUE])) max_length = len(parse_value(descriptor_conf[CONF_VALUE]))
desc_var = cg.new_Pvariable(descriptor_conf[CONF_ID], parse_uuid(descriptor_conf[CONF_UUID]), max_length) desc_var = cg.new_Pvariable(
descriptor_conf[CONF_ID],
parse_uuid(descriptor_conf[CONF_UUID]),
max_length,
)
if CONF_VALUE in descriptor_conf: if CONF_VALUE in descriptor_conf:
cg.add(desc_var.set_value(parse_value(descriptor_conf[CONF_VALUE]))) cg.add(desc_var.set_value(parse_value(descriptor_conf[CONF_VALUE])))
cg.add(var.enqueue_start_service(service_var)) cg.add(var.enqueue_start_service(service_var))
@ -197,10 +233,16 @@ async def to_code(config):
if CORE.using_esp_idf: if CORE.using_esp_idf:
add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True) add_idf_sdkconfig_option("CONFIG_BT_ENABLED", True)
@automation.register_action("ble_server.characteristic_set_value", BLECharacteristicSetValueAction, cv.Schema({ @automation.register_action(
cv.Required(CONF_ID): cv.use_id(BLECharacteristic), "ble_server.characteristic_set_value",
cv.Required(CONF_VALUE): cv.templatable(cv.string), BLECharacteristicSetValueAction,
})) cv.Schema(
{
cv.Required(CONF_ID): cv.use_id(BLECharacteristic),
cv.Required(CONF_VALUE): cv.templatable(cv.string),
}
),
)
async def ble_server_characteristic_set_value(config, action_id, template_arg, args): async def ble_server_characteristic_set_value(config, action_id, template_arg, args):
paren = await cg.get_variable(config[CONF_ID]) paren = await cg.get_variable(config[CONF_ID])
var = cg.new_Pvariable(action_id, template_arg, paren) var = cg.new_Pvariable(action_id, template_arg, paren)

View file

@ -289,7 +289,8 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
} }
if (!param->write.is_prep) { if (!param->write.is_prep) {
if (this->on_write_) this->on_write_(this->value_); if (this->on_write_)
this->on_write_(this->value_);
} }
break; break;
@ -300,7 +301,8 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
break; break;
this->write_event_ = false; this->write_event_ = false;
if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) { if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) {
if (this->on_write_) this->on_write_(this->value_); if (this->on_write_)
this->on_write_(this->value_);
} }
esp_err_t err = esp_err_t err =
esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, nullptr); esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, nullptr);

View file

@ -38,12 +38,8 @@ void BLEDescriptor::do_create(BLECharacteristic *characteristic) {
this->state_ = CREATING; this->state_ = CREATING;
} }
void BLEDescriptor::set_value(std::vector<uint8_t> value) { void BLEDescriptor::set_value(std::vector<uint8_t> value) { this->set_value(value.data(), value.size()); }
this->set_value(value.data(), value.size()); void BLEDescriptor::set_value(const std::string &value) { this->set_value((uint8_t *) value.data(), value.length()); }
}
void BLEDescriptor::set_value(const std::string &value) {
this->set_value((uint8_t *) value.data(), value.length());
}
void BLEDescriptor::set_value(uint8_t &data) { void BLEDescriptor::set_value(uint8_t &data) {
uint8_t temp[1]; uint8_t temp[1];
temp[0] = data; temp[0] = data;

View file

@ -48,21 +48,23 @@ void BLEServer::loop() {
} }
switch (this->state_) { switch (this->state_) {
case RUNNING: { case RUNNING: {
if (this->services_to_start_.empty()) break; // Start all services that are pending to start
uint16_t index_to_remove = 0; if (!this->services_to_start_.empty()) {
// Iterate over the services to start uint16_t index_to_remove = 0;
for (unsigned i = 0; i < this->services_to_start_.size(); i++) { // Iterate over the services to start
BLEService *service = this->services_to_start_[i]; for (unsigned i = 0; i < this->services_to_start_.size(); i++) {
if (service->is_created()) { BLEService *service = this->services_to_start_[i];
service->start(); if (service->is_created()) {
} else { service->start();
index_to_remove = i + 1; } else {
index_to_remove = i + 1;
}
}
// Remove the services that have been started
if (index_to_remove > 0) {
this->services_to_start_.erase(this->services_to_start_.begin(),
this->services_to_start_.begin() + index_to_remove - 1);
} }
}
// Remove the services that have been started
if (index_to_remove > 0) {
this->services_to_start_.erase(this->services_to_start_.begin(),
this->services_to_start_.begin() + index_to_remove - 1);
} }
break; break;
} }
@ -83,7 +85,8 @@ void BLEServer::loop() {
pair.second->do_create(this); pair.second->do_create(this);
} }
if (this->device_information_service_ == nullptr) { if (this->device_information_service_ == nullptr) {
this->device_information_service_ = this->create_service(ESPBTUUID::from_uint16(DEVICE_INFORMATION_SERVICE_UUID), false, 7); this->device_information_service_ =
this->create_service(ESPBTUUID::from_uint16(DEVICE_INFORMATION_SERVICE_UUID), false, 7);
this->create_device_characteristics_(); this->create_device_characteristics_();
} }
this->state_ = STARTING_SERVICE; this->state_ = STARTING_SERVICE;
@ -148,7 +151,8 @@ BLEService *BLEServer::create_service(ESPBTUUID uuid, bool advertise, uint16_t n
ESP_LOGW(TAG, "Could not create BLE service %s, too many instances", uuid.to_string().c_str()); ESP_LOGW(TAG, "Could not create BLE service %s, too many instances", uuid.to_string().c_str());
return nullptr; return nullptr;
} }
BLEService *service = new BLEService(uuid, num_handles, inst_id, advertise); // NOLINT(cppcoreguidelines-owning-memory) BLEService *service =
new BLEService(uuid, num_handles, inst_id, advertise); // NOLINT(cppcoreguidelines-owning-memory)
this->services_.emplace(BLEServer::get_service_key(uuid, inst_id), service); this->services_.emplace(BLEServer::get_service_key(uuid, inst_id), service);
if (this->parent_->is_active() && this->registered_) { if (this->parent_->is_active() && this->registered_) {
service->do_create(this); service->do_create(this);

View file

@ -29,15 +29,15 @@ using namespace esp32_ble;
class BLEServerAutomationInterface { class BLEServerAutomationInterface {
public: public:
static Trigger<std::string> *create_on_write_trigger(BLECharacteristic *characteristic); static Trigger<std::string> *create_on_write_trigger(BLECharacteristic *characteristic);
template<typename... Ts> class BLECharacteristicSetValueAction : public Action<Ts...> {
public:
BLECharacteristicSetValueAction(BLECharacteristic *characteristic) : parent_(characteristic) {}
TEMPLATABLE_VALUE(std::string, value)
void play(Ts... x) override {this->parent_->set_value(this->value_.value(x...)); }
protected: template<typename... Ts> class BLECharacteristicSetValueAction : public Action<Ts...> {
BLECharacteristic *parent_; public:
BLECharacteristicSetValueAction(BLECharacteristic *characteristic) : parent_(characteristic) {}
TEMPLATABLE_VALUE(std::string, value)
void play(Ts... x) override { this->parent_->set_value(this->value_.value(x...)); }
protected:
BLECharacteristic *parent_;
}; };
}; };

View file

@ -58,6 +58,16 @@ void BLEService::do_create(BLEServer *server) {
this->state_ = CREATING; 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 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() { void BLEService::do_delete() {
if (this->state_ == DELETING || this->state_ == DELETED) if (this->state_ == DELETING || this->state_ == DELETED)
return; return;

View file

@ -52,8 +52,8 @@ class BLEService {
bool is_deleted() { return this->state_ == DELETED; } 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_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 on_client_disconnect(const std::function<void(const uint16_t)> &&func) { this->on_client_disconnect_ = func; }
void emit_client_connect(const uint16_t conn_id) { if (this->on_client_connect_ && this->is_running()) this->on_client_connect_(conn_id); } void emit_client_connect(const uint16_t conn_id);
void emit_client_disconnect(const uint16_t conn_id) { if (this->on_client_disconnect_ && this->is_running()) this->on_client_disconnect_(conn_id); } void emit_client_disconnect(const uint16_t conn_id);
protected: protected:
std::vector<BLECharacteristic *> characteristics_; std::vector<BLECharacteristic *> characteristics_;

View file

@ -1,6 +1,6 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.components import binary_sensor, output, esp32_ble_server from esphome.components import binary_sensor, output
from esphome.const import CONF_ID from esphome.const import CONF_ID

View file

@ -30,4 +30,4 @@ esp32_ble_server:
ESP_LOGD("BLE", "Received: %s", x.c_str()); ESP_LOGD("BLE", "Received: %s", x.c_str());
- ble_server.characteristic_set_value: - ble_server.characteristic_set_value:
id: test_change_characteristic id: test_change_characteristic
value: !lambda 'return "Echo " + x + "";' value: !lambda 'return "Echo " + x + "";'