Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
eaecca9
docs(dali_gear): update readme to match implemented behaviour
netmindz May 23, 2026
0fc601c
esp32s3dev_8MB_opi_dali_gear
netmindz May 23, 2026
23a9360
esp32s3dev_8MB_opi_dali_gear
netmindz May 23, 2026
8394038
fix(dali_gear): address code review comments
netmindz May 24, 2026
6bc19e9
feat(dali_gear): address PR review — TX invert, query responses, QUER…
netmindz May 24, 2026
0d77a27
fix(dali_gear): do not respond to 0xE7 — QUERY COLOUR TYPE is 0xF7 only
netmindz May 24, 2026
670a6fd
feat(dali_gear): respond to QUERY DEVICE TYPE (0x18) with 0x08
netmindz May 24, 2026
71767b7
ci: discover and build custom PlatformIO envs from usermods platformi…
netmindz May 24, 2026
badfcfc
ci: consolidate usermod build envs into per-usermod platformio_overri…
netmindz May 24, 2026
2daf17a
run on push
netmindz May 24, 2026
af4b39e
Fix AHT10_v2 example
netmindz May 24, 2026
d459e6c
no d1_mini env
netmindz May 24, 2026
e68bd2a
no d1_mini env
netmindz May 24, 2026
50cd900
ci: filter usermod matrix to only build changed usermod directories
netmindz May 24, 2026
fb0c1df
SN_Photoresistor
netmindz May 24, 2026
9b4eafa
fix(ci): use PR base SHA for diff and guard jobs against push events
netmindz May 24, 2026
3007564
ESP32 builds all V4
netmindz May 24, 2026
83e32ea
fix: rename/fix platformio_override sample files across usermods
netmindz May 24, 2026
818c3cb
perf: filter custom build matrix to changed usermods on PRs
netmindz May 24, 2026
76a505f
fix release name
netmindz May 24, 2026
76b1e0a
fix release name
netmindz May 24, 2026
133aecb
Merge branch 'usermod-ci' into dali2
netmindz May 24, 2026
fb7e309
Revert "esp32s3dev_8MB_opi_dali_gear"
netmindz May 24, 2026
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
114 changes: 104 additions & 10 deletions .github/workflows/usermods.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ on:
pull_request:
paths:
- usermods/**
push:
paths:
- usermods/**

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
Expand All @@ -12,28 +15,40 @@ jobs:

get_usermod_envs:
# Only run for pull requests from forks (not from branches within wled/WLED)
if: github.event.pull_request.head.repo.full_name != github.repository
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository
name: Gather Usermods
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
- name: Install PlatformIO
run: pip install -r requirements.txt
- name: Get default environments
fetch-depth: 0
- name: Get changed usermod environments
id: envs
run: |
echo "usermods=$(find usermods/ -name library.json | xargs dirname | xargs -n 1 basename | jq -R | grep -v PWM_fan | grep -v BME68X_v2| grep -v pixels_dice_tray | jq --slurp -c)" >> $GITHUB_OUTPUT
# Usermods whose directories changed in this PR
changed=$(git diff --name-only ${{ github.event.pull_request.base.sha }} HEAD \
| grep '^usermods/' | cut -d/ -f2 | sort -u || true)

# All usermods with a library.json (excluding known-incompatible ones)
all=$(find usermods/ -name library.json \
| xargs dirname | xargs -n 1 basename \
| grep -v PWM_fan | grep -v BME68X_v2 | grep -v pixels_dice_tray \
| sort || true)

if [ -z "$changed" ] || [ -z "$all" ]; then
echo "usermods=[]" >> $GITHUB_OUTPUT
else
usermods=$(comm -12 <(echo "$all") <(echo "$changed") | jq -R | jq --slurp -c)
echo "usermods=$usermods" >> $GITHUB_OUTPUT
fi
outputs:
usermods: ${{ steps.envs.outputs.usermods }}


build:
# Only run for pull requests from forks (not from branches within wled/WLED)
if: github.event.pull_request.head.repo.full_name != github.repository
# Skip when no changed usermods were found (e.g. only non-library changes)
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository && needs.get_usermod_envs.outputs.usermods != '[]'
name: Build Enviornments
runs-on: ubuntu-latest
needs: get_usermod_envs
Expand Down Expand Up @@ -74,4 +89,83 @@ jobs:
cat platformio_override.ini

- name: Build firmware
run: pio run -e ${{ matrix.environment }}
run: pio run -e ${{ matrix.environment }}


get_custom_build_envs:
name: Gather Custom Build Environments
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Find usermods with custom build environments
id: custom_envs
run: |
# On PRs: only scan usermods whose directories changed.
# On push: scan all usermods (validates the full set on merge).
if [ "${{ github.event_name }}" = "pull_request" ]; then
changed=$(git diff --name-only ${{ github.event.pull_request.base.sha }} HEAD \
| grep '^usermods/' | cut -d/ -f2 | sort -u || true)
if [ -z "$changed" ]; then
echo "matrix=[]" >> $GITHUB_OUTPUT
exit 0
fi
samples=$(for mod in $changed; do
f="usermods/$mod/platformio_override.ini.sample"
[ -f "$f" ] && echo "$f"
done | sort)
else
samples=$(find usermods/ -name "platformio_override.ini.sample" | sort)
fi

result='[]'
for sample in $samples; do
usermod=$(dirname "$sample" | xargs basename)
envs=$(grep -E '^\[env:[^]]+\]' "$sample" | sed 's/^\[env:\(.*\)\]$/\1/')
for env in $envs; do
result=$(echo "$result" | jq --arg u "$usermod" --arg e "$env" '. + [{usermod: $u, env: $e}]')
done
done
echo "matrix=$(echo "$result" | jq -c '.')" >> $GITHUB_OUTPUT
outputs:
matrix: ${{ steps.custom_envs.outputs.matrix }}


build_custom:
name: Build Custom Env (${{ matrix.usermod }} / ${{ matrix.env }})
runs-on: ubuntu-latest
needs: get_custom_build_envs
if: needs.get_custom_build_envs.outputs.matrix != '[]'
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.get_custom_build_envs.outputs.matrix) }}
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'
- run: npm ci
- name: Cache PlatformIO
uses: actions/cache@v4
with:
path: |
~/.platformio/.cache
~/.buildcache
build_output
key: pio-${{ runner.os }}-${{ matrix.env }}-${{ hashFiles('platformio.ini', 'pio-scripts/output_bins.py') }}-${{ hashFiles('wled00/**', 'usermods/**') }}
restore-keys: pio-${{ runner.os }}-${{ matrix.env }}-${{ hashFiles('platformio.ini', 'pio-scripts/output_bins.py') }}-
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
- name: Install PlatformIO
run: pip install -r requirements.txt
- name: Apply custom build environment
run: cp -v "usermods/${{ matrix.usermod }}/platformio_override.ini.sample" platformio_override.ini
- name: Build firmware
run: pio run -e ${{ matrix.env }}
11 changes: 11 additions & 0 deletions platformio_override.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[env:esp32s3dev_8MB_opi_dali_gear]
;; ESP32-S3 dev board (8MB Flash, QSPI PSRAM) with dali_gear usermod
extends = env:esp32s3dev_8MB_qspi
custom_usermods = dali_gear
lib_deps = ${env:esp32s3dev_8MB_qspi.lib_deps}
https://github.com/netmindz/DALI-Lighting-Interface.git#fix/esp32-volatile-cast
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_dali_gear\"
-D WLED_WATCHDOG_TIMEOUT=0
-D ARDUINO_USB_CDC_ON_BOOT=0 ;; use UART0 via built-in JTAG/serial debug unit (303a:1001)
-DBOARD_HAS_PSRAM
-D WLED_DEBUG
31 changes: 2 additions & 29 deletions platformio_override.sample.ini
Original file line number Diff line number Diff line change
Expand Up @@ -506,42 +506,15 @@ lib_deps = ${esp8266.lib_deps}

# ------------------------------------------------------------------------------
# EleksTube-IPS
# See usermods/EleksTube_IPS/platformio_override.ini.sample
# ------------------------------------------------------------------------------
[env:elekstube_ips]
extends = esp32 ;; use default esp32 platform
board = esp32dev
upload_speed = 921600
custom_usermods = ${env:esp32dev.custom_usermods} RTC EleksTube_IPS
build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_DISABLE_BROWNOUT_DET -D WLED_DISABLE_INFRARED
-D DATA_PINS=12
-D RLYPIN=27
-D BTNPIN=34
-D PIXEL_COUNTS=6
# Display config
-D ST7789_DRIVER
-D TFT_WIDTH=135
-D TFT_HEIGHT=240
-D CGRAM_OFFSET
-D TFT_SDA_READ
-D TFT_MOSI=23
-D TFT_SCLK=18
-D TFT_DC=25
-D TFT_RST=26
-D SPI_FREQUENCY=40000000
-D USER_SETUP_LOADED
monitor_filters = esp32_exception_decoder


# ------------------------------------------------------------------------------
# Usermod examples
# ------------------------------------------------------------------------------

# 433MHz RF remote example for esp32dev
[env:esp32dev_usermod_RF433]
extends = env:esp32dev
custom_usermods =
${env:esp32dev.custom_usermods}
RF433
# 433MHz RF remote example: see usermods/usermod_v2_RF433/platformio_override.ini.sample

# External usermod from a git repository.
# The library's `library.json` must include `"build": {"libArchive": false}`.
Expand Down
5 changes: 0 additions & 5 deletions usermods/AHT10_v2/platformio_override.ini

This file was deleted.

9 changes: 9 additions & 0 deletions usermods/AHT10_v2/platformio_override.ini.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# AHT10/AHT15/AHT20 temperature/humidity usermod build environment
# Copy to platformio_override.ini in the WLED root to use.

[platformio]
default_envs = aht10_example

[env:aht10_example]
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} AHT10_v2
9 changes: 9 additions & 0 deletions usermods/BME280_v2/platformio_override.ini.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# BME280_v2 usermod build environment
# Copy to platformio_override.ini in the WLED root to use.

[platformio]
default_envs = usermod_bme280_esp8266_2m

[env:usermod_esp8266_2m]
extends = env:esp8266_2m
custom_usermods = ${env:esp8266_2m.custom_usermods} BME280_v2
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
; USERMOD_DHT_MQTT - publish measurements to the MQTT broker
; USERMOD_DHT_STATS - For debug, report delay stats

[env:d1_mini_usermod_dht_C]
extends = env:d1_mini
custom_usermods = ${env:d1_mini.custom_usermods} DHT
build_flags = ${env:d1_mini.build_flags} -D USERMOD_DHT_CELSIUS
[env:esp8266_2m_usermod_dht_C]
extends = env:esp8266_2m
custom_usermods = ${env:esp8266_2m.custom_usermods} DHT
build_flags = ${env:esp8266_2m.build_flags} -D USERMOD_DHT_CELSIUS

[env:custom32_LEDPIN_16_usermod_dht_C]
extends = env:custom32_LEDPIN_16
Expand Down
32 changes: 32 additions & 0 deletions usermods/EleksTube_IPS/platformio_override.ini.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# EleksTube IPS clock build environment
# Copy to platformio_override.ini in the WLED root to use.
#
# Note: usermods/EleksTube_IPS/library.json is currently disabled.
# To enable custom_usermods support, rename library.json.disabled to library.json.

[platformio]
default_envs = elekstube_ips

[env:elekstube_ips]
extends = esp32 ;; use default esp32 platform
board = esp32dev
upload_speed = 921600
custom_usermods = ${env:esp32dev.custom_usermods} RTC EleksTube_IPS
build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_DISABLE_BROWNOUT_DET -D WLED_DISABLE_INFRARED
-D DATA_PINS=12
-D RLYPIN=27
-D BTNPIN=34
-D PIXEL_COUNTS=6
# Display config
-D ST7789_DRIVER
-D TFT_WIDTH=135
-D TFT_HEIGHT=240
-D CGRAM_OFFSET
-D TFT_SDA_READ
-D TFT_MOSI=23
-D TFT_SCLK=18
-D TFT_DC=25
-D TFT_RST=26
-D SPI_FREQUENCY=40000000
-D USER_SETUP_LOADED
monitor_filters = esp32_exception_decoder
6 changes: 0 additions & 6 deletions usermods/INA226_v2/platformio_override.ini

This file was deleted.

23 changes: 23 additions & 0 deletions usermods/INA226_v2/platformio_override.ini.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# INA226 power monitor usermod build environments
# Copy to platformio_override.ini in the WLED root to use.

[platformio]
default_envs = ina226_example

# Minimal example — enable the usermod with default settings
[env:ina226_example]
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} INA226_v2
build_flags = ${env:esp32dev.build_flags}
; -D USERMOD_INA226_DEBUG ; uncomment to add debug status to the info modal

# Custom calibration example — adjust constants to match your hardware
[env:ina226_custom]
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} INA226_v2
build_flags = ${env:esp32dev.build_flags}
-D INA226_ENABLED_DEFAULT=true
-D INA226_SHUNT_MICRO_OHMS=2888
-D INA226_DEFAULT_CURRENT_RANGE=10000
-D INA226_CURRENT_OFFSET_MA=-118
-D INA226_CHECK_INTERVAL_MS=1000
9 changes: 9 additions & 0 deletions usermods/LD2410_v2/platformio_override.ini.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# LD2410 presence sensor usermod build environment
# Copy to platformio_override.ini in the WLED root to use.

[platformio]
default_envs = usermod_LD2410_v2_esp32dev

[env:usermod_LD2410_v2_esp32dev]
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} LD2410_v2
10 changes: 10 additions & 0 deletions usermods/LDR_Dusk_Dawn_v2/platformio_override.ini.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# LDR Dusk/Dawn usermod build environment
# Copy to platformio_override.ini in the WLED root to use.

[platformio]
default_envs = usermod_LDR_Dusk_Dawn_esp32dev

[env:usermod_LDR_Dusk_Dawn_esp32dev]
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods}
LDR_Dusk_Dawn
9 changes: 9 additions & 0 deletions usermods/MAX17048_v2/platformio_override.ini.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# MAX17048 battery fuel gauge usermod build environment
# Copy to platformio_override.ini in the WLED root to use.

[platformio]
default_envs = usermod_max17048_esp8266_2m

[env:usermod_max17048_esp8266_2m]
extends = env:esp8266_2m
custom_usermods = ${env:esp8266_2m.custom_usermods} MAX17048_v2
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
; Options
; -------
; USERMOD_SN_PHOTORESISTOR - define this to have this user mod included wled00\usermods_list.cpp
; USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL - the number of milliseconds between measurements, defaults to 60 seconds
; USERMOD_SN_PHOTORESISTOR_FIRST_MEASUREMENT_AT - the number of milliseconds after boot to take first measurement, defaults to 20 seconds
; USERMOD_SN_PHOTORESISTOR_REFERENCE_VOLTAGE - the voltage supplied to the sensor, defaults to 5v
; USERMOD_SN_PHOTORESISTOR_ADC_PRECISION - the ADC precision is the number of distinguishable ADC inputs, defaults to 1024.0 (10 bits)
; USERMOD_SN_PHOTORESISTOR_RESISTOR_VALUE - the resistor size, defaults to 10000.0 (10K hms)
; USERMOD_SN_PHOTORESISTOR_OFFSET_VALUE - the offset value to report on, defaults to 25
;
[env:usermod_sn_photoresistor_d1_mini]
extends = env:d1_mini
[env:usermod_sn_photoresistor_esp8266_2m]
extends = env:esp8266_2m
custom_usermods = ${env:esp8266_2m.custom_usermods} SN_Photoresistor
build_flags =
${common.build_flags_esp8266}
-D USERMOD_SN_PHOTORESISTOR
-D USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL=60
lib_deps = ${env.lib_deps}
8 changes: 0 additions & 8 deletions usermods/TTGO-T-Display/platformio_override.ini

This file was deleted.

16 changes: 16 additions & 0 deletions usermods/TTGO-T-Display/platformio_override.ini.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
; TTGO-T-Display usermod build example.
; Note: this usermod has no library.json so custom_usermods is not available.
; The usermod.cpp must be included manually in your build.

[platformio]
default_envs = ttgo_t_display_example

[env:ttgo_t_display_example]
extends = env:esp32dev
build_flags = ${env:esp32dev.build_flags}
; PIN defines - uncomment and change, if needed:
; -D LEDPIN=2
-D BTNPIN=35
; -D IRPIN=4
; -D RLYPIN=12
; -D RLYMDE=1
5 changes: 0 additions & 5 deletions usermods/Temperature/platformio_override.ini

This file was deleted.

Loading
Loading