Compare commits

..

9 Commits

Author SHA1 Message Date
Benjam Welker 9b1f509d77 Analog button fix (#5659)
* add analog button options

* fix issues with duplicate options for digital vs analog

* dynamic button type options
2026-06-15 21:24:27 +02:00
Damian Schneider 55cee99a74 Update pixel buffer after changing matrix dimensions (#5675)
* update pixel buffer after changing matrix dimensions
2026-06-15 21:08:18 +02:00
Will Tatam 4efb02de58 docs: refresh README to reflect current feature set and project state (#5626)
* docs: refresh README to reflect current feature set and project state

* docs: fix HUB75 support note — available on all ESP32 variants, not just S3

* docs: mention network audio sources in AudioReactive feature description

* docs: remove ESP8266 references — EOL platform, not recommended for new installs

* docs: make PayPal donation link clearly attributed to Aircoookie

* docs: add cross-references to kno.wled.ge docs throughout feature list
2026-06-14 08:17:54 +01:00
Will Tatam a4b14c0191 ci: discover and build custom PlatformIO envs from usermods platformi… (#5649)
* ci: discover and build custom PlatformIO envs from usermods platformio_override.ini.sample files

Adds two new jobs to the Usermod CI workflow to address issue #5648:
- get_custom_build_envs: scans all usermods/*/platformio_override.ini.sample files
  and emits a matrix of {usermod, env} pairs by extracting [env:*] section names
- build_custom: builds each discovered environment by copying the .ini.sample as
  platformio_override.ini and running pio run -e <env>

This allows PRs introducing usermods with custom build environments (such as
pixels_dice_tray) to have those environments validated in CI without committing
platformio_override.ini to the repository.

* ci: consolidate usermod build envs into per-usermod platformio_override.ini.sample files

Move usermod-specific PlatformIO environments out of the root
platformio_override.sample.ini and into dedicated files within each
usermod's own directory, making them discoverable by CI:


* run on push

* Fix AHT10_v2 example

* no d1_mini env

* no d1_mini env

* ci: filter usermod matrix to only build changed usermod directories

Instead of building every usermod with a library.json on each PR, use
git diff to identify which usermods/ subdirectories were actually touched
and intersect that with the known-good library.json list.

This reduces CI time significantly for PRs that only modify one or two
usermods (previously every PR triggered ~40 usermods × 4 chipsets).

Also removes the unnecessary PlatformIO install from get_usermod_envs
(the step only uses shell/jq, not pio) and adds fetch-depth: 0 to
ensure the base branch is available for the diff.

* SN_Photoresistor

* fix(ci): use PR base SHA for diff and guard jobs against push events

github.base_ref is empty on push events, causing 'ambiguous argument
origin/...HEAD'. Fix by:
- Adding github.event_name == 'pull_request' guard to both jobs so
  they never run on push events where pull_request context is absent
- Replacing origin/${{ github.base_ref }}...HEAD with
  ${{ github.event.pull_request.base.sha }} HEAD which uses the
  concrete base commit SHA provided by GitHub directly

* ESP32 builds all V4

* fix: rename/fix platformio_override sample files across usermods

- Rename *.ini (gitignored) and *.sample.ini (wrong extension order) to
  the correct platformio_override.ini.sample convention so CI discovers them
- Fix AHT10_v2: custom_usermods AHT10 → AHT10_v2 (match library.json name)
- Fix INA226_v2: custom_usermods INA226 → INA226_v2 (both envs)
- Fix TTGO-T-Display: replace direct [env:esp32dev] override with a named
  env that extends esp32dev; add note that library.json is absent so
  custom_usermods is not available for this usermod

Affected usermods: AHT10_v2, DHT, INA226_v2, SN_Photoresistor,
TTGO-T-Display, Temperature, four_line_display_ALT, rotary_encoder_ui_ALT

* perf: filter custom build matrix to changed usermods on PRs

On pull_request events, get_custom_build_envs now only scans usermod
directories that changed in the PR (matching the behaviour of the
get_usermod_envs job). On push events (e.g. merging a PR) it still
scans all usermods to validate the full set.

* fix release name

* fix release name

* fix: resolve 8 CI build failures in custom usermod environments

- BME280_v2: fix default_envs typo (usermod_bme280_esp8266_2m →
  usermod_esp8266_2m to match actual [env:] section name)
- DHT: replace extends env:custom32_LEDPIN_16 (not in this fork) with
  env:esp32dev + -D LEDPIN=16; rename env accordingly
- SN_Photoresistor: replace ${common.build_flags_esp8266} (key absent in
  this fork) with ${env:esp8266_2m.build_flags} / lib_deps equivalent
- sht: guard ESP.getChipModel() behind #ifdef ARDUINO_ARCH_ESP32 — method
  does not exist on ESP8266 (fixes custom_esp8266_2m_usermod_sht build)
- EleksTube_IPS: delete platformio_override.ini.sample — library.json is
  disabled so the env cannot build; delete rather than ship a broken sample
- pixels_dice_tray: exclude from build_custom matrix (same as standard
  matrix) — BLE library incompatibility with current IDF causes build failure
- workflow: add PWM_fan / BME68X_v2 to exclusion list in get_custom_build_envs
  for consistency with get_usermod_envs

* Do not add platformio_override.ini.sample just because example was in readme

---------

Co-authored-by: Frank Möhle <91616163+softhack007@users.noreply.github.com>
2026-06-12 08:58:09 +01:00
Frank Möhle d8e3578084 disable fb infer in coderabbit tools list 2026-06-09 14:12:50 +02:00
Frank Möhle 30abc01c0c Remove outdated Wiki link from CONTRIBUTING.md
Removed link to WIKI for submitting a PR. The information in the wiki is outdated, and it contradicts the "no force-push" rule.
2026-06-08 17:42:40 +02:00
Frank Möhle dea6ec0e4c Update links in CONTRIBUTING.md to reference AGENTS.md 2026-06-08 10:29:55 +02:00
Frank Möhle dfd78f4903 Clarify branch maintenance status in instructions
Updated branch descriptions for clarity and maintenance status.
2026-06-08 10:23:57 +02:00
Frank Möhle 5f7910742e Clarify repository language requirement
Emphasize that the repository language is English for all aspects including code, comments, and documentation.
2026-06-05 22:22:46 +02:00
22 changed files with 332 additions and 189 deletions
+7
View File
@@ -33,6 +33,13 @@ reviews:
- V5
ignore_title_keywords:
- WIP
tools:
fbinfer:
enabled: false # Arduino.h not available on Linux analysis host
cppcheck:
enabled: true # cppcheck works fine without Arduino headers
clang:
enabled: true # clang tidy likewise works
path_instructions:
- path: "**/*.{cpp,h,hpp,ino}"
+2 -1
View File
@@ -50,7 +50,7 @@ For detailed build timeouts, development workflows, troubleshooting, and validat
main # Main development trunk (daily/nightly) 17.0.0-dev
├── V5 # special branch: code rework for esp-idf 5.5.x (unstable)
├── V5-C6 # special branch: integration of new MCU types: esp32-c5, esp32-c6, esp32-p4 (unstable)
16_x # current beta, preparations for next release 16.0.0
16_x # maintenance for release 16.x.y
0_15_x # maintenance (bugfixes only) for current release 0.15.4
(tag) v0.14.4 # previous version 0.14.4 (no maintenance)
(tag) v0.13.3 # old version 0.13.3 (no maintenance)
@@ -60,6 +60,7 @@ main # Main development trunk (daily/nightly) 17.0.0-dev
- ``main``: development trunk (daily/nightly)
- ``V5`` and ``V5-C6``: code rework for esp-idf 5.5.x (unstable) - branched from ``main``.
- ``16_x``: maintenance for release 16.x.y
- ``0_15_x``: bugfixing / maintenance for release 0.15.x
### Repository Structure
+106 -10
View File
@@ -4,6 +4,9 @@ on:
pull_request:
paths:
- usermods/**
push:
paths:
- usermods/**
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
@@ -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
@@ -74,4 +89,85 @@ 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)
# Skip usermods known to be incompatible (same list as get_usermod_envs)
case "$usermod" in PWM_fan|BME68X_v2|pixels_dice_tray) continue ;; esac
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 }}
+1 -1
View File
@@ -233,7 +233,7 @@ No automated linting is configured. Match existing code style in files you edit.
## General Rules
- Repository language is English.
- Important: Repository language is **English**. This applies to source code (including comments), commit messages and any kind of documentation for developer or users.
- The `docs/` folder is for developer/contributor information (coding conventions, architecture, etc.). User documentation is maintained in the [wled/WLED-Docs](https://github.com/wled/WLED-Docs) repository.
- Never edit or commit auto-generated `wled00/html_*.h` / `wled00/js_*.h`.
- When updating an existing PR, retain the original description. Only modify it to ensure technical accuracy. Add change logs after the existing description.
+2 -4
View File
@@ -10,8 +10,8 @@ We'll work with you to refine your contribution, but we'll also push back if som
Here are a few suggestions to make it easier for you to contribute:
### Important Developer Infos
* [Project Structure, Files and Directories](.github/copilot-instructions.md#project-structure-overview) (in our AI instructions)
* [Instructions for creating usermods](.github/copilot-instructions.md#usermod-guidelines) (in our AI instructions)
* [Project Structure, Files and Directories](AGENTS.md#project-structure) (in our AI instructions)
* [Instructions for creating usermods](AGENTS.md#usermod-pattern) (in our AI instructions)
* KB: [Compiling WLED](https://kno.wled.ge/advanced/compiling-wled/) - slightly outdated but still helpful :-)
* Arduino IDE is not supported any more. Use VSCode with the PlatformIO extension.
* [Compiling in VSCode/Platformio](https://github.com/wled/WLED-Docs/issues/161) - modern way without command line or platformio.ini changes.
@@ -141,8 +141,6 @@ Sometimes you might hit merge conflicts with `main` that are harder to solve. He
### Additional Resources
Want to know more? Check out:
- 📚 [GitHub Desktop documentation](https://docs.github.com/en/desktop) - if you prefer GUI tools
- 🎓 [How to properly submit a PR](https://github.com/wled-dev/WLED/wiki/How-to-properly-submit-a-PR) - detailed tips and tricks
## After Approval
Once approved, a maintainer will merge your PR (possibly squashing commits).
+2 -29
View File
@@ -509,42 +509,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}`.
+63 -47
View File
@@ -7,81 +7,97 @@
<a href="https://kno.wled.ge"><img src="https://img.shields.io/badge/quick_start-wiki-blue.svg?style=flat-square"></a>
<a href="https://github.com/Aircoookie/WLED-App"><img src="https://img.shields.io/badge/app-wled-blue.svg?style=flat-square"></a>
<a href="https://gitpod.io/#https://github.com/wled-dev/WLED"><img src="https://img.shields.io/badge/Gitpod-ready--to--code-blue?style=flat-square&logo=gitpod"></a>
</p>
</p>
# Welcome to WLED! ✨
A fast and feature-rich implementation of an ESP32 and ESP8266 webserver to control NeoPixel (WS2812B, WS2811, SK6812) LEDs or also SPI based chipsets like the WS2801 and APA102!
A fast and feature-rich firmware for ESP32 microcontrollers to control addressable LEDs — from simple strips to large 2D matrices and HUB75 panels.
Originally created by [Aircoookie](https://github.com/Aircoookie)
Originally created by [Aircoookie](https://github.com/Aircoookie), now maintained by a community of contributors.
## ⚙️ Features
- WS2812FX library with more than 100 special effects
- FastLED noise effects and 50 palettes
- Modern UI with color, effect and segment controls
- Segments to set different effects and colors to user defined parts of the LED string
- Settings page - configuration via the network
- Access Point and station mode - automatic failsafe AP
- [Up to 10 LED outputs](https://kno.wled.ge/features/multi-strip/#esp32) per instance
- Support for RGBW strips
- Up to 250 user presets to save and load colors/effects easily, supports cycling through them.
- Presets can be used to automatically execute API calls
- Nightlight function (gradually dims down)
- Full OTA software updateability (HTTP + ArduinoOTA), password protectable
- Configurable analog clock (Cronixie, 7-segment and EleksTube IPS clock support via usermods)
- Configurable Auto Brightness limit for safe operation
- Filesystem-based config for easier backup of presets and settings
## 💡 Supported light control interfaces
- WLED app for [Android](https://play.google.com/store/apps/details?id=ca.cgagnier.wlednativeandroid) and [iOS](https://apps.apple.com/gb/app/wled-native/id6446207239)
- JSON and HTTP request APIs
- MQTT
- E1.31, Art-Net, DDP and TPM2.net
- [diyHue](https://github.com/diyhue/diyHue) (Wled is supported by diyHue, including Hue Sync Entertainment under udp. Thanks to [Gregory Mallios](https://github.com/gmallios))
- [Hyperion](https://github.com/hyperion-project/hyperion.ng)
- UDP realtime
- Alexa voice control (including dimming and color)
- Sync to Philips hue lights
- Adalight (PC ambilight via serial) and TPM2
- Sync color of multiple WLED devices (UDP notifier)
- Infrared remotes (24-key RGB, receiver required)
- Simple timers/schedules (time from NTP, timezones/DST supported)
### Effects & Visuals
- [**200+ built-in effects**](https://kno.wled.ge/features/effects/) including classic animations, audio-reactive, and 2D/matrix effects
- [50+ color palettes](https://kno.wled.ge/features/palettes/) plus a built-in **custom palette editor** (PixelForge)
- [**2D LED matrix support**](https://kno.wled.ge/advanced/mapping/) with dedicated 2D effects and flexible panel mapping
- [**HUB75 RGB matrix panel support**](https://kno.wled.ge/advanced/HUB75/) (ESP32)
- [**AudioReactive**](https://kno.wled.ge/advanced/audio-reactive/) effects — included by default, responding to sound via microphone, line-in, or network audio source
- Effect blending for smooth transitions between animations
- Antialiased drawing functions for smooth graphics
### Segments & Control
- [**Segments**](https://kno.wled.ge/features/segments/) — apply different effects, colors and palettes to independent parts of your LED setup simultaneously
- Up to **250 presets** to save and recall colors, effects and segment configurations — supports [playlists](https://kno.wled.ge/features/presets/) for automated cycling
- Nightlight function with configurable dimming curve
- Configurable **Auto Brightness Limiter** (per output) for safe operation
### Hardware Support
- **ESP32** (all variants: original, S2, S3, C3)
- [**Up to 17 LED outputs**](https://kno.wled.ge/features/multi-strip/) on ESP32 using parallel I2S + RMT
- [Addressable LED support](https://kno.wled.ge/basics/compatible-led-strips/): WS2812B, WS2811, WS2815, SK6812, WS2805, TM1914, APA102, WS2801, LPD8806, and many more
- RGBW, [RGB+CCT](https://kno.wled.ge/features/cct/) and white-only strips
- PWM outputs for analog LEDs and dimmers
- [**Ethernet** support](https://kno.wled.ge/features/ethernet-lan/) for a wide range of boards (QuinLED, LILYGO, Olimex, and more)
- Filesystem-based config for easy backup and restore of presets and settings
- Full OTA firmware updates (HTTP + ArduinoOTA), password-protectable
### Connectivity & Integrations
- **WLED app** for [Android](https://play.google.com/store/apps/details?id=ca.cgagnier.wlednativeandroid) and [iOS](https://apps.apple.com/gb/app/wled-native/id6446207239)
- [JSON](https://kno.wled.ge/interfaces/json-api/) and [HTTP request](https://kno.wled.ge/interfaces/http-api/) APIs
- **Multi-WiFi** — connect to up to 3 networks with automatic AP fallback
- **ESP-NOW** wireless sync between devices (no WiFi router required)
- [**MQTT**](https://kno.wled.ge/interfaces/mqtt/) with Home Assistant discovery
- [**E1.31, Art-Net**](https://kno.wled.ge/interfaces/e1.31-dmx/), [DDP](https://kno.wled.ge/interfaces/ddp/) and [TPM2.net](https://kno.wled.ge/interfaces/udp-realtime/) for DMX/professional lighting control
- [UDP realtime sync](https://kno.wled.ge/interfaces/udp-notifier/) across multiple WLED devices
- Alexa voice control (on/off, brightness, color)
- [Philips Hue sync](https://kno.wled.ge/interfaces/philips-hue/)
- [diyHue](https://github.com/diyhue/diyHue) and [Hyperion](https://github.com/hyperion-project/hyperion.ng) integration
- [Adalight / TPM2](https://kno.wled.ge/interfaces/serial/) (PC ambilight via serial)
- [Infrared remote control](https://kno.wled.ge/interfaces/infrared/) (24-key RGB, receiver required)
- Timers and schedules (NTP time sync, full timezone and DST support)
### Developer-Friendly
- **Usermod system** — extend WLED with community or custom modules without modifying core code
- Large and active [usermod library](https://kno.wled.ge/advanced/community-usermods/) including AudioReactive, temperature sensors, rotary encoders, displays, and much more
- Well-documented [JSON API](https://kno.wled.ge/interfaces/json-api/)
- Licensed under the **EUPL v1.2**
## 📲 Quick start guide and documentation
See the [documentation on our official site](https://kno.wled.ge)!
See the [documentation at kno.wled.ge](https://kno.wled.ge)!
[On this page](https://kno.wled.ge/basics/tutorials/) you can find excellent tutorials and tools to help you get your new project up and running!
[Tutorials and getting-started guides](https://kno.wled.ge/basics/tutorials/) to help you get your project running quickly.
## 🖼️ User interface
<img src="/images/macbook-pro-space-gray-on-the-wooden-table.jpg" width="50%"><img src="/images/walking-with-iphone-x.jpg" width="50%">
## 💾 Compatible hardware
See [here](https://kno.wled.ge/basics/compatible-hardware)!
See the [compatible hardware list](https://kno.wled.ge/basics/compatible-hardware) on the wiki.
## ✌️ Other
Licensed under the EUPL v1.2 license
Credits [here](https://kno.wled.ge/about/contributors/)!
CORS proxy by [Corsfix](https://corsfix.com/)
Licensed under the [EUPL v1.2](https://raw.githubusercontent.com/wled-dev/WLED/main/LICENSE).
Credits to all [contributors](https://kno.wled.ge/about/contributors/)!
CORS proxy by [Corsfix](https://corsfix.com/).
Join the Discord server to discuss everything about WLED!
<a href="https://discord.gg/QAh7wJHrRM"><img src="https://discordapp.com/api/guilds/473448917040758787/widget.png?style=banner2" width="25%"></a>
Check out the WLED [Discourse forum](https://wled.discourse.group)!
Check out the WLED [Discourse forum](https://wled.discourse.group)!
You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com), but please, only do so if you want to talk to me privately.
If you'd like to reach the original creator privately: [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com).
If WLED really brightens up your day, you can [![](https://img.shields.io/badge/send%20me%20a%20small%20gift-paypal-blue.svg?style=flat-square)](https://paypal.me/aircoookie)
If WLED brightens up your day, you can [send a gift to Aircoookie via PayPal](https://paypal.me/aircoookie).
---
*Disclaimer:*
*Disclaimer:*
If you are prone to photosensitive epilepsy, we recommended you do **not** use this software.
If you still want to try, don't use strobe, lighting or noise modes or high effect speed settings.
As per the EUPL license, I assume no liability for any damage to you or any other person or equipment.
If you are prone to photosensitive epilepsy, we recommend you do **not** use this software.
If you still want to try, avoid strobe, lightning or noise modes and high effect speed settings.
As per the EUPL license, no liability is assumed for any damage to you or any other person or equipment.
@@ -1,5 +0,0 @@
[env:aht10_example]
extends = env:esp32dev
build_flags =
${common.build_flags} ${esp32.build_flags}
; -D USERMOD_AHT10_DEBUG ; -- add a debug status to the info modal
@@ -8,13 +8,13 @@
; 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
custom_usermods = ${env:custom32_LEDPIN_16.custom_usermods} DHT
build_flags = ${env:custom32_LEDPIN_16.build_flags} -D USERMOD_DHT_CELSIUS -D USERMOD_DHT_STATS
[env:esp32dev_LEDPIN_16_usermod_dht_C]
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} DHT
build_flags = ${env:esp32dev.build_flags} -D LEDPIN=16 -D USERMOD_DHT_CELSIUS -D USERMOD_DHT_STATS
@@ -1,6 +0,0 @@
[env:ina226_example]
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} INA226_v2
build_flags =
${env:esp32dev.build_flags}
; -D USERMOD_INA226_DEBUG ; -- add a debug status to the info modal
@@ -1,6 +1,5 @@
; 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
@@ -8,9 +7,10 @@
; 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
lib_deps = ${env.lib_deps}
${env:esp8266_2m.build_flags}
-D USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL=60
lib_deps = ${env:esp8266_2m.lib_deps}
@@ -1,8 +0,0 @@
[env:esp32dev]
build_flags = ${common.build_flags_esp32}
; PIN defines - uncomment and change, if needed:
; -D LEDPIN=2
-D BTNPIN=35
; -D IRPIN=4
; -D RLYPIN=12
; -D RLYMDE=1
@@ -1,5 +0,0 @@
; Options
; -------
; USERMOD_DALLASTEMPERATURE_MEASUREMENT_INTERVAL - the number of milliseconds between measurements, defaults to 60 seconds
;
@@ -13,7 +13,7 @@ board_build.partitions = ${esp32.large_partitions}
board_build.f_flash = 80000000L
board_build.flash_mode = qio
monitor_filters = esp32_exception_decoder
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=T-QT-PRO-8MB
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"T-QT-PRO-8MB_dice\"
-D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
@@ -75,7 +75,7 @@ board_build.partitions = ${esp32.large_partitions}
board_build.f_flash = 80000000L
board_build.flash_mode = qio
monitor_filters = esp32_exception_decoder
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_8MB_qspi
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=\"ESP32-S3_8MB_qspi_dice\"
-D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
@@ -105,7 +105,7 @@ lib_deps = ${esp32s3.lib_deps}
# https://github.com/wled-dev/WLED/issues/1382
; [env:esp32dev_dice]
; extends = env:esp32dev
; build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=ESP32
; build_flags = ${common.build_flags} ${esp32.build_flags} -D WLED_RELEASE_NAME=\"ESP32_dice\"
; ; Enable Pixels dice mod
; -D USERMOD_PIXELS_DICE_TRAY
; lib_deps = ${esp32.lib_deps}
+6
View File
@@ -143,7 +143,13 @@ void ShtUsermod::appendDeviceToMqttDiscoveryMessage(JsonDocument& root) {
device[F("ids")] = escapedMac.c_str();
device[F("name")] = serverDescription;
device[F("sw")] = versionString;
// AI: below section was generated by an AI
#ifdef ARDUINO_ARCH_ESP32
device[F("mdl")] = ESP.getChipModel();
#else
device[F("mdl")] = F("ESP8266");
#endif
// AI: end
device[F("mf")] = F("espressif");
}
@@ -2,10 +2,10 @@
default_envs = esp32dev_fld
[env:esp32dev_fld]
extends = env:esp32dev_V4
custom_usermods = ${env:esp32dev_V4.custom_usermods} four_line_display_ALT
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} four_line_display_ALT
build_flags =
${env:esp32dev_V4.build_flags}
${env:esp32dev.build_flags}
-D FLD_TYPE=SH1106
-D I2CSCLPIN=27
-D I2CSDAPIN=26
@@ -2,10 +2,10 @@
default_envs = esp32dev_re
[env:esp32dev_re]
extends = env:esp32dev_V4
custom_usermods = ${env:esp32dev_V4.custom_usermods} rotary_encoder_ui_ALT
extends = env:esp32dev
custom_usermods = ${env:esp32dev.custom_usermods} rotary_encoder_ui_ALT
build_flags =
${env:esp32dev_V4.build_flags}
${env:esp32dev.build_flags}
-D USERMOD_ROTARY_ENCODER_GPIO=INPUT
-D ENCODER_DT_PIN=21
-D ENCODER_CLK_PIN=23
+1
View File
@@ -879,6 +879,7 @@ class WS2812FX {
printSize(), // prints memory usage for strip components
#endif
finalizeInit(), // initialises strip components
updatePixelBuffer(), // (re)allocate memory for _pixels[]
service(), // executes effect functions when due and calls strip.show()
setCCT(uint16_t k), // sets global CCT (either in relative 0-255 value or in K)
setBrightness(uint8_t b, bool direct = false), // sets strip brightness
+14 -3
View File
@@ -1272,11 +1272,17 @@ void WS2812FX::finalizeInit() {
deserializeMap(); // (re)load default ledmap (will also setUpMatrix() if ledmap does not exist)
// allocate frame buffer after matrix has been set up (gaps!)
updatePixelBuffer();
DEBUG_PRINTF_P(PSTR("Heap after strip init: %uB\n"), getFreeHeapSize());
}
// update global _pixels[] buffer to match getLengthTotal() note: if allocation fails, WLED will not render anything
void WS2812FX::updatePixelBuffer() {
uint32_t requiredMem = getLengthTotal() * sizeof(uint32_t);
p_free(_pixels); // using realloc on large buffers can cause additional fragmentation instead of reducing it
// use PSRAM if available: there is no measurable perfomance impact between PSRAM and DRAM on S2/S3 with QSPI PSRAM for this buffer
_pixels = static_cast<uint32_t*>(allocate_buffer(getLengthTotal() * sizeof(uint32_t), BFRALLOC_ENFORCE_PSRAM | BFRALLOC_NOBYTEACCESS | BFRALLOC_CLEAR));
DEBUG_PRINTF_P(PSTR("strip buffer size: %uB\n"), getLengthTotal() * sizeof(uint32_t));
DEBUG_PRINTF_P(PSTR("Heap after strip init: %uB\n"), getFreeHeapSize());
_pixels = static_cast<uint32_t*>(allocate_buffer(requiredMem, BFRALLOC_ENFORCE_PSRAM | BFRALLOC_NOBYTEACCESS | BFRALLOC_CLEAR));
DEBUG_PRINTF_P(PSTR("strip buffer size: %uB\n"), requiredMem);
}
void WS2812FX::service() {
@@ -2080,10 +2086,13 @@ bool WS2812FX::deserializeMap(unsigned n) {
customMappingSize = 0; // prevent use of mapping if anything goes wrong
currentLedmap = 0;
if (n == 0 || isFile) interfaceUpdateCallMode = CALL_MODE_WS_SEND; // schedule WS update (to inform UI)
uint32_t lengthTotalBefore = strip.getLengthTotal();
if (!isFile && n==0 && isMatrix) {
// 2D panel support creates its own ledmap (on the fly) if a ledmap.json does not exist
setUpMatrix();
if (strip.getLengthTotal() != lengthTotalBefore)
strip.updatePixelBuffer(); // allocate _pixels[] to match new length
return false;
}
@@ -2158,6 +2167,8 @@ bool WS2812FX::deserializeMap(unsigned n) {
}
releaseJSONBufferLock();
if (strip.getLengthTotal() != lengthTotalBefore)
strip.updatePixelBuffer(); // allocate _pixels[] to match new length
return (customMappingSize > 0);
}
+14 -21
View File
@@ -802,11 +802,10 @@ BusHub75Matrix::BusHub75Matrix(const BusConfig &bc) : Bus(bc.type, bc.start, bc.
_hasRgb = true;
_hasWhite = false;
virtualDisp = nullptr; // todo: this should be solved properly, can cause memory leak (if omitted here, nothing seems to work)
_isVirtual = false;
// aliases for easier reading
unsigned panelWidth = bc.pins[0];
unsigned panelHeight = bc.pins[1];
unsigned chainLength = bc.pins[2];
uint8_t panelWidth = bc.pins[0];
uint8_t panelHeight = bc.pins[1];
uint8_t chainLength = bc.pins[2];
_rows = bc.pins[3];
_cols = bc.pins[4];
@@ -823,7 +822,7 @@ BusHub75Matrix::BusHub75Matrix(const BusConfig &bc) : Bus(bc.type, bc.start, bc.
mxconfig.clkphase = bc.reversed;
// allow chain length up to 4, limit to prevent bad data from preventing boot due to low memory
mxconfig.chain_length = max(1U, min(chainLength, 4U));
mxconfig.chain_length = max((uint8_t) 1, min(chainLength, (uint8_t) 4));
if (mxconfig.mx_height >= 64 && (mxconfig.chain_length > 1)) {
#if defined(BOARD_HAS_PSRAM) // limitation to one panel only applies to boards without PSRAM
@@ -836,12 +835,12 @@ BusHub75Matrix::BusHub75Matrix(const BusConfig &bc) : Bus(bc.type, bc.start, bc.
}
if (bc.type == TYPE_HUB75MATRIX_HS) {
mxconfig.mx_width = min(128U, panelWidth); // UI limit is 128
mxconfig.mx_height = min(64U, panelHeight);
mxconfig.mx_width = min((uint8_t) 64, panelWidth); // TODO: UI limit is 128, this limits to 64
mxconfig.mx_height = min((uint8_t) 64, panelHeight);
} else if (bc.type == TYPE_HUB75MATRIX_QS) {
_isVirtual = true;
mxconfig.mx_width = min(128U, panelWidth) * 2;
mxconfig.mx_height = min(64U, panelHeight) / 2;
mxconfig.mx_width = min((uint8_t) 64, panelWidth) * 2;
mxconfig.mx_height = min((uint8_t) 64, panelHeight) / 2;
mxconfig.driver = HUB75_I2S_CFG::FM6124; // use FM6124 for "outdoor" 4-scan panels - workaround until we can make the driver user-configurable
} else {
DEBUGBUS_PRINTLN("Unknown type");
@@ -888,12 +887,6 @@ BusHub75Matrix::BusHub75Matrix(const BusConfig &bc) : Bus(bc.type, bc.start, bc.
// HUB75_I2S_CFG::i2s_pins _pins={R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN};
mxconfig.gpio = {4, 5, 6, 7, 15, 16, 18, 8, 3, 42, 9, 40, 2, 41};
#elif defined(SEENGREAT_V2_PINOUT)
DEBUGBUS_PRINTLN("MatrixPanel_I2S_DMA - S3 devKit-C with PSRAM, SEENGREAT_V2 pinout");
mxconfig.gpio = { 18, 8, 17, // R1_PIN, G1_PIN, B1_PIN,
16, 1, 15, // R2_PIN, G2_PIN, B2_PIN,
7, 48, 6, 47, 2, // A_PIN, B_PIN, C_PIN, D_PIN, E_PIN,
21, 4, 5 }; //LAT_PIN, OE_PIN,CLK_PIN
#else
DEBUGBUS_PRINTLN("MatrixPanel_I2S_DMA - S3 with PSRAM");
// HUB75_I2S_CFG::i2s_pins _pins={R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN};
@@ -1018,15 +1011,15 @@ BusHub75Matrix::BusHub75Matrix(const BusConfig &bc) : Bus(bc.type, bc.start, bc.
// chained panels with cols and rows define need the virtual display driver, so do quarter-scan panels
if (chainLength > 1 && (_rows > 1 || _cols > 1) || bc.type == TYPE_HUB75MATRIX_QS) {
_isVirtual = true;
if (chainLength > 1 && (_rows > 1 || _cols > 1)) chainType = CHAIN_TOP_RIGHT_DOWN; // we need to use a _DOWN chainType, otherwise the display is upside-down
DEBUGBUS_PRINTF_P(PSTR("Using virtual matrix: %ux%u panels of %ux%u pixels\n"), _cols, _rows, mxconfig.mx_width/2, mxconfig.mx_height*2);
chainType = CHAIN_BOTTOM_LEFT_UP; // TODO: is there any need to support other chaining types?
DEBUGBUS_PRINTF_P(PSTR("Using virtual matrix: %ux%u panels of %ux%u pixels\n"), _cols, _rows, mxconfig.mx_width, mxconfig.mx_height);
}
else {
_isVirtual = false;
}
if (_isVirtual) {
virtualDisp = new VirtualMatrixPanel((*display), _rows, _cols, mxconfig.mx_width/2, mxconfig.mx_height*2, chainType);
virtualDisp = new VirtualMatrixPanel((*display), _rows, _cols, mxconfig.mx_width, mxconfig.mx_height, chainType);
virtualDisp->setRotation(0);
if (bc.type == TYPE_HUB75MATRIX_QS) {
switch(panelHeight) {
@@ -1097,7 +1090,7 @@ void IRAM_ATTR BusHub75Matrix::setPixelColor(unsigned pix, uint32_t c) {
uint32_t BusHub75Matrix::getPixelColor(unsigned pix) const {
if (!_valid) return IS_BLACK; // note: no need to check pix >= _len as that is checked in containsPixel()
if (_ledBuffer)
return uint32_t(_ledBuffer[pix]) & 0x00FFFFFF; // FastLED 32bit is RGBA, we need RGBW
return uint32_t(_ledBuffer[pix]);
else
return getBitFromArray(_ledsDirty, pix) ? IS_DARKGREY: IS_BLACK; // just a hack - we only know if the pixel is black or not
}
@@ -1162,8 +1155,8 @@ std::vector<LEDType> BusHub75Matrix::getLEDTypes() {
size_t BusHub75Matrix::getPins(uint8_t* pinArray) const {
if (pinArray) {
pinArray[0] = _isVirtual ? mxconfig.mx_width /2 : mxconfig.mx_width;
pinArray[1] = _isVirtual ? mxconfig.mx_height *2 : mxconfig.mx_height;
pinArray[0] = mxconfig.mx_width;
pinArray[1] = mxconfig.mx_height;
pinArray[2] = mxconfig.chain_length;
pinArray[3] = _rows;
pinArray[4] = _cols;
+90 -25
View File
@@ -190,7 +190,7 @@
}
}
function pMP() { // populateMacroPresets
var presetOpts = '<option value="0">Default Action</option>' + sortedPresetOptions;
var presetOpts = '<option value="0">Default Action (0)</option>' + sortedPresetOptions;
var fields = ['A0','A1','MC','MN'];
for (var f of fields) {
var inp = gN(f);
@@ -219,13 +219,38 @@
rPS(sel, presetOpts, "data-preset");
}
}
function bAO() { // buildAnalogOptions: analog functions + per-segment opacity (segment 0 included; MD=0 => segment 0)
var o = '<optgroup label="Analog Functions"><option value="250">Global brightness (250)</option><option value="249">Effect speed (249)</option><option value="248">Effect intensity (248)</option><option value="247">Palette (247)</option><option value="200">Primary color hue (200)</option></optgroup><optgroup label="Analog Segment Opacity">';
for (var j=0; j<=32; j++) o += `<option value="${j}">Segment ${j} opacity</option>`;
o += '</optgroup>';
return o;
}
function isAnalogBtn(t) { return t==7 || t==8; } // BTN_TYPE_ANALOG / BTN_TYPE_ANALOG_INVERTED
function isSwitchBtn(t) { return t==4 || t==5 || t==9; } // BTN_TYPE_SWITCH / BTN_TYPE_PIR_SENSOR / BTN_TYPE_TOUCH_SWITCH
function btnTypeName(t) { // mirrors the button type dropdown on the LED settings page
switch (+t) {
case 2: return 'Pushbutton';
case 3: return 'Push inverted';
case 4: return 'Switch';
case 5: return 'PIR sensor';
case 6: return 'Touch';
case 7: return 'Analog';
case 8: return 'Analog inverted';
case 9: return 'Touch (switch)';
default: return 'Disabled';
}
}
function rBPO() { // refreshButtonPresetOptions
var presetOpts = '<option value="0">Default Action</option>' + sortedPresetOptions;
var presetOpts = '<option value="0">Default Action (0)</option>' + sortedPresetOptions;
var analogOpts = bAO();
var container = gId("macros");
if (!container) return;
// analog buttons only have an MD select (MP/ML are hidden 0 inputs); MD uses analog options, never presets
var sels = container.querySelectorAll('select[name^="MP"],select[name^="ML"],select[name^="MD"]');
for (var sel of sels) {
rPS(sel, presetOpts, "data-preset");
var bb = sel.closest ? sel.closest(".bb") : null;
var t = bb ? parseInt(bb.getAttribute("data-btype")||"0",10) : 0;
rPS(sel, isAnalogBtn(t) ? analogOpts : presetOpts, "data-preset");
}
}
function Wd()
@@ -246,33 +271,73 @@
if (d.Sf.LTR.value==="S") { d.Sf.LT.value = -1*parseFloat(d.Sf.LT.value); }
if (d.Sf.LNR.value==="W") { d.Sf.LN.value = -1*parseFloat(d.Sf.LN.value); }
}
function addRow(i,p,l,d) {
function addRow(i,p,l,d,t) {
if (t===undefined) t = 0;
var b = String.fromCharCode((i<10?48:55)+i);
var presetOpts = '<option value="0">Default Action</option>' + sortedPresetOptions;
var presetOpts = '<option value="0">Default Action (0)</option>' + sortedPresetOptions;
var typeName = btnTypeName(t);
var buttonBlock = document.createElement('div');
buttonBlock.className = 'bb';
buttonBlock.innerHTML = `
<div class="bh">Button (switch) ${i}</div>
<div class="bs">
<div class="ba">
<label>Short (on → off)</label>
<select name="MP${b}" class="s" required>${presetOpts}</select>
buttonBlock.setAttribute('data-btype', t); // read back by rBPO() to rebuild selects correctly
if (isAnalogBtn(t)) {
// analog buttons: MD holds the function/segment; short/long press are unused (firmware defaults missing MP/ML to 0)
buttonBlock.innerHTML = `
<div class="bh">Analog ${i} - ${typeName}</div>
<div class="bs">
<div class="ba">
<label>Analog function</label>
<select name="MD${b}" class="s" required>${bAO()}</select>
</div>
</div>
<div class="ba">
<label>Long (off → on)</label>
<select name="ML${b}" class="s" required>${presetOpts}</select>
<hr style="width:100%;margin:8px 0 0 0;">
`;
sPSV(buttonBlock.querySelector('select[name="MD'+b+'"]'), String(d), "data-preset");
} else if (isSwitchBtn(t)) {
// switches: MP fires on On->Off, ML on Off->On; double press (MD) is unused (firmware defaults missing MD to 0)
buttonBlock.innerHTML = `
<div class="bh">Switch ${i} - ${typeName}</div>
<div class="bs">
<div class="ba">
<label>On → Off</label>
<select name="MP${b}" class="s" required>${presetOpts}</select>
</div>
<div class="ba">
<label>Off → On</label>
<select name="ML${b}" class="s" required>${presetOpts}</select>
</div>
</div>
<div class="ba">
<label>Double press (n/a)</label>
<select name="MD${b}" class="s" required>${presetOpts}</select>
<hr style="width:100%;margin:8px 0 0 0;">
`;
var switchSels = buttonBlock.querySelectorAll("select");
var switchVals = [String(p), String(l)];
for (var si=0; si<switchSels.length; si++) {
sPSV(switchSels[si], switchVals[si], "data-preset");
}
} else {
// pushbuttons: short (MP), long (ML) and double (MD) press
buttonBlock.innerHTML = `
<div class="bh">Button ${i} - ${typeName}</div>
<div class="bs">
<div class="ba">
<label>Short press</label>
<select name="MP${b}" class="s" required>${presetOpts}</select>
</div>
<div class="ba">
<label>Long press</label>
<select name="ML${b}" class="s" required>${presetOpts}</select>
</div>
<div class="ba">
<label>Double press</label>
<select name="MD${b}" class="s" required>${presetOpts}</select>
</div>
</div>
</div>
<hr style="width:100%;margin:8px 0 0 0;">
`;
var buttonSels = buttonBlock.querySelectorAll("select");
var buttonVals = [String(p), String(l), String(d)];
for (var si=0; si<buttonSels.length; si++) {
sPSV(buttonSels[si], buttonVals[si], "data-preset");
<hr style="width:100%;margin:8px 0 0 0;">
`;
var buttonSels = buttonBlock.querySelectorAll("select");
var buttonVals = [String(p), String(l), String(d)];
for (var si=0; si<buttonSels.length; si++) {
sPSV(buttonSels[si], buttonVals[si], "data-preset");
}
}
gId("macros").appendChild(buttonBlock);
}
@@ -372,7 +437,7 @@
Alexa On/Off Preset: <input name="A0" class="m" type="number" min="0" max="250" required> <input name="A1" class="m" type="number" min="0" max="250" required><br>
</div>
<div class="sec">
<h3>Button (switch) Action Presets</h3>
<h3>Button Action Presets</h3>
<div id="macros"></div>
<a href="https://kno.wled.ge/features/macros/#analog-button" target="_blank">Analog Button setup</a>
</div>
+1 -1
View File
@@ -628,7 +628,7 @@ void getSettingsJS(byte subPage, Print& settingsScript)
printSetFormValue(settingsScript,PSTR("MN"),macroNl);
int ii = 0;
for (const auto &button : buttons) {
settingsScript.printf_P(PSTR("addRow(%d,%d,%d,%d);"), ii++, button.macroButton, button.macroLongPress, button.macroDoublePress);
settingsScript.printf_P(PSTR("addRow(%d,%d,%d,%d,%d);"), ii++, button.macroButton, button.macroLongPress, button.macroDoublePress, button.type);
}
settingsScript.printf_P(PSTR("maxTimers=%d;"), WLED_MAX_TIMERS);