[mqtt] Use ESPHOME_F() for JSON strings to reduce ESP8266 RAM usage (#13049)

This commit is contained in:
J. Nick Koston
2026-01-07 08:26:21 -10:00
committed by GitHub
parent ed39a130a8
commit ef64226ed0
8 changed files with 109 additions and 108 deletions

View File

@@ -58,22 +58,22 @@ void MQTTAlarmControlPanelComponent::send_discovery(JsonObject root, mqtt::SendD
JsonArray supported_features = root[MQTT_SUPPORTED_FEATURES].to<JsonArray>();
const uint32_t acp_supported_features = this->alarm_control_panel_->get_supported_features();
if (acp_supported_features & ACP_FEAT_ARM_AWAY) {
supported_features.add("arm_away");
supported_features.add(ESPHOME_F("arm_away"));
}
if (acp_supported_features & ACP_FEAT_ARM_HOME) {
supported_features.add("arm_home");
supported_features.add(ESPHOME_F("arm_home"));
}
if (acp_supported_features & ACP_FEAT_ARM_NIGHT) {
supported_features.add("arm_night");
supported_features.add(ESPHOME_F("arm_night"));
}
if (acp_supported_features & ACP_FEAT_ARM_VACATION) {
supported_features.add("arm_vacation");
supported_features.add(ESPHOME_F("arm_vacation"));
}
if (acp_supported_features & ACP_FEAT_ARM_CUSTOM_BYPASS) {
supported_features.add("arm_custom_bypass");
supported_features.add(ESPHOME_F("arm_custom_bypass"));
}
if (acp_supported_features & ACP_FEAT_TRIGGER) {
supported_features.add("trigger");
supported_features.add(ESPHOME_F("trigger"));
}
root[MQTT_CODE_DISARM_REQUIRED] = this->alarm_control_panel_->get_requires_code();
root[MQTT_CODE_ARM_REQUIRED] = this->alarm_control_panel_->get_requires_code_to_arm();

View File

@@ -94,45 +94,46 @@ void MQTTClientComponent::send_device_info_() {
index++;
}
}
root["name"] = App.get_name();
root[ESPHOME_F("name")] = App.get_name();
if (!App.get_friendly_name().empty()) {
root["friendly_name"] = App.get_friendly_name();
root[ESPHOME_F("friendly_name")] = App.get_friendly_name();
}
#ifdef USE_API
root["port"] = api::global_api_server->get_port();
root[ESPHOME_F("port")] = api::global_api_server->get_port();
#endif
root["version"] = ESPHOME_VERSION;
root["mac"] = get_mac_address();
root[ESPHOME_F("version")] = ESPHOME_VERSION;
root[ESPHOME_F("mac")] = get_mac_address();
#ifdef USE_ESP8266
root["platform"] = "ESP8266";
root[ESPHOME_F("platform")] = ESPHOME_F("ESP8266");
#endif
#ifdef USE_ESP32
root["platform"] = "ESP32";
root[ESPHOME_F("platform")] = ESPHOME_F("ESP32");
#endif
#ifdef USE_LIBRETINY
root["platform"] = lt_cpu_get_model_name();
root[ESPHOME_F("platform")] = lt_cpu_get_model_name();
#endif
root["board"] = ESPHOME_BOARD;
root[ESPHOME_F("board")] = ESPHOME_BOARD;
#if defined(USE_WIFI)
root["network"] = "wifi";
root[ESPHOME_F("network")] = ESPHOME_F("wifi");
#elif defined(USE_ETHERNET)
root["network"] = "ethernet";
root[ESPHOME_F("network")] = ESPHOME_F("ethernet");
#endif
#ifdef ESPHOME_PROJECT_NAME
root["project_name"] = ESPHOME_PROJECT_NAME;
root["project_version"] = ESPHOME_PROJECT_VERSION;
root[ESPHOME_F("project_name")] = ESPHOME_PROJECT_NAME;
root[ESPHOME_F("project_version")] = ESPHOME_PROJECT_VERSION;
#endif // ESPHOME_PROJECT_NAME
#ifdef USE_DASHBOARD_IMPORT
root["package_import_url"] = dashboard_import::get_package_import_url();
root[ESPHOME_F("package_import_url")] = dashboard_import::get_package_import_url();
#endif
#ifdef USE_API_NOISE
root[api::global_api_server->get_noise_ctx().has_psk() ? "api_encryption" : "api_encryption_supported"] =
"Noise_NNpsk0_25519_ChaChaPoly_SHA256";
root[api::global_api_server->get_noise_ctx().has_psk() ? ESPHOME_F("api_encryption")
: ESPHOME_F("api_encryption_supported")] =
ESPHOME_F("Noise_NNpsk0_25519_ChaChaPoly_SHA256");
#endif
},
2, this->discovery_info_.retain);

View File

@@ -31,18 +31,18 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo
JsonArray modes = root[MQTT_MODES].to<JsonArray>();
// sort array for nice UI in HA
if (traits.supports_mode(CLIMATE_MODE_AUTO))
modes.add("auto");
modes.add("off");
modes.add(ESPHOME_F("auto"));
modes.add(ESPHOME_F("off"));
if (traits.supports_mode(CLIMATE_MODE_COOL))
modes.add("cool");
modes.add(ESPHOME_F("cool"));
if (traits.supports_mode(CLIMATE_MODE_HEAT))
modes.add("heat");
modes.add(ESPHOME_F("heat"));
if (traits.supports_mode(CLIMATE_MODE_FAN_ONLY))
modes.add("fan_only");
modes.add(ESPHOME_F("fan_only"));
if (traits.supports_mode(CLIMATE_MODE_DRY))
modes.add("dry");
modes.add(ESPHOME_F("dry"));
if (traits.supports_mode(CLIMATE_MODE_HEAT_COOL))
modes.add("heat_cool");
modes.add(ESPHOME_F("heat_cool"));
if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE |
climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) {
@@ -90,21 +90,21 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo
// preset_mode_state_topic
root[MQTT_PRESET_MODE_STATE_TOPIC] = this->get_preset_state_topic();
// presets
JsonArray presets = root["preset_modes"].to<JsonArray>();
JsonArray presets = root[ESPHOME_F("preset_modes")].to<JsonArray>();
if (traits.supports_preset(CLIMATE_PRESET_HOME))
presets.add("home");
presets.add(ESPHOME_F("home"));
if (traits.supports_preset(CLIMATE_PRESET_AWAY))
presets.add("away");
presets.add(ESPHOME_F("away"));
if (traits.supports_preset(CLIMATE_PRESET_BOOST))
presets.add("boost");
presets.add(ESPHOME_F("boost"));
if (traits.supports_preset(CLIMATE_PRESET_COMFORT))
presets.add("comfort");
presets.add(ESPHOME_F("comfort"));
if (traits.supports_preset(CLIMATE_PRESET_ECO))
presets.add("eco");
presets.add(ESPHOME_F("eco"));
if (traits.supports_preset(CLIMATE_PRESET_SLEEP))
presets.add("sleep");
presets.add(ESPHOME_F("sleep"));
if (traits.supports_preset(CLIMATE_PRESET_ACTIVITY))
presets.add("activity");
presets.add(ESPHOME_F("activity"));
for (const auto &preset : traits.get_supported_custom_presets())
presets.add(preset);
}
@@ -120,27 +120,27 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo
// fan_mode_state_topic
root[MQTT_FAN_MODE_STATE_TOPIC] = this->get_fan_mode_state_topic();
// fan_modes
JsonArray fan_modes = root["fan_modes"].to<JsonArray>();
JsonArray fan_modes = root[ESPHOME_F("fan_modes")].to<JsonArray>();
if (traits.supports_fan_mode(CLIMATE_FAN_ON))
fan_modes.add("on");
fan_modes.add(ESPHOME_F("on"));
if (traits.supports_fan_mode(CLIMATE_FAN_OFF))
fan_modes.add("off");
fan_modes.add(ESPHOME_F("off"));
if (traits.supports_fan_mode(CLIMATE_FAN_AUTO))
fan_modes.add("auto");
fan_modes.add(ESPHOME_F("auto"));
if (traits.supports_fan_mode(CLIMATE_FAN_LOW))
fan_modes.add("low");
fan_modes.add(ESPHOME_F("low"));
if (traits.supports_fan_mode(CLIMATE_FAN_MEDIUM))
fan_modes.add("medium");
fan_modes.add(ESPHOME_F("medium"));
if (traits.supports_fan_mode(CLIMATE_FAN_HIGH))
fan_modes.add("high");
fan_modes.add(ESPHOME_F("high"));
if (traits.supports_fan_mode(CLIMATE_FAN_MIDDLE))
fan_modes.add("middle");
fan_modes.add(ESPHOME_F("middle"));
if (traits.supports_fan_mode(CLIMATE_FAN_FOCUS))
fan_modes.add("focus");
fan_modes.add(ESPHOME_F("focus"));
if (traits.supports_fan_mode(CLIMATE_FAN_DIFFUSE))
fan_modes.add("diffuse");
fan_modes.add(ESPHOME_F("diffuse"));
if (traits.supports_fan_mode(CLIMATE_FAN_QUIET))
fan_modes.add("quiet");
fan_modes.add(ESPHOME_F("quiet"));
for (const auto &fan_mode : traits.get_supported_custom_fan_modes())
fan_modes.add(fan_mode);
}
@@ -151,15 +151,15 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo
// swing_mode_state_topic
root[MQTT_SWING_MODE_STATE_TOPIC] = this->get_swing_mode_state_topic();
// swing_modes
JsonArray swing_modes = root["swing_modes"].to<JsonArray>();
JsonArray swing_modes = root[ESPHOME_F("swing_modes")].to<JsonArray>();
if (traits.supports_swing_mode(CLIMATE_SWING_OFF))
swing_modes.add("off");
swing_modes.add(ESPHOME_F("off"));
if (traits.supports_swing_mode(CLIMATE_SWING_BOTH))
swing_modes.add("both");
swing_modes.add(ESPHOME_F("both"));
if (traits.supports_swing_mode(CLIMATE_SWING_VERTICAL))
swing_modes.add("vertical");
swing_modes.add(ESPHOME_F("vertical"));
if (traits.supports_swing_mode(CLIMATE_SWING_HORIZONTAL))
swing_modes.add("horizontal");
swing_modes.add(ESPHOME_F("horizontal"));
}
config.state_topic = false;

View File

@@ -19,14 +19,14 @@ MQTTDateComponent::MQTTDateComponent(DateEntity *date) : date_(date) {}
void MQTTDateComponent::setup() {
this->subscribe_json(this->get_command_topic_(), [this](const std::string &topic, JsonObject root) {
auto call = this->date_->make_call();
if (root["year"].is<uint16_t>()) {
call.set_year(root["year"]);
if (root[ESPHOME_F("year")].is<uint16_t>()) {
call.set_year(root[ESPHOME_F("year")]);
}
if (root["month"].is<uint8_t>()) {
call.set_month(root["month"]);
if (root[ESPHOME_F("month")].is<uint8_t>()) {
call.set_month(root[ESPHOME_F("month")]);
}
if (root["day"].is<uint8_t>()) {
call.set_day(root["day"]);
if (root[ESPHOME_F("day")].is<uint8_t>()) {
call.set_day(root[ESPHOME_F("day")]);
}
call.perform();
});
@@ -55,9 +55,9 @@ bool MQTTDateComponent::send_initial_state() {
bool MQTTDateComponent::publish_state(uint16_t year, uint8_t month, uint8_t day) {
return this->publish_json(this->get_state_topic_(), [year, month, day](JsonObject root) {
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
root["year"] = year;
root["month"] = month;
root["day"] = day;
root[ESPHOME_F("year")] = year;
root[ESPHOME_F("month")] = month;
root[ESPHOME_F("day")] = day;
});
}

View File

@@ -19,23 +19,23 @@ MQTTDateTimeComponent::MQTTDateTimeComponent(DateTimeEntity *datetime) : datetim
void MQTTDateTimeComponent::setup() {
this->subscribe_json(this->get_command_topic_(), [this](const std::string &topic, JsonObject root) {
auto call = this->datetime_->make_call();
if (root["year"].is<uint16_t>()) {
call.set_year(root["year"]);
if (root[ESPHOME_F("year")].is<uint16_t>()) {
call.set_year(root[ESPHOME_F("year")]);
}
if (root["month"].is<uint8_t>()) {
call.set_month(root["month"]);
if (root[ESPHOME_F("month")].is<uint8_t>()) {
call.set_month(root[ESPHOME_F("month")]);
}
if (root["day"].is<uint8_t>()) {
call.set_day(root["day"]);
if (root[ESPHOME_F("day")].is<uint8_t>()) {
call.set_day(root[ESPHOME_F("day")]);
}
if (root["hour"].is<uint8_t>()) {
call.set_hour(root["hour"]);
if (root[ESPHOME_F("hour")].is<uint8_t>()) {
call.set_hour(root[ESPHOME_F("hour")]);
}
if (root["minute"].is<uint8_t>()) {
call.set_minute(root["minute"]);
if (root[ESPHOME_F("minute")].is<uint8_t>()) {
call.set_minute(root[ESPHOME_F("minute")]);
}
if (root["second"].is<uint8_t>()) {
call.set_second(root["second"]);
if (root[ESPHOME_F("second")].is<uint8_t>()) {
call.set_second(root[ESPHOME_F("second")]);
}
call.perform();
});
@@ -68,12 +68,12 @@ bool MQTTDateTimeComponent::publish_state(uint16_t year, uint8_t month, uint8_t
uint8_t second) {
return this->publish_json(this->get_state_topic_(), [year, month, day, hour, minute, second](JsonObject root) {
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
root["year"] = year;
root["month"] = month;
root["day"] = day;
root["hour"] = hour;
root["minute"] = minute;
root["second"] = second;
root[ESPHOME_F("year")] = year;
root[ESPHOME_F("month")] = month;
root[ESPHOME_F("day")] = day;
root[ESPHOME_F("hour")] = hour;
root[ESPHOME_F("minute")] = minute;
root[ESPHOME_F("second")] = second;
});
}

View File

@@ -43,33 +43,33 @@ LightState *MQTTJSONLightComponent::get_state() const { return this->state_; }
void MQTTJSONLightComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
root["schema"] = "json";
root[ESPHOME_F("schema")] = ESPHOME_F("json");
auto traits = this->state_->get_traits();
root[MQTT_COLOR_MODE] = true;
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
JsonArray color_modes = root["supported_color_modes"].to<JsonArray>();
JsonArray color_modes = root[ESPHOME_F("supported_color_modes")].to<JsonArray>();
if (traits.supports_color_mode(ColorMode::ON_OFF))
color_modes.add("onoff");
color_modes.add(ESPHOME_F("onoff"));
if (traits.supports_color_mode(ColorMode::BRIGHTNESS))
color_modes.add("brightness");
color_modes.add(ESPHOME_F("brightness"));
if (traits.supports_color_mode(ColorMode::WHITE))
color_modes.add("white");
color_modes.add(ESPHOME_F("white"));
if (traits.supports_color_mode(ColorMode::COLOR_TEMPERATURE) ||
traits.supports_color_mode(ColorMode::COLD_WARM_WHITE))
color_modes.add("color_temp");
color_modes.add(ESPHOME_F("color_temp"));
if (traits.supports_color_mode(ColorMode::RGB))
color_modes.add("rgb");
color_modes.add(ESPHOME_F("rgb"));
if (traits.supports_color_mode(ColorMode::RGB_WHITE) ||
// HA doesn't support RGBCT, and there's no CWWW->CT emulation in ESPHome yet, so ignore CT control for now
traits.supports_color_mode(ColorMode::RGB_COLOR_TEMPERATURE))
color_modes.add("rgbw");
color_modes.add(ESPHOME_F("rgbw"));
if (traits.supports_color_mode(ColorMode::RGB_COLD_WARM_WHITE))
color_modes.add("rgbww");
color_modes.add(ESPHOME_F("rgbww"));
// legacy API
if (traits.supports_color_capability(ColorCapability::BRIGHTNESS))
root["brightness"] = true;
root[ESPHOME_F("brightness")] = true;
if (traits.supports_color_mode(ColorMode::COLOR_TEMPERATURE) ||
traits.supports_color_mode(ColorMode::COLD_WARM_WHITE)) {
@@ -78,11 +78,11 @@ void MQTTJSONLightComponent::send_discovery(JsonObject root, mqtt::SendDiscovery
}
if (this->state_->supports_effects()) {
root["effect"] = true;
root[ESPHOME_F("effect")] = true;
JsonArray effect_list = root[MQTT_EFFECT_LIST].to<JsonArray>();
for (auto *effect : this->state_->get_effects())
effect_list.add(effect->get_name());
effect_list.add("None");
effect_list.add(ESPHOME_F("None"));
}
}
bool MQTTJSONLightComponent::send_initial_state() { return this->publish_state_(); }

View File

@@ -19,14 +19,14 @@ MQTTTimeComponent::MQTTTimeComponent(TimeEntity *time) : time_(time) {}
void MQTTTimeComponent::setup() {
this->subscribe_json(this->get_command_topic_(), [this](const std::string &topic, JsonObject root) {
auto call = this->time_->make_call();
if (root["hour"].is<uint8_t>()) {
call.set_hour(root["hour"]);
if (root[ESPHOME_F("hour")].is<uint8_t>()) {
call.set_hour(root[ESPHOME_F("hour")]);
}
if (root["minute"].is<uint8_t>()) {
call.set_minute(root["minute"]);
if (root[ESPHOME_F("minute")].is<uint8_t>()) {
call.set_minute(root[ESPHOME_F("minute")]);
}
if (root["second"].is<uint8_t>()) {
call.set_second(root["second"]);
if (root[ESPHOME_F("second")].is<uint8_t>()) {
call.set_second(root[ESPHOME_F("second")]);
}
call.perform();
});
@@ -55,9 +55,9 @@ bool MQTTTimeComponent::send_initial_state() {
bool MQTTTimeComponent::publish_state(uint8_t hour, uint8_t minute, uint8_t second) {
return this->publish_json(this->get_state_topic_(), [hour, minute, second](JsonObject root) {
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
root["hour"] = hour;
root["minute"] = minute;
root["second"] = second;
root[ESPHOME_F("hour")] = hour;
root[ESPHOME_F("minute")] = minute;
root[ESPHOME_F("second")] = second;
});
}

View File

@@ -29,20 +29,20 @@ void MQTTUpdateComponent::setup() {
bool MQTTUpdateComponent::publish_state() {
return this->publish_json(this->get_state_topic_(), [this](JsonObject root) {
root["installed_version"] = this->update_->update_info.current_version;
root["latest_version"] = this->update_->update_info.latest_version;
root["title"] = this->update_->update_info.title;
root[ESPHOME_F("installed_version")] = this->update_->update_info.current_version;
root[ESPHOME_F("latest_version")] = this->update_->update_info.latest_version;
root[ESPHOME_F("title")] = this->update_->update_info.title;
if (!this->update_->update_info.summary.empty())
root["release_summary"] = this->update_->update_info.summary;
root[ESPHOME_F("release_summary")] = this->update_->update_info.summary;
if (!this->update_->update_info.release_url.empty())
root["release_url"] = this->update_->update_info.release_url;
root[ESPHOME_F("release_url")] = this->update_->update_info.release_url;
});
}
void MQTTUpdateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) {
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson
root["schema"] = "json";
root[MQTT_PAYLOAD_INSTALL] = "INSTALL";
root[ESPHOME_F("schema")] = ESPHOME_F("json");
root[MQTT_PAYLOAD_INSTALL] = ESPHOME_F("INSTALL");
}
bool MQTTUpdateComponent::send_initial_state() { return this->publish_state(); }