From c3ab3835e419b67bcdda2f5babe035c8e54955ad Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 16 Jan 2026 23:23:03 -1000 Subject: [PATCH] [light] Store color mode JSON strings in flash on ESP8266 --- .../components/light/light_json_schema.cpp | 50 ++++++++++--------- esphome/core/progmem.h | 4 ++ 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/esphome/components/light/light_json_schema.cpp b/esphome/components/light/light_json_schema.cpp index f370980737..43353afd50 100644 --- a/esphome/components/light/light_json_schema.cpp +++ b/esphome/components/light/light_json_schema.cpp @@ -1,4 +1,5 @@ #include "light_json_schema.h" +#include "color_mode.h" #include "light_output.h" #include "esphome/core/progmem.h" @@ -8,29 +9,32 @@ namespace esphome::light { // See https://www.home-assistant.io/integrations/light.mqtt/#json-schema for documentation on the schema -// Get JSON string for color mode using linear search (avoids large switch jump table) -static const char *get_color_mode_json_str(ColorMode mode) { - // Parallel arrays: mode values and their corresponding strings - // Uses less RAM than a switch jump table on sparse enum values - static constexpr ColorMode MODES[] = { - ColorMode::ON_OFF, - ColorMode::BRIGHTNESS, - ColorMode::WHITE, - ColorMode::COLOR_TEMPERATURE, - ColorMode::COLD_WARM_WHITE, - ColorMode::RGB, - ColorMode::RGB_WHITE, - ColorMode::RGB_COLOR_TEMPERATURE, - ColorMode::RGB_COLD_WARM_WHITE, - }; - static constexpr const char *STRINGS[] = { - "onoff", "brightness", "white", "color_temp", "cwww", "rgb", "rgbw", "rgbct", "rgbww", - }; - for (size_t i = 0; i < sizeof(MODES) / sizeof(MODES[0]); i++) { - if (MODES[i] == mode) - return STRINGS[i]; +// Get JSON string for color mode. +// ColorMode enum values are sparse bitmasks (0, 1, 3, 7, 11, 19, 35, 39, 47, 51) which would +// generate a large jump table. Converting to bit index (0-9) allows a compact switch. +static ProgmemStr get_color_mode_json_str(ColorMode mode) { + switch (ColorModeBitPolicy::to_bit(mode)) { + case 1: + return ESPHOME_F("onoff"); + case 2: + return ESPHOME_F("brightness"); + case 3: + return ESPHOME_F("white"); + case 4: + return ESPHOME_F("color_temp"); + case 5: + return ESPHOME_F("cwww"); + case 6: + return ESPHOME_F("rgb"); + case 7: + return ESPHOME_F("rgbw"); + case 8: + return ESPHOME_F("rgbct"); + case 9: + return ESPHOME_F("rgbww"); + default: + return nullptr; } - return nullptr; } void LightJSONSchema::dump_json(LightState &state, JsonObject root) { @@ -44,7 +48,7 @@ void LightJSONSchema::dump_json(LightState &state, JsonObject root) { auto values = state.remote_values; const auto color_mode = values.get_color_mode(); - const char *mode_str = get_color_mode_json_str(color_mode); + auto mode_str = get_color_mode_json_str(color_mode); if (mode_str != nullptr) { root[ESPHOME_F("color_mode")] = mode_str; } diff --git a/esphome/core/progmem.h b/esphome/core/progmem.h index fe9c9b5a75..6c3e4cec96 100644 --- a/esphome/core/progmem.h +++ b/esphome/core/progmem.h @@ -12,6 +12,8 @@ #define ESPHOME_strncpy_P strncpy_P #define ESPHOME_strncat_P strncat_P #define ESPHOME_snprintf_P snprintf_P +// Type for pointers to PROGMEM strings (for use with ESPHOME_F return values) +using ProgmemStr = const __FlashStringHelper *; #else #define ESPHOME_F(string_literal) (string_literal) #define ESPHOME_PGM_P const char * @@ -19,4 +21,6 @@ #define ESPHOME_strncpy_P strncpy #define ESPHOME_strncat_P strncat #define ESPHOME_snprintf_P snprintf +// Type for pointers to strings (no PROGMEM on non-ESP8266 platforms) +using ProgmemStr = const char *; #endif