1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-24 14:12:24 +01:00

zero copy vectors

This commit is contained in:
J. Nick Koston
2025-07-27 22:17:56 -10:00
parent 2c9987869e
commit 224ea51cd7
11 changed files with 175 additions and 104 deletions

View File

@@ -419,7 +419,7 @@ message ListEntitiesFanResponse {
bool disabled_by_default = 9;
string icon = 10 [(field_ifdef) = "USE_ENTITY_ICON"];
EntityCategory entity_category = 11;
repeated string supported_preset_modes = 12;
repeated string supported_preset_modes = 12 [(container_pointer) = "std::set"];
uint32 device_id = 13 [(field_ifdef) = "USE_DEVICES"];
}
// Deprecated in API version 1.6 - only used in deprecated fields
@@ -500,7 +500,7 @@ message ListEntitiesLightResponse {
string name = 3;
reserved 4; // Deprecated: was string unique_id
repeated ColorMode supported_color_modes = 12;
repeated ColorMode supported_color_modes = 12 [(container_pointer) = "std::set<light::ColorMode>"];
// next four supports_* are for legacy clients, newer clients should use color modes
// Deprecated in API version 1.6
bool legacy_supports_brightness = 5 [deprecated=true];
@@ -966,7 +966,7 @@ message ListEntitiesClimateResponse {
bool supports_current_temperature = 5;
bool supports_two_point_target_temperature = 6;
repeated ClimateMode supported_modes = 7;
repeated ClimateMode supported_modes = 7 [(container_pointer) = "std::set<climate::ClimateMode>"];
float visual_min_temperature = 8;
float visual_max_temperature = 9;
float visual_target_temperature_step = 10;
@@ -975,11 +975,11 @@ message ListEntitiesClimateResponse {
// Deprecated in API version 1.5
bool legacy_supports_away = 11 [deprecated=true];
bool supports_action = 12;
repeated ClimateFanMode supported_fan_modes = 13;
repeated ClimateSwingMode supported_swing_modes = 14;
repeated string supported_custom_fan_modes = 15;
repeated ClimatePreset supported_presets = 16;
repeated string supported_custom_presets = 17;
repeated ClimateFanMode supported_fan_modes = 13 [(container_pointer) = "std::set<climate::ClimateFanMode>"];
repeated ClimateSwingMode supported_swing_modes = 14 [(container_pointer) = "std::set<climate::ClimateSwingMode>"];
repeated string supported_custom_fan_modes = 15 [(container_pointer) = "std::set"];
repeated ClimatePreset supported_presets = 16 [(container_pointer) = "std::set<climate::ClimatePreset>"];
repeated string supported_custom_presets = 17 [(container_pointer) = "std::set"];
bool disabled_by_default = 18;
string icon = 19 [(field_ifdef) = "USE_ENTITY_ICON"];
EntityCategory entity_category = 20;
@@ -1119,7 +1119,7 @@ message ListEntitiesSelectResponse {
reserved 4; // Deprecated: was string unique_id
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"];
repeated string options = 6;
repeated string options = 6 [(container_pointer) = "std::vector"];
bool disabled_by_default = 7;
EntityCategory entity_category = 8;
uint32 device_id = 9 [(field_ifdef) = "USE_DEVICES"];
@@ -1834,7 +1834,7 @@ message VoiceAssistantConfigurationResponse {
option (ifdef) = "USE_VOICE_ASSISTANT";
repeated VoiceAssistantWakeWord available_wake_words = 1;
repeated string active_wake_words = 2;
repeated string active_wake_words = 2 [(container_pointer) = "std::vector"];
uint32 max_active_wake_words = 3;
}

View File

@@ -413,8 +413,7 @@ uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *con
msg.supports_speed = traits.supports_speed();
msg.supports_direction = traits.supports_direction();
msg.supported_speed_count = traits.supported_speed_count();
for (auto const &preset : traits.supported_preset_modes())
msg.supported_preset_modes.push_back(preset);
msg.supported_preset_modes = &traits.supported_preset_modes();
return fill_and_encode_entity_info(fan, msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
}
void APIConnection::fan_command(const FanCommandRequest &msg) {
@@ -470,8 +469,7 @@ uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *c
auto *light = static_cast<light::LightState *>(entity);
ListEntitiesLightResponse msg;
auto traits = light->get_traits();
for (auto mode : traits.get_supported_color_modes())
msg.supported_color_modes.push_back(static_cast<enums::ColorMode>(mode));
msg.supported_color_modes = &traits.get_supported_color_modes();
if (traits.supports_color_capability(light::ColorCapability::COLOR_TEMPERATURE) ||
traits.supports_color_capability(light::ColorCapability::COLD_WARM_WHITE)) {
msg.min_mireds = traits.get_min_mireds();
@@ -657,8 +655,7 @@ uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection
msg.supports_current_humidity = traits.get_supports_current_humidity();
msg.supports_two_point_target_temperature = traits.get_supports_two_point_target_temperature();
msg.supports_target_humidity = traits.get_supports_target_humidity();
for (auto mode : traits.get_supported_modes())
msg.supported_modes.push_back(static_cast<enums::ClimateMode>(mode));
msg.supported_modes = &traits.get_supported_modes();
msg.visual_min_temperature = traits.get_visual_min_temperature();
msg.visual_max_temperature = traits.get_visual_max_temperature();
msg.visual_target_temperature_step = traits.get_visual_target_temperature_step();
@@ -666,16 +663,11 @@ uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection
msg.visual_min_humidity = traits.get_visual_min_humidity();
msg.visual_max_humidity = traits.get_visual_max_humidity();
msg.supports_action = traits.get_supports_action();
for (auto fan_mode : traits.get_supported_fan_modes())
msg.supported_fan_modes.push_back(static_cast<enums::ClimateFanMode>(fan_mode));
for (auto const &custom_fan_mode : traits.get_supported_custom_fan_modes())
msg.supported_custom_fan_modes.push_back(custom_fan_mode);
for (auto preset : traits.get_supported_presets())
msg.supported_presets.push_back(static_cast<enums::ClimatePreset>(preset));
for (auto const &custom_preset : traits.get_supported_custom_presets())
msg.supported_custom_presets.push_back(custom_preset);
for (auto swing_mode : traits.get_supported_swing_modes())
msg.supported_swing_modes.push_back(static_cast<enums::ClimateSwingMode>(swing_mode));
msg.supported_fan_modes = &traits.get_supported_fan_modes();
msg.supported_custom_fan_modes = &traits.get_supported_custom_fan_modes();
msg.supported_presets = &traits.get_supported_presets();
msg.supported_custom_presets = &traits.get_supported_custom_presets();
msg.supported_swing_modes = &traits.get_supported_swing_modes();
return fill_and_encode_entity_info(climate, msg, ListEntitiesClimateResponse::MESSAGE_TYPE, conn, remaining_size,
is_single);
}
@@ -881,8 +873,7 @@ uint16_t APIConnection::try_send_select_info(EntityBase *entity, APIConnection *
bool is_single) {
auto *select = static_cast<select::Select *>(entity);
ListEntitiesSelectResponse msg;
for (const auto &option : select->traits.get_options())
msg.options.push_back(option);
msg.options = &select->traits.get_options();
return fill_and_encode_entity_info(select, msg, ListEntitiesSelectResponse::MESSAGE_TYPE, conn, remaining_size,
is_single);
}
@@ -1196,9 +1187,7 @@ bool APIConnection::send_voice_assistant_get_configuration_response(const VoiceA
resp_wake_word.trained_languages.push_back(lang);
}
}
for (auto &wake_word_id : config.active_wake_words) {
resp.active_wake_words.push_back(wake_word_id);
}
resp.active_wake_words = &config.active_wake_words;
resp.max_active_wake_words = config.max_active_wake_words;
return this->send_message(resp, VoiceAssistantConfigurationResponse::MESSAGE_TYPE);
}

View File

@@ -28,4 +28,5 @@ extend google.protobuf.FieldOptions {
optional string field_ifdef = 1042;
optional uint32 fixed_array_size = 50007;
optional bool no_zero_copy = 50008 [default=false];
optional string container_pointer = 50001;
}

View File

@@ -331,7 +331,7 @@ void ListEntitiesFanResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(10, this->icon_ref_);
#endif
buffer.encode_uint32(11, static_cast<uint32_t>(this->entity_category));
for (auto &it : this->supported_preset_modes) {
for (const auto &it : *this->supported_preset_modes) {
buffer.encode_string(12, it, true);
}
#ifdef USE_DEVICES
@@ -351,8 +351,8 @@ void ListEntitiesFanResponse::calculate_size(ProtoSize &size) const {
size.add_length(1, this->icon_ref_.size());
#endif
size.add_uint32(1, static_cast<uint32_t>(this->entity_category));
if (!this->supported_preset_modes.empty()) {
for (const auto &it : this->supported_preset_modes) {
if (!this->supported_preset_modes->empty()) {
for (const auto &it : *this->supported_preset_modes) {
size.add_length_force(1, it.size());
}
}
@@ -447,7 +447,7 @@ void ListEntitiesLightResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(1, this->object_id_ref_);
buffer.encode_fixed32(2, this->key);
buffer.encode_string(3, this->name_ref_);
for (auto &it : this->supported_color_modes) {
for (const auto &it : *this->supported_color_modes) {
buffer.encode_uint32(12, static_cast<uint32_t>(it), true);
}
buffer.encode_float(9, this->min_mireds);
@@ -468,8 +468,8 @@ void ListEntitiesLightResponse::calculate_size(ProtoSize &size) const {
size.add_length(1, this->object_id_ref_.size());
size.add_fixed32(1, this->key);
size.add_length(1, this->name_ref_.size());
if (!this->supported_color_modes.empty()) {
for (const auto &it : this->supported_color_modes) {
if (!this->supported_color_modes->empty()) {
for (const auto &it : *this->supported_color_modes) {
size.add_uint32_force(1, static_cast<uint32_t>(it));
}
}
@@ -1064,26 +1064,26 @@ void ListEntitiesClimateResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(3, this->name_ref_);
buffer.encode_bool(5, this->supports_current_temperature);
buffer.encode_bool(6, this->supports_two_point_target_temperature);
for (auto &it : this->supported_modes) {
for (const auto &it : *this->supported_modes) {
buffer.encode_uint32(7, static_cast<uint32_t>(it), true);
}
buffer.encode_float(8, this->visual_min_temperature);
buffer.encode_float(9, this->visual_max_temperature);
buffer.encode_float(10, this->visual_target_temperature_step);
buffer.encode_bool(12, this->supports_action);
for (auto &it : this->supported_fan_modes) {
for (const auto &it : *this->supported_fan_modes) {
buffer.encode_uint32(13, static_cast<uint32_t>(it), true);
}
for (auto &it : this->supported_swing_modes) {
for (const auto &it : *this->supported_swing_modes) {
buffer.encode_uint32(14, static_cast<uint32_t>(it), true);
}
for (auto &it : this->supported_custom_fan_modes) {
for (const auto &it : *this->supported_custom_fan_modes) {
buffer.encode_string(15, it, true);
}
for (auto &it : this->supported_presets) {
for (const auto &it : *this->supported_presets) {
buffer.encode_uint32(16, static_cast<uint32_t>(it), true);
}
for (auto &it : this->supported_custom_presets) {
for (const auto &it : *this->supported_custom_presets) {
buffer.encode_string(17, it, true);
}
buffer.encode_bool(18, this->disabled_by_default);
@@ -1106,8 +1106,8 @@ void ListEntitiesClimateResponse::calculate_size(ProtoSize &size) const {
size.add_length(1, this->name_ref_.size());
size.add_bool(1, this->supports_current_temperature);
size.add_bool(1, this->supports_two_point_target_temperature);
if (!this->supported_modes.empty()) {
for (const auto &it : this->supported_modes) {
if (!this->supported_modes->empty()) {
for (const auto &it : *this->supported_modes) {
size.add_uint32_force(1, static_cast<uint32_t>(it));
}
}
@@ -1115,28 +1115,28 @@ void ListEntitiesClimateResponse::calculate_size(ProtoSize &size) const {
size.add_float(1, this->visual_max_temperature);
size.add_float(1, this->visual_target_temperature_step);
size.add_bool(1, this->supports_action);
if (!this->supported_fan_modes.empty()) {
for (const auto &it : this->supported_fan_modes) {
if (!this->supported_fan_modes->empty()) {
for (const auto &it : *this->supported_fan_modes) {
size.add_uint32_force(1, static_cast<uint32_t>(it));
}
}
if (!this->supported_swing_modes.empty()) {
for (const auto &it : this->supported_swing_modes) {
if (!this->supported_swing_modes->empty()) {
for (const auto &it : *this->supported_swing_modes) {
size.add_uint32_force(1, static_cast<uint32_t>(it));
}
}
if (!this->supported_custom_fan_modes.empty()) {
for (const auto &it : this->supported_custom_fan_modes) {
if (!this->supported_custom_fan_modes->empty()) {
for (const auto &it : *this->supported_custom_fan_modes) {
size.add_length_force(1, it.size());
}
}
if (!this->supported_presets.empty()) {
for (const auto &it : this->supported_presets) {
if (!this->supported_presets->empty()) {
for (const auto &it : *this->supported_presets) {
size.add_uint32_force(2, static_cast<uint32_t>(it));
}
}
if (!this->supported_custom_presets.empty()) {
for (const auto &it : this->supported_custom_presets) {
if (!this->supported_custom_presets->empty()) {
for (const auto &it : *this->supported_custom_presets) {
size.add_length_force(2, it.size());
}
}
@@ -1371,7 +1371,7 @@ void ListEntitiesSelectResponse::encode(ProtoWriteBuffer buffer) const {
#ifdef USE_ENTITY_ICON
buffer.encode_string(5, this->icon_ref_);
#endif
for (auto &it : this->options) {
for (const auto &it : *this->options) {
buffer.encode_string(6, it, true);
}
buffer.encode_bool(7, this->disabled_by_default);
@@ -1387,8 +1387,8 @@ void ListEntitiesSelectResponse::calculate_size(ProtoSize &size) const {
#ifdef USE_ENTITY_ICON
size.add_length(1, this->icon_ref_.size());
#endif
if (!this->options.empty()) {
for (const auto &it : this->options) {
if (!this->options->empty()) {
for (const auto &it : *this->options) {
size.add_length_force(1, it.size());
}
}
@@ -2332,15 +2332,15 @@ void VoiceAssistantConfigurationResponse::encode(ProtoWriteBuffer buffer) const
for (auto &it : this->available_wake_words) {
buffer.encode_message(1, it, true);
}
for (auto &it : this->active_wake_words) {
for (const auto &it : *this->active_wake_words) {
buffer.encode_string(2, it, true);
}
buffer.encode_uint32(3, this->max_active_wake_words);
}
void VoiceAssistantConfigurationResponse::calculate_size(ProtoSize &size) const {
size.add_repeated_message(1, this->available_wake_words);
if (!this->active_wake_words.empty()) {
for (const auto &it : this->active_wake_words) {
if (!this->active_wake_words->empty()) {
for (const auto &it : *this->active_wake_words) {
size.add_length_force(1, it.size());
}
}

View File

@@ -6,6 +6,9 @@
#include "esphome/core/string_ref.h"
#include "proto.h"
#include "api_pb2_includes.h"
#include <set>
namespace esphome::api {
@@ -695,7 +698,7 @@ class ListEntitiesFanResponse : public InfoResponseProtoMessage {
bool supports_speed{false};
bool supports_direction{false};
int32_t supported_speed_count{0};
std::vector<std::string> supported_preset_modes{};
const std::set<std::string> *supported_preset_modes{};
void encode(ProtoWriteBuffer buffer) const override;
void calculate_size(ProtoSize &size) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
@@ -760,7 +763,7 @@ class ListEntitiesLightResponse : public InfoResponseProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "list_entities_light_response"; }
#endif
std::vector<enums::ColorMode> supported_color_modes{};
const std::set<light::ColorMode> *supported_color_modes{};
float min_mireds{0.0f};
float max_mireds{0.0f};
std::vector<std::string> effects{};
@@ -1311,16 +1314,16 @@ class ListEntitiesClimateResponse : public InfoResponseProtoMessage {
#endif
bool supports_current_temperature{false};
bool supports_two_point_target_temperature{false};
std::vector<enums::ClimateMode> supported_modes{};
const std::set<climate::ClimateMode> *supported_modes{};
float visual_min_temperature{0.0f};
float visual_max_temperature{0.0f};
float visual_target_temperature_step{0.0f};
bool supports_action{false};
std::vector<enums::ClimateFanMode> supported_fan_modes{};
std::vector<enums::ClimateSwingMode> supported_swing_modes{};
std::vector<std::string> supported_custom_fan_modes{};
std::vector<enums::ClimatePreset> supported_presets{};
std::vector<std::string> supported_custom_presets{};
const std::set<climate::ClimateFanMode> *supported_fan_modes{};
const std::set<climate::ClimateSwingMode> *supported_swing_modes{};
const std::set<std::string> *supported_custom_fan_modes{};
const std::set<climate::ClimatePreset> *supported_presets{};
const std::set<std::string> *supported_custom_presets{};
float visual_current_temperature_step{0.0f};
bool supports_current_humidity{false};
bool supports_target_humidity{false};
@@ -1467,7 +1470,7 @@ class ListEntitiesSelectResponse : public InfoResponseProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "list_entities_select_response"; }
#endif
std::vector<std::string> options{};
const std::vector<std::string> *options{};
void encode(ProtoWriteBuffer buffer) const override;
void calculate_size(ProtoSize &size) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
@@ -2439,7 +2442,7 @@ class VoiceAssistantConfigurationResponse : public ProtoMessage {
const char *message_name() const override { return "voice_assistant_configuration_response"; }
#endif
std::vector<VoiceAssistantWakeWord> available_wake_words{};
std::vector<std::string> active_wake_words{};
const std::vector<std::string> *active_wake_words{};
uint32_t max_active_wake_words{0};
void encode(ProtoWriteBuffer buffer) const override;
void calculate_size(ProtoSize &size) const override;

View File

@@ -814,7 +814,7 @@ void ListEntitiesFanResponse::dump_to(std::string &out) const {
dump_field(out, "icon", this->icon_ref_);
#endif
dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category));
for (const auto &it : this->supported_preset_modes) {
for (const auto &it : *this->supported_preset_modes) {
dump_field(out, "supported_preset_modes", it, 4);
}
#ifdef USE_DEVICES
@@ -857,7 +857,7 @@ void ListEntitiesLightResponse::dump_to(std::string &out) const {
dump_field(out, "object_id", this->object_id_ref_);
dump_field(out, "key", this->key);
dump_field(out, "name", this->name_ref_);
for (const auto &it : this->supported_color_modes) {
for (const auto &it : *this->supported_color_modes) {
dump_field(out, "supported_color_modes", static_cast<enums::ColorMode>(it), 4);
}
dump_field(out, "min_mireds", this->min_mireds);
@@ -1173,26 +1173,26 @@ void ListEntitiesClimateResponse::dump_to(std::string &out) const {
dump_field(out, "name", this->name_ref_);
dump_field(out, "supports_current_temperature", this->supports_current_temperature);
dump_field(out, "supports_two_point_target_temperature", this->supports_two_point_target_temperature);
for (const auto &it : this->supported_modes) {
for (const auto &it : *this->supported_modes) {
dump_field(out, "supported_modes", static_cast<enums::ClimateMode>(it), 4);
}
dump_field(out, "visual_min_temperature", this->visual_min_temperature);
dump_field(out, "visual_max_temperature", this->visual_max_temperature);
dump_field(out, "visual_target_temperature_step", this->visual_target_temperature_step);
dump_field(out, "supports_action", this->supports_action);
for (const auto &it : this->supported_fan_modes) {
for (const auto &it : *this->supported_fan_modes) {
dump_field(out, "supported_fan_modes", static_cast<enums::ClimateFanMode>(it), 4);
}
for (const auto &it : this->supported_swing_modes) {
for (const auto &it : *this->supported_swing_modes) {
dump_field(out, "supported_swing_modes", static_cast<enums::ClimateSwingMode>(it), 4);
}
for (const auto &it : this->supported_custom_fan_modes) {
for (const auto &it : *this->supported_custom_fan_modes) {
dump_field(out, "supported_custom_fan_modes", it, 4);
}
for (const auto &it : this->supported_presets) {
for (const auto &it : *this->supported_presets) {
dump_field(out, "supported_presets", static_cast<enums::ClimatePreset>(it), 4);
}
for (const auto &it : this->supported_custom_presets) {
for (const auto &it : *this->supported_custom_presets) {
dump_field(out, "supported_custom_presets", it, 4);
}
dump_field(out, "disabled_by_default", this->disabled_by_default);
@@ -1305,7 +1305,7 @@ void ListEntitiesSelectResponse::dump_to(std::string &out) const {
#ifdef USE_ENTITY_ICON
dump_field(out, "icon", this->icon_ref_);
#endif
for (const auto &it : this->options) {
for (const auto &it : *this->options) {
dump_field(out, "options", it, 4);
}
dump_field(out, "disabled_by_default", this->disabled_by_default);
@@ -1769,7 +1769,7 @@ void VoiceAssistantConfigurationResponse::dump_to(std::string &out) const {
it.dump_to(out);
out.append("\n");
}
for (const auto &it : this->active_wake_words) {
for (const auto &it : *this->active_wake_words) {
dump_field(out, "active_wake_words", it, 4);
}
dump_field(out, "max_active_wake_words", this->max_active_wake_words);

View File

@@ -0,0 +1,30 @@
#pragma once
// This file provides includes needed by the generated protobuf code
// when using pointer optimizations for component-specific types
#ifdef USE_CLIMATE
#include "esphome/components/climate/climate_mode.h"
#include "esphome/components/climate/climate_traits.h"
#endif
#ifdef USE_LIGHT
#include "esphome/components/light/light_traits.h"
#endif
#ifdef USE_FAN
#include "esphome/components/fan/fan_traits.h"
#endif
#ifdef USE_SELECT
#include "esphome/components/select/select_traits.h"
#endif
#ifdef USE_MEDIA_PLAYER
#include "esphome/components/media_player/media_player_traits.h"
#endif
// Standard library includes that might be needed
#include <set>
#include <vector>
#include <string>