Allow entity names to be set to None (#4607)

* Allow entity names to be set to None so they take on the device friendly_name automatically

* Use empty
This commit is contained in:
Jesse Hills 2023-03-27 11:49:09 +13:00 committed by GitHub
parent 56504692af
commit c2756d57d8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 24 deletions

View file

@ -180,6 +180,7 @@ bool APIConnection::send_binary_sensor_info(binary_sensor::BinarySensor *binary_
ListEntitiesBinarySensorResponse msg; ListEntitiesBinarySensorResponse msg;
msg.object_id = binary_sensor->get_object_id(); msg.object_id = binary_sensor->get_object_id();
msg.key = binary_sensor->get_object_id_hash(); msg.key = binary_sensor->get_object_id_hash();
if (binary_sensor->has_own_name())
msg.name = binary_sensor->get_name(); msg.name = binary_sensor->get_name();
msg.unique_id = get_default_unique_id("binary_sensor", binary_sensor); msg.unique_id = get_default_unique_id("binary_sensor", binary_sensor);
msg.device_class = binary_sensor->get_device_class(); msg.device_class = binary_sensor->get_device_class();
@ -212,6 +213,7 @@ bool APIConnection::send_cover_info(cover::Cover *cover) {
ListEntitiesCoverResponse msg; ListEntitiesCoverResponse msg;
msg.key = cover->get_object_id_hash(); msg.key = cover->get_object_id_hash();
msg.object_id = cover->get_object_id(); msg.object_id = cover->get_object_id();
if (cover->has_own_name())
msg.name = cover->get_name(); msg.name = cover->get_name();
msg.unique_id = get_default_unique_id("cover", cover); msg.unique_id = get_default_unique_id("cover", cover);
msg.assumed_state = traits.get_is_assumed_state(); msg.assumed_state = traits.get_is_assumed_state();
@ -275,6 +277,7 @@ bool APIConnection::send_fan_info(fan::Fan *fan) {
ListEntitiesFanResponse msg; ListEntitiesFanResponse msg;
msg.key = fan->get_object_id_hash(); msg.key = fan->get_object_id_hash();
msg.object_id = fan->get_object_id(); msg.object_id = fan->get_object_id();
if (fan->has_own_name())
msg.name = fan->get_name(); msg.name = fan->get_name();
msg.unique_id = get_default_unique_id("fan", fan); msg.unique_id = get_default_unique_id("fan", fan);
msg.supports_oscillation = traits.supports_oscillation(); msg.supports_oscillation = traits.supports_oscillation();
@ -337,6 +340,7 @@ bool APIConnection::send_light_info(light::LightState *light) {
ListEntitiesLightResponse msg; ListEntitiesLightResponse msg;
msg.key = light->get_object_id_hash(); msg.key = light->get_object_id_hash();
msg.object_id = light->get_object_id(); msg.object_id = light->get_object_id();
if (light->has_own_name())
msg.name = light->get_name(); msg.name = light->get_name();
msg.unique_id = get_default_unique_id("light", light); msg.unique_id = get_default_unique_id("light", light);
@ -418,6 +422,7 @@ bool APIConnection::send_sensor_info(sensor::Sensor *sensor) {
ListEntitiesSensorResponse msg; ListEntitiesSensorResponse msg;
msg.key = sensor->get_object_id_hash(); msg.key = sensor->get_object_id_hash();
msg.object_id = sensor->get_object_id(); msg.object_id = sensor->get_object_id();
if (sensor->has_own_name())
msg.name = sensor->get_name(); msg.name = sensor->get_name();
msg.unique_id = sensor->unique_id(); msg.unique_id = sensor->unique_id();
if (msg.unique_id.empty()) if (msg.unique_id.empty())
@ -448,6 +453,7 @@ bool APIConnection::send_switch_info(switch_::Switch *a_switch) {
ListEntitiesSwitchResponse msg; ListEntitiesSwitchResponse msg;
msg.key = a_switch->get_object_id_hash(); msg.key = a_switch->get_object_id_hash();
msg.object_id = a_switch->get_object_id(); msg.object_id = a_switch->get_object_id();
if (a_switch->has_own_name())
msg.name = a_switch->get_name(); msg.name = a_switch->get_name();
msg.unique_id = get_default_unique_id("switch", a_switch); msg.unique_id = get_default_unique_id("switch", a_switch);
msg.icon = a_switch->get_icon(); msg.icon = a_switch->get_icon();
@ -533,6 +539,7 @@ bool APIConnection::send_climate_info(climate::Climate *climate) {
ListEntitiesClimateResponse msg; ListEntitiesClimateResponse msg;
msg.key = climate->get_object_id_hash(); msg.key = climate->get_object_id_hash();
msg.object_id = climate->get_object_id(); msg.object_id = climate->get_object_id();
if (climate->has_own_name())
msg.name = climate->get_name(); msg.name = climate->get_name();
msg.unique_id = get_default_unique_id("climate", climate); msg.unique_id = get_default_unique_id("climate", climate);
@ -611,6 +618,7 @@ bool APIConnection::send_number_info(number::Number *number) {
ListEntitiesNumberResponse msg; ListEntitiesNumberResponse msg;
msg.key = number->get_object_id_hash(); msg.key = number->get_object_id_hash();
msg.object_id = number->get_object_id(); msg.object_id = number->get_object_id();
if (number->has_own_name())
msg.name = number->get_name(); msg.name = number->get_name();
msg.unique_id = get_default_unique_id("number", number); msg.unique_id = get_default_unique_id("number", number);
msg.icon = number->get_icon(); msg.icon = number->get_icon();
@ -652,6 +660,7 @@ bool APIConnection::send_select_info(select::Select *select) {
ListEntitiesSelectResponse msg; ListEntitiesSelectResponse msg;
msg.key = select->get_object_id_hash(); msg.key = select->get_object_id_hash();
msg.object_id = select->get_object_id(); msg.object_id = select->get_object_id();
if (select->has_own_name())
msg.name = select->get_name(); msg.name = select->get_name();
msg.unique_id = get_default_unique_id("select", select); msg.unique_id = get_default_unique_id("select", select);
msg.icon = select->get_icon(); msg.icon = select->get_icon();
@ -679,6 +688,7 @@ bool APIConnection::send_button_info(button::Button *button) {
ListEntitiesButtonResponse msg; ListEntitiesButtonResponse msg;
msg.key = button->get_object_id_hash(); msg.key = button->get_object_id_hash();
msg.object_id = button->get_object_id(); msg.object_id = button->get_object_id();
if (button->has_own_name())
msg.name = button->get_name(); msg.name = button->get_name();
msg.unique_id = get_default_unique_id("button", button); msg.unique_id = get_default_unique_id("button", button);
msg.icon = button->get_icon(); msg.icon = button->get_icon();
@ -710,6 +720,7 @@ bool APIConnection::send_lock_info(lock::Lock *a_lock) {
ListEntitiesLockResponse msg; ListEntitiesLockResponse msg;
msg.key = a_lock->get_object_id_hash(); msg.key = a_lock->get_object_id_hash();
msg.object_id = a_lock->get_object_id(); msg.object_id = a_lock->get_object_id();
if (a_lock->has_own_name())
msg.name = a_lock->get_name(); msg.name = a_lock->get_name();
msg.unique_id = get_default_unique_id("lock", a_lock); msg.unique_id = get_default_unique_id("lock", a_lock);
msg.icon = a_lock->get_icon(); msg.icon = a_lock->get_icon();
@ -755,6 +766,7 @@ bool APIConnection::send_media_player_info(media_player::MediaPlayer *media_play
ListEntitiesMediaPlayerResponse msg; ListEntitiesMediaPlayerResponse msg;
msg.key = media_player->get_object_id_hash(); msg.key = media_player->get_object_id_hash();
msg.object_id = media_player->get_object_id(); msg.object_id = media_player->get_object_id();
if (media_player->has_own_name())
msg.name = media_player->get_name(); msg.name = media_player->get_name();
msg.unique_id = get_default_unique_id("media_player", media_player); msg.unique_id = get_default_unique_id("media_player", media_player);
msg.icon = media_player->get_icon(); msg.icon = media_player->get_icon();
@ -799,6 +811,7 @@ bool APIConnection::send_camera_info(esp32_camera::ESP32Camera *camera) {
ListEntitiesCameraResponse msg; ListEntitiesCameraResponse msg;
msg.key = camera->get_object_id_hash(); msg.key = camera->get_object_id_hash();
msg.object_id = camera->get_object_id(); msg.object_id = camera->get_object_id();
if (camera->has_own_name())
msg.name = camera->get_name(); msg.name = camera->get_name();
msg.unique_id = get_default_unique_id("camera", camera); msg.unique_id = get_default_unique_id("camera", camera);
msg.disabled_by_default = camera->is_disabled_by_default(); msg.disabled_by_default = camera->is_disabled_by_default();

View file

@ -22,20 +22,12 @@ ESP32ImprovComponent = esp32_improv_ns.class_(
) )
def validate_none_(value):
if value in ("none", "None"):
return None
if cv.boolean(value) is False:
return None
raise cv.Invalid("Must be none")
CONFIG_SCHEMA = cv.Schema( CONFIG_SCHEMA = cv.Schema(
{ {
cv.GenerateID(): cv.declare_id(ESP32ImprovComponent), cv.GenerateID(): cv.declare_id(ESP32ImprovComponent),
cv.GenerateID(CONF_BLE_SERVER_ID): cv.use_id(esp32_ble_server.BLEServer), cv.GenerateID(CONF_BLE_SERVER_ID): cv.use_id(esp32_ble_server.BLEServer),
cv.Required(CONF_AUTHORIZER): cv.Any( cv.Required(CONF_AUTHORIZER): cv.Any(
validate_none_, cv.use_id(binary_sensor.BinarySensor) cv.none, cv.use_id(binary_sensor.BinarySensor)
), ),
cv.Optional(CONF_STATUS_INDICATOR): cv.use_id(output.BinaryOutput), cv.Optional(CONF_STATUS_INDICATOR): cv.use_id(output.BinaryOutput),
cv.Optional( cv.Optional(

View file

@ -1514,6 +1514,8 @@ def _entity_base_validator(config):
config[CONF_NAME] = id.id config[CONF_NAME] = id.id
config[CONF_INTERNAL] = True config[CONF_INTERNAL] = True
return config return config
if config[CONF_NAME] is None:
config[CONF_NAME] = ""
return config return config
@ -1573,6 +1575,23 @@ def validate_registry_entry(name, registry):
return validator return validator
def none(value):
if value in ("none", "None"):
return None
if boolean(value) is False:
return None
raise Invalid("Must be none")
def requires_friendly_name(message):
def validate(value):
if CORE.friendly_name is None:
raise Invalid(message)
return value
return validate
def validate_registry(name, registry): def validate_registry(name, registry):
return ensure_list(validate_registry_entry(name, registry)) return ensure_list(validate_registry_entry(name, registry))
@ -1632,7 +1651,15 @@ MQTT_COMMAND_COMPONENT_SCHEMA = MQTT_COMPONENT_SCHEMA.extend(
ENTITY_BASE_SCHEMA = Schema( ENTITY_BASE_SCHEMA = Schema(
{ {
Optional(CONF_NAME): string, Optional(CONF_NAME): Any(
All(
none,
requires_friendly_name(
"Name cannot be None when esphome->friendly_name is not set!"
),
),
string,
),
Optional(CONF_INTERNAL): boolean, Optional(CONF_INTERNAL): boolean,
Optional(CONF_DISABLED_BY_DEFAULT, default=False): boolean, Optional(CONF_DISABLED_BY_DEFAULT, default=False): boolean,
Optional(CONF_ICON): icon, Optional(CONF_ICON): icon,

View file

@ -1,4 +1,5 @@
#include "esphome/core/entity_base.h" #include "esphome/core/entity_base.h"
#include "esphome/core/application.h"
#include "esphome/core/helpers.h" #include "esphome/core/helpers.h"
namespace esphome { namespace esphome {
@ -10,7 +11,13 @@ EntityBase::EntityBase(std::string name) : name_(std::move(name)) { this->calc_o
// Entity Name // Entity Name
const std::string &EntityBase::get_name() const { return this->name_; } const std::string &EntityBase::get_name() const { return this->name_; }
void EntityBase::set_name(const std::string &name) { void EntityBase::set_name(const std::string &name) {
if (name.empty()) {
this->name_ = App.get_friendly_name();
this->has_own_name_ = false;
} else {
this->name_ = name; this->name_ = name;
this->has_own_name_ = true;
}
this->calc_object_id_(); this->calc_object_id_();
} }

View file

@ -21,6 +21,9 @@ class EntityBase {
const std::string &get_name() const; const std::string &get_name() const;
void set_name(const std::string &name); void set_name(const std::string &name);
// Get whether this Entity has its own name or it should use the device friendly_name.
bool has_own_name() const { return this->has_own_name_; }
// Get the sanitized name of this Entity as an ID. Caching it internally. // Get the sanitized name of this Entity as an ID. Caching it internally.
const std::string &get_object_id(); const std::string &get_object_id();
@ -52,6 +55,7 @@ class EntityBase {
void calc_object_id_(); void calc_object_id_();
std::string name_; std::string name_;
bool has_own_name_{false};
std::string object_id_; std::string object_id_;
const char *icon_c_str_{nullptr}; const char *icon_c_str_{nullptr};
uint32_t object_id_hash_; uint32_t object_id_hash_;