Skip to content

Commit bdc54e5

Browse files
fhirschmannclaude
andcommitted
feat: configurable idle LED and progress bar colors
Replace the fixed idle-dot color and progress hue start/end with configurable RGB colors (idle color, progress start/end), exposed in the LED settings of the web interface and stored in NVS. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent d3cc69c commit bdc54e5

9 files changed

Lines changed: 51 additions & 42 deletions

File tree

‎html/locales/de.json‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@
4242
"numcontrol": "Anzahl Kontroll-LEDs",
4343
"controlled": "Kontroll-LED",
4444
"numidledots": "Anzahl LEDs im Leerlauf",
45+
"idlecolor": "Farbe der Leerlauf-LEDs",
46+
"progcolorstart": "Startfarbe Fortschrittsanzeige",
47+
"progcolorend": "Endfarbe Fortschrittsanzeige",
4548
"offsetpause": "Pausen-LEDs zentrieren",
46-
"huestart": "Farbton-Start (Playlist-Fortschritt)",
47-
"hueend": "Farbton-Ende (Playlist-Fortschritt)",
4849
"hueatmo": "Farbton-Atmolight",
4950
"satatmo": "Sättigung-Atmolight",
5051
"dimmablestates": "Dimmbare Stufen",

‎html/locales/en.json‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@
4242
"numcontrol": "Number of control LEDs",
4343
"controlled": "Control-LED",
4444
"numidledots": "Number of LEDs in idle state",
45+
"idlecolor": "Color of the idle dots",
46+
"progcolorstart": "Start color of progress bar",
47+
"progcolorend": "End color of progress bar",
4548
"offsetpause": "Center pause LEDs",
46-
"huestart": "Hue-Start for playlist progress",
47-
"hueend": "Hue-End for playlist progress",
4849
"hueatmo": "Hue-Atmolight",
4950
"satatmo": "Saturation-Atmolight",
5051
"dimmablestates": "Dimmable steps",

‎html/locales/fr.json‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@
4242
"numcontrol": "Nombre de LED de contrôle",
4343
"controlled": "LED de contrôle",
4444
"numidledots": "Nombre de LED en état de veille",
45+
"idlecolor": "Couleur des LED en veille",
46+
"progcolorstart": "Couleur de début du progrès",
47+
"progcolorend": "Couleur de fin du progrès",
4548
"offsetpause": "LED pause centre",
46-
"huestart": "Début de la couleur",
47-
"hueend": "Fin de la couleur",
4849
"hueatmo": "Couleur d'ambiance",
4950
"satatmo": "Saturation d'ambiance",
5051
"dimmablestates": "Étapes à gradation",

‎html/management.html‎

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,18 +1267,12 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
12671267
<label for="led_idleDots" data-i18n="settingsex.led.numidledots"></label>: <br>
12681268
<input type="number" class="form-control" id="led_idleDots" name="led_idleDots" min="0"
12691269
max="128"><br>
1270-
<label for="led_hueStart" data-i18n="settingsex.led.huestart"></label>: <br>
1271-
<div class="hue-slider">
1272-
<input id="led_hueStart" type="number" data-provide="slider" data-slider-min="-1"
1273-
data-slider-max="255" min="-1" max="255" class="form-control"
1274-
name="led_hueStart" data-slider-value="-1" value="-1">
1275-
</div>
1276-
<label for="led_hueEnd" data-i18n="settingsex.led.hueend"></label>: <br>
1277-
<div class="hue-slider">
1278-
<input id="led_hueEnd" type="number" data-provide="slider" data-slider-min="-1"
1279-
data-slider-max="255" min="-1" max="255" class="form-control" name="led_hueEnd"
1280-
data-slider-value="-1" value="-1">
1281-
</div>
1270+
<label for="led_idleColor" data-i18n="settingsex.led.idlecolor"></label>: <br>
1271+
<input type="color" class="form-control" id="led_idleColor" name="led_idleColor"><br>
1272+
<label for="led_progColorStart" data-i18n="settingsex.led.progcolorstart"></label>: <br>
1273+
<input type="color" class="form-control" id="led_progColorStart" name="led_progColorStart"><br>
1274+
<label for="led_progColorEnd" data-i18n="settingsex.led.progcolorend"></label>: <br>
1275+
<input type="color" class="form-control" id="led_progColorEnd" name="led_progColorEnd"><br>
12821276
<label for="led_hueAtmo" data-i18n="settingsex.led.hueatmo"></label>: <br>
12831277
<div class="hue-slider">
12841278
<input id="led_hueAtmo" type="number" data-provide="slider" data-slider-min="-1"
@@ -2602,8 +2596,9 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
26022596
document.getElementById('led_numControl').value = ledSettings.numControl;
26032597
listControlColors(ledSettings.numControl, ledSettings.controlColors);
26042598
document.getElementById('led_idleDots').value = ledSettings.numIdleDots;
2605-
$('#led_hueStart').bootstrapSlider('setValue', ledSettings.hueStart);
2606-
$('#led_hueEnd').bootstrapSlider('setValue', ledSettings.hueEnd);
2599+
document.getElementById('led_idleColor').value = getHexColor(ledSettings.idleColor);
2600+
document.getElementById('led_progColorStart').value = getHexColor(ledSettings.progColorStart);
2601+
document.getElementById('led_progColorEnd').value = getHexColor(ledSettings.progColorEnd);
26072602
$('#led_hueAtmo').bootstrapSlider('setValue', ledSettings.hueAtmo);
26082603
$('#led_satAtmo').bootstrapSlider('setValue', ledSettings.satAtmo);
26092604
document.getElementById('led_dimStates').value = ledSettings.dimStates;
@@ -2986,8 +2981,9 @@ <h5 class="modal-title" data-i18n="tools.nvs.erase.title"></h5>
29862981
numControl: Number(document.getElementById("led_numControl").value),
29872982
controlColors: [],
29882983
numIdleDots: Number(document.getElementById("led_idleDots").value),
2989-
hueStart: Number($('#led_hueStart').val()),
2990-
hueEnd: Number($('#led_hueEnd').val()),
2984+
idleColor: hexColorToInt(document.getElementById("led_idleColor").value),
2985+
progColorStart: hexColorToInt(document.getElementById("led_progColorStart").value),
2986+
progColorEnd: hexColorToInt(document.getElementById("led_progColorEnd").value),
29912987
hueAtmo: Number($('#led_hueAtmo').val()),
29922988
satAtmo: Number($('#led_satAtmo').val()),
29932989
dimStates: Number(document.getElementById("led_dimStates").value),

‎src/Button.cpp‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ static void onTimer();
7171
static void Button_DoButtonActions(void);
7272

7373
void Button_Init() {
74+
memset(gButtons, 0, sizeof(gButtons));
7475
#if (WAKEUP_BUTTON >= 0 && WAKEUP_BUTTON <= MAX_GPIO)
7576
if (ESP_ERR_INVALID_ARG == esp_sleep_enable_ext0_wakeup((gpio_num_t) WAKEUP_BUTTON, 0)) {
7677
Log_Printf(LOGLEVEL_ERROR, wrongWakeUpGpio, WAKEUP_BUTTON);
@@ -342,7 +343,7 @@ void Button_DoButtonActions(void) {
342343
}
343344

344345
unsigned long currentTimestamp = millis();
345-
for (uint8_t i = 0; i < 8; i++) {
346+
for (uint8_t i = 0; i < sizeof(buttonCmdConfig) / sizeof(buttonCmdConfig[0]); i++) {
346347
if (gButtons[i].isPressed) {
347348
Button_HandleSinglePress(i, currentTimestamp);
348349
}

‎src/Led.cpp‎

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#define LED_VOLUME_INDICATOR_RETURN_DELAY 1000U
2828
#define LED_VOLUME_INDICATOR_NUM_CYCLES (LED_VOLUME_INDICATOR_RETURN_DELAY / 20)
2929

30-
extern t_button gButtons[7]; // next + prev + pplay + rotEnc + button4 + button5 + dummy-button
30+
extern t_button gButtons[8]; // next + prev + pplay + rotEnc + button4 + button5 + button6 + dummy-button
3131
extern uint8_t gShutdownButton;
3232

3333
static std::atomic<uint32_t> Led_Indicators = 0u;
@@ -108,15 +108,19 @@ bool Led_LoadSettings(LedSettings &settings) {
108108
settings.numIdleDots = 4;
109109
}
110110

111+
// Get the idle color from NVS
112+
settings.idleColor = gPrefsSettings.getUInt("idleColor", IDLE_COLOR);
113+
111114
// Get offset LED pause from NVS
112115
settings.offsetLedPause = gPrefsSettings.getBool("offsetPause", OFFSET_PAUSE_LEDS);
113116

114117
// get dimmableStates from NVS
115118
settings.dimmableStates = gPrefsSettings.getUChar("dimStates", DIMMABLE_STATES);
116119

117-
// get hue start/end from NVS
118-
settings.progressHueStart = gPrefsSettings.getShort("hueStart", PROGRESS_HUE_START);
119-
settings.progressHueEnd = gPrefsSettings.getShort("hueEnd", PROGRESS_HUE_END);
120+
// get progress colors from NVS
121+
settings.progressColorStart = gPrefsSettings.getUInt("progColorStart", PROGRESS_COLOR_START);
122+
settings.progressColorEnd = gPrefsSettings.getUInt("progColorEnd", PROGRESS_COLOR_END);
123+
120124
// get atmo light from NVS
121125
settings.atmoHue = gPrefsSettings.getShort("hueAtmo", ATMO_HUE);
122126
settings.atmoSaturation = gPrefsSettings.getShort("satAtmo", ATMO_SATURATION);
@@ -369,7 +373,7 @@ CRGB::HTMLColorCode Led_GetIdleColor() {
369373
} else {
370374
idleColor = CRGB::Green;
371375
if (Wlan_IsConnected()) {
372-
idleColor = CRGB::White;
376+
idleColor = (CRGB::HTMLColorCode)gLedSettings.idleColor;
373377
}
374378
}
375379
}
@@ -1037,23 +1041,23 @@ AnimationReturnType Animation_Progress(const bool startNewAnimation, CRGBSet &le
10371041
lastPos = gPlayProperties.currentRelPos;
10381042
leds = CRGB::Black;
10391043
if (gLedSettings.numIndicatorLeds == 1) {
1040-
leds[0].setHue((uint8_t) (85 - ((double) 90 / 100) * gPlayProperties.currentRelPos));
1044+
leds[0] = blend((CRGB)gLedSettings.progressColorStart, (CRGB)gLedSettings.progressColorEnd, (uint8_t)(gPlayProperties.currentRelPos * 255 / 100));
10411045
} else {
10421046
const uint32_t ledValue = std::clamp<uint32_t>(map(gPlayProperties.currentRelPos, 0, 98, 0, leds.size() * gLedSettings.dimmableStates), 0, leds.size() * gLedSettings.dimmableStates);
10431047
const uint8_t fullLeds = ledValue / gLedSettings.dimmableStates;
10441048
const uint8_t lastLed = ledValue % gLedSettings.dimmableStates;
10451049
for (uint8_t led = 0; led < fullLeds; led++) {
10461050
if (System_AreControlsLocked()) {
10471051
leds[Led_Address(led)] = CRGB::Red;
1048-
} else if (!gPlayProperties.pausePlay) { // Hue-rainbow
1049-
leds[Led_Address(led)].setHue((uint8_t) (((float) gLedSettings.progressHueEnd - (float) gLedSettings.progressHueStart) / (leds.size() - 1) * led + gLedSettings.progressHueStart));
1052+
} else if (!gPlayProperties.pausePlay) {
1053+
leds[Led_Address(led)] = blend((CRGB)gLedSettings.progressColorStart, (CRGB)gLedSettings.progressColorEnd, (led * 255) / (leds.size() - 1));
10501054
}
10511055
}
10521056
if (lastLed > 0) {
10531057
if (System_AreControlsLocked()) {
10541058
leds[Led_Address(fullLeds)] = CRGB::Red;
10551059
} else {
1056-
leds[Led_Address(fullLeds)].setHue((uint8_t) (((float) gLedSettings.progressHueEnd - (float) gLedSettings.progressHueStart) / (leds.size() - 1) * fullLeds + gLedSettings.progressHueStart));
1060+
leds[Led_Address(fullLeds)] = blend((CRGB)gLedSettings.progressColorStart, (CRGB)gLedSettings.progressColorEnd, (fullLeds * 255) / (leds.size() - 1));
10571061
}
10581062
leds[Led_Address(fullLeds)] = Led_DimColor(leds[Led_Address(fullLeds)], lastLed);
10591063
}

‎src/Led.h‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,10 @@ struct LedSettings {
7171
uint8_t numControlLeds = NUM_CONTROL_LEDS;
7272
std::vector<uint32_t> controlLedColors;
7373
uint8_t numIdleDots = NUM_LEDS_IDLE_DOTS;
74+
uint32_t idleColor = IDLE_COLOR;
7475
bool offsetLedPause = OFFSET_PAUSE_LEDS;
75-
int16_t progressHueStart = PROGRESS_HUE_START;
76-
int16_t progressHueEnd = PROGRESS_HUE_END;
76+
uint32_t progressColorStart = PROGRESS_COLOR_START;
77+
uint32_t progressColorEnd = PROGRESS_COLOR_END;
7778
int16_t atmoHue = ATMO_HUE;
7879
int16_t atmoSaturation = ATMO_SATURATION;
7980
uint8_t dimmableStates = DIMMABLE_STATES;

‎src/Web.cpp‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -748,9 +748,10 @@ WebsocketCodeType JSONToSettings(JsonObject doc) {
748748
success = success && (gPrefsSettings.putUChar("numIndicator", ledObj["numIndicator"].as<uint8_t>()) != 0);
749749
success = success && (gPrefsSettings.putUChar("numControl", ledObj["numControl"].as<uint8_t>()) != 0);
750750
success = success && (gPrefsSettings.putUChar("numIdleDots", ledObj["numIdleDots"].as<uint8_t>()) != 0);
751+
success = success && (gPrefsSettings.putUInt("idleColor", ledObj["idleColor"].as<uint32_t>()) != 0);
751752
success = success && (gPrefsSettings.putBool("offsetPause", ledObj["offsetPause"].as<bool>()) != 0);
752-
success = success && (gPrefsSettings.putShort("hueStart", ledObj["hueStart"].as<int16_t>()) != 0);
753-
success = success && (gPrefsSettings.putShort("hueEnd", ledObj["hueEnd"].as<int16_t>()) != 0);
753+
success = success && (gPrefsSettings.putUInt("progColorStart", ledObj["progColorStart"].as<uint32_t>()) != 0);
754+
success = success && (gPrefsSettings.putUInt("progColorEnd", ledObj["progColorEnd"].as<uint32_t>()) != 0);
754755
success = success && (gPrefsSettings.putShort("hueAtmo", ledObj["hueAtmo"].as<int16_t>()) != 0);
755756
success = success && (gPrefsSettings.putShort("satAtmo", ledObj["satAtmo"].as<int16_t>()) != 0);
756757
success = success && (gPrefsSettings.putUChar("dimStates", ledObj["dimStates"].as<uint8_t>()) != 0);
@@ -1103,9 +1104,10 @@ static void settingsToJSON(JsonObject obj, const String section) {
11031104
}
11041105
}
11051106
ledObj["numIdleDots"].set(gPrefsSettings.getUChar("numIdleDots", NUM_LEDS_IDLE_DOTS));
1107+
ledObj["idleColor"].set(gPrefsSettings.getUInt("idleColor", IDLE_COLOR));
11061108
ledObj["offsetPause"].set(gPrefsSettings.getBool("offsetPause", OFFSET_PAUSE_LEDS));
1107-
ledObj["hueStart"].set(gPrefsSettings.getShort("hueStart", PROGRESS_HUE_START));
1108-
ledObj["hueEnd"].set(gPrefsSettings.getShort("hueEnd", PROGRESS_HUE_END));
1109+
ledObj["progColorStart"].set(gPrefsSettings.getUInt("progColorStart", PROGRESS_COLOR_START));
1110+
ledObj["progColorEnd"].set(gPrefsSettings.getUInt("progColorEnd", PROGRESS_COLOR_END));
11091111
ledObj["hueAtmo"].set(gPrefsSettings.getShort("hueAtmo", ATMO_HUE));
11101112
ledObj["satAtmo"].set(gPrefsSettings.getShort("satAtmo", ATMO_SATURATION));
11111113
ledObj["dimStates"].set(gPrefsSettings.getUChar("dimStates", DIMMABLE_STATES));
@@ -1211,9 +1213,10 @@ static void settingsToJSON(JsonObject obj, const String section) {
12111213
ledSettings["numIndicator"].set(NUM_INDICATOR_LEDS); // NUM_INDICATOR_LEDS
12121214
ledSettings["numControl"].set(NUM_CONTROL_LEDS); // NUM_CONTROL_LEDS
12131215
ledSettings["numIdleDots"].set(NUM_LEDS_IDLE_DOTS); // NUM_LEDS_IDLE_DOTS
1216+
ledSettings["idleColor"].set(IDLE_COLOR); // IDLE_COLOR
12141217
ledSettings["offsetPause"].set(OFFSET_PAUSE_LEDS); // OFFSET_PAUSE_LEDS
1215-
ledSettings["hueStart"].set(PROGRESS_HUE_START); // PROGRESS_HUE_START
1216-
ledSettings["hueEnd"].set(PROGRESS_HUE_END); // PROGRESS_HUE_END
1218+
ledSettings["progColorStart"].set(PROGRESS_COLOR_START); // PROGRESS_COLOR_START
1219+
ledSettings["progColorEnd"].set(PROGRESS_COLOR_END); // PROGRESS_COLOR_END
12171220
ledSettings["hueAtmo"].set(ATMO_HUE);
12181221
ledSettings["satAtmo"].set(ATMO_SATURATION);
12191222
ledSettings["dimStates"].set(DIMMABLE_STATES); // DIMMABLE_STATES

‎src/settings.h‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,9 +219,10 @@
219219
#define CHIPSET WS2812B // type of Neopixel
220220
#define COLOR_ORDER GRB
221221
#define NUM_LEDS_IDLE_DOTS 4 // count of LEDs, which are shown when Idle
222+
#define IDLE_COLOR CRGB::White // color of the idle dots
222223
#define OFFSET_PAUSE_LEDS false // if true the pause-leds are centered in the mid of the LED-Strip
223-
#define PROGRESS_HUE_START 85 // Start and end hue of mulitple-LED progress indicator. Hue ranges from basically 0 - 255, but you can also set numbers outside this range to get the desired effect (e.g. 85-215 will go from green to purple via blue, 341-215 start and end at exactly the same color but go from green to purple via yellow and red)
224-
#define PROGRESS_HUE_END -1
224+
#define PROGRESS_COLOR_START 0x00FF00 // start color of the progress bar
225+
#define PROGRESS_COLOR_END 0xFF0000 // end color of the progress bar
225226
#define ATMO_HUE 10
226227
#define ATMO_SATURATION 180
227228
#define DIMMABLE_STATES 50 // Number of dimmed values between two full LEDs (https://forum.espuino.de/t/led-verbesserungen-rework/1739)

0 commit comments

Comments
 (0)