mirror of
https://github.com/wled/WLED.git
synced 2025-07-25 03:36:45 +00:00
Merge branch '0_15' into harmonic-random-palette-generator
This commit is contained in:
commit
66d9e8c038
76
.github/workflows/wled-ci.yml
vendored
76
.github/workflows/wled-ci.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: PlatformIO CI
|
name: WLED CI
|
||||||
|
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
@ -8,17 +8,11 @@ jobs:
|
|||||||
name: Gather Environments
|
name: Gather Environments
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Cache pip
|
- uses: actions/setup-python@v5
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/pip
|
python-version: '3.12'
|
||||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
cache: 'pip'
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pip-
|
|
||||||
- uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: '3.9'
|
|
||||||
- name: Install PlatformIO
|
- name: Install PlatformIO
|
||||||
run: pip install -r requirements.txt
|
run: pip install -r requirements.txt
|
||||||
- name: Get default environments
|
- name: Get default environments
|
||||||
@ -38,59 +32,63 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
environment: ${{ fromJSON(needs.get_default_envs.outputs.environments) }}
|
environment: ${{ fromJSON(needs.get_default_envs.outputs.environments) }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- name: Cache pip
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ~/.cache/pip
|
|
||||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-pip-
|
|
||||||
- name: Cache PlatformIO
|
- name: Cache PlatformIO
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.platformio
|
path: |
|
||||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
~/.platformio/.cache
|
||||||
|
~/.buildcache
|
||||||
|
build_output
|
||||||
|
key: pio-${{ runner.os }}-${{ matrix.environment }}-${{ hashFiles('platformio.ini', 'pio-scripts/output_bins.py') }}-${{ hashFiles('wled00/**') }}
|
||||||
|
restore-keys: pio-${{ runner.os }}-${{ matrix.environment }}-${{ hashFiles('platformio.ini', 'pio-scripts/output_bins.py') }}-
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: '3.9'
|
python-version: '3.12'
|
||||||
|
cache: 'pip'
|
||||||
- name: Install PlatformIO
|
- name: Install PlatformIO
|
||||||
run: pip install -r requirements.txt
|
run: pip install -r requirements.txt
|
||||||
- name: Build firmware
|
- name: Build firmware
|
||||||
env:
|
|
||||||
WLED_RELEASE: True
|
|
||||||
run: pio run -e ${{ matrix.environment }}
|
run: pio run -e ${{ matrix.environment }}
|
||||||
- uses: actions/upload-artifact@v2
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-${{ matrix.environment }}
|
name: firmware-${{ matrix.environment }}
|
||||||
path: |
|
path: |
|
||||||
build_output/firmware/*.bin
|
build_output/release/*.bin
|
||||||
build_output/firmware/*.gz
|
build_output/release/*_ESP02.bin.gz
|
||||||
- uses: actions/upload-artifact@v2
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
with:
|
|
||||||
name: firmware-release
|
|
||||||
path: build_output/release/*.bin
|
|
||||||
release:
|
release:
|
||||||
name: Create Release
|
name: Create Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [get_default_envs, build]
|
needs: build
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/download-artifact@v2
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-release
|
merge-multiple: true
|
||||||
- name: Create draft release
|
- name: Create draft release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
draft: True
|
draft: True
|
||||||
files: |
|
files: |
|
||||||
*.bin
|
*.bin
|
||||||
env:
|
*.bin.gz
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
|
testCdata:
|
||||||
|
name: Test cdata.js
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Use Node.js
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: '20.x'
|
||||||
|
cache: 'npm'
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm test
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
## WLED changelog
|
## WLED changelog
|
||||||
|
|
||||||
#### Build 2309120 till build 2401270
|
#### Build 2309120 till build 2402010
|
||||||
- WLED version 0.15.0-a0
|
- WLED version 0.15.0-a0
|
||||||
|
- Multi-WiFi support. Add up to 3 (or more via cusom compile) WiFis to connect to
|
||||||
|
- Temporary AP. Use your WLED in public with temporary AP.
|
||||||
|
- Github CI build system enhancements (#3718 by @WoodyLetsCode)
|
||||||
|
- Accessibility: Node list ( #3715 by @WoodyLetsCode)
|
||||||
|
- Analog clock overlay enhancement (#3489 by @WoodyLetsCode)
|
||||||
|
- ESP32-POE-WROVER from Olimex ethernet support (#3625 by @m-wachter)
|
||||||
|
- APA106 support (#3580 by @itstefanjanos)
|
||||||
- BREAKING: Effect: updated Palette effect to support 2D (#3683 by @TripleWhy)
|
- BREAKING: Effect: updated Palette effect to support 2D (#3683 by @TripleWhy)
|
||||||
- "SuperSync" from WLED MM (by @MoonModules)
|
- "SuperSync" from WLED MM (by @MoonModules)
|
||||||
- Effect: DNA Spiral Effect Speed Fix (#3723 by @Derek4aty1)
|
- Effect: DNA Spiral Effect Speed Fix (#3723 by @Derek4aty1)
|
||||||
|
2072
package-lock.json
generated
2072
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -9,6 +9,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node tools/cdata.js",
|
"build": "node tools/cdata.js",
|
||||||
|
"test": "node --test",
|
||||||
"dev": "nodemon -e js,html,htm,css,png,jpg,gif,ico,js -w tools/ -w wled00/data/ -x node tools/cdata.js"
|
"dev": "nodemon -e js,html,htm,css,png,jpg,gif,ico,js -w tools/ -w wled00/data/ -x node tools/cdata.js"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -22,10 +23,10 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/Aircoookie/WLED#readme",
|
"homepage": "https://github.com/Aircoookie/WLED#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clean-css": "^4.2.3",
|
"clean-css": "^5.3.3",
|
||||||
"html-minifier-terser": "^5.1.1",
|
"html-minifier-terser": "^7.2.0",
|
||||||
"inliner": "^1.13.1",
|
"inliner": "^1.13.1",
|
||||||
"nodemon": "^2.0.20",
|
"nodemon": "^3.0.2",
|
||||||
"zlib": "^1.0.5"
|
"zlib": "^1.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,16 @@ def _create_dirs(dirs=["firmware", "map"]):
|
|||||||
if not os.path.isdir("{}{}".format(OUTPUT_DIR, d)):
|
if not os.path.isdir("{}{}".format(OUTPUT_DIR, d)):
|
||||||
os.mkdir("{}{}".format(OUTPUT_DIR, d))
|
os.mkdir("{}{}".format(OUTPUT_DIR, d))
|
||||||
|
|
||||||
|
def create_release(source):
|
||||||
|
release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME")
|
||||||
|
if release_name:
|
||||||
|
_create_dirs(["release"])
|
||||||
|
version = _get_cpp_define_value(env, "WLED_VERSION")
|
||||||
|
# get file extension of source file (.bin or .bin.gz)
|
||||||
|
ext = source.split(".", 1)[1]
|
||||||
|
release_file = "{}release{}WLED_{}_{}.{}".format(OUTPUT_DIR, os.path.sep, version, release_name, ext)
|
||||||
|
shutil.copy(source, release_file)
|
||||||
|
|
||||||
def bin_rename_copy(source, target, env):
|
def bin_rename_copy(source, target, env):
|
||||||
_create_dirs()
|
_create_dirs()
|
||||||
variant = env["PIOENV"]
|
variant = env["PIOENV"]
|
||||||
@ -30,14 +40,6 @@ def bin_rename_copy(source, target, env):
|
|||||||
map_file = "{}map{}{}.map".format(OUTPUT_DIR, os.path.sep, variant)
|
map_file = "{}map{}{}.map".format(OUTPUT_DIR, os.path.sep, variant)
|
||||||
bin_file = "{}firmware{}{}.bin".format(OUTPUT_DIR, os.path.sep, variant)
|
bin_file = "{}firmware{}{}.bin".format(OUTPUT_DIR, os.path.sep, variant)
|
||||||
|
|
||||||
release_name = _get_cpp_define_value(env, "WLED_RELEASE_NAME")
|
|
||||||
|
|
||||||
if release_name:
|
|
||||||
_create_dirs(["release"])
|
|
||||||
version = _get_cpp_define_value(env, "WLED_VERSION")
|
|
||||||
release_file = "{}release{}WLED_{}_{}.bin".format(OUTPUT_DIR, os.path.sep, version, release_name)
|
|
||||||
shutil.copy(str(target[0]), release_file)
|
|
||||||
|
|
||||||
# check if new target files exist and remove if necessary
|
# check if new target files exist and remove if necessary
|
||||||
for f in [map_file, bin_file]:
|
for f in [map_file, bin_file]:
|
||||||
if os.path.isfile(f):
|
if os.path.isfile(f):
|
||||||
@ -46,6 +48,8 @@ def bin_rename_copy(source, target, env):
|
|||||||
# copy firmware.bin to firmware/<variant>.bin
|
# copy firmware.bin to firmware/<variant>.bin
|
||||||
shutil.copy(str(target[0]), bin_file)
|
shutil.copy(str(target[0]), bin_file)
|
||||||
|
|
||||||
|
create_release(bin_file)
|
||||||
|
|
||||||
# copy firmware.map to map/<variant>.map
|
# copy firmware.map to map/<variant>.map
|
||||||
if os.path.isfile("firmware.map"):
|
if os.path.isfile("firmware.map"):
|
||||||
shutil.move("firmware.map", map_file)
|
shutil.move("firmware.map", map_file)
|
||||||
@ -66,4 +70,6 @@ def bin_gzip(source, target, env):
|
|||||||
with gzip.open(gzip_file, "wb", compresslevel = 9) as f:
|
with gzip.open(gzip_file, "wb", compresslevel = 9) as f:
|
||||||
shutil.copyfileobj(fp, f)
|
shutil.copyfileobj(fp, f)
|
||||||
|
|
||||||
|
create_release(gzip_file)
|
||||||
|
|
||||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [bin_rename_copy, bin_gzip])
|
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", [bin_rename_copy, bin_gzip])
|
||||||
|
415
platformio.ini
415
platformio.ini
@ -9,39 +9,8 @@
|
|||||||
# (use `platformio_override.ini` when building for your own board; see `platformio_override.ini.sample` for an example)
|
# (use `platformio_override.ini` when building for your own board; see `platformio_override.ini.sample` for an example)
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
# CI binaries
|
# CI/release binaries
|
||||||
; default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth # ESP32 variant builds are temporarily excluded from CI due to toolchain issues on the GitHub Actions Linux environment
|
default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, esp32dev_audioreactive, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB, esp32s3dev_8MB_PSRAM_opi, esp32_wrover
|
||||||
default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, esp32dev_audioreactive, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB, esp32s3dev_8MB_PSRAM_opi
|
|
||||||
|
|
||||||
# Release binaries
|
|
||||||
; default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB
|
|
||||||
|
|
||||||
# Build everything
|
|
||||||
; default_envs = esp32dev, esp8285_4CH_MagicHome, codm-controller-0_6-rev2, codm-controller-0_6, esp32s2_saola, d1_mini_5CH_Shojo_PCB, d1_mini, sp501e, nodemcuv2, esp32_eth, anavi_miracle_controller, esp07, esp01_1m_full, m5atom, h803wf, d1_mini_ota, heltec_wifi_kit_8, esp8285_H801, d1_mini_debug, wemos_shield_esp32, elekstube_ips
|
|
||||||
|
|
||||||
# Single binaries (uncomment your board)
|
|
||||||
; default_envs = elekstube_ips
|
|
||||||
; default_envs = nodemcuv2
|
|
||||||
; default_envs = esp8266_2m
|
|
||||||
; default_envs = esp01_1m_full
|
|
||||||
; default_envs = esp07
|
|
||||||
; default_envs = d1_mini
|
|
||||||
; default_envs = heltec_wifi_kit_8
|
|
||||||
; default_envs = h803wf
|
|
||||||
; default_envs = d1_mini_debug
|
|
||||||
; default_envs = d1_mini_ota
|
|
||||||
; default_envs = esp32dev
|
|
||||||
; default_envs = esp8285_4CH_MagicHome
|
|
||||||
; default_envs = esp8285_H801
|
|
||||||
; default_envs = d1_mini_5CH_Shojo_PCB
|
|
||||||
; default_envs = wemos_shield_esp32
|
|
||||||
; default_envs = m5atom
|
|
||||||
; default_envs = esp32_eth
|
|
||||||
; default_envs = esp32dev_qio80
|
|
||||||
; default_envs = esp32_eth_ota1mapp
|
|
||||||
; default_envs = esp32s2_saola
|
|
||||||
; default_envs = esp32c3dev
|
|
||||||
; default_envs = lolin_s2_mini
|
|
||||||
|
|
||||||
src_dir = ./wled00
|
src_dir = ./wled00
|
||||||
data_dir = ./wled00/data
|
data_dir = ./wled00/data
|
||||||
@ -60,9 +29,9 @@ extra_configs =
|
|||||||
arduino_core_2_6_3 = espressif8266@2.3.3
|
arduino_core_2_6_3 = espressif8266@2.3.3
|
||||||
arduino_core_2_7_4 = espressif8266@2.6.2
|
arduino_core_2_7_4 = espressif8266@2.6.2
|
||||||
arduino_core_3_0_0 = espressif8266@3.0.0
|
arduino_core_3_0_0 = espressif8266@3.0.0
|
||||||
arduino_core_3_2_0 = espressif8266@3.2.0
|
arduino_core_3_0_2 = espressif8266@3.2.0
|
||||||
arduino_core_4_1_0 = espressif8266@4.1.0
|
arduino_core_3_1_0 = espressif8266@4.1.0
|
||||||
arduino_core_3_1_2 = espressif8266@4.2.0
|
arduino_core_3_1_2 = espressif8266@4.2.1
|
||||||
|
|
||||||
# Development platforms
|
# Development platforms
|
||||||
arduino_core_develop = https://github.com/platformio/platform-espressif8266#develop
|
arduino_core_develop = https://github.com/platformio/platform-espressif8266#develop
|
||||||
@ -132,12 +101,7 @@ build_flags =
|
|||||||
-D DECODE_SONY=true
|
-D DECODE_SONY=true
|
||||||
-D DECODE_SAMSUNG=true
|
-D DECODE_SAMSUNG=true
|
||||||
-D DECODE_LG=true
|
-D DECODE_LG=true
|
||||||
;-Dregister= # remove warnings in C++17 due to use of deprecated register keyword by the FastLED library ;; warning: this breaks framework code on ESP32-C3 and ESP32-S2
|
|
||||||
-DWLED_USE_MY_CONFIG
|
-DWLED_USE_MY_CONFIG
|
||||||
; -D USERMOD_SENSORSTOMQTT
|
|
||||||
#For ADS1115 sensor uncomment following
|
|
||||||
; -D USERMOD_ADS1115
|
|
||||||
; -D USERMOD_ANIMARTRIX
|
|
||||||
|
|
||||||
build_unflags =
|
build_unflags =
|
||||||
|
|
||||||
@ -165,10 +129,8 @@ extra_scripts =
|
|||||||
framework = arduino
|
framework = arduino
|
||||||
board_build.flash_mode = dout
|
board_build.flash_mode = dout
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
# slow upload speed (comment this out with a ';' when building for development use)
|
# slow upload speed but most compatible (use platformio_override.ini to use faster speed)
|
||||||
upload_speed = 115200
|
upload_speed = 115200
|
||||||
# fast upload speed (remove ';' when building for development use)
|
|
||||||
; upload_speed = 921600
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# LIBRARIES: required dependencies
|
# LIBRARIES: required dependencies
|
||||||
@ -183,15 +145,17 @@ lib_deps =
|
|||||||
IRremoteESP8266 @ 2.8.2
|
IRremoteESP8266 @ 2.8.2
|
||||||
makuna/NeoPixelBus @ 2.7.5
|
makuna/NeoPixelBus @ 2.7.5
|
||||||
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.7
|
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.7
|
||||||
|
# for I2C interface
|
||||||
|
;Wire
|
||||||
# ESP-NOW library (includes mandatory QuickDebug library)
|
# ESP-NOW library (includes mandatory QuickDebug library)
|
||||||
;gmag11/QuickESPNow @ 0.6.2
|
;gmag11/QuickESPNow @ 0.6.2
|
||||||
https://github.com/blazoncek/QuickESPNow.git#optional-debug
|
https://github.com/blazoncek/QuickESPNow.git#optional-debug
|
||||||
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
|
#For use of the TTGO T-Display ESP32 Module with integrated TFT display uncomment the following line
|
||||||
#TFT_eSPI
|
#TFT_eSPI
|
||||||
#For compatible OLED display uncomment following
|
#For compatible OLED display uncomment following
|
||||||
#U8g2 #@ ~2.33.15
|
#olikraus/U8g2 #@ ~2.33.15
|
||||||
#For Dallas sensor uncomment following
|
#For Dallas sensor uncomment following
|
||||||
#OneWire @ ~2.3.7
|
#paulstoffregen/OneWire @ ~2.3.8
|
||||||
#For BME280 sensor uncomment following
|
#For BME280 sensor uncomment following
|
||||||
#BME280 @ ~3.0.0
|
#BME280 @ ~3.0.0
|
||||||
;adafruit/Adafruit BMP280 Library @ 2.1.0
|
;adafruit/Adafruit BMP280 Library @ 2.1.0
|
||||||
@ -205,6 +169,10 @@ lib_deps =
|
|||||||
# For -D USERMOD_ANIMARTRIX
|
# For -D USERMOD_ANIMARTRIX
|
||||||
# CC BY-NC 3.0 licensed effects by Stefan Petrick, include this usermod only if you accept the terms!
|
# CC BY-NC 3.0 licensed effects by Stefan Petrick, include this usermod only if you accept the terms!
|
||||||
;https://github.com/netmindz/animartrix.git#18bf17389e57c69f11bc8d04ebe1d215422c7fb7
|
;https://github.com/netmindz/animartrix.git#18bf17389e57c69f11bc8d04ebe1d215422c7fb7
|
||||||
|
# SHT85
|
||||||
|
;robtillaart/SHT85@~0.3.3
|
||||||
|
# Audioreactive usermod
|
||||||
|
;https://github.com/kosme/arduinoFFT#develop @ ^1.9.2
|
||||||
|
|
||||||
extra_scripts = ${scripts_defaults.extra_scripts}
|
extra_scripts = ${scripts_defaults.extra_scripts}
|
||||||
|
|
||||||
@ -280,6 +248,7 @@ lib_deps =
|
|||||||
;; generic definitions for all ESP32-S2 boards
|
;; generic definitions for all ESP32-S2 boards
|
||||||
platform = espressif32@5.3.0
|
platform = espressif32@5.3.0
|
||||||
platform_packages =
|
platform_packages =
|
||||||
|
default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
|
||||||
build_flags = -g
|
build_flags = -g
|
||||||
-DARDUINO_ARCH_ESP32
|
-DARDUINO_ARCH_ESP32
|
||||||
-DARDUINO_ARCH_ESP32S2
|
-DARDUINO_ARCH_ESP32S2
|
||||||
@ -290,7 +259,6 @@ build_flags = -g
|
|||||||
-DARDUINO_USB_MODE=0 ;; this flag is mandatory for ESP32-S2 !
|
-DARDUINO_USB_MODE=0 ;; this flag is mandatory for ESP32-S2 !
|
||||||
;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry:
|
;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry:
|
||||||
;; ARDUINO_USB_CDC_ON_BOOT
|
;; ARDUINO_USB_CDC_ON_BOOT
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0
|
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
@ -308,7 +276,6 @@ build_flags = -g
|
|||||||
-DARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C3
|
-DARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C3
|
||||||
;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry:
|
;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry:
|
||||||
;; ARDUINO_USB_CDC_ON_BOOT
|
;; ARDUINO_USB_CDC_ON_BOOT
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0
|
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
@ -366,44 +333,6 @@ build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_D
|
|||||||
; -D WLED_USE_UNREAL_MATH ;; may cause wrong sunset/sunrise times, but saves 7064 bytes FLASH and 975 bytes RAM
|
; -D WLED_USE_UNREAL_MATH ;; may cause wrong sunset/sunrise times, but saves 7064 bytes FLASH and 975 bytes RAM
|
||||||
lib_deps = ${esp8266.lib_deps}
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
[env:esp07]
|
|
||||||
board = esp07
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_4m1m}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266}
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
[env:d1_mini]
|
|
||||||
board = d1_mini
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
upload_speed = 921600
|
|
||||||
board_build.ldscript = ${common.ldscript_4m1m}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266}
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
monitor_filters = esp8266_exception_decoder
|
|
||||||
|
|
||||||
[env:heltec_wifi_kit_8]
|
|
||||||
board = d1_mini
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_4m1m}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266}
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
[env:h803wf]
|
|
||||||
board = d1_mini
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_4m1m}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266} -D LEDPIN=1 -D WLED_DISABLE_INFRARED
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
[env:esp32dev]
|
[env:esp32dev]
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
platform = ${esp32.platform}
|
platform = ${esp32.platform}
|
||||||
@ -428,33 +357,6 @@ board_build.partitions = ${esp32.default_partitions}
|
|||||||
; board_build.f_flash = 80000000L
|
; board_build.f_flash = 80000000L
|
||||||
; board_build.flash_mode = dio
|
; board_build.flash_mode = dio
|
||||||
|
|
||||||
[env:esp32dev_qio80]
|
|
||||||
board = esp32dev
|
|
||||||
platform = ${esp32.platform}
|
|
||||||
platform_packages = ${esp32.platform_packages}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_qio80 #-D WLED_DISABLE_BROWNOUT_DET
|
|
||||||
lib_deps = ${esp32.lib_deps}
|
|
||||||
monitor_filters = esp32_exception_decoder
|
|
||||||
board_build.partitions = ${esp32.default_partitions}
|
|
||||||
board_build.f_flash = 80000000L
|
|
||||||
board_build.flash_mode = qio
|
|
||||||
|
|
||||||
[env:esp32dev_V4_dio80]
|
|
||||||
;; experimental ESP32 env using ESP-IDF V4.4.x
|
|
||||||
;; Warning: this build environment is not stable!!
|
|
||||||
;; please erase your device before installing.
|
|
||||||
board = esp32dev
|
|
||||||
platform = ${esp32_idf_V4.platform}
|
|
||||||
platform_packages = ${esp32_idf_V4.platform_packages}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=ESP32_V4_qio80 #-D WLED_DISABLE_BROWNOUT_DET
|
|
||||||
lib_deps = ${esp32_idf_V4.lib_deps}
|
|
||||||
monitor_filters = esp32_exception_decoder
|
|
||||||
board_build.partitions = ${esp32_idf_V4.default_partitions}
|
|
||||||
board_build.f_flash = 80000000L
|
|
||||||
board_build.flash_mode = dio
|
|
||||||
|
|
||||||
[env:esp32_eth]
|
[env:esp32_eth]
|
||||||
board = esp32-poe
|
board = esp32-poe
|
||||||
platform = ${esp32.platform}
|
platform = ${esp32.platform}
|
||||||
@ -466,19 +368,18 @@ build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet -D
|
|||||||
lib_deps = ${esp32.lib_deps}
|
lib_deps = ${esp32.lib_deps}
|
||||||
board_build.partitions = ${esp32.default_partitions}
|
board_build.partitions = ${esp32.default_partitions}
|
||||||
|
|
||||||
[env:esp32s2_saola]
|
[env:esp32_wrover]
|
||||||
board = esp32-s2-saola-1
|
platform = ${esp32.platform}
|
||||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.2/platform-tasmota-espressif32-2.0.2.zip
|
board = ttgo-t7-v14-mini32
|
||||||
platform_packages =
|
board_build.f_flash = 80000000L
|
||||||
framework = arduino
|
|
||||||
board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
|
|
||||||
board_build.flash_mode = qio
|
board_build.flash_mode = qio
|
||||||
upload_speed = 460800
|
board_build.partitions = ${esp32.default_partitions}
|
||||||
build_unflags = ${common.build_unflags}
|
build_unflags = ${common.build_unflags}
|
||||||
build_flags = ${common.build_flags} ${esp32s2.build_flags} #-D WLED_RELEASE_NAME=S2_saola
|
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_WROVER
|
||||||
;-DLOLIN_WIFI_FIX ;; try this in case Wifi does not work
|
-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue
|
||||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
-D WLED_USE_PSRAM
|
||||||
lib_deps = ${esp32s2.lib_deps}
|
-D LEDPIN=25
|
||||||
|
lib_deps = ${esp32.lib_deps}
|
||||||
|
|
||||||
[env:esp32c3dev]
|
[env:esp32c3dev]
|
||||||
extends = esp32c3
|
extends = esp32c3
|
||||||
@ -523,7 +424,7 @@ platform = ${esp32s3.platform}
|
|||||||
platform_packages = ${esp32s3.platform_packages}
|
platform_packages = ${esp32s3.platform_packages}
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
build_unflags = ${common.build_unflags}
|
build_unflags = ${common.build_unflags}
|
||||||
build_flags = ${common.build_flags} ${esp32s3.build_flags}
|
build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME=ESP32-S3_8MB_PSRAM_opi
|
||||||
-D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0
|
-D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0
|
||||||
;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
|
;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
|
||||||
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
|
-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
|
||||||
@ -535,95 +436,24 @@ board_build.f_flash = 80000000L
|
|||||||
board_build.flash_mode = qio
|
board_build.flash_mode = qio
|
||||||
monitor_filters = esp32_exception_decoder
|
monitor_filters = esp32_exception_decoder
|
||||||
|
|
||||||
[env:esp32s3dev_8MB_PSRAM_qspi]
|
|
||||||
;; ESP32-TinyS3 development board, with 8MB FLASH and PSRAM (memory_type: qio_qspi)
|
|
||||||
extends = env:esp32s3dev_8MB_PSRAM_opi
|
|
||||||
;board = um_tinys3 ; -> needs workaround from https://github.com/Aircoookie/WLED/pull/2905#issuecomment-1328049860
|
|
||||||
board = esp32-s3-devkitc-1 ;; generic dev board; the next line adds PSRAM support
|
|
||||||
board_build.arduino.memory_type = qio_qspi ;; use with PSRAM: 2MB or 4MB
|
|
||||||
|
|
||||||
[env:esp8285_4CH_MagicHome]
|
|
||||||
board = esp8285
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_1m128k}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
[env:esp8285_H801]
|
|
||||||
board = esp8285
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_1m128k}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
[env:d1_mini_5CH_Shojo_PCB]
|
|
||||||
board = d1_mini
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_4m1m}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_USE_SHOJO_PCB
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# DEVELOPMENT BOARDS
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[env:d1_mini_debug]
|
|
||||||
board = d1_mini
|
|
||||||
build_type = debug
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_4m1m}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266} ${common.debug_flags}
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
[env:d1_mini_ota]
|
|
||||||
board = d1_mini
|
|
||||||
upload_protocol = espota
|
|
||||||
# exchange for your WLED IP
|
|
||||||
upload_port = "10.10.1.27"
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_4m1m}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266}
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
[env:anavi_miracle_controller]
|
|
||||||
board = d1_mini
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_4m1m}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266} -D LEDPIN=12 -D IRPIN=-1 -D RLYPIN=2
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
[env:lolin_s2_mini]
|
[env:lolin_s2_mini]
|
||||||
platform = ${esp32s2.platform}
|
platform = ${esp32s2.platform}
|
||||||
platform_packages = ${esp32s2.platform_packages}
|
platform_packages = ${esp32s2.platform_packages}
|
||||||
board = lolin_s2_mini
|
board = lolin_s2_mini
|
||||||
board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
|
board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
|
||||||
build_unflags = ${common.build_unflags} #-DARDUINO_USB_CDC_ON_BOOT=1
|
;board_build.flash_mode = qio
|
||||||
|
;board_build.f_flash = 80000000L
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=ESP32-S2
|
build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=ESP32-S2
|
||||||
-DBOARD_HAS_PSRAM
|
-DBOARD_HAS_PSRAM
|
||||||
-DARDUINO_USB_CDC_ON_BOOT=1 # try disabling and enabling unflag above in case of board-specific issues, will disable Serial
|
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||||
-DARDUINO_USB_MSC_ON_BOOT=0
|
-DARDUINO_USB_MSC_ON_BOOT=0
|
||||||
-DARDUINO_USB_DFU_ON_BOOT=0
|
-DARDUINO_USB_DFU_ON_BOOT=0
|
||||||
-DLOLIN_WIFI_FIX ; seems to work much better with this
|
-DLOLIN_WIFI_FIX ; seems to work much better with this
|
||||||
-D WLED_USE_PSRAM
|
-D WLED_USE_PSRAM
|
||||||
; -D WLED_USE_UNREAL_MATH ;; may cause wrong sunset/sunrise times, but saves 6792 bytes FLASH
|
|
||||||
-D WLED_WATCHDOG_TIMEOUT=0
|
-D WLED_WATCHDOG_TIMEOUT=0
|
||||||
-D CONFIG_ASYNC_TCP_USE_WDT=0
|
-D CONFIG_ASYNC_TCP_USE_WDT=0
|
||||||
-D LEDPIN=16
|
-D LEDPIN=16
|
||||||
-D BTNPIN=18
|
|
||||||
-D RLYPIN=9
|
|
||||||
-D IRPIN=7
|
|
||||||
-D HW_PIN_SCL=35
|
-D HW_PIN_SCL=35
|
||||||
-D HW_PIN_SDA=33
|
-D HW_PIN_SDA=33
|
||||||
-D HW_PIN_CLOCKSPI=7
|
-D HW_PIN_CLOCKSPI=7
|
||||||
@ -631,188 +461,3 @@ build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME=
|
|||||||
-D HW_PIN_MISOSPI=9
|
-D HW_PIN_MISOSPI=9
|
||||||
; -D STATUSLED=15
|
; -D STATUSLED=15
|
||||||
lib_deps = ${esp32s2.lib_deps}
|
lib_deps = ${esp32s2.lib_deps}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# custom board configurations
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[env:esp32c3dev_2MB]
|
|
||||||
;; for ESP32-C3 boards with 2MB flash (instead of 4MB).
|
|
||||||
;; this board need a specific partition file. OTA not possible.
|
|
||||||
extends = esp32c3
|
|
||||||
platform = ${esp32c3.platform}
|
|
||||||
platform_packages = ${esp32c3.platform_packages}
|
|
||||||
board = esp32-c3-devkitm-1
|
|
||||||
build_flags = ${common.build_flags} ${esp32c3.build_flags} #-D WLED_RELEASE_NAME=ESP32-C3
|
|
||||||
-D WLED_WATCHDOG_TIMEOUT=0
|
|
||||||
-D WLED_DISABLE_OTA
|
|
||||||
; -DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB
|
|
||||||
-DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
upload_speed = 115200
|
|
||||||
lib_deps = ${esp32c3.lib_deps}
|
|
||||||
board_build.partitions = tools/WLED_ESP32_2MB_noOTA.csv
|
|
||||||
board_build.flash_mode = dio
|
|
||||||
|
|
||||||
[env:wemos_shield_esp32]
|
|
||||||
board = esp32dev
|
|
||||||
platform = ${esp32.platform}
|
|
||||||
platform_packages = ${esp32.platform_packages}
|
|
||||||
upload_speed = 460800
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp32}
|
|
||||||
-D LEDPIN=16
|
|
||||||
-D RLYPIN=19
|
|
||||||
-D BTNPIN=17
|
|
||||||
-D IRPIN=18
|
|
||||||
-D UWLED_USE_MY_CONFIG
|
|
||||||
-D USERMOD_DALLASTEMPERATURE
|
|
||||||
-D USERMOD_FOUR_LINE_DISPLAY
|
|
||||||
-D TEMPERATURE_PIN=23
|
|
||||||
-D USE_ALT_DISPlAY ; new versions of USERMOD_FOUR_LINE_DISPLAY and USERMOD_ROTARY_ENCODER_UI
|
|
||||||
-D USERMOD_AUDIOREACTIVE
|
|
||||||
lib_deps = ${esp32.lib_deps}
|
|
||||||
OneWire@~2.3.5
|
|
||||||
olikraus/U8g2 @ ^2.28.8
|
|
||||||
https://github.com/blazoncek/arduinoFFT.git
|
|
||||||
board_build.partitions = ${esp32.default_partitions}
|
|
||||||
|
|
||||||
[env:m5atom]
|
|
||||||
board = esp32dev
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp32} -D LEDPIN=27 -D BTNPIN=39
|
|
||||||
lib_deps = ${esp32.lib_deps}
|
|
||||||
platform = ${esp32.platform}
|
|
||||||
platform_packages = ${esp32.platform_packages}
|
|
||||||
board_build.partitions = ${esp32.default_partitions}
|
|
||||||
|
|
||||||
[env:sp501e]
|
|
||||||
board = esp_wroom_02
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
board_build.ldscript = ${common.ldscript_2m512k}
|
|
||||||
build_flags = ${common.build_flags_esp8266} -D LEDPIN=3 -D BTNPIN=1
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
[env:sp511e]
|
|
||||||
board = esp_wroom_02
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
board_build.ldscript = ${common.ldscript_2m512k}
|
|
||||||
build_flags = ${common.build_flags_esp8266} -D LEDPIN=3 -D BTNPIN=2 -D IRPIN=5 -D WLED_MAX_BUTTONS=3
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
[env:Athom_RGBCW] ;7w and 5w(GU10) bulbs
|
|
||||||
board = esp8285
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_2m512k}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=-1 -D RLYPIN=-1 -D DATA_PINS=4,12,14,13,5
|
|
||||||
-D DEFAULT_LED_TYPE=TYPE_ANALOG_5CH -D WLED_DISABLE_INFRARED -D WLED_MAX_CCT_BLEND=0
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
|
|
||||||
[env:Athom_15w_RGBCW] ;15w bulb
|
|
||||||
board = esp8285
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_2m512k}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=-1 -D RLYPIN=-1 -D DATA_PINS=4,12,14,5,13
|
|
||||||
-D DEFAULT_LED_TYPE=TYPE_ANALOG_5CH -D WLED_DISABLE_INFRARED -D WLED_MAX_CCT_BLEND=0 -D WLED_USE_IC_CCT
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
|
|
||||||
[env:Athom_3Pin_Controller] ;small controller with only data
|
|
||||||
board = esp8285
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_2m512k}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=0 -D RLYPIN=-1 -D LEDPIN=1 -D WLED_DISABLE_INFRARED
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
|
|
||||||
[env:Athom_4Pin_Controller] ; With clock and data interface
|
|
||||||
board = esp8285
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_2m512k}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=0 -D RLYPIN=12 -D LEDPIN=1 -D WLED_DISABLE_INFRARED
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
|
|
||||||
[env:Athom_5Pin_Controller] ;Analog light strip controller
|
|
||||||
board = esp8285
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_2m512k}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=0 -D RLYPIN=-1 DATA_PINS=4,12,14,13 -D WLED_DISABLE_INFRARED
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
|
|
||||||
[env:MY9291]
|
|
||||||
board = esp01_1m
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_1m128k}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_DISABLE_OTA -D USERMOD_MY9291
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# codm pixel controller board configurations
|
|
||||||
# codm-controller-0_6 can also be used for the TYWE3S controller
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
[env:codm-controller-0_6]
|
|
||||||
board = esp_wroom_02
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_2m512k}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266}
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
[env:codm-controller-0_6-rev2]
|
|
||||||
board = esp_wroom_02
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_4m1m}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266}
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# EleksTube-IPS
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
[env:elekstube_ips]
|
|
||||||
board = esp32dev
|
|
||||||
platform = ${esp32.platform}
|
|
||||||
platform_packages = ${esp32.platform_packages}
|
|
||||||
upload_speed = 921600
|
|
||||||
build_flags = ${common.build_flags_esp32} -D WLED_DISABLE_BROWNOUT_DET -D WLED_DISABLE_INFRARED
|
|
||||||
-D USERMOD_RTC
|
|
||||||
-D USERMOD_ELEKSTUBE_IPS
|
|
||||||
-D LEDPIN=12
|
|
||||||
-D RLYPIN=27
|
|
||||||
-D BTNPIN=34
|
|
||||||
-D DEFAULT_LED_COUNT=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
|
|
||||||
lib_deps =
|
|
||||||
${esp32.lib_deps}
|
|
||||||
TFT_eSPI @ ^2.3.70
|
|
||||||
board_build.partitions = ${esp32.default_partitions}
|
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
# Example PlatformIO Project Configuration Override
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Copy to platformio_override.ini to activate overrides
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
# Please visit documentation: https://docs.platformio.org/page/projectconf.html
|
|
||||||
|
|
||||||
[platformio]
|
|
||||||
default_envs = WLED_tasmota_1M
|
|
||||||
|
|
||||||
[env:WLED_tasmota_1M]
|
|
||||||
board = esp01_1m
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
board_build.ldscript = ${common.ldscript_1m128k}
|
|
||||||
lib_deps = ${esp8266.lib_deps}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags = ${common.build_flags_esp8266}
|
|
||||||
; *********************************************************************
|
|
||||||
; *** Use custom settings from file my_config.h
|
|
||||||
-DWLED_USE_MY_CONFIG
|
|
||||||
; *********************************************************************
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; *** To use the below defines/overrides, copy and paste each onto it's own line just below build_flags in the section above.
|
|
||||||
;
|
|
||||||
; disable specific features
|
|
||||||
; -D WLED_DISABLE_OTA
|
|
||||||
; -D WLED_DISABLE_ALEXA
|
|
||||||
; -D WLED_DISABLE_HUESYNC
|
|
||||||
; -D WLED_DISABLE_INFRARED
|
|
||||||
; -D WLED_DISABLE_WEBSOCKETS
|
|
||||||
; PIN defines - uncomment and change, if needed:
|
|
||||||
; -D LEDPIN=2
|
|
||||||
; -D BTNPIN=0
|
|
||||||
; -D TOUCHPIN=T0
|
|
||||||
; -D IRPIN=4
|
|
||||||
; -D RLYPIN=12
|
|
||||||
; -D RLYMDE=1
|
|
||||||
; digital LED strip types - uncomment only one ! - this will disable WS281x / SK681x support
|
|
||||||
; -D USE_APA102
|
|
||||||
; -D USE_WS2801
|
|
||||||
; -D USE_LPD8806
|
|
||||||
; PIN defines for 2 wire LEDs
|
|
||||||
-D CLKPIN=0
|
|
||||||
-D DATAPIN=2
|
|
||||||
; to drive analog LED strips (aka 5050) hardware configuration is no longer necessary
|
|
||||||
; configure the settings in the UI as follows (hard):
|
|
||||||
; for the Magic Home LED Controller use PWM pins 5,12,13,15
|
|
||||||
; for the H801 controller use PINs 15,13,12,14 (W2 = 04)
|
|
||||||
; for the BW-LT11 controller use PINs 12,4,14,5
|
|
||||||
;
|
|
||||||
; set the name of the module - make sure there is a quote-backslash-quote before the name and a backslash-quote-quote after the name
|
|
||||||
; -D SERVERNAME="\"WLED\""
|
|
||||||
;
|
|
||||||
; set the number of LEDs
|
|
||||||
; -D DEFAULT_LED_COUNT=30
|
|
||||||
;
|
|
||||||
; set milliampere limit when using ESP pin to power leds
|
|
||||||
; -D ABL_MILLIAMPS_DEFAULT=850
|
|
||||||
;
|
|
||||||
; enable IR by setting remote type
|
|
||||||
; -D IRTYPE=0 ;0 Remote disabled | 1 24-key RGB | 2 24-key with CT | 3 40-key blue | 4 40-key RGB | 5 21-key RGB | 6 6-key black | 7 9-key red | 8 JSON remote
|
|
||||||
;
|
|
||||||
; set default color order of your led strip
|
|
||||||
; -D DEFAULT_LED_COLOR_ORDER=COL_ORDER_GRB
|
|
495
platformio_override.sample.ini
Normal file
495
platformio_override.sample.ini
Normal file
@ -0,0 +1,495 @@
|
|||||||
|
# Example PlatformIO Project Configuration Override
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Copy to platformio_override.ini to activate overrides
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Please visit documentation: https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
|
[platformio]
|
||||||
|
default_envs = WLED_tasmota_1M # define as many as you need
|
||||||
|
|
||||||
|
#----------
|
||||||
|
# SAMPLE
|
||||||
|
#----------
|
||||||
|
[env:WLED_tasmota_1M]
|
||||||
|
extends = env:esp01_1m_full # when you want to extend the existing environment (define only updated options)
|
||||||
|
; board = esp01_1m # uncomment when ou need different board
|
||||||
|
; platform = ${common.platform_wled_default} # uncomment and change when you want particular platform
|
||||||
|
; platform_packages = ${common.platform_packages}
|
||||||
|
; board_build.ldscript = ${common.ldscript_1m128k}
|
||||||
|
; upload_speed = 921600 # fast upload speed (remove ';' if your board supports fast upload speed)
|
||||||
|
# Sample libraries used for various usermods. Uncomment when using particular usermod.
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
; olikraus/U8g2 # @~2.33.15
|
||||||
|
; paulstoffregen/OneWire@~2.3.8
|
||||||
|
; adafruit/Adafruit Unified Sensor@^1.1.4
|
||||||
|
; adafruit/DHT sensor library@^1.4.1
|
||||||
|
; adafruit/Adafruit BME280 Library@^2.2.2
|
||||||
|
; Wire
|
||||||
|
; robtillaart/SHT85@~0.3.3
|
||||||
|
; gmag11/QuickESPNow ;@ 0.6.2
|
||||||
|
; https://github.com/blazoncek/QuickESPNow.git#optional-debug ;; exludes debug library
|
||||||
|
; https://github.com/kosme/arduinoFFT#develop @ 1.9.2+sha.419d7b0 ;; used for USERMOD_AUDIOREACTIVE - using "known working" hash
|
||||||
|
; build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266}
|
||||||
|
;
|
||||||
|
; *** To use the below defines/overrides, copy and paste each onto it's own line just below build_flags in the section above.
|
||||||
|
;
|
||||||
|
; disable specific features
|
||||||
|
; -D WLED_DISABLE_OTA
|
||||||
|
; -D WLED_DISABLE_ALEXA
|
||||||
|
; -D WLED_DISABLE_HUESYNC
|
||||||
|
; -D WLED_DISABLE_LOXONE
|
||||||
|
; -D WLED_DISABLE_INFRARED
|
||||||
|
; -D WLED_DISABLE_WEBSOCKETS
|
||||||
|
; -D WLED_DISABLE_MQTT
|
||||||
|
; -D WLED_DISABLE_ADALIGHT
|
||||||
|
; -D WLED_DISABLE_2D
|
||||||
|
; -D WLED_DISABLE_PXMAGIC
|
||||||
|
; -D WLED_DISABLE_ESPNOW
|
||||||
|
; -D WLED_DISABLE_BROWNOUT_DET
|
||||||
|
;
|
||||||
|
; PIN defines - uncomment and change, if needed:
|
||||||
|
; -D LEDPIN=2
|
||||||
|
; or use this for multiple outputs
|
||||||
|
; -D DATA_PINS=1,3
|
||||||
|
; -D BTNPIN=0
|
||||||
|
; -D IRPIN=4
|
||||||
|
; -D RLYPIN=12
|
||||||
|
; -D RLYMDE=1
|
||||||
|
; -D LED_BUILTIN=2 # GPIO of built-in LED
|
||||||
|
;
|
||||||
|
; Limit max buses
|
||||||
|
; -D WLED_MAX_BUSSES=2
|
||||||
|
;
|
||||||
|
; Configure default WiFi
|
||||||
|
; -D CLIENT_SSID='"MyNetwork"'
|
||||||
|
; -D CLIENT_PASS='"Netw0rkPassw0rd"'
|
||||||
|
;
|
||||||
|
; Configure and use Ethernet
|
||||||
|
; -D WLED_USE_ETHERNET
|
||||||
|
; -D WLED_ETH_DEFAULT=5
|
||||||
|
; do not use pins 5, (16,) 17, 18, 19, 21, 22, 23, 25, 26, 27 for anything but ethernet
|
||||||
|
; -D PHY_ADDR=0 -D ETH_PHY_POWER=5 -D ETH_PHY_MDC=23 -D ETH_PHY_MDIO=18
|
||||||
|
; -D ETH_CLK_MODE=ETH_CLOCK_GPIO17_OUT
|
||||||
|
;
|
||||||
|
; NTP time configuration
|
||||||
|
; -D WLED_NTP_ENABLED=true
|
||||||
|
; -D WLED_TIMEZONE=2
|
||||||
|
; -D WLED_LAT=48.86
|
||||||
|
; -D WLED_LON=2.33
|
||||||
|
;
|
||||||
|
; Use Watchdog timer with 10s guard
|
||||||
|
; -D WLED_WATCHDOG_TIMEOUT=10
|
||||||
|
;
|
||||||
|
; Create debug build (with remote debug)
|
||||||
|
; -D WLED_DEBUG
|
||||||
|
; -D WLED_DEBUG_HOST='"192.168.0.100"'
|
||||||
|
; -D WLED_DEBUG_PORT=7868
|
||||||
|
;
|
||||||
|
; Use Autosave usermod and set it to do save after 90s
|
||||||
|
; -D USERMOD_AUTO_SAVE
|
||||||
|
; -D AUTOSAVE_AFTER_SEC=90
|
||||||
|
;
|
||||||
|
; Use 4 Line Display usermod with SPI display
|
||||||
|
; -D USERMOD_FOUR_LINE_DISPLAY
|
||||||
|
; -D USE_ALT_DISPlAY # mandatory
|
||||||
|
; -DFLD_SPI_DEFAULT
|
||||||
|
; -D FLD_TYPE=SSD1306_SPI64
|
||||||
|
; -D FLD_PIN_CLOCKSPI=14
|
||||||
|
; -D FLD_PIN_DATASPI=13
|
||||||
|
; -D FLD_PIN_DC=26
|
||||||
|
; -D FLD_PIN_CS=15
|
||||||
|
; -D FLD_PIN_RESET=27
|
||||||
|
;
|
||||||
|
; Use Rotary encoder usermod (in conjunction with 4LD)
|
||||||
|
; -D USERMOD_ROTARY_ENCODER_UI
|
||||||
|
; -D ENCODER_DT_PIN=5
|
||||||
|
; -D ENCODER_CLK_PIN=18
|
||||||
|
; -D ENCODER_SW_PIN=19
|
||||||
|
;
|
||||||
|
; Use Dallas DS18B20 temperature sensor usermod and configure it to use GPIO13
|
||||||
|
; -D USERMOD_DALLASTEMPERATURE
|
||||||
|
; -D TEMPERATURE_PIN=13
|
||||||
|
;
|
||||||
|
; Use Multi Relay usermod and configure it to use 6 relays and appropriate GPIO
|
||||||
|
; -D USERMOD_MULTI_RELAY
|
||||||
|
; -D MULTI_RELAY_MAX_RELAYS=6
|
||||||
|
; -D MULTI_RELAY_PINS=12,23,22,21,24,25
|
||||||
|
;
|
||||||
|
; Use PIR sensor usermod and configure it to use GPIO4 and timer of 60s
|
||||||
|
; -D USERMOD_PIRSWITCH
|
||||||
|
; -D PIR_SENSOR_PIN=4
|
||||||
|
; -D PIR_SENSOR_OFF_SEC=60
|
||||||
|
;
|
||||||
|
; Use Audioreactive usermod and configure I2S microphone
|
||||||
|
; -D USERMOD_AUDIOREACTIVE
|
||||||
|
; -D UM_AUDIOREACTIVE_USE_NEW_FFT
|
||||||
|
; -D AUDIOPIN=-1
|
||||||
|
; -D DMTYPE=1 # 0-analog/disabled, 1-I2S generic, 2-ES7243, 3-SPH0645, 4-I2S+mclk, 5-I2S PDM
|
||||||
|
; -D I2S_SDPIN=36
|
||||||
|
; -D I2S_WSPIN=23
|
||||||
|
; -D I2S_CKPIN=19
|
||||||
|
;
|
||||||
|
; Use PWM fan usermod
|
||||||
|
; -D USERMOD_PWM_FAN
|
||||||
|
; -D TACHO_PIN=33
|
||||||
|
; -D PWM_PIN=32
|
||||||
|
;
|
||||||
|
; Use built-in or custom LED as a status indicator (assumes LED is connected to GPIO16)
|
||||||
|
; -D STATUSLED=16
|
||||||
|
;
|
||||||
|
; set the name of the module - make sure there is a quote-backslash-quote before the name and a backslash-quote-quote after the name
|
||||||
|
; -D SERVERNAME="\"WLED\""
|
||||||
|
;
|
||||||
|
; set the number of LEDs
|
||||||
|
; -D DEFAULT_LED_COUNT=30
|
||||||
|
; or this for multiple outputs
|
||||||
|
; -D PIXEL_COUNTS=30,30
|
||||||
|
;
|
||||||
|
; set milliampere limit when using ESP pin to power leds
|
||||||
|
; -D ABL_MILLIAMPS_DEFAULT=850
|
||||||
|
;
|
||||||
|
; enable IR by setting remote type
|
||||||
|
; -D IRTYPE=0 ;0 Remote disabled | 1 24-key RGB | 2 24-key with CT | 3 40-key blue | 4 40-key RGB | 5 21-key RGB | 6 6-key black | 7 9-key red | 8 JSON remote
|
||||||
|
;
|
||||||
|
; set default color order of your led strip
|
||||||
|
; -D DEFAULT_LED_COLOR_ORDER=COL_ORDER_GRB
|
||||||
|
;
|
||||||
|
; use PSRAM if a device (ESP) has one
|
||||||
|
; -DBOARD_HAS_PSRAM
|
||||||
|
; -D WLED_USE_PSRAM
|
||||||
|
;
|
||||||
|
; configure I2C and SPI interface (for various hardware)
|
||||||
|
; -D I2CSDAPIN=33 # initialise interface
|
||||||
|
; -D I2CSCLPIN=35 # initialise interface
|
||||||
|
; -D HW_PIN_SCL=35
|
||||||
|
; -D HW_PIN_SDA=33
|
||||||
|
; -D HW_PIN_CLOCKSPI=7
|
||||||
|
; -D HW_PIN_DATASPI=11
|
||||||
|
; -D HW_PIN_MISOSPI=9
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# PRE-CONFIGURED DEVELOPMENT BOARDS AND CONTROLLERS
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[env:esp07]
|
||||||
|
board = esp07
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_4m1m}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266}
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:d1_mini]
|
||||||
|
board = d1_mini
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
upload_speed = 921600
|
||||||
|
board_build.ldscript = ${common.ldscript_4m1m}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266}
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
monitor_filters = esp8266_exception_decoder
|
||||||
|
|
||||||
|
[env:heltec_wifi_kit_8]
|
||||||
|
board = d1_mini
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_4m1m}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266}
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:h803wf]
|
||||||
|
board = d1_mini
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_4m1m}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266} -D LEDPIN=1 -D WLED_DISABLE_INFRARED
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:esp32dev_qio80]
|
||||||
|
board = esp32dev
|
||||||
|
platform = ${esp32.platform}
|
||||||
|
platform_packages = ${esp32.platform_packages}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_qio80 #-D WLED_DISABLE_BROWNOUT_DET
|
||||||
|
lib_deps = ${esp32.lib_deps}
|
||||||
|
monitor_filters = esp32_exception_decoder
|
||||||
|
board_build.partitions = ${esp32.default_partitions}
|
||||||
|
board_build.f_flash = 80000000L
|
||||||
|
board_build.flash_mode = qio
|
||||||
|
|
||||||
|
[env:esp32dev_V4_dio80]
|
||||||
|
;; experimental ESP32 env using ESP-IDF V4.4.x
|
||||||
|
;; Warning: this build environment is not stable!!
|
||||||
|
;; please erase your device before installing.
|
||||||
|
board = esp32dev
|
||||||
|
platform = ${esp32_idf_V4.platform}
|
||||||
|
platform_packages = ${esp32_idf_V4.platform_packages}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=ESP32_V4_qio80 #-D WLED_DISABLE_BROWNOUT_DET
|
||||||
|
lib_deps = ${esp32_idf_V4.lib_deps}
|
||||||
|
monitor_filters = esp32_exception_decoder
|
||||||
|
board_build.partitions = ${esp32_idf_V4.default_partitions}
|
||||||
|
board_build.f_flash = 80000000L
|
||||||
|
board_build.flash_mode = dio
|
||||||
|
|
||||||
|
[env:esp32s2_saola]
|
||||||
|
board = esp32-s2-saola-1
|
||||||
|
platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.2/platform-tasmota-espressif32-2.0.2.zip
|
||||||
|
platform_packages =
|
||||||
|
framework = arduino
|
||||||
|
board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
|
||||||
|
board_build.flash_mode = qio
|
||||||
|
upload_speed = 460800
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags} ${esp32s2.build_flags} #-D WLED_RELEASE_NAME=S2_saola
|
||||||
|
;-DLOLIN_WIFI_FIX ;; try this in case Wifi does not work
|
||||||
|
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||||
|
lib_deps = ${esp32s2.lib_deps}
|
||||||
|
|
||||||
|
[env:esp32s3dev_8MB_PSRAM_qspi]
|
||||||
|
;; ESP32-TinyS3 development board, with 8MB FLASH and PSRAM (memory_type: qio_qspi)
|
||||||
|
extends = env:esp32s3dev_8MB_PSRAM_opi
|
||||||
|
;board = um_tinys3 ; -> needs workaround from https://github.com/Aircoookie/WLED/pull/2905#issuecomment-1328049860
|
||||||
|
board = esp32-s3-devkitc-1 ;; generic dev board; the next line adds PSRAM support
|
||||||
|
board_build.arduino.memory_type = qio_qspi ;; use with PSRAM: 2MB or 4MB
|
||||||
|
|
||||||
|
[env:esp8285_4CH_MagicHome]
|
||||||
|
board = esp8285
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_1m128k}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:esp8285_H801]
|
||||||
|
board = esp8285
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_1m128k}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:d1_mini_5CH_Shojo_PCB]
|
||||||
|
board = d1_mini
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_4m1m}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266} -D WLED_USE_SHOJO_PCB
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:d1_mini_debug]
|
||||||
|
board = d1_mini
|
||||||
|
build_type = debug
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_4m1m}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266} ${common.debug_flags}
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:d1_mini_ota]
|
||||||
|
board = d1_mini
|
||||||
|
upload_protocol = espota
|
||||||
|
# exchange for your WLED IP
|
||||||
|
upload_port = "10.10.1.27"
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_4m1m}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266}
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:anavi_miracle_controller]
|
||||||
|
board = d1_mini
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_4m1m}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266} -D LEDPIN=12 -D IRPIN=-1 -D RLYPIN=2
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:esp32c3dev_2MB]
|
||||||
|
;; for ESP32-C3 boards with 2MB flash (instead of 4MB).
|
||||||
|
;; this board need a specific partition file. OTA not possible.
|
||||||
|
extends = esp32c3
|
||||||
|
platform = ${esp32c3.platform}
|
||||||
|
platform_packages = ${esp32c3.platform_packages}
|
||||||
|
board = esp32-c3-devkitm-1
|
||||||
|
build_flags = ${common.build_flags} ${esp32c3.build_flags} #-D WLED_RELEASE_NAME=ESP32-C3
|
||||||
|
-D WLED_WATCHDOG_TIMEOUT=0
|
||||||
|
-D WLED_DISABLE_OTA
|
||||||
|
; -DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB
|
||||||
|
-DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
upload_speed = 115200
|
||||||
|
lib_deps = ${esp32c3.lib_deps}
|
||||||
|
board_build.partitions = tools/WLED_ESP32_2MB_noOTA.csv
|
||||||
|
board_build.flash_mode = dio
|
||||||
|
|
||||||
|
[env:wemos_shield_esp32]
|
||||||
|
board = esp32dev
|
||||||
|
platform = ${esp32.platform}
|
||||||
|
platform_packages = ${esp32.platform_packages}
|
||||||
|
upload_speed = 460800
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp32}
|
||||||
|
-D LEDPIN=16
|
||||||
|
-D RLYPIN=19
|
||||||
|
-D BTNPIN=17
|
||||||
|
-D IRPIN=18
|
||||||
|
-D UWLED_USE_MY_CONFIG
|
||||||
|
-D USERMOD_DALLASTEMPERATURE
|
||||||
|
-D USERMOD_FOUR_LINE_DISPLAY
|
||||||
|
-D TEMPERATURE_PIN=23
|
||||||
|
-D USE_ALT_DISPlAY ; new versions of USERMOD_FOUR_LINE_DISPLAY and USERMOD_ROTARY_ENCODER_UI
|
||||||
|
-D USERMOD_AUDIOREACTIVE
|
||||||
|
lib_deps = ${esp32.lib_deps}
|
||||||
|
OneWire@~2.3.5
|
||||||
|
olikraus/U8g2 @ ^2.28.8
|
||||||
|
https://github.com/blazoncek/arduinoFFT.git
|
||||||
|
board_build.partitions = ${esp32.default_partitions}
|
||||||
|
|
||||||
|
[env:m5atom]
|
||||||
|
board = esp32dev
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp32} -D LEDPIN=27 -D BTNPIN=39
|
||||||
|
lib_deps = ${esp32.lib_deps}
|
||||||
|
platform = ${esp32.platform}
|
||||||
|
platform_packages = ${esp32.platform_packages}
|
||||||
|
board_build.partitions = ${esp32.default_partitions}
|
||||||
|
|
||||||
|
[env:sp501e]
|
||||||
|
board = esp_wroom_02
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
board_build.ldscript = ${common.ldscript_2m512k}
|
||||||
|
build_flags = ${common.build_flags_esp8266} -D LEDPIN=3 -D BTNPIN=1
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:sp511e]
|
||||||
|
board = esp_wroom_02
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
board_build.ldscript = ${common.ldscript_2m512k}
|
||||||
|
build_flags = ${common.build_flags_esp8266} -D LEDPIN=3 -D BTNPIN=2 -D IRPIN=5 -D WLED_MAX_BUTTONS=3
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:Athom_RGBCW] ;7w and 5w(GU10) bulbs
|
||||||
|
board = esp8285
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_2m512k}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=-1 -D RLYPIN=-1 -D DATA_PINS=4,12,14,13,5
|
||||||
|
-D DEFAULT_LED_TYPE=TYPE_ANALOG_5CH -D WLED_DISABLE_INFRARED -D WLED_MAX_CCT_BLEND=0
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:Athom_15w_RGBCW] ;15w bulb
|
||||||
|
board = esp8285
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_2m512k}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=-1 -D RLYPIN=-1 -D DATA_PINS=4,12,14,5,13
|
||||||
|
-D DEFAULT_LED_TYPE=TYPE_ANALOG_5CH -D WLED_DISABLE_INFRARED -D WLED_MAX_CCT_BLEND=0 -D WLED_USE_IC_CCT
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:Athom_3Pin_Controller] ;small controller with only data
|
||||||
|
board = esp8285
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_2m512k}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=0 -D RLYPIN=-1 -D LEDPIN=1 -D WLED_DISABLE_INFRARED
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:Athom_4Pin_Controller] ; With clock and data interface
|
||||||
|
board = esp8285
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_2m512k}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=0 -D RLYPIN=12 -D LEDPIN=1 -D WLED_DISABLE_INFRARED
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:Athom_5Pin_Controller] ;Analog light strip controller
|
||||||
|
board = esp8285
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_2m512k}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=0 -D RLYPIN=-1 DATA_PINS=4,12,14,13 -D WLED_DISABLE_INFRARED
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:MY9291]
|
||||||
|
board = esp01_1m
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_1m128k}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_DISABLE_OTA -D USERMOD_MY9291
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# codm pixel controller board configurations
|
||||||
|
# codm-controller-0_6 can also be used for the TYWE3S controller
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
[env:codm-controller-0_6]
|
||||||
|
board = esp_wroom_02
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_2m512k}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266}
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
[env:codm-controller-0_6-rev2]
|
||||||
|
board = esp_wroom_02
|
||||||
|
platform = ${common.platform_wled_default}
|
||||||
|
platform_packages = ${common.platform_packages}
|
||||||
|
board_build.ldscript = ${common.ldscript_4m1m}
|
||||||
|
build_unflags = ${common.build_unflags}
|
||||||
|
build_flags = ${common.build_flags_esp8266}
|
||||||
|
lib_deps = ${esp8266.lib_deps}
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# EleksTube-IPS
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
[env:elekstube_ips]
|
||||||
|
board = esp32dev
|
||||||
|
platform = ${esp32.platform}
|
||||||
|
platform_packages = ${esp32.platform_packages}
|
||||||
|
upload_speed = 921600
|
||||||
|
build_flags = ${common.build_flags_esp32} -D WLED_DISABLE_BROWNOUT_DET -D WLED_DISABLE_INFRARED
|
||||||
|
-D USERMOD_RTC
|
||||||
|
-D USERMOD_ELEKSTUBE_IPS
|
||||||
|
-D LEDPIN=12
|
||||||
|
-D RLYPIN=27
|
||||||
|
-D BTNPIN=34
|
||||||
|
-D DEFAULT_LED_COUNT=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
|
||||||
|
lib_deps =
|
||||||
|
${esp32.lib_deps}
|
||||||
|
TFT_eSPI @ ^2.3.70
|
||||||
|
board_build.partitions = ${esp32.default_partitions}
|
@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# This file is autogenerated by pip-compile with python 3.8
|
# This file is autogenerated by pip-compile with Python 3.12
|
||||||
# To update, run:
|
# by the following command:
|
||||||
#
|
#
|
||||||
# pip-compile
|
# pip-compile
|
||||||
#
|
#
|
||||||
@ -21,7 +21,9 @@ click==8.1.3
|
|||||||
# platformio
|
# platformio
|
||||||
# uvicorn
|
# uvicorn
|
||||||
colorama==0.4.6
|
colorama==0.4.6
|
||||||
# via platformio
|
# via
|
||||||
|
# click
|
||||||
|
# platformio
|
||||||
h11==0.14.0
|
h11==0.14.0
|
||||||
# via
|
# via
|
||||||
# uvicorn
|
# uvicorn
|
||||||
|
205
tools/cdata-test.js
Normal file
205
tools/cdata-test.js
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('node:assert');
|
||||||
|
const { describe, it, before, after } = require('node:test');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const child_process = require('child_process');
|
||||||
|
const util = require('util');
|
||||||
|
const execPromise = util.promisify(child_process.exec);
|
||||||
|
|
||||||
|
process.env.NODE_ENV = 'test'; // Set the environment to testing
|
||||||
|
const cdata = require('./cdata.js');
|
||||||
|
|
||||||
|
describe('Function', () => {
|
||||||
|
const testFolderPath = path.join(__dirname, 'testFolder');
|
||||||
|
const oldFilePath = path.join(testFolderPath, 'oldFile.txt');
|
||||||
|
const newFilePath = path.join(testFolderPath, 'newFile.txt');
|
||||||
|
|
||||||
|
// Create a temporary file before the test
|
||||||
|
before(() => {
|
||||||
|
// Create test folder
|
||||||
|
if (!fs.existsSync(testFolderPath)) {
|
||||||
|
fs.mkdirSync(testFolderPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an old file
|
||||||
|
fs.writeFileSync(oldFilePath, 'This is an old file.');
|
||||||
|
// Modify the 'mtime' to simulate an old file
|
||||||
|
const oldTime = new Date();
|
||||||
|
oldTime.setFullYear(oldTime.getFullYear() - 1);
|
||||||
|
fs.utimesSync(oldFilePath, oldTime, oldTime);
|
||||||
|
|
||||||
|
// Create a new file
|
||||||
|
fs.writeFileSync(newFilePath, 'This is a new file.');
|
||||||
|
});
|
||||||
|
|
||||||
|
// delete the temporary files after the test
|
||||||
|
after(() => {
|
||||||
|
fs.rmSync(testFolderPath, { recursive: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isFileNewerThan', async () => {
|
||||||
|
it('should return true if the file is newer than the provided time', async () => {
|
||||||
|
const pastTime = Date.now() - 10000; // 10 seconds ago
|
||||||
|
assert.strictEqual(cdata.isFileNewerThan(newFilePath, pastTime), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if the file is older than the provided time', async () => {
|
||||||
|
assert.strictEqual(cdata.isFileNewerThan(oldFilePath, Date.now()), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an exception if the file does not exist', async () => {
|
||||||
|
assert.throws(() => {
|
||||||
|
cdata.isFileNewerThan('nonexistent.txt', Date.now());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isAnyFileInFolderNewerThan', async () => {
|
||||||
|
it('should return true if a file in the folder is newer than the given time', async () => {
|
||||||
|
const time = fs.statSync(path.join(testFolderPath, 'oldFile.txt')).mtime;
|
||||||
|
assert.strictEqual(cdata.isAnyFileInFolderNewerThan(testFolderPath, time), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if no files in the folder are newer than the given time', async () => {
|
||||||
|
assert.strictEqual(cdata.isAnyFileInFolderNewerThan(testFolderPath, new Date()), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an exception if the folder does not exist', async () => {
|
||||||
|
assert.throws(() => {
|
||||||
|
cdata.isAnyFileInFolderNewerThan('nonexistent', new Date());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Script', () => {
|
||||||
|
const folderPath = 'wled00';
|
||||||
|
const dataPath = path.join(folderPath, 'data');
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
process.env.NODE_ENV = 'production';
|
||||||
|
// Backup files
|
||||||
|
fs.cpSync("wled00/data", "wled00Backup", { recursive: true });
|
||||||
|
fs.cpSync("tools/cdata.js", "cdata.bak.js");
|
||||||
|
});
|
||||||
|
after(() => {
|
||||||
|
// Restore backup
|
||||||
|
fs.rmSync("wled00/data", { recursive: true });
|
||||||
|
fs.renameSync("wled00Backup", "wled00/data");
|
||||||
|
fs.rmSync("tools/cdata.js");
|
||||||
|
fs.renameSync("cdata.bak.js", "tools/cdata.js");
|
||||||
|
});
|
||||||
|
|
||||||
|
// delete all html_*.h files
|
||||||
|
async function deleteBuiltFiles() {
|
||||||
|
const files = await fs.promises.readdir(folderPath);
|
||||||
|
await Promise.all(files.map(file => {
|
||||||
|
if (file.startsWith('html_') && path.extname(file) === '.h') {
|
||||||
|
return fs.promises.unlink(path.join(folderPath, file));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if html_*.h files were created
|
||||||
|
async function checkIfBuiltFilesExist() {
|
||||||
|
const files = await fs.promises.readdir(folderPath);
|
||||||
|
const htmlFiles = files.filter(file => file.startsWith('html_') && path.extname(file) === '.h');
|
||||||
|
assert(htmlFiles.length > 0, 'html_*.h files were not created');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runAndCheckIfBuiltFilesExist() {
|
||||||
|
await execPromise('node tools/cdata.js');
|
||||||
|
await checkIfBuiltFilesExist();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkIfFileWasNewlyCreated(file) {
|
||||||
|
const modifiedTime = fs.statSync(file).mtimeMs;
|
||||||
|
assert(Date.now() - modifiedTime < 500, file + ' was not modified');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function testFileModification(sourceFilePath, resultFile) {
|
||||||
|
// run cdata.js to ensure html_*.h files are created
|
||||||
|
await execPromise('node tools/cdata.js');
|
||||||
|
|
||||||
|
// modify file
|
||||||
|
fs.appendFileSync(sourceFilePath, ' ');
|
||||||
|
// delay for 1 second to ensure the modified time is different
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
|
|
||||||
|
// run script cdata.js again and wait for it to finish
|
||||||
|
await execPromise('node tools/cdata.js');
|
||||||
|
|
||||||
|
checkIfFileWasNewlyCreated(path.join(folderPath, resultFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('should build if', () => {
|
||||||
|
it('html_*.h files are missing', async () => {
|
||||||
|
await deleteBuiltFiles();
|
||||||
|
await runAndCheckIfBuiltFilesExist();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('only one html_*.h file is missing', async () => {
|
||||||
|
// run script cdata.js and wait for it to finish
|
||||||
|
await execPromise('node tools/cdata.js');
|
||||||
|
|
||||||
|
// delete a random html_*.h file
|
||||||
|
let files = await fs.promises.readdir(folderPath);
|
||||||
|
let htmlFiles = files.filter(file => file.startsWith('html_') && path.extname(file) === '.h');
|
||||||
|
const randomFile = htmlFiles[Math.floor(Math.random() * htmlFiles.length)];
|
||||||
|
await fs.promises.unlink(path.join(folderPath, randomFile));
|
||||||
|
|
||||||
|
await runAndCheckIfBuiltFilesExist();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('script was executed with -f or --force', async () => {
|
||||||
|
await execPromise('node tools/cdata.js');
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
|
await execPromise('node tools/cdata.js --force');
|
||||||
|
await checkIfFileWasNewlyCreated(path.join(folderPath, 'html_ui.h'));
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
|
await execPromise('node tools/cdata.js -f');
|
||||||
|
await checkIfFileWasNewlyCreated(path.join(folderPath, 'html_ui.h'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('a file changes', async () => {
|
||||||
|
await testFileModification(path.join(dataPath, 'index.htm'), 'html_ui.h');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('a inlined file changes', async () => {
|
||||||
|
await testFileModification(path.join(dataPath, 'index.js'), 'html_ui.h');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('a settings file changes', async () => {
|
||||||
|
await testFileModification(path.join(dataPath, 'settings_leds.htm'), 'html_ui.h');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('the favicon changes', async () => {
|
||||||
|
await testFileModification(path.join(dataPath, 'favicon.ico'), 'html_ui.h');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cdata.js changes', async () => {
|
||||||
|
await testFileModification('tools/cdata.js', 'html_ui.h');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('should not build if', () => {
|
||||||
|
it('the files are already built', async () => {
|
||||||
|
await deleteBuiltFiles();
|
||||||
|
|
||||||
|
// run script cdata.js and wait for it to finish
|
||||||
|
let startTime = Date.now();
|
||||||
|
await execPromise('node tools/cdata.js');
|
||||||
|
const firstRunTime = Date.now() - startTime;
|
||||||
|
|
||||||
|
// run script cdata.js and wait for it to finish
|
||||||
|
startTime = Date.now();
|
||||||
|
await execPromise('node tools/cdata.js');
|
||||||
|
const secondRunTime = Date.now() - startTime;
|
||||||
|
|
||||||
|
// check if second run was faster than the first (must be at least 2x faster)
|
||||||
|
assert(secondRunTime < firstRunTime / 2, 'html_*.h files were rebuilt');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
245
tools/cdata.js
245
tools/cdata.js
@ -16,18 +16,49 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require('path');
|
const path = require("path");
|
||||||
const inliner = require("inliner");
|
const inliner = require("inliner");
|
||||||
const zlib = require("zlib");
|
const zlib = require("zlib");
|
||||||
const CleanCSS = require("clean-css");
|
const CleanCSS = require("clean-css");
|
||||||
const MinifyHTML = require("html-minifier-terser").minify;
|
const minifyHtml = require("html-minifier-terser").minify;
|
||||||
const packageJson = require("../package.json");
|
const packageJson = require("../package.json");
|
||||||
|
|
||||||
|
// Export functions for testing
|
||||||
|
module.exports = { isFileNewerThan, isAnyFileInFolderNewerThan };
|
||||||
|
|
||||||
const output = ["wled00/html_ui.h", "wled00/html_pixart.h", "wled00/html_cpal.h", "wled00/html_pxmagic.h", "wled00/html_settings.h", "wled00/html_other.h"]
|
const output = ["wled00/html_ui.h", "wled00/html_pixart.h", "wled00/html_cpal.h", "wled00/html_pxmagic.h", "wled00/html_settings.h", "wled00/html_other.h"]
|
||||||
|
|
||||||
/**
|
// \x1b[34m is blue, \x1b[36m is cyan, \x1b[0m is reset
|
||||||
|
const wledBanner = `
|
||||||
|
\t\x1b[34m## ## ## ######## ########
|
||||||
|
\t\x1b[34m## ## ## ## ## ## ##
|
||||||
|
\t\x1b[34m## ## ## ## ## ## ##
|
||||||
|
\t\x1b[34m## ## ## ## ###### ## ##
|
||||||
|
\t\x1b[34m## ## ## ## ## ## ##
|
||||||
|
\t\x1b[34m## ## ## ## ## ## ##
|
||||||
|
\t\x1b[34m ### ### ######## ######## ########
|
||||||
|
\t\t\x1b[36mbuild script for web UI
|
||||||
|
\x1b[0m`;
|
||||||
|
|
||||||
|
const singleHeader = `/*
|
||||||
|
* Binary array for the Web UI.
|
||||||
|
* gzip is used for smaller size and improved speeds.
|
||||||
*
|
*
|
||||||
|
* Please see https://kno.wled.ge/advanced/custom-features/#changing-web-ui
|
||||||
|
* to find out how to easily modify the web UI source!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
|
const multiHeader = `/*
|
||||||
|
* More web UI HTML source arrays.
|
||||||
|
* This file is auto generated, please don't make any changes manually.
|
||||||
|
*
|
||||||
|
* Instead, see https://kno.wled.ge/advanced/custom-features/#changing-web-ui
|
||||||
|
* to find out how to easily modify the web UI source!
|
||||||
|
*/
|
||||||
|
`;
|
||||||
|
|
||||||
function hexdump(buffer, isHex = false) {
|
function hexdump(buffer, isHex = false) {
|
||||||
let lines = [];
|
let lines = [];
|
||||||
|
|
||||||
@ -54,183 +85,112 @@ function hexdump(buffer,isHex=false) {
|
|||||||
return lines.join(",\n");
|
return lines.join(",\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
function strReplace(str, search, replacement) {
|
|
||||||
return str.split(search).join(replacement);
|
|
||||||
}
|
|
||||||
|
|
||||||
function adoptVersionAndRepo(html) {
|
function adoptVersionAndRepo(html) {
|
||||||
let repoUrl = packageJson.repository ? packageJson.repository.url : undefined;
|
let repoUrl = packageJson.repository ? packageJson.repository.url : undefined;
|
||||||
if (repoUrl) {
|
if (repoUrl) {
|
||||||
repoUrl = repoUrl.replace(/^git\+/, "");
|
repoUrl = repoUrl.replace(/^git\+/, "");
|
||||||
repoUrl = repoUrl.replace(/\.git$/, "");
|
repoUrl = repoUrl.replace(/\.git$/, "");
|
||||||
// Replace we
|
html = html.replaceAll("https://github.com/atuline/WLED", repoUrl);
|
||||||
html = strReplace(html, "https://github.com/atuline/WLED", repoUrl);
|
html = html.replaceAll("https://github.com/Aircoookie/WLED", repoUrl);
|
||||||
html = strReplace(html, "https://github.com/Aircoookie/WLED", repoUrl);
|
|
||||||
}
|
}
|
||||||
let version = packageJson.version;
|
let version = packageJson.version;
|
||||||
if (version) {
|
if (version) {
|
||||||
html = strReplace(html, "##VERSION##", version);
|
html = html.replaceAll("##VERSION##", version);
|
||||||
}
|
}
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
function filter(str, type) {
|
async function minify(str, type = "plain") {
|
||||||
str = adoptVersionAndRepo(str);
|
const options = {
|
||||||
if (type === undefined) {
|
collapseWhitespace: true,
|
||||||
|
collapseBooleanAttributes: true,
|
||||||
|
collapseInlineTagWhitespace: true,
|
||||||
|
minifyCSS: true,
|
||||||
|
minifyJS: true,
|
||||||
|
removeAttributeQuotes: true,
|
||||||
|
removeComments: true,
|
||||||
|
sortAttributes: true,
|
||||||
|
sortClassName: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (type == "plain") {
|
||||||
return str;
|
return str;
|
||||||
} else if (type == "css-minify") {
|
} else if (type == "css-minify") {
|
||||||
return new CleanCSS({}).minify(str).styles;
|
return new CleanCSS({}).minify(str).styles;
|
||||||
} else if (type == "js-minify") {
|
} else if (type == "js-minify") {
|
||||||
return MinifyHTML('<script>' + str + '</script>', {
|
return await minifyHtml('<script>' + str + '</script>', options).replace(/<[\/]*script>/g, '');
|
||||||
collapseWhitespace: true,
|
|
||||||
minifyJS: true,
|
|
||||||
continueOnParseError: false,
|
|
||||||
removeComments: true,
|
|
||||||
}).replace(/<[\/]*script>/g,'');
|
|
||||||
} else if (type == "html-minify") {
|
} else if (type == "html-minify") {
|
||||||
return MinifyHTML(str, {
|
return await minifyHtml(str, options);
|
||||||
collapseWhitespace: true,
|
|
||||||
maxLineLength: 80,
|
|
||||||
minifyCSS: true,
|
|
||||||
minifyJS: true,
|
|
||||||
continueOnParseError: false,
|
|
||||||
removeComments: true,
|
|
||||||
});
|
|
||||||
} else if (type == "html-minify-ui") {
|
|
||||||
return MinifyHTML(str, {
|
|
||||||
collapseWhitespace: true,
|
|
||||||
conservativeCollapse: true,
|
|
||||||
maxLineLength: 80,
|
|
||||||
minifyCSS: true,
|
|
||||||
minifyJS: true,
|
|
||||||
continueOnParseError: false,
|
|
||||||
removeComments: true,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.warn("Unknown filter: " + type);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeHtmlGzipped(sourceFile, resultFile, page) {
|
throw new Error("Unknown filter: " + type);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function writeHtmlGzipped(sourceFile, resultFile, page) {
|
||||||
console.info("Reading " + sourceFile);
|
console.info("Reading " + sourceFile);
|
||||||
new inliner(sourceFile, function (error, html) {
|
new inliner(sourceFile, async function (error, html) {
|
||||||
console.info("Inlined " + html.length + " characters");
|
if (error) throw error;
|
||||||
html = filter(html, "html-minify-ui");
|
|
||||||
console.info("Minified to " + html.length + " characters");
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.warn(error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
html = adoptVersionAndRepo(html);
|
html = adoptVersionAndRepo(html);
|
||||||
zlib.gzip(html, { level: zlib.constants.Z_BEST_COMPRESSION }, function (error, result) {
|
const originalLength = html.length;
|
||||||
if (error) {
|
html = await minify(html, "html-minify");
|
||||||
console.warn(error);
|
const result = zlib.gzipSync(html, { level: zlib.constants.Z_BEST_COMPRESSION });
|
||||||
throw error;
|
console.info("Minified and compressed " + sourceFile + " from " + originalLength + " to " + result.length + " bytes");
|
||||||
}
|
|
||||||
|
|
||||||
console.info("Compressed " + result.length + " bytes");
|
|
||||||
const array = hexdump(result);
|
const array = hexdump(result);
|
||||||
const src = `/*
|
let src = singleHeader;
|
||||||
* Binary array for the Web UI.
|
src += `const uint16_t PAGE_${page}_L = ${result.length};\n`;
|
||||||
* gzip is used for smaller size and improved speeds.
|
src += `const uint8_t PAGE_${page}[] PROGMEM = {\n${array}\n};\n\n`;
|
||||||
*
|
|
||||||
* Please see https://kno.wled.ge/advanced/custom-features/#changing-web-ui
|
|
||||||
* to find out how to easily modify the web UI source!
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Autogenerated from ${sourceFile}, do not edit!!
|
|
||||||
const uint16_t PAGE_${page}_L = ${result.length};
|
|
||||||
const uint8_t PAGE_${page}[] PROGMEM = {
|
|
||||||
${array}
|
|
||||||
};
|
|
||||||
`;
|
|
||||||
console.info("Writing " + resultFile);
|
console.info("Writing " + resultFile);
|
||||||
fs.writeFileSync(resultFile, src);
|
fs.writeFileSync(resultFile, src);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function specToChunk(srcDir, s) {
|
async function specToChunk(srcDir, s) {
|
||||||
if (s.method == "plaintext") {
|
|
||||||
const buf = fs.readFileSync(srcDir + "/" + s.file);
|
const buf = fs.readFileSync(srcDir + "/" + s.file);
|
||||||
const str = buf.toString("utf-8");
|
let chunk = `\n// Autogenerated from ${srcDir}/${s.file}, do not edit!!\n`
|
||||||
const chunk = `
|
|
||||||
// Autogenerated from ${srcDir}/${s.file}, do not edit!!
|
|
||||||
const char ${s.name}[] PROGMEM = R"${s.prepend || ""}${filter(str, s.filter)}${
|
|
||||||
s.append || ""
|
|
||||||
}";
|
|
||||||
|
|
||||||
`;
|
if (s.method == "plaintext" || s.method == "gzip") {
|
||||||
return s.mangle ? s.mangle(chunk) : chunk;
|
let str = buf.toString("utf-8");
|
||||||
} else if (s.method == "gzip") {
|
str = adoptVersionAndRepo(str);
|
||||||
const buf = fs.readFileSync(srcDir + "/" + s.file);
|
const originalLength = str.length;
|
||||||
var str = buf.toString('utf-8');
|
if (s.method == "gzip") {
|
||||||
if (s.mangle) str = s.mangle(str);
|
if (s.mangle) str = s.mangle(str);
|
||||||
const zip = zlib.gzipSync(filter(str, s.filter), { level: zlib.constants.Z_BEST_COMPRESSION });
|
const zip = zlib.gzipSync(await minify(str, s.filter), { level: zlib.constants.Z_BEST_COMPRESSION });
|
||||||
const result = hexdump(zip.toString('hex'), true);
|
console.info("Minified and compressed " + s.file + " from " + originalLength + " to " + zip.length + " bytes");
|
||||||
const chunk = `
|
const result = hexdump(zip);
|
||||||
// Autogenerated from ${srcDir}/${s.file}, do not edit!!
|
chunk += `const uint16_t ${s.name}_length = ${zip.length};\n`;
|
||||||
const uint16_t ${s.name}_length = ${zip.length};
|
chunk += `const uint8_t ${s.name}[] PROGMEM = {\n${result}\n};\n\n`;
|
||||||
const uint8_t ${s.name}[] PROGMEM = {
|
|
||||||
${result}
|
|
||||||
};
|
|
||||||
|
|
||||||
`;
|
|
||||||
return chunk;
|
|
||||||
} else if (s.method == "binary") {
|
|
||||||
const buf = fs.readFileSync(srcDir + "/" + s.file);
|
|
||||||
const result = hexdump(buf);
|
|
||||||
const chunk = `
|
|
||||||
// Autogenerated from ${srcDir}/${s.file}, do not edit!!
|
|
||||||
const uint16_t ${s.name}_length = ${buf.length};
|
|
||||||
const uint8_t ${s.name}[] PROGMEM = {
|
|
||||||
${result}
|
|
||||||
};
|
|
||||||
|
|
||||||
`;
|
|
||||||
return chunk;
|
return chunk;
|
||||||
} else {
|
} else {
|
||||||
console.warn("Unknown method: " + s.method);
|
const minified = await minify(str, s.filter);
|
||||||
return undefined;
|
console.info("Minified " + s.file + " from " + originalLength + " to " + minified.length + " bytes");
|
||||||
|
chunk += `const char ${s.name}[] PROGMEM = R"${s.prepend || ""}${minified}${s.append || ""}";\n\n`;
|
||||||
|
return s.mangle ? s.mangle(chunk) : chunk;
|
||||||
}
|
}
|
||||||
|
} else if (s.method == "binary") {
|
||||||
|
const result = hexdump(buf);
|
||||||
|
chunk += `const uint16_t ${s.name}_length = ${buf.length};\n`;
|
||||||
|
chunk += `const uint8_t ${s.name}[] PROGMEM = {\n${result}\n};\n\n`;
|
||||||
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeChunks(srcDir, specs, resultFile) {
|
throw new Error("Unknown method: " + s.method);
|
||||||
let src = `/*
|
}
|
||||||
* More web UI HTML source arrays.
|
|
||||||
* This file is auto generated, please don't make any changes manually.
|
async function writeChunks(srcDir, specs, resultFile) {
|
||||||
* Instead, see https://kno.wled.ge/advanced/custom-features/#changing-web-ui
|
let src = multiHeader;
|
||||||
* to find out how to easily modify the web UI source!
|
for (const s of specs) {
|
||||||
*/
|
console.info("Reading " + srcDir + "/" + s.file + " as " + s.name);
|
||||||
`;
|
src += await specToChunk(srcDir, s);
|
||||||
specs.forEach((s) => {
|
|
||||||
const file = srcDir + "/" + s.file;
|
|
||||||
try {
|
|
||||||
console.info("Reading " + file + " as " + s.name);
|
|
||||||
src += specToChunk(srcDir, s);
|
|
||||||
} catch (e) {
|
|
||||||
console.warn(
|
|
||||||
"Failed " + s.name + " from " + file,
|
|
||||||
e.message.length > 60 ? e.message.substring(0, 60) : e.message
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
console.info("Writing " + src.length + " characters into " + resultFile);
|
console.info("Writing " + src.length + " characters into " + resultFile);
|
||||||
fs.writeFileSync(resultFile, src);
|
fs.writeFileSync(resultFile, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a file is newer than a given time
|
// Check if a file is newer than a given time
|
||||||
function isFileNewerThan(filePath, time) {
|
function isFileNewerThan(filePath, time) {
|
||||||
try {
|
|
||||||
const stats = fs.statSync(filePath);
|
const stats = fs.statSync(filePath);
|
||||||
return stats.mtimeMs > time;
|
return stats.mtimeMs > time;
|
||||||
} catch (e) {
|
|
||||||
console.error(`Failed to get stats for file ${filePath}:`, e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if any file in a folder (or its subfolders) is newer than a given time
|
// Check if any file in a folder (or its subfolders) is newer than a given time
|
||||||
@ -248,21 +208,30 @@ function isAnyFileInFolderNewerThan(folderPath, time) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if the web UI is already built
|
||||||
function isAlreadyBuilt(folderPath) {
|
function isAlreadyBuilt(folderPath) {
|
||||||
let lastBuildTime = Infinity;
|
let lastBuildTime = Infinity;
|
||||||
|
|
||||||
for (const file of output) {
|
for (const file of output) {
|
||||||
try {
|
try {
|
||||||
lastBuildTime = Math.min(lastBuildTime, fs.statSync(file).mtimeMs);
|
lastBuildTime = Math.min(lastBuildTime, fs.statSync(file).mtimeMs);
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
if (e.code !== 'ENOENT') throw e;
|
||||||
|
console.info("File " + file + " does not exist. Rebuilding...");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return !isAnyFileInFolderNewerThan(folderPath, lastBuildTime);
|
return !isAnyFileInFolderNewerThan(folderPath, lastBuildTime) && !isFileNewerThan("tools/cdata.js", lastBuildTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't run this script if we're in a test environment
|
||||||
|
if (process.env.NODE_ENV === 'test') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.info(wledBanner);
|
||||||
|
|
||||||
if (isAlreadyBuilt("wled00/data") && process.argv[2] !== '--force' && process.argv[2] !== '-f') {
|
if (isAlreadyBuilt("wled00/data") && process.argv[2] !== '--force' && process.argv[2] !== '-f') {
|
||||||
console.info("Web UI is already built");
|
console.info("Web UI is already built");
|
||||||
return;
|
return;
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
#define PIR_SENSOR_OFF_SEC 600
|
#define PIR_SENSOR_OFF_SEC 600
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef PIR_SENSOR_MAX_SENSORS
|
||||||
|
#define PIR_SENSOR_MAX_SENSORS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This usermod handles PIR sensor states.
|
* This usermod handles PIR sensor states.
|
||||||
@ -50,13 +53,13 @@ private:
|
|||||||
|
|
||||||
volatile unsigned long offTimerStart = 0; // off timer start time
|
volatile unsigned long offTimerStart = 0; // off timer start time
|
||||||
volatile bool PIRtriggered = false; // did PIR trigger?
|
volatile bool PIRtriggered = false; // did PIR trigger?
|
||||||
bool sensorPinState = LOW; // current PIR sensor pin state
|
|
||||||
bool initDone = false; // status of initialization
|
bool initDone = false; // status of initialization
|
||||||
unsigned long lastLoop = 0;
|
unsigned long lastLoop = 0;
|
||||||
|
bool sensorPinState[PIR_SENSOR_MAX_SENSORS] = {LOW}; // current PIR sensor pin state
|
||||||
|
|
||||||
// configurable parameters
|
// configurable parameters
|
||||||
bool enabled = true; // PIR sensor enabled
|
bool enabled = true; // PIR sensor enabled
|
||||||
int8_t PIRsensorPin = PIR_SENSOR_PIN; // PIR sensor pin
|
int8_t PIRsensorPin[PIR_SENSOR_MAX_SENSORS] = {PIR_SENSOR_PIN}; // PIR sensor pin
|
||||||
uint32_t m_switchOffDelay = PIR_SENSOR_OFF_SEC*1000; // delay before switch off after the sensor state goes LOW (10min)
|
uint32_t m_switchOffDelay = PIR_SENSOR_OFF_SEC*1000; // delay before switch off after the sensor state goes LOW (10min)
|
||||||
uint8_t m_onPreset = 0; // on preset
|
uint8_t m_onPreset = 0; // on preset
|
||||||
uint8_t m_offPreset = 0; // off preset
|
uint8_t m_offPreset = 0; // off preset
|
||||||
@ -325,21 +328,29 @@ void PIRsensorSwitch::publishHomeAssistantAutodiscovery()
|
|||||||
|
|
||||||
bool PIRsensorSwitch::updatePIRsensorState()
|
bool PIRsensorSwitch::updatePIRsensorState()
|
||||||
{
|
{
|
||||||
bool pinState = digitalRead(PIRsensorPin);
|
bool stateChanged = false;
|
||||||
if (pinState != sensorPinState) {
|
bool allOff = true;
|
||||||
sensorPinState = pinState; // change previous state
|
for (int i = 0; i < PIR_SENSOR_MAX_SENSORS; i++) {
|
||||||
|
if (PIRsensorPin[i] < 0) continue;
|
||||||
|
|
||||||
if (sensorPinState == HIGH) {
|
bool pinState = digitalRead(PIRsensorPin[i]);
|
||||||
|
if (pinState != sensorPinState[i]) {
|
||||||
|
sensorPinState[i] = pinState; // change previous state
|
||||||
|
stateChanged = true;
|
||||||
|
|
||||||
|
if (sensorPinState[i] == HIGH) {
|
||||||
offTimerStart = 0;
|
offTimerStart = 0;
|
||||||
|
allOff = false;
|
||||||
if (!m_mqttOnly && (!m_nightTimeOnly || (m_nightTimeOnly && !isDayTime()))) switchStrip(true);
|
if (!m_mqttOnly && (!m_nightTimeOnly || (m_nightTimeOnly && !isDayTime()))) switchStrip(true);
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stateChanged) {
|
||||||
|
publishMqtt(!allOff);
|
||||||
// start switch off timer
|
// start switch off timer
|
||||||
offTimerStart = millis();
|
if (allOff) offTimerStart = millis();
|
||||||
}
|
}
|
||||||
publishMqtt(sensorPinState == HIGH);
|
return stateChanged;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PIRsensorSwitch::handleOffTimer()
|
bool PIRsensorSwitch::handleOffTimer()
|
||||||
@ -356,18 +367,21 @@ bool PIRsensorSwitch::handleOffTimer()
|
|||||||
|
|
||||||
void PIRsensorSwitch::setup()
|
void PIRsensorSwitch::setup()
|
||||||
{
|
{
|
||||||
if (enabled) {
|
for (int i = 0; i < PIR_SENSOR_MAX_SENSORS; i++) {
|
||||||
|
sensorPinState[i] = LOW;
|
||||||
|
if (PIRsensorPin[i] < 0) continue;
|
||||||
// pin retrieved from cfg.json (readFromConfig()) prior to running setup()
|
// pin retrieved from cfg.json (readFromConfig()) prior to running setup()
|
||||||
if (PIRsensorPin >= 0 && pinManager.allocatePin(PIRsensorPin, false, PinOwner::UM_PIR)) {
|
if (pinManager.allocatePin(PIRsensorPin[i], false, PinOwner::UM_PIR)) {
|
||||||
// PIR Sensor mode INPUT_PULLUP
|
// PIR Sensor mode INPUT_PULLDOWN
|
||||||
pinMode(PIRsensorPin, INPUT_PULLUP);
|
#ifdef ESP8266
|
||||||
sensorPinState = digitalRead(PIRsensorPin);
|
pinMode(PIRsensorPin[i], PIRsensorPin[i]==16 ? INPUT_PULLDOWN_16 : INPUT_PULLUP); // ESP8266 has INPUT_PULLDOWN on GPIO16 only
|
||||||
|
#else
|
||||||
|
pinMode(PIRsensorPin[i], INPUT_PULLDOWN);
|
||||||
|
#endif
|
||||||
|
sensorPinState[i] = digitalRead(PIRsensorPin[i]);
|
||||||
} else {
|
} else {
|
||||||
if (PIRsensorPin >= 0) {
|
DEBUG_PRINT(F("PIRSensorSwitch pin ")); DEBUG_PRINTLN(i); DEBUG_PRINTLN(F(" allocation failed."));
|
||||||
DEBUG_PRINTLN(F("PIRSensorSwitch pin allocation failed."));
|
PIRsensorPin[i] = -1; // allocation failed
|
||||||
}
|
|
||||||
PIRsensorPin = -1; // allocation failed
|
|
||||||
enabled = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initDone = true;
|
initDone = true;
|
||||||
@ -382,8 +396,8 @@ void PIRsensorSwitch::onMqttConnect(bool sessionPresent)
|
|||||||
|
|
||||||
void PIRsensorSwitch::loop()
|
void PIRsensorSwitch::loop()
|
||||||
{
|
{
|
||||||
// only check sensors 4x/s
|
// only check sensors 5x/s
|
||||||
if (!enabled || millis() - lastLoop < 250 || strip.isUpdating()) return;
|
if (!enabled || millis() - lastLoop < 200) return;
|
||||||
lastLoop = millis();
|
lastLoop = millis();
|
||||||
|
|
||||||
if (!updatePIRsensorState()) {
|
if (!updatePIRsensorState()) {
|
||||||
@ -396,37 +410,35 @@ void PIRsensorSwitch::addToJsonInfo(JsonObject &root)
|
|||||||
JsonObject user = root["u"];
|
JsonObject user = root["u"];
|
||||||
if (user.isNull()) user = root.createNestedObject("u");
|
if (user.isNull()) user = root.createNestedObject("u");
|
||||||
|
|
||||||
|
bool state = LOW;
|
||||||
|
for (int i = 0; i < PIR_SENSOR_MAX_SENSORS; i++)
|
||||||
|
if (PIRsensorPin[i] >= 0) state |= sensorPinState[i];
|
||||||
|
|
||||||
JsonArray infoArr = user.createNestedArray(FPSTR(_name));
|
JsonArray infoArr = user.createNestedArray(FPSTR(_name));
|
||||||
|
|
||||||
String uiDomString;
|
String uiDomString;
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
if (offTimerStart > 0)
|
if (offTimerStart > 0) {
|
||||||
{
|
|
||||||
uiDomString = "";
|
uiDomString = "";
|
||||||
unsigned int offSeconds = (m_switchOffDelay - (millis() - offTimerStart)) / 1000;
|
unsigned int offSeconds = (m_switchOffDelay - (millis() - offTimerStart)) / 1000;
|
||||||
if (offSeconds >= 3600)
|
if (offSeconds >= 3600) {
|
||||||
{
|
|
||||||
uiDomString += (offSeconds / 3600);
|
uiDomString += (offSeconds / 3600);
|
||||||
uiDomString += F("h ");
|
uiDomString += F("h ");
|
||||||
offSeconds %= 3600;
|
offSeconds %= 3600;
|
||||||
}
|
}
|
||||||
if (offSeconds >= 60)
|
if (offSeconds >= 60) {
|
||||||
{
|
|
||||||
uiDomString += (offSeconds / 60);
|
uiDomString += (offSeconds / 60);
|
||||||
offSeconds %= 60;
|
offSeconds %= 60;
|
||||||
}
|
} else if (uiDomString.length() > 0) {
|
||||||
else if (uiDomString.length() > 0)
|
|
||||||
{
|
|
||||||
uiDomString += 0;
|
uiDomString += 0;
|
||||||
}
|
}
|
||||||
if (uiDomString.length() > 0)
|
if (uiDomString.length() > 0) {
|
||||||
{
|
|
||||||
uiDomString += F("min ");
|
uiDomString += F("min ");
|
||||||
}
|
}
|
||||||
uiDomString += (offSeconds);
|
uiDomString += (offSeconds);
|
||||||
infoArr.add(uiDomString + F("s"));
|
infoArr.add(uiDomString + F("s"));
|
||||||
} else {
|
} else {
|
||||||
infoArr.add(sensorPinState ? F("sensor on") : F("inactive"));
|
infoArr.add(state ? F("sensor on") : F("inactive"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
infoArr.add(F("disabled"));
|
infoArr.add(F("disabled"));
|
||||||
@ -446,9 +458,11 @@ void PIRsensorSwitch::addToJsonInfo(JsonObject &root)
|
|||||||
uiDomString += F("</button>");
|
uiDomString += F("</button>");
|
||||||
infoArr.add(uiDomString);
|
infoArr.add(uiDomString);
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
JsonObject sensor = root[F("sensor")];
|
JsonObject sensor = root[F("sensor")];
|
||||||
if (sensor.isNull()) sensor = root.createNestedObject(F("sensor"));
|
if (sensor.isNull()) sensor = root.createNestedObject(F("sensor"));
|
||||||
sensor[F("motion")] = sensorPinState || offTimerStart>0 ? true : false;
|
sensor[F("motion")] = state || offTimerStart>0 ? true : false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PIRsensorSwitch::onStateChange(uint8_t mode) {
|
void PIRsensorSwitch::onStateChange(uint8_t mode) {
|
||||||
@ -478,7 +492,8 @@ void PIRsensorSwitch::addToConfig(JsonObject &root)
|
|||||||
JsonObject top = root.createNestedObject(FPSTR(_name));
|
JsonObject top = root.createNestedObject(FPSTR(_name));
|
||||||
top[FPSTR(_enabled)] = enabled;
|
top[FPSTR(_enabled)] = enabled;
|
||||||
top[FPSTR(_switchOffDelay)] = m_switchOffDelay / 1000;
|
top[FPSTR(_switchOffDelay)] = m_switchOffDelay / 1000;
|
||||||
top["pin"] = PIRsensorPin;
|
JsonArray pinArray = top.createNestedArray("pin");
|
||||||
|
for (int i = 0; i < PIR_SENSOR_MAX_SENSORS; i++) pinArray.add(PIRsensorPin[i]);
|
||||||
top[FPSTR(_onPreset)] = m_onPreset;
|
top[FPSTR(_onPreset)] = m_onPreset;
|
||||||
top[FPSTR(_offPreset)] = m_offPreset;
|
top[FPSTR(_offPreset)] = m_offPreset;
|
||||||
top[FPSTR(_nightTime)] = m_nightTimeOnly;
|
top[FPSTR(_nightTime)] = m_nightTimeOnly;
|
||||||
@ -494,12 +509,20 @@ void PIRsensorSwitch::appendConfigData()
|
|||||||
{
|
{
|
||||||
oappend(SET_F("addInfo('PIRsensorSwitch:HA-discovery',1,'HA=Home Assistant');")); // 0 is field type, 1 is actual field
|
oappend(SET_F("addInfo('PIRsensorSwitch:HA-discovery',1,'HA=Home Assistant');")); // 0 is field type, 1 is actual field
|
||||||
oappend(SET_F("addInfo('PIRsensorSwitch:override',1,'Cancel timer on change');")); // 0 is field type, 1 is actual field
|
oappend(SET_F("addInfo('PIRsensorSwitch:override',1,'Cancel timer on change');")); // 0 is field type, 1 is actual field
|
||||||
|
for (int i = 0; i < PIR_SENSOR_MAX_SENSORS; i++) {
|
||||||
|
char str[128];
|
||||||
|
sprintf_P(str, PSTR("addInfo('PIRsensorSwitch:pin[]',%d,'','#%d');"), i, i);
|
||||||
|
oappend(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PIRsensorSwitch::readFromConfig(JsonObject &root)
|
bool PIRsensorSwitch::readFromConfig(JsonObject &root)
|
||||||
{
|
{
|
||||||
bool oldEnabled = enabled;
|
int8_t oldPin[PIR_SENSOR_MAX_SENSORS];
|
||||||
int8_t oldPin = PIRsensorPin;
|
for (int i = 0; i < PIR_SENSOR_MAX_SENSORS; i++) {
|
||||||
|
oldPin[i] = PIRsensorPin[i];
|
||||||
|
PIRsensorPin[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG_PRINT(FPSTR(_name));
|
DEBUG_PRINT(FPSTR(_name));
|
||||||
JsonObject top = root[FPSTR(_name)];
|
JsonObject top = root[FPSTR(_name)];
|
||||||
@ -508,7 +531,13 @@ bool PIRsensorSwitch::readFromConfig(JsonObject &root)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PIRsensorPin = top["pin"] | PIRsensorPin;
|
JsonArray pins = top["pin"];
|
||||||
|
if (!pins.isNull()) {
|
||||||
|
for (size_t i = 0; i < PIR_SENSOR_MAX_SENSORS; i++)
|
||||||
|
if (i < pins.size()) PIRsensorPin[i] = pins[i] | PIRsensorPin[i];
|
||||||
|
} else {
|
||||||
|
PIRsensorPin[0] = top["pin"] | oldPin[0];
|
||||||
|
}
|
||||||
|
|
||||||
enabled = top[FPSTR(_enabled)] | enabled;
|
enabled = top[FPSTR(_enabled)] | enabled;
|
||||||
|
|
||||||
@ -530,26 +559,11 @@ bool PIRsensorSwitch::readFromConfig(JsonObject &root)
|
|||||||
// reading config prior to setup()
|
// reading config prior to setup()
|
||||||
DEBUG_PRINTLN(F(" config loaded."));
|
DEBUG_PRINTLN(F(" config loaded."));
|
||||||
} else {
|
} else {
|
||||||
if (oldPin != PIRsensorPin || oldEnabled != enabled) {
|
for (int i = 0; i < PIR_SENSOR_MAX_SENSORS; i++)
|
||||||
// check if pin is OK
|
if (oldPin[i] >= 0) pinManager.deallocatePin(oldPin[i], PinOwner::UM_PIR);
|
||||||
if (oldPin != PIRsensorPin && oldPin >= 0) {
|
setup();
|
||||||
// if we are changing pin in settings page
|
|
||||||
// deallocate old pin
|
|
||||||
pinManager.deallocatePin(oldPin, PinOwner::UM_PIR);
|
|
||||||
if (pinManager.allocatePin(PIRsensorPin, false, PinOwner::UM_PIR)) {
|
|
||||||
pinMode(PIRsensorPin, INPUT_PULLUP);
|
|
||||||
} else {
|
|
||||||
// allocation failed
|
|
||||||
PIRsensorPin = -1;
|
|
||||||
enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (enabled) {
|
|
||||||
sensorPinState = digitalRead(PIRsensorPin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DEBUG_PRINTLN(F(" config (re)loaded."));
|
DEBUG_PRINTLN(F(" config (re)loaded."));
|
||||||
}
|
}
|
||||||
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
||||||
return !top[FPSTR(_domoticzIDX)].isNull();
|
return !(pins.isNull() || pins.size() != PIR_SENSOR_MAX_SENSORS);
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,11 @@ static uint8_t audioSyncEnabled = 0; // bit field: bit 0 - send, bit 1
|
|||||||
static bool udpSyncConnected = false; // UDP connection status -> true if connected to multicast group
|
static bool udpSyncConnected = false; // UDP connection status -> true if connected to multicast group
|
||||||
|
|
||||||
// user settable parameters for limitSoundDynamics()
|
// user settable parameters for limitSoundDynamics()
|
||||||
static bool limiterOn = true; // bool: enable / disable dynamics limiter
|
#ifdef UM_AUDIOREACTIVE_DYNAMICS_LIMITER_OFF
|
||||||
|
static bool limiterOn = false; // bool: enable / disable dynamics limiter
|
||||||
|
#else
|
||||||
|
static bool limiterOn = true;
|
||||||
|
#endif
|
||||||
static uint16_t attackTime = 80; // int: attack time in milliseconds. Default 0.08sec
|
static uint16_t attackTime = 80; // int: attack time in milliseconds. Default 0.08sec
|
||||||
static uint16_t decayTime = 1400; // int: decay time in milliseconds. Default 1.40sec
|
static uint16_t decayTime = 1400; // int: decay time in milliseconds. Default 1.40sec
|
||||||
// user settable options for FFTResult scaling
|
// user settable options for FFTResult scaling
|
||||||
@ -614,7 +618,12 @@ class AudioReactive : public Usermod {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer)
|
// set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer)
|
||||||
|
#ifdef UM_AUDIOREACTIVE_ENABLE
|
||||||
|
bool enabled = true;
|
||||||
|
#else
|
||||||
bool enabled = false;
|
bool enabled = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool initDone = false;
|
bool initDone = false;
|
||||||
bool addPalettes = false;
|
bool addPalettes = false;
|
||||||
int8_t palettes = 0;
|
int8_t palettes = 0;
|
||||||
|
@ -55,6 +55,11 @@ If you want to define default GPIOs during compile time, use the following (defa
|
|||||||
- `-D ES7243_SDAPIN` : GPIO for I2C SDA pin on ES7243 microphone (-1)
|
- `-D ES7243_SDAPIN` : GPIO for I2C SDA pin on ES7243 microphone (-1)
|
||||||
- `-D ES7243_SCLPIN` : GPIO for I2C SCL pin on ES7243 microphone (-1)
|
- `-D ES7243_SCLPIN` : GPIO for I2C SCL pin on ES7243 microphone (-1)
|
||||||
|
|
||||||
|
Other options:
|
||||||
|
|
||||||
|
- `-D UM_AUDIOREACTIVE_ENABLE` : makes usermod default enabled (not the same as include into build option!)
|
||||||
|
- `-D UM_AUDIOREACTIVE_DYNAMICS_LIMITER_OFF` : disables rise/fall limiter default
|
||||||
|
|
||||||
**NOTE** I2S is used for analog audio sampling. Hence, the analog *buttons* (i.e. potentiometers) are disabled when running this usermod with an analog microphone.
|
**NOTE** I2S is used for analog audio sampling. Hence, the analog *buttons* (i.e. potentiometers) are disabled when running this usermod with an analog microphone.
|
||||||
|
|
||||||
### Advanced Compile-Time Options
|
### Advanced Compile-Time Options
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
# I2C 4 Line Display Usermod
|
|
||||||
|
|
||||||
First, thanks to the authors of the ssd11306_i2c_oled_u8g2 mod.
|
|
||||||
|
|
||||||
Provides a four line display using either
|
|
||||||
128x32 or 128x64 OLED displays.
|
|
||||||
It can operate independently, but starts to provide
|
|
||||||
a relatively complete on-device UI when paired with the
|
|
||||||
Rotary Encoder UI usermod. I strongly encourage you to use
|
|
||||||
them together.
|
|
||||||
|
|
||||||
[See the pair of usermods in action](https://www.youtube.com/watch?v=tITQY80rIOA)
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
Copy and update the example `platformio_override.ini.sample`
|
|
||||||
from the Rotary Encoder UI usermode folder to the root directory of your particular build.
|
|
||||||
This file should be placed in the same directory as `platformio.ini`.
|
|
||||||
|
|
||||||
### Define Your Options
|
|
||||||
|
|
||||||
* `USERMOD_FOUR_LINE_DISPLAY` - define this to have this mod included wled00\usermods_list.cpp - also tells Rotary Encoder usermod, if installed, the display is available
|
|
||||||
* `FLD_PIN_SCL` - The display SCL pin, defaults to 5
|
|
||||||
* `FLD_PIN_SDA` - The display SDA pin, defaults to 4
|
|
||||||
|
|
||||||
All of the parameters can be configured via the Usermods settings page, inluding GPIO pins.
|
|
||||||
|
|
||||||
### PlatformIO requirements
|
|
||||||
|
|
||||||
This usermod requires the `U8g2` and `Wire` libraries. See the
|
|
||||||
`platformio_override.ini.sample` found in the Rotary Encoder
|
|
||||||
UI usermod folder for how to include these using `platformio_override.ini`.
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
* `enabled` - enable/disable usermod
|
|
||||||
* `pin` - GPIO pins used for display; I2C displays use Clk & Data; SPI displays can use SCK, MOSI, CS, DC & RST
|
|
||||||
* `type` - display type in numeric format
|
|
||||||
* 1 = I2C SSD1306 128x32
|
|
||||||
* 2 = I2C SH1106 128x32
|
|
||||||
* 3 = I2C SSD1306 128x64 (4 double-height lines)
|
|
||||||
* 4 = I2C SSD1305 128x32
|
|
||||||
* 5 = I2C SSD1305 128x64 (4 double-height lines)
|
|
||||||
* 6 = SPI SSD1306 128x32
|
|
||||||
* 7 = SPI SSD1306 128x64 (4 double-height lines)
|
|
||||||
* `contrast` - set display contrast (higher contrast may reduce display lifetime)
|
|
||||||
* `refreshRateSec` - display refresh time in seconds
|
|
||||||
* `screenTimeOutSec` - screen saver time-out in seconds
|
|
||||||
* `flip` - flip/rotate display 180°
|
|
||||||
* `sleepMode` - enable/disable screen saver
|
|
||||||
* `clockMode` - enable/disable clock display in screen saver mode
|
|
||||||
* `i2c-freq-kHz` - I2C clock frequency in kHz (may help reduce dropped frames, range: 400-3400)
|
|
||||||
|
|
||||||
## Change Log
|
|
||||||
|
|
||||||
2021-02
|
|
||||||
* First public release
|
|
||||||
|
|
||||||
2021-04
|
|
||||||
* Adaptation for runtime configuration.
|
|
||||||
|
|
||||||
2021-11
|
|
||||||
* Added configuration option description.
|
|
@ -1,742 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "wled.h"
|
|
||||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
|
||||||
|
|
||||||
//
|
|
||||||
// Insired by the v1 usermod: ssd1306_i2c_oled_u8g2
|
|
||||||
//
|
|
||||||
// v2 usermod for using 128x32 or 128x64 i2c
|
|
||||||
// OLED displays to provide a four line display
|
|
||||||
// for WLED.
|
|
||||||
//
|
|
||||||
// Dependencies
|
|
||||||
// * This usermod REQURES the ModeSortUsermod
|
|
||||||
// * This Usermod works best, by far, when coupled
|
|
||||||
// with RotaryEncoderUIUsermod.
|
|
||||||
//
|
|
||||||
// Make sure to enable NTP and set your time zone in WLED Config | Time.
|
|
||||||
//
|
|
||||||
// REQUIREMENT: You must add the following requirements to
|
|
||||||
// REQUIREMENT: "lib_deps" within platformio.ini / platformio_override.ini
|
|
||||||
// REQUIREMENT: * U8g2 (the version already in platformio.ini is fine)
|
|
||||||
// REQUIREMENT: * Wire
|
|
||||||
//
|
|
||||||
|
|
||||||
//The SCL and SDA pins are defined here.
|
|
||||||
#ifndef FLD_PIN_SCL
|
|
||||||
#define FLD_PIN_SCL i2c_scl
|
|
||||||
#endif
|
|
||||||
#ifndef FLD_PIN_SDA
|
|
||||||
#define FLD_PIN_SDA i2c_sda
|
|
||||||
#endif
|
|
||||||
#ifndef FLD_PIN_CLOCKSPI
|
|
||||||
#define FLD_PIN_CLOCKSPI spi_sclk
|
|
||||||
#endif
|
|
||||||
#ifndef FLD_PIN_DATASPI
|
|
||||||
#define FLD_PIN_DATASPI spi_mosi
|
|
||||||
#endif
|
|
||||||
#ifndef FLD_PIN_CS
|
|
||||||
#define FLD_PIN_CS spi_cs
|
|
||||||
#endif
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
#ifndef FLD_PIN_DC
|
|
||||||
#define FLD_PIN_DC 19
|
|
||||||
#endif
|
|
||||||
#ifndef FLD_PIN_RESET
|
|
||||||
#define FLD_PIN_RESET 26
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
#ifndef FLD_PIN_DC
|
|
||||||
#define FLD_PIN_DC 12
|
|
||||||
#endif
|
|
||||||
#ifndef FLD_PIN_RESET
|
|
||||||
#define FLD_PIN_RESET 16
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FLD_TYPE
|
|
||||||
#ifndef FLD_SPI_DEFAULT
|
|
||||||
#define FLD_TYPE SSD1306
|
|
||||||
#else
|
|
||||||
#define FLD_TYPE SSD1306_SPI
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// When to time out to the clock or blank the screen
|
|
||||||
// if SLEEP_MODE_ENABLED.
|
|
||||||
#define SCREEN_TIMEOUT_MS 60*1000 // 1 min
|
|
||||||
|
|
||||||
#define TIME_INDENT 0
|
|
||||||
#define DATE_INDENT 2
|
|
||||||
|
|
||||||
// Minimum time between redrawing screen in ms
|
|
||||||
#define USER_LOOP_REFRESH_RATE_MS 1000
|
|
||||||
|
|
||||||
// Extra char (+1) for null
|
|
||||||
#define LINE_BUFFER_SIZE 16+1
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
FLD_LINE_BRIGHTNESS = 0,
|
|
||||||
FLD_LINE_EFFECT_SPEED,
|
|
||||||
FLD_LINE_EFFECT_INTENSITY,
|
|
||||||
FLD_LINE_MODE,
|
|
||||||
FLD_LINE_PALETTE,
|
|
||||||
FLD_LINE_TIME
|
|
||||||
} Line4Type;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
NONE = 0,
|
|
||||||
SSD1306, // U8X8_SSD1306_128X32_UNIVISION_HW_I2C
|
|
||||||
SH1106, // U8X8_SH1106_128X64_WINSTAR_HW_I2C
|
|
||||||
SSD1306_64, // U8X8_SSD1306_128X64_NONAME_HW_I2C
|
|
||||||
SSD1305, // U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C
|
|
||||||
SSD1305_64, // U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C
|
|
||||||
SSD1306_SPI, // U8X8_SSD1306_128X32_NONAME_HW_SPI
|
|
||||||
SSD1306_SPI64 // U8X8_SSD1306_128X64_NONAME_HW_SPI
|
|
||||||
} DisplayType;
|
|
||||||
|
|
||||||
class FourLineDisplayUsermod : public Usermod {
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool initDone = false;
|
|
||||||
unsigned long lastTime = 0;
|
|
||||||
|
|
||||||
// HW interface & configuration
|
|
||||||
U8X8 *u8x8 = nullptr; // pointer to U8X8 display object
|
|
||||||
#ifndef FLD_SPI_DEFAULT
|
|
||||||
int8_t ioPin[5] = {FLD_PIN_SCL, FLD_PIN_SDA, -1, -1, -1}; // I2C pins: SCL, SDA
|
|
||||||
uint32_t ioFrequency = 400000; // in Hz (minimum is 100000, baseline is 400000 and maximum should be 3400000)
|
|
||||||
#else
|
|
||||||
int8_t ioPin[5] = {FLD_PIN_CLOCKSPI, FLD_PIN_DATASPI, FLD_PIN_CS, FLD_PIN_DC, FLD_PIN_RESET}; // SPI pins: CLK, MOSI, CS, DC, RST
|
|
||||||
uint32_t ioFrequency = 1000000; // in Hz (minimum is 500kHz, baseline is 1MHz and maximum should be 20MHz)
|
|
||||||
#endif
|
|
||||||
DisplayType type = FLD_TYPE; // display type
|
|
||||||
bool flip = false; // flip display 180°
|
|
||||||
uint8_t contrast = 10; // screen contrast
|
|
||||||
uint8_t lineHeight = 1; // 1 row or 2 rows
|
|
||||||
uint32_t refreshRate = USER_LOOP_REFRESH_RATE_MS; // in ms
|
|
||||||
uint32_t screenTimeout = SCREEN_TIMEOUT_MS; // in ms
|
|
||||||
bool sleepMode = true; // allow screen sleep?
|
|
||||||
bool clockMode = false; // display clock
|
|
||||||
bool enabled = true;
|
|
||||||
|
|
||||||
// Next variables hold the previous known values to determine if redraw is
|
|
||||||
// required.
|
|
||||||
String knownSsid = "";
|
|
||||||
IPAddress knownIp;
|
|
||||||
uint8_t knownBrightness = 0;
|
|
||||||
uint8_t knownEffectSpeed = 0;
|
|
||||||
uint8_t knownEffectIntensity = 0;
|
|
||||||
uint8_t knownMode = 0;
|
|
||||||
uint8_t knownPalette = 0;
|
|
||||||
uint8_t knownMinute = 99;
|
|
||||||
uint8_t knownHour = 99;
|
|
||||||
|
|
||||||
bool displayTurnedOff = false;
|
|
||||||
unsigned long lastUpdate = 0;
|
|
||||||
unsigned long lastRedraw = 0;
|
|
||||||
unsigned long overlayUntil = 0;
|
|
||||||
Line4Type lineType = FLD_LINE_BRIGHTNESS;
|
|
||||||
// Set to 2 or 3 to mark lines 2 or 3. Other values ignored.
|
|
||||||
byte markLineNum = 0;
|
|
||||||
|
|
||||||
// strings to reduce flash memory usage (used more than twice)
|
|
||||||
static const char _name[];
|
|
||||||
static const char _enabled[];
|
|
||||||
static const char _contrast[];
|
|
||||||
static const char _refreshRate[];
|
|
||||||
static const char _screenTimeOut[];
|
|
||||||
static const char _flip[];
|
|
||||||
static const char _sleepMode[];
|
|
||||||
static const char _clockMode[];
|
|
||||||
static const char _busClkFrequency[];
|
|
||||||
|
|
||||||
// If display does not work or looks corrupted check the
|
|
||||||
// constructor reference:
|
|
||||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
|
||||||
// or check the gallery:
|
|
||||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
// gets called once at boot. Do all initialization that doesn't depend on
|
|
||||||
// network here
|
|
||||||
void setup() {
|
|
||||||
if (type == NONE || !enabled) return;
|
|
||||||
|
|
||||||
bool isHW;
|
|
||||||
PinOwner po = PinOwner::UM_FourLineDisplay;
|
|
||||||
if (type == SSD1306_SPI || type == SSD1306_SPI64) {
|
|
||||||
isHW = (ioPin[0]==spi_sclk && ioPin[1]==spi_mosi);
|
|
||||||
if (isHW) po = PinOwner::HW_SPI; // allow multiple allocations of HW I2C bus pins
|
|
||||||
PinManagerPinType pins[5] = { { ioPin[0], true }, { ioPin[1], true }, { ioPin[2], true }, { ioPin[3], true }, { ioPin[4], true }};
|
|
||||||
if (!pinManager.allocateMultiplePins(pins, 5, po)) { type=NONE; return; }
|
|
||||||
} else {
|
|
||||||
isHW = (ioPin[0]==i2c_scl && ioPin[1]==i2c_sda);
|
|
||||||
if (isHW) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
|
||||||
PinManagerPinType pins[2] = { { ioPin[0], true }, { ioPin[1], true } };
|
|
||||||
if (!pinManager.allocateMultiplePins(pins, 2, po)) { type=NONE; return; }
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_PRINTLN(F("Allocating display."));
|
|
||||||
switch (type) {
|
|
||||||
case SSD1306:
|
|
||||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
|
||||||
else u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
|
||||||
lineHeight = 1;
|
|
||||||
break;
|
|
||||||
case SH1106:
|
|
||||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
|
||||||
else u8x8 = (U8X8 *) new U8X8_SH1106_128X64_WINSTAR_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
|
||||||
lineHeight = 2;
|
|
||||||
break;
|
|
||||||
case SSD1306_64:
|
|
||||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
|
||||||
else u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
|
||||||
lineHeight = 2;
|
|
||||||
break;
|
|
||||||
case SSD1305:
|
|
||||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_NONAME_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
|
||||||
else u8x8 = (U8X8 *) new U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
|
||||||
lineHeight = 1;
|
|
||||||
break;
|
|
||||||
case SSD1305_64:
|
|
||||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_SW_I2C(ioPin[0], ioPin[1]); // SCL, SDA, reset
|
|
||||||
else u8x8 = (U8X8 *) new U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C(U8X8_PIN_NONE, ioPin[0], ioPin[1]); // Pins are Reset, SCL, SDA
|
|
||||||
lineHeight = 2;
|
|
||||||
break;
|
|
||||||
case SSD1306_SPI:
|
|
||||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_SW_SPI(ioPin[0], ioPin[1], ioPin[2], ioPin[3], ioPin[4]);
|
|
||||||
else u8x8 = (U8X8 *) new U8X8_SSD1306_128X32_UNIVISION_4W_HW_SPI(ioPin[2], ioPin[3], ioPin[4]); // Pins are cs, dc, reset
|
|
||||||
lineHeight = 1;
|
|
||||||
break;
|
|
||||||
case SSD1306_SPI64:
|
|
||||||
if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_SW_SPI(ioPin[0], ioPin[1], ioPin[2], ioPin[3], ioPin[4]);
|
|
||||||
else u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_HW_SPI(ioPin[2], ioPin[3], ioPin[4]); // Pins are cs, dc, reset
|
|
||||||
lineHeight = 2;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
u8x8 = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nullptr == u8x8) {
|
|
||||||
DEBUG_PRINTLN(F("Display init failed."));
|
|
||||||
pinManager.deallocateMultiplePins((const uint8_t*)ioPin, (type == SSD1306_SPI || type == SSD1306_SPI64) ? 5 : 2, po);
|
|
||||||
type = NONE;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
initDone = true;
|
|
||||||
DEBUG_PRINTLN(F("Starting display."));
|
|
||||||
/*if (!(type == SSD1306_SPI || type == SSD1306_SPI64))*/ u8x8->setBusClock(ioFrequency); // can be used for SPI too
|
|
||||||
u8x8->begin();
|
|
||||||
setFlipMode(flip);
|
|
||||||
setContrast(contrast); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
|
||||||
setPowerSave(0);
|
|
||||||
drawString(0, 0, "Loading...");
|
|
||||||
}
|
|
||||||
|
|
||||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
|
||||||
// interfaces here
|
|
||||||
void connected() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Da loop.
|
|
||||||
*/
|
|
||||||
void loop() {
|
|
||||||
if (!enabled || millis() - lastUpdate < (clockMode?1000:refreshRate) || strip.isUpdating()) return;
|
|
||||||
lastUpdate = millis();
|
|
||||||
|
|
||||||
redraw(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrappers for screen drawing
|
|
||||||
*/
|
|
||||||
void setFlipMode(uint8_t mode) {
|
|
||||||
if (type == NONE || !enabled) return;
|
|
||||||
u8x8->setFlipMode(mode);
|
|
||||||
}
|
|
||||||
void setContrast(uint8_t contrast) {
|
|
||||||
if (type == NONE || !enabled) return;
|
|
||||||
u8x8->setContrast(contrast);
|
|
||||||
}
|
|
||||||
void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false) {
|
|
||||||
if (type == NONE || !enabled) return;
|
|
||||||
u8x8->setFont(u8x8_font_chroma48medium8_r);
|
|
||||||
if (!ignoreLH && lineHeight==2) u8x8->draw1x2String(col, row, string);
|
|
||||||
else u8x8->drawString(col, row, string);
|
|
||||||
}
|
|
||||||
void draw2x2String(uint8_t col, uint8_t row, const char *string) {
|
|
||||||
if (type == NONE || !enabled) return;
|
|
||||||
u8x8->setFont(u8x8_font_chroma48medium8_r);
|
|
||||||
u8x8->draw2x2String(col, row, string);
|
|
||||||
}
|
|
||||||
void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false) {
|
|
||||||
if (type == NONE || !enabled) return;
|
|
||||||
u8x8->setFont(font);
|
|
||||||
if (!ignoreLH && lineHeight==2) u8x8->draw1x2Glyph(col, row, glyph);
|
|
||||||
else u8x8->drawGlyph(col, row, glyph);
|
|
||||||
}
|
|
||||||
uint8_t getCols() {
|
|
||||||
if (type==NONE || !enabled) return 0;
|
|
||||||
return u8x8->getCols();
|
|
||||||
}
|
|
||||||
void clear() {
|
|
||||||
if (type == NONE || !enabled) return;
|
|
||||||
u8x8->clear();
|
|
||||||
}
|
|
||||||
void setPowerSave(uint8_t save) {
|
|
||||||
if (type == NONE || !enabled) return;
|
|
||||||
u8x8->setPowerSave(save);
|
|
||||||
}
|
|
||||||
|
|
||||||
void center(String &line, uint8_t width) {
|
|
||||||
int len = line.length();
|
|
||||||
if (len<width) for (byte i=(width-len)/2; i>0; i--) line = ' ' + line;
|
|
||||||
for (byte i=line.length(); i<width; i++) line += ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redraw the screen (but only if things have changed
|
|
||||||
* or if forceRedraw).
|
|
||||||
*/
|
|
||||||
void redraw(bool forceRedraw) {
|
|
||||||
static bool showName = false;
|
|
||||||
unsigned long now = millis();
|
|
||||||
|
|
||||||
if (type == NONE || !enabled) return;
|
|
||||||
if (overlayUntil > 0) {
|
|
||||||
if (now >= overlayUntil) {
|
|
||||||
// Time to display the overlay has elapsed.
|
|
||||||
overlayUntil = 0;
|
|
||||||
forceRedraw = true;
|
|
||||||
} else {
|
|
||||||
// We are still displaying the overlay
|
|
||||||
// Don't redraw.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if values which are shown on display changed from the last time.
|
|
||||||
if (forceRedraw ||
|
|
||||||
(((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) ||
|
|
||||||
(knownIp != (apActive ? IPAddress(4, 3, 2, 1) : Network.localIP())) ||
|
|
||||||
(knownBrightness != bri) ||
|
|
||||||
(knownEffectSpeed != effectSpeed) ||
|
|
||||||
(knownEffectIntensity != effectIntensity) ||
|
|
||||||
(knownMode != strip.getMainSegment().mode) ||
|
|
||||||
(knownPalette != strip.getMainSegment().palette)) {
|
|
||||||
knownHour = 99; // force time update
|
|
||||||
lastRedraw = now; // update lastRedraw marker
|
|
||||||
} else if (sleepMode && !displayTurnedOff && ((now - lastRedraw)/1000)%5 == 0) {
|
|
||||||
// change line every 5s
|
|
||||||
showName = !showName;
|
|
||||||
switch (lineType) {
|
|
||||||
case FLD_LINE_BRIGHTNESS:
|
|
||||||
lineType = FLD_LINE_EFFECT_SPEED;
|
|
||||||
break;
|
|
||||||
case FLD_LINE_MODE:
|
|
||||||
lineType = FLD_LINE_BRIGHTNESS;
|
|
||||||
break;
|
|
||||||
case FLD_LINE_PALETTE:
|
|
||||||
lineType = clockMode ? FLD_LINE_MODE : FLD_LINE_BRIGHTNESS;
|
|
||||||
break;
|
|
||||||
case FLD_LINE_EFFECT_SPEED:
|
|
||||||
lineType = FLD_LINE_EFFECT_INTENSITY;
|
|
||||||
break;
|
|
||||||
case FLD_LINE_EFFECT_INTENSITY:
|
|
||||||
lineType = FLD_LINE_PALETTE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
lineType = FLD_LINE_MODE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
knownHour = 99; // force time update
|
|
||||||
// do not update lastRedraw marker if just switching row contenet
|
|
||||||
} else {
|
|
||||||
// Nothing to change.
|
|
||||||
// Turn off display after 3 minutes with no change.
|
|
||||||
if(sleepMode && !displayTurnedOff && (millis() - lastRedraw > screenTimeout)) {
|
|
||||||
// We will still check if there is a change in redraw()
|
|
||||||
// and turn it back on if it changed.
|
|
||||||
sleepOrClock(true);
|
|
||||||
} else if (displayTurnedOff && clockMode) {
|
|
||||||
showTime();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turn the display back on
|
|
||||||
if (displayTurnedOff) sleepOrClock(false);
|
|
||||||
|
|
||||||
// Update last known values.
|
|
||||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
|
||||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : Network.localIP();
|
|
||||||
knownBrightness = bri;
|
|
||||||
knownMode = strip.getMainSegment().mode;
|
|
||||||
knownPalette = strip.getMainSegment().palette;
|
|
||||||
knownEffectSpeed = effectSpeed;
|
|
||||||
knownEffectIntensity = effectIntensity;
|
|
||||||
|
|
||||||
// Do the actual drawing
|
|
||||||
String line;
|
|
||||||
// First row with Wifi name
|
|
||||||
drawGlyph(0, 0, 80, u8x8_font_open_iconic_embedded_1x1); // home icon
|
|
||||||
line = knownSsid.substring(0, getCols() > 1 ? getCols() - 2 : 0);
|
|
||||||
center(line, getCols()-2);
|
|
||||||
drawString(1, 0, line.c_str());
|
|
||||||
// Print `~` char to indicate that SSID is longer, than our display
|
|
||||||
if (knownSsid.length() > (int)getCols()-1) {
|
|
||||||
drawString(getCols() - 1, 0, "~");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second row with IP or Psssword
|
|
||||||
drawGlyph(0, lineHeight, 68, u8x8_font_open_iconic_embedded_1x1); // wifi icon
|
|
||||||
// Print password in AP mode and if led is OFF.
|
|
||||||
if (apActive && bri == 0) {
|
|
||||||
drawString(1, lineHeight, apPass);
|
|
||||||
} else {
|
|
||||||
// alternate IP address and server name
|
|
||||||
line = knownIp.toString();
|
|
||||||
if (showName && strcmp(serverDescription, "WLED") != 0) {
|
|
||||||
line = serverDescription;
|
|
||||||
}
|
|
||||||
center(line, getCols()-1);
|
|
||||||
drawString(1, lineHeight, line.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw third and fourth row
|
|
||||||
drawLine(2, clockMode ? lineType : FLD_LINE_MODE);
|
|
||||||
drawLine(3, clockMode ? FLD_LINE_TIME : lineType);
|
|
||||||
|
|
||||||
drawGlyph(0, 2*lineHeight, 66 + (bri > 0 ? 3 : 0), u8x8_font_open_iconic_weather_2x2); // sun/moon icon
|
|
||||||
//if (markLineNum>1) drawGlyph(2, markLineNum*lineHeight, 66, u8x8_font_open_iconic_arrow_1x1); // arrow icon
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawLine(uint8_t line, Line4Type lineType) {
|
|
||||||
char lineBuffer[LINE_BUFFER_SIZE];
|
|
||||||
uint8_t printedChars;
|
|
||||||
switch(lineType) {
|
|
||||||
case FLD_LINE_BRIGHTNESS:
|
|
||||||
sprintf_P(lineBuffer, PSTR("Brightness %3d"), bri);
|
|
||||||
drawString(2, line*lineHeight, lineBuffer);
|
|
||||||
break;
|
|
||||||
case FLD_LINE_EFFECT_SPEED:
|
|
||||||
sprintf_P(lineBuffer, PSTR("FX Speed %3d"), effectSpeed);
|
|
||||||
drawString(2, line*lineHeight, lineBuffer);
|
|
||||||
break;
|
|
||||||
case FLD_LINE_EFFECT_INTENSITY:
|
|
||||||
sprintf_P(lineBuffer, PSTR("FX Intens. %3d"), effectIntensity);
|
|
||||||
drawString(2, line*lineHeight, lineBuffer);
|
|
||||||
break;
|
|
||||||
case FLD_LINE_MODE:
|
|
||||||
printedChars = extractModeName(knownMode, JSON_mode_names, lineBuffer, LINE_BUFFER_SIZE-1);
|
|
||||||
for (;printedChars < getCols()-2 && printedChars < LINE_BUFFER_SIZE-3; printedChars++) lineBuffer[printedChars]=' ';
|
|
||||||
lineBuffer[printedChars] = 0;
|
|
||||||
drawString(2, line*lineHeight, lineBuffer);
|
|
||||||
break;
|
|
||||||
case FLD_LINE_PALETTE:
|
|
||||||
printedChars = extractModeName(knownPalette, JSON_palette_names, lineBuffer, LINE_BUFFER_SIZE-1);
|
|
||||||
for (;printedChars < getCols()-2 && printedChars < LINE_BUFFER_SIZE-3; printedChars++) lineBuffer[printedChars]=' ';
|
|
||||||
lineBuffer[printedChars] = 0;
|
|
||||||
drawString(2, line*lineHeight, lineBuffer);
|
|
||||||
break;
|
|
||||||
case FLD_LINE_TIME:
|
|
||||||
default:
|
|
||||||
showTime(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If there screen is off or in clock is displayed,
|
|
||||||
* this will return true. This allows us to throw away
|
|
||||||
* the first input from the rotary encoder but
|
|
||||||
* to wake up the screen.
|
|
||||||
*/
|
|
||||||
bool wakeDisplay() {
|
|
||||||
if (type == NONE || !enabled) return false;
|
|
||||||
knownHour = 99;
|
|
||||||
if (displayTurnedOff) {
|
|
||||||
// Turn the display back on
|
|
||||||
sleepOrClock(false);
|
|
||||||
redraw(true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows you to show up to two lines as overlay for a
|
|
||||||
* period of time.
|
|
||||||
* Clears the screen and prints on the middle two lines.
|
|
||||||
*/
|
|
||||||
void overlay(const char* line1, const char *line2, long showHowLong) {
|
|
||||||
if (type == NONE || !enabled) return;
|
|
||||||
|
|
||||||
if (displayTurnedOff) {
|
|
||||||
// Turn the display back on (includes clear())
|
|
||||||
sleepOrClock(false);
|
|
||||||
} else {
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print the overlay
|
|
||||||
if (line1) {
|
|
||||||
String buf = line1;
|
|
||||||
center(buf, getCols());
|
|
||||||
drawString(0, 1*lineHeight, buf.c_str());
|
|
||||||
}
|
|
||||||
if (line2) {
|
|
||||||
String buf = line2;
|
|
||||||
center(buf, getCols());
|
|
||||||
drawString(0, 2*lineHeight, buf.c_str());
|
|
||||||
}
|
|
||||||
overlayUntil = millis() + showHowLong;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLineType(byte lT) {
|
|
||||||
lineType = (Line4Type) lT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Line 3 or 4 (last two lines) can be marked with an
|
|
||||||
* arrow in the first column. Pass 2 or 3 to this to
|
|
||||||
* specify which line to mark with an arrow.
|
|
||||||
* Any other values are ignored.
|
|
||||||
*/
|
|
||||||
void setMarkLine(byte newMarkLineNum) {
|
|
||||||
if (newMarkLineNum == 2 || newMarkLineNum == 3) {
|
|
||||||
markLineNum = newMarkLineNum;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
markLineNum = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable sleep (turn the display off) or clock mode.
|
|
||||||
*/
|
|
||||||
void sleepOrClock(bool enabled) {
|
|
||||||
clear();
|
|
||||||
if (enabled) {
|
|
||||||
if (clockMode) showTime();
|
|
||||||
else setPowerSave(1);
|
|
||||||
displayTurnedOff = true;
|
|
||||||
} else {
|
|
||||||
setPowerSave(0);
|
|
||||||
displayTurnedOff = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the current date and time in large characters
|
|
||||||
* on the middle rows. Based 24 or 12 hour depending on
|
|
||||||
* the useAMPM configuration.
|
|
||||||
*/
|
|
||||||
void showTime(bool fullScreen = true) {
|
|
||||||
if (type == NONE || !enabled) return;
|
|
||||||
char lineBuffer[LINE_BUFFER_SIZE];
|
|
||||||
|
|
||||||
updateLocalTime();
|
|
||||||
byte minuteCurrent = minute(localTime);
|
|
||||||
byte hourCurrent = hour(localTime);
|
|
||||||
byte secondCurrent = second(localTime);
|
|
||||||
if (knownMinute == minuteCurrent && knownHour == hourCurrent) {
|
|
||||||
// Time hasn't changed.
|
|
||||||
if (!fullScreen) return;
|
|
||||||
}
|
|
||||||
knownMinute = minuteCurrent;
|
|
||||||
knownHour = hourCurrent;
|
|
||||||
|
|
||||||
byte currentMonth = month(localTime);
|
|
||||||
sprintf_P(lineBuffer, PSTR("%s %2d "), monthShortStr(currentMonth), day(localTime));
|
|
||||||
if (fullScreen)
|
|
||||||
draw2x2String(DATE_INDENT, lineHeight==1 ? 0 : lineHeight, lineBuffer); // adjust for 8 line displays
|
|
||||||
else
|
|
||||||
drawString(2, lineHeight*3, lineBuffer);
|
|
||||||
|
|
||||||
byte showHour = hourCurrent;
|
|
||||||
boolean isAM = false;
|
|
||||||
if (useAMPM) {
|
|
||||||
if (showHour == 0) {
|
|
||||||
showHour = 12;
|
|
||||||
isAM = true;
|
|
||||||
}
|
|
||||||
else if (showHour > 12) {
|
|
||||||
showHour -= 12;
|
|
||||||
isAM = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
isAM = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf_P(lineBuffer, (secondCurrent%2 || !fullScreen) ? PSTR("%2d:%02d") : PSTR("%2d %02d"), (useAMPM ? showHour : hourCurrent), minuteCurrent);
|
|
||||||
// For time, we always use LINE_HEIGHT of 2 since
|
|
||||||
// we are printing it big.
|
|
||||||
if (fullScreen) {
|
|
||||||
draw2x2String(TIME_INDENT+2, lineHeight*2, lineBuffer);
|
|
||||||
sprintf_P(lineBuffer, PSTR("%02d"), secondCurrent);
|
|
||||||
if (useAMPM) drawString(12+(fullScreen?0:2), lineHeight*2, (isAM ? "AM" : "PM"), true);
|
|
||||||
else drawString(12, lineHeight*2+1, lineBuffer, true); // even with double sized rows print seconds in 1 line
|
|
||||||
} else {
|
|
||||||
drawString(9+(useAMPM?0:2), lineHeight*3, lineBuffer);
|
|
||||||
if (useAMPM) drawString(12+(fullScreen?0:2), lineHeight*3, (isAM ? "AM" : "PM"), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
|
||||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
|
||||||
* Below it is shown how this could be used for e.g. a light sensor
|
|
||||||
*/
|
|
||||||
//void addToJsonInfo(JsonObject& root) {
|
|
||||||
//JsonObject user = root["u"];
|
|
||||||
//if (user.isNull()) user = root.createNestedObject("u");
|
|
||||||
//JsonArray data = user.createNestedArray(F("4LineDisplay"));
|
|
||||||
//data.add(F("Loaded."));
|
|
||||||
//}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
|
||||||
* Values in the state object may be modified by connected clients
|
|
||||||
*/
|
|
||||||
//void addToJsonState(JsonObject& root) {
|
|
||||||
//}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
|
||||||
* Values in the state object may be modified by connected clients
|
|
||||||
*/
|
|
||||||
//void readFromJsonState(JsonObject& root) {
|
|
||||||
// if (!initDone) return; // prevent crash on boot applyPreset()
|
|
||||||
//}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
|
|
||||||
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
|
||||||
* If you want to force saving the current state, use serializeConfig() in your loop().
|
|
||||||
*
|
|
||||||
* CAUTION: serializeConfig() will initiate a filesystem write operation.
|
|
||||||
* It might cause the LEDs to stutter and will cause flash wear if called too often.
|
|
||||||
* Use it sparingly and always in the loop, never in network callbacks!
|
|
||||||
*
|
|
||||||
* addToConfig() will also not yet add your setting to one of the settings pages automatically.
|
|
||||||
* To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually.
|
|
||||||
*
|
|
||||||
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
|
||||||
*/
|
|
||||||
void addToConfig(JsonObject& root) {
|
|
||||||
JsonObject top = root.createNestedObject(FPSTR(_name));
|
|
||||||
top[FPSTR(_enabled)] = enabled;
|
|
||||||
JsonArray io_pin = top.createNestedArray("pin");
|
|
||||||
for (byte i=0; i<5; i++) io_pin.add(ioPin[i]);
|
|
||||||
top["help4Pins"] = F("Clk,Data,CS,DC,RST"); // help for Settings page
|
|
||||||
top["type"] = type;
|
|
||||||
top["help4Type"] = F("1=SSD1306,2=SH1106,3=SSD1306_128x64,4=SSD1305,5=SSD1305_128x64,6=SSD1306_SPI,7=SSD1306_SPI_128x64"); // help for Settings page
|
|
||||||
top[FPSTR(_flip)] = (bool) flip;
|
|
||||||
top[FPSTR(_contrast)] = contrast;
|
|
||||||
top[FPSTR(_refreshRate)] = refreshRate/1000;
|
|
||||||
top[FPSTR(_screenTimeOut)] = screenTimeout/1000;
|
|
||||||
top[FPSTR(_sleepMode)] = (bool) sleepMode;
|
|
||||||
top[FPSTR(_clockMode)] = (bool) clockMode;
|
|
||||||
top[FPSTR(_busClkFrequency)] = ioFrequency/1000;
|
|
||||||
DEBUG_PRINTLN(F("4 Line Display config saved."));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* readFromConfig() can be used to read back the custom settings you added with addToConfig().
|
|
||||||
* This is called by WLED when settings are loaded (currently this only happens once immediately after boot)
|
|
||||||
*
|
|
||||||
* readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes),
|
|
||||||
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
|
|
||||||
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
|
|
||||||
*/
|
|
||||||
bool readFromConfig(JsonObject& root) {
|
|
||||||
bool needsRedraw = false;
|
|
||||||
DisplayType newType = type;
|
|
||||||
int8_t newPin[5]; for (byte i=0; i<5; i++) newPin[i] = ioPin[i];
|
|
||||||
|
|
||||||
JsonObject top = root[FPSTR(_name)];
|
|
||||||
if (top.isNull()) {
|
|
||||||
DEBUG_PRINT(FPSTR(_name));
|
|
||||||
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
enabled = top[FPSTR(_enabled)] | enabled;
|
|
||||||
newType = top["type"] | newType;
|
|
||||||
for (byte i=0; i<5; i++) newPin[i] = top["pin"][i] | ioPin[i];
|
|
||||||
flip = top[FPSTR(_flip)] | flip;
|
|
||||||
contrast = top[FPSTR(_contrast)] | contrast;
|
|
||||||
refreshRate = (top[FPSTR(_refreshRate)] | refreshRate/1000) * 1000;
|
|
||||||
screenTimeout = (top[FPSTR(_screenTimeOut)] | screenTimeout/1000) * 1000;
|
|
||||||
sleepMode = top[FPSTR(_sleepMode)] | sleepMode;
|
|
||||||
clockMode = top[FPSTR(_clockMode)] | clockMode;
|
|
||||||
if (newType == SSD1306_SPI || newType == SSD1306_SPI64)
|
|
||||||
ioFrequency = min(20000, max(500, (int)(top[FPSTR(_busClkFrequency)] | ioFrequency/1000))) * 1000; // limit frequency
|
|
||||||
else
|
|
||||||
ioFrequency = min(3400, max(100, (int)(top[FPSTR(_busClkFrequency)] | ioFrequency/1000))) * 1000; // limit frequency
|
|
||||||
|
|
||||||
DEBUG_PRINT(FPSTR(_name));
|
|
||||||
if (!initDone) {
|
|
||||||
// first run: reading from cfg.json
|
|
||||||
for (byte i=0; i<5; i++) ioPin[i] = newPin[i];
|
|
||||||
type = newType;
|
|
||||||
DEBUG_PRINTLN(F(" config loaded."));
|
|
||||||
} else {
|
|
||||||
DEBUG_PRINTLN(F(" config (re)loaded."));
|
|
||||||
// changing parameters from settings page
|
|
||||||
bool pinsChanged = false;
|
|
||||||
for (byte i=0; i<5; i++) if (ioPin[i] != newPin[i]) { pinsChanged = true; break; }
|
|
||||||
if (pinsChanged || type!=newType) {
|
|
||||||
if (type != NONE) delete u8x8;
|
|
||||||
PinOwner po = PinOwner::UM_FourLineDisplay;
|
|
||||||
bool isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64);
|
|
||||||
if (isSPI) {
|
|
||||||
if (ioPin[0]==spi_sclk && ioPin[1]==spi_mosi) po = PinOwner::HW_SPI; // allow multiple allocations of HW SPI bus pins
|
|
||||||
pinManager.deallocateMultiplePins((const uint8_t *)ioPin, 5, po);
|
|
||||||
} else {
|
|
||||||
if (ioPin[0]==i2c_scl && ioPin[1]==i2c_sda) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
|
||||||
pinManager.deallocateMultiplePins((const uint8_t *)ioPin, 2, po);
|
|
||||||
}
|
|
||||||
for (byte i=0; i<5; i++) ioPin[i] = newPin[i];
|
|
||||||
if (ioPin[0]<0 || ioPin[1]<0) { // data & clock must be > -1
|
|
||||||
type = NONE;
|
|
||||||
return true;
|
|
||||||
} else type = newType;
|
|
||||||
setup();
|
|
||||||
needsRedraw |= true;
|
|
||||||
}
|
|
||||||
if (!(type == SSD1306_SPI || type == SSD1306_SPI64)) u8x8->setBusClock(ioFrequency); // can be used for SPI too
|
|
||||||
setContrast(contrast);
|
|
||||||
setFlipMode(flip);
|
|
||||||
if (needsRedraw && !wakeDisplay()) redraw(true);
|
|
||||||
}
|
|
||||||
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
|
||||||
return !top[FPSTR(_enabled)].isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
|
||||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
|
||||||
*/
|
|
||||||
uint16_t getId() {
|
|
||||||
return USERMOD_ID_FOUR_LINE_DISP;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// strings to reduce flash memory usage (used more than twice)
|
|
||||||
const char FourLineDisplayUsermod::_name[] PROGMEM = "4LineDisplay";
|
|
||||||
const char FourLineDisplayUsermod::_enabled[] PROGMEM = "enabled";
|
|
||||||
const char FourLineDisplayUsermod::_contrast[] PROGMEM = "contrast";
|
|
||||||
const char FourLineDisplayUsermod::_refreshRate[] PROGMEM = "refreshRateSec";
|
|
||||||
const char FourLineDisplayUsermod::_screenTimeOut[] PROGMEM = "screenTimeOutSec";
|
|
||||||
const char FourLineDisplayUsermod::_flip[] PROGMEM = "flip";
|
|
||||||
const char FourLineDisplayUsermod::_sleepMode[] PROGMEM = "sleepMode";
|
|
||||||
const char FourLineDisplayUsermod::_clockMode[] PROGMEM = "clockMode";
|
|
||||||
const char FourLineDisplayUsermod::_busClkFrequency[] PROGMEM = "i2c-freq-kHz";
|
|
@ -1,33 +0,0 @@
|
|||||||
# Mode Sort
|
|
||||||
|
|
||||||
v2 usermod that provides data about modes and
|
|
||||||
palettes to other usermods. Notably it provides:
|
|
||||||
* A direct method for a mode or palette name
|
|
||||||
* Ability to retrieve mode and palette names in
|
|
||||||
alphabetical order
|
|
||||||
|
|
||||||
```char **getModesQStrings()```
|
|
||||||
|
|
||||||
Provides a char* array (pointers) to the names of the
|
|
||||||
palettes contained in JSON_mode_names, in the same order as
|
|
||||||
JSON_mode_names. These strings end in double quote (")
|
|
||||||
(or \0 if there is a problem).
|
|
||||||
|
|
||||||
```byte *getModesAlphaIndexes()```
|
|
||||||
|
|
||||||
A byte array designating the indexes of names of the
|
|
||||||
modes in alphabetical order. "Solid" will always remain
|
|
||||||
at the top of the list.
|
|
||||||
|
|
||||||
```char **getPalettesQStrings()```
|
|
||||||
|
|
||||||
Provides a char* array (pointers) to the names of the
|
|
||||||
palettes contained in JSON_palette_names, in the same order as
|
|
||||||
JSON_palette_names. These strings end in double quote (")
|
|
||||||
(or \0 if there is a problem).
|
|
||||||
|
|
||||||
```byte *getPalettesAlphaIndexes()```
|
|
||||||
|
|
||||||
A byte array designating the indexes of names of the
|
|
||||||
palettes in alphabetical order. "Default" and those
|
|
||||||
starting with "(" will always remain at the top of the list.
|
|
@ -1,244 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "wled.h"
|
|
||||||
|
|
||||||
//
|
|
||||||
// v2 usermod that provides data about modes and
|
|
||||||
// palettes to other usermods. Notably it provides:
|
|
||||||
// * A direct method for a mode or palette name
|
|
||||||
// * Ability to retrieve mode and palette names in
|
|
||||||
// alphabetical order
|
|
||||||
//
|
|
||||||
// char **getModesQStrings()
|
|
||||||
// Provides an array of char* (pointers) to the names of the
|
|
||||||
// palettes within JSON_mode_names, in the same order as
|
|
||||||
// JSON_mode_names. These strings end in double quote (")
|
|
||||||
// (or \0 if there is a problem).
|
|
||||||
//
|
|
||||||
// byte *getModesAlphaIndexes()
|
|
||||||
// An array of byte designating the indexes of names of the
|
|
||||||
// modes in alphabetical order. "Solid" will always remain
|
|
||||||
// at the front of the list.
|
|
||||||
//
|
|
||||||
// char **getPalettesQStrings()
|
|
||||||
// Provides an array of char* (pointers) to the names of the
|
|
||||||
// palettes within JSON_palette_names, in the same order as
|
|
||||||
// JSON_palette_names. These strings end in double quote (")
|
|
||||||
// (or \0 if there is a problem).
|
|
||||||
//
|
|
||||||
// byte *getPalettesAlphaIndexes()
|
|
||||||
// An array of byte designating the indexes of names of the
|
|
||||||
// palettes in alphabetical order. "Default" and those
|
|
||||||
// starting with "(" will always remain at the front of the list.
|
|
||||||
//
|
|
||||||
|
|
||||||
// Number of modes at the start of the list to not sort
|
|
||||||
#define MODE_SORT_SKIP_COUNT 1
|
|
||||||
|
|
||||||
// Which list is being sorted
|
|
||||||
char **listBeingSorted = nullptr;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modes and palettes are stored as strings that
|
|
||||||
* end in a quote character. Compare two of them.
|
|
||||||
* We are comparing directly within either
|
|
||||||
* JSON_mode_names or JSON_palette_names.
|
|
||||||
*/
|
|
||||||
int re_qstringCmp(const void *ap, const void *bp) {
|
|
||||||
char *a = listBeingSorted[*((byte *)ap)];
|
|
||||||
char *b = listBeingSorted[*((byte *)bp)];
|
|
||||||
int i = 0;
|
|
||||||
do {
|
|
||||||
char aVal = pgm_read_byte_near(a + i);
|
|
||||||
if (aVal >= 97 && aVal <= 122) {
|
|
||||||
// Lowercase
|
|
||||||
aVal -= 32;
|
|
||||||
}
|
|
||||||
char bVal = pgm_read_byte_near(b + i);
|
|
||||||
if (bVal >= 97 && bVal <= 122) {
|
|
||||||
// Lowercase
|
|
||||||
bVal -= 32;
|
|
||||||
}
|
|
||||||
// Relly we shouldn't ever get to '\0'
|
|
||||||
if (aVal == '"' || bVal == '"' || aVal == '\0' || bVal == '\0') {
|
|
||||||
// We're done. one is a substring of the other
|
|
||||||
// or something happenend and the quote didn't stop us.
|
|
||||||
if (aVal == bVal) {
|
|
||||||
// Same value, probably shouldn't happen
|
|
||||||
// with this dataset
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if (aVal == '"' || aVal == '\0') {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (aVal == bVal) {
|
|
||||||
// Same characters. Move to the next.
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// We're done
|
|
||||||
if (aVal < bVal) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} while (true);
|
|
||||||
// We shouldn't get here.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ModeSortUsermod : public Usermod {
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Pointers the start of the mode names within JSON_mode_names
|
|
||||||
char **modes_qstrings = nullptr;
|
|
||||||
|
|
||||||
// Array of mode indexes in alphabetical order.
|
|
||||||
byte *modes_alpha_indexes = nullptr;
|
|
||||||
|
|
||||||
// Pointers the start of the palette names within JSON_palette_names
|
|
||||||
char **palettes_qstrings = nullptr;
|
|
||||||
|
|
||||||
// Array of palette indexes in alphabetical order.
|
|
||||||
byte *palettes_alpha_indexes = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
|
||||||
* You can use it to initialize variables, sensors or similar.
|
|
||||||
*/
|
|
||||||
void setup() {
|
|
||||||
// Sort the modes and palettes on startup
|
|
||||||
// as they are guarantted to change.
|
|
||||||
sortModesAndPalettes();
|
|
||||||
}
|
|
||||||
|
|
||||||
char **getModesQStrings() {
|
|
||||||
return modes_qstrings;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte *getModesAlphaIndexes() {
|
|
||||||
return modes_alpha_indexes;
|
|
||||||
}
|
|
||||||
|
|
||||||
char **getPalettesQStrings() {
|
|
||||||
return palettes_qstrings;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte *getPalettesAlphaIndexes() {
|
|
||||||
return palettes_alpha_indexes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This Usermod doesn't have anything for loop.
|
|
||||||
*/
|
|
||||||
void loop() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort the modes and palettes to the index arrays
|
|
||||||
* modes_alpha_indexes and palettes_alpha_indexes.
|
|
||||||
*/
|
|
||||||
void sortModesAndPalettes() {
|
|
||||||
modes_qstrings = re_findModeStrings(JSON_mode_names, strip.getModeCount());
|
|
||||||
modes_alpha_indexes = re_initIndexArray(strip.getModeCount());
|
|
||||||
re_sortModes(modes_qstrings, modes_alpha_indexes, strip.getModeCount(), MODE_SORT_SKIP_COUNT);
|
|
||||||
|
|
||||||
palettes_qstrings = re_findModeStrings(JSON_palette_names, strip.getPaletteCount());
|
|
||||||
palettes_alpha_indexes = re_initIndexArray(strip.getPaletteCount());
|
|
||||||
|
|
||||||
int skipPaletteCount = 1;
|
|
||||||
while (true) {
|
|
||||||
// How many palette names start with '*' and should not be sorted?
|
|
||||||
// (Also skipping the first one, 'Default').
|
|
||||||
if (pgm_read_byte_near(palettes_qstrings[skipPaletteCount]) == '*') {
|
|
||||||
skipPaletteCount++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
re_sortModes(palettes_qstrings, palettes_alpha_indexes, strip.getPaletteCount(), skipPaletteCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte *re_initIndexArray(int numModes) {
|
|
||||||
byte *indexes = (byte *)malloc(sizeof(byte) * numModes);
|
|
||||||
for (byte i = 0; i < numModes; i++) {
|
|
||||||
indexes[i] = i;
|
|
||||||
}
|
|
||||||
return indexes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an array of mode or palette names from the JSON string.
|
|
||||||
* They don't end in '\0', they end in '"'.
|
|
||||||
*/
|
|
||||||
char **re_findModeStrings(const char json[], int numModes) {
|
|
||||||
char **modeStrings = (char **)malloc(sizeof(char *) * numModes);
|
|
||||||
uint8_t modeIndex = 0;
|
|
||||||
bool insideQuotes = false;
|
|
||||||
// advance past the mark for markLineNum that may exist.
|
|
||||||
char singleJsonSymbol;
|
|
||||||
|
|
||||||
// Find the mode name in JSON
|
|
||||||
bool complete = false;
|
|
||||||
for (size_t i = 0; i < strlen_P(json); i++) {
|
|
||||||
singleJsonSymbol = pgm_read_byte_near(json + i);
|
|
||||||
if (singleJsonSymbol == '\0') break;
|
|
||||||
switch (singleJsonSymbol) {
|
|
||||||
case '"':
|
|
||||||
insideQuotes = !insideQuotes;
|
|
||||||
if (insideQuotes) {
|
|
||||||
// We have a new mode or palette
|
|
||||||
modeStrings[modeIndex] = (char *)(json + i + 1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case '[':
|
|
||||||
break;
|
|
||||||
case ']':
|
|
||||||
if (!insideQuotes) complete = true;
|
|
||||||
break;
|
|
||||||
case ',':
|
|
||||||
if (!insideQuotes) modeIndex++;
|
|
||||||
default:
|
|
||||||
if (!insideQuotes) break;
|
|
||||||
}
|
|
||||||
if (complete) break;
|
|
||||||
}
|
|
||||||
return modeStrings;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort either the modes or the palettes using quicksort.
|
|
||||||
*/
|
|
||||||
void re_sortModes(char **modeNames, byte *indexes, int count, int numSkip) {
|
|
||||||
listBeingSorted = modeNames;
|
|
||||||
qsort(indexes + numSkip, count - numSkip, sizeof(byte), re_qstringCmp);
|
|
||||||
listBeingSorted = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
|
||||||
* Values in the state object may be modified by connected clients
|
|
||||||
*/
|
|
||||||
void addToJsonState(JsonObject &root) {}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
|
||||||
* Values in the state object may be modified by connected clients
|
|
||||||
*/
|
|
||||||
void readFromJsonState(JsonObject &root) {}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
|
||||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
|
||||||
*/
|
|
||||||
uint16_t getId()
|
|
||||||
{
|
|
||||||
return USERMOD_ID_MODE_SORT;
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,48 +0,0 @@
|
|||||||
[platformio]
|
|
||||||
default_envs = d1_mini
|
|
||||||
; default_envs = esp32dev
|
|
||||||
|
|
||||||
[env:esp32dev]
|
|
||||||
board = esp32dev
|
|
||||||
platform = espressif32@3.2
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags =
|
|
||||||
${common.build_flags_esp32}
|
|
||||||
-D USERMOD_MODE_SORT
|
|
||||||
-D USERMOD_FOUR_LINE_DISPLAY -D FLD_PIN_SCL=22 -D FLD_PIN_SDA=21
|
|
||||||
-D USERMOD_ROTARY_ENCODER_UI -D ENCODER_DT_PIN=18 -D ENCODER_CLK_PIN=5 -D ENCODER_SW_PIN=19
|
|
||||||
-D USERMOD_AUTO_SAVE -D AUTOSAVE_PRESET_NUM=1
|
|
||||||
-D LEDPIN=16 -D BTNPIN=13
|
|
||||||
upload_speed = 460800
|
|
||||||
lib_ignore =
|
|
||||||
ESPAsyncTCP
|
|
||||||
ESPAsyncUDP
|
|
||||||
|
|
||||||
[env:d1_mini]
|
|
||||||
board = d1_mini
|
|
||||||
platform = ${common.platform_wled_default}
|
|
||||||
platform_packages = ${common.platform_packages}
|
|
||||||
upload_speed = 460800
|
|
||||||
board_build.ldscript = ${common.ldscript_4m1m}
|
|
||||||
build_unflags = ${common.build_unflags}
|
|
||||||
build_flags =
|
|
||||||
${common.build_flags_esp8266}
|
|
||||||
-D USERMOD_MODE_SORT
|
|
||||||
-D USERMOD_FOUR_LINE_DISPLAY -D FLD_PIN_SCL=5 -D FLD_PIN_SDA=4
|
|
||||||
-D USERMOD_ROTARY_ENCODER_UI -D ENCODER_DT_PIN=12 -D ENCODER_CLK_PIN=14 -D ENCODER_SW_PIN=13
|
|
||||||
-D USERMOD_AUTO_SAVE -D AUTOSAVE_PRESET_NUM=1
|
|
||||||
-D LEDPIN=3 -D BTNPIN=0
|
|
||||||
monitor_filters = esp8266_exception_decoder
|
|
||||||
|
|
||||||
[env]
|
|
||||||
lib_deps =
|
|
||||||
fastled/FastLED @ 3.3.2
|
|
||||||
NeoPixelBus @ 2.6.0
|
|
||||||
ESPAsyncTCP @ 1.2.0
|
|
||||||
ESPAsyncUDP
|
|
||||||
AsyncTCP @ 1.0.3
|
|
||||||
IRremoteESP8266 @ 2.7.3
|
|
||||||
https://github.com/lorol/LITTLEFS.git
|
|
||||||
https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.0
|
|
||||||
U8g2@~2.27.2
|
|
||||||
Wire
|
|
@ -1,39 +0,0 @@
|
|||||||
# Rotary Encoder UI Usermod
|
|
||||||
|
|
||||||
First, thanks to the authors of other Rotary Encoder usermods.
|
|
||||||
|
|
||||||
This usermod starts to provide a relatively complete on-device
|
|
||||||
UI when paired with the Four Line Display usermod. I strongly
|
|
||||||
encourage you to try them together.
|
|
||||||
|
|
||||||
[See the pair of usermods in action](https://www.youtube.com/watch?v=tITQY80rIOA)
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
Copy and update the example `platformio_override.ini.sample` to the root directory of your particular build.
|
|
||||||
This file should be placed in the same directory as `platformio.ini`.
|
|
||||||
|
|
||||||
### Define Your Options
|
|
||||||
|
|
||||||
* `USERMOD_ROTARY_ENCODER_UI` - define this to have this user mod included wled00\usermods_list.cpp
|
|
||||||
* `USERMOD_ROTARY_ENCODER_GPIO` - define the GPIO function (INPUT, INPUT_PULLUP, etc...)
|
|
||||||
* `USERMOD_FOUR_LINE_DISPLAY` - define this to have this the Four Line Display mod included wled00\usermods_list.cpp
|
|
||||||
also tells this usermod that the display is available
|
|
||||||
(see the Four Line Display usermod `readme.md` for more details)
|
|
||||||
* `ENCODER_DT_PIN` - defaults to 12
|
|
||||||
* `ENCODER_CLK_PIN` - defaults to 14
|
|
||||||
* `ENCODER_SW_PIN` - defaults to 13
|
|
||||||
* `USERMOD_ROTARY_ENCODER_GPIO` - GPIO functionality:
|
|
||||||
`INPUT_PULLUP` to use internal pull-up
|
|
||||||
`INPUT` to use pull-up on the PCB
|
|
||||||
|
|
||||||
### PlatformIO requirements
|
|
||||||
|
|
||||||
No special requirements.
|
|
||||||
|
|
||||||
Note: the Four Line Display usermod requires the libraries `U8g2` and `Wire`.
|
|
||||||
|
|
||||||
## Change Log
|
|
||||||
|
|
||||||
2021-02
|
|
||||||
* First public release
|
|
@ -1,496 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "wled.h"
|
|
||||||
|
|
||||||
//
|
|
||||||
// Inspired by the v1 usermods
|
|
||||||
// * rotary_encoder_change_brightness
|
|
||||||
// * rotary_encoder_change_effect
|
|
||||||
//
|
|
||||||
// v2 usermod that provides a rotary encoder-based UI.
|
|
||||||
//
|
|
||||||
// This usermod allows you to control:
|
|
||||||
//
|
|
||||||
// * Brightness
|
|
||||||
// * Selected Effect
|
|
||||||
// * Effect Speed
|
|
||||||
// * Effect Intensity
|
|
||||||
// * Palette
|
|
||||||
//
|
|
||||||
// Change between modes by pressing a button.
|
|
||||||
//
|
|
||||||
// Dependencies
|
|
||||||
// * This usermod REQURES the ModeSortUsermod
|
|
||||||
// * This Usermod works best coupled with
|
|
||||||
// FourLineDisplayUsermod.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef ENCODER_DT_PIN
|
|
||||||
#define ENCODER_DT_PIN 12
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ENCODER_CLK_PIN
|
|
||||||
#define ENCODER_CLK_PIN 14
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ENCODER_SW_PIN
|
|
||||||
#define ENCODER_SW_PIN 13
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef USERMOD_FOUR_LINE_DISPLAY
|
|
||||||
// These constants won't be defined if we aren't using FourLineDisplay.
|
|
||||||
#define FLD_LINE_BRIGHTNESS 0
|
|
||||||
#define FLD_LINE_MODE 0
|
|
||||||
#define FLD_LINE_EFFECT_SPEED 0
|
|
||||||
#define FLD_LINE_EFFECT_INTENSITY 0
|
|
||||||
#define FLD_LINE_PALETTE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// The last UI state
|
|
||||||
#define LAST_UI_STATE 4
|
|
||||||
|
|
||||||
|
|
||||||
class RotaryEncoderUIUsermod : public Usermod {
|
|
||||||
private:
|
|
||||||
int fadeAmount = 10; // Amount to change every step (brightness)
|
|
||||||
unsigned long currentTime;
|
|
||||||
unsigned long loopTime;
|
|
||||||
int8_t pinA = ENCODER_DT_PIN; // DT from encoder
|
|
||||||
int8_t pinB = ENCODER_CLK_PIN; // CLK from encoder
|
|
||||||
int8_t pinC = ENCODER_SW_PIN; // SW from encoder
|
|
||||||
unsigned char select_state = 0; // 0: brightness, 1: effect, 2: effect speed
|
|
||||||
unsigned char button_state = HIGH;
|
|
||||||
unsigned char prev_button_state = HIGH;
|
|
||||||
|
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
|
||||||
FourLineDisplayUsermod *display;
|
|
||||||
#else
|
|
||||||
void* display = nullptr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
byte *modes_alpha_indexes = nullptr;
|
|
||||||
byte *palettes_alpha_indexes = nullptr;
|
|
||||||
|
|
||||||
unsigned char Enc_A;
|
|
||||||
unsigned char Enc_B;
|
|
||||||
unsigned char Enc_A_prev = 0;
|
|
||||||
|
|
||||||
bool currentEffectAndPaletteInitialized = false;
|
|
||||||
uint8_t effectCurrentIndex = 0;
|
|
||||||
uint8_t effectPaletteIndex = 0;
|
|
||||||
|
|
||||||
bool initDone = false;
|
|
||||||
bool enabled = true;
|
|
||||||
|
|
||||||
// strings to reduce flash memory usage (used more than twice)
|
|
||||||
static const char _name[];
|
|
||||||
static const char _enabled[];
|
|
||||||
static const char _DT_pin[];
|
|
||||||
static const char _CLK_pin[];
|
|
||||||
static const char _SW_pin[];
|
|
||||||
|
|
||||||
public:
|
|
||||||
/*
|
|
||||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
|
||||||
* You can use it to initialize variables, sensors or similar.
|
|
||||||
*/
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
DEBUG_PRINTLN(F("Usermod Rotary Encoder init."));
|
|
||||||
PinManagerPinType pins[3] = { { pinA, false }, { pinB, false }, { pinC, false } };
|
|
||||||
if (!pinManager.allocateMultiplePins(pins, 3, PinOwner::UM_RotaryEncoderUI)) {
|
|
||||||
// BUG: configuring this usermod with conflicting pins
|
|
||||||
// will cause it to de-allocate pins it does not own
|
|
||||||
// (at second config)
|
|
||||||
// This is the exact type of bug solved by pinManager
|
|
||||||
// tracking the owner tags....
|
|
||||||
pinA = pinB = pinC = -1;
|
|
||||||
enabled = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef USERMOD_ROTARY_ENCODER_GPIO
|
|
||||||
#define USERMOD_ROTARY_ENCODER_GPIO INPUT_PULLUP
|
|
||||||
#endif
|
|
||||||
pinMode(pinA, USERMOD_ROTARY_ENCODER_GPIO);
|
|
||||||
pinMode(pinB, USERMOD_ROTARY_ENCODER_GPIO);
|
|
||||||
pinMode(pinC, USERMOD_ROTARY_ENCODER_GPIO);
|
|
||||||
|
|
||||||
currentTime = millis();
|
|
||||||
loopTime = currentTime;
|
|
||||||
|
|
||||||
ModeSortUsermod *modeSortUsermod = (ModeSortUsermod*) usermods.lookup(USERMOD_ID_MODE_SORT);
|
|
||||||
modes_alpha_indexes = modeSortUsermod->getModesAlphaIndexes();
|
|
||||||
palettes_alpha_indexes = modeSortUsermod->getPalettesAlphaIndexes();
|
|
||||||
|
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
|
||||||
// This Usermod uses FourLineDisplayUsermod for the best experience.
|
|
||||||
// But it's optional. But you want it.
|
|
||||||
display = (FourLineDisplayUsermod*) usermods.lookup(USERMOD_ID_FOUR_LINE_DISP);
|
|
||||||
if (display != nullptr) {
|
|
||||||
display->setLineType(FLD_LINE_BRIGHTNESS);
|
|
||||||
display->setMarkLine(3);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
initDone = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* connected() is called every time the WiFi is (re)connected
|
|
||||||
* Use it to initialize network interfaces
|
|
||||||
*/
|
|
||||||
void connected()
|
|
||||||
{
|
|
||||||
//Serial.println("Connected to WiFi!");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
|
||||||
*
|
|
||||||
* Tips:
|
|
||||||
* 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection.
|
|
||||||
* Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker.
|
|
||||||
*
|
|
||||||
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
|
|
||||||
* Instead, use a timer check as shown here.
|
|
||||||
*/
|
|
||||||
void loop()
|
|
||||||
{
|
|
||||||
if (!enabled) return;
|
|
||||||
|
|
||||||
currentTime = millis(); // get the current elapsed time
|
|
||||||
|
|
||||||
// Initialize effectCurrentIndex and effectPaletteIndex to
|
|
||||||
// current state. We do it here as (at least) effectCurrent
|
|
||||||
// is not yet initialized when setup is called.
|
|
||||||
if (!currentEffectAndPaletteInitialized) {
|
|
||||||
findCurrentEffectAndPalette();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentTime >= (loopTime + 2)) // 2ms since last check of encoder = 500Hz
|
|
||||||
{
|
|
||||||
button_state = digitalRead(pinC);
|
|
||||||
if (prev_button_state != button_state)
|
|
||||||
{
|
|
||||||
if (button_state == LOW)
|
|
||||||
{
|
|
||||||
prev_button_state = button_state;
|
|
||||||
|
|
||||||
char newState = select_state + 1;
|
|
||||||
if (newState > LAST_UI_STATE) newState = 0;
|
|
||||||
|
|
||||||
bool changedState = true;
|
|
||||||
if (display != nullptr) {
|
|
||||||
switch(newState) {
|
|
||||||
case 0:
|
|
||||||
changedState = changeState("Brightness", FLD_LINE_BRIGHTNESS, 3);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
changedState = changeState("Select FX", FLD_LINE_MODE, 2);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
changedState = changeState("FX Speed", FLD_LINE_EFFECT_SPEED, 3);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
changedState = changeState("FX Intensity", FLD_LINE_EFFECT_INTENSITY, 3);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
changedState = changeState("Palette", FLD_LINE_PALETTE, 3);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (changedState) {
|
|
||||||
select_state = newState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
prev_button_state = button_state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int Enc_A = digitalRead(pinA); // Read encoder pins
|
|
||||||
int Enc_B = digitalRead(pinB);
|
|
||||||
if ((!Enc_A) && (Enc_A_prev))
|
|
||||||
{ // A has gone from high to low
|
|
||||||
if (Enc_B == HIGH)
|
|
||||||
{ // B is high so clockwise
|
|
||||||
switch(select_state) {
|
|
||||||
case 0:
|
|
||||||
changeBrightness(true);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
changeEffect(true);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
changeEffectSpeed(true);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
changeEffectIntensity(true);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
changePalette(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (Enc_B == LOW)
|
|
||||||
{ // B is low so counter-clockwise
|
|
||||||
switch(select_state) {
|
|
||||||
case 0:
|
|
||||||
changeBrightness(false);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
changeEffect(false);
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
changeEffectSpeed(false);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
changeEffectIntensity(false);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
changePalette(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Enc_A_prev = Enc_A; // Store value of A for next time
|
|
||||||
loopTime = currentTime; // Updates loopTime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void findCurrentEffectAndPalette() {
|
|
||||||
currentEffectAndPaletteInitialized = true;
|
|
||||||
for (uint8_t i = 0; i < strip.getModeCount(); i++) {
|
|
||||||
//byte value = modes_alpha_indexes[i];
|
|
||||||
if (modes_alpha_indexes[i] == effectCurrent) {
|
|
||||||
effectCurrentIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < strip.getPaletteCount(); i++) {
|
|
||||||
//byte value = palettes_alpha_indexes[i];
|
|
||||||
if (palettes_alpha_indexes[i] == strip.getSegment(0).palette) {
|
|
||||||
effectPaletteIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean changeState(const char *stateName, byte lineThreeMode, byte markedLine) {
|
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
|
||||||
if (display != nullptr) {
|
|
||||||
if (display->wakeDisplay()) {
|
|
||||||
// Throw away wake up input
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
display->overlay("Mode change", stateName, 1500);
|
|
||||||
display->setLineType(lineThreeMode);
|
|
||||||
display->setMarkLine(markedLine);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void lampUdated() {
|
|
||||||
colorUpdated(CALL_MODE_BUTTON);
|
|
||||||
updateInterfaces(CALL_MODE_BUTTON);
|
|
||||||
}
|
|
||||||
|
|
||||||
void changeBrightness(bool increase) {
|
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
|
||||||
if (display && display->wakeDisplay()) {
|
|
||||||
// Throw away wake up input
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (increase) {
|
|
||||||
bri = (bri + fadeAmount <= 255) ? (bri + fadeAmount) : 255;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bri = (bri - fadeAmount >= 0) ? (bri - fadeAmount) : 0;
|
|
||||||
}
|
|
||||||
lampUdated();
|
|
||||||
}
|
|
||||||
|
|
||||||
void changeEffect(bool increase) {
|
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
|
||||||
if (display && display->wakeDisplay()) {
|
|
||||||
// Throw away wake up input
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (increase) {
|
|
||||||
effectCurrentIndex = (effectCurrentIndex + 1 >= strip.getModeCount()) ? 0 : (effectCurrentIndex + 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
effectCurrentIndex = (effectCurrentIndex - 1 < 0) ? (strip.getModeCount() - 1) : (effectCurrentIndex - 1);
|
|
||||||
}
|
|
||||||
effectCurrent = modes_alpha_indexes[effectCurrentIndex];
|
|
||||||
lampUdated();
|
|
||||||
}
|
|
||||||
|
|
||||||
void changeEffectSpeed(bool increase) {
|
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
|
||||||
if (display && display->wakeDisplay()) {
|
|
||||||
// Throw away wake up input
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (increase) {
|
|
||||||
effectSpeed = (effectSpeed + fadeAmount <= 255) ? (effectSpeed + fadeAmount) : 255;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
effectSpeed = (effectSpeed - fadeAmount >= 0) ? (effectSpeed - fadeAmount) : 0;
|
|
||||||
}
|
|
||||||
lampUdated();
|
|
||||||
}
|
|
||||||
|
|
||||||
void changeEffectIntensity(bool increase) {
|
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
|
||||||
if (display && display->wakeDisplay()) {
|
|
||||||
// Throw away wake up input
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (increase) {
|
|
||||||
effectIntensity = (effectIntensity + fadeAmount <= 255) ? (effectIntensity + fadeAmount) : 255;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
effectIntensity = (effectIntensity - fadeAmount >= 0) ? (effectIntensity - fadeAmount) : 0;
|
|
||||||
}
|
|
||||||
lampUdated();
|
|
||||||
}
|
|
||||||
|
|
||||||
void changePalette(bool increase) {
|
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
|
||||||
if (display && display->wakeDisplay()) {
|
|
||||||
// Throw away wake up input
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (increase) {
|
|
||||||
effectPaletteIndex = (effectPaletteIndex + 1 >= strip.getPaletteCount()) ? 0 : (effectPaletteIndex + 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
effectPaletteIndex = (effectPaletteIndex - 1 < 0) ? (strip.getPaletteCount() - 1) : (effectPaletteIndex - 1);
|
|
||||||
}
|
|
||||||
effectPalette = palettes_alpha_indexes[effectPaletteIndex];
|
|
||||||
lampUdated();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
|
||||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
|
||||||
* Below it is shown how this could be used for e.g. a light sensor
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
void addToJsonInfo(JsonObject& root)
|
|
||||||
{
|
|
||||||
int reading = 20;
|
|
||||||
//this code adds "u":{"Light":[20," lux"]} to the info object
|
|
||||||
JsonObject user = root["u"];
|
|
||||||
if (user.isNull()) user = root.createNestedObject("u");
|
|
||||||
JsonArray lightArr = user.createNestedArray("Light"); //name
|
|
||||||
lightArr.add(reading); //value
|
|
||||||
lightArr.add(" lux"); //unit
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
|
||||||
* Values in the state object may be modified by connected clients
|
|
||||||
*/
|
|
||||||
void addToJsonState(JsonObject &root)
|
|
||||||
{
|
|
||||||
//root["user0"] = userVar0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
|
||||||
* Values in the state object may be modified by connected clients
|
|
||||||
*/
|
|
||||||
void readFromJsonState(JsonObject &root)
|
|
||||||
{
|
|
||||||
//userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
|
|
||||||
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* addToConfig() (called from set.cpp) stores persistent properties to cfg.json
|
|
||||||
*/
|
|
||||||
void addToConfig(JsonObject &root) {
|
|
||||||
// we add JSON object: {"Rotary-Encoder":{"DT-pin":12,"CLK-pin":14,"SW-pin":13}}
|
|
||||||
JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
|
|
||||||
top[FPSTR(_enabled)] = enabled;
|
|
||||||
top[FPSTR(_DT_pin)] = pinA;
|
|
||||||
top[FPSTR(_CLK_pin)] = pinB;
|
|
||||||
top[FPSTR(_SW_pin)] = pinC;
|
|
||||||
DEBUG_PRINTLN(F("Rotary Encoder config saved."));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* readFromConfig() is called before setup() to populate properties from values stored in cfg.json
|
|
||||||
*
|
|
||||||
* The function should return true if configuration was successfully loaded or false if there was no configuration.
|
|
||||||
*/
|
|
||||||
bool readFromConfig(JsonObject &root) {
|
|
||||||
// we look for JSON object: {"Rotary-Encoder":{"DT-pin":12,"CLK-pin":14,"SW-pin":13}}
|
|
||||||
JsonObject top = root[FPSTR(_name)];
|
|
||||||
if (top.isNull()) {
|
|
||||||
DEBUG_PRINT(FPSTR(_name));
|
|
||||||
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int8_t newDTpin = top[FPSTR(_DT_pin)] | pinA;
|
|
||||||
int8_t newCLKpin = top[FPSTR(_CLK_pin)] | pinB;
|
|
||||||
int8_t newSWpin = top[FPSTR(_SW_pin)] | pinC;
|
|
||||||
|
|
||||||
enabled = top[FPSTR(_enabled)] | enabled;
|
|
||||||
|
|
||||||
DEBUG_PRINT(FPSTR(_name));
|
|
||||||
if (!initDone) {
|
|
||||||
// first run: reading from cfg.json
|
|
||||||
pinA = newDTpin;
|
|
||||||
pinB = newCLKpin;
|
|
||||||
pinC = newSWpin;
|
|
||||||
DEBUG_PRINTLN(F(" config loaded."));
|
|
||||||
} else {
|
|
||||||
DEBUG_PRINTLN(F(" config (re)loaded."));
|
|
||||||
// changing parameters from settings page
|
|
||||||
if (pinA!=newDTpin || pinB!=newCLKpin || pinC!=newSWpin) {
|
|
||||||
pinManager.deallocatePin(pinA, PinOwner::UM_RotaryEncoderUI);
|
|
||||||
pinManager.deallocatePin(pinB, PinOwner::UM_RotaryEncoderUI);
|
|
||||||
pinManager.deallocatePin(pinC, PinOwner::UM_RotaryEncoderUI);
|
|
||||||
pinA = newDTpin;
|
|
||||||
pinB = newCLKpin;
|
|
||||||
pinC = newSWpin;
|
|
||||||
if (pinA<0 || pinB<0 || pinC<0) {
|
|
||||||
enabled = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
setup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
|
||||||
return !top[FPSTR(_enabled)].isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
|
||||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
|
||||||
*/
|
|
||||||
uint16_t getId()
|
|
||||||
{
|
|
||||||
return USERMOD_ID_ROTARY_ENC_UI;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// strings to reduce flash memory usage (used more than twice)
|
|
||||||
const char RotaryEncoderUIUsermod::_name[] PROGMEM = "Rotary-Encoder";
|
|
||||||
const char RotaryEncoderUIUsermod::_enabled[] PROGMEM = "enabled";
|
|
||||||
const char RotaryEncoderUIUsermod::_DT_pin[] PROGMEM = "DT-pin";
|
|
||||||
const char RotaryEncoderUIUsermod::_CLK_pin[] PROGMEM = "CLK-pin";
|
|
||||||
const char RotaryEncoderUIUsermod::_SW_pin[] PROGMEM = "SW-pin";
|
|
@ -63,6 +63,11 @@
|
|||||||
#define I_8266_U1_UCS_4 54
|
#define I_8266_U1_UCS_4 54
|
||||||
#define I_8266_DM_UCS_4 55
|
#define I_8266_DM_UCS_4 55
|
||||||
#define I_8266_BB_UCS_4 56
|
#define I_8266_BB_UCS_4 56
|
||||||
|
//ESP8266 APA106
|
||||||
|
#define I_8266_U0_APA106_3 81
|
||||||
|
#define I_8266_U1_APA106_3 82
|
||||||
|
#define I_8266_DM_APA106_3 83
|
||||||
|
#define I_8266_BB_APA106_3 84
|
||||||
|
|
||||||
/*** ESP32 Neopixel methods ***/
|
/*** ESP32 Neopixel methods ***/
|
||||||
//RGB
|
//RGB
|
||||||
@ -100,6 +105,10 @@
|
|||||||
#define I_32_I0_UCS_4 61
|
#define I_32_I0_UCS_4 61
|
||||||
#define I_32_I1_UCS_4 62
|
#define I_32_I1_UCS_4 62
|
||||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
||||||
|
#define I_32_RN_APA106_3 85
|
||||||
|
#define I_32_I0_APA106_3 86
|
||||||
|
#define I_32_I1_APA106_3 87
|
||||||
|
#define I_32_BB_APA106_3 88 // bitbangging on ESP32 not recommended
|
||||||
|
|
||||||
//APA102
|
//APA102
|
||||||
#define I_HS_DOT_3 39 //hardware SPI
|
#define I_HS_DOT_3 39 //hardware SPI
|
||||||
@ -162,6 +171,11 @@
|
|||||||
#define B_8266_U1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp8266Uart1Ws2813Method, NeoGammaNullMethod> //4 chan, esp8266, gpio2
|
#define B_8266_U1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp8266Uart1Ws2813Method, NeoGammaNullMethod> //4 chan, esp8266, gpio2
|
||||||
#define B_8266_DM_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp8266Dma800KbpsMethod, NeoGammaNullMethod> //4 chan, esp8266, gpio3
|
#define B_8266_DM_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp8266Dma800KbpsMethod, NeoGammaNullMethod> //4 chan, esp8266, gpio3
|
||||||
#define B_8266_BB_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp8266BitBang800KbpsMethod, NeoGammaNullMethod> //4 chan, esp8266, bb (any pin)
|
#define B_8266_BB_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp8266BitBang800KbpsMethod, NeoGammaNullMethod> //4 chan, esp8266, bb (any pin)
|
||||||
|
//APA106
|
||||||
|
#define B_8266_U0_APA106_3 NeoPixelBusLg<NeoRbgFeature, NeoEsp8266Uart0Apa106Method, NeoGammaNullMethod> //3 chan, esp8266, gpio1
|
||||||
|
#define B_8266_U1_APA106_3 NeoPixelBusLg<NeoRbgFeature, NeoEsp8266Uart1Apa106Method, NeoGammaNullMethod> //3 chan, esp8266, gpio2
|
||||||
|
#define B_8266_DM_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266DmaApa106Method, NeoGammaNullMethod> //3 chan, esp8266, gpio3
|
||||||
|
#define B_8266_BB_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266BitBangApa106Method, NeoGammaNullMethod> //3 chan, esp8266, bb (any pin but 16)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*** ESP32 Neopixel methods ***/
|
/*** ESP32 Neopixel methods ***/
|
||||||
@ -229,6 +243,14 @@
|
|||||||
#define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
|
#define B_32_I1_UCS_4 NeoPixelBusLg<NeoRgbwUcs8904Feature, NeoEsp32I2s1800KbpsMethod, NeoGammaNullMethod>
|
||||||
#endif
|
#endif
|
||||||
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
//Bit Bang theoratically possible, but very undesirable and not needed (no pin restrictions on RMT and I2S)
|
||||||
|
#define B_32_RN_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32RmtNApa106Method, NeoGammaNullMethod>
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
#define B_32_I0_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s0Apa106Method, NeoGammaNullMethod>
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
#define B_32_I1_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp32I2s1Apa106Method, NeoGammaNullMethod>
|
||||||
|
#endif
|
||||||
|
//#define B_32_BB_APA106_3 NeoPixelBusLg<NeoGrbFeature, NeoEsp8266BitBangApa106Method, NeoGammaNullMethod> // NeoEsp8266BitBang800KbpsMethod
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -327,6 +349,10 @@ class PolyBus {
|
|||||||
case I_8266_U1_UCS_4: (static_cast<B_8266_U1_UCS_4*>(busPtr))->Begin(); break;
|
case I_8266_U1_UCS_4: (static_cast<B_8266_U1_UCS_4*>(busPtr))->Begin(); break;
|
||||||
case I_8266_DM_UCS_4: (static_cast<B_8266_DM_UCS_4*>(busPtr))->Begin(); break;
|
case I_8266_DM_UCS_4: (static_cast<B_8266_DM_UCS_4*>(busPtr))->Begin(); break;
|
||||||
case I_8266_BB_UCS_4: (static_cast<B_8266_BB_UCS_4*>(busPtr))->Begin(); break;
|
case I_8266_BB_UCS_4: (static_cast<B_8266_BB_UCS_4*>(busPtr))->Begin(); break;
|
||||||
|
case I_8266_U0_APA106_3: (static_cast<B_8266_U0_APA106_3*>(busPtr))->Begin(); break;
|
||||||
|
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->Begin(); break;
|
||||||
|
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->Begin(); break;
|
||||||
|
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->Begin(); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Begin(); break;
|
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Begin(); break;
|
||||||
@ -379,6 +405,14 @@ class PolyBus {
|
|||||||
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Begin(); break;
|
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Begin(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->Begin(); break;
|
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->Begin(); break;
|
||||||
|
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->Begin(); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->Begin(); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Begin(); break;
|
||||||
|
#endif
|
||||||
|
// case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->Begin(); break;
|
||||||
// ESP32 can (and should, to avoid inadvertantly driving the chip select signal) specify the pins used for SPI, but only in begin()
|
// ESP32 can (and should, to avoid inadvertantly driving the chip select signal) specify the pins used for SPI, but only in begin()
|
||||||
case I_HS_DOT_3: beginDotStar<B_HS_DOT_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break;
|
case I_HS_DOT_3: beginDotStar<B_HS_DOT_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break;
|
||||||
case I_HS_LPD_3: beginDotStar<B_HS_LPD_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break;
|
case I_HS_LPD_3: beginDotStar<B_HS_LPD_3*>(busPtr, pins[1], -1, pins[0], -1, clock_kHz); break;
|
||||||
@ -427,6 +461,10 @@ class PolyBus {
|
|||||||
case I_8266_U1_UCS_4: busPtr = new B_8266_U1_UCS_4(len, pins[0]); break;
|
case I_8266_U1_UCS_4: busPtr = new B_8266_U1_UCS_4(len, pins[0]); break;
|
||||||
case I_8266_DM_UCS_4: busPtr = new B_8266_DM_UCS_4(len, pins[0]); break;
|
case I_8266_DM_UCS_4: busPtr = new B_8266_DM_UCS_4(len, pins[0]); break;
|
||||||
case I_8266_BB_UCS_4: busPtr = new B_8266_BB_UCS_4(len, pins[0]); break;
|
case I_8266_BB_UCS_4: busPtr = new B_8266_BB_UCS_4(len, pins[0]); break;
|
||||||
|
case I_8266_U0_APA106_3: busPtr = new B_8266_U0_APA106_3(len, pins[0]); break;
|
||||||
|
case I_8266_U1_APA106_3: busPtr = new B_8266_U1_APA106_3(len, pins[0]); break;
|
||||||
|
case I_8266_DM_APA106_3: busPtr = new B_8266_DM_APA106_3(len, pins[0]); break;
|
||||||
|
case I_8266_BB_APA106_3: busPtr = new B_8266_BB_APA106_3(len, pins[0]); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: busPtr = new B_32_RN_NEO_3(len, pins[0], (NeoBusChannel)channel); break;
|
case I_32_RN_NEO_3: busPtr = new B_32_RN_NEO_3(len, pins[0], (NeoBusChannel)channel); break;
|
||||||
@ -479,6 +517,14 @@ class PolyBus {
|
|||||||
case I_32_I1_UCS_4: busPtr = new B_32_I1_UCS_4(len, pins[0]); break;
|
case I_32_I1_UCS_4: busPtr = new B_32_I1_UCS_4(len, pins[0]); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: busPtr = new B_32_BB_UCS_4(len, pins[0], (NeoBusChannel)channel); break;
|
// case I_32_BB_UCS_4: busPtr = new B_32_BB_UCS_4(len, pins[0], (NeoBusChannel)channel); break;
|
||||||
|
case I_32_RN_APA106_3: busPtr = new B_32_RN_APA106_3(len, pins[0], (NeoBusChannel)channel); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_APA106_3: busPtr = new B_32_I0_APA106_3(len, pins[0]); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_APA106_3: busPtr = new B_32_I1_APA106_3(len, pins[0]); break;
|
||||||
|
#endif
|
||||||
|
// case I_32_BB_APA106_3: busPtr = new B_32_BB_APA106_3(len, pins[0], (NeoBusChannel)channel); break;
|
||||||
#endif
|
#endif
|
||||||
// for 2-wire: pins[1] is clk, pins[0] is dat. begin expects (len, clk, dat)
|
// for 2-wire: pins[1] is clk, pins[0] is dat. begin expects (len, clk, dat)
|
||||||
case I_HS_DOT_3: busPtr = new B_HS_DOT_3(len, pins[1], pins[0]); break;
|
case I_HS_DOT_3: busPtr = new B_HS_DOT_3(len, pins[1], pins[0]); break;
|
||||||
@ -528,6 +574,10 @@ class PolyBus {
|
|||||||
case I_8266_U1_UCS_4: (static_cast<B_8266_U1_UCS_4*>(busPtr))->Show(consistent); break;
|
case I_8266_U1_UCS_4: (static_cast<B_8266_U1_UCS_4*>(busPtr))->Show(consistent); break;
|
||||||
case I_8266_DM_UCS_4: (static_cast<B_8266_DM_UCS_4*>(busPtr))->Show(consistent); break;
|
case I_8266_DM_UCS_4: (static_cast<B_8266_DM_UCS_4*>(busPtr))->Show(consistent); break;
|
||||||
case I_8266_BB_UCS_4: (static_cast<B_8266_BB_UCS_4*>(busPtr))->Show(consistent); break;
|
case I_8266_BB_UCS_4: (static_cast<B_8266_BB_UCS_4*>(busPtr))->Show(consistent); break;
|
||||||
|
case I_8266_U0_APA106_3: (static_cast<B_8266_U0_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
|
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
|
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
|
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Show(consistent); break;
|
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->Show(consistent); break;
|
||||||
@ -580,6 +630,14 @@ class PolyBus {
|
|||||||
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Show(consistent); break;
|
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->Show(consistent); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->Show(consistent); break;
|
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->Show(consistent); break;
|
||||||
|
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
|
#endif
|
||||||
|
// case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->Show(consistent); break;
|
||||||
#endif
|
#endif
|
||||||
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->Show(consistent); break;
|
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->Show(consistent); break;
|
||||||
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->Show(consistent); break;
|
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->Show(consistent); break;
|
||||||
@ -625,6 +683,10 @@ class PolyBus {
|
|||||||
case I_8266_U0_UCS_4: return (static_cast<B_8266_U0_UCS_4*>(busPtr))->CanShow(); break;
|
case I_8266_U0_UCS_4: return (static_cast<B_8266_U0_UCS_4*>(busPtr))->CanShow(); break;
|
||||||
case I_8266_U1_UCS_4: return (static_cast<B_8266_U1_UCS_4*>(busPtr))->CanShow(); break;
|
case I_8266_U1_UCS_4: return (static_cast<B_8266_U1_UCS_4*>(busPtr))->CanShow(); break;
|
||||||
case I_8266_DM_UCS_4: return (static_cast<B_8266_DM_UCS_4*>(busPtr))->CanShow(); break;
|
case I_8266_DM_UCS_4: return (static_cast<B_8266_DM_UCS_4*>(busPtr))->CanShow(); break;
|
||||||
|
case I_8266_U0_APA106_3: return (static_cast<B_8266_U0_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
|
case I_8266_U1_APA106_3: return (static_cast<B_8266_U1_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
|
case I_8266_DM_APA106_3: return (static_cast<B_8266_DM_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
|
case I_8266_BB_APA106_3: return (static_cast<B_8266_BB_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: return (static_cast<B_32_RN_NEO_3*>(busPtr))->CanShow(); break;
|
case I_32_RN_NEO_3: return (static_cast<B_32_RN_NEO_3*>(busPtr))->CanShow(); break;
|
||||||
@ -677,6 +739,14 @@ class PolyBus {
|
|||||||
case I_32_I1_UCS_4: return (static_cast<B_32_I1_UCS_4*>(busPtr))->CanShow(); break;
|
case I_32_I1_UCS_4: return (static_cast<B_32_I1_UCS_4*>(busPtr))->CanShow(); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: return (static_cast<B_32_BB_UCS_4*>(busPtr))->CanShow(); break;
|
// case I_32_BB_UCS_4: return (static_cast<B_32_BB_UCS_4*>(busPtr))->CanShow(); break;
|
||||||
|
case I_32_RN_APA106_3: return (static_cast<B_32_RN_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_APA106_3: return (static_cast<B_32_I0_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_APA106_3: return (static_cast<B_32_I1_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
|
#endif
|
||||||
|
// case I_32_BB_APA106_3: return (static_cast<B_32_BB_APA106_3*>(busPtr))->CanShow(); break;
|
||||||
#endif
|
#endif
|
||||||
case I_HS_DOT_3: return (static_cast<B_HS_DOT_3*>(busPtr))->CanShow(); break;
|
case I_HS_DOT_3: return (static_cast<B_HS_DOT_3*>(busPtr))->CanShow(); break;
|
||||||
case I_SS_DOT_3: return (static_cast<B_SS_DOT_3*>(busPtr))->CanShow(); break;
|
case I_SS_DOT_3: return (static_cast<B_SS_DOT_3*>(busPtr))->CanShow(); break;
|
||||||
@ -747,6 +817,10 @@ class PolyBus {
|
|||||||
case I_8266_U1_UCS_4: (static_cast<B_8266_U1_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
case I_8266_U1_UCS_4: (static_cast<B_8266_U1_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
||||||
case I_8266_DM_UCS_4: (static_cast<B_8266_DM_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
case I_8266_DM_UCS_4: (static_cast<B_8266_DM_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
||||||
case I_8266_BB_UCS_4: (static_cast<B_8266_BB_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
case I_8266_BB_UCS_4: (static_cast<B_8266_BB_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
||||||
|
case I_8266_U0_APA106_3: (static_cast<B_8266_U0_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
|
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
|
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
|
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
@ -799,6 +873,14 @@ class PolyBus {
|
|||||||
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->SetPixelColor(pix, Rgbw64Color(col)); break;
|
||||||
|
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
|
#endif
|
||||||
|
// case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
#endif
|
#endif
|
||||||
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetPixelColor(pix, RgbColor(col)); break;
|
||||||
@ -845,6 +927,10 @@ class PolyBus {
|
|||||||
case I_8266_U1_UCS_4: (static_cast<B_8266_U1_UCS_4*>(busPtr))->SetLuminance(b); break;
|
case I_8266_U1_UCS_4: (static_cast<B_8266_U1_UCS_4*>(busPtr))->SetLuminance(b); break;
|
||||||
case I_8266_DM_UCS_4: (static_cast<B_8266_DM_UCS_4*>(busPtr))->SetLuminance(b); break;
|
case I_8266_DM_UCS_4: (static_cast<B_8266_DM_UCS_4*>(busPtr))->SetLuminance(b); break;
|
||||||
case I_8266_BB_UCS_4: (static_cast<B_8266_BB_UCS_4*>(busPtr))->SetLuminance(b); break;
|
case I_8266_BB_UCS_4: (static_cast<B_8266_BB_UCS_4*>(busPtr))->SetLuminance(b); break;
|
||||||
|
case I_8266_U0_APA106_3: (static_cast<B_8266_U0_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
|
case I_8266_U1_APA106_3: (static_cast<B_8266_U1_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
|
case I_8266_DM_APA106_3: (static_cast<B_8266_DM_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
|
case I_8266_BB_APA106_3: (static_cast<B_8266_BB_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetLuminance(b); break;
|
case I_32_RN_NEO_3: (static_cast<B_32_RN_NEO_3*>(busPtr))->SetLuminance(b); break;
|
||||||
@ -897,6 +983,14 @@ class PolyBus {
|
|||||||
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetLuminance(b); break;
|
case I_32_I1_UCS_4: (static_cast<B_32_I1_UCS_4*>(busPtr))->SetLuminance(b); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->SetLuminance(b); break;
|
// case I_32_BB_UCS_4: (static_cast<B_32_BB_UCS_4*>(busPtr))->SetLuminance(b); break;
|
||||||
|
case I_32_RN_APA106_3: (static_cast<B_32_RN_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_APA106_3: (static_cast<B_32_I0_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_APA106_3: (static_cast<B_32_I1_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
|
#endif
|
||||||
|
// case I_32_BB_APA106_3: (static_cast<B_32_BB_APA106_3*>(busPtr))->SetLuminance(b); break;
|
||||||
#endif
|
#endif
|
||||||
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetLuminance(b); break;
|
case I_HS_DOT_3: (static_cast<B_HS_DOT_3*>(busPtr))->SetLuminance(b); break;
|
||||||
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetLuminance(b); break;
|
case I_SS_DOT_3: (static_cast<B_SS_DOT_3*>(busPtr))->SetLuminance(b); break;
|
||||||
@ -944,6 +1038,10 @@ class PolyBus {
|
|||||||
case I_8266_U1_UCS_4: { Rgbw64Color c = (static_cast<B_8266_U1_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
case I_8266_U1_UCS_4: { Rgbw64Color c = (static_cast<B_8266_U1_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
||||||
case I_8266_DM_UCS_4: { Rgbw64Color c = (static_cast<B_8266_DM_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
case I_8266_DM_UCS_4: { Rgbw64Color c = (static_cast<B_8266_DM_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
||||||
case I_8266_BB_UCS_4: { Rgbw64Color c = (static_cast<B_8266_BB_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
case I_8266_BB_UCS_4: { Rgbw64Color c = (static_cast<B_8266_BB_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
||||||
|
case I_8266_U0_APA106_3: col = (static_cast<B_8266_U0_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
|
case I_8266_U1_APA106_3: col = (static_cast<B_8266_U1_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
|
case I_8266_DM_APA106_3: col = (static_cast<B_8266_DM_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
|
case I_8266_BB_APA106_3: col = (static_cast<B_8266_BB_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: col = (static_cast<B_32_RN_NEO_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_32_RN_NEO_3: col = (static_cast<B_32_RN_NEO_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
@ -996,6 +1094,14 @@ class PolyBus {
|
|||||||
case I_32_I1_UCS_4: { Rgbw64Color c = (static_cast<B_32_I1_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
case I_32_I1_UCS_4: { Rgbw64Color c = (static_cast<B_32_I1_UCS_4*>(busPtr))->GetPixelColor(pix); col = RGBW32(c.R>>8,c.G>>8,c.B>>8,c.W>>8); } break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: col = (static_cast<B_32_BB_UCS_4*>(busPtr))->GetPixelColor(pix); break;
|
// case I_32_BB_UCS_4: col = (static_cast<B_32_BB_UCS_4*>(busPtr))->GetPixelColor(pix); break;
|
||||||
|
case I_32_RN_APA106_3: col = (static_cast<B_32_RN_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_APA106_3: col = (static_cast<B_32_I0_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_APA106_3: col = (static_cast<B_32_I1_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
|
#endif
|
||||||
|
// case I_32_BB_APA106_3: col = (static_cast<B_32_BB_APA106_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
#endif
|
#endif
|
||||||
case I_HS_DOT_3: col = (static_cast<B_HS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_HS_DOT_3: col = (static_cast<B_HS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
case I_SS_DOT_3: col = (static_cast<B_SS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
|
case I_SS_DOT_3: col = (static_cast<B_SS_DOT_3*>(busPtr))->GetPixelColor(pix); break;
|
||||||
@ -1061,6 +1167,10 @@ class PolyBus {
|
|||||||
case I_8266_U1_UCS_4: delete (static_cast<B_8266_U1_UCS_4*>(busPtr)); break;
|
case I_8266_U1_UCS_4: delete (static_cast<B_8266_U1_UCS_4*>(busPtr)); break;
|
||||||
case I_8266_DM_UCS_4: delete (static_cast<B_8266_DM_UCS_4*>(busPtr)); break;
|
case I_8266_DM_UCS_4: delete (static_cast<B_8266_DM_UCS_4*>(busPtr)); break;
|
||||||
case I_8266_BB_UCS_4: delete (static_cast<B_8266_BB_UCS_4*>(busPtr)); break;
|
case I_8266_BB_UCS_4: delete (static_cast<B_8266_BB_UCS_4*>(busPtr)); break;
|
||||||
|
case I_8266_U0_APA106_3: delete (static_cast<B_8266_U0_APA106_3*>(busPtr)); break;
|
||||||
|
case I_8266_U1_APA106_3: delete (static_cast<B_8266_U1_APA106_3*>(busPtr)); break;
|
||||||
|
case I_8266_DM_APA106_3: delete (static_cast<B_8266_DM_APA106_3*>(busPtr)); break;
|
||||||
|
case I_8266_BB_APA106_3: delete (static_cast<B_8266_BB_APA106_3*>(busPtr)); break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
case I_32_RN_NEO_3: delete (static_cast<B_32_RN_NEO_3*>(busPtr)); break;
|
case I_32_RN_NEO_3: delete (static_cast<B_32_RN_NEO_3*>(busPtr)); break;
|
||||||
@ -1113,6 +1223,14 @@ class PolyBus {
|
|||||||
case I_32_I1_UCS_4: delete (static_cast<B_32_I1_UCS_4*>(busPtr)); break;
|
case I_32_I1_UCS_4: delete (static_cast<B_32_I1_UCS_4*>(busPtr)); break;
|
||||||
#endif
|
#endif
|
||||||
// case I_32_BB_UCS_4: delete (static_cast<B_32_BB_UCS_4*>(busPtr)); break;
|
// case I_32_BB_UCS_4: delete (static_cast<B_32_BB_UCS_4*>(busPtr)); break;
|
||||||
|
case I_32_RN_APA106_3: delete (static_cast<B_32_RN_APA106_3*>(busPtr)); break;
|
||||||
|
#ifndef WLED_NO_I2S0_PIXELBUS
|
||||||
|
case I_32_I0_APA106_3: delete (static_cast<B_32_I0_APA106_3*>(busPtr)); break;
|
||||||
|
#endif
|
||||||
|
#ifndef WLED_NO_I2S1_PIXELBUS
|
||||||
|
case I_32_I1_APA106_3: delete (static_cast<B_32_I1_APA106_3*>(busPtr)); break;
|
||||||
|
#endif
|
||||||
|
// case I_32_BB_APA106_3: delete (static_cast<B_32_BB_APA106_3*>(busPtr)); break;
|
||||||
#endif
|
#endif
|
||||||
case I_HS_DOT_3: delete (static_cast<B_HS_DOT_3*>(busPtr)); break;
|
case I_HS_DOT_3: delete (static_cast<B_HS_DOT_3*>(busPtr)); break;
|
||||||
case I_SS_DOT_3: delete (static_cast<B_SS_DOT_3*>(busPtr)); break;
|
case I_SS_DOT_3: delete (static_cast<B_SS_DOT_3*>(busPtr)); break;
|
||||||
@ -1172,6 +1290,8 @@ class PolyBus {
|
|||||||
return I_8266_U0_UCS_3 + offset;
|
return I_8266_U0_UCS_3 + offset;
|
||||||
case TYPE_UCS8904:
|
case TYPE_UCS8904:
|
||||||
return I_8266_U0_UCS_4 + offset;
|
return I_8266_U0_UCS_4 + offset;
|
||||||
|
case TYPE_APA106:
|
||||||
|
return I_8266_U0_APA106_3 + offset;
|
||||||
}
|
}
|
||||||
#else //ESP32
|
#else //ESP32
|
||||||
uint8_t offset = 0; //0 = RMT (num 0-7) 8 = I2S0 9 = I2S1
|
uint8_t offset = 0; //0 = RMT (num 0-7) 8 = I2S0 9 = I2S1
|
||||||
@ -1210,6 +1330,8 @@ class PolyBus {
|
|||||||
return I_32_RN_UCS_3 + offset;
|
return I_32_RN_UCS_3 + offset;
|
||||||
case TYPE_UCS8904:
|
case TYPE_UCS8904:
|
||||||
return I_32_RN_UCS_4 + offset;
|
return I_32_RN_UCS_4 + offset;
|
||||||
|
case TYPE_APA106:
|
||||||
|
return I_32_RN_APA106_3 + offset;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
104
wled00/cfg.cpp
104
wled00/cfg.cpp
@ -40,21 +40,39 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
linked_remote[12] = '\0';
|
linked_remote[12] = '\0';
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JsonObject nw_ins_0 = nw["ins"][0];
|
size_t n = 0;
|
||||||
getStringFromJson(clientSSID, nw_ins_0[F("ssid")], 33);
|
JsonArray nw_ins = nw["ins"];
|
||||||
//int nw_ins_0_pskl = nw_ins_0[F("pskl")];
|
if (!nw_ins.isNull()) {
|
||||||
//The WiFi PSK is normally not contained in the regular file for security reasons.
|
// as password are stored separately in wsec.json when reading configuration vector resize happens there, but for dynamic config we need to resize if necessary
|
||||||
//If it is present however, we will use it
|
if (nw_ins.size() > 1 && nw_ins.size() > multiWiFi.size()) multiWiFi.resize(nw_ins.size()); // resize constructs objects while resizing
|
||||||
getStringFromJson(clientPass, nw_ins_0["psk"], 65);
|
for (JsonObject wifi : nw_ins) {
|
||||||
|
JsonArray ip = wifi["ip"];
|
||||||
|
JsonArray gw = wifi["gw"];
|
||||||
|
JsonArray sn = wifi["sn"];
|
||||||
|
char ssid[33] = "";
|
||||||
|
char pass[65] = "";
|
||||||
|
IPAddress nIP = (uint32_t)0U, nGW = (uint32_t)0U, nSN = (uint32_t)0x00FFFFFF; // little endian
|
||||||
|
getStringFromJson(ssid, wifi[F("ssid")], 33);
|
||||||
|
getStringFromJson(pass, wifi["psk"], 65); // password is not normally present but if it is, use it
|
||||||
|
for (size_t i = 0; i < 4; i++) {
|
||||||
|
CJSON(nIP[i], ip[i]);
|
||||||
|
CJSON(nGW[i], gw[i]);
|
||||||
|
CJSON(nSN[i], sn[i]);
|
||||||
|
}
|
||||||
|
if (strlen(ssid) > 0) strlcpy(multiWiFi[n].clientSSID, ssid, 33); // this will keep old SSID intact if not present in JSON
|
||||||
|
if (strlen(pass) > 0) strlcpy(multiWiFi[n].clientPass, pass, 65); // this will keep old password intact if not present in JSON
|
||||||
|
multiWiFi[n].staticIP = nIP;
|
||||||
|
multiWiFi[n].staticGW = nGW;
|
||||||
|
multiWiFi[n].staticSN = nSN;
|
||||||
|
if (++n >= WLED_MAX_WIFI_COUNT) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JsonArray nw_ins_0_ip = nw_ins_0["ip"];
|
JsonArray dns = nw[F("dns")];
|
||||||
JsonArray nw_ins_0_gw = nw_ins_0["gw"];
|
if (!dns.isNull()) {
|
||||||
JsonArray nw_ins_0_sn = nw_ins_0["sn"];
|
for (size_t i = 0; i < 4; i++) {
|
||||||
|
CJSON(dnsAddress[i], dns[i]);
|
||||||
for (byte i = 0; i < 4; i++) {
|
}
|
||||||
CJSON(staticIP[i], nw_ins_0_ip[i]);
|
|
||||||
CJSON(staticGateway[i], nw_ins_0_gw[i]);
|
|
||||||
CJSON(staticSubnet[i], nw_ins_0_sn[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject ap = doc["ap"];
|
JsonObject ap = doc["ap"];
|
||||||
@ -212,7 +230,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
JsonObject btn_obj = hw["btn"];
|
JsonObject btn_obj = hw["btn"];
|
||||||
bool pull = btn_obj[F("pull")] | (!disablePullUp); // if true, pullup is enabled
|
bool pull = btn_obj[F("pull")] | (!disablePullUp); // if true, pullup is enabled
|
||||||
disablePullUp = !pull;
|
disablePullUp = !pull;
|
||||||
JsonArray hw_btn_ins = btn_obj[F("ins")];
|
JsonArray hw_btn_ins = btn_obj["ins"];
|
||||||
if (!hw_btn_ins.isNull()) {
|
if (!hw_btn_ins.isNull()) {
|
||||||
for (uint8_t b = 0; b < WLED_MAX_BUTTONS; b++) { // deallocate existing button pins
|
for (uint8_t b = 0; b < WLED_MAX_BUTTONS; b++) { // deallocate existing button pins
|
||||||
pinManager.deallocatePin(btnPin[b], PinOwner::Button); // does nothing if trying to deallocate a pin with PinOwner != Button
|
pinManager.deallocatePin(btnPin[b], PinOwner::Button); // does nothing if trying to deallocate a pin with PinOwner != Button
|
||||||
@ -433,7 +451,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
if (e131Port == DDP_DEFAULT_PORT) e131Port = E131_DEFAULT_PORT; // prevent double DDP port allocation
|
if (e131Port == DDP_DEFAULT_PORT) e131Port = E131_DEFAULT_PORT; // prevent double DDP port allocation
|
||||||
CJSON(e131Multicast, if_live[F("mc")]);
|
CJSON(e131Multicast, if_live[F("mc")]);
|
||||||
|
|
||||||
JsonObject if_live_dmx = if_live[F("dmx")];
|
JsonObject if_live_dmx = if_live["dmx"];
|
||||||
CJSON(e131Universe, if_live_dmx[F("uni")]);
|
CJSON(e131Universe, if_live_dmx[F("uni")]);
|
||||||
CJSON(e131SkipOutOfSequence, if_live_dmx[F("seqskip")]);
|
CJSON(e131SkipOutOfSequence, if_live_dmx[F("seqskip")]);
|
||||||
CJSON(DMXAddress, if_live_dmx[F("addr")]);
|
CJSON(DMXAddress, if_live_dmx[F("addr")]);
|
||||||
@ -507,6 +525,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
CJSON(analogClock12pixel, ol[F("o12pix")]);
|
CJSON(analogClock12pixel, ol[F("o12pix")]);
|
||||||
CJSON(analogClock5MinuteMarks, ol[F("o5m")]);
|
CJSON(analogClock5MinuteMarks, ol[F("o5m")]);
|
||||||
CJSON(analogClockSecondsTrail, ol[F("osec")]);
|
CJSON(analogClockSecondsTrail, ol[F("osec")]);
|
||||||
|
CJSON(analogClockSolidBlack, ol[F("osb")]);
|
||||||
|
|
||||||
//timed macro rules
|
//timed macro rules
|
||||||
JsonObject tm = doc[F("timers")];
|
JsonObject tm = doc[F("timers")];
|
||||||
@ -665,19 +684,23 @@ void serializeConfig() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
JsonArray nw_ins = nw.createNestedArray("ins");
|
JsonArray nw_ins = nw.createNestedArray("ins");
|
||||||
|
for (size_t n = 0; n < multiWiFi.size(); n++) {
|
||||||
|
JsonObject wifi = nw_ins.createNestedObject();
|
||||||
|
wifi[F("ssid")] = multiWiFi[n].clientSSID;
|
||||||
|
wifi[F("pskl")] = strlen(multiWiFi[n].clientPass);
|
||||||
|
JsonArray wifi_ip = wifi.createNestedArray("ip");
|
||||||
|
JsonArray wifi_gw = wifi.createNestedArray("gw");
|
||||||
|
JsonArray wifi_sn = wifi.createNestedArray("sn");
|
||||||
|
for (size_t i = 0; i < 4; i++) {
|
||||||
|
wifi_ip.add(multiWiFi[n].staticIP[i]);
|
||||||
|
wifi_gw.add(multiWiFi[n].staticGW[i]);
|
||||||
|
wifi_sn.add(multiWiFi[n].staticSN[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JsonObject nw_ins_0 = nw_ins.createNestedObject();
|
JsonArray dns = nw.createNestedArray(F("dns"));
|
||||||
nw_ins_0[F("ssid")] = clientSSID;
|
for (size_t i = 0; i < 4; i++) {
|
||||||
nw_ins_0[F("pskl")] = strlen(clientPass);
|
dns.add(dnsAddress[i]);
|
||||||
|
|
||||||
JsonArray nw_ins_0_ip = nw_ins_0.createNestedArray("ip");
|
|
||||||
JsonArray nw_ins_0_gw = nw_ins_0.createNestedArray("gw");
|
|
||||||
JsonArray nw_ins_0_sn = nw_ins_0.createNestedArray("sn");
|
|
||||||
|
|
||||||
for (byte i = 0; i < 4; i++) {
|
|
||||||
nw_ins_0_ip.add(staticIP[i]);
|
|
||||||
nw_ins_0_gw.add(staticGateway[i]);
|
|
||||||
nw_ins_0_sn.add(staticSubnet[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject ap = root.createNestedObject("ap");
|
JsonObject ap = root.createNestedObject("ap");
|
||||||
@ -693,7 +716,7 @@ void serializeConfig() {
|
|||||||
ap_ip.add(2);
|
ap_ip.add(2);
|
||||||
ap_ip.add(1);
|
ap_ip.add(1);
|
||||||
|
|
||||||
JsonObject wifi = root.createNestedObject("wifi");
|
JsonObject wifi = root.createNestedObject(F("wifi"));
|
||||||
wifi[F("sleep")] = !noWifiSleep;
|
wifi[F("sleep")] = !noWifiSleep;
|
||||||
wifi[F("phy")] = force802_3g;
|
wifi[F("phy")] = force802_3g;
|
||||||
|
|
||||||
@ -721,7 +744,7 @@ void serializeConfig() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JsonObject hw = root.createNestedObject("hw");
|
JsonObject hw = root.createNestedObject(F("hw"));
|
||||||
|
|
||||||
JsonObject hw_led = hw.createNestedObject("led");
|
JsonObject hw_led = hw.createNestedObject("led");
|
||||||
hw_led[F("total")] = strip.getLengthTotal(); //provided for compatibility on downgrade and per-output ABL
|
hw_led[F("total")] = strip.getLengthTotal(); //provided for compatibility on downgrade and per-output ABL
|
||||||
@ -973,6 +996,7 @@ void serializeConfig() {
|
|||||||
ol[F("o12pix")] = analogClock12pixel;
|
ol[F("o12pix")] = analogClock12pixel;
|
||||||
ol[F("o5m")] = analogClock5MinuteMarks;
|
ol[F("o5m")] = analogClock5MinuteMarks;
|
||||||
ol[F("osec")] = analogClockSecondsTrail;
|
ol[F("osec")] = analogClockSecondsTrail;
|
||||||
|
ol[F("osb")] = analogClockSolidBlack;
|
||||||
|
|
||||||
JsonObject timers = root.createNestedObject(F("timers"));
|
JsonObject timers = root.createNestedObject(F("timers"));
|
||||||
|
|
||||||
@ -1048,8 +1072,17 @@ bool deserializeConfigSec() {
|
|||||||
|
|
||||||
JsonObject root = pDoc->as<JsonObject>();
|
JsonObject root = pDoc->as<JsonObject>();
|
||||||
|
|
||||||
JsonObject nw_ins_0 = root["nw"]["ins"][0];
|
size_t n = 0;
|
||||||
getStringFromJson(clientPass, nw_ins_0["psk"], 65);
|
JsonArray nw_ins = root["nw"]["ins"];
|
||||||
|
if (!nw_ins.isNull()) {
|
||||||
|
if (nw_ins.size() > 1 && nw_ins.size() > multiWiFi.size()) multiWiFi.resize(nw_ins.size()); // resize constructs objects while resizing
|
||||||
|
for (JsonObject wifi : nw_ins) {
|
||||||
|
char pw[65] = "";
|
||||||
|
getStringFromJson(pw, wifi["psk"], 65);
|
||||||
|
strlcpy(multiWiFi[n].clientPass, pw, 65);
|
||||||
|
if (++n >= WLED_MAX_WIFI_COUNT) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JsonObject ap = root["ap"];
|
JsonObject ap = root["ap"];
|
||||||
getStringFromJson(apPass, ap["psk"] , 65);
|
getStringFromJson(apPass, ap["psk"] , 65);
|
||||||
@ -1088,9 +1121,10 @@ void serializeConfigSec() {
|
|||||||
JsonObject nw = root.createNestedObject("nw");
|
JsonObject nw = root.createNestedObject("nw");
|
||||||
|
|
||||||
JsonArray nw_ins = nw.createNestedArray("ins");
|
JsonArray nw_ins = nw.createNestedArray("ins");
|
||||||
|
for (size_t i = 0; i < multiWiFi.size(); i++) {
|
||||||
JsonObject nw_ins_0 = nw_ins.createNestedObject();
|
JsonObject wifi = nw_ins.createNestedObject();
|
||||||
nw_ins_0["psk"] = clientPass;
|
wifi[F("psk")] = multiWiFi[i].clientPass;
|
||||||
|
}
|
||||||
|
|
||||||
JsonObject ap = root.createNestedObject("ap");
|
JsonObject ap = root.createNestedObject("ap");
|
||||||
ap["psk"] = apPass;
|
ap["psk"] = apPass;
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
#define DEFAULT_MDNS_NAME "x"
|
#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
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef WLED_MAX_USERMODS
|
#ifndef WLED_MAX_USERMODS
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
#define WLED_MAX_USERMODS 4
|
#define WLED_MAX_USERMODS 4
|
||||||
@ -157,6 +161,10 @@
|
|||||||
#define AP_BEHAVIOR_NO_CONN 1 //Open when no connection (either after boot or if connection is lost)
|
#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_ALWAYS 2 //Always open
|
||||||
#define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec
|
#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
|
//Notifier callMode
|
||||||
#define CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
|
#define CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
|
||||||
@ -235,6 +243,7 @@
|
|||||||
#define TYPE_WS2811_400KHZ 24 //half-speed WS2812 protocol, used by very old WS2811 units
|
#define TYPE_WS2811_400KHZ 24 //half-speed WS2812 protocol, used by very old WS2811 units
|
||||||
#define TYPE_TM1829 25
|
#define TYPE_TM1829 25
|
||||||
#define TYPE_UCS8903 26
|
#define TYPE_UCS8903 26
|
||||||
|
#define TYPE_APA106 27
|
||||||
#define TYPE_UCS8904 29 //first RGBW digital type (hardcoded in busmanager.cpp, memUsage())
|
#define TYPE_UCS8904 29 //first RGBW digital type (hardcoded in busmanager.cpp, memUsage())
|
||||||
#define TYPE_SK6812_RGBW 30
|
#define TYPE_SK6812_RGBW 30
|
||||||
#define TYPE_TM1814 31
|
#define TYPE_TM1814 31
|
||||||
@ -292,7 +301,7 @@
|
|||||||
#define BTN_TYPE_TOUCH_SWITCH 9
|
#define BTN_TYPE_TOUCH_SWITCH 9
|
||||||
|
|
||||||
//Ethernet board types
|
//Ethernet board types
|
||||||
#define WLED_NUM_ETH_TYPES 11
|
#define WLED_NUM_ETH_TYPES 12
|
||||||
|
|
||||||
#define WLED_ETH_NONE 0
|
#define WLED_ETH_NONE 0
|
||||||
#define WLED_ETH_WT32_ETH01 1
|
#define WLED_ETH_WT32_ETH01 1
|
||||||
@ -305,6 +314,7 @@
|
|||||||
#define WLED_ETH_QUINLED_OCTA 8
|
#define WLED_ETH_QUINLED_OCTA 8
|
||||||
#define WLED_ETH_ABCWLEDV43ETH 9
|
#define WLED_ETH_ABCWLEDV43ETH 9
|
||||||
#define WLED_ETH_SERG74 10
|
#define WLED_ETH_SERG74 10
|
||||||
|
#define WLED_ETH_ESP32_POE_WROVER 11
|
||||||
|
|
||||||
//Hue error codes
|
//Hue error codes
|
||||||
#define HUE_ERROR_INACTIVE 0
|
#define HUE_ERROR_INACTIVE 0
|
||||||
@ -416,7 +426,7 @@
|
|||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
#define SETTINGS_STACK_BUF_SIZE 2048
|
#define SETTINGS_STACK_BUF_SIZE 2048
|
||||||
#else
|
#else
|
||||||
#define SETTINGS_STACK_BUF_SIZE 3608 // warning: quite a large value for stack
|
#define SETTINGS_STACK_BUF_SIZE 3840 // warning: quite a large value for stack (640 * WLED_MAX_USERMODS)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WLED_USE_ETHERNET
|
#ifdef WLED_USE_ETHERNET
|
||||||
|
@ -346,10 +346,14 @@ button {
|
|||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#Segments, #Presets, #Effects, #Colors {
|
||||||
|
font-size: 19px;
|
||||||
|
padding: 4px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
#segutil, #segutil2, #segcont, #putil, #pcont, #pql, #fx, #palw,
|
#segutil, #segutil2, #segcont, #putil, #pcont, #pql, #fx, #palw,
|
||||||
.fnd {
|
.fnd {
|
||||||
max-width: 280px;
|
max-width: 280px;
|
||||||
font-size: 19px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#putil, #segutil, #segutil2 {
|
#putil, #segutil, #segutil2 {
|
||||||
@ -361,7 +365,7 @@ button {
|
|||||||
padding-top: 12px;
|
padding-top: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#fx, #pql, #segcont, #pcont, #sliders, #picker, #qcs-w, #hexw, #pall, #ledmap,
|
#fx, #pql, #segcont, #pcont, #sliders, #qcs-w, #hexw, #pall, #ledmap,
|
||||||
.slider, .filter, .option, .segname, .pname, .fnd {
|
.slider, .filter, .option, .segname, .pname, .fnd {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
@ -371,15 +375,10 @@ button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Quick load magin for simplified UI */
|
/* Quick load magin for simplified UI */
|
||||||
.simplified #pql {
|
.simplified #pql, .simplified #palw, .simplified #fx {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Button margin for simplified UI */
|
|
||||||
.simplified #fx .btn, .simplified #palw .btn {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.smooth { transition: transform calc(var(--f, 1)*.5s) ease-out }
|
.smooth { transition: transform calc(var(--f, 1)*.5s) ease-out }
|
||||||
|
|
||||||
.tab-label {
|
.tab-label {
|
||||||
@ -624,12 +623,10 @@ button {
|
|||||||
padding-bottom: 8px;
|
padding-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#info .btn {
|
.infobtn {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
}
|
}
|
||||||
#info table .btn, #nodes table .btn {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
#info div, #nodes div {
|
#info div, #nodes div {
|
||||||
max-width: 490px;
|
max-width: 490px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@ -784,14 +781,14 @@ input[type=range]::-moz-range-thumb {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#picker {
|
#picker {
|
||||||
margin-top: 8px !important;
|
margin: 4px auto 0 !important;
|
||||||
max-width: max-content;
|
max-width: max-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* buttons */
|
/* buttons */
|
||||||
.btn {
|
.btn {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
margin: 10px 4px;
|
/*margin: 10px 4px;*/
|
||||||
width: 230px;
|
width: 230px;
|
||||||
font-size: 19px;
|
font-size: 19px;
|
||||||
color: var(--c-d);
|
color: var(--c-d);
|
||||||
@ -837,14 +834,14 @@ input[type=range]::-moz-range-thumb {
|
|||||||
text-overflow: clip;
|
text-overflow: clip;
|
||||||
}
|
}
|
||||||
.btn-xs {
|
.btn-xs {
|
||||||
margin: 2px 0 0 0;
|
|
||||||
}
|
|
||||||
#putil .btn-xs {
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
#info .btn-xs {
|
#info .btn-xs {
|
||||||
border: 1px solid var(--c-4);
|
border: 1px solid var(--c-4);
|
||||||
}
|
}
|
||||||
|
#btns .btn-xs {
|
||||||
|
margin: 0 4px;
|
||||||
|
}
|
||||||
|
|
||||||
#putil .btn-s {
|
#putil .btn-s {
|
||||||
width: 135px;
|
width: 135px;
|
||||||
@ -863,6 +860,15 @@ input[type=range]::-moz-range-thumb {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
a.btn {
|
||||||
|
display: block;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-align: center;
|
||||||
|
padding: 9px 32px 7px 24px;
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Quick color select wrapper div */
|
/* Quick color select wrapper div */
|
||||||
#qcs-w {
|
#qcs-w {
|
||||||
@ -913,9 +919,6 @@ select {
|
|||||||
#tt {
|
#tt {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.cl {
|
|
||||||
background-color: #000;
|
|
||||||
}
|
|
||||||
select.sel-p, select.sel-pl, select.sel-ple {
|
select.sel-p, select.sel-pl, select.sel-ple {
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -1018,7 +1021,7 @@ textarea {
|
|||||||
width: 50px !important;
|
width: 50px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.segname, .pname, .bname {
|
.segname, .pname {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -1028,9 +1031,6 @@ textarea {
|
|||||||
max-width: 170px;
|
max-width: 170px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.bname {
|
|
||||||
padding: 0 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.segname .flr, .pname .flr {
|
.segname .flr, .pname .flr {
|
||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
@ -1065,27 +1065,24 @@ textarea {
|
|||||||
.newseg {
|
.newseg {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
.ic {
|
.ic {
|
||||||
padding: 6px 0 0 0;
|
padding: 6px 0 0 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
.xxs {
|
/* color selector */
|
||||||
|
#csl button {
|
||||||
width: 44px;
|
width: 44px;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
border: 2px solid var(--c-d) !important;
|
||||||
|
background-color: #000;
|
||||||
}
|
}
|
||||||
|
/* selected color selector */
|
||||||
.xxs-w {
|
#csl .sl {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
|
||||||
|
|
||||||
#csl .xxs {
|
|
||||||
border: 2px solid var(--c-d) !important;
|
|
||||||
}
|
|
||||||
#csl .xxs-w {
|
|
||||||
border-width: 5px !important;
|
border-width: 5px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1290,15 +1287,11 @@ TD .checkmark, TD .radiomark {
|
|||||||
position: -webkit-sticky;
|
position: -webkit-sticky;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
border-radius: 21px;
|
border-radius: 21px;
|
||||||
margin: 13px auto 0;
|
margin: 0 auto 12px;
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
border: 1px solid var(--c-2);
|
border: 1px solid var(--c-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#segutil .lstI {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Simplify segments */
|
/* Simplify segments */
|
||||||
.simplified #segcont .lstI {
|
.simplified #segcont .lstI {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
@ -1397,7 +1390,7 @@ dialog {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding: 8px 40px 8px 44px;
|
padding: 8px 40px 8px 44px;
|
||||||
margin: 5px auto 0;
|
margin: 4px auto 12px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border-radius: 21px;
|
border-radius: 21px;
|
||||||
background: var(--c-2);
|
background: var(--c-2);
|
||||||
@ -1415,6 +1408,13 @@ dialog {
|
|||||||
background-color: var(--c-3);
|
background-color: var(--c-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#fxFind.fnd input[type="text"] {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
#fxFind {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
/* segment & preset inner/expanded content */
|
/* segment & preset inner/expanded content */
|
||||||
.segin,
|
.segin,
|
||||||
.presin {
|
.presin {
|
||||||
@ -1520,7 +1520,7 @@ dialog {
|
|||||||
#info .infobtn, #nodes .infobtn {
|
#info .infobtn, #nodes .infobtn {
|
||||||
width: 145px;
|
width: 145px;
|
||||||
}
|
}
|
||||||
#info div, #nodes div {
|
#info div, #nodes div, #nodes a.btn {
|
||||||
max-width: 320px;
|
max-width: 320px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,91 +46,91 @@
|
|||||||
<div id="Colors" class="tabcontent">
|
<div id="Colors" class="tabcontent">
|
||||||
<div id="picker" class="noslide"></div>
|
<div id="picker" class="noslide"></div>
|
||||||
<div id="hwrap" class="slider">
|
<div id="hwrap" class="slider">
|
||||||
<div tooltip="Hue" class="sliderwrap il">
|
<div title="Hue" class="sliderwrap il">
|
||||||
<input id="sliderH" class="noslide" oninput="fromH()" onchange="setColor(0)" max="359" min="0" type="range" value="0" step="any">
|
<input id="sliderH" class="noslide" oninput="fromH()" onchange="setColor(0)" max="359" min="0" type="range" value="0" step="any">
|
||||||
<div class="sliderdisplay" style="background: linear-gradient(90deg, #f00 2%, #ff0 19%, #0f0 35%, #0ff 52%, #00f 68%, #f0f 85%, #f00)"></div>
|
<div class="sliderdisplay" style="background: linear-gradient(90deg, #f00 2%, #ff0 19%, #0f0 35%, #0ff 52%, #00f 68%, #f0f 85%, #f00)"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="swrap" class="slider">
|
<div id="swrap" class="slider">
|
||||||
<div tooltip="Saturation" class="sliderwrap il">
|
<div title="Saturation" class="sliderwrap il">
|
||||||
<input id="sliderS" class="noslide" oninput="fromS()" onchange="setColor(0)" max="100" min="0" type="range" value="100" step="any">
|
<input id="sliderS" class="noslide" oninput="fromS()" onchange="setColor(0)" max="100" min="0" type="range" value="100" step="any">
|
||||||
<div class="sliderdisplay" style="background: linear-gradient(90deg, #aaa 0%, #f00)"></div>
|
<div class="sliderdisplay" style="background: linear-gradient(90deg, #aaa 0%, #f00)"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="vwrap" class="slider">
|
<div id="vwrap" class="slider">
|
||||||
<div tooltip="Value/Brightness" class="sliderwrap il">
|
<div title="Value/Brightness" class="sliderwrap il">
|
||||||
<input id="sliderV" class="noslide" oninput="fromV()" onchange="setColor(0)" max="100" min="0" type="range" value="100" step="any" />
|
<input id="sliderV" class="noslide" oninput="fromV()" onchange="setColor(0)" max="100" min="0" type="range" value="100" step="any" />
|
||||||
<div class="sliderdisplay"></div>
|
<div class="sliderdisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="kwrap" class="slider">
|
<div id="kwrap" class="slider">
|
||||||
<div tooltip="Kelvin/Temperature" class="sliderwrap il">
|
<div title="Kelvin/Temperature" class="sliderwrap il">
|
||||||
<input id="sliderK" class="noslide" oninput="fromK()" onchange="setColor(0)" max="10091" min="1900" type="range" value="6550" />
|
<input id="sliderK" class="noslide" oninput="fromK()" onchange="setColor(0)" max="10091" min="1900" type="range" value="6550" />
|
||||||
<div class="sliderdisplay"></div>
|
<div class="sliderdisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="rgbwrap">
|
<div id="rgbwrap">
|
||||||
<div id="rwrap" class="slider">
|
<div id="rwrap" class="slider">
|
||||||
<div tooltip="Red channel" class="sliderwrap il">
|
<div title="Red channel" class="sliderwrap il">
|
||||||
<input id="sliderR" class="noslide" oninput="fromRgb()" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
<input id="sliderR" class="noslide" oninput="fromRgb()" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
||||||
<div class="sliderdisplay"></div>
|
<div class="sliderdisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="gwrap" class="slider">
|
<div id="gwrap" class="slider">
|
||||||
<div tooltip="Green channel" class="sliderwrap il">
|
<div title="Green channel" class="sliderwrap il">
|
||||||
<input id="sliderG" class="noslide" oninput="fromRgb()" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
<input id="sliderG" class="noslide" oninput="fromRgb()" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
||||||
<div class="sliderdisplay"></div>
|
<div class="sliderdisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="bwrap" class="slider">
|
<div id="bwrap" class="slider">
|
||||||
<div tooltip="Blue channel" class="sliderwrap il">
|
<div title="Blue channel" class="sliderwrap il">
|
||||||
<input id="sliderB" class="noslide" oninput="fromRgb()" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
<input id="sliderB" class="noslide" oninput="fromRgb()" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
||||||
<div class="sliderdisplay"></div>
|
<div class="sliderdisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="wwrap" class="slider">
|
<div id="wwrap" class="slider">
|
||||||
<div id="whibri" tooltip="White channel" class="sliderwrap il">
|
<div id="whibri" title="White channel" class="sliderwrap il">
|
||||||
<input id="sliderW" class="noslide" oninput="fromW()" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
<input id="sliderW" class="noslide" oninput="fromW()" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
||||||
<div class="sliderdisplay"></div>
|
<div class="sliderdisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="wbal" class="slider">
|
<div id="wbal" class="slider">
|
||||||
<div tooltip="White balance" class="sliderwrap il">
|
<div title="White balance" class="sliderwrap il">
|
||||||
<input id="sliderA" class="noslide" onchange="setBalance(this.value)" max="255" min="0" type="range" value="128" />
|
<input id="sliderA" class="noslide" onchange="setBalance(this.value)" max="255" min="0" type="range" value="128" />
|
||||||
<div class="sliderdisplay"></div>
|
<div class="sliderdisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="qcs-w">
|
<div id="qcs-w">
|
||||||
<div class="qcs" onclick="pC('#ff0000');" tooltip="Red" style="background-color:#ff0000;"></div>
|
<div class="qcs" onclick="pC('#ff0000');" style="background-color:#ff0000;"></div>
|
||||||
<div class="qcs" onclick="pC('#ffa000');" tooltip="Orange" style="background-color:#ffa000;"></div>
|
<div class="qcs" onclick="pC('#ffa000');" style="background-color:#ffa000;"></div>
|
||||||
<div class="qcs" onclick="pC('#ffc800');" tooltip="Yellow" style="background-color:#ffc800;"></div>
|
<div class="qcs" onclick="pC('#ffc800');" style="background-color:#ffc800;"></div>
|
||||||
<div class="qcs" onclick="pC('#ffe0a0');" tooltip="Warm White" style="background-color:#ffe0a0;"></div>
|
<div class="qcs" onclick="pC('#ffe0a0');" style="background-color:#ffe0a0;"></div>
|
||||||
<div class="qcs" onclick="pC('#ffffff');" tooltip="White" style="background-color:#ffffff;"></div>
|
<div class="qcs" onclick="pC('#ffffff');" style="background-color:#ffffff;"></div>
|
||||||
<div class="qcs qcsb" onclick="pC('#000000');" tooltip="Black" style="background-color:#000000;"></div><br>
|
<div class="qcs qcsb" onclick="pC('#000000');" style="background-color:#000000;"></div><br>
|
||||||
<div class="qcs" onclick="pC('#ff00ff');" tooltip="Pink" style="background-color:#ff00ff;"></div>
|
<div class="qcs" onclick="pC('#ff00ff');" style="background-color:#ff00ff;"></div>
|
||||||
<div class="qcs" onclick="pC('#0000ff');" tooltip="Blue" style="background-color:#0000ff;"></div>
|
<div class="qcs" onclick="pC('#0000ff');" style="background-color:#0000ff;"></div>
|
||||||
<div class="qcs" onclick="pC('#00ffc8');" tooltip="Cyan" style="background-color:#00ffc8;"></div>
|
<div class="qcs" onclick="pC('#00ffc8');" style="background-color:#00ffc8;"></div>
|
||||||
<div class="qcs" onclick="pC('#08ff00');" tooltip="Green" style="background-color:#08ff00;"></div>
|
<div class="qcs" onclick="pC('#08ff00');" style="background-color:#08ff00;"></div>
|
||||||
<div class="qcs" onclick="pC('rnd');" tooltip="Random" style="background:linear-gradient(to right, red, orange, yellow, green, blue, purple);transform: translateY(-11px);">R</div>
|
<div class="qcs" onclick="pC('rnd');" title="Random" style="background:linear-gradient(to right, red, orange, yellow, green, blue, purple);transform: translateY(-11px);">R</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="csl">
|
<div id="csl">
|
||||||
<button id="csl0" tooltip="Select slot" class="btn xxs cl" onclick="selectSlot(0);" data-r="0" data-g="0" data-b="0" data-w="0">1</button>
|
<button id="csl0" title="Select slot" class="btn" onclick="selectSlot(0);" data-r="0" data-g="0" data-b="0" data-w="0">1</button>
|
||||||
<button id="csl1" tooltip="Select slot" class="btn xxs cl" onclick="selectSlot(1);" data-r="0" data-g="0" data-b="0" data-w="0">2</button>
|
<button id="csl1" title="Select slot" class="btn" onclick="selectSlot(1);" data-r="0" data-g="0" data-b="0" data-w="0">2</button>
|
||||||
<button id="csl2" tooltip="Select slot" class="btn xxs cl" onclick="selectSlot(2);" data-r="0" data-g="0" data-b="0" data-w="0">3</button>
|
<button id="csl2" title="Select slot" class="btn" onclick="selectSlot(2);" data-r="0" data-g="0" data-b="0" data-w="0">3</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="labels h" id="cslLabel"></p>
|
<p class="labels h" id="cslLabel"></p>
|
||||||
<div id="hexw">
|
<div id="hexw">
|
||||||
<i class="icons sel-icon" onclick="tglRgb()"></i>
|
<i class="icons sel-icon" onclick="tglRgb()"></i>
|
||||||
<input id="hexc" tooltip="Hex RGB" type="text" class="noslide" onkeydown="hexEnter()" autocomplete="off" maxlength="8" />
|
<input id="hexc" title="Hex RGB" type="text" class="noslide" onkeydown="hexEnter()" autocomplete="off" maxlength="8" />
|
||||||
<button id="hexcnf" class="btn btn-xs" onclick="fromHex();"><i class="icons btn-icon"></i></button>
|
<button id="hexcnf" class="btn btn-xs" onclick="fromHex();"><i class="icons btn-icon"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<div style="padding: 8px 0;" id="btns">
|
<div style="padding: 8px 0;" id="btns">
|
||||||
<button class="btn btn-xs" tooltip="Pixel Magic Tool" type="button" id="pxmb" onclick="window.location.href=getURL('/pxmagic.htm')"><i class="icons btn-icon"></i></button>
|
<button class="btn btn-xs" title="Pixel Magic Tool" type="button" id="pxmb" onclick="window.location.href=getURL('/pxmagic.htm')"><i class="icons btn-icon"></i></button>
|
||||||
<button class="btn btn-xs" tooltip="Add custom palette" type="button" onclick="window.location.href=getURL('/cpal.htm')"><i class="icons btn-icon"></i></button>
|
<button class="btn btn-xs" title="Add custom palette" type="button" onclick="window.location.href=getURL('/cpal.htm')"><i class="icons btn-icon"></i></button>
|
||||||
<button class="btn btn-xs" tooltip="Remove custom palette" type="button" id="rmPal" onclick="palettesData=null;localStorage.removeItem('wledPalx');requestJson({rmcpal:true});setTimeout(loadPalettes,250,loadPalettesData);"><i class="icons btn-icon"></i></button>
|
<button class="btn btn-xs" title="Remove custom palette" type="button" id="rmPal" onclick="palettesData=null;localStorage.removeItem('wledPalx');requestJson({rmcpal:true});setTimeout(loadPalettes,250,loadPalettesData);"><i class="icons btn-icon"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<p class="labels" id="pall"><i class="icons sel-icon" onclick="tglHex()"></i> Color palette</p>
|
<p class="labels hd" id="pall"><i class="icons sel-icon" onclick="tglHex()"></i> Color palette</p>
|
||||||
<div id="palw" class="il">
|
<div id="palw" class="il">
|
||||||
<div class="staytop fnd">
|
<div class="staytop fnd">
|
||||||
<input type="text" placeholder="Search" oninput="search(this,'pallist')" onfocus="search(this,'pallist')" />
|
<input type="text" placeholder="Search" oninput="search(this,'pallist')" onfocus="search(this,'pallist')" />
|
||||||
@ -159,27 +159,27 @@
|
|||||||
<i class="icons clear-icon" onclick="clean(this);"></i>
|
<i class="icons clear-icon" onclick="clean(this);"></i>
|
||||||
<i class="icons search-icon" style="cursor:pointer;"></i>
|
<i class="icons search-icon" style="cursor:pointer;"></i>
|
||||||
<div id="filters" class="filter fade">
|
<div id="filters" class="filter fade">
|
||||||
<label id="filterPal" tooltip="Uses palette" class="check fchkl">🎨
|
<label id="filterPal" title="Uses palette" class="check fchkl">🎨
|
||||||
<input type="checkbox" data-flt="🎨" onchange="filterFx();">
|
<input type="checkbox" data-flt="🎨" onchange="filterFx();">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label id="filter0D" tooltip="Single pixel" class="check fchkl">•
|
<label id="filter0D" title="Single pixel" class="check fchkl">•
|
||||||
<input type="checkbox" data-flt="•" onchange="filterFx();">
|
<input type="checkbox" data-flt="•" onchange="filterFx();">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label id="filter1D" tooltip="1D" class="check fchkl">⋮
|
<label id="filter1D" title="1D" class="check fchkl">⋮
|
||||||
<input type="checkbox" data-flt="⋮" onchange="filterFx();">
|
<input type="checkbox" data-flt="⋮" onchange="filterFx();">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label id="filter2D" tooltip="2D" class="check fchkl">▦
|
<label id="filter2D" title="2D" class="check fchkl">▦
|
||||||
<input type="checkbox" data-flt="▦" onchange="filterFx();">
|
<input type="checkbox" data-flt="▦" onchange="filterFx();">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label id="filterVol" tooltip="Volume" class="check fchkl">♪
|
<label id="filterVol" title="Volume" class="check fchkl">♪
|
||||||
<input type="checkbox" data-flt="♪" onchange="filterFx();">
|
<input type="checkbox" data-flt="♪" onchange="filterFx();">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label id="filterFreq" tooltip="Frequency" class="check fchkl">♫
|
<label id="filterFreq" title="Frequency" class="check fchkl">♫
|
||||||
<input type="checkbox" data-flt="♫" onchange="filterFx();">
|
<input type="checkbox" data-flt="♫" onchange="filterFx();">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
@ -199,16 +199,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="sliders">
|
<div id="sliders">
|
||||||
<div id="slider0" class="slider">
|
<div id="slider0" class="slider">
|
||||||
<i class="icons slider-icon" onclick="tglFreeze()"></i>
|
<i class="icons slider-icon" title="Freeze" onclick="tglFreeze()"></i>
|
||||||
<div tooltip="Effect speed" class="sliderwrap il">
|
<div title="Effect speed" class="sliderwrap il">
|
||||||
<input id="sliderSpeed" class="noslide" onchange="setSpeed()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
|
<input id="sliderSpeed" class="noslide" onchange="setSpeed()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
|
||||||
<div class="sliderdisplay"></div>
|
<div class="sliderdisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
<output class="sliderbubble"></output>
|
<output class="sliderbubble"></output>
|
||||||
</div>
|
</div>
|
||||||
<div id="slider1" class="slider">
|
<div id="slider1" class="slider">
|
||||||
<i class="icons slider-icon" onclick="tglLabels()"></i>
|
<i class="icons slider-icon" title="Toggle labels" onclick="tglLabels()"></i>
|
||||||
<div tooltip="Effect intensity" class="sliderwrap il">
|
<div title="Effect intensity" class="sliderwrap il">
|
||||||
<input id="sliderIntensity" class="noslide" onchange="setIntensity()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
|
<input id="sliderIntensity" class="noslide" onchange="setIntensity()" oninput="updateTrail(this)" max="255" min="0" type="range" value="128" />
|
||||||
<div class="sliderdisplay"></div>
|
<div class="sliderdisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -216,7 +216,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="slider2" class="slider hide">
|
<div id="slider2" class="slider hide">
|
||||||
<i class="icons slider-icon"></i>
|
<i class="icons slider-icon"></i>
|
||||||
<div tooltip="Custom 1" class="sliderwrap il">
|
<div title="Custom 1" class="sliderwrap il">
|
||||||
<input id="sliderC1" class="noslide" onchange="setCustom(1)" oninput="updateTrail(this)" max="255" min="0" type="range" value="0" />
|
<input id="sliderC1" class="noslide" onchange="setCustom(1)" oninput="updateTrail(this)" max="255" min="0" type="range" value="0" />
|
||||||
<div class="sliderdisplay"></div>
|
<div class="sliderdisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -224,7 +224,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="slider3" class="slider hide">
|
<div id="slider3" class="slider hide">
|
||||||
<i class="icons slider-icon"></i>
|
<i class="icons slider-icon"></i>
|
||||||
<div tooltip="Custom 2" class="sliderwrap il">
|
<div title="Custom 2" class="sliderwrap il">
|
||||||
<input id="sliderC2" class="noslide" onchange="setCustom(2)" oninput="updateTrail(this)" max="255" min="0" type="range" value="0" />
|
<input id="sliderC2" class="noslide" onchange="setCustom(2)" oninput="updateTrail(this)" max="255" min="0" type="range" value="0" />
|
||||||
<div class="sliderdisplay"></div>
|
<div class="sliderdisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -232,22 +232,22 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="slider4" class="slider hide">
|
<div id="slider4" class="slider hide">
|
||||||
<i class="icons slider-icon"></i>
|
<i class="icons slider-icon"></i>
|
||||||
<div tooltip="Custom 3" class="sliderwrap il">
|
<div title="Custom 3" class="sliderwrap il">
|
||||||
<input id="sliderC3" class="noslide" onchange="setCustom(3)" oninput="updateTrail(this)" max="31" min="0" type="range" value="0" />
|
<input id="sliderC3" class="noslide" onchange="setCustom(3)" oninput="updateTrail(this)" max="31" min="0" type="range" value="0" />
|
||||||
<div class="sliderdisplay"></div>
|
<div class="sliderdisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
<output class="sliderbubble"></output>
|
<output class="sliderbubble"></output>
|
||||||
</div>
|
</div>
|
||||||
<div id="fxopt" class="option fade">
|
<div id="fxopt" class="option fade">
|
||||||
<label id="opt0" tooltip="Check 1" class="check ochkl hide"><i class="icons"></i>
|
<label id="opt0" title="Check 1" class="check ochkl hide"><i class="icons"></i>
|
||||||
<input id="checkO1" type="checkbox" onchange="setOption(1, this.checked)">
|
<input id="checkO1" type="checkbox" onchange="setOption(1, this.checked)">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label id="opt1" tooltip="Check 2" class="check ochkl hide"><i class="icons"></i>
|
<label id="opt1" title="Check 2" class="check ochkl hide"><i class="icons"></i>
|
||||||
<input id="checkO2" type="checkbox" onchange="setOption(2, this.checked)">
|
<input id="checkO2" type="checkbox" onchange="setOption(2, this.checked)">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label id="opt2" tooltip="Check 3" class="check ochkl hide"><i class="icons"></i>
|
<label id="opt2" title="Check 3" class="check ochkl hide"><i class="icons"></i>
|
||||||
<input id="checkO3" type="checkbox" onchange="setOption(3, this.checked)">
|
<input id="checkO3" type="checkbox" onchange="setOption(3, this.checked)">
|
||||||
<span class="checkmark"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
@ -256,6 +256,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="Segments" class="tabcontent">
|
<div id="Segments" class="tabcontent">
|
||||||
|
<p class="labels hd" id="segLabel">Segments</p>
|
||||||
<div id="segcont">
|
<div id="segcont">
|
||||||
Loading...
|
Loading...
|
||||||
</div>
|
</div>
|
||||||
|
@ -88,7 +88,6 @@ function setCSL(cs)
|
|||||||
function applyCfg()
|
function applyCfg()
|
||||||
{
|
{
|
||||||
cTheme(cfg.theme.base === "light");
|
cTheme(cfg.theme.base === "light");
|
||||||
gId("Colors").style.paddingTop = cfg.comp.colors.picker ? "0" : "28px";
|
|
||||||
var bg = cfg.theme.color.bg;
|
var bg = cfg.theme.color.bg;
|
||||||
if (bg) sCol('--c-1', bg);
|
if (bg) sCol('--c-1', bg);
|
||||||
var l = cfg.comp.labels;
|
var l = cfg.comp.labels;
|
||||||
@ -809,13 +808,13 @@ function populateSegments(s)
|
|||||||
`<span class="checkmark"></span>`+
|
`<span class="checkmark"></span>`+
|
||||||
`</label>`+
|
`</label>`+
|
||||||
`<div class="segname ${smpl}" onclick="selSegEx(${i})">`+
|
`<div class="segname ${smpl}" onclick="selSegEx(${i})">`+
|
||||||
`<i class="icons e-icon frz" id="seg${i}frz" onclick="event.preventDefault();tglFreeze(${i});">&#x${inst.frz ? (li.live && li.liveseg==i?'e410':'e0e8') : 'e325'};</i>`+
|
`<i class="icons e-icon frz" id="seg${i}frz" title="(un)Freeze" onclick="event.preventDefault();tglFreeze(${i});">&#x${inst.frz ? (li.live && li.liveseg==i?'e410':'e0e8') : 'e325'};</i>`+
|
||||||
(inst.n ? inst.n : "Segment "+i) +
|
(inst.n ? inst.n : "Segment "+i) +
|
||||||
`<div class="pop hide" onclick="event.preventDefault();event.stopPropagation();">`+
|
`<div class="pop hide" onclick="event.preventDefault();event.stopPropagation();">`+
|
||||||
`<i class="icons g-icon" style="color:${cG};" onclick="this.nextElementSibling.classList.toggle('hide');">ɸ${String.fromCharCode(inst.set+"A".charCodeAt(0))};</i>`+
|
`<i class="icons g-icon" title="Set group" style="color:${cG};" onclick="this.nextElementSibling.classList.toggle('hide');">ɸ${String.fromCharCode(inst.set+"A".charCodeAt(0))};</i>`+
|
||||||
`<div class="pop-c hide"><span style="color:var(--c-f);" onclick="setGrp(${i},0);">➊</span><span style="color:var(--c-r);" onclick="setGrp(${i},1);">➋</span><span style="color:var(--c-g);" onclick="setGrp(${i},2);">➌</span><span style="color:var(--c-l);" onclick="setGrp(${i},3);">➍</span></div>`+
|
`<div class="pop-c hide"><span style="color:var(--c-f);" onclick="setGrp(${i},0);">➊</span><span style="color:var(--c-r);" onclick="setGrp(${i},1);">➋</span><span style="color:var(--c-g);" onclick="setGrp(${i},2);">➌</span><span style="color:var(--c-l);" onclick="setGrp(${i},3);">➍</span></div>`+
|
||||||
`</div> `+
|
`</div> `+
|
||||||
`<i class="icons edit-icon flr ${smpl}" id="seg${i}nedit" onclick="tglSegn(${i})"></i>`+
|
`<i class="icons edit-icon flr ${smpl}" id="seg${i}nedit" title="Edit" onclick="tglSegn(${i})"></i>`+
|
||||||
`</div>`+
|
`</div>`+
|
||||||
`<i class="icons e-icon flr ${smpl}" id="sege${i}" onclick="expand(${i})"></i>`+
|
`<i class="icons e-icon flr ${smpl}" id="sege${i}" onclick="expand(${i})"></i>`+
|
||||||
(cfg.comp.segpwr ? segp : '') +
|
(cfg.comp.segpwr ? segp : '') +
|
||||||
@ -846,7 +845,7 @@ function populateSegments(s)
|
|||||||
`<tr>`+
|
`<tr>`+
|
||||||
`<td><input class="segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>`+
|
`<td><input class="segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>`+
|
||||||
`<td><input class="segn" id="seg${i}spc" type="number" min="0" max="255" value="${inst.spc}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>`+
|
`<td><input class="segn" id="seg${i}spc" type="number" min="0" max="255" value="${inst.spc}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>`+
|
||||||
`<td><button class="btn btn-xs" onclick="setSeg(${i})"><i class="icons btn-icon" id="segc${i}"></i></button></td>`+
|
`<td><button class="btn btn-xs" title="Update" onclick="setSeg(${i})"><i class="icons btn-icon" id="segc${i}"></i></button></td>`+
|
||||||
`</tr>`+
|
`</tr>`+
|
||||||
`</table>`+
|
`</table>`+
|
||||||
`<div class="h bp" id="seg${i}len"></div>`+
|
`<div class="h bp" id="seg${i}len"></div>`+
|
||||||
@ -898,6 +897,7 @@ function populateSegments(s)
|
|||||||
} else {
|
} else {
|
||||||
gId("ledmap").classList.add('hide');
|
gId("ledmap").classList.add('hide');
|
||||||
}
|
}
|
||||||
|
tooltip("#Segments");
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateEffects()
|
function populateEffects()
|
||||||
@ -1088,7 +1088,7 @@ function populateNodes(i,n)
|
|||||||
for (var o of n.nodes) {
|
for (var o of n.nodes) {
|
||||||
if (o.name) {
|
if (o.name) {
|
||||||
let onoff = `<i class="icons e-icon flr ${o.type&0x80?'':'off'}" onclick="rmtTgl('${o.ip}',this);""></i>`;
|
let onoff = `<i class="icons e-icon flr ${o.type&0x80?'':'off'}" onclick="rmtTgl('${o.ip}',this);""></i>`;
|
||||||
var url = `<button class="btn" title="${o.ip}" onclick="location.assign('http://${o.ip}');"><div class="bname">${bname(o)}</div>${o.vid<2307130?'':onoff}</button>`;
|
var url = `<a class="btn" title="${o.ip}" href="http://${o.ip}">${bname(o)}${o.vid<2307130?'':onoff}</a>`;
|
||||||
urows += inforow(url,`${btype(o.type&0x7F)}<br><i>${o.vid==0?"N/A":o.vid}</i>`);
|
urows += inforow(url,`${btype(o.type&0x7F)}<br><i>${o.vid==0?"N/A":o.vid}</i>`);
|
||||||
nnodes++;
|
nnodes++;
|
||||||
}
|
}
|
||||||
@ -1560,12 +1560,12 @@ function setEffectParameters(idx)
|
|||||||
// set html slider items on/off
|
// set html slider items on/off
|
||||||
let sliders = d.querySelectorAll("#sliders .sliderwrap");
|
let sliders = d.querySelectorAll("#sliders .sliderwrap");
|
||||||
sliders.forEach((slider, i)=>{
|
sliders.forEach((slider, i)=>{
|
||||||
let text = slider.getAttribute("tooltip");
|
let text = slider.getAttribute("title");
|
||||||
if ((!controlDefined && i<((idx<128)?2:nSliders)) || (slOnOff.length>i && slOnOff[i]!="")) {
|
if ((!controlDefined && i<((idx<128)?2:nSliders)) || (slOnOff.length>i && slOnOff[i]!="")) {
|
||||||
if (slOnOff.length>i && slOnOff[i]!="!") text = slOnOff[i];
|
if (slOnOff.length>i && slOnOff[i]!="!") text = slOnOff[i];
|
||||||
// restore overwritten default tooltips
|
// restore overwritten default tooltips
|
||||||
if (i<2 && slOnOff[i]==="!") text = i==0 ? "Effect speed" : "Effect intensity";
|
if (i<2 && slOnOff[i]==="!") text = i==0 ? "Effect speed" : "Effect intensity";
|
||||||
slider.setAttribute("tooltip", text);
|
slider.setAttribute("title", text);
|
||||||
slider.parentElement.classList.remove('hide');
|
slider.parentElement.classList.remove('hide');
|
||||||
} else
|
} else
|
||||||
slider.parentElement.classList.add('hide');
|
slider.parentElement.classList.add('hide');
|
||||||
@ -1575,10 +1575,10 @@ function setEffectParameters(idx)
|
|||||||
gId('fxopt').classList.remove('fade');
|
gId('fxopt').classList.remove('fade');
|
||||||
let checks = d.querySelectorAll("#sliders .ochkl");
|
let checks = d.querySelectorAll("#sliders .ochkl");
|
||||||
checks.forEach((check, i)=>{
|
checks.forEach((check, i)=>{
|
||||||
let text = check.getAttribute("tooltip");
|
let text = check.getAttribute("title");
|
||||||
if (5+i<slOnOff.length && slOnOff[5+i]!=='') {
|
if (5+i<slOnOff.length && slOnOff[5+i]!=='') {
|
||||||
if (slOnOff.length>5+i && slOnOff[5+i]!="!") text = slOnOff[5+i];
|
if (slOnOff.length>5+i && slOnOff[5+i]!="!") text = slOnOff[5+i];
|
||||||
check.setAttribute("tooltip", text);
|
check.setAttribute("title", text);
|
||||||
check.classList.remove('hide');
|
check.classList.remove('hide');
|
||||||
} else
|
} else
|
||||||
check.classList.add('hide');
|
check.classList.add('hide');
|
||||||
@ -1876,7 +1876,7 @@ function resetUtil(off=false)
|
|||||||
+ '<label class="check schkl"><input type="checkbox" id="selall" onchange="selSegAll(this)"><span class="checkmark"></span></label>'
|
+ '<label class="check schkl"><input type="checkbox" id="selall" onchange="selSegAll(this)"><span class="checkmark"></span></label>'
|
||||||
+ `<div class="segname" ${off?'':'onclick="makeSeg()"'}><i class="icons btn-icon"></i>Add segment</div>`
|
+ `<div class="segname" ${off?'':'onclick="makeSeg()"'}><i class="icons btn-icon"></i>Add segment</div>`
|
||||||
+ '<div class="pop hide" onclick="event.stopPropagation();">'
|
+ '<div class="pop hide" onclick="event.stopPropagation();">'
|
||||||
+ `<i class="icons g-icon" onclick="this.nextElementSibling.classList.toggle('hide');"></i>`
|
+ `<i class="icons g-icon" title="Select group" onclick="this.nextElementSibling.classList.toggle('hide');"></i>`
|
||||||
+ '<div class="pop-c hide"><span style="color:var(--c-f);" onclick="selGrp(0);">➊</span><span style="color:var(--c-r);" onclick="selGrp(1);">➋</span><span style="color:var(--c-g);" onclick="selGrp(2);">➌</span><span style="color:var(--c-l);" onclick="selGrp(3);">➍</span></div>'
|
+ '<div class="pop-c hide"><span style="color:var(--c-f);" onclick="selGrp(0);">➊</span><span style="color:var(--c-r);" onclick="selGrp(1);">➋</span><span style="color:var(--c-g);" onclick="selGrp(2);">➌</span><span style="color:var(--c-l);" onclick="selGrp(3);">➍</span></div>'
|
||||||
+ '</div></div>';
|
+ '</div></div>';
|
||||||
}
|
}
|
||||||
@ -2514,8 +2514,8 @@ function selectSlot(b)
|
|||||||
{
|
{
|
||||||
csel = b;
|
csel = b;
|
||||||
var cd = gId('csl').children;
|
var cd = gId('csl').children;
|
||||||
for (let i of cd) i.classList.remove('xxs-w');
|
for (let i of cd) i.classList.remove('sl');
|
||||||
cd[b].classList.add('xxs-w');
|
cd[b].classList.add('sl');
|
||||||
setPicker(rgbStr(cd[b].dataset));
|
setPicker(rgbStr(cd[b].dataset));
|
||||||
// force slider update on initial load (picker "color:change" not fired if black)
|
// force slider update on initial load (picker "color:change" not fired if black)
|
||||||
if (cpick.color.value == 0) updatePSliders();
|
if (cpick.color.value == 0) updatePSliders();
|
||||||
@ -2802,6 +2802,7 @@ function search(field, listId = null) {
|
|||||||
if (!listId) return;
|
if (!listId) return;
|
||||||
|
|
||||||
const search = field.value !== '';
|
const search = field.value !== '';
|
||||||
|
const presets = listId === 'pcont';
|
||||||
|
|
||||||
// clear filter if searching in fxlist
|
// clear filter if searching in fxlist
|
||||||
if (listId === 'fxlist' && search) {
|
if (listId === 'fxlist' && search) {
|
||||||
@ -2813,7 +2814,7 @@ function search(field, listId = null) {
|
|||||||
|
|
||||||
const listItems = gId(listId).querySelectorAll('.lstI');
|
const listItems = gId(listId).querySelectorAll('.lstI');
|
||||||
// filter list items but leave (Default & Solid) always visible
|
// filter list items but leave (Default & Solid) always visible
|
||||||
for (i = (listId === 'pcont' ? 0 : 1); i < listItems.length; i++) {
|
for (i = (presets ? 0 : 1); i < listItems.length; i++) {
|
||||||
const listItem = listItems[i];
|
const listItem = listItems[i];
|
||||||
const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase();
|
const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase();
|
||||||
const searchIndex = listItemName.indexOf(field.value.toUpperCase());
|
const searchIndex = listItemName.indexOf(field.value.toUpperCase());
|
||||||
@ -2821,6 +2822,7 @@ function search(field, listId = null) {
|
|||||||
listItem.dataset.searchIndex = searchIndex;
|
listItem.dataset.searchIndex = searchIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!presets) {
|
||||||
// sort list items by search index and name
|
// sort list items by search index and name
|
||||||
const sortedListItems = Array.from(listItems).sort((a, b) => {
|
const sortedListItems = Array.from(listItems).sort((a, b) => {
|
||||||
const aSearchIndex = parseInt(a.dataset.searchIndex);
|
const aSearchIndex = parseInt(a.dataset.searchIndex);
|
||||||
@ -2845,6 +2847,7 @@ function search(field, listId = null) {
|
|||||||
firstVisibleItem.scrollIntoView({ behavior: "instant", block: "center" });
|
firstVisibleItem.scrollIntoView({ behavior: "instant", block: "center" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function clean(clearButton) {
|
function clean(clearButton) {
|
||||||
clearButton.style.display = 'none';
|
clearButton.style.display = 'none';
|
||||||
@ -3071,14 +3074,19 @@ function mergeDeep(target, ...sources)
|
|||||||
return mergeDeep(target, ...sources);
|
return mergeDeep(target, ...sources);
|
||||||
}
|
}
|
||||||
|
|
||||||
function tooltip()
|
function tooltip(cont=null)
|
||||||
{
|
{
|
||||||
const elements = d.querySelectorAll("[tooltip]");
|
const elements = d.querySelectorAll((cont?cont+" ":"")+"[title]");
|
||||||
elements.forEach((element)=>{
|
elements.forEach((element)=>{
|
||||||
element.addEventListener("mouseover", ()=>{
|
element.addEventListener("mouseover", ()=>{
|
||||||
|
// save title
|
||||||
|
element.setAttribute("data-title", element.getAttribute("title"));
|
||||||
const tooltip = d.createElement("span");
|
const tooltip = d.createElement("span");
|
||||||
tooltip.className = "tooltip";
|
tooltip.className = "tooltip";
|
||||||
tooltip.textContent = element.getAttribute("tooltip");
|
tooltip.textContent = element.getAttribute("title");
|
||||||
|
|
||||||
|
// prevent default title popup
|
||||||
|
element.removeAttribute("title");
|
||||||
|
|
||||||
let { top, left, width } = element.getBoundingClientRect();
|
let { top, left, width } = element.getBoundingClientRect();
|
||||||
|
|
||||||
@ -3101,6 +3109,8 @@ function tooltip()
|
|||||||
tooltip.classList.remove("visible");
|
tooltip.classList.remove("visible");
|
||||||
d.body.removeChild(tooltip);
|
d.body.removeChild(tooltip);
|
||||||
});
|
});
|
||||||
|
// restore title
|
||||||
|
element.setAttribute("title", element.getAttribute("data-title"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -394,6 +394,7 @@ ${i+1}:
|
|||||||
<option value="24">400kHz</option>\
|
<option value="24">400kHz</option>\
|
||||||
<option value="25">TM1829</option>\
|
<option value="25">TM1829</option>\
|
||||||
<option value="26">UCS8903</option>\
|
<option value="26">UCS8903</option>\
|
||||||
|
<option value="27">APA106/PL9823</option>\
|
||||||
<option value="29">UCS8904 RGBW</option>\
|
<option value="29">UCS8904 RGBW</option>\
|
||||||
<option value="50">WS2801</option>\
|
<option value="50">WS2801</option>\
|
||||||
<option value="51">APA102</option>\
|
<option value="51">APA102</option>\
|
||||||
|
@ -212,6 +212,7 @@
|
|||||||
12h LED: <input name="OM" type="number" min="0" max="255" required><br>
|
12h LED: <input name="OM" type="number" min="0" max="255" required><br>
|
||||||
Show 5min marks: <input type="checkbox" name="O5"><br>
|
Show 5min marks: <input type="checkbox" name="O5"><br>
|
||||||
Seconds (as trail): <input type="checkbox" name="OS"><br>
|
Seconds (as trail): <input type="checkbox" name="OS"><br>
|
||||||
|
Show clock overlay only if all LEDs are solid black: <input type="checkbox" name="OB"><br>
|
||||||
</div>
|
</div>
|
||||||
Countdown Mode: <input type="checkbox" name="CE"><br>
|
Countdown Mode: <input type="checkbox" name="CE"><br>
|
||||||
Countdown Goal:<br>
|
Countdown Goal:<br>
|
||||||
|
@ -227,10 +227,10 @@
|
|||||||
} else if (typeof(fld) === "number") sel.classList.add("pin"); // a hack to add a class
|
} else if (typeof(fld) === "number") sel.classList.add("pin"); // a hack to add a class
|
||||||
let arr = d.getElementsByName(um);
|
let arr = d.getElementsByName(um);
|
||||||
let idx = arr[0].type==="hidden"?1:0; // ignore hidden field
|
let idx = arr[0].type==="hidden"?1:0; // ignore hidden field
|
||||||
if (arr.length > 2) {
|
if (arr.length > 1+idx) {
|
||||||
// we have array of values (usually pins)
|
// we have array of values (usually pins)
|
||||||
for (let i of arr) {
|
for (let i of arr) {
|
||||||
if (i.type === "number") break;
|
if (i.nodeName === "INPUT" && i.type === "number") break;
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
var d = document;
|
var d = document;
|
||||||
var loc = false, locip, locproto = "http:";
|
var loc = false, locip, locproto = "http:";
|
||||||
var scanLoops = 0, preScanSSID = "";
|
var scanLoops = 0, preScanSSID = "";
|
||||||
|
var maxNetworks = 3;
|
||||||
function gId(e) { return d.getElementById(e); }
|
function gId(e) { return d.getElementById(e); }
|
||||||
function cE(e) { return d.createElement(e); }
|
function cE(e) { return d.createElement(e); }
|
||||||
function toggle(el){gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide");}
|
function toggle(el){gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide");}
|
||||||
@ -52,13 +52,14 @@
|
|||||||
}
|
}
|
||||||
scanLoops = 0;
|
scanLoops = 0;
|
||||||
|
|
||||||
let cs = gId("CS");
|
let cs = d.querySelectorAll("#wifi_entries input[type=text]");
|
||||||
if (cs) {
|
for (let input of (cs||[])) {
|
||||||
|
let found = false;
|
||||||
let select = cE("select");
|
let select = cE("select");
|
||||||
select.setAttribute("id", "CS");
|
select.id = input.id;
|
||||||
select.setAttribute("name", "CS");
|
select.name = input.name;
|
||||||
select.setAttribute("onchange", "T()");
|
select.setAttribute("onchange", "T(this)");
|
||||||
preScanSSID = cs.value;
|
preScanSSID = input.value;
|
||||||
|
|
||||||
for (let i = 0; i < select.children.length; i++) {
|
for (let i = 0; i < select.children.length; i++) {
|
||||||
select.removeChild(select.children[i]);
|
select.removeChild(select.children[i]);
|
||||||
@ -70,8 +71,9 @@
|
|||||||
option.setAttribute("value", networks[i].ssid);
|
option.setAttribute("value", networks[i].ssid);
|
||||||
option.textContent = `${networks[i].ssid} (${networks[i].rssi} dBm)`;
|
option.textContent = `${networks[i].ssid} (${networks[i].rssi} dBm)`;
|
||||||
|
|
||||||
if (networks[i].ssid === cs.value) {
|
if (networks[i].ssid === input.value) {
|
||||||
option.setAttribute("selected", "selected");
|
option.setAttribute("selected", "selected");
|
||||||
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
select.appendChild(option);
|
select.appendChild(option);
|
||||||
@ -79,10 +81,11 @@
|
|||||||
const option = cE("option");
|
const option = cE("option");
|
||||||
|
|
||||||
option.setAttribute("value", "!Cs");
|
option.setAttribute("value", "!Cs");
|
||||||
option.textContent = `Other network...`;
|
option.textContent = "Other network...";
|
||||||
select.appendChild(option);
|
select.appendChild(option);
|
||||||
|
|
||||||
cs.replaceWith(select);
|
if (input.value === "" || found) input.replaceWith(select);
|
||||||
|
else select.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
button.disabled = false;
|
button.disabled = false;
|
||||||
@ -90,17 +93,48 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// replace WiFi select with custom SSID input field again
|
// replace WiFi select with custom SSID input field again
|
||||||
function T() {
|
function T(cs) {
|
||||||
let cs = gId("CS");
|
|
||||||
if (!cs || cs.value != "!Cs") return;
|
if (!cs || cs.value != "!Cs") return;
|
||||||
let input = cE("input");
|
let input = cE("input");
|
||||||
input.type = "text";
|
input.type = "text";
|
||||||
input.id = "CS";
|
input.id = cs.id;
|
||||||
input.name ="CS";
|
input.name = cs.name;
|
||||||
input.setAttribute("maxlength",32);
|
input.setAttribute("maxlength",32);
|
||||||
input.value = preScanSSID;
|
input.value = preScanSSID;
|
||||||
cs.replaceWith(input);
|
cs.replaceWith(input);
|
||||||
}
|
}
|
||||||
|
function resetWiFi(maxN = undefined) {
|
||||||
|
if (maxN) maxNetworks = maxN;
|
||||||
|
let entries = gId("wifi_entries").children
|
||||||
|
for (let i = entries.length; i > 0; i--) entries[i-1].remove();
|
||||||
|
btnWiFi(0);
|
||||||
|
}
|
||||||
|
function btnWiFi(i) {
|
||||||
|
gId("wifi_add").style.display = (i<maxNetworks) ? "inline":"none";
|
||||||
|
gId("wifi_rem").style.display = (i>1) ? "inline":"none";
|
||||||
|
}
|
||||||
|
function addWiFi(ssid="",pass="",ip=0,gw=0,sn=0x00ffffff) { // little endian
|
||||||
|
var i = gId("wifi_entries").childNodes.length;
|
||||||
|
if (i >= maxNetworks) return;
|
||||||
|
var b = `<div id="net${i}"><hr class="sml">
|
||||||
|
Network name (SSID${i==0?", empty to not connect":""}):<br><input type="text" id="CS${i}" name="CS${i}" maxlength="32" value="${ssid}" ${i>0?"required":""}><br>
|
||||||
|
Network password:<br><input type="password" name="PW${i}" maxlength="64" value="${pass}"><br>
|
||||||
|
Static IP (leave at 0.0.0.0 for DHCP)${i==0?"<br>Also used by Ethernet":""}:<br>
|
||||||
|
<input name="IP${i}0" type="number" class="s" min="0" max="255" value="${ip&0xFF}" required>.<input name="IP${i}1" type="number" class="s" min="0" max="255" value="${(ip>>8)&0xFF}" required>.<input name="IP${i}2" type="number" class="s" min="0" max="255" value="${(ip>>16)&0xFF}" required>.<input name="IP${i}3" type="number" class="s" min="0" max="255" value="${(ip>>24)&0xFF}" required><br>
|
||||||
|
Static gateway:<br>
|
||||||
|
<input name="GW${i}0" type="number" class="s" min="0" max="255" value="${gw&0xFF}" required>.<input name="GW${i}1" type="number" class="s" min="0" max="255" value="${(gw>>8)&0xFF}" required>.<input name="GW${i}2" type="number" class="s" min="0" max="255" value="${(gw>>16)&0xFF}" required>.<input name="GW${i}3" type="number" class="s" min="0" max="255" value="${(gw>>24)&0xFF}" required><br>
|
||||||
|
Static subnet mask:<br>
|
||||||
|
<input name="SN${i}0" type="number" class="s" min="0" max="255" value="${sn&0xFF}" required>.<input name="SN${i}1" type="number" class="s" min="0" max="255" value="${(sn>>8)&0xFF}" required>.<input name="SN${i}2" type="number" class="s" min="0" max="255" value="${(sn>>16)&0xFF}" required>.<input name="SN${i}3" type="number" class="s" min="0" max="255" value="${(sn>>24)&0xFF}" required></div>`;
|
||||||
|
gId("wifi_entries").insertAdjacentHTML("beforeend", b);
|
||||||
|
btnWiFi(i+1);
|
||||||
|
}
|
||||||
|
function remWiFi() {
|
||||||
|
const entries = gId("wifi_entries").children;
|
||||||
|
const i = entries.length;
|
||||||
|
if (i < 2) return;
|
||||||
|
entries[i-1].remove();
|
||||||
|
btnWiFi(i-1);
|
||||||
|
}
|
||||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||||
function loadJS(FILE_URL, async = true) {
|
function loadJS(FILE_URL, async = true) {
|
||||||
let scE = cE("script");
|
let scE = cE("script");
|
||||||
@ -158,24 +192,16 @@
|
|||||||
<h2>WiFi setup</h2>
|
<h2>WiFi setup</h2>
|
||||||
<h3>Connect to existing network</h3>
|
<h3>Connect to existing network</h3>
|
||||||
<button type="button" id="scan" onclick="N()">Scan</button><br>
|
<button type="button" id="scan" onclick="N()">Scan</button><br>
|
||||||
Network name (SSID, empty to not connect):<br>
|
<div id="wifi">
|
||||||
<input type="text" id="CS" name="CS" maxlength="32"><br>
|
Wireless networks
|
||||||
Network password: <br> <input type="password" name="CP" maxlength="63"><br>
|
<div id="wifi_entries"></div>
|
||||||
Static IP (leave at 0.0.0.0 for DHCP):<br>
|
<hr class="sml">
|
||||||
<input name="I0" type="number" class="s" min="0" max="255" required> .
|
<button type="button" id="wifi_add" onclick="addWiFi()">+</button>
|
||||||
<input name="I1" type="number" class="s" min="0" max="255" required> .
|
<button type="button" id="wifi_rem" onclick="remWiFi()">-</button><br>
|
||||||
<input name="I2" type="number" class="s" min="0" max="255" required> .
|
</div>
|
||||||
<input name="I3" type="number" class="s" min="0" max="255" required><br>
|
DNS server address:<br>
|
||||||
Static gateway:<br>
|
<input name="D0" type="number" class="s" min="0" max="255" required>.<input name="D1" type="number" class="s" min="0" max="255" required>.<input name="D2" type="number" class="s" min="0" max="255" required>.<input name="D3" type="number" class="s" min="0" max="255" required><br>
|
||||||
<input name="G0" type="number" class="s" min="0" max="255" required> .
|
<br>
|
||||||
<input name="G1" type="number" class="s" min="0" max="255" required> .
|
|
||||||
<input name="G2" type="number" class="s" min="0" max="255" required> .
|
|
||||||
<input name="G3" type="number" class="s" min="0" max="255" required><br>
|
|
||||||
Static subnet mask:<br>
|
|
||||||
<input name="S0" type="number" class="s" min="0" max="255" required> .
|
|
||||||
<input name="S1" type="number" class="s" min="0" max="255" required> .
|
|
||||||
<input name="S2" type="number" class="s" min="0" max="255" required> .
|
|
||||||
<input name="S3" type="number" class="s" min="0" max="255" required><br>
|
|
||||||
mDNS address (leave empty for no mDNS):<br>
|
mDNS address (leave empty for no mDNS):<br>
|
||||||
http:// <input type="text" name="CM" maxlength="32"> .local<br>
|
http:// <input type="text" name="CM" maxlength="32"> .local<br>
|
||||||
Client IP: <span class="sip"> Not connected </span> <br>
|
Client IP: <span class="sip"> Not connected </span> <br>
|
||||||
@ -189,7 +215,9 @@
|
|||||||
<option value="0">No connection after boot</option>
|
<option value="0">No connection after boot</option>
|
||||||
<option value="1">Disconnected</option>
|
<option value="1">Disconnected</option>
|
||||||
<option value="2">Always</option>
|
<option value="2">Always</option>
|
||||||
<option value="3">Never (not recommended)</option></select><br>
|
<option value="3">Never (not recommended)</option>
|
||||||
|
<option value="4">Temporary (no connection after boot)</option>
|
||||||
|
</select><br>
|
||||||
AP IP: <span class="sip"> Not active </span><br>
|
AP IP: <span class="sip"> Not active </span><br>
|
||||||
<h3>Experimental</h3>
|
<h3>Experimental</h3>
|
||||||
Force 802.11g mode (ESP8266 only): <input type="checkbox" name="FG"><br>
|
Force 802.11g mode (ESP8266 only): <input type="checkbox" name="FG"><br>
|
||||||
@ -215,6 +243,7 @@
|
|||||||
<option value="0">None</option>
|
<option value="0">None</option>
|
||||||
<option value="9">ABC! WLED V43 & compatible</option>
|
<option value="9">ABC! WLED V43 & compatible</option>
|
||||||
<option value="2">ESP32-POE</option>
|
<option value="2">ESP32-POE</option>
|
||||||
|
<option value="11">ESP32-POE-WROVER</option>
|
||||||
<option value="6">ESP32Deux</option>
|
<option value="6">ESP32Deux</option>
|
||||||
<option value="7">KIT-VE</option>
|
<option value="7">KIT-VE</option>
|
||||||
<option value="8">QuinLED-Dig-Octa & T-ETH-POE</option>
|
<option value="8">QuinLED-Dig-Octa & T-ETH-POE</option>
|
||||||
|
@ -81,6 +81,7 @@ input:disabled {
|
|||||||
}
|
}
|
||||||
input[type="text"],
|
input[type="text"],
|
||||||
input[type="number"],
|
input[type="number"],
|
||||||
|
input[type="password"],
|
||||||
select {
|
select {
|
||||||
font-size: medium;
|
font-size: medium;
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
|
@ -490,7 +490,7 @@ void prepareArtnetPollReply(ArtPollReply *reply) {
|
|||||||
// Node is DHCP capable
|
// Node is DHCP capable
|
||||||
// Node supports 15 bit Port-Address (Art-Net 3 or 4)
|
// Node supports 15 bit Port-Address (Art-Net 3 or 4)
|
||||||
// Node is able to switch between ArtNet and sACN
|
// Node is able to switch between ArtNet and sACN
|
||||||
reply->reply_status_2 = (staticIP[0] == 0) ? 0x1F : 0x1D;
|
reply->reply_status_2 = (multiWiFi[0].staticIP[0] == 0) ? 0x1F : 0x1D;
|
||||||
|
|
||||||
// RDM is disabled
|
// RDM is disabled
|
||||||
// Output style is continuous
|
// Output style is continuous
|
||||||
|
@ -48,6 +48,21 @@ bool getJsonValue(const JsonVariant& element, DestType& destination, const Defau
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct WiFiConfig {
|
||||||
|
char clientSSID[33];
|
||||||
|
char clientPass[65];
|
||||||
|
IPAddress staticIP;
|
||||||
|
IPAddress staticGW;
|
||||||
|
IPAddress staticSN;
|
||||||
|
WiFiConfig(const char *ssid="", const char *pass="", uint32_t ip=0, uint32_t gw=0, uint32_t subnet=0x00FFFFFF) // little endian
|
||||||
|
: staticIP(ip)
|
||||||
|
, staticGW(gw)
|
||||||
|
, staticSN(subnet)
|
||||||
|
{
|
||||||
|
strncpy(clientSSID, ssid, 32); clientSSID[32] = 0;
|
||||||
|
strncpy(clientPass, pass, 64); clientPass[64] = 0;
|
||||||
|
}
|
||||||
|
} wifi_config;
|
||||||
|
|
||||||
//colors.cpp
|
//colors.cpp
|
||||||
// similar to NeoPixelBus NeoGammaTableMethod but allows dynamic changes (superseded by NPB::NeoGammaDynamicTableMethod)
|
// similar to NeoPixelBus NeoGammaTableMethod but allows dynamic changes (superseded by NPB::NeoGammaDynamicTableMethod)
|
||||||
|
@ -259,14 +259,14 @@ void parseWiFiCommand(char* rpcData) {
|
|||||||
|
|
||||||
uint8_t ssidLen = rpcData[1];
|
uint8_t ssidLen = rpcData[1];
|
||||||
if (ssidLen > len -1 || ssidLen > 32) return;
|
if (ssidLen > len -1 || ssidLen > 32) return;
|
||||||
memset(clientSSID, 0, 32);
|
memset(multiWiFi[0].clientSSID, 0, 32);
|
||||||
memcpy(clientSSID, rpcData+2, ssidLen);
|
memcpy(multiWiFi[0].clientSSID, rpcData+2, ssidLen);
|
||||||
|
|
||||||
memset(clientPass, 0, 64);
|
memset(multiWiFi[0].clientPass, 0, 64);
|
||||||
if (len > ssidLen +1) {
|
if (len > ssidLen +1) {
|
||||||
uint8_t passLen = rpcData[2+ssidLen];
|
uint8_t passLen = rpcData[2+ssidLen];
|
||||||
memset(clientPass, 0, 64);
|
memset(multiWiFi[0].clientPass, 0, 64);
|
||||||
memcpy(clientPass, rpcData+3+ssidLen, passLen);
|
memcpy(multiWiFi[0].clientPass, rpcData+3+ssidLen, passLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendImprovStateResponse(0x03); //provisioning
|
sendImprovStateResponse(0x03); //provisioning
|
||||||
|
@ -470,6 +470,19 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JsonObject wifi = root[F("wifi")];
|
||||||
|
if (!wifi.isNull()) {
|
||||||
|
bool apMode = getBoolVal(wifi[F("ap")], apActive);
|
||||||
|
if (!apActive && apMode) WLED::instance().initAP(); // start AP mode immediately
|
||||||
|
else if (apActive && !apMode) { // stop AP mode immediately
|
||||||
|
dnsServer.stop();
|
||||||
|
WiFi.softAPdisconnect(true);
|
||||||
|
apActive = false;
|
||||||
|
}
|
||||||
|
//bool restart = wifi[F("restart")] | false;
|
||||||
|
//if (restart) forceReconnect = true;
|
||||||
|
}
|
||||||
|
|
||||||
stateUpdated(callMode);
|
stateUpdated(callMode);
|
||||||
if (presetToRestore) currentPreset = presetToRestore;
|
if (presetToRestore) currentPreset = presetToRestore;
|
||||||
|
|
||||||
|
@ -123,6 +123,16 @@ const ethernet_settings ethernetBoards[] = {
|
|||||||
18, // eth_mdio,
|
18, // eth_mdio,
|
||||||
ETH_PHY_LAN8720, // eth_type,
|
ETH_PHY_LAN8720, // eth_type,
|
||||||
ETH_CLOCK_GPIO17_OUT // eth_clk_mode
|
ETH_CLOCK_GPIO17_OUT // eth_clk_mode
|
||||||
|
},
|
||||||
|
|
||||||
|
// ESP32-POE-WROVER
|
||||||
|
{
|
||||||
|
0, // eth_address,
|
||||||
|
12, // eth_power,
|
||||||
|
23, // eth_mdc,
|
||||||
|
18, // eth_mdio,
|
||||||
|
ETH_PHY_LAN8720, // eth_type,
|
||||||
|
ETH_CLOCK_GPIO0_OUT // eth_clk_mode
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@ -163,8 +173,8 @@ void WiFiEvent(WiFiEvent_t event)
|
|||||||
if (!apActive) {
|
if (!apActive) {
|
||||||
WiFi.disconnect(true);
|
WiFi.disconnect(true);
|
||||||
}
|
}
|
||||||
if (staticIP != (uint32_t)0x00000000 && staticGateway != (uint32_t)0x00000000) {
|
if (multiWiFi[0].staticIP != (uint32_t)0x00000000 && multiWiFi[0].staticGW != (uint32_t)0x00000000) {
|
||||||
ETH.config(staticIP, staticGateway, staticSubnet, IPAddress(8, 8, 8, 8));
|
ETH.config(multiWiFi[0].staticIP, multiWiFi[0].staticGW, multiWiFi[0].staticSN, dnsAddress);
|
||||||
} else {
|
} else {
|
||||||
ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||||
}
|
}
|
||||||
|
@ -89,6 +89,16 @@ void _overlayAnalogCountdown()
|
|||||||
|
|
||||||
void handleOverlayDraw() {
|
void handleOverlayDraw() {
|
||||||
usermods.handleOverlayDraw();
|
usermods.handleOverlayDraw();
|
||||||
|
if (analogClockSolidBlack) {
|
||||||
|
const Segment* segments = strip.getSegments();
|
||||||
|
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
|
const Segment& segment = segments[i];
|
||||||
|
if (!segment.isActive()) continue;
|
||||||
|
if (segment.mode > 0 || segment.colors[0] > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (overlayCurrent == 1) _overlayAnalogClock();
|
if (overlayCurrent == 1) _overlayAnalogClock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ static bool remoteJson(int button)
|
|||||||
JsonObject fdo = pDoc->as<JsonObject>();
|
JsonObject fdo = pDoc->as<JsonObject>();
|
||||||
if (fdo.isNull()) {
|
if (fdo.isNull()) {
|
||||||
// the received button does not exist
|
// the received button does not exist
|
||||||
if (!WLED_FS.exists("/remote.json")) errorFlag = ERR_FS_RMLOAD; //warn if file itself doesn't exist
|
//if (!WLED_FS.exists("/remote.json")) errorFlag = ERR_FS_RMLOAD; //warn if file itself doesn't exist
|
||||||
releaseJSONBufferLock();
|
releaseJSONBufferLock();
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
@ -19,21 +19,52 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
//WIFI SETTINGS
|
//WIFI SETTINGS
|
||||||
if (subPage == SUBPAGE_WIFI)
|
if (subPage == SUBPAGE_WIFI)
|
||||||
{
|
{
|
||||||
char oldSSID[sizeof(clientSSID)];
|
unsigned cnt = 0;
|
||||||
|
for (size_t n = 0; n < WLED_MAX_WIFI_COUNT; n++) {
|
||||||
|
char cs[4] = "CS"; cs[2] = 48+n; cs[3] = 0; //client SSID
|
||||||
|
char pw[4] = "PW"; pw[2] = 48+n; pw[3] = 0; //client password
|
||||||
|
char ip[5] = "IP"; ip[2] = 48+n; ip[4] = 0; //IP address
|
||||||
|
char gw[5] = "GW"; gw[2] = 48+n; gw[4] = 0; //GW address
|
||||||
|
char sn[5] = "SN"; sn[2] = 48+n; sn[4] = 0; //subnet mask
|
||||||
|
if (request->hasArg(cs)) {
|
||||||
|
if (n >= multiWiFi.size()) multiWiFi.push_back(WiFiConfig()); // expand vector by one
|
||||||
|
char oldSSID[33]; strcpy(oldSSID, multiWiFi[n].clientSSID);
|
||||||
|
char oldPass[65]; strcpy(oldPass, multiWiFi[n].clientPass);
|
||||||
|
|
||||||
strcpy(oldSSID, clientSSID);
|
strlcpy(multiWiFi[n].clientSSID, request->arg(cs).c_str(), 33);
|
||||||
strlcpy(clientSSID,request->arg(F("CS")).c_str(), 33);
|
if (strlen(oldSSID) == 0 || !strncmp(multiWiFi[n].clientSSID, oldSSID, 32)) {
|
||||||
if (!strcmp(oldSSID, clientSSID)) forceReconnect = true;
|
|
||||||
|
|
||||||
if (!isAsterisksOnly(request->arg(F("CP")).c_str(), 65)) {
|
|
||||||
strlcpy(clientPass, request->arg(F("CP")).c_str(), 65);
|
|
||||||
forceReconnect = true;
|
forceReconnect = true;
|
||||||
}
|
}
|
||||||
|
if (!isAsterisksOnly(request->arg(pw).c_str(), 65)) {
|
||||||
|
strlcpy(multiWiFi[n].clientPass, request->arg(pw).c_str(), 65);
|
||||||
|
forceReconnect = true;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < 4; i++) {
|
||||||
|
ip[3] = 48+i;
|
||||||
|
gw[3] = 48+i;
|
||||||
|
sn[3] = 48+i;
|
||||||
|
multiWiFi[n].staticIP[i] = request->arg(ip).toInt();
|
||||||
|
multiWiFi[n].staticGW[i] = request->arg(gw).toInt();
|
||||||
|
multiWiFi[n].staticSN[i] = request->arg(sn).toInt();
|
||||||
|
}
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// remove unused
|
||||||
|
if (cnt < multiWiFi.size()) {
|
||||||
|
cnt = multiWiFi.size() - cnt;
|
||||||
|
while (cnt--) multiWiFi.pop_back();
|
||||||
|
multiWiFi.shrink_to_fit(); // release memory
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request->hasArg(F("D0"))) {
|
||||||
|
dnsAddress = IPAddress(request->arg(F("D0")).toInt(),request->arg(F("D1")).toInt(),request->arg(F("D2")).toInt(),request->arg(F("D3")).toInt());
|
||||||
|
}
|
||||||
|
|
||||||
strlcpy(cmDNS, request->arg(F("CM")).c_str(), 33);
|
strlcpy(cmDNS, request->arg(F("CM")).c_str(), 33);
|
||||||
|
|
||||||
apBehavior = request->arg(F("AB")).toInt();
|
apBehavior = request->arg(F("AB")).toInt();
|
||||||
strcpy(oldSSID, apSSID);
|
char oldSSID[33]; strcpy(oldSSID, apSSID);
|
||||||
strlcpy(apSSID, request->arg(F("AS")).c_str(), 33);
|
strlcpy(apSSID, request->arg(F("AS")).c_str(), 33);
|
||||||
if (!strcmp(oldSSID, apSSID) && apActive) forceReconnect = true;
|
if (!strcmp(oldSSID, apSSID) && apActive) forceReconnect = true;
|
||||||
apHide = request->hasArg(F("AH"));
|
apHide = request->hasArg(F("AH"));
|
||||||
@ -61,21 +92,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
ethernetType = request->arg(F("ETH")).toInt();
|
ethernetType = request->arg(F("ETH")).toInt();
|
||||||
WLED::instance().initEthernet();
|
WLED::instance().initEthernet();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char k[3]; k[2] = 0;
|
|
||||||
for (int i = 0; i<4; i++)
|
|
||||||
{
|
|
||||||
k[1] = i+48;//ascii 0,1,2,3
|
|
||||||
|
|
||||||
k[0] = 'I'; //static IP
|
|
||||||
staticIP[i] = request->arg(k).toInt();
|
|
||||||
|
|
||||||
k[0] = 'G'; //gateway
|
|
||||||
staticGateway[i] = request->arg(k).toInt();
|
|
||||||
|
|
||||||
k[0] = 'S'; //subnet
|
|
||||||
staticSubnet[i] = request->arg(k).toInt();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//LED SETTINGS
|
//LED SETTINGS
|
||||||
@ -440,6 +456,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
analogClock12pixel = request->arg(F("OM")).toInt();
|
analogClock12pixel = request->arg(F("OM")).toInt();
|
||||||
analogClock5MinuteMarks = request->hasArg(F("O5"));
|
analogClock5MinuteMarks = request->hasArg(F("O5"));
|
||||||
analogClockSecondsTrail = request->hasArg(F("OS"));
|
analogClockSecondsTrail = request->hasArg(F("OS"));
|
||||||
|
analogClockSolidBlack = request->hasArg(F("OB"));
|
||||||
|
|
||||||
countdownMode = request->hasArg(F("CE"));
|
countdownMode = request->hasArg(F("CE"));
|
||||||
countdownYear = request->arg(F("CY")).toInt();
|
countdownYear = request->arg(F("CY")).toInt();
|
||||||
|
@ -44,10 +44,6 @@
|
|||||||
#include "../usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h"
|
#include "../usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USERMOD_MODE_SORT
|
|
||||||
#include "../usermods/usermod_v2_mode_sort/usermod_v2_mode_sort.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USERMOD_BH1750
|
#ifdef USERMOD_BH1750
|
||||||
#include "../usermods/BH1750_v2/usermod_BH1750.h"
|
#include "../usermods/BH1750_v2/usermod_BH1750.h"
|
||||||
#endif
|
#endif
|
||||||
@ -58,19 +54,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||||
#ifdef USE_ALT_DISPlAY
|
|
||||||
#include "../usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h"
|
#include "../usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h"
|
||||||
#else
|
|
||||||
#include "../usermods/usermod_v2_four_line_display/usermod_v2_four_line_display.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USERMOD_ROTARY_ENCODER_UI
|
#ifdef USERMOD_ROTARY_ENCODER_UI
|
||||||
#ifdef USE_ALT_DISPlAY
|
|
||||||
#include "../usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h"
|
#include "../usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h"
|
||||||
#else
|
|
||||||
#include "../usermods/usermod_v2_rotary_encoder_ui/usermod_v2_rotary_encoder_ui.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USERMOD_AUTO_SAVE
|
#ifdef USERMOD_AUTO_SAVE
|
||||||
@ -254,10 +242,6 @@ void registerUsermods()
|
|||||||
usermods.add(new PIRsensorSwitch());
|
usermods.add(new PIRsensorSwitch());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USERMOD_MODE_SORT
|
|
||||||
usermods.add(new ModeSortUsermod());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||||
usermods.add(new FourLineDisplayUsermod());
|
usermods.add(new FourLineDisplayUsermod());
|
||||||
#endif
|
#endif
|
||||||
|
143
wled00/wled.cpp
143
wled00/wled.cpp
@ -34,6 +34,8 @@ void WLED::reset()
|
|||||||
|
|
||||||
void WLED::loop()
|
void WLED::loop()
|
||||||
{
|
{
|
||||||
|
static uint32_t lastHeap = UINT32_MAX;
|
||||||
|
static unsigned long heapTime = 0;
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
static unsigned long lastRun = 0;
|
static unsigned long lastRun = 0;
|
||||||
unsigned long loopMillis = millis();
|
unsigned long loopMillis = millis();
|
||||||
@ -151,6 +153,21 @@ void WLED::loop()
|
|||||||
createEditHandler(false);
|
createEditHandler(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reconnect WiFi to clear stale allocations if heap gets too low
|
||||||
|
if (millis() - heapTime > 15000) {
|
||||||
|
uint32_t heap = ESP.getFreeHeap();
|
||||||
|
if (heap < MIN_HEAP_SIZE && lastHeap < MIN_HEAP_SIZE) {
|
||||||
|
DEBUG_PRINT(F("Heap too low! ")); DEBUG_PRINTLN(heap);
|
||||||
|
forceReconnect = true;
|
||||||
|
strip.resetSegments(); // remove all but one segments from memory
|
||||||
|
} else if (heap < MIN_HEAP_SIZE) {
|
||||||
|
DEBUG_PRINTLN(F("Heap low, purging segments."));
|
||||||
|
strip.purgeSegments();
|
||||||
|
}
|
||||||
|
lastHeap = heap;
|
||||||
|
heapTime = millis();
|
||||||
|
}
|
||||||
|
|
||||||
//LED settings have been saved, re-init busses
|
//LED settings have been saved, re-init busses
|
||||||
//This code block causes severe FPS drop on ESP32 with the original "if (busConfigs[0] != nullptr)" conditional. Investigate!
|
//This code block causes severe FPS drop on ESP32 with the original "if (busConfigs[0] != nullptr)" conditional. Investigate!
|
||||||
if (doInitBusses) {
|
if (doInitBusses) {
|
||||||
@ -424,6 +441,7 @@ void WLED::setup()
|
|||||||
escapedMac.toLowerCase();
|
escapedMac.toLowerCase();
|
||||||
|
|
||||||
WLED_SET_AP_SSID(); // otherwise it is empty on first boot until config is saved
|
WLED_SET_AP_SSID(); // otherwise it is empty on first boot until config is saved
|
||||||
|
multiWiFi.push_back(WiFiConfig(CLIENT_SSID,CLIENT_PASS)); // initialise vector with default WiFi
|
||||||
|
|
||||||
DEBUG_PRINTLN(F("Reading config"));
|
DEBUG_PRINTLN(F("Reading config"));
|
||||||
deserializeConfigFromFS();
|
deserializeConfigFromFS();
|
||||||
@ -445,13 +463,16 @@ void WLED::setup()
|
|||||||
usermods.setup();
|
usermods.setup();
|
||||||
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||||
|
|
||||||
if (strcmp(clientSSID, DEFAULT_CLIENT_SSID) == 0)
|
if (strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) == 0)
|
||||||
showWelcomePage = true;
|
showWelcomePage = true;
|
||||||
WiFi.persistent(false);
|
WiFi.persistent(false);
|
||||||
#ifdef WLED_USE_ETHERNET
|
#ifdef WLED_USE_ETHERNET
|
||||||
WiFi.onEvent(WiFiEvent);
|
WiFi.onEvent(WiFiEvent);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
WiFi.mode(WIFI_STA); // enable scanning
|
||||||
|
findWiFi(true); // start scanning for available WiFi-s
|
||||||
|
|
||||||
#ifdef WLED_ENABLE_ADALIGHT
|
#ifdef WLED_ENABLE_ADALIGHT
|
||||||
//Serial RX (Adalight, Improv, Serial JSON) only possible if GPIO3 unused
|
//Serial RX (Adalight, Improv, Serial JSON) only possible if GPIO3 unused
|
||||||
//Serial TX (Debug, Improv, Serial JSON) only possible if GPIO1 unused
|
//Serial TX (Debug, Improv, Serial JSON) only possible if GPIO1 unused
|
||||||
@ -697,11 +718,52 @@ bool WLED::initEthernet()
|
|||||||
#else
|
#else
|
||||||
return false; // Ethernet not enabled for build
|
return false; // Ethernet not enabled for build
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// performs asynchronous scan for available networks (which may take couple of seconds to finish)
|
||||||
|
// returns configured WiFi ID with the strongest signal (or default if no configured networks available)
|
||||||
|
int8_t WLED::findWiFi(bool doScan) {
|
||||||
|
if (multiWiFi.size() <= 1) {
|
||||||
|
DEBUG_PRINTLN(F("Defaulf WiFi used."));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doScan) WiFi.scanDelete(); // restart scan
|
||||||
|
|
||||||
|
int status = WiFi.scanComplete(); // complete scan may take as much as several seconds (usually <3s with not very crowded air)
|
||||||
|
|
||||||
|
if (status == WIFI_SCAN_FAILED) {
|
||||||
|
DEBUG_PRINTLN(F("WiFi scan started."));
|
||||||
|
WiFi.scanNetworks(true); // start scanning in asynchronous mode
|
||||||
|
} else if (status >= 0) { // status contains number of found networks
|
||||||
|
DEBUG_PRINT(F("WiFi scan completed: ")); DEBUG_PRINTLN(status);
|
||||||
|
int rssi = -9999;
|
||||||
|
int selected = selectedWiFi;
|
||||||
|
for (int o = 0; o < status; o++) {
|
||||||
|
DEBUG_PRINT(F(" WiFi available: ")); DEBUG_PRINT(WiFi.SSID(o));
|
||||||
|
DEBUG_PRINT(F(" RSSI: ")); DEBUG_PRINT(WiFi.RSSI(o)); DEBUG_PRINTLN(F("dB"));
|
||||||
|
for (unsigned n = 0; n < multiWiFi.size(); n++)
|
||||||
|
if (!strcmp(WiFi.SSID(o).c_str(), multiWiFi[n].clientSSID)) {
|
||||||
|
// find the WiFi with the strongest signal (but keep priority of entry if signal difference is not big)
|
||||||
|
if ((n < selected && WiFi.RSSI(o) > rssi-10) || WiFi.RSSI(o) > rssi) {
|
||||||
|
rssi = WiFi.RSSI(o);
|
||||||
|
selected = n;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DEBUG_PRINT(F("Selected: ")); DEBUG_PRINT(multiWiFi[selected].clientSSID);
|
||||||
|
DEBUG_PRINT(F(" RSSI: ")); DEBUG_PRINT(rssi); DEBUG_PRINTLN(F("dB"));
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
//DEBUG_PRINT(F("WiFi scan running."));
|
||||||
|
return status; // scan is still running or there was an error
|
||||||
}
|
}
|
||||||
|
|
||||||
void WLED::initConnection()
|
void WLED::initConnection()
|
||||||
{
|
{
|
||||||
|
DEBUG_PRINTLN(F("initConnection() called."));
|
||||||
|
|
||||||
#ifdef WLED_ENABLE_WEBSOCKETS
|
#ifdef WLED_ENABLE_WEBSOCKETS
|
||||||
ws.onEvent(wsEvent);
|
ws.onEvent(wsEvent);
|
||||||
#endif
|
#endif
|
||||||
@ -719,8 +781,8 @@ void WLED::initConnection()
|
|||||||
WiFi.setPhyMode(force802_3g ? WIFI_PHY_MODE_11G : WIFI_PHY_MODE_11N);
|
WiFi.setPhyMode(force802_3g ? WIFI_PHY_MODE_11G : WIFI_PHY_MODE_11N);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (staticIP[0] != 0 && staticGateway[0] != 0) {
|
if (multiWiFi[selectedWiFi].staticIP != 0U && multiWiFi[selectedWiFi].staticGW != 0U) {
|
||||||
WiFi.config(staticIP, staticGateway, staticSubnet, IPAddress(1, 1, 1, 1));
|
WiFi.config(multiWiFi[selectedWiFi].staticIP, multiWiFi[selectedWiFi].staticGW, multiWiFi[selectedWiFi].staticSN, dnsAddress);
|
||||||
} else {
|
} else {
|
||||||
WiFi.config(IPAddress((uint32_t)0), IPAddress((uint32_t)0), IPAddress((uint32_t)0));
|
WiFi.config(IPAddress((uint32_t)0), IPAddress((uint32_t)0), IPAddress((uint32_t)0));
|
||||||
}
|
}
|
||||||
@ -745,13 +807,14 @@ void WLED::initConnection()
|
|||||||
showWelcomePage = false;
|
showWelcomePage = false;
|
||||||
|
|
||||||
DEBUG_PRINT(F("Connecting to "));
|
DEBUG_PRINT(F("Connecting to "));
|
||||||
DEBUG_PRINT(clientSSID);
|
DEBUG_PRINT(multiWiFi[selectedWiFi].clientSSID);
|
||||||
DEBUG_PRINTLN("...");
|
DEBUG_PRINTLN("...");
|
||||||
|
|
||||||
// convert the "serverDescription" into a valid DNS hostname (alphanumeric)
|
// convert the "serverDescription" into a valid DNS hostname (alphanumeric)
|
||||||
char hostname[25];
|
char hostname[25];
|
||||||
prepareHostname(hostname);
|
prepareHostname(hostname);
|
||||||
WiFi.begin(clientSSID, clientPass);
|
WiFi.begin(multiWiFi[selectedWiFi].clientSSID, multiWiFi[selectedWiFi].clientPass); // no harm if called multiple times
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
#if defined(LOLIN_WIFI_FIX) && (defined(ARDUINO_ARCH_ESP32C3) || defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32S3))
|
#if defined(LOLIN_WIFI_FIX) && (defined(ARDUINO_ARCH_ESP32C3) || defined(ARDUINO_ARCH_ESP32S2) || defined(ARDUINO_ARCH_ESP32S3))
|
||||||
WiFi.setTxPower(WIFI_POWER_8_5dBm);
|
WiFi.setTxPower(WIFI_POWER_8_5dBm);
|
||||||
@ -843,35 +906,26 @@ void WLED::initInterfaces()
|
|||||||
|
|
||||||
void WLED::handleConnection()
|
void WLED::handleConnection()
|
||||||
{
|
{
|
||||||
|
static bool scanDone = true;
|
||||||
static byte stacO = 0;
|
static byte stacO = 0;
|
||||||
static uint32_t lastHeap = UINT32_MAX;
|
|
||||||
static unsigned long heapTime = 0;
|
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
|
const bool wifiConfigured = WLED_WIFI_CONFIGURED;
|
||||||
|
|
||||||
if (now < 2000 && (!WLED_WIFI_CONFIGURED || apBehavior == AP_BEHAVIOR_ALWAYS))
|
// ignore connection handling if WiFi is configured and scan still running
|
||||||
|
// or within first 2s if WiFi is not configured or AP is always active
|
||||||
|
if ((wifiConfigured && multiWiFi.size() > 1 && WiFi.scanComplete() < 0) || (now < 2000 && (!wifiConfigured || apBehavior == AP_BEHAVIOR_ALWAYS)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (lastReconnectAttempt == 0) {
|
if (lastReconnectAttempt == 0 || forceReconnect) {
|
||||||
DEBUG_PRINTLN(F("lastReconnectAttempt == 0"));
|
DEBUG_PRINTLN(F("Initial connect or forced reconnect."));
|
||||||
|
selectedWiFi = findWiFi(); // find strongest WiFi
|
||||||
initConnection();
|
initConnection();
|
||||||
|
interfacesInited = false;
|
||||||
|
forceReconnect = false;
|
||||||
|
wasConnected = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reconnect WiFi to clear stale allocations if heap gets too low
|
|
||||||
if (now - heapTime > 5000) {
|
|
||||||
uint32_t heap = ESP.getFreeHeap();
|
|
||||||
if (heap < MIN_HEAP_SIZE && lastHeap < MIN_HEAP_SIZE) {
|
|
||||||
DEBUG_PRINT(F("Heap too low! "));
|
|
||||||
DEBUG_PRINTLN(heap);
|
|
||||||
forceReconnect = true;
|
|
||||||
strip.resetSegments();
|
|
||||||
} else if (heap < MIN_HEAP_SIZE) {
|
|
||||||
strip.purgeSegments();
|
|
||||||
}
|
|
||||||
lastHeap = heap;
|
|
||||||
heapTime = now;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte stac = 0;
|
byte stac = 0;
|
||||||
if (apActive) {
|
if (apActive) {
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
@ -885,7 +939,7 @@ void WLED::handleConnection()
|
|||||||
stacO = stac;
|
stacO = stac;
|
||||||
DEBUG_PRINT(F("Connected AP clients: "));
|
DEBUG_PRINT(F("Connected AP clients: "));
|
||||||
DEBUG_PRINTLN(stac);
|
DEBUG_PRINTLN(stac);
|
||||||
if (!WLED_CONNECTED && WLED_WIFI_CONFIGURED) { // trying to connect, but not connected
|
if (!WLED_CONNECTED && wifiConfigured) { // trying to connect, but not connected
|
||||||
if (stac)
|
if (stac)
|
||||||
WiFi.disconnect(); // disable search so that AP can work
|
WiFi.disconnect(); // disable search so that AP can work
|
||||||
else
|
else
|
||||||
@ -893,36 +947,49 @@ void WLED::handleConnection()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (forceReconnect) {
|
|
||||||
DEBUG_PRINTLN(F("Forcing reconnect."));
|
|
||||||
initConnection();
|
|
||||||
interfacesInited = false;
|
|
||||||
forceReconnect = false;
|
|
||||||
wasConnected = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!Network.isConnected()) {
|
if (!Network.isConnected()) {
|
||||||
if (interfacesInited) {
|
if (interfacesInited) {
|
||||||
|
if (scanDone && multiWiFi.size() > 1) {
|
||||||
|
DEBUG_PRINTLN(F("WiFi scan initiated on disconnect."));
|
||||||
|
findWiFi(true); // reinit scan
|
||||||
|
scanDone = false;
|
||||||
|
return; // try to connect in next iteration
|
||||||
|
}
|
||||||
DEBUG_PRINTLN(F("Disconnected!"));
|
DEBUG_PRINTLN(F("Disconnected!"));
|
||||||
|
selectedWiFi = findWiFi();
|
||||||
initConnection();
|
initConnection();
|
||||||
interfacesInited = false;
|
interfacesInited = false;
|
||||||
|
scanDone = true;
|
||||||
}
|
}
|
||||||
//send improv failed 6 seconds after second init attempt (24 sec. after provisioning)
|
//send improv failed 6 seconds after second init attempt (24 sec. after provisioning)
|
||||||
if (improvActive > 2 && now - lastReconnectAttempt > 6000) {
|
if (improvActive > 2 && now - lastReconnectAttempt > 6000) {
|
||||||
sendImprovStateResponse(0x03, true);
|
sendImprovStateResponse(0x03, true);
|
||||||
improvActive = 2;
|
improvActive = 2;
|
||||||
}
|
}
|
||||||
if (now - lastReconnectAttempt > ((stac) ? 300000 : 18000) && WLED_WIFI_CONFIGURED) {
|
if (now - lastReconnectAttempt > ((stac) ? 300000 : 18000) && wifiConfigured) {
|
||||||
if (improvActive == 2) improvActive = 3;
|
if (improvActive == 2) improvActive = 3;
|
||||||
DEBUG_PRINTLN(F("Last reconnect too old."));
|
DEBUG_PRINTLN(F("Last reconnect too old."));
|
||||||
|
if (++selectedWiFi >= multiWiFi.size()) selectedWiFi = 0; // we couldn't connect, try with another network from the list
|
||||||
initConnection();
|
initConnection();
|
||||||
}
|
}
|
||||||
if (!apActive && now - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == AP_BEHAVIOR_NO_CONN)) {
|
if (!apActive && now - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == AP_BEHAVIOR_NO_CONN)) {
|
||||||
|
if (!(apBehavior == AP_BEHAVIOR_TEMPORARY && now > WLED_AP_TIMEOUT)) {
|
||||||
DEBUG_PRINTLN(F("Not connected AP."));
|
DEBUG_PRINTLN(F("Not connected AP."));
|
||||||
initAP();
|
initAP(); // start AP only within first 5min
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (apActive && apBehavior == AP_BEHAVIOR_TEMPORARY && now > WLED_AP_TIMEOUT && stac == 0) { // disconnect AP after 5min if no clients connected
|
||||||
|
// if AP was enabled more than 10min after boot or if client was connected more than 10min after boot do not disconnect AP mode
|
||||||
|
if (now < 2*WLED_AP_TIMEOUT) {
|
||||||
|
dnsServer.stop();
|
||||||
|
WiFi.softAPdisconnect(true);
|
||||||
|
apActive = false;
|
||||||
|
DEBUG_PRINTLN(F("Temporary AP disabled."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (!interfacesInited) { //newly connected
|
} else if (!interfacesInited) { //newly connected
|
||||||
DEBUG_PRINTLN("");
|
DEBUG_PRINTLN();
|
||||||
DEBUG_PRINT(F("Connected! IP address: "));
|
DEBUG_PRINT(F("Connected! IP address: "));
|
||||||
DEBUG_PRINTLN(Network.localIP());
|
DEBUG_PRINTLN(Network.localIP());
|
||||||
if (improvActive) {
|
if (improvActive) {
|
||||||
@ -940,7 +1007,7 @@ void WLED::handleConnection()
|
|||||||
dnsServer.stop();
|
dnsServer.stop();
|
||||||
WiFi.softAPdisconnect(true);
|
WiFi.softAPdisconnect(true);
|
||||||
apActive = false;
|
apActive = false;
|
||||||
DEBUG_PRINTLN(F("Access point disabled (handle)."));
|
DEBUG_PRINTLN(F("Access point disabled (connected)."));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2401270
|
#define VERSION 2402010
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
@ -307,22 +307,21 @@ WLED_GLOBAL int8_t irPin _INIT(IRPIN);
|
|||||||
WLED_GLOBAL char ntpServerName[33] _INIT("0.wled.pool.ntp.org"); // NTP server to use
|
WLED_GLOBAL char ntpServerName[33] _INIT("0.wled.pool.ntp.org"); // NTP server to use
|
||||||
|
|
||||||
// WiFi CONFIG (all these can be changed via web UI, no need to set them here)
|
// WiFi CONFIG (all these can be changed via web UI, no need to set them here)
|
||||||
WLED_GLOBAL char clientSSID[33] _INIT(CLIENT_SSID);
|
WLED_GLOBAL uint8_t selectedWiFi _INIT(0);
|
||||||
WLED_GLOBAL char clientPass[65] _INIT(CLIENT_PASS);
|
WLED_GLOBAL std::vector<WiFiConfig> multiWiFi;
|
||||||
|
WLED_GLOBAL IPAddress dnsAddress _INIT_N((( 8, 8, 8, 8))); // Google's DNS
|
||||||
WLED_GLOBAL char cmDNS[33] _INIT(MDNS_NAME); // mDNS address (*.local, replaced by wledXXXXXX if default is used)
|
WLED_GLOBAL char cmDNS[33] _INIT(MDNS_NAME); // mDNS address (*.local, replaced by wledXXXXXX if default is used)
|
||||||
WLED_GLOBAL char apSSID[33] _INIT(""); // AP off by default (unless setup)
|
WLED_GLOBAL char apSSID[33] _INIT(""); // AP off by default (unless setup)
|
||||||
WLED_GLOBAL byte apChannel _INIT(1); // 2.4GHz WiFi AP channel (1-13)
|
WLED_GLOBAL byte apChannel _INIT(1); // 2.4GHz WiFi AP channel (1-13)
|
||||||
WLED_GLOBAL byte apHide _INIT(0); // hidden AP SSID
|
WLED_GLOBAL byte apHide _INIT(0); // hidden AP SSID
|
||||||
WLED_GLOBAL byte apBehavior _INIT(AP_BEHAVIOR_BOOT_NO_CONN); // access point opens when no connection after boot by default
|
WLED_GLOBAL byte apBehavior _INIT(AP_BEHAVIOR_BOOT_NO_CONN); // access point opens when no connection after boot by default
|
||||||
WLED_GLOBAL IPAddress staticIP _INIT_N((( 0, 0, 0, 0))); // static IP of ESP
|
|
||||||
WLED_GLOBAL IPAddress staticGateway _INIT_N((( 0, 0, 0, 0))); // gateway (router) IP
|
|
||||||
WLED_GLOBAL IPAddress staticSubnet _INIT_N(((255, 255, 255, 0))); // most common subnet in home networks
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
WLED_GLOBAL bool noWifiSleep _INIT(true); // disabling modem sleep modes will increase heat output and power usage, but may help with connection issues
|
WLED_GLOBAL bool noWifiSleep _INIT(true); // disabling modem sleep modes will increase heat output and power usage, but may help with connection issues
|
||||||
#else
|
#else
|
||||||
WLED_GLOBAL bool noWifiSleep _INIT(false);
|
WLED_GLOBAL bool noWifiSleep _INIT(false);
|
||||||
#endif
|
#endif
|
||||||
WLED_GLOBAL bool force802_3g _INIT(false);
|
WLED_GLOBAL bool force802_3g _INIT(false);
|
||||||
|
#define WLED_WIFI_CONFIGURED (strlen(multiWiFi[0].clientSSID) >= 1 && strcmp(multiWiFi[0].clientSSID, DEFAULT_CLIENT_SSID) != 0)
|
||||||
|
|
||||||
#ifdef WLED_USE_ETHERNET
|
#ifdef WLED_USE_ETHERNET
|
||||||
#ifdef WLED_ETH_DEFAULT // default ethernet board type if specified
|
#ifdef WLED_ETH_DEFAULT // default ethernet board type if specified
|
||||||
@ -497,6 +496,7 @@ WLED_GLOBAL byte overlayMin _INIT(0), overlayMax _INIT(DEFAULT_LED_COUNT - 1);
|
|||||||
WLED_GLOBAL byte analogClock12pixel _INIT(0); // The pixel in your strip where "midnight" would be
|
WLED_GLOBAL byte analogClock12pixel _INIT(0); // The pixel in your strip where "midnight" would be
|
||||||
WLED_GLOBAL bool analogClockSecondsTrail _INIT(false); // Display seconds as trail of LEDs instead of a single pixel
|
WLED_GLOBAL bool analogClockSecondsTrail _INIT(false); // Display seconds as trail of LEDs instead of a single pixel
|
||||||
WLED_GLOBAL bool analogClock5MinuteMarks _INIT(false); // Light pixels at every 5-minute position
|
WLED_GLOBAL bool analogClock5MinuteMarks _INIT(false); // Light pixels at every 5-minute position
|
||||||
|
WLED_GLOBAL bool analogClockSolidBlack _INIT(false); // Show clock overlay only if all LEDs are solid black (effect is 0 and color is black)
|
||||||
|
|
||||||
WLED_GLOBAL bool countdownMode _INIT(false); // Clock will count down towards date
|
WLED_GLOBAL bool countdownMode _INIT(false); // Clock will count down towards date
|
||||||
WLED_GLOBAL byte countdownYear _INIT(20), countdownMonth _INIT(1); // Countdown target date, year is last two digits
|
WLED_GLOBAL byte countdownYear _INIT(20), countdownMonth _INIT(1); // Countdown target date, year is last two digits
|
||||||
@ -836,7 +836,6 @@ WLED_GLOBAL volatile uint8_t jsonBufferLock _INIT(0);
|
|||||||
#else
|
#else
|
||||||
#define WLED_CONNECTED (WiFi.status() == WL_CONNECTED)
|
#define WLED_CONNECTED (WiFi.status() == WL_CONNECTED)
|
||||||
#endif
|
#endif
|
||||||
#define WLED_WIFI_CONFIGURED (strlen(clientSSID) >= 1 && strcmp(clientSSID, DEFAULT_CLIENT_SSID) != 0)
|
|
||||||
|
|
||||||
#ifndef WLED_AP_SSID_UNIQUE
|
#ifndef WLED_AP_SSID_UNIQUE
|
||||||
#define WLED_SET_AP_SSID() do { \
|
#define WLED_SET_AP_SSID() do { \
|
||||||
@ -886,6 +885,7 @@ public:
|
|||||||
void initAP(bool resetAP = false);
|
void initAP(bool resetAP = false);
|
||||||
void initConnection();
|
void initConnection();
|
||||||
void initInterfaces();
|
void initInterfaces();
|
||||||
|
int8_t findWiFi(bool doScan = false);
|
||||||
#if defined(STATUSLED)
|
#if defined(STATUSLED)
|
||||||
void handleStatusLED();
|
void handleStatusLED();
|
||||||
#endif
|
#endif
|
||||||
|
@ -74,8 +74,8 @@ void loadSettingsFromEEPROM()
|
|||||||
int lastEEPROMversion = EEPROM.read(377); //last EEPROM version before update
|
int lastEEPROMversion = EEPROM.read(377); //last EEPROM version before update
|
||||||
|
|
||||||
|
|
||||||
readStringFromEEPROM( 0, clientSSID, 32);
|
readStringFromEEPROM( 0, multiWiFi[0].clientSSID, 32);
|
||||||
readStringFromEEPROM( 32, clientPass, 64);
|
readStringFromEEPROM( 32, multiWiFi[0].clientPass, 64);
|
||||||
readStringFromEEPROM( 96, cmDNS, 32);
|
readStringFromEEPROM( 96, cmDNS, 32);
|
||||||
readStringFromEEPROM(128, apSSID, 32);
|
readStringFromEEPROM(128, apSSID, 32);
|
||||||
readStringFromEEPROM(160, apPass, 64);
|
readStringFromEEPROM(160, apPass, 64);
|
||||||
|
@ -248,23 +248,34 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
|
|
||||||
if (subPage == SUBPAGE_WIFI)
|
if (subPage == SUBPAGE_WIFI)
|
||||||
{
|
{
|
||||||
sappends('s',SET_F("CS"),clientSSID);
|
char nS[10];
|
||||||
|
size_t l;
|
||||||
byte l = strlen(clientPass);
|
oappend(SET_F("resetWiFi("));
|
||||||
|
oappend(itoa(WLED_MAX_WIFI_COUNT,nS,10));
|
||||||
|
oappend(SET_F(");"));
|
||||||
|
for (size_t n = 0; n < multiWiFi.size(); n++) {
|
||||||
|
l = strlen(multiWiFi[n].clientPass);
|
||||||
char fpass[l+1]; //fill password field with ***
|
char fpass[l+1]; //fill password field with ***
|
||||||
fpass[l] = 0;
|
fpass[l] = 0;
|
||||||
memset(fpass,'*',l);
|
memset(fpass,'*',l);
|
||||||
sappends('s',SET_F("CP"),fpass);
|
oappend(SET_F("addWiFi(\""));
|
||||||
|
oappend(multiWiFi[n].clientSSID);
|
||||||
char k[3]; k[2] = 0; //IP addresses
|
oappend(SET_F("\",\""));
|
||||||
for (int i = 0; i<4; i++)
|
oappend(fpass);
|
||||||
{
|
oappend(SET_F("\",0x"));
|
||||||
k[1] = 48+i; //ascii 0,1,2,3
|
oappend(itoa(multiWiFi[n].staticIP,nS,16));
|
||||||
k[0] = 'I'; sappend('v',k,staticIP[i]);
|
oappend(SET_F(",0x"));
|
||||||
k[0] = 'G'; sappend('v',k,staticGateway[i]);
|
oappend(itoa(multiWiFi[n].staticGW,nS,16));
|
||||||
k[0] = 'S'; sappend('v',k,staticSubnet[i]);
|
oappend(SET_F(",0x"));
|
||||||
|
oappend(itoa(multiWiFi[n].staticSN,nS,16));
|
||||||
|
oappend(SET_F(");"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sappend('v',SET_F("D0"),dnsAddress[0]);
|
||||||
|
sappend('v',SET_F("D1"),dnsAddress[1]);
|
||||||
|
sappend('v',SET_F("D2"),dnsAddress[2]);
|
||||||
|
sappend('v',SET_F("D3"),dnsAddress[3]);
|
||||||
|
|
||||||
sappends('s',SET_F("CM"),cmDNS);
|
sappends('s',SET_F("CM"),cmDNS);
|
||||||
sappend('i',SET_F("AB"),apBehavior);
|
sappend('i',SET_F("AB"),apBehavior);
|
||||||
sappends('s',SET_F("AS"),apSSID);
|
sappends('s',SET_F("AS"),apSSID);
|
||||||
@ -597,6 +608,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
sappend('v',SET_F("OM"),analogClock12pixel);
|
sappend('v',SET_F("OM"),analogClock12pixel);
|
||||||
sappend('c',SET_F("OS"),analogClockSecondsTrail);
|
sappend('c',SET_F("OS"),analogClockSecondsTrail);
|
||||||
sappend('c',SET_F("O5"),analogClock5MinuteMarks);
|
sappend('c',SET_F("O5"),analogClock5MinuteMarks);
|
||||||
|
sappend('c',SET_F("OB"),analogClockSolidBlack);
|
||||||
|
|
||||||
sappend('c',SET_F("CE"),countdownMode);
|
sappend('c',SET_F("CE"),countdownMode);
|
||||||
sappend('v',SET_F("CY"),countdownYear);
|
sappend('v',SET_F("CY"),countdownYear);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user