mirror of
https://github.com/esphome/esphome.git
synced 2026-10-14 10:12:52 +00:00
Compare commits
34
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4c19a00e0 | ||
|
|
522395de11 | ||
|
|
39d63a3166 | ||
|
|
36cfe5c785 | ||
|
|
d8dd8cf36c | ||
|
|
12c35c1545 | ||
|
|
0e8a3dfb6f | ||
|
|
00f8e89f28 | ||
|
|
5326d1dfe9 | ||
|
|
ba9705e19b | ||
|
|
543a818307 | ||
|
|
b31bedd464 | ||
|
|
c8d331d44b | ||
|
|
62f79e007a | ||
|
|
b989221c71 | ||
|
|
096921cddb | ||
|
|
e3d33df379 | ||
|
|
c263852df9 | ||
|
|
7c58d26d13 | ||
|
|
88f7fc7454 | ||
|
|
140488723d | ||
|
|
b626711d50 | ||
|
|
a6cb560e90 | ||
|
|
a721574706 | ||
|
|
568934cc91 | ||
|
|
13057b7ae3 | ||
|
|
b4289aee59 | ||
|
|
93aecdd435 | ||
|
|
afac871938 | ||
|
|
4c6e6b5447 | ||
|
|
b5c06efb2f | ||
|
|
5cbdf26993 | ||
|
|
6f5108eb70 | ||
|
|
4ef86fe534 |
@@ -552,7 +552,7 @@ message ListEntitiesBinarySensorResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string device_class = 5 [(max_data_length) = 47];
|
||||
@@ -586,7 +586,7 @@ message ListEntitiesCoverResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
bool assumed_state = 5;
|
||||
@@ -670,7 +670,7 @@ message ListEntitiesFanResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
bool supports_oscillation = 5;
|
||||
@@ -758,7 +758,7 @@ message ListEntitiesLightResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
repeated ColorMode supported_color_modes = 12 [(container_pointer_no_template) = "light::ColorModeMask"];
|
||||
@@ -863,7 +863,7 @@ message ListEntitiesSensorResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -904,7 +904,7 @@ message ListEntitiesSwitchResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -949,7 +949,7 @@ message ListEntitiesTextSensorResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1220,7 +1220,7 @@ message ListEntitiesCameraResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
bool disabled_by_default = 5;
|
||||
string icon = 6 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1312,7 +1312,7 @@ message ListEntitiesClimateResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
bool supports_current_temperature = 5; // Deprecated: use feature_flags
|
||||
@@ -1427,7 +1427,7 @@ message ListEntitiesWaterHeaterResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 5;
|
||||
EntityCategory entity_category = 6;
|
||||
@@ -1507,7 +1507,7 @@ message ListEntitiesNumberResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1556,7 +1556,7 @@ message ListEntitiesSelectResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1600,7 +1600,7 @@ message ListEntitiesSirenResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1665,7 +1665,7 @@ message ListEntitiesLockResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1714,7 +1714,7 @@ message ListEntitiesButtonResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1781,7 +1781,7 @@ message ListEntitiesMediaPlayerResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2373,7 +2373,7 @@ message ListEntitiesAlarmControlPanelResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 6;
|
||||
@@ -2420,7 +2420,7 @@ message ListEntitiesTextResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 6;
|
||||
@@ -2468,7 +2468,7 @@ message ListEntitiesDateResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2515,7 +2515,7 @@ message ListEntitiesTimeResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2562,7 +2562,7 @@ message ListEntitiesEventResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2593,7 +2593,7 @@ message ListEntitiesValveResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2648,7 +2648,7 @@ message ListEntitiesDateTimeResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2691,7 +2691,7 @@ message ListEntitiesUpdateResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2791,7 +2791,7 @@ message ListEntitiesInfraredResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 5;
|
||||
EntityCategory entity_category = 6;
|
||||
@@ -2860,7 +2860,7 @@ message ListEntitiesRadioFrequencyResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 5;
|
||||
EntityCategory entity_category = 6;
|
||||
|
||||
@@ -474,7 +474,7 @@ uint16_t APIConnection::fill_and_encode_entity_info(EntityBase *entity, InfoResp
|
||||
msg.key = entity->get_object_id_hash();
|
||||
|
||||
if (entity->has_own_name()) {
|
||||
msg.name = entity->get_name();
|
||||
msg.name = entity->get_name_progmem();
|
||||
}
|
||||
|
||||
// Set common EntityBase properties
|
||||
|
||||
@@ -123,7 +123,7 @@ extend google.protobuf.FieldOptions {
|
||||
// from an absent one (e.g. a UTC ParsedTimezone, which is all zeros).
|
||||
optional bool track_presence = 50020 [default=false];
|
||||
|
||||
// progmem: The pointer_to_buffer bytes field points into flash (PROGMEM).
|
||||
// progmem: The string field, or pointer_to_buffer bytes field, points into flash (PROGMEM).
|
||||
// The generated encode and dump copy it with progmem_memcpy, as ESP8266
|
||||
// cannot read flash with ordinary loads.
|
||||
optional bool progmem = 50021 [default=false];
|
||||
|
||||
@@ -401,7 +401,7 @@ uint8_t *ListEntitiesBinarySensorResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesBinarySensorResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.device_class);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.is_status_binary_sensor);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.disabled_by_default);
|
||||
@@ -459,7 +459,7 @@ uint8_t *ListEntitiesCoverResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesCoverResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.assumed_state);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_position);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.supports_tilt);
|
||||
@@ -558,7 +558,7 @@ uint8_t *ListEntitiesFanResponse::encode_msg(const void *self, uint8_t *__restri
|
||||
const auto &msg = *static_cast<const ListEntitiesFanResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.supports_oscillation);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_speed);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.supports_direction);
|
||||
@@ -678,7 +678,7 @@ uint8_t *ListEntitiesLightResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesLightResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
for (const auto &it : *msg.supported_color_modes) {
|
||||
pos = ProtoEncode::encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast<uint32_t>(it));
|
||||
}
|
||||
@@ -884,7 +884,7 @@ uint8_t *ListEntitiesSensorResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesSensorResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -954,7 +954,7 @@ uint8_t *ListEntitiesSwitchResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesSwitchResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -1030,7 +1030,7 @@ uint8_t *ListEntitiesTextSensorResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesTextSensorResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -1478,7 +1478,7 @@ uint8_t *ListEntitiesCameraResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesCameraResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.disabled_by_default);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.icon);
|
||||
@@ -1544,7 +1544,7 @@ uint8_t *ListEntitiesClimateResponse::encode_msg(const void *self, uint8_t *__re
|
||||
const auto &msg = *static_cast<const ListEntitiesClimateResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.supports_current_temperature);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_two_point_target_temperature);
|
||||
for (const auto &it : *msg.supported_modes) {
|
||||
@@ -1781,7 +1781,7 @@ uint8_t *ListEntitiesWaterHeaterResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesWaterHeaterResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
|
||||
#endif
|
||||
@@ -1908,7 +1908,7 @@ uint8_t *ListEntitiesNumberResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesNumberResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -1999,7 +1999,7 @@ uint8_t *ListEntitiesSelectResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesSelectResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -2078,7 +2078,7 @@ uint8_t *ListEntitiesSirenResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesSirenResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -2180,7 +2180,7 @@ uint8_t *ListEntitiesLockResponse::encode_msg(const void *self, uint8_t *__restr
|
||||
const auto &msg = *static_cast<const ListEntitiesLockResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -2263,7 +2263,7 @@ uint8_t *ListEntitiesButtonResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesButtonResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -2332,7 +2332,7 @@ uint8_t *ListEntitiesMediaPlayerResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesMediaPlayerResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3178,7 +3178,7 @@ uint8_t *ListEntitiesAlarmControlPanelResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesAlarmControlPanelResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3258,7 +3258,7 @@ uint8_t *ListEntitiesTextResponse::encode_msg(const void *self, uint8_t *__restr
|
||||
const auto &msg = *static_cast<const ListEntitiesTextResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3337,7 +3337,7 @@ uint8_t *ListEntitiesDateResponse::encode_msg(const void *self, uint8_t *__restr
|
||||
const auto &msg = *static_cast<const ListEntitiesDateResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3418,7 +3418,7 @@ uint8_t *ListEntitiesTimeResponse::encode_msg(const void *self, uint8_t *__restr
|
||||
const auto &msg = *static_cast<const ListEntitiesTimeResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3499,7 +3499,7 @@ uint8_t *ListEntitiesEventResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesEventResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3561,7 +3561,7 @@ uint8_t *ListEntitiesValveResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesValveResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3649,7 +3649,7 @@ uint8_t *ListEntitiesDateTimeResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesDateTimeResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3722,7 +3722,7 @@ uint8_t *ListEntitiesUpdateResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesUpdateResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3878,7 +3878,7 @@ uint8_t *ListEntitiesInfraredResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesInfraredResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
|
||||
#endif
|
||||
@@ -3996,7 +3996,7 @@ uint8_t *ListEntitiesRadioFrequencyResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesRadioFrequencyResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
|
||||
#endif
|
||||
|
||||
@@ -399,7 +399,7 @@ class InfoResponseProtoMessage : public ProtoMessage {
|
||||
public:
|
||||
StringRef object_id{};
|
||||
uint32_t key{0};
|
||||
StringRef name{};
|
||||
ProgmemStringRef name{};
|
||||
bool disabled_by_default{false};
|
||||
#ifdef USE_ENTITY_ICON
|
||||
StringRef icon{nullptr, 0}; // null until set, encode only
|
||||
|
||||
@@ -12,8 +12,9 @@ namespace esphome::api {
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
// Out-of-line to avoid inlining strlen_P/memcpy_P at every call site
|
||||
void DumpBuffer::append_p_esp8266(const char *str) {
|
||||
size_t len = strlen_P(str);
|
||||
void DumpBuffer::append_p_esp8266(const char *str) { this->append_p_esp8266(str, strlen_P(str)); }
|
||||
|
||||
void DumpBuffer::append_p_esp8266(const char *str, size_t len) {
|
||||
size_t space = CAPACITY - 1 - pos_;
|
||||
if (len > space)
|
||||
len = space;
|
||||
@@ -134,6 +135,13 @@ static void dump_progmem_bytes_field(DumpBuffer &out, const char *field_name, co
|
||||
progmem_memcpy(data_buf, data, len);
|
||||
dump_bytes_field(out, field_name, data_buf, len, indent);
|
||||
}
|
||||
|
||||
// Helper for string fields in flash
|
||||
static void dump_progmem_string_field(DumpBuffer &out, const char *field_name, const ProgmemStringRef &value,
|
||||
int indent = 2) {
|
||||
append_field_prefix(out, field_name, indent);
|
||||
out.append("'").append_p(value.progmem_ptr(), value.size()).append("'\n");
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
template<> const char *proto_enum_to_string<enums::DisconnectReason>(enums::DisconnectReason value) {
|
||||
@@ -1182,7 +1190,7 @@ const char *ListEntitiesBinarySensorResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesBinarySensorResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
|
||||
dump_field(out, ESPHOME_PSTR("is_status_binary_sensor"), this->is_status_binary_sensor);
|
||||
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
|
||||
@@ -1211,7 +1219,7 @@ const char *ListEntitiesCoverResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesCoverResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("assumed_state"), this->assumed_state);
|
||||
dump_field(out, ESPHOME_PSTR("supports_position"), this->supports_position);
|
||||
dump_field(out, ESPHOME_PSTR("supports_tilt"), this->supports_tilt);
|
||||
@@ -1257,7 +1265,7 @@ const char *ListEntitiesFanResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesFanResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("supports_oscillation"), this->supports_oscillation);
|
||||
dump_field(out, ESPHOME_PSTR("supports_speed"), this->supports_speed);
|
||||
dump_field(out, ESPHOME_PSTR("supports_direction"), this->supports_direction);
|
||||
@@ -1312,7 +1320,7 @@ const char *ListEntitiesLightResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesLightResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
for (const auto &it : *this->supported_color_modes) {
|
||||
dump_field(out, ESPHOME_PSTR("supported_color_modes"), static_cast<enums::ColorMode>(it), 4);
|
||||
}
|
||||
@@ -1391,7 +1399,7 @@ const char *ListEntitiesSensorResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSensorResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1423,7 +1431,7 @@ const char *ListEntitiesSwitchResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSwitchResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1461,7 +1469,7 @@ const char *ListEntitiesTextSensorResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTextSensorResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1692,7 +1700,7 @@ const char *ListEntitiesCameraResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesCameraResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
@@ -1725,7 +1733,7 @@ const char *ListEntitiesClimateResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesClimateResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("supports_current_temperature"), this->supports_current_temperature);
|
||||
dump_field(out, ESPHOME_PSTR("supports_two_point_target_temperature"), this->supports_two_point_target_temperature);
|
||||
for (const auto &it : *this->supported_modes) {
|
||||
@@ -1823,7 +1831,7 @@ const char *ListEntitiesWaterHeaterResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesWaterHeaterResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1877,7 +1885,7 @@ const char *ListEntitiesNumberResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesNumberResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1919,7 +1927,7 @@ const char *ListEntitiesSelectResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSelectResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1958,7 +1966,7 @@ const char *ListEntitiesSirenResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSirenResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2005,7 +2013,7 @@ const char *ListEntitiesLockResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesLockResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2046,7 +2054,7 @@ const char *ListEntitiesButtonResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesButtonResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2081,7 +2089,7 @@ const char *ListEntitiesMediaPlayerResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesMediaPlayerResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2471,7 +2479,7 @@ const char *ListEntitiesAlarmControlPanelResponse::dump_to(DumpBuffer &out) cons
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesAlarmControlPanelResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2510,7 +2518,7 @@ const char *ListEntitiesTextResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTextResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2550,7 +2558,7 @@ const char *ListEntitiesDateResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesDateResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2590,7 +2598,7 @@ const char *ListEntitiesTimeResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTimeResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2630,7 +2638,7 @@ const char *ListEntitiesEventResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesEventResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2660,7 +2668,7 @@ const char *ListEntitiesValveResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesValveResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2702,7 +2710,7 @@ const char *ListEntitiesDateTimeResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesDateTimeResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2738,7 +2746,7 @@ const char *ListEntitiesUpdateResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesUpdateResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2801,7 +2809,7 @@ const char *ListEntitiesInfraredResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesInfraredResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2859,7 +2867,7 @@ const char *ListEntitiesRadioFrequencyResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesRadioFrequencyResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
|
||||
@@ -409,6 +409,10 @@ class ProtoEncode {
|
||||
/// Tag must be a single-byte varint (< 128). Always encodes (no zero check).
|
||||
[[nodiscard]] static inline uint8_t *encode_short_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
|
||||
uint8_t tag, const StringRef &ref) {
|
||||
#ifdef USE_ESP8266
|
||||
// memcpy_P reads RAM too, and sharing the progmem copy is smaller than an inline memcpy
|
||||
return encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, tag, ProgmemStringRef(ref));
|
||||
#else
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
assert(ref.size() < 128 && "encode_short_string_force: string exceeds max_data_length < 128");
|
||||
#endif
|
||||
@@ -417,6 +421,19 @@ class ProtoEncode {
|
||||
pos[1] = static_cast<uint8_t>(ref.size());
|
||||
std::memcpy(pos + 2, ref.c_str(), ref.size());
|
||||
return pos + 2 + ref.size();
|
||||
#endif
|
||||
}
|
||||
/// encode_short_string_force for a string that may be in flash (PROGMEM).
|
||||
[[nodiscard]] static inline uint8_t *encode_short_progmem_string_force(
|
||||
uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint8_t tag, const ProgmemStringRef &ref) {
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
assert(ref.size() < 128 && "encode_short_progmem_string_force: string exceeds max_data_length < 128");
|
||||
#endif
|
||||
PROTO_ENCODE_CHECK_BOUNDS(pos, 2 + ref.size());
|
||||
pos[0] = tag;
|
||||
pos[1] = static_cast<uint8_t>(ref.size());
|
||||
progmem_memcpy(pos + 2, ref.progmem_ptr(), ref.size());
|
||||
return pos + 2 + ref.size();
|
||||
}
|
||||
/// Write a precomputed tag byte + 32-bit value. Outlined on embedded: one copy beats inline stores per field.
|
||||
[[nodiscard]] static PROTO_OUTLINE_FOR_SIZE uint8_t *write_tag_and_fixed32(
|
||||
@@ -481,6 +498,17 @@ class ProtoEncode {
|
||||
progmem_memcpy(pos, data, len);
|
||||
return pos + len;
|
||||
}
|
||||
/// encode_progmem_bytes for a string field that may be in flash.
|
||||
[[nodiscard]] static inline uint8_t *encode_progmem_string(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
|
||||
uint32_t field_id, const ProgmemStringRef &ref) {
|
||||
return encode_progmem_bytes(pos PROTO_ENCODE_DEBUG_ARG, field_id,
|
||||
reinterpret_cast<const uint8_t *>(ref.progmem_ptr()), ref.size());
|
||||
}
|
||||
[[nodiscard]] static inline uint8_t *encode_progmem_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
|
||||
uint32_t field_id, const ProgmemStringRef &ref) {
|
||||
return encode_progmem_bytes_force(pos PROTO_ENCODE_DEBUG_ARG, field_id,
|
||||
reinterpret_cast<const uint8_t *>(ref.progmem_ptr()), ref.size());
|
||||
}
|
||||
[[nodiscard]] static inline uint8_t *encode_uint32_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
|
||||
uint32_t field_id, uint32_t value) {
|
||||
pos = encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 0);
|
||||
@@ -680,9 +708,20 @@ class DumpBuffer {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Append len bytes of a PROGMEM string
|
||||
DumpBuffer &append_p(const char *str, size_t len) {
|
||||
#ifdef USE_ESP8266
|
||||
append_p_esp8266(str, len);
|
||||
#else
|
||||
append_impl_(str, len);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
/// Out-of-line ESP8266 PROGMEM append to avoid inlining strlen_P/memcpy_P at every call site
|
||||
void append_p_esp8266(const char *str);
|
||||
void append_p_esp8266(const char *str, size_t len);
|
||||
#endif
|
||||
|
||||
const char *c_str() const { return buf_; }
|
||||
|
||||
@@ -207,7 +207,12 @@ bool MQTTComponent::send_discovery_() {
|
||||
}
|
||||
|
||||
// Fields from EntityBase
|
||||
root[MQTT_NAME] = this->get_entity()->has_own_name() ? this->friendly_name_() : StringRef();
|
||||
if (this->get_entity()->has_own_name()) {
|
||||
// ArduinoJson copies flash strings into the document itself
|
||||
root[MQTT_NAME] = reinterpret_cast<ProgmemStr>(this->get_entity()->get_name_progmem().progmem_ptr());
|
||||
} else {
|
||||
root[MQTT_NAME] = StringRef();
|
||||
}
|
||||
|
||||
if (this->is_disabled_by_default_())
|
||||
root[MQTT_ENABLED_BY_DEFAULT] = false;
|
||||
@@ -253,9 +258,10 @@ bool MQTTComponent::send_discovery_() {
|
||||
char object_id_buf[OBJECT_ID_MAX_LEN];
|
||||
StringRef object_id = this->get_default_object_id_to_(object_id_buf);
|
||||
if (discovery_info.unique_id_generator == MQTT_MAC_ADDRESS_UNIQUE_ID_GENERATOR) {
|
||||
char name_buf[ENTITY_NAME_BUF_SIZE];
|
||||
char friendly_name_hash[9];
|
||||
buf_append_printf(friendly_name_hash, sizeof(friendly_name_hash), 0, "%08" PRIx32,
|
||||
fnv1_hash(this->friendly_name_().c_str()));
|
||||
fnv1_hash(this->get_entity()->get_name_to(name_buf).c_str()));
|
||||
// Format: mac-component_type-hash (e.g. "aabbccddeeff-sensor-12345678")
|
||||
// MAC (12) + "-" (1) + domain (max 20) + "-" (1) + hash (8) + null (1) = 43
|
||||
char unique_id[MAC_ADDRESS_BUFFER_SIZE + ESPHOME_DOMAIN_MAX_LEN + 11];
|
||||
|
||||
@@ -109,18 +109,23 @@ void PrometheusHandler::handleRequest(AsyncWebServerRequest *req) {
|
||||
req->send(stream);
|
||||
}
|
||||
|
||||
std::string PrometheusHandler::relabel_id_(EntityBase *obj) {
|
||||
void PrometheusHandler::print_relabel_id_(AsyncResponseStream *stream, EntityBase *obj) {
|
||||
auto item = relabel_map_id_.find(obj);
|
||||
if (item != relabel_map_id_.end()) {
|
||||
return item->second;
|
||||
stream->print(item->second.c_str());
|
||||
return;
|
||||
}
|
||||
char object_id_buf[OBJECT_ID_MAX_LEN];
|
||||
return obj->get_object_id_to(object_id_buf).str();
|
||||
stream->print(obj->get_object_id_to(object_id_buf).c_str());
|
||||
}
|
||||
|
||||
std::string PrometheusHandler::relabel_name_(EntityBase *obj) {
|
||||
void PrometheusHandler::print_relabel_name_(AsyncResponseStream *stream, EntityBase *obj) {
|
||||
auto item = relabel_map_name_.find(obj);
|
||||
return item == relabel_map_name_.end() ? obj->get_name() : item->second;
|
||||
if (item != relabel_map_name_.end()) {
|
||||
stream->print(item->second.c_str());
|
||||
return;
|
||||
}
|
||||
stream->print(reinterpret_cast<ProgmemStr>(obj->get_name_progmem().progmem_ptr()));
|
||||
}
|
||||
|
||||
void PrometheusHandler::add_area_label_(AsyncResponseStream *stream, std::string &area) {
|
||||
@@ -148,12 +153,12 @@ void PrometheusHandler::print_metric_labels_(AsyncResponseStream *stream, Progme
|
||||
std::string &area, std::string &node, std::string &friendly_name) {
|
||||
stream->print(metric_name);
|
||||
stream->print(ESPHOME_F("{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
}
|
||||
|
||||
// Type-specific implementation
|
||||
@@ -169,21 +174,21 @@ void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor
|
||||
if (!std::isnan(obj->state)) {
|
||||
// We have a valid value, output this value
|
||||
stream->print(ESPHOME_F("esphome_sensor_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(ESPHOME_F("esphome_sensor_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\",unit=\""));
|
||||
stream->print(obj->get_unit_of_measurement_ref().c_str());
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
@@ -194,12 +199,12 @@ void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor
|
||||
} else {
|
||||
// Invalid state
|
||||
stream->print(ESPHOME_F("esphome_sensor_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 1\n"));
|
||||
}
|
||||
}
|
||||
@@ -218,33 +223,33 @@ void PrometheusHandler::binary_sensor_row_(AsyncResponseStream *stream, binary_s
|
||||
if (obj->has_state()) {
|
||||
// We have a valid value, output this value
|
||||
stream->print(ESPHOME_F("esphome_binary_sensor_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(ESPHOME_F("esphome_binary_sensor_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
stream->print(obj->state);
|
||||
stream->print(ESPHOME_F("\n"));
|
||||
} else {
|
||||
// Invalid state
|
||||
stream->print(ESPHOME_F("esphome_binary_sensor_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 1\n"));
|
||||
}
|
||||
}
|
||||
@@ -262,33 +267,33 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj, std
|
||||
if (obj->is_internal() && !this->include_internal_)
|
||||
return;
|
||||
stream->print(ESPHOME_F("esphome_fan_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(ESPHOME_F("esphome_fan_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
stream->print(obj->state);
|
||||
stream->print(ESPHOME_F("\n"));
|
||||
// Speed if available
|
||||
if (obj->get_traits().supports_speed()) {
|
||||
stream->print(ESPHOME_F("esphome_fan_speed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
stream->print(obj->speed);
|
||||
stream->print(ESPHOME_F("\n"));
|
||||
@@ -296,12 +301,12 @@ void PrometheusHandler::fan_row_(AsyncResponseStream *stream, fan::Fan *obj, std
|
||||
// Oscillation if available
|
||||
if (obj->get_traits().supports_oscillation()) {
|
||||
stream->print(ESPHOME_F("esphome_fan_oscillation{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
stream->print(obj->oscillating);
|
||||
stream->print(ESPHOME_F("\n"));
|
||||
@@ -385,32 +390,32 @@ void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *ob
|
||||
if (!std::isnan(obj->position)) {
|
||||
// We have a valid value, output this value
|
||||
stream->print(ESPHOME_F("esphome_cover_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(ESPHOME_F("esphome_cover_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
stream->print(obj->position);
|
||||
stream->print(ESPHOME_F("\n"));
|
||||
if (obj->get_traits().get_supports_tilt()) {
|
||||
stream->print(ESPHOME_F("esphome_cover_tilt{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
stream->print(obj->tilt);
|
||||
stream->print(ESPHOME_F("\n"));
|
||||
@@ -418,12 +423,12 @@ void PrometheusHandler::cover_row_(AsyncResponseStream *stream, cover::Cover *ob
|
||||
} else {
|
||||
// Invalid state
|
||||
stream->print(ESPHOME_F("esphome_cover_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 1\n"));
|
||||
}
|
||||
}
|
||||
@@ -439,21 +444,21 @@ void PrometheusHandler::switch_row_(AsyncResponseStream *stream, switch_::Switch
|
||||
if (obj->is_internal() && !this->include_internal_)
|
||||
return;
|
||||
stream->print(ESPHOME_F("esphome_switch_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(ESPHOME_F("esphome_switch_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
stream->print(obj->state);
|
||||
stream->print(ESPHOME_F("\n"));
|
||||
@@ -470,21 +475,21 @@ void PrometheusHandler::lock_row_(AsyncResponseStream *stream, lock::Lock *obj,
|
||||
if (obj->is_internal() && !this->include_internal_)
|
||||
return;
|
||||
stream->print(ESPHOME_F("esphome_lock_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(ESPHOME_F("esphome_lock_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
stream->print(obj->state);
|
||||
stream->print(ESPHOME_F("\n"));
|
||||
@@ -504,21 +509,21 @@ void PrometheusHandler::text_sensor_row_(AsyncResponseStream *stream, text_senso
|
||||
if (obj->has_state()) {
|
||||
// We have a valid value, output this value
|
||||
stream->print(ESPHOME_F("esphome_text_sensor_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(ESPHOME_F("esphome_text_sensor_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\",value=\""));
|
||||
stream->print(obj->state.c_str());
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
@@ -527,12 +532,12 @@ void PrometheusHandler::text_sensor_row_(AsyncResponseStream *stream, text_senso
|
||||
} else {
|
||||
// Invalid state
|
||||
stream->print(ESPHOME_F("esphome_text_sensor_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 1\n"));
|
||||
}
|
||||
}
|
||||
@@ -551,21 +556,21 @@ void PrometheusHandler::text_row_(AsyncResponseStream *stream, text::Text *obj,
|
||||
if (obj->has_state()) {
|
||||
// We have a valid value, output this value
|
||||
stream->print(ESPHOME_F("esphome_text_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(ESPHOME_F("esphome_text_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\",value=\""));
|
||||
stream->print(obj->state.c_str());
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
@@ -574,12 +579,12 @@ void PrometheusHandler::text_row_(AsyncResponseStream *stream, text::Text *obj,
|
||||
} else {
|
||||
// Invalid state
|
||||
stream->print(ESPHOME_F("esphome_text_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 1\n"));
|
||||
}
|
||||
}
|
||||
@@ -598,21 +603,21 @@ void PrometheusHandler::event_row_(AsyncResponseStream *stream, event::Event *ob
|
||||
if (obj->has_event()) {
|
||||
// We have a valid event type, output this value
|
||||
stream->print(ESPHOME_F("esphome_event_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(ESPHOME_F("esphome_event_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\",last_event_type=\""));
|
||||
// get_last_event_type() returns StringRef (null-terminated)
|
||||
stream->print(obj->get_last_event_type().c_str());
|
||||
@@ -622,12 +627,12 @@ void PrometheusHandler::event_row_(AsyncResponseStream *stream, event::Event *ob
|
||||
} else {
|
||||
// No event triggered yet
|
||||
stream->print(ESPHOME_F("esphome_event_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 1\n"));
|
||||
}
|
||||
}
|
||||
@@ -646,33 +651,33 @@ void PrometheusHandler::number_row_(AsyncResponseStream *stream, number::Number
|
||||
if (!std::isnan(obj->state)) {
|
||||
// We have a valid value, output this value
|
||||
stream->print(ESPHOME_F("esphome_number_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(ESPHOME_F("esphome_number_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
stream->print(obj->state);
|
||||
stream->print(ESPHOME_F("\n"));
|
||||
} else {
|
||||
// Invalid state
|
||||
stream->print(ESPHOME_F("esphome_number_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 1\n"));
|
||||
}
|
||||
}
|
||||
@@ -690,21 +695,21 @@ void PrometheusHandler::select_row_(AsyncResponseStream *stream, select::Select
|
||||
if (obj->has_state()) {
|
||||
// We have a valid value, output this value
|
||||
stream->print(ESPHOME_F("esphome_select_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(ESPHOME_F("esphome_select_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\",value=\""));
|
||||
// c_str() is safe as option values are null-terminated strings from codegen
|
||||
stream->print(obj->current_option().c_str());
|
||||
@@ -714,12 +719,12 @@ void PrometheusHandler::select_row_(AsyncResponseStream *stream, select::Select
|
||||
} else {
|
||||
// Invalid state
|
||||
stream->print(ESPHOME_F("esphome_select_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 1\n"));
|
||||
}
|
||||
}
|
||||
@@ -737,43 +742,43 @@ void PrometheusHandler::media_player_row_(AsyncResponseStream *stream, media_pla
|
||||
if (obj->is_internal() && !this->include_internal_)
|
||||
return;
|
||||
stream->print(ESPHOME_F("esphome_media_player_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(ESPHOME_F("esphome_media_player_state_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\",value=\""));
|
||||
stream->print(media_player::media_player_state_to_string(obj->state));
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
stream->print(ESPHOME_F("1.0"));
|
||||
stream->print(ESPHOME_F("\n"));
|
||||
stream->print(ESPHOME_F("esphome_media_player_volume{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
stream->print(obj->volume);
|
||||
stream->print(ESPHOME_F("\n"));
|
||||
stream->print(ESPHOME_F("esphome_media_player_is_muted{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
if (obj->is_muted()) {
|
||||
stream->print(ESPHOME_F("1.0"));
|
||||
@@ -818,21 +823,21 @@ void PrometheusHandler::update_entity_row_(AsyncResponseStream *stream, update::
|
||||
if (obj->has_state()) {
|
||||
// We have a valid value, output this value
|
||||
stream->print(ESPHOME_F("esphome_update_entity_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// First update state
|
||||
stream->print(ESPHOME_F("esphome_update_entity_state{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\",value=\""));
|
||||
handle_update_state_(stream, obj->state);
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
@@ -840,12 +845,12 @@ void PrometheusHandler::update_entity_row_(AsyncResponseStream *stream, update::
|
||||
stream->print(ESPHOME_F("\n"));
|
||||
// Next update info
|
||||
stream->print(ESPHOME_F("esphome_update_entity_info{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\",current_version=\""));
|
||||
stream->print(obj->update_info.current_version.c_str());
|
||||
stream->print(ESPHOME_F("\",latest_version=\""));
|
||||
@@ -858,12 +863,12 @@ void PrometheusHandler::update_entity_row_(AsyncResponseStream *stream, update::
|
||||
} else {
|
||||
// Invalid state
|
||||
stream->print(ESPHOME_F("esphome_update_entity_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 1\n"));
|
||||
}
|
||||
}
|
||||
@@ -881,21 +886,21 @@ void PrometheusHandler::valve_row_(AsyncResponseStream *stream, valve::Valve *ob
|
||||
if (obj->is_internal() && !this->include_internal_)
|
||||
return;
|
||||
stream->print(ESPHOME_F("esphome_valve_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} 0\n"));
|
||||
// Data itself
|
||||
stream->print(ESPHOME_F("esphome_valve_operation{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\",operation=\""));
|
||||
stream->print(reinterpret_cast<ProgmemStr>(valve::valve_operation_to_str(obj->current_operation)));
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
@@ -904,12 +909,12 @@ void PrometheusHandler::valve_row_(AsyncResponseStream *stream, valve::Valve *ob
|
||||
// Now see if position is supported
|
||||
if (obj->get_traits().get_supports_position()) {
|
||||
stream->print(ESPHOME_F("esphome_valve_position{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
stream->print(obj->position);
|
||||
stream->print(ESPHOME_F("\n"));
|
||||
@@ -928,12 +933,12 @@ void PrometheusHandler::climate_setting_row_(AsyncResponseStream *stream, climat
|
||||
std::string &node, std::string &friendly_name, std::string &setting,
|
||||
const LogString *setting_value) {
|
||||
stream->print(ESPHOME_F("esphome_climate_setting{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\",category=\""));
|
||||
stream->print(setting.c_str());
|
||||
stream->print(ESPHOME_F("\",setting_value=\""));
|
||||
@@ -951,12 +956,12 @@ void PrometheusHandler::climate_value_row_(AsyncResponseStream *stream, climate:
|
||||
std::string &node, std::string &friendly_name, std::string &category,
|
||||
const char *climate_value) {
|
||||
stream->print(ESPHOME_F("esphome_climate_value{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\",category=\""));
|
||||
stream->print(category.c_str());
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
@@ -968,12 +973,12 @@ void PrometheusHandler::climate_failed_row_(AsyncResponseStream *stream, climate
|
||||
std::string &node, std::string &friendly_name, std::string &category,
|
||||
bool is_failed_value) {
|
||||
stream->print(ESPHOME_F("esphome_climate_failed{id=\""));
|
||||
stream->print(relabel_id_(obj).c_str());
|
||||
this->print_relabel_id_(stream, obj);
|
||||
add_area_label_(stream, area);
|
||||
add_node_label_(stream, node);
|
||||
add_friendly_name_label_(stream, friendly_name);
|
||||
stream->print(ESPHOME_F("\",name=\""));
|
||||
stream->print(relabel_name_(obj).c_str());
|
||||
this->print_relabel_name_(stream, obj);
|
||||
stream->print(ESPHOME_F("\",category=\""));
|
||||
stream->print(category.c_str());
|
||||
stream->print(ESPHOME_F("\"} "));
|
||||
|
||||
@@ -63,8 +63,8 @@ class PrometheusHandler final : public AsyncWebHandler, public Component {
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string relabel_id_(EntityBase *obj);
|
||||
std::string relabel_name_(EntityBase *obj);
|
||||
void print_relabel_id_(AsyncResponseStream *stream, EntityBase *obj);
|
||||
void print_relabel_name_(AsyncResponseStream *stream, EntityBase *obj);
|
||||
void add_area_label_(AsyncResponseStream *stream, std::string &area);
|
||||
void add_node_label_(AsyncResponseStream *stream, std::string &node);
|
||||
void add_friendly_name_label_(AsyncResponseStream *stream, std::string &friendly_name);
|
||||
|
||||
@@ -218,7 +218,7 @@ EntityMatchResult UrlMatch::match_entity(EntityBase *entity) const {
|
||||
#endif
|
||||
|
||||
// Match by entity name
|
||||
if (this->id == entity->get_name()) {
|
||||
if (entity->name_equals(this->id)) {
|
||||
result.matched = true;
|
||||
}
|
||||
|
||||
@@ -651,9 +651,7 @@ void WebServer::handle_js_request(AsyncWebServerRequest *request) {
|
||||
// Build unique id as: {domain}/{device_name}/{entity_name} or {domain}/{entity_name}
|
||||
// Uses names (not object_id) to avoid UTF-8 collision issues
|
||||
static void set_json_id(JsonObject root, EntityBase *obj, const char *prefix, JsonDetail start_config) {
|
||||
const StringRef &name = obj->get_name();
|
||||
size_t prefix_len = strlen(prefix);
|
||||
size_t name_len = name.size();
|
||||
|
||||
#ifdef USE_DEVICES
|
||||
Device *device = obj->get_device();
|
||||
@@ -683,13 +681,20 @@ static void set_json_id(JsonObject root, EntityBase *obj, const char *prefix, Js
|
||||
*p++ = '/';
|
||||
}
|
||||
#endif
|
||||
memcpy(p, name.c_str(), name_len);
|
||||
p[name_len] = '\0';
|
||||
#ifdef USE_ESP8266
|
||||
const char *name = p;
|
||||
#endif
|
||||
obj->write_name_to(p, id_buf + ID_BUF_SIZE - p);
|
||||
root[ESPHOME_F("id")] = static_cast<const char *>(id_buf);
|
||||
|
||||
if (start_config == DETAIL_ALL) {
|
||||
root[ESPHOME_F("domain")] = linked(prefix, prefix_len);
|
||||
root[ESPHOME_F("name")] = linked(name);
|
||||
#ifdef USE_ESP8266
|
||||
root[ESPHOME_F("name")] = name; // in id_buf on the stack, so copied
|
||||
#else
|
||||
const StringRef &ram_name = obj->get_name_progmem().ram_ref();
|
||||
root[ESPHOME_F("name")] = linked(ram_name.c_str(), ram_name.size());
|
||||
#endif
|
||||
#ifdef USE_DEVICES
|
||||
if (device_name) {
|
||||
root[ESPHOME_F("device")] = linked(device_name, device_len);
|
||||
|
||||
@@ -42,8 +42,10 @@ void write_row(AsyncResponseStream *stream, EntityBase *obj, const std::string &
|
||||
// Add data attributes for hierarchical URL support
|
||||
stream->print("\" data-domain=\"");
|
||||
stream->print(klass.c_str());
|
||||
char name_buf[ENTITY_NAME_BUF_SIZE];
|
||||
const char *name = obj->get_name_to(name_buf).c_str();
|
||||
stream->print("\" data-name=\"");
|
||||
write_html_escaped(stream, obj->get_name().c_str());
|
||||
write_html_escaped(stream, name);
|
||||
#ifdef USE_DEVICES
|
||||
Device *device = obj->get_device();
|
||||
if (device != nullptr) {
|
||||
@@ -59,7 +61,7 @@ void write_row(AsyncResponseStream *stream, EntityBase *obj, const std::string &
|
||||
stream->print("] ");
|
||||
}
|
||||
#endif
|
||||
write_html_escaped(stream, obj->get_name().c_str());
|
||||
write_html_escaped(stream, name);
|
||||
stream->print("</td><td></td><td>");
|
||||
stream->print(action.c_str());
|
||||
if (action_func) {
|
||||
|
||||
@@ -2471,6 +2471,7 @@ def _validate_no_slash(value):
|
||||
# This ensures web server URL IDs fit in a 280-byte buffer:
|
||||
# domain(20) + "/" + device(120) + "/" + name(120) + null = 263 bytes
|
||||
# Note: Must be < 255 because web_server UrlMatch uses uint8_t for length fields
|
||||
# Keep in sync with ESPHOME_ENTITY_NAME_MAX_LEN in esphome/core/entity_base.h
|
||||
NAME_MAX_LENGTH = 120
|
||||
|
||||
|
||||
|
||||
@@ -1,20 +1,64 @@
|
||||
#include "esphome/core/entity_base.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
#include "esphome/core/string_ref.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
namespace esphome {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "entity_base");
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
namespace {
|
||||
// fnv1_hash_object_id() for a name in flash
|
||||
uint32_t fnv1_hash_object_id_progmem(const char *str, size_t len) {
|
||||
uint32_t hash = FNV1_OFFSET_BASIS;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
hash *= FNV1_PRIME;
|
||||
char c = static_cast<char>(progmem_read_byte(reinterpret_cast<const uint8_t *>(str + i)));
|
||||
hash ^= static_cast<uint8_t>(to_sanitized_char(to_snake_case_char(c)));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
// RAM copies made by get_name(), only for entities whose name is asked for
|
||||
struct NameCopy {
|
||||
NameCopy *next;
|
||||
const char *key;
|
||||
StringRef ref;
|
||||
};
|
||||
NameCopy *name_copies = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
const StringRef EMPTY_NAME;
|
||||
} // namespace
|
||||
|
||||
const StringRef &EntityBase::get_name() const {
|
||||
const char *key = this->name_.progmem_ptr();
|
||||
for (NameCopy *copy = name_copies; copy != nullptr; copy = copy->next) {
|
||||
if (copy->key == key)
|
||||
return copy->ref;
|
||||
}
|
||||
size_t len = this->name_.size();
|
||||
void *mem = malloc(sizeof(NameCopy) + len + 1); // NOLINT(cppcoreguidelines-no-malloc)
|
||||
if (mem == nullptr)
|
||||
return EMPTY_NAME;
|
||||
char *buf = static_cast<char *>(mem) + sizeof(NameCopy);
|
||||
this->name_.write_to(buf, len + 1);
|
||||
name_copies = new (mem) NameCopy{name_copies, key, StringRef(buf, len)};
|
||||
return name_copies->ref;
|
||||
}
|
||||
#endif
|
||||
|
||||
void EntityBase::configure_entity_(const char *name, uint32_t object_id_hash, uint32_t entity_fields) {
|
||||
this->name_ = StringRef(name);
|
||||
this->name_ = ProgmemStringRef(name, ESPHOME_strlen_P(name));
|
||||
if (this->name_.empty()) {
|
||||
StringRef fallback;
|
||||
#ifdef USE_DEVICES
|
||||
if (this->device_ != nullptr) {
|
||||
this->name_ = StringRef(this->device_->get_name());
|
||||
fallback = StringRef(this->device_->get_name());
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@@ -24,23 +68,27 @@ void EntityBase::configure_entity_(const char *name, uint32_t object_id_hash, ui
|
||||
const auto &friendly = App.get_friendly_name();
|
||||
if (App.is_name_add_mac_suffix_enabled()) {
|
||||
// MAC suffix enabled - use friendly_name directly (even if empty) for compatibility
|
||||
this->name_ = friendly;
|
||||
fallback = friendly;
|
||||
} else {
|
||||
// No MAC suffix - fallback to device name if friendly_name is empty
|
||||
this->name_ = !friendly.empty() ? friendly : App.get_name();
|
||||
fallback = !friendly.empty() ? friendly : App.get_name();
|
||||
}
|
||||
}
|
||||
this->name_ = ProgmemStringRef(fallback);
|
||||
this->flags_.has_own_name = false;
|
||||
// Dynamic name - must calculate hash at runtime
|
||||
this->calc_object_id_();
|
||||
// Dynamic name in RAM - hash it at runtime
|
||||
this->object_id_hash_ = fnv1_hash_object_id(fallback.c_str(), fallback.size());
|
||||
} else {
|
||||
this->flags_.has_own_name = true;
|
||||
// Static name - use pre-computed hash if provided
|
||||
if (object_id_hash != 0) {
|
||||
this->object_id_hash_ = object_id_hash;
|
||||
} else {
|
||||
this->calc_object_id_();
|
||||
// Static name - codegen precomputes the hash; external register_* callers may pass 0
|
||||
if (object_id_hash == 0) {
|
||||
#ifdef USE_ESP8266
|
||||
object_id_hash = fnv1_hash_object_id_progmem(this->name_.progmem_ptr(), this->name_.size());
|
||||
#else
|
||||
object_id_hash = fnv1_hash_object_id(this->name_.progmem_ptr(), this->name_.size());
|
||||
#endif
|
||||
}
|
||||
this->object_id_hash_ = object_id_hash;
|
||||
}
|
||||
// Unpack entity string table indices and flags from entity_fields.
|
||||
#ifdef USE_ENTITY_DEVICE_CLASS
|
||||
@@ -61,7 +109,7 @@ void EntityBase::set_internal(bool internal) {
|
||||
// Remove the after-setup path in 2027.3.0 and ignore the call instead.
|
||||
if (App.is_setup_complete()) {
|
||||
ESP_LOGE(TAG, "'%s': set_internal() after setup is undefined behavior, stops working in 2027.3.0",
|
||||
this->get_name().c_str());
|
||||
LOG_STR_ARG(this->get_log_name()));
|
||||
}
|
||||
this->flags_.internal = internal;
|
||||
}
|
||||
@@ -117,17 +165,11 @@ const char *EntityBase::get_icon_to([[maybe_unused]] std::span<char, MAX_ICON_LE
|
||||
#endif
|
||||
}
|
||||
|
||||
// Calculate Object ID Hash directly from name using snake_case + sanitize
|
||||
void EntityBase::calc_object_id_() {
|
||||
this->object_id_hash_ = fnv1_hash_object_id(this->name_.c_str(), this->name_.size());
|
||||
}
|
||||
|
||||
size_t EntityBase::write_object_id_to(char *buf, size_t buf_size) const {
|
||||
size_t len = std::min(this->name_.size(), buf_size - 1);
|
||||
size_t len = this->write_name_to(buf, buf_size);
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
buf[i] = to_sanitized_char(to_snake_case_char(this->name_[i]));
|
||||
buf[i] = to_sanitized_char(to_snake_case_char(buf[i]));
|
||||
}
|
||||
buf[len] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,11 @@ static constexpr size_t ESPHOME_DEVICE_NAME_MAX_LEN = 31;
|
||||
// esphome/core/config.py
|
||||
static constexpr size_t ESPHOME_FRIENDLY_NAME_MAX_LEN = 120;
|
||||
|
||||
// Maximum entity name length - keep in sync with NAME_MAX_LENGTH in esphome/config_validation.py
|
||||
static constexpr size_t ESPHOME_ENTITY_NAME_MAX_LEN = 120;
|
||||
|
||||
static constexpr size_t ENTITY_NAME_BUF_SIZE = ESPHOME_ENTITY_NAME_MAX_LEN + 1;
|
||||
|
||||
// Maximum domain length (longest: "alarm_control_panel" = 19)
|
||||
static constexpr size_t ESPHOME_DOMAIN_MAX_LEN = 20;
|
||||
|
||||
@@ -67,8 +72,28 @@ static constexpr uint8_t ENTITY_FIELD_ENTITY_CATEGORY_SHIFT = 26;
|
||||
// The generic Entity base class that provides an interface common to all Entities.
|
||||
class EntityBase {
|
||||
public:
|
||||
// Get the name of this Entity
|
||||
const StringRef &get_name() const { return this->name_; }
|
||||
#ifdef USE_ESP8266
|
||||
/// The name is in flash here; the first call makes a RAM copy that is kept for the life of the device.
|
||||
const StringRef &get_name() const;
|
||||
/// Get the name of this Entity, copied out of flash into buffer.
|
||||
StringRef get_name_to(std::span<char, ENTITY_NAME_BUF_SIZE> buffer) const {
|
||||
return StringRef(buffer.data(), this->write_name_to(buffer.data(), buffer.size()));
|
||||
}
|
||||
#else
|
||||
const StringRef &get_name() const { return this->name_.ram_ref(); }
|
||||
const StringRef &get_name_to(std::span<char, ENTITY_NAME_BUF_SIZE> /*buffer*/) const { return this->name_.ram_ref(); }
|
||||
#endif
|
||||
|
||||
bool name_equals(const StringRef &other) const { return this->name_.equals(other); }
|
||||
|
||||
/// The name as stored, for consumers that read flash themselves (e.g. API progmem fields).
|
||||
const ProgmemStringRef &get_name_progmem() const { return this->name_; }
|
||||
|
||||
/// Copy the name into buf (null terminated), returns its length.
|
||||
size_t write_name_to(char *buf, size_t buf_size) const { return this->name_.write_to(buf, buf_size); }
|
||||
|
||||
/// Get the name for a "%s" log argument (LOG_STR_ARG).
|
||||
const LogString *get_log_name() const { return reinterpret_cast<const LogString *>(this->name_.progmem_ptr()); }
|
||||
|
||||
// Get whether this Entity has its own name or it should use the device friendly_name.
|
||||
bool has_own_name() const { return this->flags_.has_own_name; }
|
||||
@@ -210,9 +235,7 @@ class EntityBase {
|
||||
/// When the preference hash algorithm changes, migration logic goes here.
|
||||
ESPPreferenceObject make_entity_preference_(size_t size, uint32_t version);
|
||||
|
||||
void calc_object_id_();
|
||||
|
||||
StringRef name_;
|
||||
ProgmemStringRef name_;
|
||||
uint32_t object_id_hash_{};
|
||||
#ifdef USE_DEVICES
|
||||
Device *device_{};
|
||||
|
||||
@@ -23,7 +23,13 @@ from esphome.core.config import (
|
||||
ICON_MAX_LENGTH,
|
||||
UNIT_OF_MEASUREMENT_MAX_LENGTH,
|
||||
)
|
||||
from esphome.cpp_generator import MockObj, RawStatement, add, get_variable
|
||||
from esphome.cpp_generator import (
|
||||
MockObj,
|
||||
RawExpression,
|
||||
RawStatement,
|
||||
add,
|
||||
get_variable,
|
||||
)
|
||||
from esphome.cpp_types import App
|
||||
import esphome.final_validate as fv
|
||||
from esphome.helpers import (
|
||||
@@ -306,7 +312,9 @@ def finalize_entity_strings(var: MockObj, config: ConfigType) -> None:
|
||||
``App.register_<method>(var, name, hash, packed)``. Otherwise falls back to a
|
||||
standalone ``var->configure_entity_(name, hash, packed)``.
|
||||
"""
|
||||
entity_name = config[_KEY_ENTITY_NAME]
|
||||
entity_name = RawExpression(
|
||||
f"ESPHOME_PSTR({cpp_string_escape(config[_KEY_ENTITY_NAME])})"
|
||||
)
|
||||
object_id_hash = config[_KEY_OBJECT_ID_HASH]
|
||||
dc_idx = config.get(_KEY_DC_IDX, 0)
|
||||
uom_idx = config.get(_KEY_UOM_IDX, 0)
|
||||
|
||||
+61
-18
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
@@ -189,24 +190,6 @@ inline bool operator!=(const StringRef &lhs, const __FlashStringHelper *rhs) { r
|
||||
|
||||
inline bool operator!=(const __FlashStringHelper *lhs, const StringRef &rhs) { return !(rhs == lhs); }
|
||||
|
||||
/// Codegen use only: a flash string literal with its byte length, compared without a runtime strlen.
|
||||
struct ProgmemStringRef {
|
||||
PGM_P str;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
inline bool operator==(const std::string &lhs, ProgmemStringRef rhs) {
|
||||
return lhs.size() == rhs.len && (rhs.len == 0 || memcmp_P(lhs.data(), rhs.str, rhs.len) == 0);
|
||||
}
|
||||
|
||||
inline bool operator!=(const std::string &lhs, ProgmemStringRef rhs) { return !(lhs == rhs); }
|
||||
|
||||
inline bool operator==(const StringRef &lhs, ProgmemStringRef rhs) {
|
||||
// A StringRef may be {nullptr, 0}, and memcmp_P with a null pointer is undefined even for 0 bytes
|
||||
return lhs.size() == rhs.len && (rhs.len == 0 || memcmp_P(lhs.c_str(), rhs.str, rhs.len) == 0);
|
||||
}
|
||||
|
||||
inline bool operator!=(const StringRef &lhs, ProgmemStringRef rhs) { return !(lhs == rhs); }
|
||||
#endif // USE_ESP8266
|
||||
|
||||
inline bool operator<(const StringRef &lhs, const StringRef &rhs) {
|
||||
@@ -241,6 +224,66 @@ inline std::string operator+(const std::string &lhs, const StringRef &rhs) {
|
||||
str.append(rhs.c_str(), rhs.size());
|
||||
return str;
|
||||
}
|
||||
|
||||
/// A string that may live in flash (on ESP8266): pointer and length, with no byte-reading operations.
|
||||
/// progmem_ptr() is safe as a "%s" log argument; read the contents with write_to() or equals().
|
||||
class ProgmemStringRef {
|
||||
public:
|
||||
constexpr ProgmemStringRef() = default;
|
||||
constexpr ProgmemStringRef(const char *s, size_t len) : ref_(s, len) {}
|
||||
constexpr explicit ProgmemStringRef(const StringRef &s) : ref_(s) {}
|
||||
|
||||
constexpr const char *progmem_ptr() const { return this->ref_.c_str(); }
|
||||
constexpr size_t size() const { return this->ref_.size(); }
|
||||
constexpr bool empty() const { return this->ref_.empty(); }
|
||||
|
||||
/// Copy into buf (null terminated, truncated to fit), returns the length copied.
|
||||
size_t write_to(char *buf, size_t buf_size) const {
|
||||
if (buf_size == 0)
|
||||
return 0;
|
||||
size_t len = std::min(this->ref_.size(), buf_size - 1);
|
||||
#ifdef USE_ESP8266
|
||||
memcpy_P(buf, this->ref_.c_str(), len);
|
||||
#else
|
||||
std::memcpy(buf, this->ref_.c_str(), len);
|
||||
#endif
|
||||
buf[len] = '\0';
|
||||
return len;
|
||||
}
|
||||
|
||||
bool equals(const StringRef &other) const {
|
||||
#ifdef USE_ESP8266
|
||||
// A StringRef may be {nullptr, 0}, and memcmp_P with a null pointer is undefined even for 0 bytes
|
||||
return other.size() == this->ref_.size() &&
|
||||
(other.empty() || memcmp_P(other.c_str(), this->ref_.c_str(), other.size()) == 0);
|
||||
#else
|
||||
return other == this->ref_;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef USE_ESP8266
|
||||
/// The string is in RAM here, so it can be viewed directly.
|
||||
constexpr const StringRef &ram_ref() const { return this->ref_; }
|
||||
#endif
|
||||
|
||||
// Remove before 2027.5.0
|
||||
[[deprecated(
|
||||
"May point to flash; use progmem_ptr() or the owner's accessors. Removed in 2027.5.0")]] constexpr const char *
|
||||
c_str() const {
|
||||
return this->ref_.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
StringRef ref_;
|
||||
};
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
inline bool operator==(const StringRef &lhs, const ProgmemStringRef &rhs) { return rhs.equals(lhs); }
|
||||
inline bool operator!=(const StringRef &lhs, const ProgmemStringRef &rhs) { return !rhs.equals(lhs); }
|
||||
inline bool operator==(const std::string &lhs, const ProgmemStringRef &rhs) { return rhs.equals(StringRef(lhs)); }
|
||||
inline bool operator!=(const std::string &lhs, const ProgmemStringRef &rhs) { return !rhs.equals(StringRef(lhs)); }
|
||||
#endif
|
||||
|
||||
// String conversion functions for ADL compatibility (allows stoi(x) where x is StringRef)
|
||||
// Must be in esphome namespace for ADL to find them. Uses strtol/strtod directly to avoid heap allocation.
|
||||
namespace internal {
|
||||
|
||||
@@ -536,16 +536,19 @@ def create_field_type_info(
|
||||
f"track_presence on field '{field.name}' has no effect; it requires "
|
||||
"a non-repeated message field in a message that is decoded"
|
||||
)
|
||||
if get_field_opt(field, pb.progmem, False) and (
|
||||
field.label == FieldDescriptorProto.LABEL_REPEATED
|
||||
or field.type != 12
|
||||
or not get_field_opt(field, pb.pointer_to_buffer, False)
|
||||
or get_field_opt(field, pb.fixed_array_size) is not None
|
||||
):
|
||||
raise ValueError(
|
||||
f"progmem on field '{field.name}' requires a non-repeated bytes field "
|
||||
"with pointer_to_buffer"
|
||||
if get_field_opt(field, pb.progmem, False):
|
||||
is_pointer_bytes = (
|
||||
field.type == FieldDescriptorProto.TYPE_BYTES
|
||||
and get_field_opt(field, pb.pointer_to_buffer, False)
|
||||
and get_field_opt(field, pb.fixed_array_size) is None
|
||||
)
|
||||
if field.label == FieldDescriptorProto.LABEL_REPEATED or not (
|
||||
field.type == FieldDescriptorProto.TYPE_STRING or is_pointer_bytes
|
||||
):
|
||||
raise ValueError(
|
||||
f"progmem on field '{field.name}' requires a non-repeated string field, "
|
||||
"or a bytes field with pointer_to_buffer"
|
||||
)
|
||||
if field.label == FieldDescriptorProto.LABEL_REPEATED:
|
||||
# Check if this is a packed_buffer field (zero-copy packed repeated)
|
||||
if get_field_opt(field, pb.packed_buffer, False):
|
||||
@@ -1155,6 +1158,11 @@ class PointerToBufferTypeBase(TypeInfo):
|
||||
"""Get the wire type for this field."""
|
||||
return WireType.LENGTH_DELIMITED # Uses wire type 2
|
||||
|
||||
@property
|
||||
def progmem(self) -> bool:
|
||||
"""Whether the data is in flash, so encode and dump copy it with progmem_memcpy."""
|
||||
return get_field_opt(self._field, pb.progmem, False)
|
||||
|
||||
def get_estimated_size(self) -> int:
|
||||
# field ID + length varint + typical data (assume small for pointer fields)
|
||||
return self.calculate_field_id_size() + 2 + 16
|
||||
@@ -1168,11 +1176,6 @@ class PointerToBytesBufferType(PointerToBufferTypeBase):
|
||||
reference_type = "const uint8_t*"
|
||||
const_reference_type = "const uint8_t*"
|
||||
|
||||
@property
|
||||
def progmem(self) -> bool:
|
||||
"""Whether the data is in flash, so encode and dump copy it with progmem_memcpy."""
|
||||
return get_field_opt(self._field, pb.progmem, False)
|
||||
|
||||
@property
|
||||
def public_content(self) -> list[str]:
|
||||
# Use uint16_t for length - max packet size is well below 65535
|
||||
@@ -1252,6 +1255,8 @@ class PointerToStringBufferType(PointerToBufferTypeBase):
|
||||
|
||||
@property
|
||||
def public_content(self) -> list[str]:
|
||||
if self.progmem:
|
||||
return [f"ProgmemStringRef {self.field_name}{{}};"]
|
||||
if self._starts_null:
|
||||
return [
|
||||
f"StringRef {self.field_name}{{nullptr, 0}}; // null until set, encode only"
|
||||
@@ -1267,9 +1272,19 @@ class PointerToStringBufferType(PointerToBufferTypeBase):
|
||||
)
|
||||
tag = self.calculate_tag()
|
||||
if tag < 128:
|
||||
return _encode_call(
|
||||
"encode_short_string_force", str(tag), f"this->{self.field_name}"
|
||||
encode_fn = (
|
||||
"encode_short_progmem_string_force"
|
||||
if self.progmem
|
||||
else "encode_short_string_force"
|
||||
)
|
||||
return _encode_call(encode_fn, str(tag), f"this->{self.field_name}")
|
||||
if self.progmem:
|
||||
return _encode_call(
|
||||
"encode_progmem_string",
|
||||
str(self.number),
|
||||
f"this->{self.field_name}",
|
||||
force=self.force,
|
||||
)
|
||||
if result := self._encode_bytes_with_precomputed_tag(
|
||||
f"this->{self.field_name}.c_str()",
|
||||
f"this->{self.field_name}.size()",
|
||||
@@ -1297,6 +1312,8 @@ class PointerToStringBufferType(PointerToBufferTypeBase):
|
||||
|
||||
@property
|
||||
def dump_content(self) -> str:
|
||||
if self.progmem:
|
||||
return f'dump_progmem_string_field(out, ESPHOME_PSTR("{self.name}"), this->{self.field_name});'
|
||||
return f'dump_field(out, ESPHOME_PSTR("{self.name}"), this->{self.field_name});'
|
||||
|
||||
def get_size_calculation(self, name: str, force: bool = False) -> str:
|
||||
@@ -3246,8 +3263,9 @@ namespace esphome::api {
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
// Out-of-line to avoid inlining strlen_P/memcpy_P at every call site
|
||||
void DumpBuffer::append_p_esp8266(const char *str) {
|
||||
size_t len = strlen_P(str);
|
||||
void DumpBuffer::append_p_esp8266(const char *str) { this->append_p_esp8266(str, strlen_P(str)); }
|
||||
|
||||
void DumpBuffer::append_p_esp8266(const char *str, size_t len) {
|
||||
size_t space = CAPACITY - 1 - pos_;
|
||||
if (len > space)
|
||||
len = space;
|
||||
@@ -3368,6 +3386,13 @@ static void dump_progmem_bytes_field(DumpBuffer &out, const char *field_name, co
|
||||
progmem_memcpy(data_buf, data, len);
|
||||
dump_bytes_field(out, field_name, data_buf, len, indent);
|
||||
}
|
||||
|
||||
// Helper for string fields in flash
|
||||
static void dump_progmem_string_field(DumpBuffer &out, const char *field_name, const ProgmemStringRef &value,
|
||||
int indent = 2) {
|
||||
append_field_prefix(out, field_name, indent);
|
||||
out.append("'").append_p(value.progmem_ptr(), value.size()).append("'\\n");
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
"""
|
||||
|
||||
@@ -16,7 +16,7 @@ static ListEntitiesSensorResponse make_sensor_response() {
|
||||
ListEntitiesSensorResponse msg;
|
||||
msg.object_id = StringRef::from_lit("living_room_temperature");
|
||||
msg.key = 0x12345678;
|
||||
msg.name = StringRef::from_lit("Living Room Temperature");
|
||||
msg.name = ProgmemStringRef(StringRef::from_lit("Living Room Temperature"));
|
||||
#ifdef USE_ENTITY_ICON
|
||||
msg.icon = StringRef::from_lit("mdi:thermometer");
|
||||
#endif
|
||||
@@ -87,7 +87,7 @@ static ListEntitiesBinarySensorResponse make_binary_sensor_response() {
|
||||
ListEntitiesBinarySensorResponse msg;
|
||||
msg.object_id = StringRef::from_lit("front_door_contact");
|
||||
msg.key = 0xAABBCCDD;
|
||||
msg.name = StringRef::from_lit("Front Door Contact");
|
||||
msg.name = ProgmemStringRef(StringRef::from_lit("Front Door Contact"));
|
||||
#ifdef USE_ENTITY_ICON
|
||||
msg.icon = StringRef::from_lit("mdi:door");
|
||||
#endif
|
||||
@@ -176,7 +176,7 @@ static ListEntitiesLightResponse make_light_response() {
|
||||
ListEntitiesLightResponse msg;
|
||||
msg.object_id = StringRef::from_lit("kitchen_ceiling_light");
|
||||
msg.key = 0x55667788;
|
||||
msg.name = StringRef::from_lit("Kitchen Ceiling Light");
|
||||
msg.name = ProgmemStringRef(StringRef::from_lit("Kitchen Ceiling Light"));
|
||||
#ifdef USE_ENTITY_ICON
|
||||
msg.icon = StringRef::from_lit("mdi:ceiling-light");
|
||||
#endif
|
||||
|
||||
@@ -739,7 +739,8 @@ def blob_in(main_cpp: str) -> bytes:
|
||||
def entity_hash(main_cpp: str, variable: str) -> int:
|
||||
"""The key the generated code passes to configure_entity_, which ListEntities then sends."""
|
||||
match = re.search(
|
||||
rf'App\.register_switch\({variable}, "[^"]*", (\d+)UL, \d+\)', main_cpp
|
||||
rf'App\.register_switch\({variable}, ESPHOME_PSTR\("[^"]*"\), (\d+)UL, \d+\)',
|
||||
main_cpp,
|
||||
)
|
||||
assert match is not None, variable
|
||||
return int(match.group(1))
|
||||
|
||||
@@ -31,7 +31,7 @@ def test_binary_sensor_sets_mandatory_fields(generate_main):
|
||||
)
|
||||
|
||||
# Then
|
||||
assert 'App.register_binary_sensor(bs_1, "test bs1",' in main_cpp
|
||||
assert 'App.register_binary_sensor(bs_1, ESPHOME_PSTR("test bs1"),' in main_cpp
|
||||
assert "bs_1->set_pin(" in main_cpp
|
||||
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ def test_button_sets_mandatory_fields(generate_main):
|
||||
main_cpp = generate_main("tests/component_tests/button/test_button.yaml")
|
||||
|
||||
# Then
|
||||
assert 'App.register_button(wol_1, "wol_test_1",' in main_cpp
|
||||
assert 'App.register_button(wol_1, ESPHOME_PSTR("wol_test_1"),' in main_cpp
|
||||
assert "wol_2->set_macaddr(18, 52, 86, 120, 144, 171);" in main_cpp
|
||||
|
||||
|
||||
|
||||
@@ -14,15 +14,12 @@ def extract_packed_value(main_cpp: str, var_name: str) -> int:
|
||||
combined form ``App.register_<entity>(var, name, hash, packed)``.
|
||||
"""
|
||||
escaped_var = re.escape(var_name)
|
||||
name_re = r'ESPHOME_PSTR\("(?:\\.|[^"\\])*"\)'
|
||||
legacy_pattern = (
|
||||
rf"{escaped_var}->configure_entity_\("
|
||||
r'"(?:\\.|[^"\\])*"'
|
||||
r",\s*\w+,\s*(\d+)\)"
|
||||
rf"{escaped_var}->configure_entity_\(" + name_re + r",\s*\w+,\s*(\d+)\)"
|
||||
)
|
||||
combined_pattern = (
|
||||
rf"App\.register_\w+\(\s*{escaped_var}\s*,\s*"
|
||||
r'"(?:\\.|[^"\\])*"'
|
||||
r",\s*\w+,\s*(\d+)\)"
|
||||
rf"App\.register_\w+\(\s*{escaped_var}\s*,\s*" + name_re + r",\s*\w+,\s*(\d+)\)"
|
||||
)
|
||||
match = re.search(combined_pattern, main_cpp) or re.search(legacy_pattern, main_cpp)
|
||||
assert match, f"configure call not found for {var_name}"
|
||||
|
||||
@@ -28,7 +28,7 @@ def test_text_sets_mandatory_fields(generate_main):
|
||||
main_cpp = generate_main("tests/component_tests/text/test_text.yaml")
|
||||
|
||||
# Then
|
||||
assert 'App.register_text(it_1, "test 1 text",' in main_cpp
|
||||
assert 'App.register_text(it_1, ESPHOME_PSTR("test 1 text"),' in main_cpp
|
||||
|
||||
|
||||
def test_text_config_value_internal_set(generate_main):
|
||||
|
||||
@@ -31,9 +31,9 @@ def test_text_sensor_sets_mandatory_fields(generate_main):
|
||||
main_cpp = generate_main("tests/component_tests/text_sensor/test_text_sensor.yaml")
|
||||
|
||||
# Then
|
||||
assert 'App.register_text_sensor(ts_1, "Template Text Sensor 1",' in main_cpp
|
||||
assert 'App.register_text_sensor(ts_2, "Template Text Sensor 2",' in main_cpp
|
||||
assert 'App.register_text_sensor(ts_3, "Template Text Sensor 3",' in main_cpp
|
||||
for i in (1, 2, 3):
|
||||
name = f'ESPHOME_PSTR("Template Text Sensor {i}")'
|
||||
assert f"App.register_text_sensor(ts_{i}, {name}," in main_cpp
|
||||
|
||||
|
||||
def test_text_sensor_config_value_internal_set(generate_main):
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "esphome/core/entity_base.h"
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace esphome::core::testing {
|
||||
|
||||
// External components return get_name() from `const StringRef &` getters, so it must stay a reference
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
static_assert(std::is_same_v<decltype(std::declval<const EntityBase &>().get_name()), const StringRef &>);
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
class TestEntity : public EntityBase {
|
||||
public:
|
||||
void configure(const char *name, uint32_t object_id_hash) { this->configure_entity_(name, object_id_hash, 0); }
|
||||
};
|
||||
|
||||
TEST(EntityBaseName, ZeroHashIsComputedFromTheName) {
|
||||
TestEntity entity;
|
||||
entity.configure("Living Room Temp", 0);
|
||||
EXPECT_EQ(entity.get_object_id_hash(), fnv1_hash_object_id("Living Room Temp", 16));
|
||||
}
|
||||
|
||||
TEST(EntityBaseName, PrecomputedHashIsKept) {
|
||||
TestEntity entity;
|
||||
entity.configure("Living Room Temp", 0x1234);
|
||||
EXPECT_EQ(entity.get_object_id_hash(), 0x1234u);
|
||||
}
|
||||
|
||||
} // namespace esphome::core::testing
|
||||
@@ -0,0 +1,49 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "esphome/core/string_ref.h"
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace esphome::core::testing {
|
||||
|
||||
// ram_ref() must return a reference so callers can hand it out as `const StringRef &`
|
||||
static_assert(std::is_same_v<decltype(std::declval<const ProgmemStringRef &>().ram_ref()), const StringRef &>);
|
||||
|
||||
TEST(ProgmemStringRef, WriteToCopiesAndTerminates) {
|
||||
ProgmemStringRef ref("Kitchen", 7);
|
||||
char buf[16];
|
||||
EXPECT_EQ(ref.write_to(buf, sizeof(buf)), 7u);
|
||||
EXPECT_STREQ(buf, "Kitchen");
|
||||
}
|
||||
|
||||
TEST(ProgmemStringRef, WriteToTruncatesToFit) {
|
||||
ProgmemStringRef ref("Kitchen", 7);
|
||||
char buf[4];
|
||||
EXPECT_EQ(ref.write_to(buf, sizeof(buf)), 3u);
|
||||
EXPECT_STREQ(buf, "Kit");
|
||||
}
|
||||
|
||||
TEST(ProgmemStringRef, WriteToZeroSizeWritesNothing) {
|
||||
ProgmemStringRef ref("Kitchen", 7);
|
||||
char buf[1] = {'x'};
|
||||
EXPECT_EQ(ref.write_to(buf, 0), 0u);
|
||||
EXPECT_EQ(buf[0], 'x');
|
||||
}
|
||||
|
||||
TEST(ProgmemStringRef, EqualsComparesLengthAndContent) {
|
||||
ProgmemStringRef ref("Kitchen", 7);
|
||||
EXPECT_TRUE(ref.equals(StringRef("Kitchen")));
|
||||
EXPECT_FALSE(ref.equals(StringRef("Kitche")));
|
||||
EXPECT_FALSE(ref.equals(StringRef("Kitchens")));
|
||||
EXPECT_FALSE(ref.equals(StringRef("Bedroom")));
|
||||
}
|
||||
|
||||
TEST(ProgmemStringRef, DefaultIsEmpty) {
|
||||
ProgmemStringRef ref;
|
||||
EXPECT_TRUE(ref.empty());
|
||||
EXPECT_EQ(ref.size(), 0u);
|
||||
EXPECT_TRUE(ref.equals(StringRef("")));
|
||||
}
|
||||
|
||||
} // namespace esphome::core::testing
|
||||
@@ -408,8 +408,39 @@ def test_progmem_rejected_in_a_decoded_message() -> None:
|
||||
|
||||
|
||||
def test_progmem_rejected_on_non_bytes_field() -> None:
|
||||
"""(progmem) only applies to bytes fields."""
|
||||
field = _field(9)
|
||||
"""(progmem) only applies to string and bytes fields."""
|
||||
field = _field(13)
|
||||
field.options.Extensions[pb.progmem] = True
|
||||
with pytest.raises(ValueError, match="progmem on field 'value'"):
|
||||
create_field_type_info(field, needs_decode=False)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("force", "max_len", "encode_fn"),
|
||||
[
|
||||
(True, 120, "encode_short_progmem_string_force("),
|
||||
(False, None, "encode_progmem_string("),
|
||||
(True, None, "encode_progmem_string_force("),
|
||||
],
|
||||
)
|
||||
def test_progmem_string_field_copies_from_flash(
|
||||
force: bool, max_len: int | None, encode_fn: str
|
||||
) -> None:
|
||||
"""A (progmem) string field is a ProgmemStringRef that encodes and dumps through the progmem helpers."""
|
||||
field = _field(9, force=force)
|
||||
field.options.Extensions[pb.progmem] = True
|
||||
if max_len is not None:
|
||||
field.options.Extensions[pb.max_data_length] = max_len
|
||||
ti = create_field_type_info(field, needs_decode=False)
|
||||
assert "ProgmemStringRef value{};" in ti.public_content
|
||||
assert encode_fn in ti.encode_content
|
||||
assert "encode_string" not in ti.encode_content
|
||||
assert "dump_progmem_string_field(" in ti.dump_content
|
||||
|
||||
|
||||
def test_progmem_rejected_on_repeated_string() -> None:
|
||||
"""(progmem) on a repeated string field fails instead of silently using memcpy."""
|
||||
field = _field(9, repeated=True)
|
||||
field.options.Extensions[pb.progmem] = True
|
||||
with pytest.raises(ValueError, match="progmem on field 'value'"):
|
||||
create_field_type_info(field, needs_decode=False)
|
||||
|
||||
@@ -38,11 +38,8 @@ from esphome.helpers import fnv1_hash, sanitize, snake_case
|
||||
|
||||
from .common import load_config_from_fixture
|
||||
|
||||
# Pre-compiled regex pattern for extracting names from configure_entity_/set_name calls
|
||||
# Matches: .configure_entity_("name", ...) or .set_name("name", ...)
|
||||
ENTITY_NAME_PATTERN = re.compile(
|
||||
r'\.(?:configure_entity_|set_name)\(["\']([^"\']*)["\']'
|
||||
)
|
||||
# Extracts the name from .configure_entity_(ESPHOME_PSTR("name"), ...)
|
||||
ENTITY_NAME_PATTERN = re.compile(r'\.configure_entity_\(ESPHOME_PSTR\("([^"]*)"')
|
||||
|
||||
FIXTURES_DIR = Path(__file__).parent.parent / "fixtures" / "core" / "entity_helpers"
|
||||
|
||||
@@ -1076,6 +1073,8 @@ async def test_finalize_no_flags(setup_test_environment: list[str]) -> None:
|
||||
packed = _extract_packed_value(added_expressions)
|
||||
assert packed == 0
|
||||
assert "//" not in added_expressions[0]
|
||||
# Names go through ESPHOME_PSTR so they stay in flash on ESP8266
|
||||
assert 'ESPHOME_PSTR("Test")' in added_expressions[0]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
Reference in New Issue
Block a user