diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index e90586a42b..10f5aace5e 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -185,6 +185,12 @@ message DeviceInfoRequest { // Empty } +message SubDeviceInfo { + string id = 1; + string name = 2; + string suggested_area = 3; +} + message DeviceInfoResponse { option (id) = 10; option (source) = SOURCE_SERVER; @@ -230,6 +236,8 @@ message DeviceInfoResponse { // The Bluetooth mac address of the device. For example "AC:BC:32:89:0E:AA" string bluetooth_mac_address = 18; + + repeated SubDeviceInfo sub_devices = 19; } message ListEntitiesRequest { @@ -273,7 +281,7 @@ message ListEntitiesBinarySensorResponse { bool disabled_by_default = 7; string icon = 8; EntityCategory entity_category = 9; - string device_name = 10; + string device_id = 10; } message BinarySensorStateResponse { option (id) = 21; @@ -307,7 +315,7 @@ message ListEntitiesCoverResponse { string icon = 10; EntityCategory entity_category = 11; bool supports_stop = 12; - string device_name = 13; + string device_id = 13; } enum LegacyCoverState { diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 2dddc3b4e0..2fdf95192b 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -280,7 +280,7 @@ bool APIConnection::try_send_binary_sensor_info(APIConnection *api, void *v_bina msg.disabled_by_default = binary_sensor->is_disabled_by_default(); msg.icon = binary_sensor->get_icon(); msg.entity_category = static_cast(binary_sensor->get_entity_category()); - msg.device_name = binary_sensor->get_device_name(); + msg.device_id = binary_sensor->get_device_id(); return api->send_list_entities_binary_sensor_response(msg); } #endif @@ -331,7 +331,7 @@ bool APIConnection::try_send_cover_info(APIConnection *api, void *v_cover) { msg.disabled_by_default = cover->is_disabled_by_default(); msg.icon = cover->get_icon(); msg.entity_category = static_cast(cover->get_entity_category()); - msg.device_name = cover->get_device_name(); + msg.device_id = cover->get_device_id(); return api->send_list_entities_cover_response(msg); } void APIConnection::cover_command(const CoverCommandRequest &msg) { diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index f386924d5e..61a53e4a0c 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -1002,7 +1002,7 @@ bool ListEntitiesBinarySensorResponse::decode_length(uint32_t field_id, ProtoLen return true; } case 10: { - this->device_name = value.as_string(); + this->device_id = value.as_string(); return true; } default: @@ -1029,7 +1029,7 @@ void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(7, this->disabled_by_default); buffer.encode_string(8, this->icon); buffer.encode_enum(9, this->entity_category); - buffer.encode_string(10, this->device_name); + buffer.encode_string(10, this->device_id); } #ifdef HAS_PROTO_MESSAGE_DUMP void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const { @@ -1072,8 +1072,8 @@ void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const { out.append(proto_enum_to_string(this->entity_category)); out.append("\n"); - out.append(" device_name: "); - out.append("'").append(this->device_name).append("'"); + out.append(" device_id: "); + out.append("'").append(this->device_id).append("'"); out.append("\n"); out.append("}"); } @@ -1179,7 +1179,7 @@ bool ListEntitiesCoverResponse::decode_length(uint32_t field_id, ProtoLengthDeli return true; } case 13: { - this->device_name = value.as_string(); + this->device_id = value.as_string(); return true; } default: @@ -1209,7 +1209,7 @@ void ListEntitiesCoverResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_string(10, this->icon); buffer.encode_enum(11, this->entity_category); buffer.encode_bool(12, this->supports_stop); - buffer.encode_string(13, this->device_name); + buffer.encode_string(13, this->device_id); } #ifdef HAS_PROTO_MESSAGE_DUMP void ListEntitiesCoverResponse::dump_to(std::string &out) const { @@ -1264,8 +1264,8 @@ void ListEntitiesCoverResponse::dump_to(std::string &out) const { out.append(YESNO(this->supports_stop)); out.append("\n"); - out.append(" device_name: "); - out.append("'").append(this->device_name).append("'"); + out.append(" device_id: "); + out.append("'").append(this->device_id).append("'"); out.append("\n"); out.append("}"); } diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 247ec0d65a..fc1b71e8ee 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -402,7 +402,7 @@ class ListEntitiesBinarySensorResponse : public ProtoMessage { bool disabled_by_default{false}; std::string icon{}; enums::EntityCategory entity_category{}; - std::string device_name{}; + std::string device_id{}; void encode(ProtoWriteBuffer buffer) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; @@ -441,7 +441,7 @@ class ListEntitiesCoverResponse : public ProtoMessage { std::string icon{}; enums::EntityCategory entity_category{}; bool supports_stop{false}; - std::string device_name{}; + std::string device_id{}; void encode(ProtoWriteBuffer buffer) const override; #ifdef HAS_PROTO_MESSAGE_DUMP void dump_to(std::string &out) const override; diff --git a/esphome/components/device/__init__.py b/esphome/components/devices/__init__.py similarity index 71% rename from esphome/components/device/__init__.py rename to esphome/components/devices/__init__.py index c7ecbb31f1..c8249f6f91 100644 --- a/esphome/components/device/__init__.py +++ b/esphome/components/devices/__init__.py @@ -1,9 +1,8 @@ -from esphome import config_validation as cv -from esphome import codegen as cg +from esphome import codegen as cg, config_validation as cv from esphome.const import CONF_ID, CONF_NAME -# ns = cg.esphome_ns.namespace("device") -# DeviceClass = ns.Class("Device") +# ns = cg.esphome_ns.namespace("devices") +# DeviceClass = ns.Class("SubDevice") StringRef = cg.esphome_ns.struct("StringRef") MULTI_CONF = True @@ -24,4 +23,4 @@ async def to_code(config): config[CONF_ID], config[CONF_NAME], ) - # cg.add_define("USE_DEVICE_ID") + cg.add_define("USE_SUB_DEVICE") diff --git a/esphome/components/device/device.h b/esphome/components/devices/devices.h similarity index 62% rename from esphome/components/device/device.h rename to esphome/components/devices/devices.h index 49a7b88704..80d7d9923c 100644 --- a/esphome/components/device/device.h +++ b/esphome/components/devices/devices.h @@ -1,16 +1,18 @@ #pragma once namespace esphome { -namespace device { +namespace devices { -class Device { +class SubDevice { public: void set_name(std::string name) { name_ = name; } std::string get_name(void) { return name_; } protected: + // std::string id_ = ""; std::string name_ = ""; + std::string suggested_area_ = ""; }; -} // namespace device +} // namespace devices } // namespace esphome diff --git a/esphome/core/application.h b/esphome/core/application.h index 462beb1f25..4336ea43d5 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -9,6 +9,9 @@ #include "esphome/core/preferences.h" #include "esphome/core/scheduler.h" +#ifdef USE_SUB_DEVICE +#include "esphome/components/devices/devices.h" +#endif #ifdef USE_BINARY_SENSOR #include "esphome/components/binary_sensor/binary_sensor.h" #endif @@ -97,6 +100,10 @@ class Application { this->compilation_time_ = compilation_time; } +#ifdef USE_SUB_DEVICE + void register_sub_device(devices::SubDevice *sub_device) { this->sub_devices_.push_back(sub_device); } +#endif + #ifdef USE_BINARY_SENSOR void register_binary_sensor(binary_sensor::BinarySensor *binary_sensor) { this->binary_sensors_.push_back(binary_sensor); @@ -243,6 +250,16 @@ class Application { uint32_t get_app_state() const { return this->app_state_; } +#ifdef USE_SUB_DEVICE + const std::vector &get_sub_devices() { return this->sub_devices_; } + // devices::SubDevice *get_sub_device_by_key(uint32_t key, bool include_internal = false) { + // for (auto *obj : this->sub_devices_) { + // if (obj->get_object_id_hash() == key && (include_internal || !obj->is_internal())) + // return obj; + // } + // return nullptr; + // } +#endif #ifdef USE_BINARY_SENSOR const std::vector &get_binary_sensors() { return this->binary_sensors_; } binary_sensor::BinarySensor *get_binary_sensor_by_key(uint32_t key, bool include_internal = false) { @@ -473,6 +490,9 @@ class Application { std::vector components_{}; std::vector looping_components_{}; +#ifdef USE_SUB_DEVICE + std::vector sub_devices_{}; +#endif #ifdef USE_BINARY_SENSOR std::vector binary_sensors_{}; #endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 64de41f23a..464ee800d4 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -99,6 +99,7 @@ #define USE_SELECT #define USE_SENSOR #define USE_STATUS_LED +#define USE_SUB_DEVICE #define USE_SWITCH #define USE_TEXT #define USE_TEXT_SENSOR diff --git a/esphome/core/entity_base.cpp b/esphome/core/entity_base.cpp index 15864e793c..a08cab622a 100644 --- a/esphome/core/entity_base.cpp +++ b/esphome/core/entity_base.cpp @@ -36,13 +36,13 @@ std::string EntityBase::get_icon() const { void EntityBase::set_icon(const char *icon) { this->icon_c_str_ = icon; } // Entity Device Name -StringRef EntityBase::get_device_name() const { - if (this->device_name_.empty()) { +StringRef EntityBase::get_device_id() const { + if (this->device_id_.empty()) { return StringRef(""); } - return this->device_name_; + return this->device_id_; } -void EntityBase::set_device_name(const StringRef *device_name) { this->device_name_ = *device_name; } +void EntityBase::set_device_id(const StringRef *device_id) { this->device_id_ = *device_id; } // Entity Category EntityCategory EntityBase::get_entity_category() const { return this->entity_category_; } diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 0f6b222efd..6975c524f6 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -48,8 +48,8 @@ class EntityBase { void set_icon(const char *icon); // Get/set this entity's device name - StringRef get_device_name() const; - void set_device_name(const StringRef *device_name); + StringRef get_device_id() const; + void set_device_id(const StringRef *device_id); protected: /// The hash_base() function has been deprecated. It is kept in this @@ -65,7 +65,7 @@ class EntityBase { bool internal_{false}; bool disabled_by_default_{false}; EntityCategory entity_category_{ENTITY_CATEGORY_NONE}; - StringRef device_name_; + StringRef device_id_; }; class EntityBase_DeviceClass { // NOLINT(readability-identifier-naming) diff --git a/esphome/cpp_helpers.py b/esphome/cpp_helpers.py index afd951b504..df191bafe2 100644 --- a/esphome/cpp_helpers.py +++ b/esphome/cpp_helpers.py @@ -89,6 +89,10 @@ async def register_component(var, config): return var +# async def register_sub_device(var, value): +# pass + + async def register_parented(var, value): if isinstance(value, ID): paren = await get_variable(value) @@ -113,7 +117,7 @@ async def setup_entity(var, config): add(var.set_entity_category(config[CONF_ENTITY_CATEGORY])) if CONF_DEVICE_ID in config: parent = await get_variable(config[CONF_DEVICE_ID]) - add(var.set_device_name(parent)) + add(var.set_device_id(parent)) def extract_registry_entry_config( diff --git a/tests/components/device/common.yaml b/tests/components/device/common.yaml index 0f24038167..232bb631c9 100644 --- a/tests/components/device/common.yaml +++ b/tests/components/device/common.yaml @@ -1,4 +1,4 @@ -device: +devices: - id: other_device name: Another device