1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-18 19:22:22 +01:00

Merge branch 'multi_device' into integration

This commit is contained in:
J. Nick Koston
2025-06-23 22:56:28 +02:00
32 changed files with 1418 additions and 59 deletions

View File

@@ -188,6 +188,17 @@ message DeviceInfoRequest {
// Empty
}
message AreaInfo {
uint32 area_id = 1;
string name = 2;
}
message DeviceInfo {
uint32 device_id = 1;
string name = 2;
uint32 area_id = 3;
}
message DeviceInfoResponse {
option (id) = 10;
option (source) = SOURCE_SERVER;
@@ -236,6 +247,12 @@ message DeviceInfoResponse {
// Supports receiving and saving api encryption key
bool api_encryption_supported = 19;
repeated DeviceInfo devices = 20;
repeated AreaInfo areas = 21;
// Top-level area info to phase out suggested_area
AreaInfo area = 22;
}
message ListEntitiesRequest {
@@ -280,6 +297,7 @@ message ListEntitiesBinarySensorResponse {
bool disabled_by_default = 7;
string icon = 8;
EntityCategory entity_category = 9;
uint32 device_id = 10;
}
message BinarySensorStateResponse {
option (id) = 21;
@@ -315,6 +333,7 @@ message ListEntitiesCoverResponse {
string icon = 10;
EntityCategory entity_category = 11;
bool supports_stop = 12;
uint32 device_id = 13;
}
enum LegacyCoverState {
@@ -388,6 +407,7 @@ message ListEntitiesFanResponse {
string icon = 10;
EntityCategory entity_category = 11;
repeated string supported_preset_modes = 12;
uint32 device_id = 13;
}
enum FanSpeed {
FAN_SPEED_LOW = 0;
@@ -471,6 +491,7 @@ message ListEntitiesLightResponse {
bool disabled_by_default = 13;
string icon = 14;
EntityCategory entity_category = 15;
uint32 device_id = 16;
}
message LightStateResponse {
option (id) = 24;
@@ -563,6 +584,7 @@ message ListEntitiesSensorResponse {
SensorLastResetType legacy_last_reset_type = 11;
bool disabled_by_default = 12;
EntityCategory entity_category = 13;
uint32 device_id = 14;
}
message SensorStateResponse {
option (id) = 25;
@@ -595,6 +617,7 @@ message ListEntitiesSwitchResponse {
bool disabled_by_default = 7;
EntityCategory entity_category = 8;
string device_class = 9;
uint32 device_id = 10;
}
message SwitchStateResponse {
option (id) = 26;
@@ -632,6 +655,7 @@ message ListEntitiesTextSensorResponse {
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
string device_class = 8;
uint32 device_id = 9;
}
message TextSensorStateResponse {
option (id) = 27;
@@ -814,6 +838,7 @@ message ListEntitiesCameraResponse {
bool disabled_by_default = 5;
string icon = 6;
EntityCategory entity_category = 7;
uint32 device_id = 8;
}
message CameraImageResponse {
@@ -916,6 +941,7 @@ message ListEntitiesClimateResponse {
bool supports_target_humidity = 23;
float visual_min_humidity = 24;
float visual_max_humidity = 25;
uint32 device_id = 26;
}
message ClimateStateResponse {
option (id) = 47;
@@ -999,6 +1025,7 @@ message ListEntitiesNumberResponse {
string unit_of_measurement = 11;
NumberMode mode = 12;
string device_class = 13;
uint32 device_id = 14;
}
message NumberStateResponse {
option (id) = 50;
@@ -1039,6 +1066,7 @@ message ListEntitiesSelectResponse {
repeated string options = 6;
bool disabled_by_default = 7;
EntityCategory entity_category = 8;
uint32 device_id = 9;
}
message SelectStateResponse {
option (id) = 53;
@@ -1081,6 +1109,7 @@ message ListEntitiesSirenResponse {
bool supports_duration = 8;
bool supports_volume = 9;
EntityCategory entity_category = 10;
uint32 device_id = 11;
}
message SirenStateResponse {
option (id) = 56;
@@ -1144,6 +1173,7 @@ message ListEntitiesLockResponse {
// Not yet implemented:
string code_format = 11;
uint32 device_id = 12;
}
message LockStateResponse {
option (id) = 59;
@@ -1183,6 +1213,7 @@ message ListEntitiesButtonResponse {
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
string device_class = 8;
uint32 device_id = 9;
}
message ButtonCommandRequest {
option (id) = 62;
@@ -1238,6 +1269,8 @@ message ListEntitiesMediaPlayerResponse {
bool supports_pause = 8;
repeated MediaPlayerSupportedFormat supported_formats = 9;
uint32 device_id = 10;
}
message MediaPlayerStateResponse {
option (id) = 64;
@@ -1778,6 +1811,7 @@ message ListEntitiesAlarmControlPanelResponse {
uint32 supported_features = 8;
bool requires_code = 9;
bool requires_code_to_arm = 10;
uint32 device_id = 11;
}
message AlarmControlPanelStateResponse {
@@ -1823,6 +1857,7 @@ message ListEntitiesTextResponse {
uint32 max_length = 9;
string pattern = 10;
TextMode mode = 11;
uint32 device_id = 12;
}
message TextStateResponse {
option (id) = 98;
@@ -1863,6 +1898,7 @@ message ListEntitiesDateResponse {
string icon = 5;
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
uint32 device_id = 8;
}
message DateStateResponse {
option (id) = 101;
@@ -1906,6 +1942,7 @@ message ListEntitiesTimeResponse {
string icon = 5;
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
uint32 device_id = 8;
}
message TimeStateResponse {
option (id) = 104;
@@ -1952,6 +1989,7 @@ message ListEntitiesEventResponse {
string device_class = 8;
repeated string event_types = 9;
uint32 device_id = 10;
}
message EventResponse {
option (id) = 108;
@@ -1983,6 +2021,7 @@ message ListEntitiesValveResponse {
bool assumed_state = 9;
bool supports_position = 10;
bool supports_stop = 11;
uint32 device_id = 12;
}
enum ValveOperation {
@@ -2029,6 +2068,7 @@ message ListEntitiesDateTimeResponse {
string icon = 5;
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
uint32 device_id = 8;
}
message DateTimeStateResponse {
option (id) = 113;
@@ -2069,6 +2109,7 @@ message ListEntitiesUpdateResponse {
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
string device_class = 8;
uint32 device_id = 9;
}
message UpdateStateResponse {
option (id) = 117;

View File

@@ -1621,6 +1621,23 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
#endif
#ifdef USE_API_NOISE
resp.api_encryption_supported = true;
#endif
#ifdef USE_DEVICES
for (auto const &device : App.get_devices()) {
DeviceInfo device_info;
device_info.device_id = device->get_device_id();
device_info.name = device->get_name();
device_info.area_id = device->get_area_id();
resp.devices.push_back(device_info);
}
#endif
#ifdef USE_AREAS
for (auto const &area : App.get_areas()) {
AreaInfo area_info;
area_info.area_id = area->get_area_id();
area_info.name = area->get_name();
resp.areas.push_back(area_info);
}
#endif
return resp;
}

View File

@@ -301,6 +301,9 @@ class APIConnection : public APIServerConnection {
response.icon = entity->get_icon();
response.disabled_by_default = entity->is_disabled_by_default();
response.entity_category = static_cast<enums::EntityCategory>(entity->get_entity_category());
#ifdef USE_DEVICES
response.device_id = entity->get_device_id();
#endif
}
// Helper function to fill common entity state fields

View File

@@ -812,6 +812,103 @@ void PingResponse::dump_to(std::string &out) const { out.append("PingResponse {}
#ifdef HAS_PROTO_MESSAGE_DUMP
void DeviceInfoRequest::dump_to(std::string &out) const { out.append("DeviceInfoRequest {}"); }
#endif
bool AreaInfo::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 1: {
this->area_id = value.as_uint32();
return true;
}
default:
return false;
}
}
bool AreaInfo::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) {
case 2: {
this->name = value.as_string();
return true;
}
default:
return false;
}
}
void AreaInfo::encode(ProtoWriteBuffer buffer) const {
buffer.encode_uint32(1, this->area_id);
buffer.encode_string(2, this->name);
}
void AreaInfo::calculate_size(uint32_t &total_size) const {
ProtoSize::add_uint32_field(total_size, 1, this->area_id, false);
ProtoSize::add_string_field(total_size, 1, this->name, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void AreaInfo::dump_to(std::string &out) const {
__attribute__((unused)) char buffer[64];
out.append("AreaInfo {\n");
out.append(" area_id: ");
sprintf(buffer, "%" PRIu32, this->area_id);
out.append(buffer);
out.append("\n");
out.append(" name: ");
out.append("'").append(this->name).append("'");
out.append("\n");
out.append("}");
}
#endif
bool DeviceInfo::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 1: {
this->device_id = value.as_uint32();
return true;
}
case 3: {
this->area_id = value.as_uint32();
return true;
}
default:
return false;
}
}
bool DeviceInfo::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) {
case 2: {
this->name = value.as_string();
return true;
}
default:
return false;
}
}
void DeviceInfo::encode(ProtoWriteBuffer buffer) const {
buffer.encode_uint32(1, this->device_id);
buffer.encode_string(2, this->name);
buffer.encode_uint32(3, this->area_id);
}
void DeviceInfo::calculate_size(uint32_t &total_size) const {
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
ProtoSize::add_string_field(total_size, 1, this->name, false);
ProtoSize::add_uint32_field(total_size, 1, this->area_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void DeviceInfo::dump_to(std::string &out) const {
__attribute__((unused)) char buffer[64];
out.append("DeviceInfo {\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append(" name: ");
out.append("'").append(this->name).append("'");
out.append("\n");
out.append(" area_id: ");
sprintf(buffer, "%" PRIu32, this->area_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
bool DeviceInfoResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
switch (field_id) {
case 1: {
@@ -896,6 +993,18 @@ bool DeviceInfoResponse::decode_length(uint32_t field_id, ProtoLengthDelimited v
this->bluetooth_mac_address = value.as_string();
return true;
}
case 20: {
this->devices.push_back(value.as_message<DeviceInfo>());
return true;
}
case 21: {
this->areas.push_back(value.as_message<AreaInfo>());
return true;
}
case 22: {
this->area = value.as_message<AreaInfo>();
return true;
}
default:
return false;
}
@@ -920,6 +1029,13 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(16, this->suggested_area);
buffer.encode_string(18, this->bluetooth_mac_address);
buffer.encode_bool(19, this->api_encryption_supported);
for (auto &it : this->devices) {
buffer.encode_message<DeviceInfo>(20, it, true);
}
for (auto &it : this->areas) {
buffer.encode_message<AreaInfo>(21, it, true);
}
buffer.encode_message<AreaInfo>(22, this->area);
}
void DeviceInfoResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_bool_field(total_size, 1, this->uses_password, false);
@@ -941,6 +1057,9 @@ void DeviceInfoResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 2, this->suggested_area, false);
ProtoSize::add_string_field(total_size, 2, this->bluetooth_mac_address, false);
ProtoSize::add_bool_field(total_size, 2, this->api_encryption_supported, false);
ProtoSize::add_repeated_message(total_size, 2, this->devices);
ProtoSize::add_repeated_message(total_size, 2, this->areas);
ProtoSize::add_message_object(total_size, 2, this->area, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void DeviceInfoResponse::dump_to(std::string &out) const {
@@ -1026,6 +1145,22 @@ void DeviceInfoResponse::dump_to(std::string &out) const {
out.append(" api_encryption_supported: ");
out.append(YESNO(this->api_encryption_supported));
out.append("\n");
for (const auto &it : this->devices) {
out.append(" devices: ");
it.dump_to(out);
out.append("\n");
}
for (const auto &it : this->areas) {
out.append(" areas: ");
it.dump_to(out);
out.append("\n");
}
out.append(" area: ");
this->area.dump_to(out);
out.append("\n");
out.append("}");
}
#endif
@@ -1052,6 +1187,10 @@ bool ListEntitiesBinarySensorResponse::decode_varint(uint32_t field_id, ProtoVar
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 10: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -1102,6 +1241,7 @@ void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_bool(7, this->disabled_by_default);
buffer.encode_string(8, this->icon);
buffer.encode_enum<enums::EntityCategory>(9, this->entity_category);
buffer.encode_uint32(10, this->device_id);
}
void ListEntitiesBinarySensorResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -1113,6 +1253,7 @@ void ListEntitiesBinarySensorResponse::calculate_size(uint32_t &total_size) cons
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
ProtoSize::add_string_field(total_size, 1, this->icon, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const {
@@ -1154,6 +1295,11 @@ void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const {
out.append(" entity_category: ");
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -1236,6 +1382,10 @@ bool ListEntitiesCoverResponse::decode_varint(uint32_t field_id, ProtoVarInt val
this->supports_stop = value.as_bool();
return true;
}
case 13: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -1289,6 +1439,7 @@ void ListEntitiesCoverResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(10, this->icon);
buffer.encode_enum<enums::EntityCategory>(11, this->entity_category);
buffer.encode_bool(12, this->supports_stop);
buffer.encode_uint32(13, this->device_id);
}
void ListEntitiesCoverResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -1303,6 +1454,7 @@ void ListEntitiesCoverResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->icon, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_bool_field(total_size, 1, this->supports_stop, false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesCoverResponse::dump_to(std::string &out) const {
@@ -1356,6 +1508,11 @@ void ListEntitiesCoverResponse::dump_to(std::string &out) const {
out.append(" supports_stop: ");
out.append(YESNO(this->supports_stop));
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -1565,6 +1722,10 @@ bool ListEntitiesFanResponse::decode_varint(uint32_t field_id, ProtoVarInt value
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 13: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -1620,6 +1781,7 @@ void ListEntitiesFanResponse::encode(ProtoWriteBuffer buffer) const {
for (auto &it : this->supported_preset_modes) {
buffer.encode_string(12, it, true);
}
buffer.encode_uint32(13, this->device_id);
}
void ListEntitiesFanResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -1638,6 +1800,7 @@ void ListEntitiesFanResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, it, true);
}
}
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesFanResponse::dump_to(std::string &out) const {
@@ -1694,6 +1857,11 @@ void ListEntitiesFanResponse::dump_to(std::string &out) const {
out.append("'").append(it).append("'");
out.append("\n");
}
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -1987,6 +2155,10 @@ bool ListEntitiesLightResponse::decode_varint(uint32_t field_id, ProtoVarInt val
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 16: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -2055,6 +2227,7 @@ void ListEntitiesLightResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_bool(13, this->disabled_by_default);
buffer.encode_string(14, this->icon);
buffer.encode_enum<enums::EntityCategory>(15, this->entity_category);
buffer.encode_uint32(16, this->device_id);
}
void ListEntitiesLightResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -2080,6 +2253,7 @@ void ListEntitiesLightResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
ProtoSize::add_string_field(total_size, 1, this->icon, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_uint32_field(total_size, 2, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesLightResponse::dump_to(std::string &out) const {
@@ -2151,6 +2325,11 @@ void ListEntitiesLightResponse::dump_to(std::string &out) const {
out.append(" entity_category: ");
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -2658,6 +2837,10 @@ bool ListEntitiesSensorResponse::decode_varint(uint32_t field_id, ProtoVarInt va
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 14: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -2716,6 +2899,7 @@ void ListEntitiesSensorResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_enum<enums::SensorLastResetType>(11, this->legacy_last_reset_type);
buffer.encode_bool(12, this->disabled_by_default);
buffer.encode_enum<enums::EntityCategory>(13, this->entity_category);
buffer.encode_uint32(14, this->device_id);
}
void ListEntitiesSensorResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -2731,6 +2915,7 @@ void ListEntitiesSensorResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->legacy_last_reset_type), false);
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesSensorResponse::dump_to(std::string &out) const {
@@ -2789,6 +2974,11 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const {
out.append(" entity_category: ");
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -2860,6 +3050,10 @@ bool ListEntitiesSwitchResponse::decode_varint(uint32_t field_id, ProtoVarInt va
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 10: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -2910,6 +3104,7 @@ void ListEntitiesSwitchResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_bool(7, this->disabled_by_default);
buffer.encode_enum<enums::EntityCategory>(8, this->entity_category);
buffer.encode_string(9, this->device_class);
buffer.encode_uint32(10, this->device_id);
}
void ListEntitiesSwitchResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -2921,6 +3116,7 @@ void ListEntitiesSwitchResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_string_field(total_size, 1, this->device_class, false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesSwitchResponse::dump_to(std::string &out) const {
@@ -2962,6 +3158,11 @@ void ListEntitiesSwitchResponse::dump_to(std::string &out) const {
out.append(" device_class: ");
out.append("'").append(this->device_class).append("'");
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -3061,6 +3262,10 @@ bool ListEntitiesTextSensorResponse::decode_varint(uint32_t field_id, ProtoVarIn
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 9: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -3110,6 +3315,7 @@ void ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_bool(6, this->disabled_by_default);
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
buffer.encode_string(8, this->device_class);
buffer.encode_uint32(9, this->device_id);
}
void ListEntitiesTextSensorResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -3120,6 +3326,7 @@ void ListEntitiesTextSensorResponse::calculate_size(uint32_t &total_size) const
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_string_field(total_size, 1, this->device_class, false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesTextSensorResponse::dump_to(std::string &out) const {
@@ -3157,6 +3364,11 @@ void ListEntitiesTextSensorResponse::dump_to(std::string &out) const {
out.append(" device_class: ");
out.append("'").append(this->device_class).append("'");
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -3922,6 +4134,10 @@ bool ListEntitiesCameraResponse::decode_varint(uint32_t field_id, ProtoVarInt va
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 8: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -3966,6 +4182,7 @@ void ListEntitiesCameraResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_bool(5, this->disabled_by_default);
buffer.encode_string(6, this->icon);
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
buffer.encode_uint32(8, this->device_id);
}
void ListEntitiesCameraResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -3975,6 +4192,7 @@ void ListEntitiesCameraResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
ProtoSize::add_string_field(total_size, 1, this->icon, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesCameraResponse::dump_to(std::string &out) const {
@@ -4008,6 +4226,11 @@ void ListEntitiesCameraResponse::dump_to(std::string &out) const {
out.append(" entity_category: ");
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -4156,6 +4379,10 @@ bool ListEntitiesClimateResponse::decode_varint(uint32_t field_id, ProtoVarInt v
this->supports_target_humidity = value.as_bool();
return true;
}
case 26: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -4262,6 +4489,7 @@ void ListEntitiesClimateResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_bool(23, this->supports_target_humidity);
buffer.encode_float(24, this->visual_min_humidity);
buffer.encode_float(25, this->visual_max_humidity);
buffer.encode_uint32(26, this->device_id);
}
void ListEntitiesClimateResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -4313,6 +4541,7 @@ void ListEntitiesClimateResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_bool_field(total_size, 2, this->supports_target_humidity, false);
ProtoSize::add_fixed_field<4>(total_size, 2, this->visual_min_humidity != 0.0f, false);
ProtoSize::add_fixed_field<4>(total_size, 2, this->visual_max_humidity != 0.0f, false);
ProtoSize::add_uint32_field(total_size, 2, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesClimateResponse::dump_to(std::string &out) const {
@@ -4436,6 +4665,11 @@ void ListEntitiesClimateResponse::dump_to(std::string &out) const {
sprintf(buffer, "%g", this->visual_max_humidity);
out.append(buffer);
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -4901,6 +5135,10 @@ bool ListEntitiesNumberResponse::decode_varint(uint32_t field_id, ProtoVarInt va
this->mode = value.as_enum<enums::NumberMode>();
return true;
}
case 14: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -4971,6 +5209,7 @@ void ListEntitiesNumberResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(11, this->unit_of_measurement);
buffer.encode_enum<enums::NumberMode>(12, this->mode);
buffer.encode_string(13, this->device_class);
buffer.encode_uint32(14, this->device_id);
}
void ListEntitiesNumberResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -4986,6 +5225,7 @@ void ListEntitiesNumberResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->unit_of_measurement, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->mode), false);
ProtoSize::add_string_field(total_size, 1, this->device_class, false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesNumberResponse::dump_to(std::string &out) const {
@@ -5046,6 +5286,11 @@ void ListEntitiesNumberResponse::dump_to(std::string &out) const {
out.append(" device_class: ");
out.append("'").append(this->device_class).append("'");
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -5151,6 +5396,10 @@ bool ListEntitiesSelectResponse::decode_varint(uint32_t field_id, ProtoVarInt va
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 9: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -5202,6 +5451,7 @@ void ListEntitiesSelectResponse::encode(ProtoWriteBuffer buffer) const {
}
buffer.encode_bool(7, this->disabled_by_default);
buffer.encode_enum<enums::EntityCategory>(8, this->entity_category);
buffer.encode_uint32(9, this->device_id);
}
void ListEntitiesSelectResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -5216,6 +5466,7 @@ void ListEntitiesSelectResponse::calculate_size(uint32_t &total_size) const {
}
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesSelectResponse::dump_to(std::string &out) const {
@@ -5255,6 +5506,11 @@ void ListEntitiesSelectResponse::dump_to(std::string &out) const {
out.append(" entity_category: ");
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -5378,6 +5634,10 @@ bool ListEntitiesSirenResponse::decode_varint(uint32_t field_id, ProtoVarInt val
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 11: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -5431,6 +5691,7 @@ void ListEntitiesSirenResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_bool(8, this->supports_duration);
buffer.encode_bool(9, this->supports_volume);
buffer.encode_enum<enums::EntityCategory>(10, this->entity_category);
buffer.encode_uint32(11, this->device_id);
}
void ListEntitiesSirenResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -5447,6 +5708,7 @@ void ListEntitiesSirenResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_bool_field(total_size, 1, this->supports_duration, false);
ProtoSize::add_bool_field(total_size, 1, this->supports_volume, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesSirenResponse::dump_to(std::string &out) const {
@@ -5494,6 +5756,11 @@ void ListEntitiesSirenResponse::dump_to(std::string &out) const {
out.append(" entity_category: ");
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -5683,6 +5950,10 @@ bool ListEntitiesLockResponse::decode_varint(uint32_t field_id, ProtoVarInt valu
this->requires_code = value.as_bool();
return true;
}
case 12: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -5735,6 +6006,7 @@ void ListEntitiesLockResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_bool(9, this->supports_open);
buffer.encode_bool(10, this->requires_code);
buffer.encode_string(11, this->code_format);
buffer.encode_uint32(12, this->device_id);
}
void ListEntitiesLockResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -5748,6 +6020,7 @@ void ListEntitiesLockResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_bool_field(total_size, 1, this->supports_open, false);
ProtoSize::add_bool_field(total_size, 1, this->requires_code, false);
ProtoSize::add_string_field(total_size, 1, this->code_format, false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesLockResponse::dump_to(std::string &out) const {
@@ -5797,6 +6070,11 @@ void ListEntitiesLockResponse::dump_to(std::string &out) const {
out.append(" code_format: ");
out.append("'").append(this->code_format).append("'");
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -5922,6 +6200,10 @@ bool ListEntitiesButtonResponse::decode_varint(uint32_t field_id, ProtoVarInt va
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 9: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -5971,6 +6253,7 @@ void ListEntitiesButtonResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_bool(6, this->disabled_by_default);
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
buffer.encode_string(8, this->device_class);
buffer.encode_uint32(9, this->device_id);
}
void ListEntitiesButtonResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -5981,6 +6264,7 @@ void ListEntitiesButtonResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_string_field(total_size, 1, this->device_class, false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesButtonResponse::dump_to(std::string &out) const {
@@ -6018,6 +6302,11 @@ void ListEntitiesButtonResponse::dump_to(std::string &out) const {
out.append(" device_class: ");
out.append("'").append(this->device_class).append("'");
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -6135,6 +6424,10 @@ bool ListEntitiesMediaPlayerResponse::decode_varint(uint32_t field_id, ProtoVarI
this->supports_pause = value.as_bool();
return true;
}
case 10: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -6187,6 +6480,7 @@ void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer buffer) const {
for (auto &it : this->supported_formats) {
buffer.encode_message<MediaPlayerSupportedFormat>(9, it, true);
}
buffer.encode_uint32(10, this->device_id);
}
void ListEntitiesMediaPlayerResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -6198,6 +6492,7 @@ void ListEntitiesMediaPlayerResponse::calculate_size(uint32_t &total_size) const
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_bool_field(total_size, 1, this->supports_pause, false);
ProtoSize::add_repeated_message(total_size, 1, this->supported_formats);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const {
@@ -6241,6 +6536,11 @@ void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const {
it.dump_to(out);
out.append("\n");
}
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -8551,6 +8851,10 @@ bool ListEntitiesAlarmControlPanelResponse::decode_varint(uint32_t field_id, Pro
this->requires_code_to_arm = value.as_bool();
return true;
}
case 11: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -8598,6 +8902,7 @@ void ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer buffer) cons
buffer.encode_uint32(8, this->supported_features);
buffer.encode_bool(9, this->requires_code);
buffer.encode_bool(10, this->requires_code_to_arm);
buffer.encode_uint32(11, this->device_id);
}
void ListEntitiesAlarmControlPanelResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -8610,6 +8915,7 @@ void ListEntitiesAlarmControlPanelResponse::calculate_size(uint32_t &total_size)
ProtoSize::add_uint32_field(total_size, 1, this->supported_features, false);
ProtoSize::add_bool_field(total_size, 1, this->requires_code, false);
ProtoSize::add_bool_field(total_size, 1, this->requires_code_to_arm, false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const {
@@ -8656,6 +8962,11 @@ void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const {
out.append(" requires_code_to_arm: ");
out.append(YESNO(this->requires_code_to_arm));
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -8783,6 +9094,10 @@ bool ListEntitiesTextResponse::decode_varint(uint32_t field_id, ProtoVarInt valu
this->mode = value.as_enum<enums::TextMode>();
return true;
}
case 12: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -8835,6 +9150,7 @@ void ListEntitiesTextResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_uint32(9, this->max_length);
buffer.encode_string(10, this->pattern);
buffer.encode_enum<enums::TextMode>(11, this->mode);
buffer.encode_uint32(12, this->device_id);
}
void ListEntitiesTextResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -8848,6 +9164,7 @@ void ListEntitiesTextResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_uint32_field(total_size, 1, this->max_length, false);
ProtoSize::add_string_field(total_size, 1, this->pattern, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->mode), false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesTextResponse::dump_to(std::string &out) const {
@@ -8899,6 +9216,11 @@ void ListEntitiesTextResponse::dump_to(std::string &out) const {
out.append(" mode: ");
out.append(proto_enum_to_string<enums::TextMode>(this->mode));
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -9014,6 +9336,10 @@ bool ListEntitiesDateResponse::decode_varint(uint32_t field_id, ProtoVarInt valu
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 8: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -9058,6 +9384,7 @@ void ListEntitiesDateResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(5, this->icon);
buffer.encode_bool(6, this->disabled_by_default);
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
buffer.encode_uint32(8, this->device_id);
}
void ListEntitiesDateResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -9067,6 +9394,7 @@ void ListEntitiesDateResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->icon, false);
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesDateResponse::dump_to(std::string &out) const {
@@ -9100,6 +9428,11 @@ void ListEntitiesDateResponse::dump_to(std::string &out) const {
out.append(" entity_category: ");
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -9255,6 +9588,10 @@ bool ListEntitiesTimeResponse::decode_varint(uint32_t field_id, ProtoVarInt valu
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 8: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -9299,6 +9636,7 @@ void ListEntitiesTimeResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(5, this->icon);
buffer.encode_bool(6, this->disabled_by_default);
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
buffer.encode_uint32(8, this->device_id);
}
void ListEntitiesTimeResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -9308,6 +9646,7 @@ void ListEntitiesTimeResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->icon, false);
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesTimeResponse::dump_to(std::string &out) const {
@@ -9341,6 +9680,11 @@ void ListEntitiesTimeResponse::dump_to(std::string &out) const {
out.append(" entity_category: ");
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -9496,6 +9840,10 @@ bool ListEntitiesEventResponse::decode_varint(uint32_t field_id, ProtoVarInt val
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 10: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -9552,6 +9900,7 @@ void ListEntitiesEventResponse::encode(ProtoWriteBuffer buffer) const {
for (auto &it : this->event_types) {
buffer.encode_string(9, it, true);
}
buffer.encode_uint32(10, this->device_id);
}
void ListEntitiesEventResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -9567,6 +9916,7 @@ void ListEntitiesEventResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, it, true);
}
}
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesEventResponse::dump_to(std::string &out) const {
@@ -9610,6 +9960,11 @@ void ListEntitiesEventResponse::dump_to(std::string &out) const {
out.append("'").append(it).append("'");
out.append("\n");
}
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -9678,6 +10033,10 @@ bool ListEntitiesValveResponse::decode_varint(uint32_t field_id, ProtoVarInt val
this->supports_stop = value.as_bool();
return true;
}
case 12: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -9730,6 +10089,7 @@ void ListEntitiesValveResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_bool(9, this->assumed_state);
buffer.encode_bool(10, this->supports_position);
buffer.encode_bool(11, this->supports_stop);
buffer.encode_uint32(12, this->device_id);
}
void ListEntitiesValveResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -9743,6 +10103,7 @@ void ListEntitiesValveResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_bool_field(total_size, 1, this->assumed_state, false);
ProtoSize::add_bool_field(total_size, 1, this->supports_position, false);
ProtoSize::add_bool_field(total_size, 1, this->supports_stop, false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesValveResponse::dump_to(std::string &out) const {
@@ -9792,6 +10153,11 @@ void ListEntitiesValveResponse::dump_to(std::string &out) const {
out.append(" supports_stop: ");
out.append(YESNO(this->supports_stop));
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -9923,6 +10289,10 @@ bool ListEntitiesDateTimeResponse::decode_varint(uint32_t field_id, ProtoVarInt
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 8: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -9967,6 +10337,7 @@ void ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_string(5, this->icon);
buffer.encode_bool(6, this->disabled_by_default);
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
buffer.encode_uint32(8, this->device_id);
}
void ListEntitiesDateTimeResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -9976,6 +10347,7 @@ void ListEntitiesDateTimeResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->icon, false);
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesDateTimeResponse::dump_to(std::string &out) const {
@@ -10009,6 +10381,11 @@ void ListEntitiesDateTimeResponse::dump_to(std::string &out) const {
out.append(" entity_category: ");
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif
@@ -10114,6 +10491,10 @@ bool ListEntitiesUpdateResponse::decode_varint(uint32_t field_id, ProtoVarInt va
this->entity_category = value.as_enum<enums::EntityCategory>();
return true;
}
case 9: {
this->device_id = value.as_uint32();
return true;
}
default:
return false;
}
@@ -10163,6 +10544,7 @@ void ListEntitiesUpdateResponse::encode(ProtoWriteBuffer buffer) const {
buffer.encode_bool(6, this->disabled_by_default);
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
buffer.encode_string(8, this->device_class);
buffer.encode_uint32(9, this->device_id);
}
void ListEntitiesUpdateResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
@@ -10173,6 +10555,7 @@ void ListEntitiesUpdateResponse::calculate_size(uint32_t &total_size) const {
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
ProtoSize::add_string_field(total_size, 1, this->device_class, false);
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void ListEntitiesUpdateResponse::dump_to(std::string &out) const {
@@ -10210,6 +10593,11 @@ void ListEntitiesUpdateResponse::dump_to(std::string &out) const {
out.append(" device_class: ");
out.append("'").append(this->device_class).append("'");
out.append("\n");
out.append(" device_id: ");
sprintf(buffer, "%" PRIu32, this->device_id);
out.append(buffer);
out.append("\n");
out.append("}");
}
#endif

View File

@@ -264,6 +264,7 @@ class InfoResponseProtoMessage : public ProtoMessage {
bool disabled_by_default{false};
std::string icon{};
enums::EntityCategory entity_category{};
uint32_t device_id{0};
protected:
};
@@ -415,10 +416,39 @@ class DeviceInfoRequest : public ProtoMessage {
protected:
};
class AreaInfo : public ProtoMessage {
public:
uint32_t area_id{0};
std::string name{};
void encode(ProtoWriteBuffer buffer) const override;
void calculate_size(uint32_t &total_size) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class DeviceInfo : public ProtoMessage {
public:
uint32_t device_id{0};
std::string name{};
uint32_t area_id{0};
void encode(ProtoWriteBuffer buffer) const override;
void calculate_size(uint32_t &total_size) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override;
#endif
protected:
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
class DeviceInfoResponse : public ProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 10;
static constexpr uint16_t ESTIMATED_SIZE = 129;
static constexpr uint16_t ESTIMATED_SIZE = 219;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "device_info_response"; }
#endif
@@ -441,6 +471,9 @@ class DeviceInfoResponse : public ProtoMessage {
std::string suggested_area{};
std::string bluetooth_mac_address{};
bool api_encryption_supported{false};
std::vector<DeviceInfo> devices{};
std::vector<AreaInfo> areas{};
AreaInfo area{};
void encode(ProtoWriteBuffer buffer) const override;
void calculate_size(uint32_t &total_size) const override;
#ifdef HAS_PROTO_MESSAGE_DUMP
@@ -493,7 +526,7 @@ class SubscribeStatesRequest : public ProtoMessage {
class ListEntitiesBinarySensorResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 12;
static constexpr uint16_t ESTIMATED_SIZE = 56;
static constexpr uint16_t ESTIMATED_SIZE = 60;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_binary_sensor_response"; }
#endif
@@ -532,7 +565,7 @@ class BinarySensorStateResponse : public StateResponseProtoMessage {
class ListEntitiesCoverResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 13;
static constexpr uint16_t ESTIMATED_SIZE = 62;
static constexpr uint16_t ESTIMATED_SIZE = 66;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_cover_response"; }
#endif
@@ -601,7 +634,7 @@ class CoverCommandRequest : public ProtoMessage {
class ListEntitiesFanResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 14;
static constexpr uint16_t ESTIMATED_SIZE = 73;
static constexpr uint16_t ESTIMATED_SIZE = 77;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_fan_response"; }
#endif
@@ -679,7 +712,7 @@ class FanCommandRequest : public ProtoMessage {
class ListEntitiesLightResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 15;
static constexpr uint16_t ESTIMATED_SIZE = 85;
static constexpr uint16_t ESTIMATED_SIZE = 90;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_light_response"; }
#endif
@@ -780,7 +813,7 @@ class LightCommandRequest : public ProtoMessage {
class ListEntitiesSensorResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 16;
static constexpr uint16_t ESTIMATED_SIZE = 73;
static constexpr uint16_t ESTIMATED_SIZE = 77;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_sensor_response"; }
#endif
@@ -823,7 +856,7 @@ class SensorStateResponse : public StateResponseProtoMessage {
class ListEntitiesSwitchResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 17;
static constexpr uint16_t ESTIMATED_SIZE = 56;
static constexpr uint16_t ESTIMATED_SIZE = 60;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_switch_response"; }
#endif
@@ -880,7 +913,7 @@ class SwitchCommandRequest : public ProtoMessage {
class ListEntitiesTextSensorResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 18;
static constexpr uint16_t ESTIMATED_SIZE = 54;
static constexpr uint16_t ESTIMATED_SIZE = 58;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_text_sensor_response"; }
#endif
@@ -1196,7 +1229,7 @@ class ExecuteServiceRequest : public ProtoMessage {
class ListEntitiesCameraResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 43;
static constexpr uint16_t ESTIMATED_SIZE = 45;
static constexpr uint16_t ESTIMATED_SIZE = 49;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_camera_response"; }
#endif
@@ -1253,7 +1286,7 @@ class CameraImageRequest : public ProtoMessage {
class ListEntitiesClimateResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 46;
static constexpr uint16_t ESTIMATED_SIZE = 151;
static constexpr uint16_t ESTIMATED_SIZE = 156;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_climate_response"; }
#endif
@@ -1362,7 +1395,7 @@ class ClimateCommandRequest : public ProtoMessage {
class ListEntitiesNumberResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 49;
static constexpr uint16_t ESTIMATED_SIZE = 80;
static constexpr uint16_t ESTIMATED_SIZE = 84;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_number_response"; }
#endif
@@ -1423,7 +1456,7 @@ class NumberCommandRequest : public ProtoMessage {
class ListEntitiesSelectResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 52;
static constexpr uint16_t ESTIMATED_SIZE = 63;
static constexpr uint16_t ESTIMATED_SIZE = 67;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_select_response"; }
#endif
@@ -1481,7 +1514,7 @@ class SelectCommandRequest : public ProtoMessage {
class ListEntitiesSirenResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 55;
static constexpr uint16_t ESTIMATED_SIZE = 67;
static constexpr uint16_t ESTIMATED_SIZE = 71;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_siren_response"; }
#endif
@@ -1547,7 +1580,7 @@ class SirenCommandRequest : public ProtoMessage {
class ListEntitiesLockResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 58;
static constexpr uint16_t ESTIMATED_SIZE = 60;
static constexpr uint16_t ESTIMATED_SIZE = 64;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_lock_response"; }
#endif
@@ -1609,7 +1642,7 @@ class LockCommandRequest : public ProtoMessage {
class ListEntitiesButtonResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 61;
static constexpr uint16_t ESTIMATED_SIZE = 54;
static constexpr uint16_t ESTIMATED_SIZE = 58;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_button_response"; }
#endif
@@ -1662,7 +1695,7 @@ class MediaPlayerSupportedFormat : public ProtoMessage {
class ListEntitiesMediaPlayerResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 63;
static constexpr uint16_t ESTIMATED_SIZE = 81;
static constexpr uint16_t ESTIMATED_SIZE = 85;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_media_player_response"; }
#endif
@@ -2532,7 +2565,7 @@ class VoiceAssistantSetConfiguration : public ProtoMessage {
class ListEntitiesAlarmControlPanelResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 94;
static constexpr uint16_t ESTIMATED_SIZE = 53;
static constexpr uint16_t ESTIMATED_SIZE = 57;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_alarm_control_panel_response"; }
#endif
@@ -2592,7 +2625,7 @@ class AlarmControlPanelCommandRequest : public ProtoMessage {
class ListEntitiesTextResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 97;
static constexpr uint16_t ESTIMATED_SIZE = 64;
static constexpr uint16_t ESTIMATED_SIZE = 68;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_text_response"; }
#endif
@@ -2653,7 +2686,7 @@ class TextCommandRequest : public ProtoMessage {
class ListEntitiesDateResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 100;
static constexpr uint16_t ESTIMATED_SIZE = 45;
static constexpr uint16_t ESTIMATED_SIZE = 49;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_date_response"; }
#endif
@@ -2713,7 +2746,7 @@ class DateCommandRequest : public ProtoMessage {
class ListEntitiesTimeResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 103;
static constexpr uint16_t ESTIMATED_SIZE = 45;
static constexpr uint16_t ESTIMATED_SIZE = 49;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_time_response"; }
#endif
@@ -2773,7 +2806,7 @@ class TimeCommandRequest : public ProtoMessage {
class ListEntitiesEventResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 107;
static constexpr uint16_t ESTIMATED_SIZE = 72;
static constexpr uint16_t ESTIMATED_SIZE = 76;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_event_response"; }
#endif
@@ -2811,7 +2844,7 @@ class EventResponse : public StateResponseProtoMessage {
class ListEntitiesValveResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 109;
static constexpr uint16_t ESTIMATED_SIZE = 60;
static constexpr uint16_t ESTIMATED_SIZE = 64;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_valve_response"; }
#endif
@@ -2873,7 +2906,7 @@ class ValveCommandRequest : public ProtoMessage {
class ListEntitiesDateTimeResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 112;
static constexpr uint16_t ESTIMATED_SIZE = 45;
static constexpr uint16_t ESTIMATED_SIZE = 49;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_date_time_response"; }
#endif
@@ -2928,7 +2961,7 @@ class DateTimeCommandRequest : public ProtoMessage {
class ListEntitiesUpdateResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 116;
static constexpr uint16_t ESTIMATED_SIZE = 54;
static constexpr uint16_t ESTIMATED_SIZE = 58;
#ifdef HAS_PROTO_MESSAGE_DUMP
static constexpr const char *message_name() { return "list_entities_update_response"; }
#endif

View File

@@ -1,5 +1,7 @@
"""Helpers for config validation using voluptuous."""
from __future__ import annotations
from contextlib import contextmanager
from dataclasses import dataclass
from datetime import datetime
@@ -29,6 +31,7 @@ from esphome.const import (
CONF_COMMAND_RETAIN,
CONF_COMMAND_TOPIC,
CONF_DAY,
CONF_DEVICE_ID,
CONF_DISABLED_BY_DEFAULT,
CONF_DISCOVERY,
CONF_ENTITY_CATEGORY,
@@ -355,6 +358,13 @@ def icon(value):
)
def sub_device_id(value: str | None) -> core.ID:
# Lazy import to avoid circular imports
from esphome.core.config import Device
return use_id(Device)(value)
def boolean(value):
"""Validate the given config option to be a boolean.
@@ -1896,6 +1906,7 @@ ENTITY_BASE_SCHEMA = Schema(
Optional(CONF_DISABLED_BY_DEFAULT, default=False): boolean,
Optional(CONF_ICON): icon,
Optional(CONF_ENTITY_CATEGORY): entity_category,
Optional(CONF_DEVICE_ID): sub_device_id,
}
)
@@ -1964,7 +1975,7 @@ class Version:
return f"{self.major}.{self.minor}.{self.patch}"
@classmethod
def parse(cls, value: str) -> "Version":
def parse(cls, value: str) -> Version:
match = re.match(r"^(\d+).(\d+).(\d+)-?\w*$", value)
if match is None:
raise ValueError(f"Not a valid version number {value}")

View File

@@ -56,6 +56,8 @@ CONF_AP = "ap"
CONF_APPARENT_POWER = "apparent_power"
CONF_ARDUINO_VERSION = "arduino_version"
CONF_AREA = "area"
CONF_AREA_ID = "area_id"
CONF_AREAS = "areas"
CONF_ARGS = "args"
CONF_ASSUMED_STATE = "assumed_state"
CONF_AT = "at"
@@ -217,6 +219,7 @@ CONF_DEST = "dest"
CONF_DEVICE = "device"
CONF_DEVICE_CLASS = "device_class"
CONF_DEVICE_FACTOR = "device_factor"
CONF_DEVICE_ID = "device_id"
CONF_DEVICES = "devices"
CONF_DIELECTRIC_CONSTANT = "dielectric_constant"
CONF_DIMENSIONS = "dimensions"

View File

@@ -10,6 +10,13 @@
#include "esphome/core/runtime_stats.h"
#include "esphome/core/scheduler.h"
#ifdef USE_DEVICES
#include "esphome/core/device.h"
#endif
#ifdef USE_AREAS
#include "esphome/core/area.h"
#endif
#ifdef USE_SOCKET_SELECT_SUPPORT
#include <sys/select.h>
#endif
@@ -88,7 +95,7 @@ static const uint32_t TEARDOWN_TIMEOUT_REBOOT_MS = 1000; // 1 second for quick
class Application {
public:
void pre_setup(const std::string &name, const std::string &friendly_name, const char *area, const char *comment,
void pre_setup(const std::string &name, const std::string &friendly_name, const char *comment,
const char *compilation_time, bool name_add_mac_suffix) {
arch_init();
this->name_add_mac_suffix_ = name_add_mac_suffix;
@@ -103,11 +110,18 @@ class Application {
this->name_ = name;
this->friendly_name_ = friendly_name;
}
this->area_ = area;
// area is now handled through the areas system
this->comment_ = comment;
this->compilation_time_ = compilation_time;
}
#ifdef USE_DEVICES
void register_device(Device *device) { this->devices_.push_back(device); }
#endif
#ifdef USE_AREAS
void register_area(Area *area) { this->areas_.push_back(area); }
#endif
void set_current_component(Component *component) { this->current_component_ = component; }
Component *get_current_component() { return this->current_component_; }
@@ -265,6 +279,12 @@ class Application {
#ifdef USE_UPDATE
void reserve_update(size_t count) { this->updates_.reserve(count); }
#endif
#ifdef USE_AREAS
void reserve_area(size_t count) { this->areas_.reserve(count); }
#endif
#ifdef USE_DEVICES
void reserve_device(size_t count) { this->devices_.reserve(count); }
#endif
/// Register the component in this Application instance.
template<class C> C *register_component(C *c) {
@@ -286,7 +306,15 @@ class Application {
const std::string &get_friendly_name() const { return this->friendly_name_; }
/// Get the area of this Application set by pre_setup().
std::string get_area() const { return this->area_ == nullptr ? "" : this->area_; }
const char *get_area() const {
#ifdef USE_AREAS
// If we have areas registered, return the name of the first one (which is the top-level area)
if (!this->areas_.empty() && this->areas_[0] != nullptr) {
return this->areas_[0]->get_name();
}
#endif
return "";
}
/// Get the comment of this Application set by pre_setup().
std::string get_comment() const { return this->comment_; }
@@ -347,6 +375,12 @@ class Application {
uint8_t get_app_state() const { return this->app_state_; }
#ifdef USE_DEVICES
const std::vector<Device *> &get_devices() { return this->devices_; }
#endif
#ifdef USE_AREAS
const std::vector<Area *> &get_areas() { return this->areas_; }
#endif
#ifdef USE_BINARY_SENSOR
const std::vector<binary_sensor::BinarySensor *> &get_binary_sensors() { return this->binary_sensors_; }
binary_sensor::BinarySensor *get_binary_sensor_by_key(uint32_t key, bool include_internal = false) {
@@ -623,6 +657,12 @@ class Application {
uint16_t current_loop_index_{0};
bool in_loop_{false};
#ifdef USE_DEVICES
std::vector<Device *> devices_{};
#endif
#ifdef USE_AREAS
std::vector<Area *> areas_{};
#endif
#ifdef USE_BINARY_SENSOR
std::vector<binary_sensor::BinarySensor *> binary_sensors_{};
#endif
@@ -689,7 +729,6 @@ class Application {
std::string name_;
std::string friendly_name_;
const char *area_{nullptr};
const char *comment_{nullptr};
const char *compilation_time_{nullptr};
bool name_add_mac_suffix_;

19
esphome/core/area.h Normal file
View File

@@ -0,0 +1,19 @@
#pragma once
#include <cstdint>
namespace esphome {
class Area {
public:
void set_area_id(uint32_t area_id) { this->area_id_ = area_id; }
uint32_t get_area_id() { return this->area_id_; }
void set_name(const char *name) { this->name_ = name; }
const char *get_name() { return this->name_; }
protected:
uint32_t area_id_{};
const char *name_ = "";
};
} // namespace esphome

View File

@@ -1,18 +1,24 @@
from __future__ import annotations
import logging
import os
from pathlib import Path
from esphome import automation
from esphome import automation, core
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.const import (
CONF_AREA,
CONF_AREA_ID,
CONF_AREAS,
CONF_BUILD_PATH,
CONF_COMMENT,
CONF_COMPILE_PROCESS_LIMIT,
CONF_DEBUG_SCHEDULER,
CONF_DEVICES,
CONF_ESPHOME,
CONF_FRIENDLY_NAME,
CONF_ID,
CONF_INCLUDES,
CONF_LIBRARIES,
CONF_MIN_VERSION,
@@ -32,7 +38,13 @@ from esphome.const import (
__version__ as ESPHOME_VERSION,
)
from esphome.core import CORE, coroutine_with_priority
from esphome.helpers import copy_file_if_changed, get_str_env, walk_files
from esphome.helpers import (
copy_file_if_changed,
fnv1a_32bit_hash,
get_str_env,
walk_files,
)
from esphome.types import ConfigType
_LOGGER = logging.getLogger(__name__)
@@ -48,7 +60,8 @@ LoopTrigger = cg.esphome_ns.class_(
ProjectUpdateTrigger = cg.esphome_ns.class_(
"ProjectUpdateTrigger", cg.Component, automation.Trigger.template(cg.std_string)
)
Device = cg.esphome_ns.class_("Device")
Area = cg.esphome_ns.class_("Area")
VALID_INCLUDE_EXTS = {".h", ".hpp", ".tcc", ".ino", ".cpp", ".c"}
@@ -71,6 +84,56 @@ def validate_hostname(config):
return config
def validate_ids_and_references(config: ConfigType) -> ConfigType:
"""Validate that there are no hash collisions between IDs and that area_id references are valid.
This validation is critical because we use 32-bit hashes for performance on microcontrollers.
By detecting collisions at compile time, we prevent any runtime issues while maintaining
optimal performance on 32-bit platforms. In practice, with typical deployments having only
a handful of areas and devices, hash collisions are virtually impossible.
"""
# Helper to check hash collisions
def check_hash_collision(
id_obj: core.ID,
hash_dict: dict[int, str],
item_type: str,
path: list[str | int],
) -> None:
hash_val: int = fnv1a_32bit_hash(id_obj.id)
if hash_val in hash_dict and hash_dict[hash_val] != id_obj.id:
raise cv.Invalid(
f"{item_type} ID '{id_obj.id}' with hash {hash_val} collides with "
f"existing {item_type.lower()} ID '{hash_dict[hash_val]}'",
path=path,
)
hash_dict[hash_val] = id_obj.id
# Collect all areas
all_areas: list[dict[str, str | core.ID]] = []
if CONF_AREA in config:
all_areas.append(config[CONF_AREA])
all_areas.extend(config[CONF_AREAS])
# Validate area hash collisions and collect IDs
area_hashes: dict[int, str] = {}
area_ids: set[str] = set()
for area in all_areas:
area_id: core.ID = area[CONF_ID]
check_hash_collision(area_id, area_hashes, "Area", [CONF_AREAS, area_id.id])
area_ids.add(area_id.id)
# Validate device hash collisions and area references
device_hashes: dict[int, str] = {}
for device in config[CONF_DEVICES]:
device_id: core.ID = device[CONF_ID]
check_hash_collision(
device_id, device_hashes, "Device", [CONF_DEVICES, device_id.id]
)
return config
def valid_include(value):
# Look for "<...>" includes
if value.startswith("<") and value.endswith(">"):
@@ -111,13 +174,32 @@ if "ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT" in os.environ:
else:
_compile_process_limit_default = cv.UNDEFINED
AREA_SCHEMA = cv.Schema(
{
cv.GenerateID(CONF_ID): cv.declare_id(Area),
cv.Required(CONF_NAME): cv.string,
}
)
DEVICE_SCHEMA = cv.Schema(
{
cv.GenerateID(CONF_ID): cv.declare_id(Device),
cv.Required(CONF_NAME): cv.string,
cv.Optional(CONF_AREA_ID): cv.use_id(Area),
}
)
def validate_area_config(config: dict | str) -> dict[str, str | core.ID]:
return cv.maybe_simple_value(AREA_SCHEMA, key=CONF_NAME)(config)
CONFIG_SCHEMA = cv.All(
cv.Schema(
{
cv.Required(CONF_NAME): cv.valid_name,
cv.Optional(CONF_FRIENDLY_NAME, ""): cv.string,
cv.Optional(CONF_AREA, ""): cv.string,
cv.Optional(CONF_AREA): validate_area_config,
cv.Optional(CONF_COMMENT): cv.string,
cv.Required(CONF_BUILD_PATH): cv.string,
cv.Optional(CONF_PLATFORMIO_OPTIONS, default={}): cv.Schema(
@@ -167,11 +249,17 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(
CONF_COMPILE_PROCESS_LIMIT, default=_compile_process_limit_default
): cv.int_range(min=1, max=get_usable_cpu_count()),
cv.Optional(CONF_AREAS, default=[]): cv.ensure_list(AREA_SCHEMA),
cv.Optional(CONF_DEVICES, default=[]): cv.ensure_list(DEVICE_SCHEMA),
}
),
validate_hostname,
)
FINAL_VALIDATE_SCHEMA = cv.All(validate_ids_and_references)
PRELOAD_CONFIG_SCHEMA = cv.Schema(
{
cv.Required(CONF_NAME): cv.valid_name,
@@ -336,7 +424,7 @@ async def _add_platform_reserves() -> None:
@coroutine_with_priority(100.0)
async def to_code(config):
async def to_code(config: ConfigType) -> None:
cg.add_global(cg.global_ns.namespace("esphome").using)
# These can be used by user lambdas, put them to default scope
cg.add_global(cg.RawExpression("using std::isnan"))
@@ -347,7 +435,6 @@ async def to_code(config):
cg.App.pre_setup(
config[CONF_NAME],
config[CONF_FRIENDLY_NAME],
config[CONF_AREA],
config.get(CONF_COMMENT, ""),
cg.RawExpression('__DATE__ ", " __TIME__'),
config[CONF_NAME_ADD_MAC_SUFFIX],
@@ -417,3 +504,50 @@ async def to_code(config):
if config[CONF_PLATFORMIO_OPTIONS]:
CORE.add_job(_add_platformio_options, config[CONF_PLATFORMIO_OPTIONS])
# Process areas
all_areas: list[dict[str, str | core.ID]] = []
if CONF_AREA in config:
all_areas.append(config[CONF_AREA])
all_areas.extend(config[CONF_AREAS])
if all_areas:
cg.add(cg.RawStatement(f"App.reserve_area({len(all_areas)});"))
cg.add_define("USE_AREAS")
for area_conf in all_areas:
area_id: core.ID = area_conf[CONF_ID]
area_id_hash: int = fnv1a_32bit_hash(area_id.id)
area_name: str = area_conf[CONF_NAME]
area_var = cg.new_Pvariable(area_id)
cg.add(area_var.set_area_id(area_id_hash))
cg.add(area_var.set_name(area_name))
cg.add(cg.App.register_area(area_var))
# Process devices
devices: list[dict[str, str | core.ID]] = config[CONF_DEVICES]
if not devices:
return
# Reserve space for devices
cg.add(cg.RawStatement(f"App.reserve_device({len(devices)});"))
cg.add_define("USE_DEVICES")
# Process each device
for dev_conf in devices:
device_id: core.ID = dev_conf[CONF_ID]
device_id_hash = fnv1a_32bit_hash(device_id.id)
device_name: str = dev_conf[CONF_NAME]
dev = cg.new_Pvariable(device_id)
cg.add(dev.set_device_id(device_id_hash))
cg.add(dev.set_name(device_name))
# Set area if specified
if CONF_AREA_ID in dev_conf:
area_id: core.ID = dev_conf[CONF_AREA_ID]
area_id_hash = fnv1a_32bit_hash(area_id.id)
cg.add(dev.set_area_id(area_id_hash))
cg.add(cg.App.register_device(dev))

View File

@@ -20,6 +20,7 @@
// Feature flags
#define USE_ALARM_CONTROL_PANEL
#define USE_AREAS
#define USE_BINARY_SENSOR
#define USE_BUTTON
#define USE_CLIMATE
@@ -29,6 +30,7 @@
#define USE_DATETIME_DATETIME
#define USE_DATETIME_TIME
#define USE_DEEP_SLEEP
#define USE_DEVICES
#define USE_DISPLAY
#define USE_ESP32_IMPROV_STATE_CALLBACK
#define USE_EVENT

20
esphome/core/device.h Normal file
View File

@@ -0,0 +1,20 @@
#pragma once
namespace esphome {
class Device {
public:
void set_device_id(uint32_t device_id) { this->device_id_ = device_id; }
uint32_t get_device_id() { return this->device_id_; }
void set_name(const char *name) { this->name_ = name; }
const char *get_name() { return this->name_; }
void set_area_id(uint32_t area_id) { this->area_id_ = area_id; }
uint32_t get_area_id() { return this->area_id_; }
protected:
uint32_t device_id_{};
uint32_t area_id_{};
const char *name_ = "";
};
} // namespace esphome

View File

@@ -51,6 +51,12 @@ class EntityBase {
std::string get_icon() const;
void set_icon(const char *icon);
#ifdef USE_DEVICES
// Get/set this entity's device id
uint32_t get_device_id() const { return this->device_id_; }
void set_device_id(const uint32_t device_id) { this->device_id_ = device_id; }
#endif
// Check if this entity has state
bool has_state() const { return this->flags_.has_state; }
@@ -67,6 +73,9 @@ class EntityBase {
const char *object_id_c_str_{nullptr};
const char *icon_c_str_{nullptr};
uint32_t object_id_hash_{};
#ifdef USE_DEVICES
uint32_t device_id_{};
#endif
// Bit-packed flags to save memory (1 byte instead of 5)
struct EntityFlags {

View File

@@ -1,6 +1,7 @@
import logging
from esphome.const import (
CONF_DEVICE_ID,
CONF_DISABLED_BY_DEFAULT,
CONF_ENTITY_CATEGORY,
CONF_ICON,
@@ -16,7 +17,7 @@ from esphome.core import CORE, ID, coroutine
from esphome.coroutine import FakeAwaitable
from esphome.cpp_generator import add, get_variable
from esphome.cpp_types import App
from esphome.helpers import sanitize, snake_case
from esphome.helpers import fnv1a_32bit_hash, sanitize, snake_case
from esphome.types import ConfigFragmentType, ConfigType
from esphome.util import Registry, RegistryEntry
@@ -110,6 +111,9 @@ async def setup_entity(var, config):
add(var.set_icon(config[CONF_ICON]))
if CONF_ENTITY_CATEGORY in config:
add(var.set_entity_category(config[CONF_ENTITY_CATEGORY]))
if CONF_DEVICE_ID in config:
device_id: ID = config[CONF_DEVICE_ID]
add(var.set_device_id(fnv1a_32bit_hash(device_id.id)))
def extract_registry_entry_config(

View File

@@ -1,25 +1,9 @@
from __future__ import annotations
import unicodedata
from esphome.const import ALLOWED_NAME_CHARS
from esphome.helpers import slugify
def strip_accents(value):
return "".join(
c
for c in unicodedata.normalize("NFD", str(value))
if unicodedata.category(c) != "Mn"
)
def friendly_name_slugify(value):
value = (
strip_accents(value)
.lower()
.replace(" ", "-")
.replace("_", "-")
.replace("--", "-")
.strip("-")
)
return "".join(c for c in value if c in ALLOWED_NAME_CHARS)
def friendly_name_slugify(value: str) -> str:
"""Convert a friendly name to a slug with dashes instead of underscores."""
# First use the standard slugify, then convert underscores to dashes
return slugify(value).replace("_", "-")

View File

@@ -29,6 +29,53 @@ def ensure_unique_string(preferred_string, current_strings):
return test_string
def fnv1a_32bit_hash(string: str) -> int:
"""FNV-1a 32-bit hash function.
Note: This uses 32-bit hash instead of 64-bit for several reasons:
1. ESPHome targets 32-bit microcontrollers with limited RAM (often <320KB)
2. Using 64-bit hashes would double the RAM usage for storing IDs
3. 64-bit operations are slower on 32-bit processors
While there's a ~50% collision probability at ~77,000 unique IDs,
ESPHome validates for collisions at compile time, preventing any
runtime issues. In practice, most ESPHome installations only have
a handful of area_ids and device_ids (typically <10 areas and <100
devices), making collisions virtually impossible.
"""
hash_value = 2166136261
for char in string:
hash_value ^= ord(char)
hash_value = (hash_value * 16777619) & 0xFFFFFFFF
return hash_value
def strip_accents(value: str) -> str:
"""Remove accents from a string."""
import unicodedata
return "".join(
c
for c in unicodedata.normalize("NFD", str(value))
if unicodedata.category(c) != "Mn"
)
def slugify(value: str) -> str:
"""Convert a string to a valid C++ identifier slug."""
from esphome.const import ALLOWED_NAME_CHARS
value = (
strip_accents(value)
.lower()
.replace(" ", "_")
.replace("-", "_")
.replace("__", "_")
.strip("_")
)
return "".join(c for c in value if c in ALLOWED_NAME_CHARS)
def indent_all_but_first_and_last(text, padding=" "):
lines = text.splitlines(True)
if len(lines) <= 2: