Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 32 additions & 8 deletions usermods/seven_segment_display/readme.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,66 @@
# 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 ```<mqttDeviceTopic||mqttGroupTopic>/sevenSeg/perSegment/set```
Payload ```3```

Topic `<mqttDeviceTopic||mqttGroupTopic>/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.

<pre>
HH - 0-23. hh - 1-12, kk - 1-24 hours
MM or mm - 0-59 minutes
SS or ss = 0-59 seconds
: for a colon
All others for alpha numeric, (will be blank when displaying time)
</pre>

##### 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.

<pre>
-------
/ A / 0 - EDCGFAB
Expand All @@ -52,4 +75,5 @@ The order your LEDs are configured in. All segments in the display need to be wi
</pre>

## Version

20211009 - Initial release
4 changes: 4 additions & 0 deletions usermods/usermod_v2_social_counter/library.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name:": "social_counter",
"dependencies": {}
}
78 changes: 78 additions & 0 deletions usermods/usermod_v2_social_counter/readme.md
Original file line number Diff line number Diff line change
@@ -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
41 changes: 41 additions & 0 deletions usermods/usermod_v2_social_counter/social_network_factory.h
Original file line number Diff line number Diff line change
@@ -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 <memory>

class SocialNetworkFactory
{
public:
static std::unique_ptr<SocialNetworkStrategy> createStrategy(int socialType)
{
switch (socialType)
{
case SOCIAL_COUNTER_MOCK:
return std::unique_ptr<SocialNetworkStrategy>(new MockStrategy());

case SOCIAL_COUNTER_INSTAGRAM:
return std::unique_ptr<SocialNetworkStrategy>(new InstagramStrategy());

case SOCIAL_COUNTER_YOUTUBE:
return std::unique_ptr<SocialNetworkStrategy>(new YouTubeStrategy());

case SOCIAL_COUNTER_TIKTOK:
return std::unique_ptr<SocialNetworkStrategy>(new TikTokStrategy());

case SOCIAL_COUNTER_TWITCH:
return std::unique_ptr<SocialNetworkStrategy>(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<SocialNetworkStrategy>(new InstagramStrategy());
}
}
};
14 changes: 14 additions & 0 deletions usermods/usermod_v2_social_counter/social_network_types.h
Original file line number Diff line number Diff line change
@@ -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
71 changes: 71 additions & 0 deletions usermods/usermod_v2_social_counter/strategies/instagram_strategy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#pragma once

#include "social_network_strategy.h"
#include "../social_network_types.h"
#include <Arduino.h>
#include <HTTPClient.h>

// 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);
}
};
35 changes: 35 additions & 0 deletions usermods/usermod_v2_social_counter/strategies/mock_strategy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include "social_network_strategy.h"
#include "../social_network_types.h"
#include <Arduino.h>

// 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;
}
Comment on lines +13 to +24
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Guard the metric index before touching values

selectedMetric ultimately comes from user-configurable JSON/UI input. If someone saves an out-of-range value (or a future metric constant exceeds 3), values[metric] writes past the four-element array, corrupting memory and crashing the MCU. Add a bounds check before using metric, bail out on invalid input, and keep the rest of the logic unchanged.

   bool fetchMetric(int metric, const String &link, int &count) override
   {
     static int values[4] = {0, 1000, 5000, 100};

+    if (metric < 0 || metric >= (int)(sizeof(values) / sizeof(values[0])))
+    {
+      Serial.printf("[MOCK] Métrica inválida: %d\n", metric);
+      return false;
+    }
+
     // Simula cada métrica com incremento independente
     values[metric] += (metric + 1) * 111; // muda a taxa por tipo
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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;
}
bool fetchMetric(int metric, const String &link, int &count) override
{
static int values[4] = {0, 1000, 5000, 100};
if (metric < 0 || metric >= (int)(sizeof(values) / sizeof(values[0])))
{
Serial.printf("[MOCK] Métrica inválida: %d\n", metric);
return false;
}
// 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;
}
🤖 Prompt for AI Agents
In usermods/usermod_v2_social_counter/strategies/mock_strategy.h around lines 13
to 24, the code indexes the static array `values[4]` with `metric` without
validating it; add a bounds check to ensure 0 <= metric < 4 before any access,
log or Serial.printf an error and return false (or otherwise bail) on invalid
index, and only then proceed with the existing increment, wrap/reset and
assignment logic so out-of-range inputs cannot corrupt memory.


String getName() override
{
return "Mock";
}

int getType() override
{
return SOCIAL_COUNTER_MOCK;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include <Arduino.h>

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;
};
Loading