Makes ble_client.ble_write's action value templatable (#3715)

This commit is contained in:
rbaron 2022-08-16 04:40:58 +02:00 committed by Jesse Hills
parent 8cfcd5904c
commit d07a6704d5
No known key found for this signature in database
GPG key ID: BEAAE804EFD8E83A
4 changed files with 43 additions and 12 deletions

View file

@ -82,7 +82,7 @@ BLE_WRITE_ACTION_SCHEMA = cv.Schema(
cv.Required(CONF_ID): cv.use_id(BLEClient), cv.Required(CONF_ID): cv.use_id(BLEClient),
cv.Required(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid, cv.Required(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid,
cv.Required(CONF_CHARACTERISTIC_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): async def ble_write_to_code(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)
value = config[CONF_VALUE] 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]) serv_uuid128 = esp32_ble_tracker.as_reversed_hex_array(config[CONF_SERVICE_UUID])
cg.add(var.set_service_uuid128(serv_uuid128)) cg.add(var.set_service_uuid128(serv_uuid128))
char_uuid128 = esp32_ble_tracker.as_reversed_hex_array( char_uuid128 = esp32_ble_tracker.as_reversed_hex_array(

View file

@ -10,7 +10,7 @@ namespace esphome {
namespace ble_client { namespace ble_client {
static const char *const TAG = "ble_client.automation"; static const char *const TAG = "ble_client.automation";
void BLEWriterClientNode::write() { void BLEWriterClientNode::write(const std::vector<uint8_t> &value) {
if (this->node_state != espbt::ClientState::ESTABLISHED) { if (this->node_state != espbt::ClientState::ESTABLISHED) {
ESP_LOGW(TAG, "Cannot write to BLE characteristic - not connected"); ESP_LOGW(TAG, "Cannot write to BLE characteristic - not connected");
return; return;
@ -29,9 +29,10 @@ void BLEWriterClientNode::write() {
ESP_LOGE(TAG, "Characteristic %s does not allow writing", this->char_uuid_.to_string().c_str()); ESP_LOGE(TAG, "Characteristic %s does not allow writing", this->char_uuid_.to_string().c_str());
return; return;
} }
ESP_LOGVV(TAG, "Will write %d bytes: %s", this->value_.size(), format_hex_pretty(this->value_).c_str()); 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_, esp_err_t err =
value_.size(), value_.data(), write_type, ESP_GATT_AUTH_REQ_NONE); esp_ble_gattc_write_char(this->parent()->gattc_if, this->parent()->conn_id, this->ble_char_handle_, value.size(),
const_cast<uint8_t *>(value.data()), write_type, ESP_GATT_AUTH_REQ_NONE);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGE(TAG, "Error writing to characteristic: %s!", esp_err_to_name(err)); ESP_LOGE(TAG, "Error writing to characteristic: %s!", esp_err_to_name(err));
} }

View file

@ -42,10 +42,8 @@ class BLEWriterClientNode : public BLEClientNode {
ble_client_ = ble_client; ble_client_ = ble_client;
} }
void set_value(std::vector<uint8_t> value) { value_ = std::move(value); } // Attempts to write the contents of value to char_uuid_.
void write(const std::vector<uint8_t> &value);
// Attempts to write the contents of value_ to char_uuid_.
void write();
void set_char_uuid128(uint8_t *uuid) { this->char_uuid_ = espbt::ESPBTUUID::from_raw(uuid); } 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_; esp_gatt_char_prop_t char_props_;
espbt::ESPBTUUID service_uuid_; espbt::ESPBTUUID service_uuid_;
espbt::ESPBTUUID char_uuid_; espbt::ESPBTUUID char_uuid_;
std::vector<uint8_t> value_;
}; };
template<typename... Ts> class BLEClientWriteAction : public Action<Ts...>, public BLEWriterClientNode { template<typename... Ts> class BLEClientWriteAction : public Action<Ts...>, public BLEWriterClientNode {
public: public:
BLEClientWriteAction(BLEClient *ble_client) : BLEWriterClientNode(ble_client) {} 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<std::vector<uint8_t>(Ts...)> func) {
this->value_template_ = std::move(func);
has_simple_value_ = false;
}
void set_value_simple(const std::vector<uint8_t> &value) {
this->value_simple_ = value;
has_simple_value_ = true;
}
private:
bool has_simple_value_ = true;
std::vector<uint8_t> value_simple_;
std::function<std::vector<uint8_t>(Ts...)> value_template_{};
}; };
} // namespace ble_client } // namespace ble_client

View file

@ -615,3 +615,9 @@ switch:
service_uuid: F61E3BE9-2826-A81B-970A-4D4DECFABBAE service_uuid: F61E3BE9-2826-A81B-970A-4D4DECFABBAE
characteristic_uuid: 6490FAFE-0734-732C-8705-91B653A081FC characteristic_uuid: 6490FAFE-0734-732C-8705-91B653A081FC
value: [0x01, 0xab, 0xff] 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};