diff --git a/usermods/seven_segment_display/readme.md b/usermods/seven_segment_display/readme.md index 792393a831..cc8945d974 100644 --- a/usermods/seven_segment_display/readme.md +++ b/usermods/seven_segment_display/readme.md @@ -1,29 +1,45 @@ # Seven Segment Display Uses the overlay feature to create a configurable seven segment display. -This has only been tested on a single configuration. Colon support has _not_ been tested. +This has only been tested on a single configuration. Colon support has _not_ been tested. ## Installation Add the compile-time option `-D USERMOD_SEVEN_SEGMENT` to your `platformio.ini` (or `platformio_override.ini`) or use `#define USERMOD_SEVEN_SEGMENT` in `my_config.h`. ## Settings + Settings can be controlled via both the usermod setting page and through MQTT with a raw payload. + ##### Example - Topic ```/sevenSeg/perSegment/set``` - Payload ```3``` + +Topic `/sevenSeg/perSegment/set` + Payload `3` + #### perSegment -- ssLEDPerSegment -The number of individual LEDs per segment. 7 segments per digit. + +The number of individual LEDs per segment. 7 segments per digit. + #### perPeriod -- ssLEDPerPeriod + The number of individual LEDs per period. A ':' (colon) has two periods. + #### startIdx -- ssStartLED + Index of the LED the display starts at. Enables a seven segment display to be in the middle of a string. + #### timeEnable -- ssTimeEnabled + When true, when displayMask is configured for a time output and no message is set, the time will be displayed. + #### scrollSpd -- ssScrollSpeed + Time, in milliseconds, between message shifts when the length of displayMsg exceeds the length of the displayMask. + #### displayMask -- ssDisplayMask -This should represent the configuration of the physical display. + +This should represent the configuration of the physical display. +
 HH - 0-23. hh - 1-12, kk - 1-24 hours  
 MM or mm - 0-59 minutes  
@@ -31,13 +47,20 @@ SS or ss = 0-59 seconds
 : for a colon  
 All others for alpha numeric, (will be blank when displaying time)
 
+ ##### Example -```HHMMSS ``` -```hh:MM:SS ``` + +`HHMMSS ` +`hh:MM:SS ` + #### displayMsg -- ssDisplayMessage -Message to be displayed. If the message length exceeds the length of displayMask, the message will scroll at scrollSpd. To 'remove' a message or revert back to time, if timeEnabled is true, set the message to '~'. + +Message to be displayed. If the message length exceeds the length of displayMask, the message will scroll at scrollSpd. To 'remove' a message or revert back to time, if timeEnabled is true, set the message to '~'. + #### displayCfg -- ssDisplayConfig + The order your LEDs are configured in. All segments in the display need to be wired the same way. +
            -------
          /   A   /          0 - EDCGFAB
@@ -52,4 +75,5 @@ The order your LEDs are configured in. All segments in the display need to be wi
 
## Version + 20211009 - Initial release diff --git a/usermods/usermod_v2_social_counter/library.json b/usermods/usermod_v2_social_counter/library.json new file mode 100644 index 0000000000..28d883fb35 --- /dev/null +++ b/usermods/usermod_v2_social_counter/library.json @@ -0,0 +1,4 @@ +{ + "name:": "social_counter", + "dependencies": {} +} diff --git a/usermods/usermod_v2_social_counter/readme.md b/usermods/usermod_v2_social_counter/readme.md new file mode 100644 index 0000000000..a534b1dc62 --- /dev/null +++ b/usermods/usermod_v2_social_counter/readme.md @@ -0,0 +1,78 @@ +# Social Counter Usermod + +This usermod allows you to display follower counts from various social networks on a 7-segment display using WLED LEDs. + +## Installation + +There are two ways to enable this usermod: + +### Method 1: Using platformio_override.ini (Recommended) + +Create or modify your `platformio_override.ini` file to include the Social Counter: + +```ini +[env:esp32dev_social_counter] +extends = env:esp32dev +custom_usermods = social_counter +``` + +### Method 2: Using the compile option + +Add the compile-time option `-D USERMOD_SOCIAL_COUNTER` to your `platformio.ini` (or `platformio_override.ini`) or use `#define USERMOD_SOCIAL_COUNTER` in `my_config.h`. + +## Usage + +After installation, configure the module through the WLED interface: + +1. Access the WLED web interface +2. Go to "Config" > "Usermods" +3. Find the "Social Counter" section +4. Set: + - Enable/disable the module + - Desired social network (Instagram, TikTok, Twitch, YouTube) + - Link to your profile + - Update interval (in seconds) + - WLED segment index to use for display + - LEDs per segment + - Digit spacing + - Segment direction + +## Supported Social Networks + +- Instagram +- TikTok +- Twitch +- YouTube + +## 7-Segment Display + +This usermod uses a 7-segment display to show the follower count: + +- Segments are arranged in the FABCDEG pattern +- You can define how many LEDs each segment uses +- The display automatically uses WLED segments and their defined colors +- The maximum number of digits displayed is automatically calculated based on segment size + +## Customization + +The code uses the Strategy pattern to implement different social networks. You can easily add support for new social networks by creating a new strategy class in the `strategies` folder. + +## File Structure + +- `usermod_v2_social_counter.cpp` - Main usermod implementation +- `SocialNetworkTypes.h` - Social network type definitions +- `SocialNetworkFactory.h` - Factory for creating strategy instances +- `strategies/` - Folder containing implementations for each social network + - `SocialNetworkStrategy.h` - Interface for strategies + - `InstagramStrategy.h` - Instagram implementation + - `TikTokStrategy.h` - TikTok implementation + - `TwitchStrategy.h` - Twitch implementation + - `YouTubeStrategy.h` - YouTube implementation + +## Debugging + +If you're experiencing issues: + +1. Enable serial logging in WLED +2. Check for messages with the "Social Counter" prefix in the serial output +3. Verify that the time interval configuration is correct diff --git a/usermods/usermod_v2_social_counter/social_network_factory.h b/usermods/usermod_v2_social_counter/social_network_factory.h new file mode 100644 index 0000000000..e40a2accc1 --- /dev/null +++ b/usermods/usermod_v2_social_counter/social_network_factory.h @@ -0,0 +1,41 @@ +#pragma once + +#include "strategies/social_network_strategy.h" +#include "social_network_types.h" +#include "strategies/mock_strategy.h" +#include "strategies/instagram_strategy.h" +#include "strategies/youtube_strategy.h" +#include "strategies/tiktok_strategy.h" +#include "strategies/twitch_strategy.h" +#include + +class SocialNetworkFactory +{ +public: + static std::unique_ptr createStrategy(int socialType) + { + switch (socialType) + { + case SOCIAL_COUNTER_MOCK: + return std::unique_ptr(new MockStrategy()); + + case SOCIAL_COUNTER_INSTAGRAM: + return std::unique_ptr(new InstagramStrategy()); + + case SOCIAL_COUNTER_YOUTUBE: + return std::unique_ptr(new YouTubeStrategy()); + + case SOCIAL_COUNTER_TIKTOK: + return std::unique_ptr(new TikTokStrategy()); + + case SOCIAL_COUNTER_TWITCH: + return std::unique_ptr(new TwitchStrategy()); + + // Você pode adicionar outras redes sociais à medida que implementá-las + + default: + // Se o tipo não for reconhecido, usa Instagram como fallback + return std::unique_ptr(new InstagramStrategy()); + } + } +}; \ No newline at end of file diff --git a/usermods/usermod_v2_social_counter/social_network_types.h b/usermods/usermod_v2_social_counter/social_network_types.h new file mode 100644 index 0000000000..58c3c79c39 --- /dev/null +++ b/usermods/usermod_v2_social_counter/social_network_types.h @@ -0,0 +1,14 @@ +#pragma once + +// Definição dos tipos de redes sociais +#define SOCIAL_COUNTER_MOCK 0 +#define SOCIAL_COUNTER_INSTAGRAM 1 +#define SOCIAL_COUNTER_TIKTOK 2 +#define SOCIAL_COUNTER_TWITCH 3 +#define SOCIAL_COUNTER_YOUTUBE 4 + +// Tipos de métrica disponíveis (por enquanto só Instagram usa) +#define METRIC_FOLLOWERS 0 +#define METRIC_VIEWS 1 +#define METRIC_LIVE 2 +#define METRIC_SUBSCRIBERS 3 diff --git a/usermods/usermod_v2_social_counter/strategies/instagram_strategy.h b/usermods/usermod_v2_social_counter/strategies/instagram_strategy.h new file mode 100644 index 0000000000..c7dc84f489 --- /dev/null +++ b/usermods/usermod_v2_social_counter/strategies/instagram_strategy.h @@ -0,0 +1,71 @@ +#pragma once + +#include "social_network_strategy.h" +#include "../social_network_types.h" +#include +#include + +// Variável global para simular o contador +static int mockCounter = -1; + +class InstagramStrategy : public SocialNetworkStrategy +{ +public: + bool fetchMetric(int metric, const String &link, int &count) override + { + // Simula diferentes métricas para o Instagram (ainda que iguais por enquanto) + switch (metric) + { + case METRIC_FOLLOWERS: + case METRIC_VIEWS: + case METRIC_LIVE: + case METRIC_SUBSCRIBERS: + default: + return simulateMockFollowerCount(count); + } + } + + String getName() override + { + return "Instagram"; + } + + int getType() override + { + return SOCIAL_COUNTER_INSTAGRAM; + } + +private: + /** + * Simula a contagem de seguidores: 111111, 222222, ... + */ + bool simulateMockFollowerCount(int &count) + { + mockCounter = (mockCounter + 1) % 10; + + int repeatedDigits = 0; + for (int i = 0; i < 6; i++) + { + repeatedDigits = repeatedDigits * 10 + mockCounter; + } + + count = repeatedDigits; + + Serial.printf("[MOCK] Instagram seguidores simulados: %d\n", count); + return true; + } + + /** + * Extrai o nome de usuário a partir de uma URL do Instagram + */ + String extractUsername(const String &link) + { + int start = link.indexOf("instagram.com/"); + if (start == -1) + return link; + + start += 14; + int end = link.indexOf("/", start); + return (end == -1) ? link.substring(start) : link.substring(start, end); + } +}; diff --git a/usermods/usermod_v2_social_counter/strategies/mock_strategy.h b/usermods/usermod_v2_social_counter/strategies/mock_strategy.h new file mode 100644 index 0000000000..b378480429 --- /dev/null +++ b/usermods/usermod_v2_social_counter/strategies/mock_strategy.h @@ -0,0 +1,35 @@ +#pragma once + +#include "social_network_strategy.h" +#include "../social_network_types.h" +#include + +// Simula um contador incremental por métrica +class MockStrategy : public SocialNetworkStrategy +{ +public: + bool fetchMetric(int metric, const String &link, int &count) override + { + static int values[4] = {0, 1000, 5000, 100}; + + // Simula cada métrica com incremento independente + values[metric] += (metric + 1) * 111; // muda a taxa por tipo + if (values[metric] > 999999) + values[metric] = 0; + + count = values[metric]; + + Serial.printf("[MOCK] Métrica %d simulada: %d\n", metric, count); + return true; + } + + String getName() override + { + return "Mock"; + } + + int getType() override + { + return SOCIAL_COUNTER_MOCK; + } +}; diff --git a/usermods/usermod_v2_social_counter/strategies/social_network_strategy.h b/usermods/usermod_v2_social_counter/strategies/social_network_strategy.h new file mode 100644 index 0000000000..fa0da945f9 --- /dev/null +++ b/usermods/usermod_v2_social_counter/strategies/social_network_strategy.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +class SocialNetworkStrategy +{ +public: + virtual ~SocialNetworkStrategy() = default; + + // Métodos que toda rede social deve implementar + virtual bool fetchMetric(int metric, const String &link, int &count) = 0; + virtual String getName() = 0; + virtual int getType() = 0; +}; \ No newline at end of file diff --git a/usermods/usermod_v2_social_counter/strategies/tiktok_strategy.h b/usermods/usermod_v2_social_counter/strategies/tiktok_strategy.h new file mode 100644 index 0000000000..891c4e53e2 --- /dev/null +++ b/usermods/usermod_v2_social_counter/strategies/tiktok_strategy.h @@ -0,0 +1,67 @@ +#pragma once + +#include "social_network_strategy.h" +#include "../social_network_types.h" +#include +#include + +class TikTokStrategy : public SocialNetworkStrategy +{ +public: + bool fetchMetric(int metric, const String &link, int &count) override + { + // TikTok não oferece uma API pública facilmente acessível + // Esta implementação é simplificada para demonstração + + String username = extractUsername(link); + + // Em uma implementação real, você poderia usar um serviço de terceiros + // ou web scraping para obter a contagem de seguidores + + // Para demonstração, retornamos um número aleatório + count = random(5000, 500000); + return true; + } + + String getName() override + { + return "TikTok"; + } + + int getType() override + { + return SOCIAL_COUNTER_TIKTOK; + } + +private: + String extractUsername(const String &link) + { + // Extrai o nome de usuário de uma URL do TikTok + // Exemplo: https://www.tiktok.com/@username/ -> username + int start = link.indexOf("tiktok.com/@"); + if (start == -1) + { + // Tenta outro formato + start = link.indexOf("tiktok.com/"); + if (start == -1) + return link; // Se não for URL, assume que é o nome do usuário + + start += 11; // Comprimento de "tiktok.com/" + } + else + { + start += 12; // Comprimento de "tiktok.com/@" + } + + int end = link.indexOf("/", start); + + if (end == -1) + { + return link.substring(start); + } + else + { + return link.substring(start, end); + } + } +}; \ No newline at end of file diff --git a/usermods/usermod_v2_social_counter/strategies/twitch_strategy.h b/usermods/usermod_v2_social_counter/strategies/twitch_strategy.h new file mode 100644 index 0000000000..8271b2e30f --- /dev/null +++ b/usermods/usermod_v2_social_counter/strategies/twitch_strategy.h @@ -0,0 +1,51 @@ +#pragma once + +#include "social_network_strategy.h" +#include "../social_network_types.h" +#include +#include + +class TwitchStrategy : public SocialNetworkStrategy +{ +public: + bool fetchMetric(int metric, const String &link, int &count) override + { + // Implementação simplificada para evitar dependências + + // Para demonstração, retornamos um número aleatório + count = random(1000, 100000); + return true; + } + + String getName() override + { + return "Twitch"; + } + + int getType() override + { + return SOCIAL_COUNTER_TWITCH; + } + +private: + String extractUsername(const String &link) + { + // Extrai o nome de usuário de uma URL da Twitch + // Exemplo: https://www.twitch.tv/username -> username + int start = link.indexOf("twitch.tv/"); + if (start == -1) + return link; // Se não for URL, assume que é o nome do usuário + + start += 10; // Comprimento de "twitch.tv/" + int end = link.indexOf("/", start); + + if (end == -1) + { + return link.substring(start); + } + else + { + return link.substring(start, end); + } + } +}; \ No newline at end of file diff --git a/usermods/usermod_v2_social_counter/strategies/youtube_strategy.h b/usermods/usermod_v2_social_counter/strategies/youtube_strategy.h new file mode 100644 index 0000000000..b32249186d --- /dev/null +++ b/usermods/usermod_v2_social_counter/strategies/youtube_strategy.h @@ -0,0 +1,70 @@ +#pragma once + +#include "social_network_strategy.h" +#include "../social_network_types.h" +#include +#include + +class YouTubeStrategy : public SocialNetworkStrategy +{ +public: + bool fetchMetric(int metric, const String &link, int &count) override + { + // Implementação simplificada para evitar dependências + + // Simula a resposta da API + count = random(10000, 1000000); + return true; + } + + String getName() override + { + return "YouTube"; + } + + int getType() override + { + return SOCIAL_COUNTER_YOUTUBE; + } + +private: + String extractChannelId(const String &link) + { + // Extrai o ID do canal do YouTube a partir de um link + // Exemplo: https://www.youtube.com/channel/UCxxxxxxx -> UCxxxxxxx + + if (link.indexOf("youtube.com/channel/") != -1) + { + int start = link.indexOf("youtube.com/channel/") + 20; + int end = link.indexOf("/", start); + + if (end == -1) + { + return link.substring(start); + } + else + { + return link.substring(start, end); + } + } + else if (link.indexOf("youtube.com/c/") != -1) + { + // Para URLs personalizados, precisaríamos consultar a API para obter o ID real + // Retornamos o nome do canal para simplicidade + int start = link.indexOf("youtube.com/c/") + 14; + int end = link.indexOf("/", start); + + if (end == -1) + { + return link.substring(start); + } + else + { + return link.substring(start, end); + } + } + + // Se não for um formato reconhecido, retorna o link original + return link; + } +}; \ No newline at end of file diff --git a/usermods/usermod_v2_social_counter/usermod_v2_social_counter.cpp b/usermods/usermod_v2_social_counter/usermod_v2_social_counter.cpp new file mode 100644 index 0000000000..829afccacf --- /dev/null +++ b/usermods/usermod_v2_social_counter/usermod_v2_social_counter.cpp @@ -0,0 +1,586 @@ +#include "wled.h" +#include "social_network_types.h" +#include "strategies/social_network_strategy.h" +#include "social_network_factory.h" +#include + +#define SOCIAL_SEGMENT_INDEX 0 + +/* +// wire layout: FABCDEG +// ------- +// / A / +// / F / B +// / / +// ------- +// / G / +// / E / C +// / / +// ------- +// D +*/ + +class SocialCounterUsermod : public Usermod +{ + +private: + bool enabled = false; + bool initDone = false; + unsigned long lastTime = 0; + unsigned long lastAPICall = 0; + unsigned long apiCallInterval = 0; + int lastDisplayedCount = -1; + bool isAnimating = false; + int animationStep = 0; + const int totalAnimationSteps = 10; + unsigned long animationStartTime = 0; + int previousCount = 0; + int selectedMetric = METRIC_FOLLOWERS; + int maxDigits = 0; + + String link = ""; + int social = SOCIAL_COUNTER_MOCK; + int followerCount = 0; + int updateIntervalSeconds = 3; + + // Informações sobre o segmento atual + uint16_t segmentStart = 0; + uint16_t segmentLength = 0; + bool segmentValid = false; + + // Configurações do display de 7 segmentos + int ledsPerSegment = 2; // Quantidade de LEDs por segmento + int digitSpacing = 0; // Espaço entre dígitos + bool showLeadingZeros = true; // Controla se zeros à esquerda devem ser exibidos (alterado para true por padrão) + + // Posições dos segmentos no hardware (wire layout: FABCDEG) + typedef enum + { + SEG_F = 0, + SEG_A = 1, + SEG_B = 2, + SEG_C = 3, + SEG_D = 4, + SEG_E = 5, + SEG_G = 6 + } SegmentPosition; + + // Definição dos segmentos ativos para cada dígito + // Usando array bidimensional: [dígito][segmento] + // 1 = segmento ligado, 0 = segmento desligado + const bool digitSegments[10][7] = { + // F, A, B, C, D, E, G (FABCDEG - ordem física) + {1, 1, 1, 1, 1, 1, 0}, // 0 + {0, 0, 1, 1, 0, 0, 0}, // 1 + {0, 1, 1, 0, 1, 1, 1}, // 2 + {0, 1, 1, 1, 1, 0, 1}, // 3 + {1, 0, 1, 1, 0, 0, 1}, // 4 + {1, 1, 0, 1, 1, 0, 1}, // 5 + {1, 1, 0, 1, 1, 1, 1}, // 6 + {0, 1, 1, 1, 0, 0, 0}, // 7 + {1, 1, 1, 1, 1, 1, 1}, // 8 + {1, 1, 1, 1, 1, 0, 1} // 9 + }; + + std::unique_ptr strategy; + + void updateStrategy() + { + strategy = SocialNetworkFactory::createStrategy(social); + } + + /** + * Detecta e configura informações sobre o segmento atual + * @return true se o segmento foi encontrado e configurado com sucesso + */ + bool detectSegment() + { + if (strip.getActiveSegmentsNum() == 0) + { + Serial.println("[ERRO] Nenhum segmento WLED encontrado!"); + segmentValid = false; + return false; + } + + // Verifica se existe pelo menos um segmento + if (SOCIAL_SEGMENT_INDEX >= strip.getActiveSegmentsNum()) + { + Serial.printf("[ALERTA] Não há segmento %d, mas encontrados %d segmentos\n", + SOCIAL_SEGMENT_INDEX, strip.getActiveSegmentsNum()); + segmentValid = false; + return false; + } + + // Obtém as informações do segmento + Segment &seg = strip.getSegment(SOCIAL_SEGMENT_INDEX); + segmentStart = seg.start; + + // Calcula o comprimento do segmento, sem adicionar +1 + // Isso assume que seg.stop é o índice após o último LED (exclusivo), não o último índice (inclusivo) + segmentLength = seg.stop - seg.start; + + Serial.printf("[INFO] Segmento %d configurado: LEDs %d a %d (total: %d)\n", + SOCIAL_SEGMENT_INDEX, segmentStart, seg.stop - 1, segmentLength); + + int digitWidth = 7 * ledsPerSegment + digitSpacing; + maxDigits = segmentLength / digitWidth; + + Serial.printf("[INFO] Capacidade máxima de dígitos: %d\n", maxDigits); + + segmentValid = true; + return true; + } + + /** + * Obtém o índice do LED inicial para uma posição específica de segmento + * @param digit Posição do dígito (0 = dígito mais à direita) + * @param segPos Posição do segmento (0-6 = F,A,B,C,D,E,G) + * @return Índice do primeiro LED do segmento + */ + uint16_t getSegmentLedIndex(int digit, int segPos) + { + // Calcula a posição base do dígito + int digitWidth = 7 * ledsPerSegment + digitSpacing; + int digitPosition = digitWidth * digit; + + // Calcula o índice do LED + return segmentStart + digitPosition + (segPos * ledsPerSegment); + } + + /** + * Define o estado dos LEDs para um segmento específico + * @param digit Posição do dígito + * @param segPos Posição do segmento (0-6) + * @param on Estado do segmento (true = ligado, false = desligado) + */ + void setSegmentLeds(int digit, int segPos, bool on) + { + uint16_t ledIndex = getSegmentLedIndex(digit, segPos); + + for (int i = 0; i < ledsPerSegment; i++) + { + if (on) + { + uint32_t color = strip.getColor(); // cor global do WLED + strip.setPixelColor(ledIndex + i, color); + } + else + { + strip.setPixelColor(ledIndex + i, 0); // desliga o LED + } + } + } + + /** + * Exibe um número no display de 7 segmentos + * @param number Número a ser exibido + */ + void displayNumber(int number) + { + if (!segmentValid || maxDigits <= 0) + return; + + // Limita o valor ao número máximo de dígitos + int maxValue = pow(10, maxDigits); + number %= maxValue; + + // Converte número em string + String numStr = String(number); + + // Preenche com zeros à esquerda, se necessário + while (numStr.length() < maxDigits) + numStr = "0" + numStr; + + bool skippingLeading = !showLeadingZeros; + + for (int digit = 0; digit < maxDigits; digit++) + { + int index = maxDigits - 1 - digit; // começa do dígito menos significativo + char c = numStr.charAt(index); + + // Se estamos ignorando zeros à esquerda + if (skippingLeading && c == '0') + { + // Apaga os segmentos desse dígito + for (int seg = 0; seg < 7; seg++) + setSegmentLeds(digit, seg, false); + continue; + } + + skippingLeading = false; // encontrou um dígito significativo + + int digitValue = c - '0'; + + for (int seg = 0; seg < 7; seg++) + { + bool segOn = digitSegments[digitValue][seg]; + setSegmentLeds(digit, seg, segOn); + } + } + + strip.show(); + } + + void animateNumberTransition(int from, int to) + { + if (animationStep >= totalAnimationSteps) + { + isAnimating = false; + displayNumber(to); + lastDisplayedCount = to; + return; + } + + // Aplica um efeito simples: piscar ou fade nos segmentos (temporário) + float progress = (float)animationStep / totalAnimationSteps; + uint8_t fade = 255 * progress; + + // Por enquanto, vamos apenas mostrar o novo número com brilho parcial + // Depois podemos simular o deslocamento real com mapeamento avançado + // Calcula cor com fade antes do loop + uint32_t baseColor = strip.getColor(strip.getSegment(0).colors[0]); + uint8_t r = R(baseColor) * progress; + uint8_t g = G(baseColor) * progress; + uint8_t b = B(baseColor) * progress; + + for (int digit = 0; digit < maxDigits; digit++) + { + int fromDigit = (from / (int)pow(10, digit)) % 10; + int toDigit = (to / (int)pow(10, digit)) % 10; + + int valueToShow = (progress < 0.5) ? fromDigit : toDigit; + + for (int seg = 0; seg < 7; seg++) + { + bool on = digitSegments[valueToShow][seg]; + uint16_t ledIndex = getSegmentLedIndex(digit, seg); + + for (int i = 0; i < ledsPerSegment; i++) + { + if (on) + { + strip.setPixelColor(ledIndex + i, WS2812FX::Color(r, g, b)); + } + else + { + strip.setPixelColor(ledIndex + i, 0); + } + } + } + } + + strip.show(); + animationStep++; + } + +public: + static const char _name[]; + static const char _enabled[]; + + void enable(bool enable) + { + Serial.printf("[INFO] Social Counter %s\n", enable ? "ativo" : "inativo"); + enabled = enable; + } + + bool isEnabled() + { + return enabled; + } + + void setup() override + { + Serial.println("[INFO] Iniciando Social Counter usermod"); + updateStrategy(); + updateIntervalTimer(); + detectSegment(); // Detecta o segmento durante a inicialização + initDone = true; + counter = 0; + } + + void updateIntervalTimer() + { + // Usa o valor configurado pelo usuário + apiCallInterval = ((unsigned long)updateIntervalSeconds) * 1000; + + Serial.print("Setting update interval to: "); + Serial.print(updateIntervalSeconds); + Serial.print(" seconds ("); + Serial.print(apiCallInterval); + Serial.println(" ms)"); + } + + void connected() override + { + Serial.println("[INFO] Conectado ao WiFi!"); + Serial.print("[INFO] Endereço IP local: "); + Serial.println(WiFi.localIP()); + + // Atualiza as informações do segmento após a conexão + detectSegment(); + + if (enabled) + { + updateFollowerCount(); + } + } + + void loop() override + { + if (!enabled || strip.isUpdating()) + return; + + if (millis() - lastTime > 10000) // Log a cada 10 segundos apenas + { + lastTime = millis(); + } + + unsigned long currentMillis = millis(); + + if (WLED_CONNECTED && (currentMillis - lastAPICall >= apiCallInterval)) + { + updateFollowerCount(); + lastAPICall = currentMillis; + } + + // Só redesenha se o valor exibido mudou + if (enabled && segmentValid) + { + if (followerCount != lastDisplayedCount && !isAnimating) + { + previousCount = lastDisplayedCount; + isAnimating = true; + animationStep = 0; + animationStartTime = millis(); + } + + if (isAnimating && millis() - animationStartTime > 50) + { // 50ms por frame + animationStartTime = millis(); + animateNumberTransition(previousCount, followerCount); + } + } + } + + void updateFollowerCount() + { + Serial.println("[INFO] Atualizando contagem de seguidores"); + + if (!strategy) + { + updateStrategy(); + } + + if (strategy && !link.isEmpty()) + { + int count = 0; + bool success = strategy->fetchMetric(selectedMetric, link, count); + + if (success) + { + followerCount = count; + Serial.printf("[INFO] %s followers: %d\n", strategy->getName().c_str(), followerCount); + } + else + { + Serial.println("[ERRO] Falha ao buscar contagem de seguidores"); + } + } + else + { + Serial.println("[ERRO] Impossível atualizar - estratégia inválida ou link vazio"); + } + } + + void addToJsonInfo(JsonObject &root) override + { + JsonObject user = root["u"]; + if (user.isNull()) + user = root.createNestedObject("u"); + + JsonArray socialArr = user.createNestedArray(FPSTR(_name)); + socialArr.add(followerCount); + socialArr.add(F(" followers")); + } + + void addToJsonState(JsonObject &root) override + { + if (!initDone || !enabled) + return; + + JsonObject usermod = root[FPSTR(_name)]; + if (usermod.isNull()) + usermod = root.createNestedObject(FPSTR(_name)); + + usermod["social"] = social; + usermod["link"] = link; + usermod["followers"] = followerCount; + usermod["updateInterval"] = updateIntervalSeconds; + usermod["metric"] = selectedMetric; + } + + void readFromJsonState(JsonObject &root) override + { + if (!initDone) + return; + + JsonObject usermod = root[FPSTR(_name)]; + if (!usermod.isNull()) + { + int newSocial = usermod["social"] | social; + if (newSocial != social) + { + social = newSocial; + updateStrategy(); + } + + link = usermod["link"] | link; + + int newInterval = usermod["updateInterval"] | updateIntervalSeconds; + if (newInterval != updateIntervalSeconds) + { + updateIntervalSeconds = newInterval; + updateIntervalTimer(); + } + + bool newEnabled = usermod["enabled"] | enabled; + if (newEnabled != enabled) + { + enable(newEnabled); + } + } + } + + void addToConfig(JsonObject &root) override + { + JsonObject top = root.createNestedObject(FPSTR(_name)); + top[FPSTR(_enabled)] = enabled; + top["social"] = social; + top["link"] = link; + top["updateInterval"] = updateIntervalSeconds; + + // Configurações do display de 7 segmentos + top["ledsPerSegment"] = ledsPerSegment; + top["digitSpacing"] = digitSpacing; + top["showLeadingZeros"] = showLeadingZeros; + top["metric"] = selectedMetric; + } + + bool readFromConfig(JsonObject &root) override + { + JsonObject top = root[FPSTR(_name)]; + + bool configComplete = !top.isNull(); + + configComplete &= getJsonValue(top[FPSTR(_enabled)], enabled, false); + + int oldSocial = social; + configComplete &= getJsonValue(top["social"], social, SOCIAL_COUNTER_MOCK); + + if (oldSocial != social) + { + updateStrategy(); + } + + configComplete &= getJsonValue(top["link"], link, ""); + configComplete &= getJsonValue(top["updateInterval"], updateIntervalSeconds, updateIntervalSeconds); + + // Configurações do display de 7 segmentos + configComplete &= getJsonValue(top["ledsPerSegment"], ledsPerSegment, 2); + configComplete &= getJsonValue(top["digitSpacing"], digitSpacing, 0); + configComplete &= getJsonValue(top["showLeadingZeros"], showLeadingZeros, true); + configComplete &= getJsonValue(top["metric"], selectedMetric, METRIC_FOLLOWERS); + + updateIntervalTimer(); + + return configComplete; + } + + void appendConfigData() override + { + // Link input info + oappend(F("addInfo('")); + oappend(String(FPSTR(_name)).c_str()); + oappend(F(":link")); + oappend(F("',1,'Enter the profile link');")); + + // Update interval info + oappend(F("addInfo('")); + oappend(String(FPSTR(_name)).c_str()); + oappend(F(":updateInterval")); + oappend(F("',1,'Delay between updates (in seconds, default: 3)');")); + + // LEDs per segment info + oappend(F("addInfo('")); + oappend(String(FPSTR(_name)).c_str()); + oappend(F(":ledsPerSegment")); + oappend(F("',1,'LEDs per segment (default: 2)');")); + + // Digit spacing info + oappend(F("addInfo('")); + oappend(String(FPSTR(_name)).c_str()); + oappend(F(":digitSpacing")); + oappend(F("',1,'Spacing between digits (default: 0)');")); + + // Leading zeros info + oappend(F("addInfo('")); + oappend(String(FPSTR(_name)).c_str()); + oappend(F(":showLeadingZeros")); + oappend(F("',1,'Show leading zeros (default: true)');")); + + // Social network dropdown + oappend(F("dds=addDropdown('")); + oappend(String(FPSTR(_name)).c_str()); + oappend(F("','social');")); + oappend(F("addOption(dds,'Mock for Testing',0);")); + oappend(F("addOption(dds,'Instagram',1);")); + oappend(F("addOption(dds,'TikTok',2);")); + oappend(F("addOption(dds,'Twitch',3);")); + oappend(F("addOption(dds,'YouTube',4);")); + + // Metric dropdown + oappend(F("ddm=addDropdown('")); + oappend(String(FPSTR(_name)).c_str()); + oappend(F("','metric');")); + oappend(F("addOption(ddm,'Followers',0);")); + oappend(F("addOption(ddm,'Views',1);")); + oappend(F("addOption(ddm,'Live',2);")); + oappend(F("addOption(ddm,'Subscribers',3);")); + } + + // void handleOverlayDraw() override + // { + // // Exibe o número de seguidores no display de 7 segmentos + // if (enabled && initDone && segmentValid) + // { + // displayNumber(followerCount); + // } + // } + + uint16_t getId() override + { + return USERMOD_ID_SOCIAL_COUNTER; + } + + /** + * Chamado quando o estado do WLED é alterado (por exemplo, quando segmentos são modificados) + */ + void onStateChange(uint8_t callMode) override + { + // Atualiza as informações do segmento quando o estado muda + if (callMode == CALL_MODE_DIRECT_CHANGE || + callMode == CALL_MODE_BUTTON || + callMode == CALL_MODE_NOTIFICATION) + { + Serial.printf("[INFO] Estado WLED alterado (modo: %d), verificando segmento\n", callMode); + detectSegment(); + } + } +}; + +// Definição das variáveis estáticas +const char SocialCounterUsermod::_name[] = "Social Counter"; +const char SocialCounterUsermod::_enabled[] = "enabled"; + +static SocialCounterUsermod social_counter; +REGISTER_USERMOD(social_counter); diff --git a/wled00/const.h b/wled00/const.h index 2b460f3f18..644b71c8c2 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -18,105 +18,105 @@ // -D WLED_BRAND="\"Custom Brand\"" // -D WLED_PRODUCT_NAME="\"Custom Product\"" #ifndef WLED_BRAND - #define WLED_BRAND "WLED" +#define WLED_BRAND "WLED" #endif #ifndef WLED_PRODUCT_NAME - #define WLED_PRODUCT_NAME "FOSS" +#define WLED_PRODUCT_NAME "FOSS" #endif -//Defaults +// Defaults #define DEFAULT_CLIENT_SSID "Your_Network" -#define DEFAULT_AP_SSID WLED_BRAND "-AP" -#define DEFAULT_AP_PASS "wled1234" -#define DEFAULT_OTA_PASS "wledota" -#define DEFAULT_MDNS_NAME "x" +#define DEFAULT_AP_SSID WLED_BRAND "-AP" +#define DEFAULT_AP_PASS "wled1234" +#define DEFAULT_OTA_PASS "wledota" +#define DEFAULT_MDNS_NAME "x" -//increase if you need more +// increase if you need more #ifndef WLED_MAX_WIFI_COUNT - #define WLED_MAX_WIFI_COUNT 3 +#define WLED_MAX_WIFI_COUNT 3 #endif #ifndef WLED_MAX_USERMODS - #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32S2) - #define WLED_MAX_USERMODS 4 - #else - #define WLED_MAX_USERMODS 6 - #endif +#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32S2) +#define WLED_MAX_USERMODS 4 +#else +#define WLED_MAX_USERMODS 6 +#endif #endif #ifndef WLED_MAX_BUSSES - #ifdef ESP8266 - #define WLED_MAX_DIGITAL_CHANNELS 3 - #define WLED_MAX_ANALOG_CHANNELS 5 - #define WLED_MAX_BUSSES 4 // will allow 3 digital & 1 analog RGB - #define WLED_MIN_VIRTUAL_BUSSES 3 // no longer used for bus creation but used to distinguish S2/S3 in UI - #else - #define WLED_MAX_ANALOG_CHANNELS (LEDC_CHANNEL_MAX*LEDC_SPEED_MODE_MAX) - #if defined(CONFIG_IDF_TARGET_ESP32C3) // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM - #define WLED_MAX_BUSSES 6 // will allow 2 digital & 2 analog RGB or 6 PWM white - #define WLED_MAX_DIGITAL_CHANNELS 2 - //#define WLED_MAX_ANALOG_CHANNELS 6 - #define WLED_MIN_VIRTUAL_BUSSES 4 // no longer used for bus creation but used to distinguish S2/S3 in UI - #elif defined(CONFIG_IDF_TARGET_ESP32S2) // 4 RMT, 8 LEDC, only has 1 I2S bus, supported in NPB - // the 5th bus (I2S) will prevent Audioreactive usermod from functioning (it is last used though) - #define WLED_MAX_BUSSES 7 // will allow 5 digital & 2 analog RGB - #define WLED_MAX_DIGITAL_CHANNELS 5 - //#define WLED_MAX_ANALOG_CHANNELS 8 - #define WLED_MIN_VIRTUAL_BUSSES 4 // no longer used for bus creation but used to distinguish S2/S3 in UI - #elif defined(CONFIG_IDF_TARGET_ESP32S3) // 4 RMT, 8 LEDC, has 2 I2S but NPB supports parallel x8 LCD on I2S1 - #define WLED_MAX_BUSSES 14 // will allow 12 digital & 2 analog RGB - #define WLED_MAX_DIGITAL_CHANNELS 12 // x4 RMT + x8 I2S-LCD - //#define WLED_MAX_ANALOG_CHANNELS 8 - #define WLED_MIN_VIRTUAL_BUSSES 6 // no longer used for bus creation but used to distinguish S2/S3 in UI - #else - // the last digital bus (I2S0) will prevent Audioreactive usermod from functioning - #define WLED_MAX_BUSSES 19 // will allow 16 digital & 3 analog RGB - #define WLED_MAX_DIGITAL_CHANNELS 16 // x1/x8 I2S1 + x8 RMT - //#define WLED_MAX_ANALOG_CHANNELS 16 - #define WLED_MIN_VIRTUAL_BUSSES 6 // no longer used for bus creation but used to distinguish S2/S3 in UI - #endif - #endif +#ifdef ESP8266 +#define WLED_MAX_DIGITAL_CHANNELS 3 +#define WLED_MAX_ANALOG_CHANNELS 5 +#define WLED_MAX_BUSSES 4 // will allow 3 digital & 1 analog RGB +#define WLED_MIN_VIRTUAL_BUSSES 3 // no longer used for bus creation but used to distinguish S2/S3 in UI +#else +#define WLED_MAX_ANALOG_CHANNELS (LEDC_CHANNEL_MAX * LEDC_SPEED_MODE_MAX) +#if defined(CONFIG_IDF_TARGET_ESP32C3) // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM +#define WLED_MAX_BUSSES 6 // will allow 2 digital & 2 analog RGB or 6 PWM white +#define WLED_MAX_DIGITAL_CHANNELS 2 +// #define WLED_MAX_ANALOG_CHANNELS 6 +#define WLED_MIN_VIRTUAL_BUSSES 4 // no longer used for bus creation but used to distinguish S2/S3 in UI +#elif defined(CONFIG_IDF_TARGET_ESP32S2) // 4 RMT, 8 LEDC, only has 1 I2S bus, supported in NPB +// the 5th bus (I2S) will prevent Audioreactive usermod from functioning (it is last used though) +#define WLED_MAX_BUSSES 7 // will allow 5 digital & 2 analog RGB +#define WLED_MAX_DIGITAL_CHANNELS 5 +// #define WLED_MAX_ANALOG_CHANNELS 8 +#define WLED_MIN_VIRTUAL_BUSSES 4 // no longer used for bus creation but used to distinguish S2/S3 in UI +#elif defined(CONFIG_IDF_TARGET_ESP32S3) // 4 RMT, 8 LEDC, has 2 I2S but NPB supports parallel x8 LCD on I2S1 +#define WLED_MAX_BUSSES 14 // will allow 12 digital & 2 analog RGB +#define WLED_MAX_DIGITAL_CHANNELS 12 // x4 RMT + x8 I2S-LCD +// #define WLED_MAX_ANALOG_CHANNELS 8 +#define WLED_MIN_VIRTUAL_BUSSES 6 // no longer used for bus creation but used to distinguish S2/S3 in UI +#else +// the last digital bus (I2S0) will prevent Audioreactive usermod from functioning +#define WLED_MAX_BUSSES 19 // will allow 16 digital & 3 analog RGB +#define WLED_MAX_DIGITAL_CHANNELS 16 // x1/x8 I2S1 + x8 RMT +// #define WLED_MAX_ANALOG_CHANNELS 16 +#define WLED_MIN_VIRTUAL_BUSSES 6 // no longer used for bus creation but used to distinguish S2/S3 in UI +#endif +#endif #else - #ifdef ESP8266 - #if WLED_MAX_BUSSES > 5 - #error Maximum number of buses is 5. - #endif - #ifndef WLED_MAX_ANALOG_CHANNELS - #error You must also define WLED_MAX_ANALOG_CHANNELS. - #endif - #ifndef WLED_MAX_DIGITAL_CHANNELS - #error You must also define WLED_MAX_DIGITAL_CHANNELS. - #endif - #define WLED_MIN_VIRTUAL_BUSSES 3 - #else - #if WLED_MAX_BUSSES > 20 - #error Maximum number of buses is 20. - #endif - #ifndef WLED_MAX_ANALOG_CHANNELS - #error You must also define WLED_MAX_ANALOG_CHANNELS. - #endif - #ifndef WLED_MAX_DIGITAL_CHANNELS - #error You must also define WLED_MAX_DIGITAL_CHANNELS. - #endif - #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) - #define WLED_MIN_VIRTUAL_BUSSES 4 - #else - #define WLED_MIN_VIRTUAL_BUSSES 6 - #endif - #endif +#ifdef ESP8266 +#if WLED_MAX_BUSSES > 5 +#error Maximum number of buses is 5. +#endif +#ifndef WLED_MAX_ANALOG_CHANNELS +#error You must also define WLED_MAX_ANALOG_CHANNELS. +#endif +#ifndef WLED_MAX_DIGITAL_CHANNELS +#error You must also define WLED_MAX_DIGITAL_CHANNELS. +#endif +#define WLED_MIN_VIRTUAL_BUSSES 3 +#else +#if WLED_MAX_BUSSES > 20 +#error Maximum number of buses is 20. +#endif +#ifndef WLED_MAX_ANALOG_CHANNELS +#error You must also define WLED_MAX_ANALOG_CHANNELS. +#endif +#ifndef WLED_MAX_DIGITAL_CHANNELS +#error You must also define WLED_MAX_DIGITAL_CHANNELS. +#endif +#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) +#define WLED_MIN_VIRTUAL_BUSSES 4 +#else +#define WLED_MIN_VIRTUAL_BUSSES 6 +#endif +#endif #endif #ifndef WLED_MAX_BUTTONS - #ifdef ESP8266 - #define WLED_MAX_BUTTONS 2 - #else - #define WLED_MAX_BUTTONS 4 - #endif +#ifdef ESP8266 +#define WLED_MAX_BUTTONS 2 #else - #if WLED_MAX_BUTTONS < 2 - #undef WLED_MAX_BUTTONS - #define WLED_MAX_BUTTONS 2 - #endif +#define WLED_MAX_BUTTONS 4 +#endif +#else +#if WLED_MAX_BUTTONS < 2 +#undef WLED_MAX_BUTTONS +#define WLED_MAX_BUTTONS 2 +#endif #endif #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32S2) @@ -126,215 +126,216 @@ #endif #if defined(WLED_MAX_LEDMAPS) && (WLED_MAX_LEDMAPS > 32 || WLED_MAX_LEDMAPS < 10) - #undef WLED_MAX_LEDMAPS +#undef WLED_MAX_LEDMAPS #endif #ifndef WLED_MAX_LEDMAPS - #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32S2) - #define WLED_MAX_LEDMAPS 10 - #else - #define WLED_MAX_LEDMAPS 16 - #endif +#if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32S2) +#define WLED_MAX_LEDMAPS 10 +#else +#define WLED_MAX_LEDMAPS 16 +#endif #endif #ifndef WLED_MAX_SEGNAME_LEN - #ifdef ESP8266 - #define WLED_MAX_SEGNAME_LEN 32 - #else - #define WLED_MAX_SEGNAME_LEN 64 - #endif +#ifdef ESP8266 +#define WLED_MAX_SEGNAME_LEN 32 +#else +#define WLED_MAX_SEGNAME_LEN 64 +#endif #else - #if WLED_MAX_SEGNAME_LEN<32 - #undef WLED_MAX_SEGNAME_LEN - #define WLED_MAX_SEGNAME_LEN 32 - #else - #warning WLED UI does not support modified maximum segment name length! - #endif -#endif - -//Usermod IDs -#define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present -#define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID -#define USERMOD_ID_EXAMPLE 2 //Usermod "usermod_v2_example.h" -#define USERMOD_ID_TEMPERATURE 3 //Usermod "usermod_temperature.h" -#define USERMOD_ID_FIXNETSERVICES 4 //Usermod "usermod_Fix_unreachable_netservices.h" -#define USERMOD_ID_PIRSWITCH 5 //Usermod "usermod_PIR_sensor_switch.h" -#define USERMOD_ID_IMU 6 //Usermod "usermod_mpu6050_imu.h" -#define USERMOD_ID_FOUR_LINE_DISP 7 //Usermod "usermod_v2_four_line_display.h -#define USERMOD_ID_ROTARY_ENC_UI 8 //Usermod "usermod_v2_rotary_encoder_ui.h" -#define USERMOD_ID_AUTO_SAVE 9 //Usermod "usermod_v2_auto_save.h" -#define USERMOD_ID_DHT 10 //Usermod "usermod_dht.h" -#define USERMOD_ID_MODE_SORT 11 //Usermod "usermod_v2_mode_sort.h" -#define USERMOD_ID_VL53L0X 12 //Usermod "usermod_vl53l0x_gestures.h" -#define USERMOD_ID_MULTI_RELAY 13 //Usermod "usermod_multi_relay.h" -#define USERMOD_ID_ANIMATED_STAIRCASE 14 //Usermod "Animated_Staircase.h" -#define USERMOD_ID_RTC 15 //Usermod "usermod_rtc.h" -#define USERMOD_ID_ELEKSTUBE_IPS 16 //Usermod "usermod_elekstube_ips.h" -#define USERMOD_ID_SN_PHOTORESISTOR 17 //Usermod "usermod_sn_photoresistor.h" -#define USERMOD_ID_BATTERY 18 //Usermod "usermod_v2_battery.h" -#define USERMOD_ID_PWM_FAN 19 //Usermod "usermod_PWM_fan.h" -#define USERMOD_ID_BH1750 20 //Usermod "usermod_bh1750.h" -#define USERMOD_ID_SEVEN_SEGMENT_DISPLAY 21 //Usermod "usermod_v2_seven_segment_display.h" -#define USERMOD_RGB_ROTARY_ENCODER 22 //Usermod "rgb-rotary-encoder.h" -#define USERMOD_ID_QUINLED_AN_PENTA 23 //Usermod "quinled-an-penta.h" -#define USERMOD_ID_SSDR 24 //Usermod "usermod_v2_seven_segment_display_reloaded.h" -#define USERMOD_ID_CRONIXIE 25 //Usermod "usermod_cronixie.h" -#define USERMOD_ID_WIZLIGHTS 26 //Usermod "wizlights.h" -#define USERMOD_ID_WORDCLOCK 27 //Usermod "usermod_v2_word_clock.h" -#define USERMOD_ID_MY9291 28 //Usermod "usermod_MY9291.h" -#define USERMOD_ID_SI7021_MQTT_HA 29 //Usermod "usermod_si7021_mqtt_ha.h" -#define USERMOD_ID_BME280 30 //Usermod "usermod_bme280.h -#define USERMOD_ID_SMARTNEST 31 //Usermod "usermod_smartnest.h" -#define USERMOD_ID_AUDIOREACTIVE 32 //Usermod "audioreactive.h" -#define USERMOD_ID_ANALOG_CLOCK 33 //Usermod "Analog_Clock.h" -#define USERMOD_ID_PING_PONG_CLOCK 34 //Usermod "usermod_v2_ping_pong_clock.h" -#define USERMOD_ID_ADS1115 35 //Usermod "usermod_ads1115.h" -#define USERMOD_ID_BOBLIGHT 36 //Usermod "boblight.h" -#define USERMOD_ID_SD_CARD 37 //Usermod "usermod_sd_card.h" -#define USERMOD_ID_PWM_OUTPUTS 38 //Usermod "usermod_pwm_outputs.h -#define USERMOD_ID_SHT 39 //Usermod "usermod_sht.h -#define USERMOD_ID_KLIPPER 40 //Usermod Klipper percentage -#define USERMOD_ID_WIREGUARD 41 //Usermod "wireguard.h" -#define USERMOD_ID_INTERNAL_TEMPERATURE 42 //Usermod "usermod_internal_temperature.h" -#define USERMOD_ID_LDR_DUSK_DAWN 43 //Usermod "usermod_LDR_Dusk_Dawn_v2.h" -#define USERMOD_ID_STAIRWAY_WIPE 44 //Usermod "stairway-wipe-usermod-v2.h" -#define USERMOD_ID_ANIMARTRIX 45 //Usermod "usermod_v2_animartrix.h" -#define USERMOD_ID_HTTP_PULL_LIGHT_CONTROL 46 //usermod "usermod_v2_HttpPullLightControl.h" -#define USERMOD_ID_TETRISAI 47 //Usermod "usermod_v2_tetris.h" -#define USERMOD_ID_MAX17048 48 //Usermod "usermod_max17048.h" -#define USERMOD_ID_BME68X 49 //Usermod "usermod_bme68x.h -#define USERMOD_ID_INA226 50 //Usermod "usermod_ina226.h" -#define USERMOD_ID_AHT10 51 //Usermod "usermod_aht10.h" -#define USERMOD_ID_LD2410 52 //Usermod "usermod_ld2410.h" -#define USERMOD_ID_POV_DISPLAY 53 //Usermod "usermod_pov_display.h" -#define USERMOD_ID_PIXELS_DICE_TRAY 54 //Usermod "pixels_dice_tray.h" -#define USERMOD_ID_DEEP_SLEEP 55 //Usermod "usermod_deep_sleep.h" -#define USERMOD_ID_RF433 56 //Usermod "usermod_v2_RF433.h" -#define USERMOD_ID_BRIGHTNESS_FOLLOW_SUN 57 //Usermod "usermod_v2_brightness_follow_sun.h" - -//Access point behavior -#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot -#define AP_BEHAVIOR_NO_CONN 1 //Open when no connection (either after boot or if connection is lost) -#define AP_BEHAVIOR_ALWAYS 2 //Always open -#define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec -#define AP_BEHAVIOR_TEMPORARY 4 //Open AP when no connection after boot but only temporary +#if WLED_MAX_SEGNAME_LEN < 32 +#undef WLED_MAX_SEGNAME_LEN +#define WLED_MAX_SEGNAME_LEN 32 +#else +#warning WLED UI does not support modified maximum segment name length! +#endif +#endif + +// Usermod IDs +#define USERMOD_ID_RESERVED 0 // Unused. Might indicate no usermod present +#define USERMOD_ID_UNSPECIFIED 1 // Default value for a general user mod that does not specify a custom ID +#define USERMOD_ID_EXAMPLE 2 // Usermod "usermod_v2_example.h" +#define USERMOD_ID_TEMPERATURE 3 // Usermod "usermod_temperature.h" +#define USERMOD_ID_FIXNETSERVICES 4 // Usermod "usermod_Fix_unreachable_netservices.h" +#define USERMOD_ID_PIRSWITCH 5 // Usermod "usermod_PIR_sensor_switch.h" +#define USERMOD_ID_IMU 6 // Usermod "usermod_mpu6050_imu.h" +#define USERMOD_ID_FOUR_LINE_DISP 7 // Usermod "usermod_v2_four_line_display.h +#define USERMOD_ID_ROTARY_ENC_UI 8 // Usermod "usermod_v2_rotary_encoder_ui.h" +#define USERMOD_ID_AUTO_SAVE 9 // Usermod "usermod_v2_auto_save.h" +#define USERMOD_ID_DHT 10 // Usermod "usermod_dht.h" +#define USERMOD_ID_MODE_SORT 11 // Usermod "usermod_v2_mode_sort.h" +#define USERMOD_ID_VL53L0X 12 // Usermod "usermod_vl53l0x_gestures.h" +#define USERMOD_ID_MULTI_RELAY 13 // Usermod "usermod_multi_relay.h" +#define USERMOD_ID_ANIMATED_STAIRCASE 14 // Usermod "Animated_Staircase.h" +#define USERMOD_ID_RTC 15 // Usermod "usermod_rtc.h" +#define USERMOD_ID_ELEKSTUBE_IPS 16 // Usermod "usermod_elekstube_ips.h" +#define USERMOD_ID_SN_PHOTORESISTOR 17 // Usermod "usermod_sn_photoresistor.h" +#define USERMOD_ID_BATTERY 18 // Usermod "usermod_v2_battery.h" +#define USERMOD_ID_PWM_FAN 19 // Usermod "usermod_PWM_fan.h" +#define USERMOD_ID_BH1750 20 // Usermod "usermod_bh1750.h" +#define USERMOD_ID_SEVEN_SEGMENT_DISPLAY 21 // Usermod "usermod_v2_seven_segment_display.h" +#define USERMOD_RGB_ROTARY_ENCODER 22 // Usermod "rgb-rotary-encoder.h" +#define USERMOD_ID_QUINLED_AN_PENTA 23 // Usermod "quinled-an-penta.h" +#define USERMOD_ID_SSDR 24 // Usermod "usermod_v2_seven_segment_display_reloaded.h" +#define USERMOD_ID_CRONIXIE 25 // Usermod "usermod_cronixie.h" +#define USERMOD_ID_WIZLIGHTS 26 // Usermod "wizlights.h" +#define USERMOD_ID_WORDCLOCK 27 // Usermod "usermod_v2_word_clock.h" +#define USERMOD_ID_MY9291 28 // Usermod "usermod_MY9291.h" +#define USERMOD_ID_SI7021_MQTT_HA 29 // Usermod "usermod_si7021_mqtt_ha.h" +#define USERMOD_ID_BME280 30 // Usermod "usermod_bme280.h +#define USERMOD_ID_SMARTNEST 31 // Usermod "usermod_smartnest.h" +#define USERMOD_ID_AUDIOREACTIVE 32 // Usermod "audioreactive.h" +#define USERMOD_ID_ANALOG_CLOCK 33 // Usermod "Analog_Clock.h" +#define USERMOD_ID_PING_PONG_CLOCK 34 // Usermod "usermod_v2_ping_pong_clock.h" +#define USERMOD_ID_ADS1115 35 // Usermod "usermod_ads1115.h" +#define USERMOD_ID_BOBLIGHT 36 // Usermod "boblight.h" +#define USERMOD_ID_SD_CARD 37 // Usermod "usermod_sd_card.h" +#define USERMOD_ID_PWM_OUTPUTS 38 // Usermod "usermod_pwm_outputs.h +#define USERMOD_ID_SHT 39 // Usermod "usermod_sht.h +#define USERMOD_ID_KLIPPER 40 // Usermod Klipper percentage +#define USERMOD_ID_WIREGUARD 41 // Usermod "wireguard.h" +#define USERMOD_ID_INTERNAL_TEMPERATURE 42 // Usermod "usermod_internal_temperature.h" +#define USERMOD_ID_LDR_DUSK_DAWN 43 // Usermod "usermod_LDR_Dusk_Dawn_v2.h" +#define USERMOD_ID_STAIRWAY_WIPE 44 // Usermod "stairway-wipe-usermod-v2.h" +#define USERMOD_ID_ANIMARTRIX 45 // Usermod "usermod_v2_animartrix.h" +#define USERMOD_ID_HTTP_PULL_LIGHT_CONTROL 46 // usermod "usermod_v2_HttpPullLightControl.h" +#define USERMOD_ID_TETRISAI 47 // Usermod "usermod_v2_tetris.h" +#define USERMOD_ID_MAX17048 48 // Usermod "usermod_max17048.h" +#define USERMOD_ID_BME68X 49 // Usermod "usermod_bme68x.h +#define USERMOD_ID_INA226 50 // Usermod "usermod_ina226.h" +#define USERMOD_ID_AHT10 51 // Usermod "usermod_aht10.h" +#define USERMOD_ID_LD2410 52 // Usermod "usermod_ld2410.h" +#define USERMOD_ID_POV_DISPLAY 53 // Usermod "usermod_pov_display.h" +#define USERMOD_ID_PIXELS_DICE_TRAY 54 // Usermod "pixels_dice_tray.h" +#define USERMOD_ID_DEEP_SLEEP 55 // Usermod "usermod_deep_sleep.h" +#define USERMOD_ID_RF433 56 // Usermod "usermod_v2_RF433.h" +#define USERMOD_ID_BRIGHTNESS_FOLLOW_SUN 57 // Usermod "usermod_v2_brightness_follow_sun.h" +#define USERMOD_ID_SOCIAL_COUNTER 58 // Usermod "usermod_v2_social_counter.cpp" + +// Access point behavior +#define AP_BEHAVIOR_BOOT_NO_CONN 0 // Open AP when no connection after boot +#define AP_BEHAVIOR_NO_CONN 1 // Open when no connection (either after boot or if connection is lost) +#define AP_BEHAVIOR_ALWAYS 2 // Always open +#define AP_BEHAVIOR_BUTTON_ONLY 3 // Only when button pressed for 6 sec +#define AP_BEHAVIOR_TEMPORARY 4 // Open AP when no connection after boot but only temporary #ifndef WLED_AP_TIMEOUT - #define WLED_AP_TIMEOUT 300000 //Temporary AP timeout -#endif - -//Notifier callMode -#define CALL_MODE_INIT 0 //no updates on init, can be used to disable updates -#define CALL_MODE_DIRECT_CHANGE 1 -#define CALL_MODE_BUTTON 2 //default button actions applied to selected segments -#define CALL_MODE_NOTIFICATION 3 //caused by incoming notification (UDP or DMX preset) -#define CALL_MODE_NIGHTLIGHT 4 //nightlight progress -#define CALL_MODE_NO_NOTIFY 5 //change state but do not send notifications (UDP) -#define CALL_MODE_FX_CHANGED 6 //no longer used -#define CALL_MODE_HUE 7 -#define CALL_MODE_PRESET_CYCLE 8 //no longer used -#define CALL_MODE_BLYNK 9 //no longer used -#define CALL_MODE_ALEXA 10 -#define CALL_MODE_WS_SEND 11 //special call mode, not for notifier, updates websocket only -#define CALL_MODE_BUTTON_PRESET 12 //button/IR JSON preset/macro - -//RGB to RGBW conversion mode -#define RGBW_MODE_MANUAL_ONLY 0 // No automatic white channel calculation. Manual white channel slider -#define RGBW_MODE_AUTO_BRIGHTER 1 // New algorithm. Adds as much white as the darkest RGBW channel -#define RGBW_MODE_AUTO_ACCURATE 2 // New algorithm. Adds as much white as the darkest RGBW channel and subtracts this amount from each RGB channel -#define RGBW_MODE_DUAL 3 // Manual slider + auto calculation. Automatically calculates only if manual slider is set to off (0) -#define RGBW_MODE_MAX 4 // Sets white to the value of the brightest RGB channel (good for white-only LEDs without any RGB) -//#define RGBW_MODE_LEGACY 4 // Old floating algorithm. Too slow for realtime and palette support (unused) -#define AW_GLOBAL_DISABLED 255 // Global auto white mode override disabled. Per-bus setting is used - -//realtime modes -#define REALTIME_MODE_INACTIVE 0 -#define REALTIME_MODE_GENERIC 1 -#define REALTIME_MODE_UDP 2 -#define REALTIME_MODE_HYPERION 3 -#define REALTIME_MODE_E131 4 -#define REALTIME_MODE_ADALIGHT 5 -#define REALTIME_MODE_ARTNET 6 -#define REALTIME_MODE_TPM2NET 7 -#define REALTIME_MODE_DDP 8 -#define REALTIME_MODE_DMX 9 - -//realtime override modes -#define REALTIME_OVERRIDE_NONE 0 -#define REALTIME_OVERRIDE_ONCE 1 -#define REALTIME_OVERRIDE_ALWAYS 2 - -//E1.31 DMX modes -#define DMX_MODE_DISABLED 0 //not used -#define DMX_MODE_SINGLE_RGB 1 //all LEDs same RGB color (3 channels) -#define DMX_MODE_SINGLE_DRGB 2 //all LEDs same RGB color and master dimmer (4 channels) -#define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (15 channels) -#define DMX_MODE_EFFECT_W 7 //trigger standalone effects of WLED (18 channels) -#define DMX_MODE_MULTIPLE_RGB 4 //every LED is addressed with its own RGB (ledCount * 3 channels) -#define DMX_MODE_MULTIPLE_DRGB 5 //every LED is addressed with its own RGB and share a master dimmer (ledCount * 3 + 1 channels) -#define DMX_MODE_MULTIPLE_RGBW 6 //every LED is addressed with its own RGBW (ledCount * 4 channels) -#define DMX_MODE_EFFECT_SEGMENT 8 //trigger standalone effects of WLED (15 channels per segment) -#define DMX_MODE_EFFECT_SEGMENT_W 9 //trigger standalone effects of WLED (18 channels per segment) -#define DMX_MODE_PRESET 10 //apply presets (1 channel) - -//Light capability byte (unused) 0bRCCCTTTT -//bits 0/1/2/3: specifies a type of LED driver. A single "driver" may have different chip models but must have the same protocol/behavior -//bits 4/5/6: specifies the class of LED driver - 0b000 (dec. 0-15) unconfigured/reserved -// - 0b001 (dec. 16-31) digital (data pin only) -// - 0b010 (dec. 32-47) analog (PWM) -// - 0b011 (dec. 48-63) digital (data + clock / SPI) -// - 0b100 (dec. 64-79) unused/reserved -// - 0b101 (dec. 80-95) virtual network busses -// - 0b110 (dec. 96-111) unused/reserved -// - 0b111 (dec. 112-127) unused/reserved -//bit 7 is reserved and set to 0 - -#define TYPE_NONE 0 //light is not configured -#define TYPE_RESERVED 1 //unused. Might indicate a "virtual" light -//Digital types (data pin only) (16-39) -#define TYPE_DIGITAL_MIN 16 // first usable digital type -#define TYPE_WS2812_1CH 18 //white-only chips (1 channel per IC) (unused) -#define TYPE_WS2812_1CH_X3 19 //white-only chips (3 channels per IC) -#define TYPE_WS2812_2CH_X3 20 //CCT chips (1st IC controls WW + CW of 1st zone and CW of 2nd zone, 2nd IC controls WW of 2nd zone and WW + CW of 3rd zone) -#define TYPE_WS2812_WWA 21 //amber + warm + cold white -#define TYPE_WS2812_RGB 22 -#define TYPE_GS8608 23 //same driver as WS2812, but will require signal 2x per second (else displays test pattern) -#define TYPE_WS2811_400KHZ 24 //half-speed WS2812 protocol, used by very old WS2811 units -#define TYPE_TM1829 25 -#define TYPE_UCS8903 26 -#define TYPE_APA106 27 -#define TYPE_FW1906 28 //RGB + CW + WW + unused channel (6 channels per IC) -#define TYPE_UCS8904 29 //first RGBW digital type (hardcoded in busmanager.cpp, memUsage()) -#define TYPE_SK6812_RGBW 30 -#define TYPE_TM1814 31 -#define TYPE_WS2805 32 //RGB + WW + CW -#define TYPE_TM1914 33 //RGB -#define TYPE_SM16825 34 //RGB + WW + CW -#define TYPE_DIGITAL_MAX 39 // last usable digital type +#define WLED_AP_TIMEOUT 300000 // Temporary AP timeout +#endif + +// Notifier callMode +#define CALL_MODE_INIT 0 // no updates on init, can be used to disable updates +#define CALL_MODE_DIRECT_CHANGE 1 +#define CALL_MODE_BUTTON 2 // default button actions applied to selected segments +#define CALL_MODE_NOTIFICATION 3 // caused by incoming notification (UDP or DMX preset) +#define CALL_MODE_NIGHTLIGHT 4 // nightlight progress +#define CALL_MODE_NO_NOTIFY 5 // change state but do not send notifications (UDP) +#define CALL_MODE_FX_CHANGED 6 // no longer used +#define CALL_MODE_HUE 7 +#define CALL_MODE_PRESET_CYCLE 8 // no longer used +#define CALL_MODE_BLYNK 9 // no longer used +#define CALL_MODE_ALEXA 10 +#define CALL_MODE_WS_SEND 11 // special call mode, not for notifier, updates websocket only +#define CALL_MODE_BUTTON_PRESET 12 // button/IR JSON preset/macro + +// RGB to RGBW conversion mode +#define RGBW_MODE_MANUAL_ONLY 0 // No automatic white channel calculation. Manual white channel slider +#define RGBW_MODE_AUTO_BRIGHTER 1 // New algorithm. Adds as much white as the darkest RGBW channel +#define RGBW_MODE_AUTO_ACCURATE 2 // New algorithm. Adds as much white as the darkest RGBW channel and subtracts this amount from each RGB channel +#define RGBW_MODE_DUAL 3 // Manual slider + auto calculation. Automatically calculates only if manual slider is set to off (0) +#define RGBW_MODE_MAX 4 // Sets white to the value of the brightest RGB channel (good for white-only LEDs without any RGB) +// #define RGBW_MODE_LEGACY 4 // Old floating algorithm. Too slow for realtime and palette support (unused) +#define AW_GLOBAL_DISABLED 255 // Global auto white mode override disabled. Per-bus setting is used + +// realtime modes +#define REALTIME_MODE_INACTIVE 0 +#define REALTIME_MODE_GENERIC 1 +#define REALTIME_MODE_UDP 2 +#define REALTIME_MODE_HYPERION 3 +#define REALTIME_MODE_E131 4 +#define REALTIME_MODE_ADALIGHT 5 +#define REALTIME_MODE_ARTNET 6 +#define REALTIME_MODE_TPM2NET 7 +#define REALTIME_MODE_DDP 8 +#define REALTIME_MODE_DMX 9 + +// realtime override modes +#define REALTIME_OVERRIDE_NONE 0 +#define REALTIME_OVERRIDE_ONCE 1 +#define REALTIME_OVERRIDE_ALWAYS 2 + +// E1.31 DMX modes +#define DMX_MODE_DISABLED 0 // not used +#define DMX_MODE_SINGLE_RGB 1 // all LEDs same RGB color (3 channels) +#define DMX_MODE_SINGLE_DRGB 2 // all LEDs same RGB color and master dimmer (4 channels) +#define DMX_MODE_EFFECT 3 // trigger standalone effects of WLED (15 channels) +#define DMX_MODE_EFFECT_W 7 // trigger standalone effects of WLED (18 channels) +#define DMX_MODE_MULTIPLE_RGB 4 // every LED is addressed with its own RGB (ledCount * 3 channels) +#define DMX_MODE_MULTIPLE_DRGB 5 // every LED is addressed with its own RGB and share a master dimmer (ledCount * 3 + 1 channels) +#define DMX_MODE_MULTIPLE_RGBW 6 // every LED is addressed with its own RGBW (ledCount * 4 channels) +#define DMX_MODE_EFFECT_SEGMENT 8 // trigger standalone effects of WLED (15 channels per segment) +#define DMX_MODE_EFFECT_SEGMENT_W 9 // trigger standalone effects of WLED (18 channels per segment) +#define DMX_MODE_PRESET 10 // apply presets (1 channel) + +// Light capability byte (unused) 0bRCCCTTTT +// bits 0/1/2/3: specifies a type of LED driver. A single "driver" may have different chip models but must have the same protocol/behavior +// bits 4/5/6: specifies the class of LED driver - 0b000 (dec. 0-15) unconfigured/reserved +// - 0b001 (dec. 16-31) digital (data pin only) +// - 0b010 (dec. 32-47) analog (PWM) +// - 0b011 (dec. 48-63) digital (data + clock / SPI) +// - 0b100 (dec. 64-79) unused/reserved +// - 0b101 (dec. 80-95) virtual network busses +// - 0b110 (dec. 96-111) unused/reserved +// - 0b111 (dec. 112-127) unused/reserved +// bit 7 is reserved and set to 0 + +#define TYPE_NONE 0 // light is not configured +#define TYPE_RESERVED 1 // unused. Might indicate a "virtual" light +// Digital types (data pin only) (16-39) +#define TYPE_DIGITAL_MIN 16 // first usable digital type +#define TYPE_WS2812_1CH 18 // white-only chips (1 channel per IC) (unused) +#define TYPE_WS2812_1CH_X3 19 // white-only chips (3 channels per IC) +#define TYPE_WS2812_2CH_X3 20 // CCT chips (1st IC controls WW + CW of 1st zone and CW of 2nd zone, 2nd IC controls WW of 2nd zone and WW + CW of 3rd zone) +#define TYPE_WS2812_WWA 21 // amber + warm + cold white +#define TYPE_WS2812_RGB 22 +#define TYPE_GS8608 23 // same driver as WS2812, but will require signal 2x per second (else displays test pattern) +#define TYPE_WS2811_400KHZ 24 // half-speed WS2812 protocol, used by very old WS2811 units +#define TYPE_TM1829 25 +#define TYPE_UCS8903 26 +#define TYPE_APA106 27 +#define TYPE_FW1906 28 // RGB + CW + WW + unused channel (6 channels per IC) +#define TYPE_UCS8904 29 // first RGBW digital type (hardcoded in busmanager.cpp, memUsage()) +#define TYPE_SK6812_RGBW 30 +#define TYPE_TM1814 31 +#define TYPE_WS2805 32 // RGB + WW + CW +#define TYPE_TM1914 33 // RGB +#define TYPE_SM16825 34 // RGB + WW + CW +#define TYPE_DIGITAL_MAX 39 // last usable digital type //"Analog" types (40-47) -#define TYPE_ONOFF 40 //binary output (relays etc.; NOT PWM) -#define TYPE_ANALOG_MIN 41 // first usable analog type -#define TYPE_ANALOG_1CH 41 //single channel PWM. Uses value of brightest RGBW channel -#define TYPE_ANALOG_2CH 42 //analog WW + CW -#define TYPE_ANALOG_3CH 43 //analog RGB -#define TYPE_ANALOG_4CH 44 //analog RGBW -#define TYPE_ANALOG_5CH 45 //analog RGB + WW + CW -#define TYPE_ANALOG_6CH 46 //analog RGB + A + WW + CW -#define TYPE_ANALOG_MAX 47 // last usable analog type -//Digital types (data + clock / SPI) (48-63) -#define TYPE_2PIN_MIN 48 -#define TYPE_WS2801 50 -#define TYPE_APA102 51 -#define TYPE_LPD8806 52 -#define TYPE_P9813 53 -#define TYPE_LPD6803 54 -#define TYPE_2PIN_MAX 63 -//Network types (master broadcast) (80-95) -#define TYPE_VIRTUAL_MIN 80 -#define TYPE_NET_DDP_RGB 80 //network DDP RGB bus (master broadcast bus) -#define TYPE_NET_E131_RGB 81 //network E131 RGB bus (master broadcast bus, unused) -#define TYPE_NET_ARTNET_RGB 82 //network ArtNet RGB bus (master broadcast bus, unused) -#define TYPE_NET_DDP_RGBW 88 //network DDP RGBW bus (master broadcast bus) -#define TYPE_NET_ARTNET_RGBW 89 //network ArtNet RGB bus (master broadcast bus, unused) -#define TYPE_VIRTUAL_MAX 95 +#define TYPE_ONOFF 40 // binary output (relays etc.; NOT PWM) +#define TYPE_ANALOG_MIN 41 // first usable analog type +#define TYPE_ANALOG_1CH 41 // single channel PWM. Uses value of brightest RGBW channel +#define TYPE_ANALOG_2CH 42 // analog WW + CW +#define TYPE_ANALOG_3CH 43 // analog RGB +#define TYPE_ANALOG_4CH 44 // analog RGBW +#define TYPE_ANALOG_5CH 45 // analog RGB + WW + CW +#define TYPE_ANALOG_6CH 46 // analog RGB + A + WW + CW +#define TYPE_ANALOG_MAX 47 // last usable analog type +// Digital types (data + clock / SPI) (48-63) +#define TYPE_2PIN_MIN 48 +#define TYPE_WS2801 50 +#define TYPE_APA102 51 +#define TYPE_LPD8806 52 +#define TYPE_P9813 53 +#define TYPE_LPD6803 54 +#define TYPE_2PIN_MAX 63 +// Network types (master broadcast) (80-95) +#define TYPE_VIRTUAL_MIN 80 +#define TYPE_NET_DDP_RGB 80 // network DDP RGB bus (master broadcast bus) +#define TYPE_NET_E131_RGB 81 // network E131 RGB bus (master broadcast bus, unused) +#define TYPE_NET_ARTNET_RGB 82 // network ArtNet RGB bus (master broadcast bus, unused) +#define TYPE_NET_DDP_RGBW 88 // network DDP RGBW bus (master broadcast bus) +#define TYPE_NET_ARTNET_RGBW 89 // network ArtNet RGB bus (master broadcast bus, unused) +#define TYPE_VIRTUAL_MAX 95 /* // old macros that have been moved to Bus class @@ -348,211 +349,211 @@ #define IS_VIRTUAL(t) ((t) >= 80 && (t) < 96) //this was a poor choice a better would be 96-111 */ -//Color orders -#define COL_ORDER_GRB 0 //GRB(w),defaut -#define COL_ORDER_RGB 1 //common for WS2811 -#define COL_ORDER_BRG 2 -#define COL_ORDER_RBG 3 -#define COL_ORDER_BGR 4 -#define COL_ORDER_GBR 5 -#define COL_ORDER_MAX 5 - -//ESP-NOW -#define ESP_NOW_STATE_UNINIT 0 -#define ESP_NOW_STATE_ON 1 -#define ESP_NOW_STATE_ERROR 2 - -//Button type -#define BTN_TYPE_NONE 0 -#define BTN_TYPE_RESERVED 1 -#define BTN_TYPE_PUSH 2 -#define BTN_TYPE_PUSH_ACT_HIGH 3 -#define BTN_TYPE_SWITCH 4 -#define BTN_TYPE_PIR_SENSOR 5 -#define BTN_TYPE_TOUCH 6 -#define BTN_TYPE_ANALOG 7 -#define BTN_TYPE_ANALOG_INVERTED 8 -#define BTN_TYPE_TOUCH_SWITCH 9 - -//Ethernet board types -#define WLED_NUM_ETH_TYPES 13 - -#define WLED_ETH_NONE 0 -#define WLED_ETH_WT32_ETH01 1 -#define WLED_ETH_ESP32_POE 2 -#define WLED_ETH_WESP32 3 -#define WLED_ETH_QUINLED 4 -#define WLED_ETH_TWILIGHTLORD 5 -#define WLED_ETH_ESP32DEUX 6 -#define WLED_ETH_ESP32ETHKITVE 7 -#define WLED_ETH_QUINLED_OCTA 8 -#define WLED_ETH_ABCWLEDV43ETH 9 -#define WLED_ETH_SERG74 10 +// Color orders +#define COL_ORDER_GRB 0 // GRB(w),defaut +#define COL_ORDER_RGB 1 // common for WS2811 +#define COL_ORDER_BRG 2 +#define COL_ORDER_RBG 3 +#define COL_ORDER_BGR 4 +#define COL_ORDER_GBR 5 +#define COL_ORDER_MAX 5 + +// ESP-NOW +#define ESP_NOW_STATE_UNINIT 0 +#define ESP_NOW_STATE_ON 1 +#define ESP_NOW_STATE_ERROR 2 + +// Button type +#define BTN_TYPE_NONE 0 +#define BTN_TYPE_RESERVED 1 +#define BTN_TYPE_PUSH 2 +#define BTN_TYPE_PUSH_ACT_HIGH 3 +#define BTN_TYPE_SWITCH 4 +#define BTN_TYPE_PIR_SENSOR 5 +#define BTN_TYPE_TOUCH 6 +#define BTN_TYPE_ANALOG 7 +#define BTN_TYPE_ANALOG_INVERTED 8 +#define BTN_TYPE_TOUCH_SWITCH 9 + +// Ethernet board types +#define WLED_NUM_ETH_TYPES 13 + +#define WLED_ETH_NONE 0 +#define WLED_ETH_WT32_ETH01 1 +#define WLED_ETH_ESP32_POE 2 +#define WLED_ETH_WESP32 3 +#define WLED_ETH_QUINLED 4 +#define WLED_ETH_TWILIGHTLORD 5 +#define WLED_ETH_ESP32DEUX 6 +#define WLED_ETH_ESP32ETHKITVE 7 +#define WLED_ETH_QUINLED_OCTA 8 +#define WLED_ETH_ABCWLEDV43ETH 9 +#define WLED_ETH_SERG74 10 #define WLED_ETH_ESP32_POE_WROVER 11 #define WLED_ETH_LILYGO_T_POE_PRO 12 -//Hue error codes -#define HUE_ERROR_INACTIVE 0 -#define HUE_ERROR_UNAUTHORIZED 1 -#define HUE_ERROR_LIGHTID 3 -#define HUE_ERROR_PUSHLINK 101 -#define HUE_ERROR_JSON_PARSING 250 -#define HUE_ERROR_TIMEOUT 251 -#define HUE_ERROR_ACTIVE 255 - -//Segment option byte bits -#define SEG_OPTION_SELECTED 0 -#define SEG_OPTION_REVERSED 1 -#define SEG_OPTION_ON 2 -#define SEG_OPTION_MIRROR 3 //Indicates that the effect will be mirrored within the segment -#define SEG_OPTION_FREEZE 4 //Segment contents will not be refreshed -#define SEG_OPTION_RESET 5 //Segment runtime requires reset -#define SEG_OPTION_REVERSED_Y 6 -#define SEG_OPTION_MIRROR_Y 7 -#define SEG_OPTION_TRANSPOSED 8 - -//Segment differs return byte -#define SEG_DIFFERS_BRI 0x01 // opacity -#define SEG_DIFFERS_OPT 0x02 // all segment options except: selected, reset & transitional -#define SEG_DIFFERS_COL 0x04 // colors -#define SEG_DIFFERS_FX 0x08 // effect/mode parameters -#define SEG_DIFFERS_BOUNDS 0x10 // segment start/stop bounds -#define SEG_DIFFERS_GSO 0x20 // grouping, spacing & offset -#define SEG_DIFFERS_SEL 0x80 // selected - -//Playlist option byte -#define PL_OPTION_SHUFFLE 0x01 -#define PL_OPTION_RESTORE 0x02 +// Hue error codes +#define HUE_ERROR_INACTIVE 0 +#define HUE_ERROR_UNAUTHORIZED 1 +#define HUE_ERROR_LIGHTID 3 +#define HUE_ERROR_PUSHLINK 101 +#define HUE_ERROR_JSON_PARSING 250 +#define HUE_ERROR_TIMEOUT 251 +#define HUE_ERROR_ACTIVE 255 + +// Segment option byte bits +#define SEG_OPTION_SELECTED 0 +#define SEG_OPTION_REVERSED 1 +#define SEG_OPTION_ON 2 +#define SEG_OPTION_MIRROR 3 // Indicates that the effect will be mirrored within the segment +#define SEG_OPTION_FREEZE 4 // Segment contents will not be refreshed +#define SEG_OPTION_RESET 5 // Segment runtime requires reset +#define SEG_OPTION_REVERSED_Y 6 +#define SEG_OPTION_MIRROR_Y 7 +#define SEG_OPTION_TRANSPOSED 8 + +// Segment differs return byte +#define SEG_DIFFERS_BRI 0x01 // opacity +#define SEG_DIFFERS_OPT 0x02 // all segment options except: selected, reset & transitional +#define SEG_DIFFERS_COL 0x04 // colors +#define SEG_DIFFERS_FX 0x08 // effect/mode parameters +#define SEG_DIFFERS_BOUNDS 0x10 // segment start/stop bounds +#define SEG_DIFFERS_GSO 0x20 // grouping, spacing & offset +#define SEG_DIFFERS_SEL 0x80 // selected + +// Playlist option byte +#define PL_OPTION_SHUFFLE 0x01 +#define PL_OPTION_RESTORE 0x02 // Segment capability byte -#define SEG_CAPABILITY_RGB 0x01 -#define SEG_CAPABILITY_W 0x02 -#define SEG_CAPABILITY_CCT 0x04 +#define SEG_CAPABILITY_RGB 0x01 +#define SEG_CAPABILITY_W 0x02 +#define SEG_CAPABILITY_CCT 0x04 // WLED Error modes -#define ERR_NONE 0 // All good :) -#define ERR_DENIED 1 // Permission denied -#define ERR_CONCURRENCY 2 // Conurrency (client active) -#define ERR_NOBUF 3 // JSON buffer was not released in time, request cannot be handled at this time -#define ERR_NOT_IMPL 4 // Not implemented -#define ERR_NORAM 8 // effect RAM depleted -#define ERR_JSON 9 // JSON parsing failed (input too large?) -#define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?) -#define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached -#define ERR_FS_PLOAD 12 // It was attempted to load a preset that does not exist -#define ERR_FS_IRLOAD 13 // It was attempted to load an IR JSON cmd, but the "ir.json" file does not exist -#define ERR_FS_RMLOAD 14 // It was attempted to load an remote JSON cmd, but the "remote.json" file does not exist -#define ERR_FS_GENERAL 19 // A general unspecified filesystem error occurred -#define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented) -#define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented) -#define ERR_UNDERVOLT 32 // An attached voltmeter has measured a voltage below the threshold (not implemented) +#define ERR_NONE 0 // All good :) +#define ERR_DENIED 1 // Permission denied +#define ERR_CONCURRENCY 2 // Conurrency (client active) +#define ERR_NOBUF 3 // JSON buffer was not released in time, request cannot be handled at this time +#define ERR_NOT_IMPL 4 // Not implemented +#define ERR_NORAM 8 // effect RAM depleted +#define ERR_JSON 9 // JSON parsing failed (input too large?) +#define ERR_FS_BEGIN 10 // Could not init filesystem (no partition?) +#define ERR_FS_QUOTA 11 // The FS is full or the maximum file size is reached +#define ERR_FS_PLOAD 12 // It was attempted to load a preset that does not exist +#define ERR_FS_IRLOAD 13 // It was attempted to load an IR JSON cmd, but the "ir.json" file does not exist +#define ERR_FS_RMLOAD 14 // It was attempted to load an remote JSON cmd, but the "remote.json" file does not exist +#define ERR_FS_GENERAL 19 // A general unspecified filesystem error occurred +#define ERR_OVERTEMP 30 // An attached temperature sensor has measured above threshold temperature (not implemented) +#define ERR_OVERCURRENT 31 // An attached current sensor has measured a current above the threshold (not implemented) +#define ERR_UNDERVOLT 32 // An attached voltmeter has measured a voltage below the threshold (not implemented) // Timer mode types -#define NL_MODE_SET 0 //After nightlight time elapsed, set to target brightness -#define NL_MODE_FADE 1 //Fade to target brightness gradually -#define NL_MODE_COLORFADE 2 //Fade to target brightness and secondary color gradually -#define NL_MODE_SUN 3 //Sunrise/sunset. Target brightness is set immediately, then Sunrise effect is started. Max 60 min. +#define NL_MODE_SET 0 // After nightlight time elapsed, set to target brightness +#define NL_MODE_FADE 1 // Fade to target brightness gradually +#define NL_MODE_COLORFADE 2 // Fade to target brightness and secondary color gradually +#define NL_MODE_SUN 3 // Sunrise/sunset. Target brightness is set immediately, then Sunrise effect is started. Max 60 min. // Settings sub page IDs -#define SUBPAGE_MENU 0 -#define SUBPAGE_WIFI 1 -#define SUBPAGE_LEDS 2 -#define SUBPAGE_UI 3 -#define SUBPAGE_SYNC 4 -#define SUBPAGE_TIME 5 -#define SUBPAGE_SEC 6 -#define SUBPAGE_DMX 7 -#define SUBPAGE_UM 8 -#define SUBPAGE_UPDATE 9 -#define SUBPAGE_2D 10 -#define SUBPAGE_LOCK 251 -#define SUBPAGE_PINREQ 252 -#define SUBPAGE_CSS 253 -#define SUBPAGE_JS 254 -#define SUBPAGE_WELCOME 255 - -#define NTP_PACKET_SIZE 48 // size of NTP receive buffer -#define NTP_MIN_PACKET_SIZE 48 // min expected size - NTP v4 allows for "extended information" appended to the standard fields +#define SUBPAGE_MENU 0 +#define SUBPAGE_WIFI 1 +#define SUBPAGE_LEDS 2 +#define SUBPAGE_UI 3 +#define SUBPAGE_SYNC 4 +#define SUBPAGE_TIME 5 +#define SUBPAGE_SEC 6 +#define SUBPAGE_DMX 7 +#define SUBPAGE_UM 8 +#define SUBPAGE_UPDATE 9 +#define SUBPAGE_2D 10 +#define SUBPAGE_LOCK 251 +#define SUBPAGE_PINREQ 252 +#define SUBPAGE_CSS 253 +#define SUBPAGE_JS 254 +#define SUBPAGE_WELCOME 255 + +#define NTP_PACKET_SIZE 48 // size of NTP receive buffer +#define NTP_MIN_PACKET_SIZE 48 // min expected size - NTP v4 allows for "extended information" appended to the standard fields // Maximum number of pins per output. 5 for RGBCCT analog LEDs. #define OUTPUT_MAX_PINS 5 -//maximum number of rendered LEDs - this does not have to match max. physical LEDs, e.g. if there are virtual busses +// maximum number of rendered LEDs - this does not have to match max. physical LEDs, e.g. if there are virtual busses #ifndef MAX_LEDS #ifdef ESP8266 -#define MAX_LEDS 1664 //can't rely on memory limit to limit this to 1600 LEDs +#define MAX_LEDS 1664 // can't rely on memory limit to limit this to 1600 LEDs #elif defined(CONFIG_IDF_TARGET_ESP32S2) -#define MAX_LEDS 2048 //due to memory constraints +#define MAX_LEDS 2048 // due to memory constraints #else #define MAX_LEDS 8192 #endif #endif #ifndef MAX_LED_MEMORY - #ifdef ESP8266 - #define MAX_LED_MEMORY 4000 - #else - #if defined(ARDUINO_ARCH_ESP32S2) - #define MAX_LED_MEMORY 16000 - #elif defined(ARDUINO_ARCH_ESP32C3) - #define MAX_LED_MEMORY 32000 - #else - #define MAX_LED_MEMORY 64000 - #endif - #endif +#ifdef ESP8266 +#define MAX_LED_MEMORY 4000 +#else +#if defined(ARDUINO_ARCH_ESP32S2) +#define MAX_LED_MEMORY 16000 +#elif defined(ARDUINO_ARCH_ESP32C3) +#define MAX_LED_MEMORY 32000 +#else +#define MAX_LED_MEMORY 64000 +#endif +#endif #endif #ifndef MAX_LEDS_PER_BUS -#define MAX_LEDS_PER_BUS 2048 // may not be enough for fast LEDs (i.e. APA102) +#define MAX_LEDS_PER_BUS 2048 // may not be enough for fast LEDs (i.e. APA102) #endif // string temp buffer (now stored in stack locally) #ifdef ESP8266 #define SETTINGS_STACK_BUF_SIZE 2560 #else -#define SETTINGS_STACK_BUF_SIZE 3840 // warning: quite a large value for stack (640 * WLED_MAX_USERMODS) +#define SETTINGS_STACK_BUF_SIZE 3840 // warning: quite a large value for stack (640 * WLED_MAX_USERMODS) #endif #ifdef WLED_USE_ETHERNET - #define E131_MAX_UNIVERSE_COUNT 20 +#define E131_MAX_UNIVERSE_COUNT 20 #else - #ifdef ESP8266 - #define E131_MAX_UNIVERSE_COUNT 9 - #else - #define E131_MAX_UNIVERSE_COUNT 12 - #endif +#ifdef ESP8266 +#define E131_MAX_UNIVERSE_COUNT 9 +#else +#define E131_MAX_UNIVERSE_COUNT 12 +#endif #endif #ifndef ABL_MILLIAMPS_DEFAULT - #define ABL_MILLIAMPS_DEFAULT 850 // auto lower brightness to stay close to milliampere limit +#define ABL_MILLIAMPS_DEFAULT 850 // auto lower brightness to stay close to milliampere limit #else - #if ABL_MILLIAMPS_DEFAULT == 0 // disable ABL - #elif ABL_MILLIAMPS_DEFAULT < 250 // make sure value is at least 250 - #warning "make sure value is at least 250" - #define ABL_MILLIAMPS_DEFAULT 250 - #endif +#if ABL_MILLIAMPS_DEFAULT == 0 // disable ABL +#elif ABL_MILLIAMPS_DEFAULT < 250 // make sure value is at least 250 +#warning "make sure value is at least 250" +#define ABL_MILLIAMPS_DEFAULT 250 +#endif #endif #ifndef LED_MILLIAMPS_DEFAULT - #define LED_MILLIAMPS_DEFAULT 55 // common WS2812B +#define LED_MILLIAMPS_DEFAULT 55 // common WS2812B #else - #if LED_MILLIAMPS_DEFAULT < 1 || LED_MILLIAMPS_DEFAULT > 100 - #warning "Unusual LED mA current, overriding with default value." - #undef LED_MILLIAMPS_DEFAULT - #define LED_MILLIAMPS_DEFAULT 55 - #endif +#if LED_MILLIAMPS_DEFAULT < 1 || LED_MILLIAMPS_DEFAULT > 100 +#warning "Unusual LED mA current, overriding with default value." +#undef LED_MILLIAMPS_DEFAULT +#define LED_MILLIAMPS_DEFAULT 55 +#endif #endif // PWM settings #ifndef WLED_PWM_FREQ #ifdef ESP8266 - #define WLED_PWM_FREQ 880 //PWM frequency proven as good for LEDs +#define WLED_PWM_FREQ 880 // PWM frequency proven as good for LEDs +#else +#ifdef SOC_LEDC_SUPPORT_XTAL_CLOCK +#define WLED_PWM_FREQ 9765 // XTAL clock is 40MHz (this will allow 12 bit resolution) #else - #ifdef SOC_LEDC_SUPPORT_XTAL_CLOCK - #define WLED_PWM_FREQ 9765 // XTAL clock is 40MHz (this will allow 12 bit resolution) - #else - #define WLED_PWM_FREQ 19531 // APB clock is 80MHz - #endif +#define WLED_PWM_FREQ 19531 // APB clock is 80MHz +#endif #endif #endif @@ -560,30 +561,30 @@ // Size of buffer for API JSON object (increase for more segments) #ifdef ESP8266 - #define JSON_BUFFER_SIZE 10240 +#define JSON_BUFFER_SIZE 10240 +#else +#if defined(ARDUINO_ARCH_ESP32S2) +#define JSON_BUFFER_SIZE 24576 #else - #if defined(ARDUINO_ARCH_ESP32S2) - #define JSON_BUFFER_SIZE 24576 - #else - #define JSON_BUFFER_SIZE 32767 - #endif +#define JSON_BUFFER_SIZE 32767 +#endif #endif -//#define MIN_HEAP_SIZE +// #define MIN_HEAP_SIZE #define MIN_HEAP_SIZE 2048 // Web server limits #ifdef ESP8266 // Minimum heap to consider handling a request -#define WLED_REQUEST_MIN_HEAP (8*1024) +#define WLED_REQUEST_MIN_HEAP (8 * 1024) // Estimated maximum heap required by any one request -#define WLED_REQUEST_HEAP_USAGE (6*1024) +#define WLED_REQUEST_HEAP_USAGE (6 * 1024) #else // ESP32 TCP stack needs much more RAM than ESP8266 // Minimum heap remaining before queuing a request -#define WLED_REQUEST_MIN_HEAP (12*1024) +#define WLED_REQUEST_MIN_HEAP (12 * 1024) // Estimated maximum heap required by any one request -#define WLED_REQUEST_HEAP_USAGE (12*1024) +#define WLED_REQUEST_HEAP_USAGE (12 * 1024) #endif // Maximum number of requests in queue; absolute cap on web server resource usage. // Websockets do not count against this limit. @@ -591,91 +592,91 @@ // Maximum size of node map (list of other WLED instances) #ifdef ESP8266 - #define WLED_MAX_NODES 24 +#define WLED_MAX_NODES 24 #else - #define WLED_MAX_NODES 150 +#define WLED_MAX_NODES 150 #endif // Defaults pins, type and counts to configure LED output #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) - #ifdef WLED_ENABLE_DMX - #define DEFAULT_LED_PIN 1 - #warning "Compiling with DMX. The default LED pin has been changed to pin 1." - #else - #define DEFAULT_LED_PIN 2 // GPIO2 (D4) on Wemos D1 mini compatible boards, safe to use on any board - #endif +#ifdef WLED_ENABLE_DMX +#define DEFAULT_LED_PIN 1 +#warning "Compiling with DMX. The default LED pin has been changed to pin 1." +#else +#define DEFAULT_LED_PIN 2 // GPIO2 (D4) on Wemos D1 mini compatible boards, safe to use on any board +#endif #else - #define DEFAULT_LED_PIN 16 // aligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards (if it is unusable it will be reassigned in WS2812FX::finalizeInit()) +#define DEFAULT_LED_PIN 16 // aligns with GPIO2 (D4) on Wemos D1 mini32 compatible boards (if it is unusable it will be reassigned in WS2812FX::finalizeInit()) #endif #define DEFAULT_LED_TYPE TYPE_WS2812_RGB #define DEFAULT_LED_COUNT 30 #define INTERFACE_UPDATE_COOLDOWN 1000 // time in ms to wait between websockets, alexa, and MQTT updates -#define PIN_RETRY_COOLDOWN 3000 // time in ms after an incorrect attempt PIN and OTA pass will be rejected even if correct -#define PIN_TIMEOUT 900000 // time in ms after which the PIN will be required again, 15 minutes +#define PIN_RETRY_COOLDOWN 3000 // time in ms after an incorrect attempt PIN and OTA pass will be rejected even if correct +#define PIN_TIMEOUT 900000 // time in ms after which the PIN will be required again, 15 minutes // HW_PIN_SCL & HW_PIN_SDA are used for information in usermods settings page and usermods themselves // which GPIO pins are actually used in a hardware layout (controller board) #if defined(I2CSCLPIN) && !defined(HW_PIN_SCL) - #define HW_PIN_SCL I2CSCLPIN +#define HW_PIN_SCL I2CSCLPIN #endif #if defined(I2CSDAPIN) && !defined(HW_PIN_SDA) - #define HW_PIN_SDA I2CSDAPIN +#define HW_PIN_SDA I2CSDAPIN #endif // you cannot change HW I2C pins on 8266 #if defined(ESP8266) && defined(HW_PIN_SCL) - #undef HW_PIN_SCL +#undef HW_PIN_SCL #endif #if defined(ESP8266) && defined(HW_PIN_SDA) - #undef HW_PIN_SDA +#undef HW_PIN_SDA #endif // defaults for 1st I2C on ESP32 (Wire global) #ifndef HW_PIN_SCL - #define HW_PIN_SCL SCL +#define HW_PIN_SCL SCL #endif #ifndef HW_PIN_SDA - #define HW_PIN_SDA SDA +#define HW_PIN_SDA SDA #endif // HW_PIN_SCLKSPI & HW_PIN_MOSISPI & HW_PIN_MISOSPI are used for information in usermods settings page and usermods themselves // which GPIO pins are actually used in a hardware layout (controller board) #if defined(SPISCLKPIN) && !defined(HW_PIN_CLOCKSPI) - #define HW_PIN_CLOCKSPI SPISCLKPIN +#define HW_PIN_CLOCKSPI SPISCLKPIN #endif #if defined(SPIMOSIPIN) && !defined(HW_PIN_MOSISPI) - #define HW_PIN_MOSISPI SPIMOSIPIN +#define HW_PIN_MOSISPI SPIMOSIPIN #endif #if defined(SPIMISOPIN) && !defined(HW_PIN_MISOSPI) - #define HW_PIN_MISOSPI SPIMISOPIN +#define HW_PIN_MISOSPI SPIMISOPIN #endif // you cannot change HW SPI pins on 8266 #if defined(ESP8266) && defined(HW_PIN_CLOCKSPI) - #undef HW_PIN_CLOCKSPI +#undef HW_PIN_CLOCKSPI #endif #if defined(ESP8266) && defined(HW_PIN_DATASPI) - #undef HW_PIN_DATASPI +#undef HW_PIN_DATASPI #endif #if defined(ESP8266) && defined(HW_PIN_MISOSPI) - #undef HW_PIN_MISOSPI +#undef HW_PIN_MISOSPI #endif // defaults for VSPI on ESP32 (SPI global, SPI.cpp) as HSPI is used by WLED (bus_wrapper.h) #ifndef HW_PIN_CLOCKSPI - #define HW_PIN_CLOCKSPI SCK +#define HW_PIN_CLOCKSPI SCK #endif #ifndef HW_PIN_DATASPI - #define HW_PIN_DATASPI MOSI +#define HW_PIN_DATASPI MOSI #endif #ifndef HW_PIN_MISOSPI - #define HW_PIN_MISOSPI MISO +#define HW_PIN_MISOSPI MISO #endif // IRAM_ATTR for 8266 with 32Kb IRAM causes error: section `.text1' will not fit in region `iram1_0_seg' // this hack removes the IRAM flag for some 1D/2D functions - somewhat slower, but it solves problems with some older 8266 chips #ifdef WLED_SAVE_IRAM - #define IRAM_ATTR_YN +#define IRAM_ATTR_YN #else - #define IRAM_ATTR_YN IRAM_ATTR +#define IRAM_ATTR_YN IRAM_ATTR #endif #endif