mirror of
https://github.com/esphome/esphome.git
synced 2026-07-11 01:15:33 +00:00
move device class strings to PROGMEM on ESP8266
Same treatment as icons in #14437. Device class strings were in .rodata (RAM on ESP8266). Now stored as individual PROGMEM char arrays. - Add get_device_class_to(std::span<char, MAX_DEVICE_CLASS_LENGTH>) buffer API matching get_icon_to() pattern - Add fill_and_encode_entity_info_with_device_class() wrapper to deduplicate buffer handling across 10 API entity types - Centralize MQTT device_class in send_discovery_() lambda where buffer lifetime outlives ArduinoJson serialization - Deprecate get_device_class_ref()/get_device_class() on non-ESP8266 - static_assert error on ESP8266 directing to get_device_class_to() - Update all callers: api, mqtt, web_server, log helper
This commit is contained in:
@@ -413,10 +413,9 @@ uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConn
|
||||
uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
|
||||
auto *binary_sensor = static_cast<binary_sensor::BinarySensor *>(entity);
|
||||
ListEntitiesBinarySensorResponse msg;
|
||||
msg.device_class = binary_sensor->get_device_class_ref();
|
||||
msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor();
|
||||
return fill_and_encode_entity_info(binary_sensor, msg, ListEntitiesBinarySensorResponse::MESSAGE_TYPE, conn,
|
||||
remaining_size);
|
||||
return fill_and_encode_entity_info_with_device_class(
|
||||
binary_sensor, msg, msg.device_class, ListEntitiesBinarySensorResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -442,8 +441,8 @@ uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *c
|
||||
msg.supports_position = traits.get_supports_position();
|
||||
msg.supports_tilt = traits.get_supports_tilt();
|
||||
msg.supports_stop = traits.get_supports_stop();
|
||||
msg.device_class = cover->get_device_class_ref();
|
||||
return fill_and_encode_entity_info(cover, msg, ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
return fill_and_encode_entity_info_with_device_class(cover, msg, msg.device_class,
|
||||
ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
}
|
||||
void APIConnection::on_cover_command_request(const CoverCommandRequest &msg) {
|
||||
ENTITY_COMMAND_MAKE_CALL(cover::Cover, cover, cover)
|
||||
@@ -608,9 +607,9 @@ uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection *
|
||||
msg.unit_of_measurement = sensor->get_unit_of_measurement_ref();
|
||||
msg.accuracy_decimals = sensor->get_accuracy_decimals();
|
||||
msg.force_update = sensor->get_force_update();
|
||||
msg.device_class = sensor->get_device_class_ref();
|
||||
msg.state_class = static_cast<enums::SensorStateClass>(sensor->get_state_class());
|
||||
return fill_and_encode_entity_info(sensor, msg, ListEntitiesSensorResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
return fill_and_encode_entity_info_with_device_class(sensor, msg, msg.device_class,
|
||||
ListEntitiesSensorResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -630,8 +629,8 @@ uint16_t APIConnection::try_send_switch_info(EntityBase *entity, APIConnection *
|
||||
auto *a_switch = static_cast<switch_::Switch *>(entity);
|
||||
ListEntitiesSwitchResponse msg;
|
||||
msg.assumed_state = a_switch->assumed_state();
|
||||
msg.device_class = a_switch->get_device_class_ref();
|
||||
return fill_and_encode_entity_info(a_switch, msg, ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
return fill_and_encode_entity_info_with_device_class(a_switch, msg, msg.device_class,
|
||||
ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
}
|
||||
void APIConnection::on_switch_command_request(const SwitchCommandRequest &msg) {
|
||||
ENTITY_COMMAND_GET(switch_::Switch, a_switch, switch)
|
||||
@@ -660,9 +659,8 @@ uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnec
|
||||
uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
|
||||
auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity);
|
||||
ListEntitiesTextSensorResponse msg;
|
||||
msg.device_class = text_sensor->get_device_class_ref();
|
||||
return fill_and_encode_entity_info(text_sensor, msg, ListEntitiesTextSensorResponse::MESSAGE_TYPE, conn,
|
||||
remaining_size);
|
||||
return fill_and_encode_entity_info_with_device_class(
|
||||
text_sensor, msg, msg.device_class, ListEntitiesTextSensorResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -775,11 +773,11 @@ uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection *
|
||||
ListEntitiesNumberResponse msg;
|
||||
msg.unit_of_measurement = number->get_unit_of_measurement_ref();
|
||||
msg.mode = static_cast<enums::NumberMode>(number->traits.get_mode());
|
||||
msg.device_class = number->get_device_class_ref();
|
||||
msg.min_value = number->traits.get_min_value();
|
||||
msg.max_value = number->traits.get_max_value();
|
||||
msg.step = number->traits.get_step();
|
||||
return fill_and_encode_entity_info(number, msg, ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
return fill_and_encode_entity_info_with_device_class(number, msg, msg.device_class,
|
||||
ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
}
|
||||
void APIConnection::on_number_command_request(const NumberCommandRequest &msg) {
|
||||
ENTITY_COMMAND_MAKE_CALL(number::Number, number, number)
|
||||
@@ -924,8 +922,8 @@ void APIConnection::on_select_command_request(const SelectCommandRequest &msg) {
|
||||
uint16_t APIConnection::try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
|
||||
auto *button = static_cast<button::Button *>(entity);
|
||||
ListEntitiesButtonResponse msg;
|
||||
msg.device_class = button->get_device_class_ref();
|
||||
return fill_and_encode_entity_info(button, msg, ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
return fill_and_encode_entity_info_with_device_class(button, msg, msg.device_class,
|
||||
ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
}
|
||||
void esphome::api::APIConnection::on_button_command_request(const ButtonCommandRequest &msg) {
|
||||
ENTITY_COMMAND_GET(button::Button, button, button)
|
||||
@@ -985,11 +983,11 @@ uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *c
|
||||
auto *valve = static_cast<valve::Valve *>(entity);
|
||||
ListEntitiesValveResponse msg;
|
||||
auto traits = valve->get_traits();
|
||||
msg.device_class = valve->get_device_class_ref();
|
||||
msg.assumed_state = traits.get_is_assumed_state();
|
||||
msg.supports_position = traits.get_supports_position();
|
||||
msg.supports_stop = traits.get_supports_stop();
|
||||
return fill_and_encode_entity_info(valve, msg, ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
return fill_and_encode_entity_info_with_device_class(valve, msg, msg.device_class,
|
||||
ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
}
|
||||
void APIConnection::on_valve_command_request(const ValveCommandRequest &msg) {
|
||||
ENTITY_COMMAND_MAKE_CALL(valve::Valve, valve, valve)
|
||||
@@ -1433,9 +1431,9 @@ uint16_t APIConnection::try_send_event_response(event::Event *event, StringRef e
|
||||
uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
|
||||
auto *event = static_cast<event::Event *>(entity);
|
||||
ListEntitiesEventResponse msg;
|
||||
msg.device_class = event->get_device_class_ref();
|
||||
msg.event_types = &event->get_event_types();
|
||||
return fill_and_encode_entity_info(event, msg, ListEntitiesEventResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
return fill_and_encode_entity_info_with_device_class(event, msg, msg.device_class,
|
||||
ListEntitiesEventResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1491,8 +1489,8 @@ uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection
|
||||
uint16_t APIConnection::try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) {
|
||||
auto *update = static_cast<update::UpdateEntity *>(entity);
|
||||
ListEntitiesUpdateResponse msg;
|
||||
msg.device_class = update->get_device_class_ref();
|
||||
return fill_and_encode_entity_info(update, msg, ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
return fill_and_encode_entity_info_with_device_class(update, msg, msg.device_class,
|
||||
ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size);
|
||||
}
|
||||
void APIConnection::on_update_command_request(const UpdateCommandRequest &msg) {
|
||||
ENTITY_COMMAND_GET(update::UpdateEntity, update, update)
|
||||
|
||||
@@ -359,6 +359,15 @@ class APIConnection final : public APIServerConnectionBase {
|
||||
return encode_message_to_buffer(msg, message_type, conn, remaining_size);
|
||||
}
|
||||
|
||||
// Wrapper for entity types that have a device_class field
|
||||
static uint16_t fill_and_encode_entity_info_with_device_class(EntityBase *entity, InfoResponseProtoMessage &msg,
|
||||
StringRef &device_class_field, uint8_t message_type,
|
||||
APIConnection *conn, uint32_t remaining_size) {
|
||||
char dc_buf[MAX_DEVICE_CLASS_LENGTH];
|
||||
device_class_field = StringRef(entity->get_device_class_to(dc_buf));
|
||||
return fill_and_encode_entity_info(entity, msg, message_type, conn, remaining_size);
|
||||
}
|
||||
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
// Helper to check voice assistant validity and connection ownership
|
||||
inline bool check_voice_assistant_api_connection_() const;
|
||||
|
||||
@@ -29,12 +29,6 @@ MQTTBinarySensorComponent::MQTTBinarySensorComponent(binary_sensor::BinarySensor
|
||||
}
|
||||
|
||||
void MQTTBinarySensorComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
||||
const auto device_class = this->binary_sensor_->get_device_class_ref();
|
||||
if (!device_class.empty()) {
|
||||
root[MQTT_DEVICE_CLASS] = device_class;
|
||||
}
|
||||
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
||||
if (this->binary_sensor_->is_status_binary_sensor())
|
||||
root[MQTT_PAYLOAD_ON] = mqtt::global_mqtt_client->get_availability().payload_available;
|
||||
if (this->binary_sensor_->is_status_binary_sensor())
|
||||
|
||||
@@ -30,13 +30,7 @@ void MQTTButtonComponent::dump_config() {
|
||||
}
|
||||
|
||||
void MQTTButtonComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
||||
config.state_topic = false;
|
||||
const auto device_class = this->button_->get_device_class_ref();
|
||||
if (!device_class.empty()) {
|
||||
root[MQTT_DEVICE_CLASS] = device_class;
|
||||
}
|
||||
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
||||
}
|
||||
|
||||
MQTT_COMPONENT_TYPE(MQTTButtonComponent, "button")
|
||||
|
||||
@@ -214,6 +214,11 @@ bool MQTTComponent::send_discovery_() {
|
||||
if (icon[0] != '\0') {
|
||||
root[MQTT_ICON] = icon;
|
||||
}
|
||||
char dc_buf[MAX_DEVICE_CLASS_LENGTH];
|
||||
const char *dc = this->get_entity()->get_device_class_to(dc_buf);
|
||||
if (dc[0] != '\0') {
|
||||
root[MQTT_DEVICE_CLASS] = dc;
|
||||
}
|
||||
|
||||
const auto entity_category = this->get_entity()->get_entity_category();
|
||||
if (entity_category != ENTITY_CATEGORY_NONE) {
|
||||
|
||||
@@ -90,13 +90,6 @@ void MQTTCoverComponent::dump_config() {
|
||||
}
|
||||
}
|
||||
void MQTTCoverComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
||||
const auto device_class = this->cover_->get_device_class_ref();
|
||||
if (!device_class.empty()) {
|
||||
root[MQTT_DEVICE_CLASS] = device_class;
|
||||
}
|
||||
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
||||
|
||||
auto traits = this->cover_->get_traits();
|
||||
if (traits.get_is_assumed_state()) {
|
||||
root[MQTT_OPTIMISTIC] = true;
|
||||
|
||||
@@ -20,13 +20,6 @@ void MQTTEventComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConf
|
||||
for (const auto &event_type : this->event_->get_event_types())
|
||||
event_types.add(event_type);
|
||||
|
||||
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
||||
const auto device_class = this->event_->get_device_class_ref();
|
||||
if (!device_class.empty()) {
|
||||
root[MQTT_DEVICE_CLASS] = device_class;
|
||||
}
|
||||
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
||||
|
||||
config.command_topic = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,10 +57,6 @@ void MQTTNumberComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCon
|
||||
root[MQTT_MODE] =
|
||||
NumberMqttModeStrings::get_progmem_str(static_cast<uint8_t>(mode), static_cast<uint8_t>(NUMBER_MODE_BOX));
|
||||
}
|
||||
const auto device_class = this->number_->get_device_class_ref();
|
||||
if (!device_class.empty()) {
|
||||
root[MQTT_DEVICE_CLASS] = device_class;
|
||||
}
|
||||
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
||||
|
||||
config.command_topic = true;
|
||||
|
||||
@@ -44,11 +44,6 @@ void MQTTSensorComponent::disable_expire_after() { this->expire_after_ = 0; }
|
||||
|
||||
void MQTTSensorComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
||||
const auto device_class = this->sensor_->get_device_class_ref();
|
||||
if (!device_class.empty()) {
|
||||
root[MQTT_DEVICE_CLASS] = device_class;
|
||||
}
|
||||
|
||||
if (this->sensor_->has_accuracy_decimals()) {
|
||||
root[MQTT_SUGGESTED_DISPLAY_PRECISION] = this->sensor_->get_accuracy_decimals();
|
||||
}
|
||||
|
||||
@@ -14,12 +14,6 @@ using namespace esphome::text_sensor;
|
||||
|
||||
MQTTTextSensor::MQTTTextSensor(TextSensor *sensor) : sensor_(sensor) {}
|
||||
void MQTTTextSensor::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
||||
const auto device_class = this->sensor_->get_device_class_ref();
|
||||
if (!device_class.empty()) {
|
||||
root[MQTT_DEVICE_CLASS] = device_class;
|
||||
}
|
||||
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
||||
config.command_topic = false;
|
||||
}
|
||||
void MQTTTextSensor::setup() {
|
||||
|
||||
@@ -63,13 +63,6 @@ void MQTTValveComponent::dump_config() {
|
||||
}
|
||||
}
|
||||
void MQTTValveComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
|
||||
// NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
|
||||
const auto device_class = this->valve_->get_device_class_ref();
|
||||
if (!device_class.empty()) {
|
||||
root[MQTT_DEVICE_CLASS] = device_class;
|
||||
}
|
||||
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)
|
||||
|
||||
auto traits = this->valve_->get_traits();
|
||||
if (traits.get_is_assumed_state()) {
|
||||
root[MQTT_OPTIMISTIC] = true;
|
||||
|
||||
@@ -2137,7 +2137,8 @@ json::SerializationBuffer<> WebServer::event_json_(event::Event *obj, StringRef
|
||||
for (const char *event_type : obj->get_event_types()) {
|
||||
event_types.add(event_type);
|
||||
}
|
||||
root[ESPHOME_F("device_class")] = obj->get_device_class_ref();
|
||||
char dc_buf[MAX_DEVICE_CLASS_LENGTH];
|
||||
root[ESPHOME_F("device_class")] = obj->get_device_class_to(dc_buf);
|
||||
this->add_sorting_info_(root, obj);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,27 @@ __attribute__((weak)) const char *entity_device_class_lookup(uint8_t) { return "
|
||||
__attribute__((weak)) const char *entity_uom_lookup(uint8_t) { return ""; }
|
||||
__attribute__((weak)) const char *entity_icon_lookup(uint8_t) { return ""; }
|
||||
|
||||
// Entity device class (from index)
|
||||
// Entity device class — buffer-based API for PROGMEM safety on ESP8266
|
||||
const char *EntityBase::get_device_class_to([[maybe_unused]] std::span<char, MAX_DEVICE_CLASS_LENGTH> buffer) const {
|
||||
#ifdef USE_ENTITY_DEVICE_CLASS
|
||||
const uint8_t idx = this->device_class_idx_;
|
||||
#else
|
||||
const uint8_t idx = 0;
|
||||
#endif
|
||||
#ifdef USE_ESP8266
|
||||
if (idx == 0)
|
||||
return "";
|
||||
const char *dc = entity_device_class_lookup(idx);
|
||||
ESPHOME_strncpy_P(buffer.data(), dc, buffer.size() - 1);
|
||||
buffer[buffer.size() - 1] = '\0';
|
||||
return buffer.data();
|
||||
#else
|
||||
return entity_device_class_lookup(idx);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef USE_ESP8266
|
||||
// Deprecated device class accessors — not available on ESP8266 (rodata is RAM)
|
||||
StringRef EntityBase::get_device_class_ref() const {
|
||||
#ifdef USE_ENTITY_DEVICE_CLASS
|
||||
return StringRef(entity_device_class_lookup(this->device_class_idx_));
|
||||
@@ -59,7 +79,14 @@ StringRef EntityBase::get_device_class_ref() const {
|
||||
return StringRef(entity_device_class_lookup(0));
|
||||
#endif
|
||||
}
|
||||
std::string EntityBase::get_device_class() const { return std::string(this->get_device_class_ref().c_str()); }
|
||||
std::string EntityBase::get_device_class() const {
|
||||
#ifdef USE_ENTITY_DEVICE_CLASS
|
||||
return std::string(entity_device_class_lookup(this->device_class_idx_));
|
||||
#else
|
||||
return std::string(entity_device_class_lookup(0));
|
||||
#endif
|
||||
}
|
||||
#endif // !USE_ESP8266
|
||||
|
||||
// Entity unit of measurement (from index)
|
||||
StringRef EntityBase::get_unit_of_measurement_ref() const {
|
||||
@@ -191,8 +218,10 @@ void log_entity_icon(const char *tag, const char *prefix, const EntityBase &obj)
|
||||
#endif
|
||||
|
||||
void log_entity_device_class(const char *tag, const char *prefix, const EntityBase &obj) {
|
||||
if (!obj.get_device_class_ref().empty()) {
|
||||
ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj.get_device_class_ref().c_str());
|
||||
char dc_buf[MAX_DEVICE_CLASS_LENGTH];
|
||||
const char *dc = obj.get_device_class_to(dc_buf);
|
||||
if (dc[0] != '\0') {
|
||||
ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, dc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,11 @@ static constexpr size_t OBJECT_ID_MAX_LEN = 128;
|
||||
// Maximum state length that Home Assistant will accept without raising ValueError
|
||||
static constexpr size_t MAX_STATE_LEN = 255;
|
||||
|
||||
// Maximum device class string buffer size (47 chars + null terminator)
|
||||
// Longest standard device class: "volatile_organic_compounds_parts" (32 chars)
|
||||
// Device classes are stored in PROGMEM; on ESP8266 they must be copied to a stack buffer.
|
||||
static constexpr size_t MAX_DEVICE_CLASS_LENGTH = 48;
|
||||
|
||||
// Maximum icon string buffer size (63 chars + null terminator)
|
||||
// Icons are stored in PROGMEM; on ESP8266 they must be copied to a stack buffer.
|
||||
static constexpr size_t MAX_ICON_LENGTH = 64;
|
||||
@@ -113,13 +118,31 @@ class EntityBase {
|
||||
#endif
|
||||
}
|
||||
|
||||
// Get device class as StringRef (from packed index)
|
||||
// Get this entity's device class into a stack buffer.
|
||||
// On ESP32: returns pointer to PROGMEM string directly (buffer unused).
|
||||
// On ESP8266: copies from PROGMEM to buffer, returns buffer pointer.
|
||||
const char *get_device_class_to(std::span<char, MAX_DEVICE_CLASS_LENGTH> buffer) const;
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
// On ESP8266, rodata is RAM. Device classes are in PROGMEM and cannot be accessed
|
||||
// directly as const char*. Use get_device_class_to() with a stack buffer instead.
|
||||
template<typename T = int> StringRef get_device_class_ref() const {
|
||||
static_assert(sizeof(T) == 0, "get_device_class_ref() unavailable on ESP8266 (rodata is RAM). "
|
||||
"Use get_device_class_to() with a stack buffer.");
|
||||
return StringRef("");
|
||||
}
|
||||
template<typename T = int> std::string get_device_class() const {
|
||||
static_assert(sizeof(T) == 0, "get_device_class() unavailable on ESP8266 (rodata is RAM). "
|
||||
"Use get_device_class_to() with a stack buffer.");
|
||||
return "";
|
||||
}
|
||||
#else
|
||||
// Deprecated: use get_device_class_to() instead. Device classes are in PROGMEM.
|
||||
ESPDEPRECATED("Use get_device_class_to() instead. Will be removed in ESPHome 2026.9.0", "2026.3.0")
|
||||
StringRef get_device_class_ref() const;
|
||||
/// Get the device class as std::string (deprecated, prefer get_device_class_ref())
|
||||
ESPDEPRECATED("Use get_device_class_ref() instead for better performance (avoids string copy). Will be removed in "
|
||||
"ESPHome 2026.9.0",
|
||||
"2026.3.0")
|
||||
ESPDEPRECATED("Use get_device_class_to() instead. Will be removed in ESPHome 2026.9.0", "2026.3.0")
|
||||
std::string get_device_class() const;
|
||||
#endif
|
||||
// Get unit of measurement as StringRef (from packed index)
|
||||
StringRef get_unit_of_measurement_ref() const;
|
||||
/// Get the unit of measurement as std::string (deprecated, prefer get_unit_of_measurement_ref())
|
||||
|
||||
@@ -131,7 +131,7 @@ def _generate_category_code(
|
||||
|
||||
|
||||
_CATEGORY_CONFIGS = (
|
||||
("ENTITY_DC_TABLE", "entity_device_class_lookup", "device_classes", False),
|
||||
("ENTITY_DC_TABLE", "entity_device_class_lookup", "device_classes", True),
|
||||
("ENTITY_UOM_TABLE", "entity_uom_lookup", "units", False),
|
||||
("ENTITY_ICON_TABLE", "entity_icon_lookup", "icons", True),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user