mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Merge branch 'multi_device' into integration
This commit is contained in:
		| @@ -188,6 +188,17 @@ message DeviceInfoRequest { | |||||||
|   // Empty |   // 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 { | message DeviceInfoResponse { | ||||||
|   option (id) = 10; |   option (id) = 10; | ||||||
|   option (source) = SOURCE_SERVER; |   option (source) = SOURCE_SERVER; | ||||||
| @@ -236,6 +247,12 @@ message DeviceInfoResponse { | |||||||
|  |  | ||||||
|   // Supports receiving and saving api encryption key |   // Supports receiving and saving api encryption key | ||||||
|   bool api_encryption_supported = 19; |   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 { | message ListEntitiesRequest { | ||||||
| @@ -280,6 +297,7 @@ message ListEntitiesBinarySensorResponse { | |||||||
|   bool disabled_by_default = 7; |   bool disabled_by_default = 7; | ||||||
|   string icon = 8; |   string icon = 8; | ||||||
|   EntityCategory entity_category = 9; |   EntityCategory entity_category = 9; | ||||||
|  |   uint32 device_id = 10; | ||||||
| } | } | ||||||
| message BinarySensorStateResponse { | message BinarySensorStateResponse { | ||||||
|   option (id) = 21; |   option (id) = 21; | ||||||
| @@ -315,6 +333,7 @@ message ListEntitiesCoverResponse { | |||||||
|   string icon = 10; |   string icon = 10; | ||||||
|   EntityCategory entity_category = 11; |   EntityCategory entity_category = 11; | ||||||
|   bool supports_stop = 12; |   bool supports_stop = 12; | ||||||
|  |   uint32 device_id = 13; | ||||||
| } | } | ||||||
|  |  | ||||||
| enum LegacyCoverState { | enum LegacyCoverState { | ||||||
| @@ -388,6 +407,7 @@ message ListEntitiesFanResponse { | |||||||
|   string icon = 10; |   string icon = 10; | ||||||
|   EntityCategory entity_category = 11; |   EntityCategory entity_category = 11; | ||||||
|   repeated string supported_preset_modes = 12; |   repeated string supported_preset_modes = 12; | ||||||
|  |   uint32 device_id = 13; | ||||||
| } | } | ||||||
| enum FanSpeed { | enum FanSpeed { | ||||||
|   FAN_SPEED_LOW = 0; |   FAN_SPEED_LOW = 0; | ||||||
| @@ -471,6 +491,7 @@ message ListEntitiesLightResponse { | |||||||
|   bool disabled_by_default = 13; |   bool disabled_by_default = 13; | ||||||
|   string icon = 14; |   string icon = 14; | ||||||
|   EntityCategory entity_category = 15; |   EntityCategory entity_category = 15; | ||||||
|  |   uint32 device_id = 16; | ||||||
| } | } | ||||||
| message LightStateResponse { | message LightStateResponse { | ||||||
|   option (id) = 24; |   option (id) = 24; | ||||||
| @@ -563,6 +584,7 @@ message ListEntitiesSensorResponse { | |||||||
|   SensorLastResetType legacy_last_reset_type = 11; |   SensorLastResetType legacy_last_reset_type = 11; | ||||||
|   bool disabled_by_default = 12; |   bool disabled_by_default = 12; | ||||||
|   EntityCategory entity_category = 13; |   EntityCategory entity_category = 13; | ||||||
|  |   uint32 device_id = 14; | ||||||
| } | } | ||||||
| message SensorStateResponse { | message SensorStateResponse { | ||||||
|   option (id) = 25; |   option (id) = 25; | ||||||
| @@ -595,6 +617,7 @@ message ListEntitiesSwitchResponse { | |||||||
|   bool disabled_by_default = 7; |   bool disabled_by_default = 7; | ||||||
|   EntityCategory entity_category = 8; |   EntityCategory entity_category = 8; | ||||||
|   string device_class = 9; |   string device_class = 9; | ||||||
|  |   uint32 device_id = 10; | ||||||
| } | } | ||||||
| message SwitchStateResponse { | message SwitchStateResponse { | ||||||
|   option (id) = 26; |   option (id) = 26; | ||||||
| @@ -632,6 +655,7 @@ message ListEntitiesTextSensorResponse { | |||||||
|   bool disabled_by_default = 6; |   bool disabled_by_default = 6; | ||||||
|   EntityCategory entity_category = 7; |   EntityCategory entity_category = 7; | ||||||
|   string device_class = 8; |   string device_class = 8; | ||||||
|  |   uint32 device_id = 9; | ||||||
| } | } | ||||||
| message TextSensorStateResponse { | message TextSensorStateResponse { | ||||||
|   option (id) = 27; |   option (id) = 27; | ||||||
| @@ -814,6 +838,7 @@ message ListEntitiesCameraResponse { | |||||||
|   bool disabled_by_default = 5; |   bool disabled_by_default = 5; | ||||||
|   string icon = 6; |   string icon = 6; | ||||||
|   EntityCategory entity_category = 7; |   EntityCategory entity_category = 7; | ||||||
|  |   uint32 device_id = 8; | ||||||
| } | } | ||||||
|  |  | ||||||
| message CameraImageResponse { | message CameraImageResponse { | ||||||
| @@ -916,6 +941,7 @@ message ListEntitiesClimateResponse { | |||||||
|   bool supports_target_humidity = 23; |   bool supports_target_humidity = 23; | ||||||
|   float visual_min_humidity = 24; |   float visual_min_humidity = 24; | ||||||
|   float visual_max_humidity = 25; |   float visual_max_humidity = 25; | ||||||
|  |   uint32 device_id = 26; | ||||||
| } | } | ||||||
| message ClimateStateResponse { | message ClimateStateResponse { | ||||||
|   option (id) = 47; |   option (id) = 47; | ||||||
| @@ -999,6 +1025,7 @@ message ListEntitiesNumberResponse { | |||||||
|   string unit_of_measurement = 11; |   string unit_of_measurement = 11; | ||||||
|   NumberMode mode = 12; |   NumberMode mode = 12; | ||||||
|   string device_class = 13; |   string device_class = 13; | ||||||
|  |   uint32 device_id = 14; | ||||||
| } | } | ||||||
| message NumberStateResponse { | message NumberStateResponse { | ||||||
|   option (id) = 50; |   option (id) = 50; | ||||||
| @@ -1039,6 +1066,7 @@ message ListEntitiesSelectResponse { | |||||||
|   repeated string options = 6; |   repeated string options = 6; | ||||||
|   bool disabled_by_default = 7; |   bool disabled_by_default = 7; | ||||||
|   EntityCategory entity_category = 8; |   EntityCategory entity_category = 8; | ||||||
|  |   uint32 device_id = 9; | ||||||
| } | } | ||||||
| message SelectStateResponse { | message SelectStateResponse { | ||||||
|   option (id) = 53; |   option (id) = 53; | ||||||
| @@ -1081,6 +1109,7 @@ message ListEntitiesSirenResponse { | |||||||
|   bool supports_duration = 8; |   bool supports_duration = 8; | ||||||
|   bool supports_volume = 9; |   bool supports_volume = 9; | ||||||
|   EntityCategory entity_category = 10; |   EntityCategory entity_category = 10; | ||||||
|  |   uint32 device_id = 11; | ||||||
| } | } | ||||||
| message SirenStateResponse { | message SirenStateResponse { | ||||||
|   option (id) = 56; |   option (id) = 56; | ||||||
| @@ -1144,6 +1173,7 @@ message ListEntitiesLockResponse { | |||||||
|  |  | ||||||
|   // Not yet implemented: |   // Not yet implemented: | ||||||
|   string code_format = 11; |   string code_format = 11; | ||||||
|  |   uint32 device_id = 12; | ||||||
| } | } | ||||||
| message LockStateResponse { | message LockStateResponse { | ||||||
|   option (id) = 59; |   option (id) = 59; | ||||||
| @@ -1183,6 +1213,7 @@ message ListEntitiesButtonResponse { | |||||||
|   bool disabled_by_default = 6; |   bool disabled_by_default = 6; | ||||||
|   EntityCategory entity_category = 7; |   EntityCategory entity_category = 7; | ||||||
|   string device_class = 8; |   string device_class = 8; | ||||||
|  |   uint32 device_id = 9; | ||||||
| } | } | ||||||
| message ButtonCommandRequest { | message ButtonCommandRequest { | ||||||
|   option (id) = 62; |   option (id) = 62; | ||||||
| @@ -1238,6 +1269,8 @@ message ListEntitiesMediaPlayerResponse { | |||||||
|   bool supports_pause = 8; |   bool supports_pause = 8; | ||||||
|  |  | ||||||
|   repeated MediaPlayerSupportedFormat supported_formats = 9; |   repeated MediaPlayerSupportedFormat supported_formats = 9; | ||||||
|  |  | ||||||
|  |   uint32 device_id = 10; | ||||||
| } | } | ||||||
| message MediaPlayerStateResponse { | message MediaPlayerStateResponse { | ||||||
|   option (id) = 64; |   option (id) = 64; | ||||||
| @@ -1778,6 +1811,7 @@ message ListEntitiesAlarmControlPanelResponse { | |||||||
|   uint32 supported_features = 8; |   uint32 supported_features = 8; | ||||||
|   bool requires_code = 9; |   bool requires_code = 9; | ||||||
|   bool requires_code_to_arm = 10; |   bool requires_code_to_arm = 10; | ||||||
|  |   uint32 device_id = 11; | ||||||
| } | } | ||||||
|  |  | ||||||
| message AlarmControlPanelStateResponse { | message AlarmControlPanelStateResponse { | ||||||
| @@ -1823,6 +1857,7 @@ message ListEntitiesTextResponse { | |||||||
|   uint32 max_length = 9; |   uint32 max_length = 9; | ||||||
|   string pattern = 10; |   string pattern = 10; | ||||||
|   TextMode mode = 11; |   TextMode mode = 11; | ||||||
|  |   uint32 device_id = 12; | ||||||
| } | } | ||||||
| message TextStateResponse { | message TextStateResponse { | ||||||
|   option (id) = 98; |   option (id) = 98; | ||||||
| @@ -1863,6 +1898,7 @@ message ListEntitiesDateResponse { | |||||||
|   string icon = 5; |   string icon = 5; | ||||||
|   bool disabled_by_default = 6; |   bool disabled_by_default = 6; | ||||||
|   EntityCategory entity_category = 7; |   EntityCategory entity_category = 7; | ||||||
|  |   uint32 device_id = 8; | ||||||
| } | } | ||||||
| message DateStateResponse { | message DateStateResponse { | ||||||
|   option (id) = 101; |   option (id) = 101; | ||||||
| @@ -1906,6 +1942,7 @@ message ListEntitiesTimeResponse { | |||||||
|   string icon = 5; |   string icon = 5; | ||||||
|   bool disabled_by_default = 6; |   bool disabled_by_default = 6; | ||||||
|   EntityCategory entity_category = 7; |   EntityCategory entity_category = 7; | ||||||
|  |   uint32 device_id = 8; | ||||||
| } | } | ||||||
| message TimeStateResponse { | message TimeStateResponse { | ||||||
|   option (id) = 104; |   option (id) = 104; | ||||||
| @@ -1952,6 +1989,7 @@ message ListEntitiesEventResponse { | |||||||
|   string device_class = 8; |   string device_class = 8; | ||||||
|  |  | ||||||
|   repeated string event_types = 9; |   repeated string event_types = 9; | ||||||
|  |   uint32 device_id = 10; | ||||||
| } | } | ||||||
| message EventResponse { | message EventResponse { | ||||||
|   option (id) = 108; |   option (id) = 108; | ||||||
| @@ -1983,6 +2021,7 @@ message ListEntitiesValveResponse { | |||||||
|   bool assumed_state = 9; |   bool assumed_state = 9; | ||||||
|   bool supports_position = 10; |   bool supports_position = 10; | ||||||
|   bool supports_stop = 11; |   bool supports_stop = 11; | ||||||
|  |   uint32 device_id = 12; | ||||||
| } | } | ||||||
|  |  | ||||||
| enum ValveOperation { | enum ValveOperation { | ||||||
| @@ -2029,6 +2068,7 @@ message ListEntitiesDateTimeResponse { | |||||||
|   string icon = 5; |   string icon = 5; | ||||||
|   bool disabled_by_default = 6; |   bool disabled_by_default = 6; | ||||||
|   EntityCategory entity_category = 7; |   EntityCategory entity_category = 7; | ||||||
|  |   uint32 device_id = 8; | ||||||
| } | } | ||||||
| message DateTimeStateResponse { | message DateTimeStateResponse { | ||||||
|   option (id) = 113; |   option (id) = 113; | ||||||
| @@ -2069,6 +2109,7 @@ message ListEntitiesUpdateResponse { | |||||||
|   bool disabled_by_default = 6; |   bool disabled_by_default = 6; | ||||||
|   EntityCategory entity_category = 7; |   EntityCategory entity_category = 7; | ||||||
|   string device_class = 8; |   string device_class = 8; | ||||||
|  |   uint32 device_id = 9; | ||||||
| } | } | ||||||
| message UpdateStateResponse { | message UpdateStateResponse { | ||||||
|   option (id) = 117; |   option (id) = 117; | ||||||
|   | |||||||
| @@ -1621,6 +1621,23 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) { | |||||||
| #endif | #endif | ||||||
| #ifdef USE_API_NOISE | #ifdef USE_API_NOISE | ||||||
|   resp.api_encryption_supported = true; |   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 | #endif | ||||||
|   return resp; |   return resp; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -301,6 +301,9 @@ class APIConnection : public APIServerConnection { | |||||||
|     response.icon = entity->get_icon(); |     response.icon = entity->get_icon(); | ||||||
|     response.disabled_by_default = entity->is_disabled_by_default(); |     response.disabled_by_default = entity->is_disabled_by_default(); | ||||||
|     response.entity_category = static_cast<enums::EntityCategory>(entity->get_entity_category()); |     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 |   // Helper function to fill common entity state fields | ||||||
|   | |||||||
| @@ -812,6 +812,103 @@ void PingResponse::dump_to(std::string &out) const { out.append("PingResponse {} | |||||||
| #ifdef HAS_PROTO_MESSAGE_DUMP | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void DeviceInfoRequest::dump_to(std::string &out) const { out.append("DeviceInfoRequest {}"); } | void DeviceInfoRequest::dump_to(std::string &out) const { out.append("DeviceInfoRequest {}"); } | ||||||
| #endif | #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) { | bool DeviceInfoResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { | ||||||
|   switch (field_id) { |   switch (field_id) { | ||||||
|     case 1: { |     case 1: { | ||||||
| @@ -896,6 +993,18 @@ bool DeviceInfoResponse::decode_length(uint32_t field_id, ProtoLengthDelimited v | |||||||
|       this->bluetooth_mac_address = value.as_string(); |       this->bluetooth_mac_address = value.as_string(); | ||||||
|       return true; |       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: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -920,6 +1029,13 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_string(16, this->suggested_area); |   buffer.encode_string(16, this->suggested_area); | ||||||
|   buffer.encode_string(18, this->bluetooth_mac_address); |   buffer.encode_string(18, this->bluetooth_mac_address); | ||||||
|   buffer.encode_bool(19, this->api_encryption_supported); |   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 { | void DeviceInfoResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_bool_field(total_size, 1, this->uses_password, false); |   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->suggested_area, false); | ||||||
|   ProtoSize::add_string_field(total_size, 2, this->bluetooth_mac_address, 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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void DeviceInfoResponse::dump_to(std::string &out) const { | 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("  api_encryption_supported: "); | ||||||
|   out.append(YESNO(this->api_encryption_supported)); |   out.append(YESNO(this->api_encryption_supported)); | ||||||
|   out.append("\n"); |   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("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -1052,6 +1187,10 @@ bool ListEntitiesBinarySensorResponse::decode_varint(uint32_t field_id, ProtoVar | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 10: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -1102,6 +1241,7 @@ void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_bool(7, this->disabled_by_default); |   buffer.encode_bool(7, this->disabled_by_default); | ||||||
|   buffer.encode_string(8, this->icon); |   buffer.encode_string(8, this->icon); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(9, this->entity_category); |   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 { | void ListEntitiesBinarySensorResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_bool_field(total_size, 1, this->disabled_by_default, false); | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->icon, 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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const { | 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("  entity_category: "); | ||||||
|   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); |   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -1236,6 +1382,10 @@ bool ListEntitiesCoverResponse::decode_varint(uint32_t field_id, ProtoVarInt val | |||||||
|       this->supports_stop = value.as_bool(); |       this->supports_stop = value.as_bool(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 13: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -1289,6 +1439,7 @@ void ListEntitiesCoverResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_string(10, this->icon); |   buffer.encode_string(10, this->icon); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(11, this->entity_category); |   buffer.encode_enum<enums::EntityCategory>(11, this->entity_category); | ||||||
|   buffer.encode_bool(12, this->supports_stop); |   buffer.encode_bool(12, this->supports_stop); | ||||||
|  |   buffer.encode_uint32(13, this->device_id); | ||||||
| } | } | ||||||
| void ListEntitiesCoverResponse::calculate_size(uint32_t &total_size) const { | void ListEntitiesCoverResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_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_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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesCoverResponse::dump_to(std::string &out) const { | 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("  supports_stop: "); | ||||||
|   out.append(YESNO(this->supports_stop)); |   out.append(YESNO(this->supports_stop)); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -1565,6 +1722,10 @@ bool ListEntitiesFanResponse::decode_varint(uint32_t field_id, ProtoVarInt value | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 13: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -1620,6 +1781,7 @@ void ListEntitiesFanResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   for (auto &it : this->supported_preset_modes) { |   for (auto &it : this->supported_preset_modes) { | ||||||
|     buffer.encode_string(12, it, true); |     buffer.encode_string(12, it, true); | ||||||
|   } |   } | ||||||
|  |   buffer.encode_uint32(13, this->device_id); | ||||||
| } | } | ||||||
| void ListEntitiesFanResponse::calculate_size(uint32_t &total_size) const { | void ListEntitiesFanResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_string_field(total_size, 1, it, true); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |   ProtoSize::add_uint32_field(total_size, 1, this->device_id, false); | ||||||
| } | } | ||||||
| #ifdef HAS_PROTO_MESSAGE_DUMP | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesFanResponse::dump_to(std::string &out) const { | 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("'").append(it).append("'"); | ||||||
|     out.append("\n"); |     out.append("\n"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -1987,6 +2155,10 @@ bool ListEntitiesLightResponse::decode_varint(uint32_t field_id, ProtoVarInt val | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 16: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -2055,6 +2227,7 @@ void ListEntitiesLightResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_bool(13, this->disabled_by_default); |   buffer.encode_bool(13, this->disabled_by_default); | ||||||
|   buffer.encode_string(14, this->icon); |   buffer.encode_string(14, this->icon); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(15, this->entity_category); |   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 { | void ListEntitiesLightResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_bool_field(total_size, 1, this->disabled_by_default, false); | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->icon, 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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesLightResponse::dump_to(std::string &out) const { | 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("  entity_category: "); | ||||||
|   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); |   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -2658,6 +2837,10 @@ bool ListEntitiesSensorResponse::decode_varint(uint32_t field_id, ProtoVarInt va | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 14: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       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_enum<enums::SensorLastResetType>(11, this->legacy_last_reset_type); | ||||||
|   buffer.encode_bool(12, this->disabled_by_default); |   buffer.encode_bool(12, this->disabled_by_default); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(13, this->entity_category); |   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 { | void ListEntitiesSensorResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_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_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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesSensorResponse::dump_to(std::string &out) const { | 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("  entity_category: "); | ||||||
|   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); |   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -2860,6 +3050,10 @@ bool ListEntitiesSwitchResponse::decode_varint(uint32_t field_id, ProtoVarInt va | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 10: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -2910,6 +3104,7 @@ void ListEntitiesSwitchResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_bool(7, this->disabled_by_default); |   buffer.encode_bool(7, this->disabled_by_default); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(8, this->entity_category); |   buffer.encode_enum<enums::EntityCategory>(8, this->entity_category); | ||||||
|   buffer.encode_string(9, this->device_class); |   buffer.encode_string(9, this->device_class); | ||||||
|  |   buffer.encode_uint32(10, this->device_id); | ||||||
| } | } | ||||||
| void ListEntitiesSwitchResponse::calculate_size(uint32_t &total_size) const { | void ListEntitiesSwitchResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_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_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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesSwitchResponse::dump_to(std::string &out) const { | 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("  device_class: "); | ||||||
|   out.append("'").append(this->device_class).append("'"); |   out.append("'").append(this->device_class).append("'"); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -3061,6 +3262,10 @@ bool ListEntitiesTextSensorResponse::decode_varint(uint32_t field_id, ProtoVarIn | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 9: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -3110,6 +3315,7 @@ void ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_bool(6, this->disabled_by_default); |   buffer.encode_bool(6, this->disabled_by_default); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(7, this->entity_category); |   buffer.encode_enum<enums::EntityCategory>(7, this->entity_category); | ||||||
|   buffer.encode_string(8, this->device_class); |   buffer.encode_string(8, this->device_class); | ||||||
|  |   buffer.encode_uint32(9, this->device_id); | ||||||
| } | } | ||||||
| void ListEntitiesTextSensorResponse::calculate_size(uint32_t &total_size) const { | void ListEntitiesTextSensorResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_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_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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesTextSensorResponse::dump_to(std::string &out) const { | 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("  device_class: "); | ||||||
|   out.append("'").append(this->device_class).append("'"); |   out.append("'").append(this->device_class).append("'"); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -3922,6 +4134,10 @@ bool ListEntitiesCameraResponse::decode_varint(uint32_t field_id, ProtoVarInt va | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 8: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -3966,6 +4182,7 @@ void ListEntitiesCameraResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_bool(5, this->disabled_by_default); |   buffer.encode_bool(5, this->disabled_by_default); | ||||||
|   buffer.encode_string(6, this->icon); |   buffer.encode_string(6, this->icon); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(7, this->entity_category); |   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 { | void ListEntitiesCameraResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_bool_field(total_size, 1, this->disabled_by_default, false); | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->icon, 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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesCameraResponse::dump_to(std::string &out) const { | 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("  entity_category: "); | ||||||
|   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); |   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -4156,6 +4379,10 @@ bool ListEntitiesClimateResponse::decode_varint(uint32_t field_id, ProtoVarInt v | |||||||
|       this->supports_target_humidity = value.as_bool(); |       this->supports_target_humidity = value.as_bool(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 26: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -4262,6 +4489,7 @@ void ListEntitiesClimateResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_bool(23, this->supports_target_humidity); |   buffer.encode_bool(23, this->supports_target_humidity); | ||||||
|   buffer.encode_float(24, this->visual_min_humidity); |   buffer.encode_float(24, this->visual_min_humidity); | ||||||
|   buffer.encode_float(25, this->visual_max_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 { | void ListEntitiesClimateResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_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_min_humidity != 0.0f, false); | ||||||
|   ProtoSize::add_fixed_field<4>(total_size, 2, this->visual_max_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesClimateResponse::dump_to(std::string &out) const { | 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); |   sprintf(buffer, "%g", this->visual_max_humidity); | ||||||
|   out.append(buffer); |   out.append(buffer); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -4901,6 +5135,10 @@ bool ListEntitiesNumberResponse::decode_varint(uint32_t field_id, ProtoVarInt va | |||||||
|       this->mode = value.as_enum<enums::NumberMode>(); |       this->mode = value.as_enum<enums::NumberMode>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 14: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -4971,6 +5209,7 @@ void ListEntitiesNumberResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_string(11, this->unit_of_measurement); |   buffer.encode_string(11, this->unit_of_measurement); | ||||||
|   buffer.encode_enum<enums::NumberMode>(12, this->mode); |   buffer.encode_enum<enums::NumberMode>(12, this->mode); | ||||||
|   buffer.encode_string(13, this->device_class); |   buffer.encode_string(13, this->device_class); | ||||||
|  |   buffer.encode_uint32(14, this->device_id); | ||||||
| } | } | ||||||
| void ListEntitiesNumberResponse::calculate_size(uint32_t &total_size) const { | void ListEntitiesNumberResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_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_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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesNumberResponse::dump_to(std::string &out) const { | 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("  device_class: "); | ||||||
|   out.append("'").append(this->device_class).append("'"); |   out.append("'").append(this->device_class).append("'"); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -5151,6 +5396,10 @@ bool ListEntitiesSelectResponse::decode_varint(uint32_t field_id, ProtoVarInt va | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 9: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -5202,6 +5451,7 @@ void ListEntitiesSelectResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   } |   } | ||||||
|   buffer.encode_bool(7, this->disabled_by_default); |   buffer.encode_bool(7, this->disabled_by_default); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(8, this->entity_category); |   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 { | void ListEntitiesSelectResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesSelectResponse::dump_to(std::string &out) const { | 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("  entity_category: "); | ||||||
|   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); |   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -5378,6 +5634,10 @@ bool ListEntitiesSirenResponse::decode_varint(uint32_t field_id, ProtoVarInt val | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 11: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -5431,6 +5691,7 @@ void ListEntitiesSirenResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_bool(8, this->supports_duration); |   buffer.encode_bool(8, this->supports_duration); | ||||||
|   buffer.encode_bool(9, this->supports_volume); |   buffer.encode_bool(9, this->supports_volume); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(10, this->entity_category); |   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 { | void ListEntitiesSirenResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_duration, false); | ||||||
|   ProtoSize::add_bool_field(total_size, 1, this->supports_volume, 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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesSirenResponse::dump_to(std::string &out) const { | 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("  entity_category: "); | ||||||
|   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); |   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -5683,6 +5950,10 @@ bool ListEntitiesLockResponse::decode_varint(uint32_t field_id, ProtoVarInt valu | |||||||
|       this->requires_code = value.as_bool(); |       this->requires_code = value.as_bool(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 12: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -5735,6 +6006,7 @@ void ListEntitiesLockResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_bool(9, this->supports_open); |   buffer.encode_bool(9, this->supports_open); | ||||||
|   buffer.encode_bool(10, this->requires_code); |   buffer.encode_bool(10, this->requires_code); | ||||||
|   buffer.encode_string(11, this->code_format); |   buffer.encode_string(11, this->code_format); | ||||||
|  |   buffer.encode_uint32(12, this->device_id); | ||||||
| } | } | ||||||
| void ListEntitiesLockResponse::calculate_size(uint32_t &total_size) const { | void ListEntitiesLockResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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->supports_open, false); | ||||||
|   ProtoSize::add_bool_field(total_size, 1, this->requires_code, 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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesLockResponse::dump_to(std::string &out) const { | 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("  code_format: "); | ||||||
|   out.append("'").append(this->code_format).append("'"); |   out.append("'").append(this->code_format).append("'"); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -5922,6 +6200,10 @@ bool ListEntitiesButtonResponse::decode_varint(uint32_t field_id, ProtoVarInt va | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 9: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -5971,6 +6253,7 @@ void ListEntitiesButtonResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_bool(6, this->disabled_by_default); |   buffer.encode_bool(6, this->disabled_by_default); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(7, this->entity_category); |   buffer.encode_enum<enums::EntityCategory>(7, this->entity_category); | ||||||
|   buffer.encode_string(8, this->device_class); |   buffer.encode_string(8, this->device_class); | ||||||
|  |   buffer.encode_uint32(9, this->device_id); | ||||||
| } | } | ||||||
| void ListEntitiesButtonResponse::calculate_size(uint32_t &total_size) const { | void ListEntitiesButtonResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_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_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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesButtonResponse::dump_to(std::string &out) const { | 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("  device_class: "); | ||||||
|   out.append("'").append(this->device_class).append("'"); |   out.append("'").append(this->device_class).append("'"); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -6135,6 +6424,10 @@ bool ListEntitiesMediaPlayerResponse::decode_varint(uint32_t field_id, ProtoVarI | |||||||
|       this->supports_pause = value.as_bool(); |       this->supports_pause = value.as_bool(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 10: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -6187,6 +6480,7 @@ void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   for (auto &it : this->supported_formats) { |   for (auto &it : this->supported_formats) { | ||||||
|     buffer.encode_message<MediaPlayerSupportedFormat>(9, it, true); |     buffer.encode_message<MediaPlayerSupportedFormat>(9, it, true); | ||||||
|   } |   } | ||||||
|  |   buffer.encode_uint32(10, this->device_id); | ||||||
| } | } | ||||||
| void ListEntitiesMediaPlayerResponse::calculate_size(uint32_t &total_size) const { | void ListEntitiesMediaPlayerResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_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_bool_field(total_size, 1, this->supports_pause, false); | ||||||
|   ProtoSize::add_repeated_message(total_size, 1, this->supported_formats); |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const { | void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const { | ||||||
| @@ -6241,6 +6536,11 @@ void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const { | |||||||
|     it.dump_to(out); |     it.dump_to(out); | ||||||
|     out.append("\n"); |     out.append("\n"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -8551,6 +8851,10 @@ bool ListEntitiesAlarmControlPanelResponse::decode_varint(uint32_t field_id, Pro | |||||||
|       this->requires_code_to_arm = value.as_bool(); |       this->requires_code_to_arm = value.as_bool(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 11: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -8598,6 +8902,7 @@ void ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer buffer) cons | |||||||
|   buffer.encode_uint32(8, this->supported_features); |   buffer.encode_uint32(8, this->supported_features); | ||||||
|   buffer.encode_bool(9, this->requires_code); |   buffer.encode_bool(9, this->requires_code); | ||||||
|   buffer.encode_bool(10, this->requires_code_to_arm); |   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 { | void ListEntitiesAlarmControlPanelResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_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, false); | ||||||
|   ProtoSize::add_bool_field(total_size, 1, this->requires_code_to_arm, 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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const { | 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("  requires_code_to_arm: "); | ||||||
|   out.append(YESNO(this->requires_code_to_arm)); |   out.append(YESNO(this->requires_code_to_arm)); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -8783,6 +9094,10 @@ bool ListEntitiesTextResponse::decode_varint(uint32_t field_id, ProtoVarInt valu | |||||||
|       this->mode = value.as_enum<enums::TextMode>(); |       this->mode = value.as_enum<enums::TextMode>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 12: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -8835,6 +9150,7 @@ void ListEntitiesTextResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_uint32(9, this->max_length); |   buffer.encode_uint32(9, this->max_length); | ||||||
|   buffer.encode_string(10, this->pattern); |   buffer.encode_string(10, this->pattern); | ||||||
|   buffer.encode_enum<enums::TextMode>(11, this->mode); |   buffer.encode_enum<enums::TextMode>(11, this->mode); | ||||||
|  |   buffer.encode_uint32(12, this->device_id); | ||||||
| } | } | ||||||
| void ListEntitiesTextResponse::calculate_size(uint32_t &total_size) const { | void ListEntitiesTextResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_uint32_field(total_size, 1, this->max_length, false); | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->pattern, 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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesTextResponse::dump_to(std::string &out) const { | 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("  mode: "); | ||||||
|   out.append(proto_enum_to_string<enums::TextMode>(this->mode)); |   out.append(proto_enum_to_string<enums::TextMode>(this->mode)); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -9014,6 +9336,10 @@ bool ListEntitiesDateResponse::decode_varint(uint32_t field_id, ProtoVarInt valu | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 8: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -9058,6 +9384,7 @@ void ListEntitiesDateResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_string(5, this->icon); |   buffer.encode_string(5, this->icon); | ||||||
|   buffer.encode_bool(6, this->disabled_by_default); |   buffer.encode_bool(6, this->disabled_by_default); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(7, this->entity_category); |   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 { | void ListEntitiesDateResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_string_field(total_size, 1, this->icon, false); | ||||||
|   ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, 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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesDateResponse::dump_to(std::string &out) const { | 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("  entity_category: "); | ||||||
|   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); |   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -9255,6 +9588,10 @@ bool ListEntitiesTimeResponse::decode_varint(uint32_t field_id, ProtoVarInt valu | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 8: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -9299,6 +9636,7 @@ void ListEntitiesTimeResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_string(5, this->icon); |   buffer.encode_string(5, this->icon); | ||||||
|   buffer.encode_bool(6, this->disabled_by_default); |   buffer.encode_bool(6, this->disabled_by_default); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(7, this->entity_category); |   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 { | void ListEntitiesTimeResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_string_field(total_size, 1, this->icon, false); | ||||||
|   ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, 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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesTimeResponse::dump_to(std::string &out) const { | 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("  entity_category: "); | ||||||
|   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); |   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -9496,6 +9840,10 @@ bool ListEntitiesEventResponse::decode_varint(uint32_t field_id, ProtoVarInt val | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 10: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -9552,6 +9900,7 @@ void ListEntitiesEventResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   for (auto &it : this->event_types) { |   for (auto &it : this->event_types) { | ||||||
|     buffer.encode_string(9, it, true); |     buffer.encode_string(9, it, true); | ||||||
|   } |   } | ||||||
|  |   buffer.encode_uint32(10, this->device_id); | ||||||
| } | } | ||||||
| void ListEntitiesEventResponse::calculate_size(uint32_t &total_size) const { | void ListEntitiesEventResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_string_field(total_size, 1, it, true); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |   ProtoSize::add_uint32_field(total_size, 1, this->device_id, false); | ||||||
| } | } | ||||||
| #ifdef HAS_PROTO_MESSAGE_DUMP | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesEventResponse::dump_to(std::string &out) const { | 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("'").append(it).append("'"); | ||||||
|     out.append("\n"); |     out.append("\n"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -9678,6 +10033,10 @@ bool ListEntitiesValveResponse::decode_varint(uint32_t field_id, ProtoVarInt val | |||||||
|       this->supports_stop = value.as_bool(); |       this->supports_stop = value.as_bool(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 12: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -9730,6 +10089,7 @@ void ListEntitiesValveResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_bool(9, this->assumed_state); |   buffer.encode_bool(9, this->assumed_state); | ||||||
|   buffer.encode_bool(10, this->supports_position); |   buffer.encode_bool(10, this->supports_position); | ||||||
|   buffer.encode_bool(11, this->supports_stop); |   buffer.encode_bool(11, this->supports_stop); | ||||||
|  |   buffer.encode_uint32(12, this->device_id); | ||||||
| } | } | ||||||
| void ListEntitiesValveResponse::calculate_size(uint32_t &total_size) const { | void ListEntitiesValveResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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->assumed_state, false); | ||||||
|   ProtoSize::add_bool_field(total_size, 1, this->supports_position, 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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesValveResponse::dump_to(std::string &out) const { | 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("  supports_stop: "); | ||||||
|   out.append(YESNO(this->supports_stop)); |   out.append(YESNO(this->supports_stop)); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -9923,6 +10289,10 @@ bool ListEntitiesDateTimeResponse::decode_varint(uint32_t field_id, ProtoVarInt | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 8: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -9967,6 +10337,7 @@ void ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_string(5, this->icon); |   buffer.encode_string(5, this->icon); | ||||||
|   buffer.encode_bool(6, this->disabled_by_default); |   buffer.encode_bool(6, this->disabled_by_default); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(7, this->entity_category); |   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 { | void ListEntitiesDateTimeResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_string_field(total_size, 1, this->icon, false); | ||||||
|   ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, 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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesDateTimeResponse::dump_to(std::string &out) const { | 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("  entity_category: "); | ||||||
|   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); |   out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category)); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| @@ -10114,6 +10491,10 @@ bool ListEntitiesUpdateResponse::decode_varint(uint32_t field_id, ProtoVarInt va | |||||||
|       this->entity_category = value.as_enum<enums::EntityCategory>(); |       this->entity_category = value.as_enum<enums::EntityCategory>(); | ||||||
|       return true; |       return true; | ||||||
|     } |     } | ||||||
|  |     case 9: { | ||||||
|  |       this->device_id = value.as_uint32(); | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|     default: |     default: | ||||||
|       return false; |       return false; | ||||||
|   } |   } | ||||||
| @@ -10163,6 +10544,7 @@ void ListEntitiesUpdateResponse::encode(ProtoWriteBuffer buffer) const { | |||||||
|   buffer.encode_bool(6, this->disabled_by_default); |   buffer.encode_bool(6, this->disabled_by_default); | ||||||
|   buffer.encode_enum<enums::EntityCategory>(7, this->entity_category); |   buffer.encode_enum<enums::EntityCategory>(7, this->entity_category); | ||||||
|   buffer.encode_string(8, this->device_class); |   buffer.encode_string(8, this->device_class); | ||||||
|  |   buffer.encode_uint32(9, this->device_id); | ||||||
| } | } | ||||||
| void ListEntitiesUpdateResponse::calculate_size(uint32_t &total_size) const { | void ListEntitiesUpdateResponse::calculate_size(uint32_t &total_size) const { | ||||||
|   ProtoSize::add_string_field(total_size, 1, this->object_id, false); |   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_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_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_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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| void ListEntitiesUpdateResponse::dump_to(std::string &out) const { | 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("  device_class: "); | ||||||
|   out.append("'").append(this->device_class).append("'"); |   out.append("'").append(this->device_class).append("'"); | ||||||
|   out.append("\n"); |   out.append("\n"); | ||||||
|  |  | ||||||
|  |   out.append("  device_id: "); | ||||||
|  |   sprintf(buffer, "%" PRIu32, this->device_id); | ||||||
|  |   out.append(buffer); | ||||||
|  |   out.append("\n"); | ||||||
|   out.append("}"); |   out.append("}"); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -264,6 +264,7 @@ class InfoResponseProtoMessage : public ProtoMessage { | |||||||
|   bool disabled_by_default{false}; |   bool disabled_by_default{false}; | ||||||
|   std::string icon{}; |   std::string icon{}; | ||||||
|   enums::EntityCategory entity_category{}; |   enums::EntityCategory entity_category{}; | ||||||
|  |   uint32_t device_id{0}; | ||||||
|  |  | ||||||
|  protected: |  protected: | ||||||
| }; | }; | ||||||
| @@ -415,10 +416,39 @@ class DeviceInfoRequest : public ProtoMessage { | |||||||
|  |  | ||||||
|  protected: |  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 { | class DeviceInfoResponse : public ProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 10; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "device_info_response"; } |   static constexpr const char *message_name() { return "device_info_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -441,6 +471,9 @@ class DeviceInfoResponse : public ProtoMessage { | |||||||
|   std::string suggested_area{}; |   std::string suggested_area{}; | ||||||
|   std::string bluetooth_mac_address{}; |   std::string bluetooth_mac_address{}; | ||||||
|   bool api_encryption_supported{false}; |   bool api_encryption_supported{false}; | ||||||
|  |   std::vector<DeviceInfo> devices{}; | ||||||
|  |   std::vector<AreaInfo> areas{}; | ||||||
|  |   AreaInfo area{}; | ||||||
|   void encode(ProtoWriteBuffer buffer) const override; |   void encode(ProtoWriteBuffer buffer) const override; | ||||||
|   void calculate_size(uint32_t &total_size) const override; |   void calculate_size(uint32_t &total_size) const override; | ||||||
| #ifdef HAS_PROTO_MESSAGE_DUMP | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
| @@ -493,7 +526,7 @@ class SubscribeStatesRequest : public ProtoMessage { | |||||||
| class ListEntitiesBinarySensorResponse : public InfoResponseProtoMessage { | class ListEntitiesBinarySensorResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 12; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_binary_sensor_response"; } |   static constexpr const char *message_name() { return "list_entities_binary_sensor_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -532,7 +565,7 @@ class BinarySensorStateResponse : public StateResponseProtoMessage { | |||||||
| class ListEntitiesCoverResponse : public InfoResponseProtoMessage { | class ListEntitiesCoverResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 13; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_cover_response"; } |   static constexpr const char *message_name() { return "list_entities_cover_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -601,7 +634,7 @@ class CoverCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesFanResponse : public InfoResponseProtoMessage { | class ListEntitiesFanResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 14; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_fan_response"; } |   static constexpr const char *message_name() { return "list_entities_fan_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -679,7 +712,7 @@ class FanCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesLightResponse : public InfoResponseProtoMessage { | class ListEntitiesLightResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 15; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_light_response"; } |   static constexpr const char *message_name() { return "list_entities_light_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -780,7 +813,7 @@ class LightCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesSensorResponse : public InfoResponseProtoMessage { | class ListEntitiesSensorResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 16; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_sensor_response"; } |   static constexpr const char *message_name() { return "list_entities_sensor_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -823,7 +856,7 @@ class SensorStateResponse : public StateResponseProtoMessage { | |||||||
| class ListEntitiesSwitchResponse : public InfoResponseProtoMessage { | class ListEntitiesSwitchResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 17; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_switch_response"; } |   static constexpr const char *message_name() { return "list_entities_switch_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -880,7 +913,7 @@ class SwitchCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesTextSensorResponse : public InfoResponseProtoMessage { | class ListEntitiesTextSensorResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 18; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_text_sensor_response"; } |   static constexpr const char *message_name() { return "list_entities_text_sensor_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -1196,7 +1229,7 @@ class ExecuteServiceRequest : public ProtoMessage { | |||||||
| class ListEntitiesCameraResponse : public InfoResponseProtoMessage { | class ListEntitiesCameraResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 43; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_camera_response"; } |   static constexpr const char *message_name() { return "list_entities_camera_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -1253,7 +1286,7 @@ class CameraImageRequest : public ProtoMessage { | |||||||
| class ListEntitiesClimateResponse : public InfoResponseProtoMessage { | class ListEntitiesClimateResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 46; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_climate_response"; } |   static constexpr const char *message_name() { return "list_entities_climate_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -1362,7 +1395,7 @@ class ClimateCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesNumberResponse : public InfoResponseProtoMessage { | class ListEntitiesNumberResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 49; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_number_response"; } |   static constexpr const char *message_name() { return "list_entities_number_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -1423,7 +1456,7 @@ class NumberCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesSelectResponse : public InfoResponseProtoMessage { | class ListEntitiesSelectResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 52; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_select_response"; } |   static constexpr const char *message_name() { return "list_entities_select_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -1481,7 +1514,7 @@ class SelectCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesSirenResponse : public InfoResponseProtoMessage { | class ListEntitiesSirenResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 55; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_siren_response"; } |   static constexpr const char *message_name() { return "list_entities_siren_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -1547,7 +1580,7 @@ class SirenCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesLockResponse : public InfoResponseProtoMessage { | class ListEntitiesLockResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 58; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_lock_response"; } |   static constexpr const char *message_name() { return "list_entities_lock_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -1609,7 +1642,7 @@ class LockCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesButtonResponse : public InfoResponseProtoMessage { | class ListEntitiesButtonResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 61; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_button_response"; } |   static constexpr const char *message_name() { return "list_entities_button_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -1662,7 +1695,7 @@ class MediaPlayerSupportedFormat : public ProtoMessage { | |||||||
| class ListEntitiesMediaPlayerResponse : public InfoResponseProtoMessage { | class ListEntitiesMediaPlayerResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 63; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_media_player_response"; } |   static constexpr const char *message_name() { return "list_entities_media_player_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -2532,7 +2565,7 @@ class VoiceAssistantSetConfiguration : public ProtoMessage { | |||||||
| class ListEntitiesAlarmControlPanelResponse : public InfoResponseProtoMessage { | class ListEntitiesAlarmControlPanelResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 94; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_alarm_control_panel_response"; } |   static constexpr const char *message_name() { return "list_entities_alarm_control_panel_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -2592,7 +2625,7 @@ class AlarmControlPanelCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesTextResponse : public InfoResponseProtoMessage { | class ListEntitiesTextResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 97; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_text_response"; } |   static constexpr const char *message_name() { return "list_entities_text_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -2653,7 +2686,7 @@ class TextCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesDateResponse : public InfoResponseProtoMessage { | class ListEntitiesDateResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 100; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_date_response"; } |   static constexpr const char *message_name() { return "list_entities_date_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -2713,7 +2746,7 @@ class DateCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesTimeResponse : public InfoResponseProtoMessage { | class ListEntitiesTimeResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 103; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_time_response"; } |   static constexpr const char *message_name() { return "list_entities_time_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -2773,7 +2806,7 @@ class TimeCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesEventResponse : public InfoResponseProtoMessage { | class ListEntitiesEventResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 107; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_event_response"; } |   static constexpr const char *message_name() { return "list_entities_event_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -2811,7 +2844,7 @@ class EventResponse : public StateResponseProtoMessage { | |||||||
| class ListEntitiesValveResponse : public InfoResponseProtoMessage { | class ListEntitiesValveResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 109; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_valve_response"; } |   static constexpr const char *message_name() { return "list_entities_valve_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -2873,7 +2906,7 @@ class ValveCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesDateTimeResponse : public InfoResponseProtoMessage { | class ListEntitiesDateTimeResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 112; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_date_time_response"; } |   static constexpr const char *message_name() { return "list_entities_date_time_response"; } | ||||||
| #endif | #endif | ||||||
| @@ -2928,7 +2961,7 @@ class DateTimeCommandRequest : public ProtoMessage { | |||||||
| class ListEntitiesUpdateResponse : public InfoResponseProtoMessage { | class ListEntitiesUpdateResponse : public InfoResponseProtoMessage { | ||||||
|  public: |  public: | ||||||
|   static constexpr uint16_t MESSAGE_TYPE = 116; |   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 | #ifdef HAS_PROTO_MESSAGE_DUMP | ||||||
|   static constexpr const char *message_name() { return "list_entities_update_response"; } |   static constexpr const char *message_name() { return "list_entities_update_response"; } | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -1,5 +1,7 @@ | |||||||
| """Helpers for config validation using voluptuous.""" | """Helpers for config validation using voluptuous.""" | ||||||
|  |  | ||||||
|  | from __future__ import annotations | ||||||
|  |  | ||||||
| from contextlib import contextmanager | from contextlib import contextmanager | ||||||
| from dataclasses import dataclass | from dataclasses import dataclass | ||||||
| from datetime import datetime | from datetime import datetime | ||||||
| @@ -29,6 +31,7 @@ from esphome.const import ( | |||||||
|     CONF_COMMAND_RETAIN, |     CONF_COMMAND_RETAIN, | ||||||
|     CONF_COMMAND_TOPIC, |     CONF_COMMAND_TOPIC, | ||||||
|     CONF_DAY, |     CONF_DAY, | ||||||
|  |     CONF_DEVICE_ID, | ||||||
|     CONF_DISABLED_BY_DEFAULT, |     CONF_DISABLED_BY_DEFAULT, | ||||||
|     CONF_DISCOVERY, |     CONF_DISCOVERY, | ||||||
|     CONF_ENTITY_CATEGORY, |     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): | def boolean(value): | ||||||
|     """Validate the given config option to be a boolean. |     """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_DISABLED_BY_DEFAULT, default=False): boolean, | ||||||
|         Optional(CONF_ICON): icon, |         Optional(CONF_ICON): icon, | ||||||
|         Optional(CONF_ENTITY_CATEGORY): entity_category, |         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}" |         return f"{self.major}.{self.minor}.{self.patch}" | ||||||
|  |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def parse(cls, value: str) -> "Version": |     def parse(cls, value: str) -> Version: | ||||||
|         match = re.match(r"^(\d+).(\d+).(\d+)-?\w*$", value) |         match = re.match(r"^(\d+).(\d+).(\d+)-?\w*$", value) | ||||||
|         if match is None: |         if match is None: | ||||||
|             raise ValueError(f"Not a valid version number {value}") |             raise ValueError(f"Not a valid version number {value}") | ||||||
|   | |||||||
| @@ -56,6 +56,8 @@ CONF_AP = "ap" | |||||||
| CONF_APPARENT_POWER = "apparent_power" | CONF_APPARENT_POWER = "apparent_power" | ||||||
| CONF_ARDUINO_VERSION = "arduino_version" | CONF_ARDUINO_VERSION = "arduino_version" | ||||||
| CONF_AREA = "area" | CONF_AREA = "area" | ||||||
|  | CONF_AREA_ID = "area_id" | ||||||
|  | CONF_AREAS = "areas" | ||||||
| CONF_ARGS = "args" | CONF_ARGS = "args" | ||||||
| CONF_ASSUMED_STATE = "assumed_state" | CONF_ASSUMED_STATE = "assumed_state" | ||||||
| CONF_AT = "at" | CONF_AT = "at" | ||||||
| @@ -217,6 +219,7 @@ CONF_DEST = "dest" | |||||||
| CONF_DEVICE = "device" | CONF_DEVICE = "device" | ||||||
| CONF_DEVICE_CLASS = "device_class" | CONF_DEVICE_CLASS = "device_class" | ||||||
| CONF_DEVICE_FACTOR = "device_factor" | CONF_DEVICE_FACTOR = "device_factor" | ||||||
|  | CONF_DEVICE_ID = "device_id" | ||||||
| CONF_DEVICES = "devices" | CONF_DEVICES = "devices" | ||||||
| CONF_DIELECTRIC_CONSTANT = "dielectric_constant" | CONF_DIELECTRIC_CONSTANT = "dielectric_constant" | ||||||
| CONF_DIMENSIONS = "dimensions" | CONF_DIMENSIONS = "dimensions" | ||||||
|   | |||||||
| @@ -10,6 +10,13 @@ | |||||||
| #include "esphome/core/runtime_stats.h" | #include "esphome/core/runtime_stats.h" | ||||||
| #include "esphome/core/scheduler.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 | #ifdef USE_SOCKET_SELECT_SUPPORT | ||||||
| #include <sys/select.h> | #include <sys/select.h> | ||||||
| #endif | #endif | ||||||
| @@ -88,7 +95,7 @@ static const uint32_t TEARDOWN_TIMEOUT_REBOOT_MS = 1000;  // 1 second for quick | |||||||
|  |  | ||||||
| class Application { | class Application { | ||||||
|  public: |  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) { |                  const char *compilation_time, bool name_add_mac_suffix) { | ||||||
|     arch_init(); |     arch_init(); | ||||||
|     this->name_add_mac_suffix_ = name_add_mac_suffix; |     this->name_add_mac_suffix_ = name_add_mac_suffix; | ||||||
| @@ -103,11 +110,18 @@ class Application { | |||||||
|       this->name_ = name; |       this->name_ = name; | ||||||
|       this->friendly_name_ = friendly_name; |       this->friendly_name_ = friendly_name; | ||||||
|     } |     } | ||||||
|     this->area_ = area; |     // area is now handled through the areas system | ||||||
|     this->comment_ = comment; |     this->comment_ = comment; | ||||||
|     this->compilation_time_ = compilation_time; |     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; } |   void set_current_component(Component *component) { this->current_component_ = component; } | ||||||
|   Component *get_current_component() { return this->current_component_; } |   Component *get_current_component() { return this->current_component_; } | ||||||
|  |  | ||||||
| @@ -265,6 +279,12 @@ class Application { | |||||||
| #ifdef USE_UPDATE | #ifdef USE_UPDATE | ||||||
|   void reserve_update(size_t count) { this->updates_.reserve(count); } |   void reserve_update(size_t count) { this->updates_.reserve(count); } | ||||||
| #endif | #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. |   /// Register the component in this Application instance. | ||||||
|   template<class C> C *register_component(C *c) { |   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_; } |   const std::string &get_friendly_name() const { return this->friendly_name_; } | ||||||
|  |  | ||||||
|   /// Get the area of this Application set by pre_setup(). |   /// 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(). |   /// Get the comment of this Application set by pre_setup(). | ||||||
|   std::string get_comment() const { return this->comment_; } |   std::string get_comment() const { return this->comment_; } | ||||||
| @@ -347,6 +375,12 @@ class Application { | |||||||
|  |  | ||||||
|   uint8_t get_app_state() const { return this->app_state_; } |   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 | #ifdef USE_BINARY_SENSOR | ||||||
|   const std::vector<binary_sensor::BinarySensor *> &get_binary_sensors() { return this->binary_sensors_; } |   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) { |   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}; |   uint16_t current_loop_index_{0}; | ||||||
|   bool in_loop_{false}; |   bool in_loop_{false}; | ||||||
|  |  | ||||||
|  | #ifdef USE_DEVICES | ||||||
|  |   std::vector<Device *> devices_{}; | ||||||
|  | #endif | ||||||
|  | #ifdef USE_AREAS | ||||||
|  |   std::vector<Area *> areas_{}; | ||||||
|  | #endif | ||||||
| #ifdef USE_BINARY_SENSOR | #ifdef USE_BINARY_SENSOR | ||||||
|   std::vector<binary_sensor::BinarySensor *> binary_sensors_{}; |   std::vector<binary_sensor::BinarySensor *> binary_sensors_{}; | ||||||
| #endif | #endif | ||||||
| @@ -689,7 +729,6 @@ class Application { | |||||||
|  |  | ||||||
|   std::string name_; |   std::string name_; | ||||||
|   std::string friendly_name_; |   std::string friendly_name_; | ||||||
|   const char *area_{nullptr}; |  | ||||||
|   const char *comment_{nullptr}; |   const char *comment_{nullptr}; | ||||||
|   const char *compilation_time_{nullptr}; |   const char *compilation_time_{nullptr}; | ||||||
|   bool name_add_mac_suffix_; |   bool name_add_mac_suffix_; | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								esphome/core/area.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								esphome/core/area.h
									
									
									
									
									
										Normal 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 | ||||||
| @@ -1,18 +1,24 @@ | |||||||
|  | from __future__ import annotations | ||||||
|  |  | ||||||
| import logging | import logging | ||||||
| import os | import os | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
|  |  | ||||||
| from esphome import automation | from esphome import automation, core | ||||||
| import esphome.codegen as cg | import esphome.codegen as cg | ||||||
| import esphome.config_validation as cv | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_AREA, |     CONF_AREA, | ||||||
|  |     CONF_AREA_ID, | ||||||
|  |     CONF_AREAS, | ||||||
|     CONF_BUILD_PATH, |     CONF_BUILD_PATH, | ||||||
|     CONF_COMMENT, |     CONF_COMMENT, | ||||||
|     CONF_COMPILE_PROCESS_LIMIT, |     CONF_COMPILE_PROCESS_LIMIT, | ||||||
|     CONF_DEBUG_SCHEDULER, |     CONF_DEBUG_SCHEDULER, | ||||||
|  |     CONF_DEVICES, | ||||||
|     CONF_ESPHOME, |     CONF_ESPHOME, | ||||||
|     CONF_FRIENDLY_NAME, |     CONF_FRIENDLY_NAME, | ||||||
|  |     CONF_ID, | ||||||
|     CONF_INCLUDES, |     CONF_INCLUDES, | ||||||
|     CONF_LIBRARIES, |     CONF_LIBRARIES, | ||||||
|     CONF_MIN_VERSION, |     CONF_MIN_VERSION, | ||||||
| @@ -32,7 +38,13 @@ from esphome.const import ( | |||||||
|     __version__ as ESPHOME_VERSION, |     __version__ as ESPHOME_VERSION, | ||||||
| ) | ) | ||||||
| from esphome.core import CORE, coroutine_with_priority | 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__) | _LOGGER = logging.getLogger(__name__) | ||||||
|  |  | ||||||
| @@ -48,7 +60,8 @@ LoopTrigger = cg.esphome_ns.class_( | |||||||
| ProjectUpdateTrigger = cg.esphome_ns.class_( | ProjectUpdateTrigger = cg.esphome_ns.class_( | ||||||
|     "ProjectUpdateTrigger", cg.Component, automation.Trigger.template(cg.std_string) |     "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"} | VALID_INCLUDE_EXTS = {".h", ".hpp", ".tcc", ".ino", ".cpp", ".c"} | ||||||
|  |  | ||||||
| @@ -71,6 +84,56 @@ def validate_hostname(config): | |||||||
|     return 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): | def valid_include(value): | ||||||
|     # Look for "<...>" includes |     # Look for "<...>" includes | ||||||
|     if value.startswith("<") and value.endswith(">"): |     if value.startswith("<") and value.endswith(">"): | ||||||
| @@ -111,13 +174,32 @@ if "ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT" in os.environ: | |||||||
| else: | else: | ||||||
|     _compile_process_limit_default = cv.UNDEFINED |     _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( | CONFIG_SCHEMA = cv.All( | ||||||
|     cv.Schema( |     cv.Schema( | ||||||
|         { |         { | ||||||
|             cv.Required(CONF_NAME): cv.valid_name, |             cv.Required(CONF_NAME): cv.valid_name, | ||||||
|             cv.Optional(CONF_FRIENDLY_NAME, ""): cv.string, |             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.Optional(CONF_COMMENT): cv.string, | ||||||
|             cv.Required(CONF_BUILD_PATH): cv.string, |             cv.Required(CONF_BUILD_PATH): cv.string, | ||||||
|             cv.Optional(CONF_PLATFORMIO_OPTIONS, default={}): cv.Schema( |             cv.Optional(CONF_PLATFORMIO_OPTIONS, default={}): cv.Schema( | ||||||
| @@ -167,11 +249,17 @@ CONFIG_SCHEMA = cv.All( | |||||||
|             cv.Optional( |             cv.Optional( | ||||||
|                 CONF_COMPILE_PROCESS_LIMIT, default=_compile_process_limit_default |                 CONF_COMPILE_PROCESS_LIMIT, default=_compile_process_limit_default | ||||||
|             ): cv.int_range(min=1, max=get_usable_cpu_count()), |             ): 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, |     validate_hostname, | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | FINAL_VALIDATE_SCHEMA = cv.All(validate_ids_and_references) | ||||||
|  |  | ||||||
|  |  | ||||||
| PRELOAD_CONFIG_SCHEMA = cv.Schema( | PRELOAD_CONFIG_SCHEMA = cv.Schema( | ||||||
|     { |     { | ||||||
|         cv.Required(CONF_NAME): cv.valid_name, |         cv.Required(CONF_NAME): cv.valid_name, | ||||||
| @@ -336,7 +424,7 @@ async def _add_platform_reserves() -> None: | |||||||
|  |  | ||||||
|  |  | ||||||
| @coroutine_with_priority(100.0) | @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) |     cg.add_global(cg.global_ns.namespace("esphome").using) | ||||||
|     # These can be used by user lambdas, put them to default scope |     # These can be used by user lambdas, put them to default scope | ||||||
|     cg.add_global(cg.RawExpression("using std::isnan")) |     cg.add_global(cg.RawExpression("using std::isnan")) | ||||||
| @@ -347,7 +435,6 @@ async def to_code(config): | |||||||
|         cg.App.pre_setup( |         cg.App.pre_setup( | ||||||
|             config[CONF_NAME], |             config[CONF_NAME], | ||||||
|             config[CONF_FRIENDLY_NAME], |             config[CONF_FRIENDLY_NAME], | ||||||
|             config[CONF_AREA], |  | ||||||
|             config.get(CONF_COMMENT, ""), |             config.get(CONF_COMMENT, ""), | ||||||
|             cg.RawExpression('__DATE__ ", " __TIME__'), |             cg.RawExpression('__DATE__ ", " __TIME__'), | ||||||
|             config[CONF_NAME_ADD_MAC_SUFFIX], |             config[CONF_NAME_ADD_MAC_SUFFIX], | ||||||
| @@ -417,3 +504,50 @@ async def to_code(config): | |||||||
|  |  | ||||||
|     if config[CONF_PLATFORMIO_OPTIONS]: |     if config[CONF_PLATFORMIO_OPTIONS]: | ||||||
|         CORE.add_job(_add_platformio_options, 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)) | ||||||
|   | |||||||
| @@ -20,6 +20,7 @@ | |||||||
|  |  | ||||||
| // Feature flags | // Feature flags | ||||||
| #define USE_ALARM_CONTROL_PANEL | #define USE_ALARM_CONTROL_PANEL | ||||||
|  | #define USE_AREAS | ||||||
| #define USE_BINARY_SENSOR | #define USE_BINARY_SENSOR | ||||||
| #define USE_BUTTON | #define USE_BUTTON | ||||||
| #define USE_CLIMATE | #define USE_CLIMATE | ||||||
| @@ -29,6 +30,7 @@ | |||||||
| #define USE_DATETIME_DATETIME | #define USE_DATETIME_DATETIME | ||||||
| #define USE_DATETIME_TIME | #define USE_DATETIME_TIME | ||||||
| #define USE_DEEP_SLEEP | #define USE_DEEP_SLEEP | ||||||
|  | #define USE_DEVICES | ||||||
| #define USE_DISPLAY | #define USE_DISPLAY | ||||||
| #define USE_ESP32_IMPROV_STATE_CALLBACK | #define USE_ESP32_IMPROV_STATE_CALLBACK | ||||||
| #define USE_EVENT | #define USE_EVENT | ||||||
|   | |||||||
							
								
								
									
										20
									
								
								esphome/core/device.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								esphome/core/device.h
									
									
									
									
									
										Normal 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 | ||||||
| @@ -51,6 +51,12 @@ class EntityBase { | |||||||
|   std::string get_icon() const; |   std::string get_icon() const; | ||||||
|   void set_icon(const char *icon); |   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 |   // Check if this entity has state | ||||||
|   bool has_state() const { return this->flags_.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 *object_id_c_str_{nullptr}; | ||||||
|   const char *icon_c_str_{nullptr}; |   const char *icon_c_str_{nullptr}; | ||||||
|   uint32_t object_id_hash_{}; |   uint32_t object_id_hash_{}; | ||||||
|  | #ifdef USE_DEVICES | ||||||
|  |   uint32_t device_id_{}; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|   // Bit-packed flags to save memory (1 byte instead of 5) |   // Bit-packed flags to save memory (1 byte instead of 5) | ||||||
|   struct EntityFlags { |   struct EntityFlags { | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| import logging | import logging | ||||||
|  |  | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|  |     CONF_DEVICE_ID, | ||||||
|     CONF_DISABLED_BY_DEFAULT, |     CONF_DISABLED_BY_DEFAULT, | ||||||
|     CONF_ENTITY_CATEGORY, |     CONF_ENTITY_CATEGORY, | ||||||
|     CONF_ICON, |     CONF_ICON, | ||||||
| @@ -16,7 +17,7 @@ from esphome.core import CORE, ID, coroutine | |||||||
| from esphome.coroutine import FakeAwaitable | from esphome.coroutine import FakeAwaitable | ||||||
| from esphome.cpp_generator import add, get_variable | from esphome.cpp_generator import add, get_variable | ||||||
| from esphome.cpp_types import App | 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.types import ConfigFragmentType, ConfigType | ||||||
| from esphome.util import Registry, RegistryEntry | from esphome.util import Registry, RegistryEntry | ||||||
|  |  | ||||||
| @@ -110,6 +111,9 @@ async def setup_entity(var, config): | |||||||
|         add(var.set_icon(config[CONF_ICON])) |         add(var.set_icon(config[CONF_ICON])) | ||||||
|     if CONF_ENTITY_CATEGORY in config: |     if CONF_ENTITY_CATEGORY in config: | ||||||
|         add(var.set_entity_category(config[CONF_ENTITY_CATEGORY])) |         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( | def extract_registry_entry_config( | ||||||
|   | |||||||
| @@ -1,25 +1,9 @@ | |||||||
| from __future__ import annotations | from __future__ import annotations | ||||||
|  |  | ||||||
| import unicodedata | from esphome.helpers import slugify | ||||||
|  |  | ||||||
| from esphome.const import ALLOWED_NAME_CHARS |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def strip_accents(value): | def friendly_name_slugify(value: str) -> str: | ||||||
|     return "".join( |     """Convert a friendly name to a slug with dashes instead of underscores.""" | ||||||
|         c |     # First use the standard slugify, then convert underscores to dashes | ||||||
|         for c in unicodedata.normalize("NFD", str(value)) |     return slugify(value).replace("_", "-") | ||||||
|         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) |  | ||||||
|   | |||||||
| @@ -29,6 +29,53 @@ def ensure_unique_string(preferred_string, current_strings): | |||||||
|     return test_string |     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="  "): | def indent_all_but_first_and_last(text, padding="  "): | ||||||
|     lines = text.splitlines(True) |     lines = text.splitlines(True) | ||||||
|     if len(lines) <= 2: |     if len(lines) <= 2: | ||||||
|   | |||||||
| @@ -2,7 +2,9 @@ esphome: | |||||||
|   debug_scheduler: true |   debug_scheduler: true | ||||||
|   platformio_options: |   platformio_options: | ||||||
|     board_build.flash_mode: dio |     board_build.flash_mode: dio | ||||||
|   area: testing |   area: | ||||||
|  |     id: testing_area | ||||||
|  |     name: Testing Area | ||||||
|   on_boot: |   on_boot: | ||||||
|     logger.log: on_boot |     logger.log: on_boot | ||||||
|   on_shutdown: |   on_shutdown: | ||||||
| @@ -17,4 +19,20 @@ esphome: | |||||||
|     version: "1.1" |     version: "1.1" | ||||||
|     on_update: |     on_update: | ||||||
|       logger.log: on_update |       logger.log: on_update | ||||||
|  |   areas: | ||||||
|  |     - id: another_area | ||||||
|  |       name: Another area | ||||||
|  |   devices: | ||||||
|  |     - id: other_device | ||||||
|  |       name: Another device | ||||||
|  |       area_id: another_area | ||||||
|  |     - id: test_device | ||||||
|  |       name: Test device in main area | ||||||
|  |       area_id: testing_area  # Reference the main area (not in areas) | ||||||
|  |     - id: no_area_device | ||||||
|  |       name: Device without area  # This device has no area_id | ||||||
|  |  | ||||||
|  | binary_sensor: | ||||||
|  |   - platform: template | ||||||
|  |     name: Other device sensor | ||||||
|  |     device_id: other_device | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| using namespace esphome; | using namespace esphome; | ||||||
|  |  | ||||||
| void setup() { | void setup() { | ||||||
|   App.pre_setup("livingroom", "LivingRoom", "LivingRoomArea", "comment", __DATE__ ", " __TIME__, false); |   App.pre_setup("livingroom", "LivingRoom", "comment", __DATE__ ", " __TIME__, false); | ||||||
|   auto *log = new logger::Logger(115200, 512);  // NOLINT |   auto *log = new logger::Logger(115200, 512);  // NOLINT | ||||||
|   log->pre_setup(); |   log->pre_setup(); | ||||||
|   log->set_uart_selection(logger::UART_SELECTION_UART0); |   log->set_uart_selection(logger::UART_SELECTION_UART0); | ||||||
|   | |||||||
							
								
								
									
										57
									
								
								tests/integration/fixtures/areas_and_devices.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								tests/integration/fixtures/areas_and_devices.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | |||||||
|  | esphome: | ||||||
|  |   name: areas-devices-test | ||||||
|  |   # Define top-level area | ||||||
|  |   area: | ||||||
|  |     id: living_room_area | ||||||
|  |     name: Living Room | ||||||
|  |   # Define additional areas | ||||||
|  |   areas: | ||||||
|  |     - id: bedroom_area | ||||||
|  |       name: Bedroom | ||||||
|  |     - id: kitchen_area | ||||||
|  |       name: Kitchen | ||||||
|  |   # Define devices with area assignments | ||||||
|  |   devices: | ||||||
|  |     - id: light_controller_device | ||||||
|  |       name: Light Controller | ||||||
|  |       area_id: living_room_area  # Uses top-level area | ||||||
|  |     - id: temp_sensor_device | ||||||
|  |       name: Temperature Sensor | ||||||
|  |       area_id: bedroom_area | ||||||
|  |     - id: motion_detector_device | ||||||
|  |       name: Motion Detector | ||||||
|  |       area_id: living_room_area  # Reuses top-level area | ||||||
|  |     - id: smart_switch_device | ||||||
|  |       name: Smart Switch | ||||||
|  |       area_id: kitchen_area | ||||||
|  |  | ||||||
|  | host: | ||||||
|  | api: | ||||||
|  | logger: | ||||||
|  |  | ||||||
|  | # Sensors assigned to different devices | ||||||
|  | sensor: | ||||||
|  |   - platform: template | ||||||
|  |     name: Light Controller Sensor | ||||||
|  |     device_id: light_controller_device | ||||||
|  |     lambda: return 1.0; | ||||||
|  |     update_interval: 0.1s | ||||||
|  |  | ||||||
|  |   - platform: template | ||||||
|  |     name: Temperature Sensor Reading | ||||||
|  |     device_id: temp_sensor_device | ||||||
|  |     lambda: return 2.0; | ||||||
|  |     update_interval: 0.1s | ||||||
|  |  | ||||||
|  |   - platform: template | ||||||
|  |     name: Motion Detector Status | ||||||
|  |     device_id: motion_detector_device | ||||||
|  |     lambda: return 3.0; | ||||||
|  |     update_interval: 0.1s | ||||||
|  |  | ||||||
|  |   - platform: template | ||||||
|  |     name: Smart Switch Power | ||||||
|  |     device_id: smart_switch_device | ||||||
|  |     lambda: return 4.0; | ||||||
|  |     update_interval: 0.1s | ||||||
|  |  | ||||||
							
								
								
									
										15
									
								
								tests/integration/fixtures/legacy_area.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tests/integration/fixtures/legacy_area.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | esphome: | ||||||
|  |   name: legacy-area-test | ||||||
|  |   # Using legacy string-based area configuration | ||||||
|  |   area: Master Bedroom | ||||||
|  |  | ||||||
|  | host: | ||||||
|  | api: | ||||||
|  | logger: | ||||||
|  |  | ||||||
|  | # Simple sensor to ensure the device compiles and runs | ||||||
|  | sensor: | ||||||
|  |   - platform: template | ||||||
|  |     name: Test Sensor | ||||||
|  |     lambda: return 42.0; | ||||||
|  |     update_interval: 1s | ||||||
							
								
								
									
										121
									
								
								tests/integration/test_areas_and_devices.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								tests/integration/test_areas_and_devices.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,121 @@ | |||||||
|  | """Integration test for areas and devices feature.""" | ||||||
|  |  | ||||||
|  | from __future__ import annotations | ||||||
|  |  | ||||||
|  | import asyncio | ||||||
|  |  | ||||||
|  | from aioesphomeapi import EntityState | ||||||
|  | import pytest | ||||||
|  |  | ||||||
|  | from .types import APIClientConnectedFactory, RunCompiledFunction | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @pytest.mark.asyncio | ||||||
|  | async def test_areas_and_devices( | ||||||
|  |     yaml_config: str, | ||||||
|  |     run_compiled: RunCompiledFunction, | ||||||
|  |     api_client_connected: APIClientConnectedFactory, | ||||||
|  | ) -> None: | ||||||
|  |     """Test areas and devices configuration with entity mapping.""" | ||||||
|  |     async with run_compiled(yaml_config), api_client_connected() as client: | ||||||
|  |         # Get device info which includes areas and devices | ||||||
|  |         device_info = await client.device_info() | ||||||
|  |         assert device_info is not None | ||||||
|  |  | ||||||
|  |         # Verify areas are reported | ||||||
|  |         areas = device_info.areas | ||||||
|  |         assert len(areas) >= 2, f"Expected at least 2 areas, got {len(areas)}" | ||||||
|  |  | ||||||
|  |         # Find our specific areas | ||||||
|  |         main_area = next((a for a in areas if a.name == "Living Room"), None) | ||||||
|  |         bedroom_area = next((a for a in areas if a.name == "Bedroom"), None) | ||||||
|  |         kitchen_area = next((a for a in areas if a.name == "Kitchen"), None) | ||||||
|  |  | ||||||
|  |         assert main_area is not None, "Living Room area not found" | ||||||
|  |         assert bedroom_area is not None, "Bedroom area not found" | ||||||
|  |         assert kitchen_area is not None, "Kitchen area not found" | ||||||
|  |  | ||||||
|  |         # Verify devices are reported | ||||||
|  |         devices = device_info.devices | ||||||
|  |         assert len(devices) >= 4, f"Expected at least 4 devices, got {len(devices)}" | ||||||
|  |  | ||||||
|  |         # Find our specific devices | ||||||
|  |         light_controller = next( | ||||||
|  |             (d for d in devices if d.name == "Light Controller"), None | ||||||
|  |         ) | ||||||
|  |         temp_sensor = next((d for d in devices if d.name == "Temperature Sensor"), None) | ||||||
|  |         motion_detector = next( | ||||||
|  |             (d for d in devices if d.name == "Motion Detector"), None | ||||||
|  |         ) | ||||||
|  |         smart_switch = next((d for d in devices if d.name == "Smart Switch"), None) | ||||||
|  |  | ||||||
|  |         assert light_controller is not None, "Light Controller device not found" | ||||||
|  |         assert temp_sensor is not None, "Temperature Sensor device not found" | ||||||
|  |         assert motion_detector is not None, "Motion Detector device not found" | ||||||
|  |         assert smart_switch is not None, "Smart Switch device not found" | ||||||
|  |  | ||||||
|  |         # Verify device area assignments | ||||||
|  |         assert light_controller.area_id == main_area.area_id, ( | ||||||
|  |             "Light Controller should be in Living Room" | ||||||
|  |         ) | ||||||
|  |         assert temp_sensor.area_id == bedroom_area.area_id, ( | ||||||
|  |             "Temperature Sensor should be in Bedroom" | ||||||
|  |         ) | ||||||
|  |         assert motion_detector.area_id == main_area.area_id, ( | ||||||
|  |             "Motion Detector should be in Living Room" | ||||||
|  |         ) | ||||||
|  |         assert smart_switch.area_id == kitchen_area.area_id, ( | ||||||
|  |             "Smart Switch should be in Kitchen" | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         # Verify suggested_area is set to the top-level area name | ||||||
|  |         assert device_info.suggested_area == "Living Room", ( | ||||||
|  |             f"Expected suggested_area to be 'Living Room', got '{device_info.suggested_area}'" | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         # Get entity list to verify device_id mapping | ||||||
|  |         entities = await client.list_entities_services() | ||||||
|  |  | ||||||
|  |         # Collect sensor entities | ||||||
|  |         sensor_entities = [e for e in entities[0] if hasattr(e, "device_id")] | ||||||
|  |         assert len(sensor_entities) >= 4, ( | ||||||
|  |             f"Expected at least 4 sensor entities, got {len(sensor_entities)}" | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         # Subscribe to states to get sensor values | ||||||
|  |         loop = asyncio.get_running_loop() | ||||||
|  |         states: dict[int, EntityState] = {} | ||||||
|  |         states_future: asyncio.Future[bool] = loop.create_future() | ||||||
|  |  | ||||||
|  |         def on_state(state: EntityState) -> None: | ||||||
|  |             states[state.key] = state | ||||||
|  |             # Check if we have all expected sensor states | ||||||
|  |             if len(states) >= 4 and not states_future.done(): | ||||||
|  |                 states_future.set_result(True) | ||||||
|  |  | ||||||
|  |         client.subscribe_states(on_state) | ||||||
|  |  | ||||||
|  |         # Wait for sensor states | ||||||
|  |         try: | ||||||
|  |             await asyncio.wait_for(states_future, timeout=10.0) | ||||||
|  |         except asyncio.TimeoutError: | ||||||
|  |             pytest.fail( | ||||||
|  |                 f"Did not receive all sensor states within 10 seconds. " | ||||||
|  |                 f"Received {len(states)} states" | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         # Verify we have sensor entities with proper device_id assignments | ||||||
|  |         device_id_mapping = { | ||||||
|  |             "Light Controller Sensor": light_controller.device_id, | ||||||
|  |             "Temperature Sensor Reading": temp_sensor.device_id, | ||||||
|  |             "Motion Detector Status": motion_detector.device_id, | ||||||
|  |             "Smart Switch Power": smart_switch.device_id, | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         for entity in sensor_entities: | ||||||
|  |             if entity.name in device_id_mapping: | ||||||
|  |                 expected_device_id = device_id_mapping[entity.name] | ||||||
|  |                 assert entity.device_id == expected_device_id, ( | ||||||
|  |                     f"{entity.name} has device_id {entity.device_id}, " | ||||||
|  |                     f"expected {expected_device_id}" | ||||||
|  |                 ) | ||||||
							
								
								
									
										41
									
								
								tests/integration/test_legacy_area.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								tests/integration/test_legacy_area.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | """Integration test for legacy string-based area configuration.""" | ||||||
|  |  | ||||||
|  | from __future__ import annotations | ||||||
|  |  | ||||||
|  | import pytest | ||||||
|  |  | ||||||
|  | from .types import APIClientConnectedFactory, RunCompiledFunction | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @pytest.mark.asyncio | ||||||
|  | async def test_legacy_area( | ||||||
|  |     yaml_config: str, | ||||||
|  |     run_compiled: RunCompiledFunction, | ||||||
|  |     api_client_connected: APIClientConnectedFactory, | ||||||
|  | ) -> None: | ||||||
|  |     """Test legacy string-based area configuration.""" | ||||||
|  |     async with run_compiled(yaml_config), api_client_connected() as client: | ||||||
|  |         # Get device info which includes areas | ||||||
|  |         device_info = await client.device_info() | ||||||
|  |         assert device_info is not None | ||||||
|  |  | ||||||
|  |         # Verify the area is reported (should be converted to structured format) | ||||||
|  |         areas = device_info.areas | ||||||
|  |         assert len(areas) == 1, f"Expected exactly 1 area, got {len(areas)}" | ||||||
|  |  | ||||||
|  |         # Find the area - should be slugified from "Master Bedroom" | ||||||
|  |         area = areas[0] | ||||||
|  |         assert area.name == "Master Bedroom", ( | ||||||
|  |             f"Expected area name 'Master Bedroom', got '{area.name}'" | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         # Verify area.id is set (it should be a hash) | ||||||
|  |         assert area.area_id > 0, "Area ID should be a positive hash value" | ||||||
|  |  | ||||||
|  |         # The suggested_area field should be set for backward compatibility | ||||||
|  |         assert device_info.suggested_area == "Master Bedroom", ( | ||||||
|  |             f"Expected suggested_area to be 'Master Bedroom', got '{device_info.suggested_area}'" | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         # Verify deprecated warning would have been logged during compilation | ||||||
|  |         # (We can't check logs directly in integration tests, but the code should work) | ||||||
							
								
								
									
										256
									
								
								tests/unit_tests/core/test_config.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								tests/unit_tests/core/test_config.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,256 @@ | |||||||
|  | """Unit tests for core config functionality including areas and devices.""" | ||||||
|  |  | ||||||
|  | from collections.abc import Callable | ||||||
|  | from pathlib import Path | ||||||
|  | from typing import Any | ||||||
|  | from unittest.mock import patch | ||||||
|  |  | ||||||
|  | import pytest | ||||||
|  |  | ||||||
|  | from esphome import config, config_validation as cv, core, yaml_util | ||||||
|  | from esphome.config import Config | ||||||
|  | from esphome.const import CONF_AREA, CONF_AREAS, CONF_DEVICES | ||||||
|  | from esphome.core import CORE | ||||||
|  | from esphome.core.config import Area, validate_area_config | ||||||
|  |  | ||||||
|  | FIXTURES_DIR = Path(__file__).parent.parent / "fixtures" / "core" / "config" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @pytest.fixture | ||||||
|  | def yaml_file(tmp_path: Path) -> Callable[[str], str]: | ||||||
|  |     """Create a temporary YAML file for testing.""" | ||||||
|  |  | ||||||
|  |     def _yaml_file(content: str) -> str: | ||||||
|  |         yaml_path = tmp_path / "test.yaml" | ||||||
|  |         yaml_path.write_text(content) | ||||||
|  |         return str(yaml_path) | ||||||
|  |  | ||||||
|  |     return _yaml_file | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @pytest.fixture(autouse=True) | ||||||
|  | def reset_core(): | ||||||
|  |     """Reset CORE after each test.""" | ||||||
|  |     yield | ||||||
|  |     CORE.reset() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def load_config_from_yaml( | ||||||
|  |     yaml_file: Callable[[str], str], yaml_content: str | ||||||
|  | ) -> Config | None: | ||||||
|  |     """Load configuration from YAML content.""" | ||||||
|  |     yaml_path = yaml_file(yaml_content) | ||||||
|  |     parsed_yaml = yaml_util.load_yaml(yaml_path) | ||||||
|  |  | ||||||
|  |     # Mock yaml_util.load_yaml to return our parsed content | ||||||
|  |     with ( | ||||||
|  |         patch.object(yaml_util, "load_yaml", return_value=parsed_yaml), | ||||||
|  |         patch.object(CORE, "config_path", yaml_path), | ||||||
|  |     ): | ||||||
|  |         return config.read_config({}) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def load_config_from_fixture( | ||||||
|  |     yaml_file: Callable[[str], str], fixture_name: str | ||||||
|  | ) -> Config | None: | ||||||
|  |     """Load configuration from a fixture file.""" | ||||||
|  |     fixture_path = FIXTURES_DIR / fixture_name | ||||||
|  |     yaml_content = fixture_path.read_text() | ||||||
|  |     return load_config_from_yaml(yaml_file, yaml_content) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_validate_area_config_with_string() -> None: | ||||||
|  |     """Test that string area config is converted to structured format.""" | ||||||
|  |     result: dict[str, Any] = validate_area_config("Living Room") | ||||||
|  |  | ||||||
|  |     assert isinstance(result, dict) | ||||||
|  |     assert "id" in result | ||||||
|  |     assert "name" in result | ||||||
|  |     assert result["name"] == "Living Room" | ||||||
|  |     assert isinstance(result["id"], core.ID) | ||||||
|  |     assert result["id"].is_declaration | ||||||
|  |     assert not result["id"].is_manual | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_validate_area_config_with_dict() -> None: | ||||||
|  |     """Test that structured area config passes through unchanged.""" | ||||||
|  |     area_id = cv.declare_id(Area)("test_area") | ||||||
|  |     input_config: dict[str, Any] = { | ||||||
|  |         "id": area_id, | ||||||
|  |         "name": "Test Area", | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     result: dict[str, Any] = validate_area_config(input_config) | ||||||
|  |  | ||||||
|  |     assert result == input_config | ||||||
|  |     assert result["id"] == area_id | ||||||
|  |     assert result["name"] == "Test Area" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_device_with_valid_area_id(yaml_file: Callable[[str], str]) -> None: | ||||||
|  |     """Test that device with valid area_id works correctly.""" | ||||||
|  |     result = load_config_from_fixture(yaml_file, "valid_area_device.yaml") | ||||||
|  |     assert result is not None | ||||||
|  |  | ||||||
|  |     esphome_config = result["esphome"] | ||||||
|  |  | ||||||
|  |     # Verify areas were parsed correctly | ||||||
|  |     assert CONF_AREAS in esphome_config | ||||||
|  |     areas = esphome_config[CONF_AREAS] | ||||||
|  |     assert len(areas) == 1 | ||||||
|  |     assert areas[0]["id"].id == "bedroom_area" | ||||||
|  |     assert areas[0]["name"] == "Bedroom" | ||||||
|  |  | ||||||
|  |     # Verify devices were parsed correctly | ||||||
|  |     assert CONF_DEVICES in esphome_config | ||||||
|  |     devices = esphome_config[CONF_DEVICES] | ||||||
|  |     assert len(devices) == 1 | ||||||
|  |     assert devices[0]["id"].id == "test_device" | ||||||
|  |     assert devices[0]["name"] == "Test Device" | ||||||
|  |     assert devices[0]["area_id"].id == "bedroom_area" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_multiple_areas_and_devices(yaml_file: Callable[[str], str]) -> None: | ||||||
|  |     """Test multiple areas and devices configuration.""" | ||||||
|  |     result = load_config_from_fixture(yaml_file, "multiple_areas_devices.yaml") | ||||||
|  |     assert result is not None | ||||||
|  |  | ||||||
|  |     esphome_config = result["esphome"] | ||||||
|  |  | ||||||
|  |     # Verify main area | ||||||
|  |     assert CONF_AREA in esphome_config | ||||||
|  |     main_area = esphome_config[CONF_AREA] | ||||||
|  |     assert main_area["id"].id == "main_area" | ||||||
|  |     assert main_area["name"] == "Main Area" | ||||||
|  |  | ||||||
|  |     # Verify additional areas | ||||||
|  |     assert CONF_AREAS in esphome_config | ||||||
|  |     areas = esphome_config[CONF_AREAS] | ||||||
|  |     assert len(areas) == 2 | ||||||
|  |     area_ids = {area["id"].id for area in areas} | ||||||
|  |     assert area_ids == {"area1", "area2"} | ||||||
|  |  | ||||||
|  |     # Verify devices | ||||||
|  |     assert CONF_DEVICES in esphome_config | ||||||
|  |     devices = esphome_config[CONF_DEVICES] | ||||||
|  |     assert len(devices) == 3 | ||||||
|  |  | ||||||
|  |     # Check device-area associations | ||||||
|  |     device_area_map = {dev["id"].id: dev["area_id"].id for dev in devices} | ||||||
|  |     assert device_area_map == { | ||||||
|  |         "device1": "main_area", | ||||||
|  |         "device2": "area1", | ||||||
|  |         "device3": "area2", | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_legacy_string_area( | ||||||
|  |     yaml_file: Callable[[str], str], caplog: pytest.LogCaptureFixture | ||||||
|  | ) -> None: | ||||||
|  |     """Test legacy string area configuration with deprecation warning.""" | ||||||
|  |     result = load_config_from_fixture(yaml_file, "legacy_string_area.yaml") | ||||||
|  |     assert result is not None | ||||||
|  |  | ||||||
|  |     esphome_config = result["esphome"] | ||||||
|  |  | ||||||
|  |     # Verify the string was converted to structured format | ||||||
|  |     assert CONF_AREA in esphome_config | ||||||
|  |     area = esphome_config[CONF_AREA] | ||||||
|  |     assert isinstance(area, dict) | ||||||
|  |     assert area["name"] == "Living Room" | ||||||
|  |     assert isinstance(area["id"], core.ID) | ||||||
|  |     assert area["id"].is_declaration | ||||||
|  |     assert not area["id"].is_manual | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_area_id_collision( | ||||||
|  |     yaml_file: Callable[[str], str], capsys: pytest.CaptureFixture[str] | ||||||
|  | ) -> None: | ||||||
|  |     """Test that duplicate area IDs are detected.""" | ||||||
|  |     result = load_config_from_fixture(yaml_file, "area_id_collision.yaml") | ||||||
|  |     assert result is None | ||||||
|  |  | ||||||
|  |     # Check for the specific error message in stdout | ||||||
|  |     captured = capsys.readouterr() | ||||||
|  |     # Exact duplicates are now caught by IDPassValidationStep | ||||||
|  |     assert "ID duplicate_id redefined! Check esphome->area->id." in captured.out | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_device_without_area(yaml_file: Callable[[str], str]) -> None: | ||||||
|  |     """Test that devices without area_id work correctly.""" | ||||||
|  |     result = load_config_from_fixture(yaml_file, "device_without_area.yaml") | ||||||
|  |     assert result is not None | ||||||
|  |  | ||||||
|  |     esphome_config = result["esphome"] | ||||||
|  |  | ||||||
|  |     # Verify device was parsed | ||||||
|  |     assert CONF_DEVICES in esphome_config | ||||||
|  |     devices = esphome_config[CONF_DEVICES] | ||||||
|  |     assert len(devices) == 1 | ||||||
|  |  | ||||||
|  |     device = devices[0] | ||||||
|  |     assert device["id"].id == "test_device" | ||||||
|  |     assert device["name"] == "Test Device" | ||||||
|  |  | ||||||
|  |     # Verify no area_id is present | ||||||
|  |     assert "area_id" not in device | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_device_with_invalid_area_id( | ||||||
|  |     yaml_file: Callable[[str], str], capsys: pytest.CaptureFixture[str] | ||||||
|  | ) -> None: | ||||||
|  |     """Test that device with non-existent area_id fails validation.""" | ||||||
|  |     result = load_config_from_fixture(yaml_file, "device_invalid_area.yaml") | ||||||
|  |     assert result is None | ||||||
|  |  | ||||||
|  |     # Check for the specific error message in stdout | ||||||
|  |     captured = capsys.readouterr() | ||||||
|  |     print(captured.out) | ||||||
|  |     assert ( | ||||||
|  |         "Couldn't find ID 'nonexistent_area'. Please check you have defined an ID with that name in your configuration." | ||||||
|  |         in captured.out | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_device_id_hash_collision( | ||||||
|  |     yaml_file: Callable[[str], str], capsys: pytest.CaptureFixture[str] | ||||||
|  | ) -> None: | ||||||
|  |     """Test that device IDs with hash collisions are detected.""" | ||||||
|  |     result = load_config_from_fixture(yaml_file, "device_id_collision.yaml") | ||||||
|  |     assert result is None | ||||||
|  |  | ||||||
|  |     # Check for the specific error message about hash collision | ||||||
|  |     captured = capsys.readouterr() | ||||||
|  |     # The error message shows the ID that collides and includes the hash value | ||||||
|  |     assert ( | ||||||
|  |         "Device ID 'd6ka' with hash 3082558663 collides with existing device ID 'test_2258'" | ||||||
|  |         in captured.out | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_area_id_hash_collision( | ||||||
|  |     yaml_file: Callable[[str], str], capsys: pytest.CaptureFixture[str] | ||||||
|  | ) -> None: | ||||||
|  |     """Test that area IDs with hash collisions are detected.""" | ||||||
|  |     result = load_config_from_fixture(yaml_file, "area_id_hash_collision.yaml") | ||||||
|  |     assert result is None | ||||||
|  |  | ||||||
|  |     # Check for the specific error message about hash collision | ||||||
|  |     captured = capsys.readouterr() | ||||||
|  |     # The error message shows the ID that collides and includes the hash value | ||||||
|  |     assert ( | ||||||
|  |         "Area ID 'd6ka' with hash 3082558663 collides with existing area ID 'test_2258'" | ||||||
|  |         in captured.out | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_device_duplicate_id( | ||||||
|  |     yaml_file: Callable[[str], str], capsys: pytest.CaptureFixture[str] | ||||||
|  | ) -> None: | ||||||
|  |     """Test that duplicate device IDs are detected by IDPassValidationStep.""" | ||||||
|  |     result = load_config_from_fixture(yaml_file, "device_duplicate_id.yaml") | ||||||
|  |     assert result is None | ||||||
|  |  | ||||||
|  |     # Check for the specific error message from IDPassValidationStep | ||||||
|  |     captured = capsys.readouterr() | ||||||
|  |     assert "ID duplicate_device redefined!" in captured.out | ||||||
							
								
								
									
										10
									
								
								tests/unit_tests/fixtures/core/config/area_id_collision.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								tests/unit_tests/fixtures/core/config/area_id_collision.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | esphome: | ||||||
|  |   name: test-collision | ||||||
|  |   area: | ||||||
|  |     id: duplicate_id | ||||||
|  |     name: Area 1 | ||||||
|  |   areas: | ||||||
|  |     - id: duplicate_id | ||||||
|  |       name: Area 2 | ||||||
|  |  | ||||||
|  | host: | ||||||
| @@ -0,0 +1,10 @@ | |||||||
|  | esphome: | ||||||
|  |   name: test | ||||||
|  |   areas: | ||||||
|  |     - id: test_2258 | ||||||
|  |       name: "Area 1" | ||||||
|  |     - id: d6ka | ||||||
|  |       name: "Area 2" | ||||||
|  |  | ||||||
|  | esp32: | ||||||
|  |   board: esp32dev | ||||||
| @@ -0,0 +1,10 @@ | |||||||
|  | esphome: | ||||||
|  |   name: test | ||||||
|  |   devices: | ||||||
|  |     - id: duplicate_device | ||||||
|  |       name: "Device 1" | ||||||
|  |     - id: duplicate_device | ||||||
|  |       name: "Device 2" | ||||||
|  |  | ||||||
|  | esp32: | ||||||
|  |   board: esp32dev | ||||||
| @@ -0,0 +1,10 @@ | |||||||
|  | esphome: | ||||||
|  |   name: test | ||||||
|  |   devices: | ||||||
|  |     - id: test_2258 | ||||||
|  |       name: "Device 1" | ||||||
|  |     - id: d6ka | ||||||
|  |       name: "Device 2" | ||||||
|  |  | ||||||
|  | esp32: | ||||||
|  |   board: esp32dev | ||||||
| @@ -0,0 +1,12 @@ | |||||||
|  | esphome: | ||||||
|  |   name: test | ||||||
|  |   areas: | ||||||
|  |     - id: valid_area | ||||||
|  |       name: "Valid Area" | ||||||
|  |   devices: | ||||||
|  |     - id: test_device | ||||||
|  |       name: "Test Device" | ||||||
|  |       area_id: nonexistent_area | ||||||
|  |  | ||||||
|  | esp32: | ||||||
|  |   board: esp32dev | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | esphome: | ||||||
|  |   name: test-device-no-area | ||||||
|  |   devices: | ||||||
|  |     - id: test_device | ||||||
|  |       name: Test Device | ||||||
|  |  | ||||||
|  | host: | ||||||
| @@ -0,0 +1,5 @@ | |||||||
|  | esphome: | ||||||
|  |   name: test-legacy-area | ||||||
|  |   area: Living Room | ||||||
|  |  | ||||||
|  | host: | ||||||
| @@ -0,0 +1,22 @@ | |||||||
|  | esphome: | ||||||
|  |   name: test-multiple | ||||||
|  |   area: | ||||||
|  |     id: main_area | ||||||
|  |     name: Main Area | ||||||
|  |   areas: | ||||||
|  |     - id: area1 | ||||||
|  |       name: Area 1 | ||||||
|  |     - id: area2 | ||||||
|  |       name: Area 2 | ||||||
|  |   devices: | ||||||
|  |     - id: device1 | ||||||
|  |       name: Device 1 | ||||||
|  |       area_id: main_area | ||||||
|  |     - id: device2 | ||||||
|  |       name: Device 2 | ||||||
|  |       area_id: area1 | ||||||
|  |     - id: device3 | ||||||
|  |       name: Device 3 | ||||||
|  |       area_id: area2 | ||||||
|  |  | ||||||
|  | host: | ||||||
							
								
								
									
										11
									
								
								tests/unit_tests/fixtures/core/config/valid_area_device.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tests/unit_tests/fixtures/core/config/valid_area_device.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | esphome: | ||||||
|  |   name: test-valid-area | ||||||
|  |   areas: | ||||||
|  |     - id: bedroom_area | ||||||
|  |       name: Bedroom | ||||||
|  |   devices: | ||||||
|  |     - id: test_device | ||||||
|  |       name: Test Device | ||||||
|  |       area_id: bedroom_area | ||||||
|  |  | ||||||
|  | host: | ||||||
		Reference in New Issue
	
	Block a user