mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 21:44:55 +01:00
EntityBase: Move ObjectId to Flash (#4569)
* Move EntityBase Object Id from memory to flash. * Sprinkler use common `setup_entity` method. * Remove `EntityBase` from Sprinkler. * Support for entity names set to None * change so gh PR picks up commit. --------- Co-authored-by: Your Name <you@example.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
922344811f
commit
3ac7bf3761
5 changed files with 82 additions and 8 deletions
|
@ -16,7 +16,6 @@ void EntityBase::set_name(const char *name) {
|
||||||
} else {
|
} else {
|
||||||
this->has_own_name_ = true;
|
this->has_own_name_ = true;
|
||||||
}
|
}
|
||||||
this->calc_object_id_();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entity Internal
|
// Entity Internal
|
||||||
|
@ -41,13 +40,37 @@ EntityCategory EntityBase::get_entity_category() const { return this->entity_cat
|
||||||
void EntityBase::set_entity_category(EntityCategory entity_category) { this->entity_category_ = entity_category; }
|
void EntityBase::set_entity_category(EntityCategory entity_category) { this->entity_category_ = entity_category; }
|
||||||
|
|
||||||
// Entity Object ID
|
// Entity Object ID
|
||||||
const std::string &EntityBase::get_object_id() { return this->object_id_; }
|
std::string EntityBase::get_object_id() const {
|
||||||
|
// Check if `App.get_friendly_name()` is constant or dynamic.
|
||||||
|
if (!this->has_own_name_ && App.is_name_add_mac_suffix_enabled()) {
|
||||||
|
// `App.get_friendly_name()` is dynamic.
|
||||||
|
return str_sanitize(str_snake_case(App.get_friendly_name()));
|
||||||
|
} else {
|
||||||
|
// `App.get_friendly_name()` is constant.
|
||||||
|
if (this->object_id_c_str_ == nullptr) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return this->object_id_c_str_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void EntityBase::set_object_id(const char *object_id) {
|
||||||
|
this->object_id_c_str_ = object_id;
|
||||||
|
this->calc_object_id_();
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate Object ID Hash from Entity Name
|
// Calculate Object ID Hash from Entity Name
|
||||||
void EntityBase::calc_object_id_() {
|
void EntityBase::calc_object_id_() {
|
||||||
this->object_id_ = str_sanitize(str_snake_case(this->name_));
|
// Check if `App.get_friendly_name()` is constant or dynamic.
|
||||||
// FNV-1 hash
|
if (!this->has_own_name_ && App.is_name_add_mac_suffix_enabled()) {
|
||||||
this->object_id_hash_ = fnv1_hash(this->object_id_);
|
// `App.get_friendly_name()` is dynamic.
|
||||||
|
const auto object_id = str_sanitize(str_snake_case(App.get_friendly_name()));
|
||||||
|
// FNV-1 hash
|
||||||
|
this->object_id_hash_ = fnv1_hash(object_id);
|
||||||
|
} else {
|
||||||
|
// `App.get_friendly_name()` is constant.
|
||||||
|
// FNV-1 hash
|
||||||
|
this->object_id_hash_ = fnv1_hash(this->object_id_c_str_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
uint32_t EntityBase::get_object_id_hash() { return this->object_id_hash_; }
|
uint32_t EntityBase::get_object_id_hash() { return this->object_id_hash_; }
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,9 @@ class EntityBase {
|
||||||
// Get whether this Entity has its own name or it should use the device friendly_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_; }
|
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.
|
||||||
const std::string &get_object_id();
|
std::string get_object_id() const;
|
||||||
|
void set_object_id(const char *object_id);
|
||||||
|
|
||||||
// Get the unique Object ID of this Entity
|
// Get the unique Object ID of this Entity
|
||||||
uint32_t get_object_id_hash();
|
uint32_t get_object_id_hash();
|
||||||
|
@ -54,7 +55,7 @@ class EntityBase {
|
||||||
|
|
||||||
StringRef name_;
|
StringRef name_;
|
||||||
bool has_own_name_{false};
|
bool has_own_name_{false};
|
||||||
std::string object_id_;
|
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_;
|
||||||
bool internal_{false};
|
bool internal_{false};
|
||||||
|
|
|
@ -20,6 +20,7 @@ from esphome.types import ConfigType, ConfigFragmentType
|
||||||
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.util import Registry, RegistryEntry
|
from esphome.util import Registry, RegistryEntry
|
||||||
|
from esphome.helpers import snake_case, sanitize
|
||||||
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -101,6 +102,10 @@ async def register_parented(var, value):
|
||||||
async def setup_entity(var, config):
|
async def setup_entity(var, config):
|
||||||
"""Set up generic properties of an Entity"""
|
"""Set up generic properties of an Entity"""
|
||||||
add(var.set_name(config[CONF_NAME]))
|
add(var.set_name(config[CONF_NAME]))
|
||||||
|
if not config[CONF_NAME]:
|
||||||
|
add(var.set_object_id(sanitize(snake_case(CORE.friendly_name))))
|
||||||
|
else:
|
||||||
|
add(var.set_object_id(sanitize(snake_case(config[CONF_NAME]))))
|
||||||
add(var.set_disabled_by_default(config[CONF_DISABLED_BY_DEFAULT]))
|
add(var.set_disabled_by_default(config[CONF_DISABLED_BY_DEFAULT]))
|
||||||
if CONF_INTERNAL in config:
|
if CONF_INTERNAL in config:
|
||||||
add(var.set_internal(config[CONF_INTERNAL]))
|
add(var.set_internal(config[CONF_INTERNAL]))
|
||||||
|
|
|
@ -7,6 +7,7 @@ from pathlib import Path
|
||||||
from typing import Union
|
from typing import Union
|
||||||
import tempfile
|
import tempfile
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
import re
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -334,3 +335,13 @@ def add_class_to_obj(value, cls):
|
||||||
if type(value) is type_: # pylint: disable=unidiomatic-typecheck
|
if type(value) is type_: # pylint: disable=unidiomatic-typecheck
|
||||||
return add_class_to_obj(func(value), cls)
|
return add_class_to_obj(func(value), cls)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def snake_case(value):
|
||||||
|
"""Same behaviour as `helpers.cpp` method `str_snake_case`."""
|
||||||
|
return value.replace(" ", "_").lower()
|
||||||
|
|
||||||
|
|
||||||
|
def sanitize(value):
|
||||||
|
"""Same behaviour as `helpers.cpp` method `str_sanitize`."""
|
||||||
|
return re.sub("[^-_0-9a-zA-Z]", r"", value)
|
||||||
|
|
|
@ -229,3 +229,37 @@ def test_file_compare(fixture_path, file1, file2, expected):
|
||||||
actual = helpers.file_compare(path1, path2)
|
actual = helpers.file_compare(path1, path2)
|
||||||
|
|
||||||
assert actual == expected
|
assert actual == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"text, expected",
|
||||||
|
(
|
||||||
|
("foo", "foo"),
|
||||||
|
("foo bar", "foo_bar"),
|
||||||
|
("foo Bar", "foo_bar"),
|
||||||
|
("foo BAR", "foo_bar"),
|
||||||
|
("foo.bar", "foo.bar"),
|
||||||
|
("fooBAR", "foobar"),
|
||||||
|
("Foo-bar_EEK", "foo-bar_eek"),
|
||||||
|
(" foo", "__foo"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_snake_case(text, expected):
|
||||||
|
actual = helpers.snake_case(text)
|
||||||
|
|
||||||
|
assert actual == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"text, expected",
|
||||||
|
(
|
||||||
|
("foo_bar", "foo_bar"),
|
||||||
|
('!"§$%&/()=?foo_bar', "foo_bar"),
|
||||||
|
('foo_!"§$%&/()=?bar', "foo_bar"),
|
||||||
|
('foo_bar!"§$%&/()=?', "foo_bar"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_sanitize(text, expected):
|
||||||
|
actual = helpers.sanitize(text)
|
||||||
|
|
||||||
|
assert actual == expected
|
||||||
|
|
Loading…
Reference in a new issue