From 9ede0f4dc33cba20e1c3f4802c43b1f06605d058 Mon Sep 17 00:00:00 2001 From: Djuri Baars Date: Sat, 8 Jun 2024 01:00:52 +0200 Subject: [PATCH] Web UI improvements, better frontlight functionality --- data | 2 +- src/lib/block_notify.cpp | 2 +- src/lib/config.cpp | 26 +- src/lib/led_handler.cpp | 610 ++++++++++++++++++++++++++------------- src/lib/led_handler.hpp | 11 + src/lib/webserver.cpp | 34 ++- src/lib/webserver.hpp | 3 + 7 files changed, 477 insertions(+), 211 deletions(-) diff --git a/data b/data index 6ecb482..e859ada 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 6ecb4826000e4a34f22d98541d28448f844340f7 +Subproject commit e859adac8631c6380a6a3f8b20b118a5531d4f8c diff --git a/src/lib/block_notify.cpp b/src/lib/block_notify.cpp index c2fb092..ab546b0 100644 --- a/src/lib/block_notify.cpp +++ b/src/lib/block_notify.cpp @@ -148,7 +148,7 @@ void onWebsocketBlockMessage(esp_websocket_event_data_t *event_data) filter["block"]["height"] = true; filter["mempool-blocks"][0]["medianFee"] = true; - DeserializationError error = deserializeJson(doc, (char *)event_data->data_ptr, DeserializationOption::Filter(filter)); + deserializeJson(doc, (char *)event_data->data_ptr, DeserializationOption::Filter(filter)); // if (error) { // Serial.print("deserializeJson() failed: "); diff --git a/src/lib/config.cpp b/src/lib/config.cpp index fd2ae09..ac5e8cb 100644 --- a/src/lib/config.cpp +++ b/src/lib/config.cpp @@ -67,6 +67,14 @@ void setup() setupOTA(); waitUntilNoneBusy(); + + #ifdef HAS_FRONTLIGHT + if (!preferences.getBool("flAlwaysOn", false)) { + frontlightFadeOutAll(preferences.getUInt("flEffectDelay"), true); + flArray.allOFF(); + } + #endif + forceFullRefresh(); } @@ -712,15 +720,17 @@ void setupFrontlight() { preferences.putUInt("flMaxBrightness", 2048); } - - if (preferences.getBool("flAlwaysOn", false)) { - Serial.println(F("FL Always on")); - - frontlightFadeInAll(); - } else { - Serial.println(F("FL all off")); - flArray.allOFF(); + if (!preferences.isKey("flEffectDelay")) + { + preferences.putUInt("flEffectDelay", 5); } + + if (!preferences.isKey("flFlashOnUpd")) + { + preferences.putBool("flFlashOnUpd", false); + } + + frontlightFadeInAll(preferences.getUInt("flEffectDelay"), true); } #endif diff --git a/src/lib/led_handler.cpp b/src/lib/led_handler.cpp index 5d37924..1c7799a 100644 --- a/src/lib/led_handler.cpp +++ b/src/lib/led_handler.cpp @@ -5,138 +5,357 @@ QueueHandle_t ledTaskQueue = NULL; Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800); uint ledTaskParams; -void ledTask(void *parameter) { - while (1) { - if (ledTaskQueue != NULL) { - if (xQueueReceive(ledTaskQueue, &ledTaskParams, portMAX_DELAY) == - pdPASS) { +#ifdef HAS_FRONTLIGHT +#define FL_FADE_STEP 50 - if (preferences.getBool("disableLeds", false)) { +bool frontlightOn = false; +bool flInTransition = false; + +void frontlightFlash(int flDelayTime) +{ + if (frontlightOn) + { + frontlightFadeOutAll(flDelayTime); + frontlightFadeInAll(flDelayTime); + } + else + { + frontlightFadeInAll(flDelayTime); + frontlightFadeOutAll(flDelayTime); + } +} + +void frontlightFadeInAll() +{ + frontlightFadeInAll(preferences.getUInt("flEffectDelay")); +} + +void frontlightFadeOutAll() +{ + frontlightFadeOutAll(preferences.getUInt("flEffectDelay")); +} + +void frontlightFadeIn(uint num) +{ + frontlightFadeIn(num, preferences.getUInt("flEffectDelay")); +} + +void frontlightFadeOut(uint num) +{ + frontlightFadeOut(num, preferences.getUInt("flEffectDelay")); +} + +void frontlightSetBrightness(uint brightness) +{ + if (brightness > 4096) + { + return; + } + + for (int ledPin = 0; ledPin <= NUM_SCREENS; ledPin++) + { + flArray.setPWM(ledPin, 0, brightness); + } +} + +void frontlightFadeInAll(int flDelayTime) +{ + frontlightFadeInAll(flDelayTime, false); +} + +void frontlightFadeInAll(int flDelayTime, bool staggered) +{ + if (flInTransition) + return; + + flInTransition = true; + + if (staggered) + { + int maxBrightness = preferences.getUInt("flMaxBrightness"); + int step = FL_FADE_STEP; + int staggerDelay = flDelayTime / NUM_SCREENS; + + for (int dutyCycle = 0; dutyCycle <= maxBrightness + (NUM_SCREENS - 1) * maxBrightness / NUM_SCREENS; dutyCycle += step) + { + for (int ledPin = 0; ledPin < NUM_SCREENS; ledPin++) + { + int ledBrightness = dutyCycle - ledPin * maxBrightness / NUM_SCREENS; + if (ledBrightness < 0) + ledBrightness = 0; + else if (ledBrightness > maxBrightness) + ledBrightness = maxBrightness; + + flArray.setPWM(ledPin + 1, 0, ledBrightness); + } + vTaskDelay(pdMS_TO_TICKS(staggerDelay)); + } + } + else + { + for (int dutyCycle = 0; dutyCycle <= preferences.getUInt("flMaxBrightness"); dutyCycle += FL_FADE_STEP) + { + for (int ledPin = 0; ledPin <= NUM_SCREENS; ledPin++) + { + flArray.setPWM(ledPin, 0, dutyCycle); + } + vTaskDelay(pdMS_TO_TICKS(flDelayTime)); + } + } + frontlightOn = true; + flInTransition = false; +} + +void frontlightFadeOutAll(int flDelayTime) +{ + frontlightFadeOutAll(flDelayTime, false); +} + +void frontlightFadeOutAll(int flDelayTime, bool staggered) +{ + if (flInTransition) + return; + flInTransition = true; + + if (staggered) + { + int maxBrightness = preferences.getUInt("flMaxBrightness"); + int step = FL_FADE_STEP; + int staggerDelay = flDelayTime / NUM_SCREENS; + + for (int dutyCycle = maxBrightness; dutyCycle >= 0; dutyCycle -= step) + { + for (int ledPin = 0; ledPin < NUM_SCREENS; ledPin++) + { + int ledBrightness = dutyCycle - (NUM_SCREENS - 1 - ledPin) * maxBrightness / NUM_SCREENS; + if (ledBrightness < 0) + ledBrightness = 0; + else if (ledBrightness > maxBrightness) + ledBrightness = maxBrightness; + + flArray.setPWM(ledPin + 1, 0, ledBrightness); + } + vTaskDelay(pdMS_TO_TICKS(staggerDelay)); + } + } + else + { + for (int dutyCycle = preferences.getUInt("flMaxBrightness"); dutyCycle >= 0; dutyCycle -= FL_FADE_STEP) + { + for (int ledPin = 0; ledPin <= NUM_SCREENS; ledPin++) + { + flArray.setPWM(ledPin, 0, dutyCycle); + } + vTaskDelay(pdMS_TO_TICKS(flDelayTime)); + } + } + + flArray.allOFF(); + frontlightOn = false; + flInTransition = false; +} + +void frontlightFadeIn(uint num, int flDelayTime) +{ + for (int dutyCycle = 0; dutyCycle <= preferences.getUInt("flMaxBrightness"); dutyCycle += 5) + { + flArray.setPWM(num, 0, dutyCycle); + vTaskDelay(pdMS_TO_TICKS(flDelayTime)); + } +} + +void frontlightFadeOut(uint num, int flDelayTime) +{ + for (int dutyCycle = preferences.getUInt("flMaxBrightness"); dutyCycle >= 0; dutyCycle -= 5) + { + flArray.setPWM(num, 0, dutyCycle); + vTaskDelay(pdMS_TO_TICKS(flDelayTime)); + } +} +#endif + +void ledTask(void *parameter) +{ + while (1) + { + if (ledTaskQueue != NULL) + { + if (xQueueReceive(ledTaskQueue, &ledTaskParams, portMAX_DELAY) == + pdPASS) + { + + if (preferences.getBool("disableLeds", false)) + { continue; } uint32_t oldLights[NEOPIXEL_COUNT]; // get current state - for (int i = 0; i < NEOPIXEL_COUNT; i++) { + for (int i = 0; i < NEOPIXEL_COUNT; i++) + { oldLights[i] = pixels.getPixelColor(i); } - switch (ledTaskParams) { - case LED_POWER_TEST: - ledRainbow(20); - pixels.clear(); - break; - case LED_EFFECT_WIFI_CONNECT_ERROR: - blinkDelayTwoColor(100, 3, pixels.Color(8, 161, 236), - pixels.Color(255, 0, 0)); - break; - case LED_FLASH_ERROR: - blinkDelayColor(250, 3, 255, 0, 0); - break; - case LED_EFFECT_HEARTBEAT: - blinkDelayColor(150, 2, 0, 0, 255); - break; - case LED_DATA_BLOCK_ERROR: - blinkDelayColor(150, 2, 128, 0, 128); - break; - case LED_DATA_PRICE_ERROR: - blinkDelayColor(150, 2, 177, 90, 31); - break; - case LED_FLASH_IDENTIFY: - blinkDelayTwoColor(100, 2, pixels.Color(255, 0, 0), - pixels.Color(0, 255, 255)); - blinkDelayTwoColor(100, 2, pixels.Color(0, 255, 0), - pixels.Color(0, 0, 255)); - break; - case LED_EFFECT_WIFI_CONNECT_SUCCESS: - case LED_FLASH_SUCCESS: - blinkDelayColor(150, 3, 0, 255, 0); - break; - case LED_PROGRESS_100: - pixels.setPixelColor(0, pixels.Color(0, 255, 0)); - case LED_PROGRESS_75: - pixels.setPixelColor(1, pixels.Color(0, 255, 0)); - case LED_PROGRESS_50: - pixels.setPixelColor(2, pixels.Color(0, 255, 0)); - case LED_PROGRESS_25: - pixels.setPixelColor(3, pixels.Color(0, 255, 0)); - pixels.show(); - break; - case LED_FLASH_UPDATE: - break; - case LED_FLASH_BLOCK_NOTIFY: - blinkDelayTwoColor(250, 3, pixels.Color(224, 67, 0), - pixels.Color(8, 2, 0)); - break; - case LED_EFFECT_WIFI_WAIT_FOR_CONFIG: - blinkDelayTwoColor(100, 1, pixels.Color(8, 161, 236), - pixels.Color(156, 225, 240)); - break; - case LED_EFFECT_WIFI_ERASE_SETTINGS: - blinkDelay(100, 3); - break; - case LED_EFFECT_WIFI_CONNECTING: - for (int i = NEOPIXEL_COUNT; i >= 0; i--) { - for (int j = NEOPIXEL_COUNT; j >= 0; j--) { - if (j == i) { - pixels.setPixelColor(i, pixels.Color(16, 197, 236)); - } else { - pixels.setPixelColor(j, pixels.Color(0, 0, 0)); - } - } - pixels.show(); - vTaskDelay(pdMS_TO_TICKS(100)); + switch (ledTaskParams) + { + case LED_POWER_TEST: + ledRainbow(20); + pixels.clear(); + break; + case LED_EFFECT_WIFI_CONNECT_ERROR: + blinkDelayTwoColor(100, 3, pixels.Color(8, 161, 236), + pixels.Color(255, 0, 0)); + break; + case LED_FLASH_ERROR: + blinkDelayColor(250, 3, 255, 0, 0); + break; + case LED_EFFECT_HEARTBEAT: + blinkDelayColor(150, 2, 0, 0, 255); + break; + case LED_DATA_BLOCK_ERROR: + blinkDelayColor(150, 2, 128, 0, 128); + break; + case LED_DATA_PRICE_ERROR: + blinkDelayColor(150, 2, 177, 90, 31); + break; + case LED_FLASH_IDENTIFY: + blinkDelayTwoColor(100, 2, pixels.Color(255, 0, 0), + pixels.Color(0, 255, 255)); + blinkDelayTwoColor(100, 2, pixels.Color(0, 255, 0), + pixels.Color(0, 0, 255)); + break; + case LED_EFFECT_WIFI_CONNECT_SUCCESS: + case LED_FLASH_SUCCESS: + blinkDelayColor(150, 3, 0, 255, 0); + break; + case LED_PROGRESS_100: + pixels.setPixelColor(0, pixels.Color(0, 255, 0)); + case LED_PROGRESS_75: + pixels.setPixelColor(1, pixels.Color(0, 255, 0)); + case LED_PROGRESS_50: + pixels.setPixelColor(2, pixels.Color(0, 255, 0)); + case LED_PROGRESS_25: + pixels.setPixelColor(3, pixels.Color(0, 255, 0)); + pixels.show(); + break; + case LED_FLASH_UPDATE: + break; + case LED_FLASH_BLOCK_NOTIFY: + { +#ifdef HAS_FRONTLIGHT + bool frontlightWasOn = false; + + if (preferences.getBool("flFlashOnUpd", false)) + { + if (frontlightOn) + { + frontlightWasOn = true; + frontlightFadeOutAll(1); } - break; - case LED_EFFECT_PAUSE_TIMER: - for (int i = NEOPIXEL_COUNT; i >= 0; i--) { - for (int j = NEOPIXEL_COUNT; j >= 0; j--) { - uint32_t c = pixels.Color(0, 0, 0); - if (i == j) c = pixels.Color(0, 255, 0); - pixels.setPixelColor(j, c); - } - - pixels.show(); - - delay(100); + else + { + frontlightFadeInAll(1); } - pixels.setPixelColor(0, pixels.Color(255, 0, 0)); - pixels.show(); - - delay(900); - - pixels.clear(); - pixels.show(); - break; - case LED_EFFECT_START_TIMER: - pixels.clear(); - pixels.setPixelColor((NEOPIXEL_COUNT - 1), pixels.Color(255, 0, 0)); - pixels.show(); - - delay(900); - - for (int i = NEOPIXEL_COUNT; i--; i > 0) { - for (int j = NEOPIXEL_COUNT; j--; j > 0) { - uint32_t c = pixels.Color(0, 0, 0); - if (i == j) c = pixels.Color(0, 255, 0); - - pixels.setPixelColor(j, c); + } +#endif + blinkDelayTwoColor(250, 3, pixels.Color(224, 67, 0), + pixels.Color(8, 2, 0)); +#ifdef HAS_FRONTLIGHT + if (preferences.getBool("flFlashOnUpd", false)) + { + if (frontlightWasOn) + { + frontlightFadeInAll(1); + } + else + { + frontlightFadeOutAll(1); + } + } +#endif + break; + } + case LED_EFFECT_WIFI_WAIT_FOR_CONFIG: + blinkDelayTwoColor(100, 1, pixels.Color(8, 161, 236), + pixels.Color(156, 225, 240)); + break; + case LED_EFFECT_WIFI_ERASE_SETTINGS: + blinkDelay(100, 3); + break; + case LED_EFFECT_WIFI_CONNECTING: + for (int i = NEOPIXEL_COUNT; i >= 0; i--) + { + for (int j = NEOPIXEL_COUNT; j >= 0; j--) + { + if (j == i) + { + pixels.setPixelColor(i, pixels.Color(16, 197, 236)); } - - pixels.show(); - - delay(100); + else + { + pixels.setPixelColor(j, pixels.Color(0, 0, 0)); + } + } + pixels.show(); + vTaskDelay(pdMS_TO_TICKS(100)); + } + break; + case LED_EFFECT_PAUSE_TIMER: + for (int i = NEOPIXEL_COUNT; i >= 0; i--) + { + for (int j = NEOPIXEL_COUNT; j >= 0; j--) + { + uint32_t c = pixels.Color(0, 0, 0); + if (i == j) + c = pixels.Color(0, 255, 0); + pixels.setPixelColor(j, c); } - pixels.clear(); pixels.show(); - break; + + delay(100); + } + pixels.setPixelColor(0, pixels.Color(255, 0, 0)); + pixels.show(); + + delay(900); + + pixels.clear(); + pixels.show(); + break; + case LED_EFFECT_START_TIMER: + pixels.clear(); + pixels.setPixelColor((NEOPIXEL_COUNT - 1), pixels.Color(255, 0, 0)); + pixels.show(); + + delay(900); + + for (int i = NEOPIXEL_COUNT; i--; i > 0) + { + for (int j = NEOPIXEL_COUNT; j--; j > 0) + { + uint32_t c = pixels.Color(0, 0, 0); + if (i == j) + c = pixels.Color(0, 255, 0); + + pixels.setPixelColor(j, c); + } + + pixels.show(); + + delay(100); + } + + pixels.clear(); + pixels.show(); + break; } // revert to previous state unless power test - for (int i = 0; i < NEOPIXEL_COUNT; i++) { + for (int i = 0; i < NEOPIXEL_COUNT; i++) + { pixels.setPixelColor(i, oldLights[i]); } @@ -146,14 +365,17 @@ void ledTask(void *parameter) { } } -void setupLeds() { +void setupLeds() +{ pixels.begin(); pixels.setBrightness(preferences.getUInt("ledBrightness", 128)); pixels.clear(); pixels.show(); setupLedTask(); - if (preferences.getBool("ledTestOnPower", true)) { - while (!ledTaskQueue) { + if (preferences.getBool("ledTestOnPower", true)) + { + while (!ledTaskQueue) + { delay(1); // wait until queue is available } @@ -161,14 +383,17 @@ void setupLeds() { } } -void setupLedTask() { +void setupLedTask() +{ ledTaskQueue = xQueueCreate(5, sizeof(uint)); - xTaskCreate(ledTask, "LedTask", 2048, NULL, tskIDLE_PRIORITY, &ledTaskHandle); + xTaskCreate(ledTask, "LedTask", 2048, NULL, 10, &ledTaskHandle); } -void blinkDelay(int d, int times) { - for (int j = 0; j < times; j++) { +void blinkDelay(int d, int times) +{ + for (int j = 0; j < times; j++) + { pixels.setPixelColor(0, pixels.Color(255, 0, 0)); pixels.setPixelColor(1, pixels.Color(0, 255, 0)); pixels.setPixelColor(2, pixels.Color(255, 0, 0)); @@ -187,9 +412,12 @@ void blinkDelay(int d, int times) { pixels.show(); } -void blinkDelayColor(int d, int times, uint r, uint g, uint b) { - for (int j = 0; j < times; j++) { - for (int i = 0; i < NEOPIXEL_COUNT; i++) { +void blinkDelayColor(int d, int times, uint r, uint g, uint b) +{ + for (int j = 0; j < times; j++) + { + for (int i = 0; i < NEOPIXEL_COUNT; i++) + { pixels.setPixelColor(i, pixels.Color(r, g, b)); } @@ -204,15 +432,19 @@ void blinkDelayColor(int d, int times, uint r, uint g, uint b) { pixels.show(); } -void blinkDelayTwoColor(int d, int times, uint32_t c1, uint32_t c2) { - for (int j = 0; j < times; j++) { - for (int i = 0; i < NEOPIXEL_COUNT; i++) { +void blinkDelayTwoColor(int d, int times, uint32_t c1, uint32_t c2) +{ + for (int j = 0; j < times; j++) + { + for (int i = 0; i < NEOPIXEL_COUNT; i++) + { pixels.setPixelColor(i, c1); } pixels.show(); vTaskDelay(pdMS_TO_TICKS(d)); - for (int i = 0; i < NEOPIXEL_COUNT; i++) { + for (int i = 0; i < NEOPIXEL_COUNT; i++) + { pixels.setPixelColor(i, c2); } pixels.show(); @@ -222,7 +454,8 @@ void blinkDelayTwoColor(int d, int times, uint32_t c1, uint32_t c2) { pixels.show(); } -void clearLeds() { +void clearLeds() +{ preferences.putBool("ledStatus", false); pixels.clear(); pixels.show(); @@ -230,24 +463,31 @@ void clearLeds() { void setLights(int r, int g, int b) { setLights(pixels.Color(r, g, b)); } -void setLights(uint32_t color) { +void setLights(uint32_t color) +{ bool ledStatus = true; - for (int i = 0; i < NEOPIXEL_COUNT; i++) { + for (int i = 0; i < NEOPIXEL_COUNT; i++) + { pixels.setPixelColor(i, color); } pixels.show(); - if (color == pixels.Color(0, 0, 0)) { + if (color == pixels.Color(0, 0, 0)) + { ledStatus = false; - } else { + } + else + { saveLedState(); } preferences.putBool("ledStatus", ledStatus); } -void saveLedState() { - for (int i = 0; i < pixels.numPixels(); i++) { +void saveLedState() +{ + for (int i = 0; i < pixels.numPixels(); i++) + { int pixelColor = pixels.getPixelColor(i); char key[12]; snprintf(key, 12, "%s%d", "ledColor_", i); @@ -257,8 +497,10 @@ void saveLedState() { xTaskNotifyGive(eventSourceTaskHandle); } -void restoreLedState() { - for (int i = 0; i < pixels.numPixels(); i++) { +void restoreLedState() +{ + for (int i = 0; i < pixels.numPixels(); i++) + { char key[12]; snprintf(key, 12, "%s%d", "ledColor_", i); uint pixelColor = preferences.getUInt(key, pixels.Color(0, 0, 0)); @@ -270,8 +512,10 @@ void restoreLedState() { QueueHandle_t getLedTaskQueue() { return ledTaskQueue; } -bool queueLedEffect(uint effect) { - if (ledTaskQueue == NULL) { +bool queueLedEffect(uint effect) +{ + if (ledTaskQueue == NULL) + { return false; } @@ -279,13 +523,15 @@ bool queueLedEffect(uint effect) { xQueueSend(ledTaskQueue, &flashType, portMAX_DELAY); } -void ledRainbow(int wait) { +void ledRainbow(int wait) +{ // Hue of first pixel runs 5 complete loops through the color wheel. // Color wheel has a range of 65536 but it's OK if we roll over, so // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time // means we'll make 5*65536/256 = 1280 passes through this loop: for (long firstPixelHue = 0; firstPixelHue < 5 * 65536; - firstPixelHue += 256) { + firstPixelHue += 256) + { // strip.rainbow() can take a single argument (first pixel hue) or // optionally a few extras: number of rainbow repetitions (default 1), // saturation and value (brightness) (both 0-255, similar to the @@ -294,83 +540,53 @@ void ledRainbow(int wait) { pixels.rainbow(firstPixelHue); // Above line is equivalent to: // strip.rainbow(firstPixelHue, 1, 255, 255, true); - pixels.show(); // Update strip with new contents + pixels.show(); // Update strip with new contents delayMicroseconds(wait); // vTaskDelay(pdMS_TO_TICKS(wait)); // Pause for a moment } } -void ledTheaterChase(uint32_t color, int wait) { - for (int a = 0; a < 10; a++) { // Repeat 10 times... - for (int b = 0; b < 3; b++) { // 'b' counts from 0 to 2... - pixels.clear(); // Set all pixels in RAM to 0 (off) +void ledTheaterChase(uint32_t color, int wait) +{ + for (int a = 0; a < 10; a++) + { // Repeat 10 times... + for (int b = 0; b < 3; b++) + { // 'b' counts from 0 to 2... + pixels.clear(); // Set all pixels in RAM to 0 (off) // 'c' counts up from 'b' to end of strip in steps of 3... - for (int c = b; c < pixels.numPixels(); c += 3) { - pixels.setPixelColor(c, color); // Set pixel 'c' to value 'color' + for (int c = b; c < pixels.numPixels(); c += 3) + { + pixels.setPixelColor(c, color); // Set pixel 'c' to value 'color' } - pixels.show(); // Update strip with new contents - vTaskDelay(pdMS_TO_TICKS(wait)); // Pause for a moment + pixels.show(); // Update strip with new contents + vTaskDelay(pdMS_TO_TICKS(wait)); // Pause for a moment } } } -void ledTheaterChaseRainbow(int wait) { - int firstPixelHue = 0; // First pixel starts at red (hue 0) - for (int a = 0; a < 30; a++) { // Repeat 30 times... - for (int b = 0; b < 3; b++) { // 'b' counts from 0 to 2... - pixels.clear(); // Set all pixels in RAM to 0 (off) +void ledTheaterChaseRainbow(int wait) +{ + int firstPixelHue = 0; // First pixel starts at red (hue 0) + for (int a = 0; a < 30; a++) + { // Repeat 30 times... + for (int b = 0; b < 3; b++) + { // 'b' counts from 0 to 2... + pixels.clear(); // Set all pixels in RAM to 0 (off) // 'c' counts up from 'b' to end of strip in increments of 3... - for (int c = b; c < pixels.numPixels(); c += 3) { + for (int c = b; c < pixels.numPixels(); c += 3) + { // hue of pixel 'c' is offset by an amount to make one full // revolution of the color wheel (range 65536) along the length // of the strip (strip.numPixels() steps): int hue = firstPixelHue + c * 65536L / pixels.numPixels(); - uint32_t color = pixels.gamma32(pixels.ColorHSV(hue)); // hue -> RGB - pixels.setPixelColor(c, color); // Set pixel 'c' to value 'color' + uint32_t color = pixels.gamma32(pixels.ColorHSV(hue)); // hue -> RGB + pixels.setPixelColor(c, color); // Set pixel 'c' to value 'color' } - pixels.show(); // Update strip with new contents - vTaskDelay(pdMS_TO_TICKS(wait)); // Pause for a moment - firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames + pixels.show(); // Update strip with new contents + vTaskDelay(pdMS_TO_TICKS(wait)); // Pause for a moment + firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames } } } Adafruit_NeoPixel getPixels() { return pixels; } - -#ifdef HAS_FRONTLIGHT -int flDelayTime = 5; - -void frontlightFadeInAll() { - for (int dutyCycle = 0; dutyCycle <= preferences.getUInt("flMaxBrightness"); dutyCycle += 5) { - for (int ledPin = 0; ledPin <= NUM_SCREENS; ledPin++) { - flArray.setPWM(ledPin, 0, dutyCycle); - } - vTaskDelay(pdMS_TO_TICKS(flDelayTime)); - } -} - -void frontlightFadeOutAll() { - for (int dutyCycle = preferences.getUInt("flMaxBrightness"); dutyCycle >= 0; dutyCycle -= 5) { - for (int ledPin = 0; ledPin <= NUM_SCREENS; ledPin++) { - flArray.setPWM(ledPin, 0, dutyCycle); - } - vTaskDelay(pdMS_TO_TICKS(flDelayTime)); - } - - flArray.allOFF(); -} - -void frontlightFadeIn(uint num) { - for (int dutyCycle = 0; dutyCycle <= preferences.getUInt("flMaxBrightness"); dutyCycle += 5) { - flArray.setPWM(num, 0, dutyCycle); - vTaskDelay(pdMS_TO_TICKS(flDelayTime)); - } -} - -void frontlightFadeOut(uint num) { - for (int dutyCycle = preferences.getUInt("flMaxBrightness"); dutyCycle >= 0; dutyCycle -= 5) { - flArray.setPWM(num, 0, dutyCycle); - vTaskDelay(pdMS_TO_TICKS(flDelayTime)); - } -} -#endif \ No newline at end of file diff --git a/src/lib/led_handler.hpp b/src/lib/led_handler.hpp index 8fba3bd..2157ac2 100644 --- a/src/lib/led_handler.hpp +++ b/src/lib/led_handler.hpp @@ -59,8 +59,19 @@ void ledTheaterChase(uint32_t color, int wait); Adafruit_NeoPixel getPixels(); #ifdef HAS_FRONTLIGHT +void frontlightFlash(int flDelayTime); void frontlightFadeInAll(); void frontlightFadeOutAll(); void frontlightFadeIn(uint num); void frontlightFadeOut(uint num); + +void frontlightSetBrightness(uint brightness); + +void frontlightFadeInAll(int flDelayTime); +void frontlightFadeInAll(int flDelayTime, bool staggered); +void frontlightFadeOutAll(int flDelayTime); +void frontlightFadeOutAll(int flDelayTime, bool staggered); + +void frontlightFadeIn(uint num, int flDelayTime); +void frontlightFadeOut(uint num, int flDelayTime); #endif \ No newline at end of file diff --git a/src/lib/webserver.cpp b/src/lib/webserver.cpp index 3c9269a..73ef946 100644 --- a/src/lib/webserver.cpp +++ b/src/lib/webserver.cpp @@ -56,8 +56,12 @@ void setupWebserver() #ifdef HAS_FRONTLIGHT server.on("/api/frontlight/on", HTTP_GET, onApiFrontlightOn); - server.on("/api/frontlight/status", HTTP_GET, onApiFrontlightStatus); + server.on("/api/frontlight/flash", HTTP_GET, onApiFrontlightFlash); + server.on("/api/frontlight/brightness", HTTP_GET, onApiFrontlightSetBrightness); server.on("/api/frontlight/off", HTTP_GET, onApiFrontlightOff); + + server.addRewrite( + new OneParamRewrite("/api/frontlight/brightness/{b}", "/api/frontlight/brightness?b={b}")); #endif // server.on("^\\/api\\/lights\\/([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$", HTTP_GET, @@ -334,7 +338,7 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json) } } - String uintSettings[] = {"minSecPriceUpd", "fullRefreshMin", "ledBrightness", "flMaxBrightness"}; + String uintSettings[] = {"minSecPriceUpd", "fullRefreshMin", "ledBrightness", "flMaxBrightness", "flEffectDelay"}; for (String setting : uintSettings) { @@ -357,7 +361,7 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json) String boolSettings[] = {"fetchEurPrice", "ledTestOnPower", "ledFlashOnUpd", "mdnsEnabled", "otaEnabled", "stealFocus", "mcapBigChar", "useSatsSymbol", "useBlkCountdown", - "suffixPrice", "disableLeds", "ownDataSource", "flAlwaysOn"}; + "suffixPrice", "disableLeds", "ownDataSource", "flAlwaysOn", "flFlashOnUpd"}; for (String setting : boolSettings) { @@ -478,8 +482,10 @@ void onApiSettingsGet(AsyncWebServerRequest *request) #ifdef HAS_FRONTLIGHT root["hasFrontlight"] = true; - root["flMaxBrightness"] = preferences.getUInt("flMaxBrightness", 4095); + root["flMaxBrightness"] = preferences.getUInt("flMaxBrightness", 2048); root["flAlwaysOn"] = preferences.getBool("flAlwaysOn", false); + root["flEffectDelay"] = preferences.getUInt("flEffectDelay"); + root["flFlashOnUpd"] = preferences.getBool("flFlashOnUpd", false); #else root["hasFrontlight"] = false; @@ -1035,6 +1041,26 @@ void onApiFrontlightStatus(AsyncWebServerRequest *request) request->send(response); } +void onApiFrontlightFlash(AsyncWebServerRequest *request) +{ + frontlightFlash(preferences.getUInt("flEffectDelay")); + + request->send(200); +} + +void onApiFrontlightSetBrightness(AsyncWebServerRequest *request) +{ + if (request->hasParam("b")) + { + frontlightSetBrightness(request->getParam("b")->value().toInt()); + request->send(200); + } + else + { + request->send(400); + } +} + void onApiFrontlightOff(AsyncWebServerRequest *request) { frontlightFadeOutAll(); diff --git a/src/lib/webserver.hpp b/src/lib/webserver.hpp index 21b2ca0..817869a 100644 --- a/src/lib/webserver.hpp +++ b/src/lib/webserver.hpp @@ -58,6 +58,9 @@ void onApiRestartDataSources(AsyncWebServerRequest *request); #ifdef HAS_FRONTLIGHT void onApiFrontlightOn(AsyncWebServerRequest *request); +void onApiFrontlightFlash(AsyncWebServerRequest *request); +void onApiFrontlightSetBrightness(AsyncWebServerRequest *request); + void onApiFrontlightStatus(AsyncWebServerRequest *request); void onApiFrontlightOff(AsyncWebServerRequest *request); #endif \ No newline at end of file