Refactor LedHandler to a class
This commit is contained in:
parent
ac13098824
commit
d023643090
11 changed files with 931 additions and 935 deletions
|
@ -1,4 +1,5 @@
|
||||||
#include "block_notify.hpp"
|
#include "block_notify.hpp"
|
||||||
|
#include "led_handler.hpp"
|
||||||
|
|
||||||
char *wsServer;
|
char *wsServer;
|
||||||
esp_websocket_client_handle_t blockNotifyClient = NULL;
|
esp_websocket_client_handle_t blockNotifyClient = NULL;
|
||||||
|
@ -217,7 +218,7 @@ void processNewBlock(uint32_t newBlockHeight) {
|
||||||
if (preferences.getBool("ledFlashOnUpd", DEFAULT_LED_FLASH_ON_UPD))
|
if (preferences.getBool("ledFlashOnUpd", DEFAULT_LED_FLASH_ON_UPD))
|
||||||
{
|
{
|
||||||
vTaskDelay(pdMS_TO_TICKS(250)); // Wait until screens are updated
|
vTaskDelay(pdMS_TO_TICKS(250)); // Wait until screens are updated
|
||||||
queueLedEffect(LED_FLASH_BLOCK_NOTIFY);
|
getLedHandler().queueEffect(LED_FLASH_BLOCK_NOTIFY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
#include "led_handler.hpp"
|
||||||
|
|
||||||
#define MAX_ATTEMPTS_WIFI_CONNECTION 20
|
#define MAX_ATTEMPTS_WIFI_CONNECTION 20
|
||||||
|
|
||||||
|
@ -50,7 +51,8 @@ void setup()
|
||||||
setupDisplays();
|
setupDisplays();
|
||||||
if (preferences.getBool("ledTestOnPower", DEFAULT_LED_TEST_ON_POWER))
|
if (preferences.getBool("ledTestOnPower", DEFAULT_LED_TEST_ON_POWER))
|
||||||
{
|
{
|
||||||
queueLedEffect(LED_POWER_TEST);
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.queueEffect(LED_POWER_TEST);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
||||||
|
@ -60,7 +62,8 @@ void setup()
|
||||||
preferences.remove("txPower");
|
preferences.remove("txPower");
|
||||||
|
|
||||||
WiFi.eraseAP();
|
WiFi.eraseAP();
|
||||||
queueLedEffect(LED_EFFECT_WIFI_ERASE_SETTINGS);
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.queueEffect(LED_EFFECT_WIFI_ERASE_SETTINGS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +79,8 @@ void setup()
|
||||||
else if (mcp1.read1(1) == LOW)
|
else if (mcp1.read1(1) == LOW)
|
||||||
{
|
{
|
||||||
preferences.clear();
|
preferences.clear();
|
||||||
queueLedEffect(LED_EFFECT_WIFI_ERASE_SETTINGS);
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.queueEffect(LED_EFFECT_WIFI_ERASE_SETTINGS);
|
||||||
nvs_flash_erase();
|
nvs_flash_erase();
|
||||||
delay(1000);
|
delay(1000);
|
||||||
|
|
||||||
|
@ -116,13 +120,13 @@ void setup()
|
||||||
#ifdef HAS_FRONTLIGHT
|
#ifdef HAS_FRONTLIGHT
|
||||||
if (!preferences.getBool("flAlwaysOn", DEFAULT_FL_ALWAYS_ON))
|
if (!preferences.getBool("flAlwaysOn", DEFAULT_FL_ALWAYS_ON))
|
||||||
{
|
{
|
||||||
frontlightFadeOutAll(preferences.getUInt("flEffectDelay"), true);
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.frontlightFadeOutAll(preferences.getUInt("flEffectDelay"), true);
|
||||||
flArray.allOFF();
|
flArray.allOFF();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
forceFullRefresh();
|
forceFullRefresh();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupWifi()
|
void setupWifi()
|
||||||
|
@ -144,7 +148,8 @@ void setupWifi()
|
||||||
// if (!preferences.getBool("wifiConfigured", DEFAULT_WIFI_CONFIGURED)
|
// if (!preferences.getBool("wifiConfigured", DEFAULT_WIFI_CONFIGURED)
|
||||||
{
|
{
|
||||||
|
|
||||||
queueLedEffect(LED_EFFECT_WIFI_WAIT_FOR_CONFIG);
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.queueEffect(LED_EFFECT_WIFI_WAIT_FOR_CONFIG);
|
||||||
|
|
||||||
bool buttonPress = false;
|
bool buttonPress = false;
|
||||||
{
|
{
|
||||||
|
@ -279,7 +284,8 @@ void syncTime()
|
||||||
|
|
||||||
while (!getLocalTime(&timeinfo))
|
while (!getLocalTime(&timeinfo))
|
||||||
{
|
{
|
||||||
queueLedEffect(LED_EFFECT_CONFIGURING);
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.queueEffect(LED_EFFECT_CONFIGURING);
|
||||||
configTime(preferences.getInt("gmtOffset", DEFAULT_TIME_OFFSET_SECONDS), 0,
|
configTime(preferences.getInt("gmtOffset", DEFAULT_TIME_OFFSET_SECONDS), 0,
|
||||||
NTP_SERVER);
|
NTP_SERVER);
|
||||||
delay(500);
|
delay(500);
|
||||||
|
@ -420,13 +426,14 @@ void setupTimers()
|
||||||
|
|
||||||
void finishSetup()
|
void finishSetup()
|
||||||
{
|
{
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
if (preferences.getBool("ledStatus", DEFAULT_LED_STATUS))
|
if (preferences.getBool("ledStatus", DEFAULT_LED_STATUS))
|
||||||
{
|
{
|
||||||
restoreLedState();
|
ledHandler.restoreLedState();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clearLeds();
|
ledHandler.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,22 +482,9 @@ void setupHardware()
|
||||||
Serial.println(F("Error loading WebUI"));
|
Serial.println(F("Error loading WebUI"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// {
|
// Initialize LED handler
|
||||||
// File f = LittleFS.open("/qr.txt", "w");
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.setup();
|
||||||
// if(f) {
|
|
||||||
// if (f.print("Hello")) {
|
|
||||||
// Serial.println(F("Written QR to FS"));
|
|
||||||
// Serial.printf("\nLittleFS free: %zu\n", LittleFS.totalBytes() - LittleFS.usedBytes());
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// Serial.println(F("Can't write QR to FS"));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// f.close();
|
|
||||||
// }
|
|
||||||
|
|
||||||
setupLeds();
|
|
||||||
|
|
||||||
WiFi.setHostname(getMyHostname().c_str());
|
WiFi.setHostname(getMyHostname().c_str());
|
||||||
if (!psramInit())
|
if (!psramInit())
|
||||||
|
@ -548,7 +542,8 @@ void setupHardware()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAS_FRONTLIGHT
|
#ifdef HAS_FRONTLIGHT
|
||||||
setupFrontlight();
|
// Initialize frontlight through LedHandler
|
||||||
|
ledHandler.initializeFrontlight();
|
||||||
|
|
||||||
Wire.beginTransmission(0x5C);
|
Wire.beginTransmission(0x5C);
|
||||||
byte error = Wire.endTransmission();
|
byte error = Wire.endTransmission();
|
||||||
|
@ -570,6 +565,7 @@ void setupHardware()
|
||||||
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
|
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
|
||||||
{
|
{
|
||||||
static bool first_connect = true;
|
static bool first_connect = true;
|
||||||
|
auto& ledHandler = getLedHandler(); // Get ledHandler reference once at the start
|
||||||
|
|
||||||
Serial.printf("[WiFi-event] event: %d\n", event);
|
Serial.printf("[WiFi-event] event: %d\n", event);
|
||||||
|
|
||||||
|
@ -595,7 +591,7 @@ void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
|
||||||
if (!first_connect)
|
if (!first_connect)
|
||||||
{
|
{
|
||||||
Serial.println(F("Disconnected from WiFi access point"));
|
Serial.println(F("Disconnected from WiFi access point"));
|
||||||
queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
|
ledHandler.queueEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
|
||||||
uint8_t reason = info.wifi_sta_disconnected.reason;
|
uint8_t reason = info.wifi_sta_disconnected.reason;
|
||||||
if (reason)
|
if (reason)
|
||||||
Serial.printf("Disconnect reason: %s, ",
|
Serial.printf("Disconnect reason: %s, ",
|
||||||
|
@ -611,13 +607,13 @@ void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
|
||||||
Serial.print("Obtained IP address: ");
|
Serial.print("Obtained IP address: ");
|
||||||
Serial.println(WiFi.localIP());
|
Serial.println(WiFi.localIP());
|
||||||
if (!first_connect)
|
if (!first_connect)
|
||||||
queueLedEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
ledHandler.queueEffect(LED_EFFECT_WIFI_CONNECT_SUCCESS);
|
||||||
first_connect = false;
|
first_connect = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
|
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
|
||||||
Serial.println(F("Lost IP address and IP address is reset to 0"));
|
Serial.println(F("Lost IP address and IP address is reset to 0"));
|
||||||
queueLedEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
|
ledHandler.queueEffect(LED_EFFECT_WIFI_CONNECT_ERROR);
|
||||||
WiFi.reconnect();
|
WiFi.reconnect();
|
||||||
break;
|
break;
|
||||||
case ARDUINO_EVENT_WIFI_AP_START:
|
case ARDUINO_EVENT_WIFI_AP_START:
|
||||||
|
@ -667,30 +663,6 @@ uint getLastTimeSync()
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAS_FRONTLIGHT
|
#ifdef HAS_FRONTLIGHT
|
||||||
void setupFrontlight()
|
|
||||||
{
|
|
||||||
if (!flArray.begin(PCA9685_MODE1_AUTOINCR | PCA9685_MODE1_ALLCALL, PCA9685_MODE2_TOTEMPOLE))
|
|
||||||
{
|
|
||||||
Serial.println(F("FL driver error"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
flArray.setFrequency(200);
|
|
||||||
Serial.println(F("FL driver active"));
|
|
||||||
|
|
||||||
if (!preferences.isKey("flMaxBrightness"))
|
|
||||||
{
|
|
||||||
preferences.putUInt("flMaxBrightness", DEFAULT_FL_MAX_BRIGHTNESS);
|
|
||||||
}
|
|
||||||
if (!preferences.isKey("flEffectDelay"))
|
|
||||||
{
|
|
||||||
preferences.putUInt("flEffectDelay", DEFAULT_FL_EFFECT_DELAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!preferences.isKey("flFlashOnUpd"))
|
|
||||||
{
|
|
||||||
preferences.putBool("flFlashOnUpd", DEFAULT_FL_FLASH_ON_UPDATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float getLightLevel()
|
float getLightLevel()
|
||||||
{
|
{
|
||||||
|
|
|
@ -52,10 +52,10 @@ void setupTimers();
|
||||||
void finishSetup();
|
void finishSetup();
|
||||||
void setupMcp();
|
void setupMcp();
|
||||||
#ifdef HAS_FRONTLIGHT
|
#ifdef HAS_FRONTLIGHT
|
||||||
void setupFrontlight();
|
extern BH1750 bh1750;
|
||||||
|
extern bool hasLuxSensor;
|
||||||
float getLightLevel();
|
float getLightLevel();
|
||||||
bool hasLightLevel();
|
bool hasLightLevel();
|
||||||
extern PCA9685 flArray;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
String getMyHostname();
|
String getMyHostname();
|
||||||
|
@ -98,6 +98,10 @@ extern MCP23017 mcp1;
|
||||||
extern MCP23017 mcp2;
|
extern MCP23017 mcp2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_FRONTLIGHT
|
||||||
|
extern PCA9685 flArray;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Expose DataSourceType enum
|
// Expose DataSourceType enum
|
||||||
extern DataSourceType getDataSource();
|
extern DataSourceType getDataSource();
|
||||||
extern void setDataSource(DataSourceType source);
|
extern void setDataSource(DataSourceType source);
|
|
@ -140,8 +140,6 @@ const GFXfont *FONT_SATSYMBOL;
|
||||||
std::mutex epdUpdateMutex;
|
std::mutex epdUpdateMutex;
|
||||||
std::mutex epdMutex[NUM_SCREENS];
|
std::mutex epdMutex[NUM_SCREENS];
|
||||||
|
|
||||||
uint8_t qrcode[800];
|
|
||||||
|
|
||||||
#ifdef IS_BTCLOCK_V8
|
#ifdef IS_BTCLOCK_V8
|
||||||
#define EPD_TASK_STACK_SIZE 4096
|
#define EPD_TASK_STACK_SIZE 4096
|
||||||
#else
|
#else
|
||||||
|
@ -159,8 +157,6 @@ void forceFullRefresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GFXfont font90;
|
|
||||||
|
|
||||||
void loadFonts(const String& fontName) {
|
void loadFonts(const String& fontName) {
|
||||||
if (fontName == FontNames::ANTONIO) {
|
if (fontName == FontNames::ANTONIO) {
|
||||||
// Load Antonio fonts
|
// Load Antonio fonts
|
||||||
|
@ -628,35 +624,45 @@ bool renderIcon(const uint dispNum, const String &text, bool partial)
|
||||||
void renderQr(const uint dispNum, const String &text, bool partial)
|
void renderQr(const uint dispNum, const String &text, bool partial)
|
||||||
{
|
{
|
||||||
#ifdef USE_QR
|
#ifdef USE_QR
|
||||||
|
// Dynamically allocate QR buffer
|
||||||
|
uint8_t* qrcode = (uint8_t*)malloc(qrcodegen_BUFFER_LEN_MAX);
|
||||||
|
if (!qrcode) {
|
||||||
|
log_e("Failed to allocate QR buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t tempBuffer[800];
|
uint8_t tempBuffer[800];
|
||||||
bool ok = qrcodegen_encodeText(
|
bool ok = qrcodegen_encodeText(
|
||||||
text.substring(2).c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW,
|
text.substring(2).c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW,
|
||||||
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
|
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
|
||||||
|
|
||||||
const int size = qrcodegen_getSize(qrcode);
|
if (ok) {
|
||||||
|
const int size = qrcodegen_getSize(qrcode);
|
||||||
|
const int padding = floor(float(displays[dispNum].width() - (size * 4)) / 2);
|
||||||
|
const int paddingY =
|
||||||
|
floor(float(displays[dispNum].height() - (size * 4)) / 2);
|
||||||
|
displays[dispNum].setRotation(2);
|
||||||
|
|
||||||
const int padding = floor(float(displays[dispNum].width() - (size * 4)) / 2);
|
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(),
|
||||||
const int paddingY =
|
displays[dispNum].height());
|
||||||
floor(float(displays[dispNum].height() - (size * 4)) / 2);
|
displays[dispNum].fillScreen(GxEPD_WHITE);
|
||||||
displays[dispNum].setRotation(2);
|
const int border = 0;
|
||||||
|
|
||||||
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(),
|
for (int y = -border; y < size * 4 + border; y++)
|
||||||
displays[dispNum].height());
|
|
||||||
displays[dispNum].fillScreen(GxEPD_WHITE);
|
|
||||||
const int border = 0;
|
|
||||||
|
|
||||||
for (int y = -border; y < size * 4 + border; y++)
|
|
||||||
{
|
|
||||||
for (int x = -border; x < size * 4 + border; x++)
|
|
||||||
{
|
{
|
||||||
displays[dispNum].drawPixel(
|
for (int x = -border; x < size * 4 + border; x++)
|
||||||
padding + x, paddingY + y,
|
{
|
||||||
qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4))
|
displays[dispNum].drawPixel(
|
||||||
? GxEPD_BLACK
|
padding + x, paddingY + y,
|
||||||
: GxEPD_WHITE);
|
qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4))
|
||||||
|
? GxEPD_BLACK
|
||||||
|
: GxEPD_WHITE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Free the buffer after we're done
|
||||||
|
free(qrcode);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,6 +4,7 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "lib/shared.hpp"
|
#include "lib/shared.hpp"
|
||||||
#include "lib/webserver.hpp"
|
#include "lib/webserver.hpp"
|
||||||
|
@ -15,12 +16,11 @@
|
||||||
#define NEOPIXEL_COUNT 4
|
#define NEOPIXEL_COUNT 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// LED effect constants
|
||||||
const int LED_FLASH_ERROR = 0;
|
const int LED_FLASH_ERROR = 0;
|
||||||
const int LED_FLASH_SUCCESS = 1;
|
const int LED_FLASH_SUCCESS = 1;
|
||||||
const int LED_FLASH_UPDATE = 2;
|
const int LED_FLASH_UPDATE = 2;
|
||||||
|
|
||||||
const int LED_EFFECT_CONFIGURING = 10;
|
const int LED_EFFECT_CONFIGURING = 10;
|
||||||
|
|
||||||
const int LED_FLASH_BLOCK_NOTIFY = 4;
|
const int LED_FLASH_BLOCK_NOTIFY = 4;
|
||||||
const int LED_EFFECT_START_TIMER = 5;
|
const int LED_EFFECT_START_TIMER = 5;
|
||||||
const int LED_EFFECT_PAUSE_TIMER = 6;
|
const int LED_EFFECT_PAUSE_TIMER = 6;
|
||||||
|
@ -30,61 +30,15 @@ const int LED_EFFECT_WIFI_CONNECTING = 101;
|
||||||
const int LED_EFFECT_WIFI_CONNECT_ERROR = 102;
|
const int LED_EFFECT_WIFI_CONNECT_ERROR = 102;
|
||||||
const int LED_EFFECT_WIFI_CONNECT_SUCCESS = 103;
|
const int LED_EFFECT_WIFI_CONNECT_SUCCESS = 103;
|
||||||
const int LED_EFFECT_WIFI_ERASE_SETTINGS = 104;
|
const int LED_EFFECT_WIFI_ERASE_SETTINGS = 104;
|
||||||
|
|
||||||
const int LED_PROGRESS_25 = 200;
|
const int LED_PROGRESS_25 = 200;
|
||||||
const int LED_PROGRESS_50 = 201;
|
const int LED_PROGRESS_50 = 201;
|
||||||
const int LED_PROGRESS_75 = 202;
|
const int LED_PROGRESS_75 = 202;
|
||||||
const int LED_PROGRESS_100 = 203;
|
const int LED_PROGRESS_100 = 203;
|
||||||
|
|
||||||
const int LED_DATA_PRICE_ERROR = 300;
|
const int LED_DATA_PRICE_ERROR = 300;
|
||||||
const int LED_DATA_BLOCK_ERROR = 301;
|
const int LED_DATA_BLOCK_ERROR = 301;
|
||||||
|
|
||||||
const int LED_EFFECT_NOSTR_ZAP = 400;
|
const int LED_EFFECT_NOSTR_ZAP = 400;
|
||||||
|
|
||||||
const int LED_FLASH_IDENTIFY = 990;
|
const int LED_FLASH_IDENTIFY = 990;
|
||||||
const int LED_POWER_TEST = 999;
|
const int LED_POWER_TEST = 999;
|
||||||
extern TaskHandle_t ledTaskHandle;
|
|
||||||
extern Adafruit_NeoPixel pixels;
|
|
||||||
|
|
||||||
void ledTask(void *pvParameters);
|
|
||||||
void setupLeds();
|
|
||||||
void setupLedTask();
|
|
||||||
void blinkDelay(int d, int times);
|
|
||||||
void blinkDelayColor(int d, int times, uint r, uint g, uint b);
|
|
||||||
void blinkDelayTwoColor(int d, int times, const uint32_t& c1, const uint32_t& c2);
|
|
||||||
void clearLeds();
|
|
||||||
void saveLedState();
|
|
||||||
void restoreLedState();
|
|
||||||
QueueHandle_t getLedTaskQueue();
|
|
||||||
bool queueLedEffect(uint effect);
|
|
||||||
void setLights(int r, int g, int b);
|
|
||||||
void setLights(uint32_t color);
|
|
||||||
void ledRainbow(int wait);
|
|
||||||
void ledTheaterChaseRainbow(int wait);
|
|
||||||
void ledTheaterChase(uint32_t color, int wait);
|
|
||||||
Adafruit_NeoPixel getPixels();
|
|
||||||
void lightningStrike();
|
|
||||||
|
|
||||||
#ifdef HAS_FRONTLIGHT
|
|
||||||
void frontlightFlash(int flDelayTime);
|
|
||||||
void frontlightFadeInAll();
|
|
||||||
void frontlightFadeOutAll();
|
|
||||||
void frontlightFadeIn(uint num);
|
|
||||||
void frontlightFadeOut(uint num);
|
|
||||||
|
|
||||||
std::vector<uint16_t> frontlightGetStatus();
|
|
||||||
|
|
||||||
void frontlightSetBrightness(uint brightness);
|
|
||||||
bool frontlightIsOn();
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
// Do Not Disturb mode settings
|
// Do Not Disturb mode settings
|
||||||
struct DNDTimeRange {
|
struct DNDTimeRange {
|
||||||
|
@ -94,12 +48,88 @@ struct DNDTimeRange {
|
||||||
uint8_t endMinute;
|
uint8_t endMinute;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool dndEnabled;
|
class LedHandler {
|
||||||
extern bool dndTimeBasedEnabled;
|
public:
|
||||||
extern DNDTimeRange dndTimeRange;
|
static LedHandler& getInstance();
|
||||||
|
|
||||||
|
// Delete copy constructor and assignment operator
|
||||||
|
LedHandler(const LedHandler&) = delete;
|
||||||
|
LedHandler& operator=(const LedHandler&) = delete;
|
||||||
|
|
||||||
void setDNDEnabled(bool enabled);
|
void setup();
|
||||||
void setDNDTimeBasedEnabled(bool enabled);
|
void setupTask();
|
||||||
void setDNDTimeRange(uint8_t startHour, uint8_t startMinute, uint8_t endHour, uint8_t endMinute);
|
bool queueEffect(uint effect);
|
||||||
bool isDNDActive();
|
void clear();
|
||||||
bool isTimeInDNDRange(uint8_t hour, uint8_t minute);
|
void setLights(int r, int g, int b);
|
||||||
|
void setLights(uint32_t color);
|
||||||
|
void saveLedState();
|
||||||
|
void restoreLedState();
|
||||||
|
QueueHandle_t getTaskQueue() const { return ledTaskQueue; }
|
||||||
|
Adafruit_NeoPixel& getPixels() { return pixels; }
|
||||||
|
|
||||||
|
// DND methods
|
||||||
|
void setDNDEnabled(bool enabled);
|
||||||
|
void setDNDTimeBasedEnabled(bool enabled);
|
||||||
|
void setDNDTimeRange(uint8_t startHour, uint8_t startMinute, uint8_t endHour, uint8_t endMinute);
|
||||||
|
bool isDNDActive() const;
|
||||||
|
bool isTimeInDNDRange(uint8_t hour, uint8_t minute) const;
|
||||||
|
|
||||||
|
// DND getters
|
||||||
|
bool isDNDEnabled() const { return dndEnabled; }
|
||||||
|
bool isDNDTimeBasedEnabled() const { return dndTimeBasedEnabled; }
|
||||||
|
uint8_t getDNDStartHour() const { return dndTimeRange.startHour; }
|
||||||
|
uint8_t getDNDStartMinute() const { return dndTimeRange.startMinute; }
|
||||||
|
uint8_t getDNDEndHour() const { return dndTimeRange.endHour; }
|
||||||
|
uint8_t getDNDEndMinute() const { return dndTimeRange.endMinute; }
|
||||||
|
|
||||||
|
// Effect methods
|
||||||
|
void rainbow(int wait);
|
||||||
|
void theaterChase(uint32_t color, int wait);
|
||||||
|
void theaterChaseRainbow(int wait);
|
||||||
|
void lightningStrike();
|
||||||
|
void blinkDelay(int d, int times);
|
||||||
|
void blinkDelayColor(int d, int times, uint r, uint g, uint b);
|
||||||
|
void blinkDelayTwoColor(int d, int times, const uint32_t& c1, const uint32_t& c2);
|
||||||
|
|
||||||
|
#ifdef HAS_FRONTLIGHT
|
||||||
|
void frontlightFlash(int flDelayTime);
|
||||||
|
void frontlightFadeInAll();
|
||||||
|
void frontlightFadeOutAll();
|
||||||
|
void frontlightFadeIn(uint num);
|
||||||
|
void frontlightFadeOut(uint num);
|
||||||
|
std::vector<uint16_t> frontlightGetStatus();
|
||||||
|
void frontlightSetBrightness(uint brightness);
|
||||||
|
bool frontlightIsOn() const { return frontlightOn; }
|
||||||
|
void frontlightFadeInAll(int flDelayTime, bool staggered = false);
|
||||||
|
void frontlightFadeOutAll(int flDelayTime, bool staggered = false);
|
||||||
|
void frontlightFadeIn(uint num, int flDelayTime);
|
||||||
|
void frontlightFadeOut(uint num, int flDelayTime);
|
||||||
|
void initializeFrontlight();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
LedHandler(); // Private constructor for singleton
|
||||||
|
void loadDNDSettings();
|
||||||
|
static void ledTask(void* pvParameters);
|
||||||
|
|
||||||
|
Adafruit_NeoPixel pixels;
|
||||||
|
TaskHandle_t ledTaskHandle;
|
||||||
|
QueueHandle_t ledTaskQueue;
|
||||||
|
uint ledTaskParams;
|
||||||
|
|
||||||
|
// DND members
|
||||||
|
bool dndEnabled;
|
||||||
|
bool dndTimeBasedEnabled;
|
||||||
|
DNDTimeRange dndTimeRange;
|
||||||
|
|
||||||
|
#ifdef HAS_FRONTLIGHT
|
||||||
|
static constexpr uint16_t FL_FADE_STEP = 25;
|
||||||
|
bool frontlightOn;
|
||||||
|
bool flInTransition;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// Global accessor function
|
||||||
|
inline LedHandler& getLedHandler() {
|
||||||
|
return LedHandler::getInstance();
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
#include "nostr_notify.hpp"
|
#include "nostr_notify.hpp"
|
||||||
|
#include "led_handler.hpp"
|
||||||
|
|
||||||
std::vector<nostr::NostrPool *> pools;
|
std::vector<nostr::NostrPool *> pools;
|
||||||
nostr::Transport *transport;
|
nostr::Transport *transport;
|
||||||
|
@ -286,7 +287,7 @@ void handleNostrZapCallback(const String &subId, nostr::SignedNostrEvent *event)
|
||||||
vTaskDelay(pdMS_TO_TICKS(315 * NUM_SCREENS) + pdMS_TO_TICKS(250));
|
vTaskDelay(pdMS_TO_TICKS(315 * NUM_SCREENS) + pdMS_TO_TICKS(250));
|
||||||
if (preferences.getBool("ledFlashOnZap", DEFAULT_LED_FLASH_ON_ZAP))
|
if (preferences.getBool("ledFlashOnZap", DEFAULT_LED_FLASH_ON_ZAP))
|
||||||
{
|
{
|
||||||
queueLedEffect(LED_EFFECT_NOSTR_ZAP);
|
getLedHandler().queueEffect(LED_EFFECT_NOSTR_ZAP);
|
||||||
}
|
}
|
||||||
if (timerPeriod > 0)
|
if (timerPeriod > 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "ota.hpp"
|
#include "ota.hpp"
|
||||||
|
#include "led_handler.hpp"
|
||||||
|
|
||||||
TaskHandle_t taskOtaHandle = NULL;
|
TaskHandle_t taskOtaHandle = NULL;
|
||||||
bool isOtaUpdating = false;
|
bool isOtaUpdating = false;
|
||||||
|
@ -31,6 +32,9 @@ void setupOTA()
|
||||||
void onOTAProgress(unsigned int progress, unsigned int total)
|
void onOTAProgress(unsigned int progress, unsigned int total)
|
||||||
{
|
{
|
||||||
uint percentage = progress / (total / 100);
|
uint percentage = progress / (total / 100);
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
|
auto& pixels = ledHandler.getPixels();
|
||||||
|
|
||||||
pixels.fill(pixels.Color(0, 255, 0));
|
pixels.fill(pixels.Color(0, 255, 0));
|
||||||
if (percentage < 100)
|
if (percentage < 100)
|
||||||
{
|
{
|
||||||
|
@ -84,15 +88,15 @@ void handleOTATask(void *parameter)
|
||||||
{
|
{
|
||||||
if (msg.updateType == UPDATE_ALL) {
|
if (msg.updateType == UPDATE_ALL) {
|
||||||
isOtaUpdating = true;
|
isOtaUpdating = true;
|
||||||
queueLedEffect(LED_FLASH_UPDATE);
|
getLedHandler().queueEffect(LED_FLASH_UPDATE);
|
||||||
int resultWebUi = downloadUpdateHandler(UPDATE_WEBUI);
|
int resultWebUi = downloadUpdateHandler(UPDATE_WEBUI);
|
||||||
queueLedEffect(LED_FLASH_UPDATE);
|
getLedHandler().queueEffect(LED_FLASH_UPDATE);
|
||||||
int resultFw = downloadUpdateHandler(UPDATE_FIRMWARE);
|
int resultFw = downloadUpdateHandler(UPDATE_FIRMWARE);
|
||||||
|
|
||||||
if (resultWebUi == 0 && resultFw == 0) {
|
if (resultWebUi == 0 && resultFw == 0) {
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
} else {
|
} else {
|
||||||
queueLedEffect(LED_FLASH_ERROR);
|
getLedHandler().queueEffect(LED_FLASH_ERROR);
|
||||||
vTaskDelay(pdMS_TO_TICKS(3000));
|
vTaskDelay(pdMS_TO_TICKS(3000));
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "timers.hpp"
|
#include "timers.hpp"
|
||||||
|
#include "led_handler.hpp"
|
||||||
|
|
||||||
esp_timer_handle_t screenRotateTimer;
|
esp_timer_handle_t screenRotateTimer;
|
||||||
esp_timer_handle_t minuteTimer;
|
esp_timer_handle_t minuteTimer;
|
||||||
|
@ -49,11 +50,11 @@ void setTimerActive(bool status) {
|
||||||
if (status) {
|
if (status) {
|
||||||
esp_timer_start_periodic(screenRotateTimer,
|
esp_timer_start_periodic(screenRotateTimer,
|
||||||
getTimerSeconds() * usPerSecond);
|
getTimerSeconds() * usPerSecond);
|
||||||
queueLedEffect(LED_EFFECT_START_TIMER);
|
getLedHandler().queueEffect(LED_EFFECT_START_TIMER);
|
||||||
preferences.putBool("timerActive", true);
|
preferences.putBool("timerActive", true);
|
||||||
} else {
|
} else {
|
||||||
esp_timer_stop(screenRotateTimer);
|
esp_timer_stop(screenRotateTimer);
|
||||||
queueLedEffect(LED_EFFECT_PAUSE_TIMER);
|
getLedHandler().queueEffect(LED_EFFECT_PAUSE_TIMER);
|
||||||
preferences.putBool("timerActive", false);
|
preferences.putBool("timerActive", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#include "webserver.hpp"
|
#include "webserver.hpp"
|
||||||
|
#include "lib/led_handler.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
|
|
||||||
static const char* JSON_CONTENT = "application/json";
|
static const char* JSON_CONTENT = "application/json";
|
||||||
|
|
||||||
|
@ -231,6 +233,7 @@ void asyncFirmwareUpdateHandler(AsyncWebServerRequest *request, String filename,
|
||||||
|
|
||||||
JsonDocument getStatusObject()
|
JsonDocument getStatusObject()
|
||||||
{
|
{
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
JsonDocument root;
|
JsonDocument root;
|
||||||
|
|
||||||
root["currentScreen"] = ScreenHandler::getCurrentScreen();
|
root["currentScreen"] = ScreenHandler::getCurrentScreen();
|
||||||
|
@ -238,25 +241,21 @@ JsonDocument getStatusObject()
|
||||||
root["timerRunning"] = isTimerActive();
|
root["timerRunning"] = isTimerActive();
|
||||||
root["isOTAUpdating"] = getIsOTAUpdating();
|
root["isOTAUpdating"] = getIsOTAUpdating();
|
||||||
root["espUptime"] = esp_timer_get_time() / 1000000;
|
root["espUptime"] = esp_timer_get_time() / 1000000;
|
||||||
// root["currentPrice"] = getPrice();
|
|
||||||
// root["currentBlockHeight"] = getBlockHeight();
|
|
||||||
root["espFreeHeap"] = ESP.getFreeHeap();
|
root["espFreeHeap"] = ESP.getFreeHeap();
|
||||||
root["espHeapSize"] = ESP.getHeapSize();
|
root["espHeapSize"] = ESP.getHeapSize();
|
||||||
// root["espFreePsram"] = ESP.getFreePsram();
|
|
||||||
// root["espPsramSize"] = ESP.getPsramSize();
|
|
||||||
|
|
||||||
JsonObject conStatus = root["connectionStatus"].to<JsonObject>();
|
JsonObject conStatus = root["connectionStatus"].to<JsonObject>();
|
||||||
|
|
||||||
conStatus["price"] = isPriceNotifyConnected();
|
conStatus["price"] = isPriceNotifyConnected();
|
||||||
conStatus["blocks"] = isBlockNotifyConnected();
|
conStatus["blocks"] = isBlockNotifyConnected();
|
||||||
conStatus["V2"] = V2Notify::isV2NotifyConnected();
|
conStatus["V2"] = V2Notify::isV2NotifyConnected();
|
||||||
|
|
||||||
conStatus["nostr"] = nostrConnected();
|
conStatus["nostr"] = nostrConnected();
|
||||||
|
|
||||||
root["rssi"] = WiFi.RSSI();
|
root["rssi"] = WiFi.RSSI();
|
||||||
root["currency"] = getCurrencyCode(ScreenHandler::getCurrentCurrency());
|
root["currency"] = getCurrencyCode(ScreenHandler::getCurrentCurrency());
|
||||||
|
|
||||||
#ifdef HAS_FRONTLIGHT
|
#ifdef HAS_FRONTLIGHT
|
||||||
std::vector<uint16_t> statuses = frontlightGetStatus();
|
std::vector<uint16_t> statuses = ledHandler.frontlightGetStatus();
|
||||||
uint16_t arr[NUM_SCREENS];
|
uint16_t arr[NUM_SCREENS];
|
||||||
std::copy(statuses.begin(), statuses.end(), arr);
|
std::copy(statuses.begin(), statuses.end(), arr);
|
||||||
|
|
||||||
|
@ -270,22 +269,24 @@ JsonDocument getStatusObject()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add DND status
|
// Add DND status
|
||||||
root["dnd"]["enabled"] = dndEnabled;
|
root["dnd"]["enabled"] = ledHandler.isDNDEnabled();
|
||||||
root["dnd"]["timeBasedEnabled"] = dndTimeBasedEnabled;
|
root["dnd"]["timeBasedEnabled"] = ledHandler.isDNDTimeBasedEnabled();
|
||||||
root["dnd"]["startTime"] = String(dndTimeRange.startHour) + ":" +
|
root["dnd"]["startTime"] = String(ledHandler.getDNDStartHour()) + ":" +
|
||||||
(dndTimeRange.startMinute < 10 ? "0" : "") + String(dndTimeRange.startMinute);
|
(ledHandler.getDNDStartMinute() < 10 ? "0" : "") + String(ledHandler.getDNDStartMinute());
|
||||||
root["dnd"]["endTime"] = String(dndTimeRange.endHour) + ":" +
|
root["dnd"]["endTime"] = String(ledHandler.getDNDEndHour()) + ":" +
|
||||||
(dndTimeRange.endMinute < 10 ? "0" : "") + String(dndTimeRange.endMinute);
|
(ledHandler.getDNDEndMinute() < 10 ? "0" : "") + String(ledHandler.getDNDEndMinute());
|
||||||
root["dnd"]["active"] = isDNDActive();
|
root["dnd"]["active"] = ledHandler.isDNDActive();
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonDocument getLedStatusObject()
|
JsonDocument getLedStatusObject()
|
||||||
{
|
{
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
|
auto& pixels = ledHandler.getPixels();
|
||||||
|
|
||||||
JsonDocument root;
|
JsonDocument root;
|
||||||
JsonArray colors = root["data"].to<JsonArray>();
|
JsonArray colors = root["data"].to<JsonArray>();
|
||||||
// Adafruit_NeoPixel pix = getPixels();
|
|
||||||
|
|
||||||
for (uint i = 0; i < pixels.numPixels(); i++)
|
for (uint i = 0; i < pixels.numPixels(); i++)
|
||||||
{
|
{
|
||||||
|
@ -295,13 +296,7 @@ JsonDocument getLedStatusObject()
|
||||||
uint blue = pixColor & 0xFF;
|
uint blue = pixColor & 0xFF;
|
||||||
char hexColor[8];
|
char hexColor[8];
|
||||||
snprintf(hexColor, sizeof(hexColor), "#%02X%02X%02X", red, green, blue);
|
snprintf(hexColor, sizeof(hexColor), "#%02X%02X%02X", red, green, blue);
|
||||||
|
colors.add(hexColor);
|
||||||
|
|
||||||
JsonObject object = colors.add<JsonObject>();
|
|
||||||
object["red"] = red;
|
|
||||||
object["green"] = green;
|
|
||||||
object["blue"] = blue;
|
|
||||||
object["hex"] = hexColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return root;
|
return root;
|
||||||
|
@ -621,24 +616,26 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
// Handle DND settings
|
// Handle DND settings
|
||||||
if (settings.containsKey("dnd")) {
|
if (settings.containsKey("dnd")) {
|
||||||
JsonObject dndObj = settings["dnd"];
|
JsonObject dndObj = settings["dnd"];
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
|
|
||||||
if (dndObj.containsKey("timeBasedEnabled")) {
|
if (dndObj.containsKey("timeBasedEnabled")) {
|
||||||
setDNDTimeBasedEnabled(dndObj["timeBasedEnabled"].as<bool>());
|
ledHandler.setDNDTimeBasedEnabled(dndObj["timeBasedEnabled"].as<bool>());
|
||||||
}
|
}
|
||||||
if (dndObj.containsKey("startHour") && dndObj.containsKey("startMinute") &&
|
if (dndObj.containsKey("startHour") && dndObj.containsKey("startMinute") &&
|
||||||
dndObj.containsKey("endHour") && dndObj.containsKey("endMinute")) {
|
dndObj.containsKey("endHour") && dndObj.containsKey("endMinute")) {
|
||||||
setDNDTimeRange(
|
ledHandler.setDNDTimeRange(
|
||||||
dndObj["startHour"].as<uint8_t>(),
|
dndObj["startHour"].as<uint8_t>(),
|
||||||
dndObj["startMinute"].as<uint8_t>(),
|
dndObj["startMinute"].as<uint8_t>(),
|
||||||
dndObj["endHour"].as<uint8_t>(),
|
dndObj["endHour"].as<uint8_t>(),
|
||||||
dndObj["endMinute"].as<uint8_t>()
|
dndObj["endMinute"].as<uint8_t>());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request->send(HTTP_OK);
|
request->send(HTTP_OK);
|
||||||
if (settingsChanged)
|
if (settingsChanged)
|
||||||
{
|
{
|
||||||
queueLedEffect(LED_FLASH_SUCCESS);
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.queueEffect(LED_FLASH_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -659,7 +656,8 @@ void onApiRestart(AsyncWebServerRequest *request)
|
||||||
|
|
||||||
void onApiIdentify(AsyncWebServerRequest *request)
|
void onApiIdentify(AsyncWebServerRequest *request)
|
||||||
{
|
{
|
||||||
queueLedEffect(LED_FLASH_IDENTIFY);
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.queueEffect(LED_FLASH_IDENTIFY);
|
||||||
|
|
||||||
request->send(HTTP_OK);
|
request->send(HTTP_OK);
|
||||||
}
|
}
|
||||||
|
@ -797,12 +795,13 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
|
||||||
root["ceDisableSSL"] = preferences.getBool("ceDisableSSL", DEFAULT_CUSTOM_ENDPOINT_DISABLE_SSL);
|
root["ceDisableSSL"] = preferences.getBool("ceDisableSSL", DEFAULT_CUSTOM_ENDPOINT_DISABLE_SSL);
|
||||||
|
|
||||||
// Add DND settings
|
// Add DND settings
|
||||||
root["dnd"]["enabled"] = dndEnabled;
|
auto& ledHandler = getLedHandler();
|
||||||
root["dnd"]["timeBasedEnabled"] = dndTimeBasedEnabled;
|
root["dnd"]["enabled"] = ledHandler.isDNDEnabled();
|
||||||
root["dnd"]["startHour"] = dndTimeRange.startHour;
|
root["dnd"]["timeBasedEnabled"] = ledHandler.isDNDTimeBasedEnabled();
|
||||||
root["dnd"]["startMinute"] = dndTimeRange.startMinute;
|
root["dnd"]["startHour"] = ledHandler.getDNDStartHour();
|
||||||
root["dnd"]["endHour"] = dndTimeRange.endHour;
|
root["dnd"]["startMinute"] = ledHandler.getDNDStartMinute();
|
||||||
root["dnd"]["endMinute"] = dndTimeRange.endMinute;
|
root["dnd"]["endHour"] = ledHandler.getDNDEndHour();
|
||||||
|
root["dnd"]["endMinute"] = ledHandler.getDNDEndMinute();
|
||||||
|
|
||||||
AsyncResponseStream *response =
|
AsyncResponseStream *response =
|
||||||
request->beginResponseStream(JSON_CONTENT);
|
request->beginResponseStream(JSON_CONTENT);
|
||||||
|
@ -929,7 +928,8 @@ void onApiRestartDataSources(AsyncWebServerRequest *request)
|
||||||
|
|
||||||
void onApiLightsOff(AsyncWebServerRequest *request)
|
void onApiLightsOff(AsyncWebServerRequest *request)
|
||||||
{
|
{
|
||||||
setLights(0, 0, 0);
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.setLights(0, 0, 0);
|
||||||
request->send(HTTP_OK);
|
request->send(HTTP_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -944,13 +944,15 @@ void onApiLightsSetColor(AsyncWebServerRequest *request)
|
||||||
|
|
||||||
if (rgbColor.compareTo("off") == 0)
|
if (rgbColor.compareTo("off") == 0)
|
||||||
{
|
{
|
||||||
setLights(0, 0, 0);
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.setLights(0, 0, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint r, g, b;
|
uint r, g, b;
|
||||||
sscanf(rgbColor.c_str(), "%02x%02x%02x", &r, &g, &b);
|
sscanf(rgbColor.c_str(), "%02x%02x%02x", &r, &g, &b);
|
||||||
setLights(r, g, b);
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.setLights(r, g, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
|
@ -968,6 +970,9 @@ void onApiLightsSetColor(AsyncWebServerRequest *request)
|
||||||
|
|
||||||
void onApiLightsSetJson(AsyncWebServerRequest *request, JsonVariant &json)
|
void onApiLightsSetJson(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
{
|
{
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
|
auto& pixels = ledHandler.getPixels();
|
||||||
|
|
||||||
JsonArray lights = json.as<JsonArray>();
|
JsonArray lights = json.as<JsonArray>();
|
||||||
|
|
||||||
if (lights.size() != pixels.numPixels())
|
if (lights.size() != pixels.numPixels())
|
||||||
|
@ -1016,7 +1021,7 @@ void onApiLightsSetJson(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
}
|
}
|
||||||
|
|
||||||
pixels.show();
|
pixels.show();
|
||||||
saveLedState();
|
ledHandler.saveLedState();
|
||||||
|
|
||||||
request->send(HTTP_OK);
|
request->send(HTTP_OK);
|
||||||
}
|
}
|
||||||
|
@ -1080,19 +1085,21 @@ void onApiShowCurrency(AsyncWebServerRequest *request)
|
||||||
#ifdef HAS_FRONTLIGHT
|
#ifdef HAS_FRONTLIGHT
|
||||||
void onApiFrontlightOn(AsyncWebServerRequest *request)
|
void onApiFrontlightOn(AsyncWebServerRequest *request)
|
||||||
{
|
{
|
||||||
frontlightFadeInAll();
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.frontlightFadeInAll();
|
||||||
|
|
||||||
request->send(HTTP_OK);
|
request->send(HTTP_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onApiFrontlightStatus(AsyncWebServerRequest *request)
|
void onApiFrontlightStatus(AsyncWebServerRequest *request)
|
||||||
{
|
{
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
AsyncResponseStream *response =
|
AsyncResponseStream *response =
|
||||||
request->beginResponseStream(JSON_CONTENT);
|
request->beginResponseStream(JSON_CONTENT);
|
||||||
|
|
||||||
JsonDocument root;
|
JsonDocument root;
|
||||||
|
|
||||||
std::vector<uint16_t> statuses = frontlightGetStatus();
|
std::vector<uint16_t> statuses = ledHandler.frontlightGetStatus();
|
||||||
uint16_t arr[NUM_SCREENS];
|
uint16_t arr[NUM_SCREENS];
|
||||||
std::copy(statuses.begin(), statuses.end(), arr);
|
std::copy(statuses.begin(), statuses.end(), arr);
|
||||||
|
|
||||||
|
@ -1105,7 +1112,8 @@ void onApiFrontlightStatus(AsyncWebServerRequest *request)
|
||||||
|
|
||||||
void onApiFrontlightFlash(AsyncWebServerRequest *request)
|
void onApiFrontlightFlash(AsyncWebServerRequest *request)
|
||||||
{
|
{
|
||||||
frontlightFlash(preferences.getUInt("flEffectDelay"));
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.frontlightFlash(preferences.getUInt("flEffectDelay"));
|
||||||
|
|
||||||
request->send(HTTP_OK);
|
request->send(HTTP_OK);
|
||||||
}
|
}
|
||||||
|
@ -1114,7 +1122,8 @@ void onApiFrontlightSetBrightness(AsyncWebServerRequest *request)
|
||||||
{
|
{
|
||||||
if (request->hasParam("b"))
|
if (request->hasParam("b"))
|
||||||
{
|
{
|
||||||
frontlightSetBrightness(request->getParam("b")->value().toInt());
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.frontlightSetBrightness(request->getParam("b")->value().toInt());
|
||||||
request->send(HTTP_OK);
|
request->send(HTTP_OK);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1125,21 +1134,51 @@ void onApiFrontlightSetBrightness(AsyncWebServerRequest *request)
|
||||||
|
|
||||||
void onApiFrontlightOff(AsyncWebServerRequest *request)
|
void onApiFrontlightOff(AsyncWebServerRequest *request)
|
||||||
{
|
{
|
||||||
frontlightFadeOutAll();
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.frontlightFadeOutAll();
|
||||||
|
|
||||||
request->send(HTTP_OK);
|
request->send(HTTP_OK);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void onApiDNDTimeBasedEnable(AsyncWebServerRequest *request) {
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.setDNDTimeBasedEnabled(true);
|
||||||
|
request->send(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onApiDNDTimeBasedDisable(AsyncWebServerRequest *request) {
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.setDNDTimeBasedEnabled(false);
|
||||||
|
request->send(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onApiDNDSetTimeRange(AsyncWebServerRequest *request) {
|
||||||
|
if (request->hasParam("startHour") && request->hasParam("startMinute") &&
|
||||||
|
request->hasParam("endHour") && request->hasParam("endMinute")) {
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
|
uint8_t startHour = request->getParam("startHour")->value().toInt();
|
||||||
|
uint8_t startMinute = request->getParam("startMinute")->value().toInt();
|
||||||
|
uint8_t endHour = request->getParam("endHour")->value().toInt();
|
||||||
|
uint8_t endMinute = request->getParam("endMinute")->value().toInt();
|
||||||
|
|
||||||
|
ledHandler.setDNDTimeRange(startHour, startMinute, endHour, endMinute);
|
||||||
|
request->send(200);
|
||||||
|
} else {
|
||||||
|
request->send(400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void onApiDNDStatus(AsyncWebServerRequest *request) {
|
void onApiDNDStatus(AsyncWebServerRequest *request) {
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc["enabled"] = dndEnabled;
|
doc["enabled"] = ledHandler.isDNDEnabled();
|
||||||
doc["timeBasedEnabled"] = dndTimeBasedEnabled;
|
doc["timeBasedEnabled"] = ledHandler.isDNDTimeBasedEnabled();
|
||||||
doc["startTime"] = String(dndTimeRange.startHour) + ":" +
|
doc["startTime"] = String(ledHandler.getDNDStartHour()) + ":" +
|
||||||
(dndTimeRange.startMinute < 10 ? "0" : "") + String(dndTimeRange.startMinute);
|
(ledHandler.getDNDStartMinute() < 10 ? "0" : "") + String(ledHandler.getDNDStartMinute());
|
||||||
doc["endTime"] = String(dndTimeRange.endHour) + ":" +
|
doc["endTime"] = String(ledHandler.getDNDEndHour()) + ":" +
|
||||||
(dndTimeRange.endMinute < 10 ? "0" : "") + String(dndTimeRange.endMinute);
|
(ledHandler.getDNDEndMinute() < 10 ? "0" : "") + String(ledHandler.getDNDEndMinute());
|
||||||
doc["active"] = isDNDActive();
|
doc["active"] = ledHandler.isDNDActive();
|
||||||
|
|
||||||
String response;
|
String response;
|
||||||
serializeJson(doc, response);
|
serializeJson(doc, response);
|
||||||
|
@ -1147,11 +1186,92 @@ void onApiDNDStatus(AsyncWebServerRequest *request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void onApiDNDEnable(AsyncWebServerRequest *request) {
|
void onApiDNDEnable(AsyncWebServerRequest *request) {
|
||||||
setDNDEnabled(true);
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.setDNDEnabled(true);
|
||||||
request->send(200);
|
request->send(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onApiDNDDisable(AsyncWebServerRequest *request) {
|
void onApiDNDDisable(AsyncWebServerRequest *request) {
|
||||||
setDNDEnabled(false);
|
auto& ledHandler = getLedHandler();
|
||||||
|
ledHandler.setDNDEnabled(false);
|
||||||
request->send(200);
|
request->send(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onApiLightsGet(AsyncWebServerRequest *request)
|
||||||
|
{
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
|
auto& pixels = ledHandler.getPixels();
|
||||||
|
|
||||||
|
DynamicJsonDocument doc(1024);
|
||||||
|
JsonArray lights = doc.createNestedArray("lights");
|
||||||
|
|
||||||
|
for (uint i = 0; i < pixels.numPixels(); i++)
|
||||||
|
{
|
||||||
|
uint32_t pixColor = pixels.getPixelColor(pixels.numPixels() - i - 1);
|
||||||
|
JsonObject light = lights.createNestedObject();
|
||||||
|
light["r"] = (uint8_t)(pixColor >> 16);
|
||||||
|
light["g"] = (uint8_t)(pixColor >> 8);
|
||||||
|
light["b"] = (uint8_t)pixColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
String output;
|
||||||
|
serializeJson(doc, output);
|
||||||
|
request->send(200, "application/json", output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onApiLightsPost(AsyncWebServerRequest *request, uint8_t *data, size_t len,
|
||||||
|
size_t index, size_t total)
|
||||||
|
{
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
|
auto& pixels = ledHandler.getPixels();
|
||||||
|
|
||||||
|
DynamicJsonDocument doc(1024);
|
||||||
|
DeserializationError error = deserializeJson(doc, data);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
request->send(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonArray lights = doc["lights"];
|
||||||
|
if (lights.size() != pixels.numPixels())
|
||||||
|
{
|
||||||
|
request->send(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i = 0; i < pixels.numPixels(); i++)
|
||||||
|
{
|
||||||
|
JsonObject light = lights[i];
|
||||||
|
uint8_t red = light["r"];
|
||||||
|
uint8_t green = light["g"];
|
||||||
|
uint8_t blue = light["b"];
|
||||||
|
|
||||||
|
pixels.setPixelColor((pixels.numPixels() - i - 1),
|
||||||
|
pixels.Color(red, green, blue));
|
||||||
|
}
|
||||||
|
pixels.show();
|
||||||
|
|
||||||
|
request->send(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onApiSettings(AsyncWebServerRequest *request, JsonVariant &json)
|
||||||
|
{
|
||||||
|
JsonObject settings = json.as<JsonObject>();
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
|
|
||||||
|
if (settings.containsKey("dnd")) {
|
||||||
|
JsonObject dndObj = settings["dnd"];
|
||||||
|
if (dndObj.containsKey("timeBasedEnabled")) {
|
||||||
|
ledHandler.setDNDTimeBasedEnabled(dndObj["timeBasedEnabled"].as<bool>());
|
||||||
|
}
|
||||||
|
if (dndObj.containsKey("startHour") && dndObj.containsKey("startMinute") &&
|
||||||
|
dndObj.containsKey("endHour") && dndObj.containsKey("endMinute")) {
|
||||||
|
ledHandler.setDNDTimeRange(
|
||||||
|
dndObj["startHour"].as<uint8_t>(),
|
||||||
|
dndObj["startMinute"].as<uint8_t>(),
|
||||||
|
dndObj["endHour"].as<uint8_t>(),
|
||||||
|
dndObj["endMinute"].as<uint8_t>());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
15
src/main.cpp
15
src/main.cpp
|
@ -18,6 +18,7 @@
|
||||||
#define WEBSERVER_H
|
#define WEBSERVER_H
|
||||||
#include "ESPAsyncWebServer.h"
|
#include "ESPAsyncWebServer.h"
|
||||||
#include "lib/config.hpp"
|
#include "lib/config.hpp"
|
||||||
|
#include "lib/led_handler.hpp"
|
||||||
|
|
||||||
uint wifiLostConnection;
|
uint wifiLostConnection;
|
||||||
uint priceNotifyLostConnection = 0;
|
uint priceNotifyLostConnection = 0;
|
||||||
|
@ -58,13 +59,14 @@ void handleFrontlight() {
|
||||||
if (hasLightLevel() && preferences.getUInt("luxLightToggle", DEFAULT_LUX_LIGHT_TOGGLE) != 0) {
|
if (hasLightLevel() && preferences.getUInt("luxLightToggle", DEFAULT_LUX_LIGHT_TOGGLE) != 0) {
|
||||||
uint lightLevel = getLightLevel();
|
uint lightLevel = getLightLevel();
|
||||||
uint luxThreshold = preferences.getUInt("luxLightToggle", DEFAULT_LUX_LIGHT_TOGGLE);
|
uint luxThreshold = preferences.getUInt("luxLightToggle", DEFAULT_LUX_LIGHT_TOGGLE);
|
||||||
|
auto& ledHandler = getLedHandler();
|
||||||
|
|
||||||
if (lightLevel <= 1 && preferences.getBool("flOffWhenDark", DEFAULT_FL_OFF_WHEN_DARK)) {
|
if (lightLevel <= 1 && preferences.getBool("flOffWhenDark", DEFAULT_FL_OFF_WHEN_DARK)) {
|
||||||
if (frontlightIsOn()) frontlightFadeOutAll();
|
if (ledHandler.frontlightIsOn()) ledHandler.frontlightFadeOutAll();
|
||||||
} else if (lightLevel < luxThreshold && !frontlightIsOn()) {
|
} else if (lightLevel < luxThreshold && !ledHandler.frontlightIsOn()) {
|
||||||
frontlightFadeInAll();
|
ledHandler.frontlightFadeInAll();
|
||||||
} else if (frontlightIsOn() && lightLevel > luxThreshold) {
|
} else if (ledHandler.frontlightIsOn() && lightLevel > luxThreshold) {
|
||||||
frontlightFadeOutAll();
|
ledHandler.frontlightFadeOutAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -100,9 +102,7 @@ void checkMissedBlocks() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void monitorDataConnections() {
|
void monitorDataConnections() {
|
||||||
|
|
||||||
// Price notification monitoring
|
// Price notification monitoring
|
||||||
if (getPriceNotifyInit() && !preferences.getBool("fetchEurPrice", DEFAULT_FETCH_EUR_PRICE) && !isPriceNotifyConnected()) {
|
if (getPriceNotifyInit() && !preferences.getBool("fetchEurPrice", DEFAULT_FETCH_EUR_PRICE) && !isPriceNotifyConnected()) {
|
||||||
handlePriceNotifyDisconnection();
|
handlePriceNotifyDisconnection();
|
||||||
|
@ -137,7 +137,6 @@ extern "C" void app_main() {
|
||||||
|
|
||||||
bool thirdPartySource = getDataSource() == THIRD_PARTY_SOURCE;
|
bool thirdPartySource = getDataSource() == THIRD_PARTY_SOURCE;
|
||||||
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (eventSourceTaskHandle != NULL) {
|
if (eventSourceTaskHandle != NULL) {
|
||||||
xTaskNotifyGive(eventSourceTaskHandle);
|
xTaskNotifyGive(eventSourceTaskHandle);
|
||||||
|
|
Loading…
Reference in a new issue