mirror of
https://github.com/esphome/esphome.git
synced 2026-06-02 11:08:06 +08:00
[light] Add zero-copy support for API effect commands (#12384)
This commit is contained in:
@@ -579,7 +579,7 @@ message LightCommandRequest {
|
|||||||
bool has_flash_length = 16;
|
bool has_flash_length = 16;
|
||||||
uint32 flash_length = 17;
|
uint32 flash_length = 17;
|
||||||
bool has_effect = 18;
|
bool has_effect = 18;
|
||||||
string effect = 19;
|
string effect = 19 [(pointer_to_buffer) = true];
|
||||||
uint32 device_id = 28 [(field_ifdef) = "USE_DEVICES"];
|
uint32 device_id = 28 [(field_ifdef) = "USE_DEVICES"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -533,7 +533,7 @@ void APIConnection::light_command(const LightCommandRequest &msg) {
|
|||||||
if (msg.has_flash_length)
|
if (msg.has_flash_length)
|
||||||
call.set_flash_length(msg.flash_length);
|
call.set_flash_length(msg.flash_length);
|
||||||
if (msg.has_effect)
|
if (msg.has_effect)
|
||||||
call.set_effect(msg.effect);
|
call.set_effect(reinterpret_cast<const char *>(msg.effect), msg.effect_len);
|
||||||
call.perform();
|
call.perform();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -611,9 +611,12 @@ bool LightCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
|||||||
}
|
}
|
||||||
bool LightCommandRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
|
bool LightCommandRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
|
||||||
switch (field_id) {
|
switch (field_id) {
|
||||||
case 19:
|
case 19: {
|
||||||
this->effect = value.as_string();
|
// Use raw data directly to avoid allocation
|
||||||
|
this->effect = value.data();
|
||||||
|
this->effect_len = value.size();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -840,7 +840,7 @@ class LightStateResponse final : public StateResponseProtoMessage {
|
|||||||
class LightCommandRequest final : public CommandProtoMessage {
|
class LightCommandRequest final : public CommandProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint8_t MESSAGE_TYPE = 32;
|
static constexpr uint8_t MESSAGE_TYPE = 32;
|
||||||
static constexpr uint8_t ESTIMATED_SIZE = 112;
|
static constexpr uint8_t ESTIMATED_SIZE = 122;
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
const char *message_name() const override { return "light_command_request"; }
|
const char *message_name() const override { return "light_command_request"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -869,7 +869,8 @@ class LightCommandRequest final : public CommandProtoMessage {
|
|||||||
bool has_flash_length{false};
|
bool has_flash_length{false};
|
||||||
uint32_t flash_length{0};
|
uint32_t flash_length{0};
|
||||||
bool has_effect{false};
|
bool has_effect{false};
|
||||||
std::string effect{};
|
const uint8_t *effect{nullptr};
|
||||||
|
uint16_t effect_len{0};
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void dump_to(std::string &out) const override;
|
void dump_to(std::string &out) const override;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -999,7 +999,9 @@ void LightCommandRequest::dump_to(std::string &out) const {
|
|||||||
dump_field(out, "has_flash_length", this->has_flash_length);
|
dump_field(out, "has_flash_length", this->has_flash_length);
|
||||||
dump_field(out, "flash_length", this->flash_length);
|
dump_field(out, "flash_length", this->flash_length);
|
||||||
dump_field(out, "has_effect", this->has_effect);
|
dump_field(out, "has_effect", this->has_effect);
|
||||||
dump_field(out, "effect", this->effect);
|
out.append(" effect: ");
|
||||||
|
out.append(format_hex_pretty(this->effect, this->effect_len));
|
||||||
|
out.append("\n");
|
||||||
#ifdef USE_DEVICES
|
#ifdef USE_DEVICES
|
||||||
dump_field(out, "device_id", this->device_id);
|
dump_field(out, "device_id", this->device_id);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -504,8 +504,8 @@ color_mode_bitmask_t LightCall::get_suitable_color_modes_mask_() {
|
|||||||
#undef KEY
|
#undef KEY
|
||||||
}
|
}
|
||||||
|
|
||||||
LightCall &LightCall::set_effect(const std::string &effect) {
|
LightCall &LightCall::set_effect(const char *effect, size_t len) {
|
||||||
if (strcasecmp(effect.c_str(), "none") == 0) {
|
if (len == 4 && strncasecmp(effect, "none", 4) == 0) {
|
||||||
this->set_effect(0);
|
this->set_effect(0);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -513,15 +513,16 @@ LightCall &LightCall::set_effect(const std::string &effect) {
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
for (uint32_t i = 0; i < this->parent_->effects_.size(); i++) {
|
for (uint32_t i = 0; i < this->parent_->effects_.size(); i++) {
|
||||||
LightEffect *e = this->parent_->effects_[i];
|
LightEffect *e = this->parent_->effects_[i];
|
||||||
|
const char *name = e->get_name();
|
||||||
|
|
||||||
if (strcasecmp(effect.c_str(), e->get_name()) == 0) {
|
if (strncasecmp(effect, name, len) == 0 && name[len] == '\0') {
|
||||||
this->set_effect(i + 1);
|
this->set_effect(i + 1);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
ESP_LOGW(TAG, "'%s': no such effect '%s'", this->parent_->get_name().c_str(), effect.c_str());
|
ESP_LOGW(TAG, "'%s': no such effect '%.*s'", this->parent_->get_name().c_str(), (int) len, effect);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,7 +129,9 @@ class LightCall {
|
|||||||
/// Set the effect of the light by its name.
|
/// Set the effect of the light by its name.
|
||||||
LightCall &set_effect(optional<std::string> effect);
|
LightCall &set_effect(optional<std::string> effect);
|
||||||
/// Set the effect of the light by its name.
|
/// Set the effect of the light by its name.
|
||||||
LightCall &set_effect(const std::string &effect);
|
LightCall &set_effect(const std::string &effect) { return this->set_effect(effect.data(), effect.size()); }
|
||||||
|
/// Set the effect of the light by its name and length (zero-copy from API).
|
||||||
|
LightCall &set_effect(const char *effect, size_t len);
|
||||||
/// Set the effect of the light by its internal index number (only for internal use).
|
/// Set the effect of the light by its internal index number (only for internal use).
|
||||||
LightCall &set_effect(uint32_t effect_number);
|
LightCall &set_effect(uint32_t effect_number);
|
||||||
LightCall &set_effect(optional<uint32_t> effect_number);
|
LightCall &set_effect(optional<uint32_t> effect_number);
|
||||||
|
|||||||
Reference in New Issue
Block a user