From 1a524a5a50a3e5630d10c43a8240cd6b74c11d86 Mon Sep 17 00:00:00 2001 From: rbaron Date: Tue, 16 Aug 2022 04:40:58 +0200 Subject: [PATCH] Makes ble_client.ble_write's action value templatable (#3715) --- esphome/components/ble_client/__init__.py | 10 +++++-- esphome/components/ble_client/automation.cpp | 9 +++--- esphome/components/ble_client/automation.h | 30 ++++++++++++++++---- tests/test2.yaml | 6 ++++ 4 files changed, 43 insertions(+), 12 deletions(-) diff --git a/esphome/components/ble_client/__init__.py b/esphome/components/ble_client/__init__.py index 6c13e7fcf5..4b7d5f5b8a 100644 --- a/esphome/components/ble_client/__init__.py +++ b/esphome/components/ble_client/__init__.py @@ -82,7 +82,7 @@ BLE_WRITE_ACTION_SCHEMA = cv.Schema( cv.Required(CONF_ID): cv.use_id(BLEClient), cv.Required(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid, cv.Required(CONF_CHARACTERISTIC_UUID): esp32_ble_tracker.bt_uuid, - cv.Required(CONF_VALUE): cv.ensure_list(cv.hex_uint8_t), + cv.Required(CONF_VALUE): cv.templatable(cv.ensure_list(cv.hex_uint8_t)), } ) @@ -93,8 +93,14 @@ BLE_WRITE_ACTION_SCHEMA = cv.Schema( async def ble_write_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_arg, paren) + value = config[CONF_VALUE] - cg.add(var.set_value(value)) + if cg.is_template(value): + templ = await cg.templatable(value, args, cg.std_vector.template(cg.uint8)) + cg.add(var.set_value_template(templ)) + else: + cg.add(var.set_value_simple(value)) + serv_uuid128 = esp32_ble_tracker.as_reversed_hex_array(config[CONF_SERVICE_UUID]) cg.add(var.set_service_uuid128(serv_uuid128)) char_uuid128 = esp32_ble_tracker.as_reversed_hex_array( diff --git a/esphome/components/ble_client/automation.cpp b/esphome/components/ble_client/automation.cpp index 8d5fe96570..6918ab31b4 100644 --- a/esphome/components/ble_client/automation.cpp +++ b/esphome/components/ble_client/automation.cpp @@ -10,7 +10,7 @@ namespace esphome { namespace ble_client { static const char *const TAG = "ble_client.automation"; -void BLEWriterClientNode::write() { +void BLEWriterClientNode::write(const std::vector &value) { if (this->node_state != espbt::ClientState::ESTABLISHED) { ESP_LOGW(TAG, "Cannot write to BLE characteristic - not connected"); return; @@ -29,9 +29,10 @@ void BLEWriterClientNode::write() { ESP_LOGE(TAG, "Characteristic %s does not allow writing", this->char_uuid_.to_string().c_str()); return; } - ESP_LOGVV(TAG, "Will write %d bytes: %s", this->value_.size(), format_hex_pretty(this->value_).c_str()); - esp_err_t err = esp_ble_gattc_write_char(this->parent()->gattc_if, this->parent()->conn_id, this->ble_char_handle_, - value_.size(), value_.data(), write_type, ESP_GATT_AUTH_REQ_NONE); + ESP_LOGVV(TAG, "Will write %d bytes: %s", value.size(), format_hex_pretty(value).c_str()); + esp_err_t err = + esp_ble_gattc_write_char(this->parent()->gattc_if, this->parent()->conn_id, this->ble_char_handle_, value.size(), + const_cast(value.data()), write_type, ESP_GATT_AUTH_REQ_NONE); if (err != ESP_OK) { ESP_LOGE(TAG, "Error writing to characteristic: %s!", esp_err_to_name(err)); } diff --git a/esphome/components/ble_client/automation.h b/esphome/components/ble_client/automation.h index 828cbca662..38e64ebd76 100644 --- a/esphome/components/ble_client/automation.h +++ b/esphome/components/ble_client/automation.h @@ -42,10 +42,8 @@ class BLEWriterClientNode : public BLEClientNode { ble_client_ = ble_client; } - void set_value(std::vector value) { value_ = std::move(value); } - - // Attempts to write the contents of value_ to char_uuid_. - void write(); + // Attempts to write the contents of value to char_uuid_. + void write(const std::vector &value); void set_char_uuid128(uint8_t *uuid) { this->char_uuid_ = espbt::ESPBTUUID::from_raw(uuid); } @@ -60,14 +58,34 @@ class BLEWriterClientNode : public BLEClientNode { esp_gatt_char_prop_t char_props_; espbt::ESPBTUUID service_uuid_; espbt::ESPBTUUID char_uuid_; - std::vector value_; }; template class BLEClientWriteAction : public Action, public BLEWriterClientNode { public: BLEClientWriteAction(BLEClient *ble_client) : BLEWriterClientNode(ble_client) {} - void play(Ts... x) override { return write(); } + void play(Ts... x) override { + if (has_simple_value_) { + return write(this->value_simple_); + } else { + return write(this->value_template_(x...)); + } + } + + void set_value_template(std::function(Ts...)> func) { + this->value_template_ = std::move(func); + has_simple_value_ = false; + } + + void set_value_simple(const std::vector &value) { + this->value_simple_ = value; + has_simple_value_ = true; + } + + private: + bool has_simple_value_ = true; + std::vector value_simple_; + std::function(Ts...)> value_template_{}; }; } // namespace ble_client diff --git a/tests/test2.yaml b/tests/test2.yaml index 5dd9e76a2f..110e8e6625 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -615,3 +615,9 @@ switch: service_uuid: F61E3BE9-2826-A81B-970A-4D4DECFABBAE characteristic_uuid: 6490FAFE-0734-732C-8705-91B653A081FC value: [0x01, 0xab, 0xff] + - ble_client.ble_write: + id: airthings01 + service_uuid: F61E3BE9-2826-A81B-970A-4D4DECFABBAE + characteristic_uuid: 6490FAFE-0734-732C-8705-91B653A081FC + value: !lambda |- + return {0x13, 0x37};