Merge branch 'master' into patch-1
This commit is contained in:
commit
a769ab6cff
20
.github/stale.yml
vendored
Normal file
20
.github/stale.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 120
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- keep
|
||||
- enhancement
|
||||
- confirmed
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
Hey! This issue has been open for quite some time without any new comments now.
|
||||
It will be closed automatically in a week if no further activity occurs.
|
||||
|
||||
Thank you for using WLED!
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -5,3 +5,7 @@
|
||||
!.vscode/extensions.json
|
||||
/wled00/Release
|
||||
/wled00/extLibs
|
||||
/platformio_override.ini
|
||||
.DS_Store
|
||||
.gitignore
|
||||
.clang-format
|
||||
|
14
.travis.yml
14
.travis.yml
@ -18,18 +18,26 @@
|
||||
# it (remove "# " before each line) or use own configuration according to the
|
||||
# Travis CI documentation (see above).
|
||||
#
|
||||
# * Test the Travis config here:
|
||||
# < https://config.travis-ci.com/explore >
|
||||
#
|
||||
|
||||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
sudo: false
|
||||
# - "2.7"
|
||||
- "3.5"
|
||||
os: linux
|
||||
cache:
|
||||
bundler: true
|
||||
ccache: true
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
- "~/.buildcache"
|
||||
env:
|
||||
- PLATFORMIO_CI_SRC=wled00
|
||||
install:
|
||||
- pip install -U platformio
|
||||
- platformio update
|
||||
script:
|
||||
- platformio ci --project-conf=./platformio.ini
|
||||
# - platformio ci --project-conf=./platformio.ini
|
||||
- platformio run
|
10
.vscode/extensions.json
vendored
10
.vscode/extensions.json
vendored
@ -1,7 +1,7 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
126
CHANGELOG.md
Normal file
126
CHANGELOG.md
Normal file
@ -0,0 +1,126 @@
|
||||
## WLED changelog
|
||||
|
||||
### Development versions after 0.10.0 release
|
||||
|
||||
#### Build 2005100
|
||||
|
||||
- Update to Espalexa v2.4.6 (+1.6kB free heap memory)
|
||||
- Added `m5atom` PlatformIO environment
|
||||
|
||||
#### Build 2005090
|
||||
|
||||
- Default to ESP8266 Arduino core v2.7.1 in PlatformIO
|
||||
- Fixed Preset Slot 16 always indicating as empty (#891)
|
||||
- Disabled Alexa emulation by default (causes bootloop for some users)
|
||||
- Added BWLT11 and SHOJO_PCB defines to NpbWrapper
|
||||
- Merged pull request #898 adding Solid Glitter effect
|
||||
|
||||
### WLED version 0.10.0
|
||||
|
||||
#### Build 2005030
|
||||
|
||||
- DMX Single RGW and Single DRGB modes now support an additional white channel
|
||||
- Improved palettes derived from set colors and changed their names
|
||||
|
||||
### Development versions between 0.9.1 and 0.10.0 release
|
||||
|
||||
#### Build 2005020
|
||||
|
||||
- Added ACST and ACST/ACDT timezones
|
||||
|
||||
#### Build 2005010
|
||||
|
||||
- Added module info page to web UI
|
||||
- Added realtime override functionality to web UI
|
||||
- Added individial segment power and brightness to web UI
|
||||
- Added feature to one-click select single segment only by tapping segment name
|
||||
- Removed palette jumping to default if color is changed
|
||||
|
||||
#### Build 2004300
|
||||
|
||||
- Added realtime override option and `lor` JSON property
|
||||
- Added `lm` (live mode) and `lip` (live IP) properties to info in JSON API
|
||||
- Added reset commands to APIs
|
||||
- Added `json/si`, returning state and info, but no FX or Palette lists
|
||||
- Added rollover detection to millis(). Can track uptimes longer than 49 days
|
||||
- Attempted to fix Wifi issues with Unifi brand APs
|
||||
|
||||
#### Build 2004230
|
||||
|
||||
- Added brightness and power for individual segments
|
||||
- Added `on` and `bri` properties to Segment object in JSON API
|
||||
- Added `C3` an `SB` commands to HTTP get API
|
||||
- Merged pull request #865 for 5CH_Shojo_PCB environment
|
||||
|
||||
#### Build 2004220
|
||||
|
||||
- Added Candle Multi effect
|
||||
- Added Palette capability to Pacifica effect
|
||||
|
||||
#### Build 2004190
|
||||
|
||||
- Added TM1814 type LED defines
|
||||
|
||||
#### Build 2004120
|
||||
|
||||
- Added Art-Net support
|
||||
- Added OTA platform to platformio.ini
|
||||
|
||||
#### Build 2004100
|
||||
|
||||
- Fixed DMX output compilation
|
||||
- Added DMX start LED setting
|
||||
|
||||
#### Build 2004061
|
||||
|
||||
- Fixed RBG and BGR getPixelColor (#825)
|
||||
- Improved formatting
|
||||
|
||||
#### Build 2004060
|
||||
|
||||
- Consolidated global variables in wled.h
|
||||
|
||||
#### Build 2003300
|
||||
|
||||
- Major change of project structure from .ino to .cpp and func_declare.h
|
||||
|
||||
#### Build 2003262
|
||||
|
||||
- Fixed compilation for Analog LEDs
|
||||
- Fixed sync settings network port fields too small
|
||||
|
||||
#### Build 2003261
|
||||
|
||||
- Fixed live preview not displaying whole light if over 255 LEDs
|
||||
|
||||
#### Build 2003251
|
||||
|
||||
- Added Pacifica effect (tentative, doesn't yet support other colors)
|
||||
- Added Atlantica palette
|
||||
- Fixed ESP32 build of Espalexa
|
||||
|
||||
#### Build 2003222
|
||||
|
||||
- Fixed Alexa Whites on non-RGBW lights (bump Espalexa to 2.4.5)
|
||||
|
||||
#### Build 2003221
|
||||
|
||||
- Moved Cronixie driver from FX library to drawOverlay handler
|
||||
|
||||
#### Build 2003211
|
||||
|
||||
- Added custom mapping compile define to FX_fcn.h
|
||||
- Merged pull request #784 by @TravisDean: Fixed initialization bug when toggling skip first
|
||||
- Added link to youtube videos by Room31 to readme
|
||||
|
||||
#### Build 2003141
|
||||
|
||||
- Fixed color of main segment returned in JSON API during transition not being target color (closes #765)
|
||||
- Fixed arlsLock() being called after pixels set in E1.31 (closes #772)
|
||||
- Fixed HTTP API calls not having an effect if no segment selected (now applies to main segment)
|
||||
|
||||
#### Build 2003121
|
||||
|
||||
- Created changelog.md - make tracking changes to code easier
|
||||
- Merged pull request #766 by @pille: Fix E1.31 out-of sequence detection
|
||||
|
469
platformio.ini
469
platformio.ini
@ -2,245 +2,326 @@
|
||||
; Please visit documentation: https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
src_dir = ./wled00
|
||||
src_dir = ./wled00
|
||||
data_dir = ./wled00/data
|
||||
;lib_extra_dirs = ./wled00/src
|
||||
lib_dir = ./wled00/src
|
||||
; Please uncomment one of the 5 lines below to select your board
|
||||
env_default = nodemcuv2
|
||||
; env_default = esp01
|
||||
; env_default = esp01_1m
|
||||
; env_default = esp07
|
||||
; env_default = d1_mini
|
||||
; env_default = esp32dev
|
||||
; env_default = esp8285_4CH_MagicHome
|
||||
; env_default = esp8285_4CH_H801
|
||||
; env_default = esp8285_5CH_H801
|
||||
lib_dir = ./wled00/src
|
||||
build_cache_dir = ~/.buildcache
|
||||
extra_configs =
|
||||
platformio_override.ini
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ENVIRONMENTS
|
||||
#
|
||||
# Please uncomment one of the lines below to select your board(s)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Travis CI binaries (comment this out when building for single board)
|
||||
default_envs = d1_mini, esp01, esp01_1m_ota, esp32dev
|
||||
|
||||
# Release binaries
|
||||
; default_envs = nodemcuv2, esp01, esp01_1m_ota, esp01_1m_full, esp32dev, custom_WS2801, custom_APA102, custom_LEDPIN_16, custom_LEDPIN_4, custom32_LEDPIN_16
|
||||
|
||||
# Single binaries (uncomment your board)
|
||||
; default_envs = nodemcuv2
|
||||
; default_envs = esp01
|
||||
; default_envs = esp01_1m_ota
|
||||
; 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_4CH_H801
|
||||
; default_envs = esp8285_5CH_H801
|
||||
; default_envs = d1_mini_5CH_Shojo_PCB
|
||||
; default_envs = wemos_shield_esp32
|
||||
; default_envs = m5atom
|
||||
|
||||
[common]
|
||||
framework = arduino
|
||||
monitor_speed = 115200
|
||||
board_build.flash_mode = dout
|
||||
upload_speed = 115200
|
||||
upload_speed_fast = 921600
|
||||
build_flags =
|
||||
-w ; supresses all C/C++ warnings
|
||||
; -D VERSION=0.8.5
|
||||
; -D DEBUG
|
||||
#build_flags for the IRremoteESP8266 library (enabled decoders have to appear here)
|
||||
-D _IR_ENABLE_DEFAULT_=false
|
||||
-D DECODE_HASH=true
|
||||
-D DECODE_NEC=true
|
||||
-D DECODE_SONY=true
|
||||
-D DECODE_PANASONIC=true
|
||||
-D DECODE_JVC=true
|
||||
-D DECODE_SAMSUNG=true
|
||||
-D DECODE_LG=true
|
||||
-D DECODE_SANYO=true
|
||||
-D DECODE_SHARP=true
|
||||
-D DECODE_DENON=true
|
||||
# TODO replace libs in /lib with managed libs in here if possible.
|
||||
# If they are not changed it's just a matter of setting the correct version and change the import statement
|
||||
lib_deps_external =
|
||||
#Blynk@0.5.4(changed)
|
||||
#E131@1.0.0(changed)
|
||||
FastLED@3.3.2
|
||||
NeoPixelBus@2.5.1
|
||||
ESPAsyncTCP@1.2.0
|
||||
ESPAsyncUDP@697c75a025
|
||||
AsyncTCP@1.0.3
|
||||
Esp Async WebServer@1.2.0
|
||||
#ArduinoJson@5.13.5
|
||||
#IRremoteESP8266@2.7.2
|
||||
#For saving 20k program space the brnach "compile_flags" will be used:
|
||||
https://github.com/crankyoldgit/IRremoteESP8266.git#compile_flags
|
||||
#Time@1.5
|
||||
#Timezone@1.2.1
|
||||
#For use SSD1306 0.91" OLED display uncomment following
|
||||
#U8g2@~2.27.2
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
#DallasTemperature@~3.8.0
|
||||
#OneWire@~2.3.5
|
||||
[common:esp8266]
|
||||
# ------------------------------------------------------------------------------
|
||||
# PLATFORM:
|
||||
# !! DO NOT confuse platformio's ESP8266 development platform with Arduino core for ESP8266
|
||||
# We use Arduino Core 2.5.0 (platformIO 2.0.4) as default
|
||||
#
|
||||
# arduino core 2.3.0 = platformIO 1.5.0
|
||||
# arduino core 2.4.0 = platformIO 1.6.0
|
||||
# arduino core 2.4.1 = platformIO 1.7.3
|
||||
# arduino core 2.4.2 = platformIO 1.8.0
|
||||
# arduino core 2.5.0 = platformIO 2.0.4
|
||||
# arduino core stage = platformIO feature#stage
|
||||
# arduino core 2.5.1 = platformIO 2.1.1
|
||||
# arduino core 2.5.2 = platformIO 2.2.3
|
||||
# arduino core 2.6.1 = platformIO 2.3.0
|
||||
# arduino core 2.6.2 = platformIO 2.3.1
|
||||
# arduino core 2.6.3 = platformIO 2.3.2
|
||||
# arduino core 2.7.0 = platformIO 2.5.0
|
||||
# ------------------------------------------------------------------------------
|
||||
arduino_core_2_3_0 = espressif8266@1.5.0
|
||||
arduino_core_2_4_0 = espressif8266@1.6.0
|
||||
arduino_core_2_4_1 = espressif8266@1.7.3
|
||||
arduino_core_2_4_2 = espressif8266@1.8.0
|
||||
arduino_core_2_5_0 = espressif8266@2.0.4
|
||||
arduino_core_2_5_1 = espressif8266@2.1.1
|
||||
arduino_core_2_5_2 = espressif8266@2.2.3
|
||||
arduino_core_2_6_1 = espressif8266@2.3.0
|
||||
arduino_core_2_6_2 = espressif8266@2.3.1
|
||||
arduino_core_stage = https://github.com/platformio/platform-espressif8266.git#feature/stage
|
||||
platform = ${common:esp8266.arduino_core_2_6_2}
|
||||
build_flags =
|
||||
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
-Wl,-Teagle.flash.4m1m.ld ;;;; Required for core > v2.5.0 or staging version 4MB Flash 3MB SPIFFs
|
||||
arduino_core_2_6_3 = espressif8266@2.3.3
|
||||
arduino_core_2_7_1 = espressif8266@2.5.1
|
||||
|
||||
[common:esp8266_1M]
|
||||
platform = espressif8266@1.8.0
|
||||
build_flags =
|
||||
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
|
||||
-Wl,-Teagle.flash.1m0.ld ;;;; Compile with no SPIFFS to leave space for OTA
|
||||
; -D WLED_DISABLE_MOBILE_UI
|
||||
; -D WLED_DISABLE_OTA
|
||||
; -D WLED_DISABLE_ALEXA
|
||||
-D WLED_DISABLE_BLYNK
|
||||
-D WLED_DISABLE_CRONIXIE
|
||||
; -D WLED_DISABLE_HUESYNC
|
||||
; -D WLED_DISABLE_INFRARED
|
||||
# Development platforms
|
||||
arduino_core_develop = https://github.com/platformio/platform-espressif8266#develop
|
||||
arduino_core_git = https://github.com/platformio/platform-espressif8266#feature/stage
|
||||
|
||||
[common:esp8266_512k]
|
||||
platform = espressif8266@1.8.0
|
||||
build_flags =
|
||||
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
|
||||
-Wl,-Teagle.flash.512k0.ld ;;;; Compile with no SPIFFS
|
||||
; -D WLED_DISABLE_MOBILE_UI
|
||||
-D WLED_DISABLE_OTA
|
||||
; -D WLED_DISABLE_ALEXA
|
||||
-D WLED_DISABLE_BLYNK
|
||||
-D WLED_DISABLE_CRONIXIE
|
||||
-D WLED_DISABLE_HUESYNC
|
||||
; -D WLED_DISABLE_INFRARED
|
||||
# Platform to use for ESP8266
|
||||
platform_latest = ${common.arduino_core_2_7_1}
|
||||
|
||||
[common:esp32]
|
||||
platform = espressif32@1.11.1
|
||||
build_flags =
|
||||
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
-D ARDUINO_ARCH_ESP32
|
||||
# ------------------------------------------------------------------------------
|
||||
# FLAGS: DEBUG
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
debug_flags = -D DEBUG=1 -D WLED_DEBUG -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_TLS_MEM
|
||||
#if needed (for memleaks etc) also add; -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h"
|
||||
#-DDEBUG_ESP_CORE is not working right now
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# FLAGS: ldscript
|
||||
# ldscript_512k ( 512 KB) = 487 KB sketch, 4 KB eeprom, no spiffs, 16 KB reserved
|
||||
# ldscript_1m0m (1024 KB) = 999 KB sketch, 4 KB eeprom, no spiffs, 16 KB reserved
|
||||
# ldscript_2m1m (2048 KB) = 1019 KB sketch, 4 KB eeprom, 1004 KB spiffs, 16 KB reserved
|
||||
# ldscript_4m1m (4096 KB) = 1019 KB sketch, 4 KB eeprom, 1002 KB spiffs, 16 KB reserved, 2048 KB empty/ota?
|
||||
# ldscript_4m3m (4096 KB) = 1019 KB sketch, 4 KB eeprom, 3040 KB spiffs, 16 KB reserved
|
||||
#
|
||||
# Available lwIP variants (macros):
|
||||
# -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH = v1.4 Higher Bandwidth (default)
|
||||
# -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY = v2 Lower Memory
|
||||
# -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH = v2 Higher Bandwidth
|
||||
#
|
||||
# BearSSL performance:
|
||||
# When building with -DSECURE_CLIENT=SECURE_CLIENT_BEARSSL, please add `board_build.f_cpu = 160000000` to the environment configuration
|
||||
#
|
||||
# BearSSL ciphers:
|
||||
# When building on core >= 2.5, you can add the build flag -DBEARSSL_SSL_BASIC in order to build BearSSL with a limited set of ciphers:
|
||||
# TLS_RSA_WITH_AES_128_CBC_SHA256 / AES128-SHA256
|
||||
# TLS_RSA_WITH_AES_256_CBC_SHA256 / AES256-SHA256
|
||||
# TLS_RSA_WITH_AES_128_CBC_SHA / AES128-SHA
|
||||
# TLS_RSA_WITH_AES_256_CBC_SHA / AES256-SHA
|
||||
# This reduces the OTA size with ~45KB, so it's especially useful on low memory boards (512k/1m).
|
||||
# ------------------------------------------------------------------------------
|
||||
build_flags = -g -w -DMQTT_MAX_PACKET_SIZE=1024 -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
||||
-DSECURE_CLIENT=SECURE_CLIENT_BEARSSL -DBEARSSL_SSL_BASIC
|
||||
#build_flags for the IRremoteESP8266 library (enabled decoders have to appear here)
|
||||
-D _IR_ENABLE_DEFAULT_=false
|
||||
-D DECODE_HASH=true
|
||||
-D DECODE_NEC=true
|
||||
-D DECODE_SONY=true
|
||||
-D DECODE_SAMSUNG=true
|
||||
-D DECODE_LG=true
|
||||
|
||||
build_flags_esp8266 = ${common.build_flags} -DESP8266
|
||||
build_flags_esp32 = ${common.build_flags} -DARDUINO_ARCH_ESP32
|
||||
|
||||
ldscript_512k = eagle.flash.512k.ld ;for older versions change this to eagle.flash.512k0.ld
|
||||
ldscript_1m0m = eagle.flash.1m.ld ;for older versions change this to eagle.flash.1m0.ld
|
||||
ldscript_2m1m = eagle.flash.2m1m.ld
|
||||
ldscript_4m1m = eagle.flash.4m1m.ld
|
||||
ldscript_4m3m = eagle.flash.4m3m.ld
|
||||
|
||||
shared_libdeps_dir = ./wled00/src
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# COMMON SETTINGS:
|
||||
# ------------------------------------------------------------------------------
|
||||
[env]
|
||||
framework = arduino
|
||||
board_build.flash_mode = dout
|
||||
monitor_speed = 115200
|
||||
upload_speed = 115200
|
||||
lib_extra_dirs =
|
||||
${common.shared_libdeps_dir}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# LIBRARIES: required dependencies
|
||||
# Please note that we don't always use the latest version of a library.
|
||||
#
|
||||
# The following libraries have been included (and some of them changd) in the source:
|
||||
# ArduinoJson@5.13.5, Blynk@0.5.4(changed), E131@1.0.0(changed), Time@1.5, Timezone@1.2.1
|
||||
# ------------------------------------------------------------------------------
|
||||
lib_compat_mode = strict
|
||||
lib_deps =
|
||||
FastLED@3.3.2
|
||||
NeoPixelBus@2.5.7
|
||||
ESPAsyncTCP@1.2.0
|
||||
ESPAsyncUDP@697c75a025
|
||||
AsyncTCP@1.0.3
|
||||
Esp Async WebServer@1.2.0
|
||||
IRremoteESP8266@2.7.3
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
#U8g2@~2.27.2
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
#OneWire@~2.3.5
|
||||
#For BME280 sensor uncomment following
|
||||
#BME280@~3.0.0
|
||||
lib_ignore =
|
||||
AsyncTCP
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# WLED BUILDS
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# see: http://docs.platformio.org/en/latest/platforms/espressif8266.html
|
||||
[env:nodemcuv2]
|
||||
board = nodemcuv2
|
||||
platform = ${common:esp8266.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266.build_flags}
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
|
||||
[env:d1_mini]
|
||||
board = d1_mini
|
||||
platform = ${common:esp8266.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266.build_flags}
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
|
||||
[env:esp01_1m]
|
||||
board = esp01_1m
|
||||
platform = ${common:esp8266_1M.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266_1M.build_flags}
|
||||
# disable IR because there is no pin for it
|
||||
-D WLED_DISABLE_INFRARED
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
[env:esp01]
|
||||
board = esp01
|
||||
platform = ${common:esp8266_512k.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266_512k.build_flags}
|
||||
-D WLED_DISABLE_INFRARED
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_512k}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA -D WLED_DISABLE_ALEXA -D WLED_DISABLE_BLYNK
|
||||
-D WLED_DISABLE_CRONIXIE -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_INFRARED
|
||||
|
||||
[env:esp01_1m_ota]
|
||||
board = esp01_1m
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_ALEXA -D WLED_DISABLE_BLYNK -D WLED_DISABLE_CRONIXIE -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_INFRARED
|
||||
|
||||
[env:esp01_1m_full]
|
||||
board = esp01_1m
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA
|
||||
|
||||
[env:esp07]
|
||||
board = esp07
|
||||
platform = ${common:esp8266.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266.build_flags}
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
[env:d1_mini]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
upload_speed = 921500
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
[env:heltec_wifi_kit_8]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
[env:h803wf]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D LEDPIN=1 -D WLED_DISABLE_INFRARED
|
||||
|
||||
# see: http://docs.platformio.org/en/latest/platforms/espressif32.html
|
||||
[env:esp32dev]
|
||||
board = esp32dev
|
||||
platform = ${common:esp32.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed_fast}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp32.build_flags}
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
platform = espressif32@1.11.2
|
||||
build_flags = ${common.build_flags_esp32}
|
||||
lib_ignore =
|
||||
ESPAsyncTCP
|
||||
ESPAsyncUDP
|
||||
|
||||
[env:esp8285_4CH_MagicHome]
|
||||
board = esp8285
|
||||
platform = ${common:esp8266_1M.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266_1M.build_flags}
|
||||
-D WLED_DISABLE_HUESYNC
|
||||
-D WLED_USE_ANALOG_LEDS
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_HUESYNC -D WLED_USE_ANALOG_LEDS
|
||||
|
||||
[env:esp8285_4CH_H801]
|
||||
board = esp8285
|
||||
platform = ${common:esp8266_1M.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266_1M.build_flags}
|
||||
-D WLED_DISABLE_HUESYNC
|
||||
-D WLED_USE_ANALOG_LEDS
|
||||
-D WLED_USE_H801
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_HUESYNC -D WLED_USE_ANALOG_LEDS -D WLED_USE_H801
|
||||
|
||||
[env:esp8285_5CH_H801]
|
||||
board = esp8285
|
||||
platform = ${common:esp8266_1M.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266_1M.build_flags}
|
||||
-D WLED_DISABLE_HUESYNC
|
||||
-D WLED_USE_ANALOG_LEDS
|
||||
-D WLED_USE_H801
|
||||
-D WLED_ENABLE_5CH_LEDS
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_HUESYNC -D WLED_USE_ANALOG_LEDS -D WLED_USE_H801 -D WLED_ENABLE_5CH_LEDS
|
||||
|
||||
[env:d1_mini_5CH_Shojo_PCB]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_USE_ANALOG_LEDS -D WLED_USE_SHOJO_PCB -D WLED_ENABLE_5CH_LEDS
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# DEVELOPMENT BOARDS
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
[env:d1_mini_debug]
|
||||
board = d1_mini
|
||||
build_type = debug
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} ${common.debug_flags}
|
||||
|
||||
[env:d1_mini_ota]
|
||||
board = d1_mini
|
||||
upload_protocol = espota
|
||||
# exchange for your WLED IP
|
||||
upload_port = "10.10.1.27"
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# custom board configurations
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
[env:custom_LEDPIN_4]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D LEDPIN=4 -D IRPIN=5
|
||||
|
||||
[env:custom_LEDPIN_16]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D LEDPIN=16
|
||||
|
||||
[env:custom_APA102]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D USE_APA102
|
||||
|
||||
[env:custom_WS2801]
|
||||
board = d1_mini
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266} -D USE_WS2801
|
||||
|
||||
[env:custom32_LEDPIN_16]
|
||||
board = esp32dev
|
||||
platform = espressif32@1.11.2
|
||||
build_flags = ${common.build_flags_esp32} -D LEDPIN=16
|
||||
lib_ignore =
|
||||
ESPAsyncTCP
|
||||
ESPAsyncUDP
|
||||
|
||||
[env:wemos_shield_esp32]
|
||||
board = esp32dev
|
||||
platform = espressif32@1.11.2
|
||||
upload_port = /dev/cu.SLAB_USBtoUART
|
||||
monitor_port = /dev/cu.SLAB_USBtoUART
|
||||
upload_speed = 460800
|
||||
build_flags = ${common.build_flags_esp32} -D LEDPIN=16 -D RLYPIN=19 -D BTNPIN=17
|
||||
lib_ignore =
|
||||
ESPAsyncTCP
|
||||
ESPAsyncUDP
|
||||
|
||||
[env:m5atom]
|
||||
board = esp32dev
|
||||
build_flags = ${common.build_flags_esp32} -D LEDPIN=27 -D BTNPIN=39
|
||||
lib_ignore =
|
||||
ESPAsyncTCP
|
||||
ESPAsyncUDP
|
||||
platform = espressif32@1.11.2
|
36
platformio_override.ini.example
Normal file
36
platformio_override.ini.example
Normal file
@ -0,0 +1,36 @@
|
||||
# Example PlatformIO Project Configuration Override
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copy to platformio_override.ini to activate overrides
|
||||
# ------------------------------------------------------------------------------
|
||||
# Please visit documentation: https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:esp8266_1m_custom]
|
||||
board = esp01_1m
|
||||
platform = ${common.arduino_core_2_4_2}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
-D WLED_DISABLE_OTA
|
||||
-D WLED_DISABLE_ALEXA
|
||||
-D WLED_DISABLE_BLYNK
|
||||
-D WLED_DISABLE_CRONIXIE
|
||||
-D WLED_DISABLE_HUESYNC
|
||||
-D WLED_DISABLE_INFRARED
|
||||
; PIN defines - uncomment and change, if needed:
|
||||
; -D LEDPIN=2
|
||||
; -D BTNPIN=0
|
||||
; -D IR_PIN=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
|
||||
; to drive analog LED strips (aka 5050), uncomment the following
|
||||
; PWM pins 5,12,13,15 are used with Magic Home LED Controller (default)
|
||||
; -D WLED_USE_ANALOG_LEDS
|
||||
; for the H801 controller (PINs 15,13,12,14 (W2 = 04)) uncomment this
|
||||
; -D WLED_USE_H801
|
||||
; for the BW-LT11 controller (PINs 12,4,14,5 ) uncomment this
|
||||
; -D WLED_USE_BWLT11
|
||||
; and to enable channel 5 for RGBW-CT led strips this
|
||||
; -D WLED_USE_5CH_LEDS
|
12
readme.md
12
readme.md
@ -1,6 +1,7 @@
|
||||
![WLED logo](https://raw.githubusercontent.com/Aircoookie/WLED/master/wled_logo.png)
|
||||
|
||||
[![](https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square)](https://github.com/Aircoookie/WLED/releases)
|
||||
[![](https://img.shields.io/discourse/topics?colorB=blue&label=forum&server=https%3A%2F%2Fwled.discourse.group%2F&style=flat-square)](https://wled.discourse.group)
|
||||
[![](https://img.shields.io/discord/473448917040758787.svg?colorB=blue&label=discord&style=flat-square)](https://discord.gg/KuqP7NE)
|
||||
[![](https://img.shields.io/badge/quick_start-wiki-blue.svg?style=flat-square)](https://github.com/Aircoookie/WLED/wiki)
|
||||
[![](https://img.shields.io/badge/app-wled-blue.svg?style=flat-square)](https://github.com/Aircoookie/WLED-App)
|
||||
@ -10,8 +11,8 @@
|
||||
A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812, APA102) LEDs!
|
||||
|
||||
### Features:
|
||||
- WS2812FX library integrated for almost 100 special effects
|
||||
- FastLED noise effects and palettes
|
||||
- WS2812FX library integrated for over 100 special effects
|
||||
- FastLED noise effects and 50 palettes
|
||||
- Modern UI with color, effect and segment controls
|
||||
- Segments to set different effects and colors to parts of the LEDs
|
||||
- Settings page - configuration over network
|
||||
@ -49,6 +50,10 @@ DrZzs has made some excellent video guides:
|
||||
|
||||
If you'd rather read, here is a very [detailed step-by-step beginner tutorial](https://tynick.com/blog/11-03-2019/getting-started-with-wled-on-esp8266/) by tynick!
|
||||
|
||||
Russian speakers, check out the videos by Room31:
|
||||
[WLED Firmware Overview: Interface and Settings](https://youtu.be/h7lKsczEI7E)
|
||||
[ESP8266 based LED controller for WS2812b strip. WLED Firmware + OpenHAB](https://youtu.be/K4ioTt3XvGc)
|
||||
|
||||
### Other
|
||||
|
||||
Licensed under the MIT license
|
||||
@ -57,7 +62,8 @@ Credits [here](https://github.com/Aircoookie/WLED/wiki/Contributors-&-About)!
|
||||
Uses Linearicons by Perxis!
|
||||
|
||||
Join the Discord [server](https://discord.gg/KuqP7NE) to discuss everything about WLED!
|
||||
You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com).
|
||||
Check out the WLED [Discourse forum](https://wled.discourse.group)!
|
||||
You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com), but please only do so if you want to talk to me privately.
|
||||
If WLED really brightens up your every day, you can [![](https://img.shields.io/badge/send%20me%20a%20small%20gift-paypal-blue.svg?style=flat-square)](https://paypal.me/aircoookie)
|
||||
|
||||
*Disclaimer:*
|
||||
|
BIN
usermods/Enclosure_with_OLED_temp_ESP07/assets/controller.jpg
Normal file
BIN
usermods/Enclosure_with_OLED_temp_ESP07/assets/controller.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 150 KiB |
BIN
usermods/Enclosure_with_OLED_temp_ESP07/assets/pcb.png
Normal file
BIN
usermods/Enclosure_with_OLED_temp_ESP07/assets/pcb.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 235 KiB |
7
usermods/Enclosure_with_OLED_temp_ESP07/assets/readme.md
Normal file
7
usermods/Enclosure_with_OLED_temp_ESP07/assets/readme.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Enclosure and PCB
|
||||
|
||||
## IP67 rated enclosure
|
||||
![Enclosure](controller.jpg)
|
||||
|
||||
## PCB
|
||||
![PCB](pcb.png)
|
68
usermods/Enclosure_with_OLED_temp_ESP07/readme.md
Normal file
68
usermods/Enclosure_with_OLED_temp_ESP07/readme.md
Normal file
@ -0,0 +1,68 @@
|
||||
# Almost universal controller board for outdoor applications
|
||||
This usermod is using ideas from @mrVanboy and @400killer
|
||||
|
||||
Installation of file: Copy and replace file in wled00 directory.
|
||||
|
||||
For BME280 sensor use usermod_bme280.cpp. Copy to wled00 and rename to usermod.cpp
|
||||
|
||||
## Project repository
|
||||
- [Original repository](https://github.com/srg74/Controller-for-WLED-firmware) - Main controller repository
|
||||
## Features
|
||||
- SSD1306 128x32 and 128x64 I2C OLED display
|
||||
- On screen IP address, SSID and controller status (e.g. ON or OFF, recent effect)
|
||||
- Auto display shutoff for saving display lifetime
|
||||
- Dallas temperature sensor
|
||||
- Reporting temperature to MQTT broker
|
||||
|
||||
## Hardware
|
||||
![Hardware connection](assets/controller.jpg)
|
||||
|
||||
## Functionality checked with
|
||||
- ESP-07S
|
||||
- PlatformIO
|
||||
- SSD1306 128x32 I2C OLED display
|
||||
- DS18B20 (temperature sensor)
|
||||
- BME280 (temperature, humidity and pressure sensor)
|
||||
- KY-022 (infrared receiver)
|
||||
- Push button (N.O. momentary switch)
|
||||
|
||||
For Dallas sensor uncomment `U8g2@~2.27.3`,`DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
default_envs = esp07
|
||||
; default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
DallasTemperature@~3.8.0
|
||||
OneWire@~2.3.5
|
||||
...
|
||||
```
|
||||
|
||||
For BME280 sensor uncomment `U8g2@~2.27.3`,`BME280@~3.0.0 under` `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
default_envs = esp07
|
||||
; default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For BME280 sensor uncomment following
|
||||
BME280@~3.0.0
|
||||
...
|
||||
```
|
209
usermods/Enclosure_with_OLED_temp_ESP07/usermod.cpp
Normal file
209
usermods/Enclosure_with_OLED_temp_ESP07/usermod.cpp
Normal file
@ -0,0 +1,209 @@
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
#include <DallasTemperature.h> //Dallastemperature sensor
|
||||
//The SCL and SDA pins are defined here.
|
||||
//Lolin32 boards use SCL=5 SDA=4
|
||||
#define U8X8_PIN_SCL 5
|
||||
#define U8X8_PIN_SDA 4
|
||||
// Dallas sensor
|
||||
OneWire oneWire(13);
|
||||
DallasTemperature sensor(&oneWire);
|
||||
long temptimer = millis();
|
||||
long lastMeasure = 0;
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
|
||||
// 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
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// gets called once at boot. Do all initialization that doesn't depend on
|
||||
// network here
|
||||
void userSetup() {
|
||||
sensor.begin(); //Start Dallas temperature sensor
|
||||
u8x8.begin();
|
||||
//u8x8.setFlipMode(1); //Uncoment if using WLED Wemos shield
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
//----> Dallas temperature sensor MQTT publishing
|
||||
temptimer = millis();
|
||||
// Timer to publishe new temperature every 60 seconds
|
||||
if (temptimer - lastMeasure > 60000)
|
||||
{
|
||||
lastMeasure = temptimer;
|
||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
sensor.requestTemperatures();
|
||||
//Gets prefered temperature scale based on selection in definitions section
|
||||
#ifdef Celsius
|
||||
float board_temperature = sensor.getTempCByIndex(0);
|
||||
#else
|
||||
float board_temperature = sensor.getTempFByIndex(0);
|
||||
#endif
|
||||
//Create character string populated with user defined device topic from the UI, and the read temperature. Then publish to MQTT server.
|
||||
char subuf[38];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/temperature");
|
||||
mqtt->publish(subuf, 0, true, String(board_temperature).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 3 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
|
||||
u8x8.setPowerSave(1);
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
u8x8.setPowerSave(0);
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#if defined(ESP8266)
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#else
|
||||
knownSsid = WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
u8x8.clear();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
u8x8.print(apPass);
|
||||
else
|
||||
u8x8.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
u8x8.setCursor(2, 2);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
u8x8.setCursor(2, 3);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
|
||||
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
|
||||
u8x8.drawGlyph(0, 0, 80); // wifi icon
|
||||
u8x8.drawGlyph(0, 1, 68); // home icon
|
||||
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
|
||||
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
|
||||
}
|
266
usermods/Enclosure_with_OLED_temp_ESP07/usermod_bme280.cpp
Normal file
266
usermods/Enclosure_with_OLED_temp_ESP07/usermod_bme280.cpp
Normal file
@ -0,0 +1,266 @@
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
#include <Wire.h>
|
||||
#include <BME280I2C.h> //BME280 sensor
|
||||
|
||||
void UpdateBME280Data();
|
||||
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
BME280I2C bme; // Default : forced mode, standby time = 1000 ms
|
||||
// Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off,
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32 //ESP32 boards
|
||||
uint8_t SCL_PIN = 22;
|
||||
uint8_t SDA_PIN = 21;
|
||||
#else //ESP8266 boards
|
||||
uint8_t SCL_PIN = 5;
|
||||
uint8_t SDA_PIN = 4;
|
||||
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
|
||||
#define U8X8_PIN_SCL SCL_PIN
|
||||
#define U8X8_PIN_SDA SDA_PIN
|
||||
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
|
||||
|
||||
// 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
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
|
||||
// gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
|
||||
// BME280 sensor timer
|
||||
long tempTimer = millis();
|
||||
long lastMeasure = 0;
|
||||
|
||||
float SensorPressure(NAN);
|
||||
float SensorTemperature(NAN);
|
||||
float SensorHumidity(NAN);
|
||||
|
||||
void userSetup() {
|
||||
u8x8.begin();
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setFlipMode(1);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
Wire.begin(SDA_PIN,SCL_PIN);
|
||||
|
||||
while(!bme.begin())
|
||||
{
|
||||
Serial.println("Could not find BME280I2C sensor!");
|
||||
delay(1000);
|
||||
}
|
||||
switch(bme.chipModel())
|
||||
{
|
||||
case BME280::ChipModel_BME280:
|
||||
Serial.println("Found BME280 sensor! Success.");
|
||||
break;
|
||||
case BME280::ChipModel_BMP280:
|
||||
Serial.println("Found BMP280 sensor! No Humidity available.");
|
||||
break;
|
||||
default:
|
||||
Serial.println("Found UNKNOWN sensor! Error!");
|
||||
}
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
// BME280 sensor MQTT publishing
|
||||
tempTimer = millis();
|
||||
// Timer to publish new sensor data every 60 seconds
|
||||
if (tempTimer - lastMeasure > 60000)
|
||||
{
|
||||
lastMeasure = tempTimer;
|
||||
|
||||
// Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
UpdateBME280Data();
|
||||
float board_temperature = SensorTemperature;
|
||||
float board_pressure = SensorPressure;
|
||||
float board_humidity = SensorHumidity;
|
||||
|
||||
// Create string populated with user defined device topic from the UI, and the read temperature, humidity and pressure. Then publish to MQTT server.
|
||||
String t = String(mqttDeviceTopic);
|
||||
t += "/temperature";
|
||||
mqtt->publish(t.c_str(), 0, true, String(board_temperature).c_str());
|
||||
String p = String(mqttDeviceTopic);
|
||||
p += "/pressure";
|
||||
mqtt->publish(p.c_str(), 0, true, String(board_pressure).c_str());
|
||||
String h = String(mqttDeviceTopic);
|
||||
h += "/humidity";
|
||||
mqtt->publish(h.c_str(), 0, true, String(board_humidity).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 3 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
|
||||
u8x8.setPowerSave(1);
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
u8x8.setPowerSave(0);
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#if defined(ESP8266)
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#else
|
||||
knownSsid = WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
u8x8.clear();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
u8x8.print(apPass);
|
||||
else
|
||||
u8x8.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
u8x8.setCursor(2, 2);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
u8x8.setCursor(2, 3);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
|
||||
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
|
||||
u8x8.drawGlyph(0, 0, 80); // wifi icon
|
||||
u8x8.drawGlyph(0, 1, 68); // home icon
|
||||
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
|
||||
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
|
||||
}
|
||||
|
||||
void UpdateBME280Data() {
|
||||
float temp(NAN), hum(NAN), pres(NAN);
|
||||
#ifdef Celsius
|
||||
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
|
||||
#else
|
||||
BME280::TempUnit tempUnit(BME280::TempUnit_Fahrenheit);
|
||||
#endif
|
||||
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
|
||||
bme.read(pres, temp, hum, tempUnit, presUnit);
|
||||
SensorTemperature=temp;
|
||||
SensorHumidity=hum;
|
||||
SensorPressure=pres;
|
||||
}
|
@ -1,8 +1,34 @@
|
||||
These files allow WLED 0.8.6 to report the temp sensor on the Quinled board to MQTT. I use it to report the board temp to Home Assistant via MQTT, so it will send notifications if something happens and the board start to heat up.
|
||||
# QuinLED Dig Uno board
|
||||
|
||||
These files allow WLED 0.9.1 to report the temp sensor on the Quinled board to MQTT. I use it to report the board temp to Home Assistant via MQTT, so it will send notifications if something happens and the board start to heat up.
|
||||
This code uses Aircookie's WLED software. It has a premade file for user modifications. I use it to publish the temperature from the dallas temperature sensor on the Quinled board. The entries for the top of the WLED00 file, initializes the required libraries, and variables for the sensor. The .ino file waits for 60 seconds, and checks to see if the MQTT server is connected (thanks Aircoookie). It then poles the sensor, and published it using the MQTT service already running, using the main topic programmed in the WLED UI.
|
||||
|
||||
To install:
|
||||
Installation of file: Copy and replace file in wled00 directory
|
||||
|
||||
Add the entries in the WLED00 file to the top of the same file from Aircoookies WLED.
|
||||
Replace the WLED06_usermod.ino file in Aircoookies WLED folder.
|
||||
## Project link
|
||||
|
||||
* [QuinLED-Dig-Uno](https://quinled.info/2018/09/15/quinled-dig-uno/) - Project link
|
||||
|
||||
### Platformio requirements
|
||||
|
||||
Uncomment `DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
||||
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
; default_envs = esp07
|
||||
default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
DallasTemperature@~3.8.0
|
||||
OneWire@~2.3.5
|
||||
...
|
||||
```
|
@ -1,8 +1,21 @@
|
||||
//starts Dallas Temp service on boot
|
||||
#include <Arduino.h>
|
||||
#include "wled.h"
|
||||
//Intiating code for QuinLED Dig-Uno temp sensor
|
||||
//Uncomment Celsius if that is your prefered temperature scale
|
||||
#include <DallasTemperature.h> //Dallastemperature sensor
|
||||
#ifdef ARDUINO_ARCH_ESP32 //ESP32 boards
|
||||
OneWire oneWire(18);
|
||||
#else //ESP8266 boards
|
||||
OneWire oneWire(14);
|
||||
#endif
|
||||
DallasTemperature sensor(&oneWire);
|
||||
long temptimer = millis();
|
||||
long lastMeasure = 0;
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
void userSetup()
|
||||
{
|
||||
// Start the DS18B20 sensor
|
||||
sensors.begin();
|
||||
sensor.begin();
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
@ -21,11 +34,11 @@ void userLoop()
|
||||
|
||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr){
|
||||
sensors.requestTemperatures();
|
||||
sensor.requestTemperatures();
|
||||
|
||||
//Gets prefered temperature scale based on selection in definitions section
|
||||
#ifdef Celsius
|
||||
float board_temperature = sensors.getTempCByIndex(0);
|
||||
float board_temperature = sensor.getTempCByIndex(0);
|
||||
#else
|
||||
float board_temperature = sensors.getTempFByIndex(0);
|
||||
#endif
|
@ -1,8 +0,0 @@
|
||||
//Intiating code for QuinLED Dig-Uno temp sensor
|
||||
//Uncomment Celsius if that is your prefered temperature scale
|
||||
#include <DallasTemperature.h>
|
||||
OneWire oneWire(14);
|
||||
DallasTemperature sensors(&oneWire);
|
||||
long temptimer = millis();
|
||||
long lastMeasure = 0;
|
||||
//#define Celsius
|
71
usermods/Wemos_D1_mini+Wemos32_mini_shield/readme.md
Normal file
71
usermods/Wemos_D1_mini+Wemos32_mini_shield/readme.md
Normal file
@ -0,0 +1,71 @@
|
||||
# Wemos D1 mini and Wemos32 mini shield
|
||||
- Installation of file: Copy and replace file in wled00 directory
|
||||
- For BME280 sensor use usermod_bme280.cpp. Copy to wled00 and rename to usermod.cpp
|
||||
- Added third choice of controller Heltec WiFi-Kit-8. Totally DIY but with OLED display.
|
||||
## Project repository
|
||||
- [Original repository](https://github.com/srg74/WLED-wemos-shield) - WLED Wemos shield repository
|
||||
- [Wemos shield project Wiki](https://github.com/srg74/WLED-wemos-shield/wiki)
|
||||
- [Precompiled WLED firmware](https://github.com/srg74/WLED-wemos-shield/tree/master/resources/Firmware)
|
||||
## Features
|
||||
- SSD1306 128x32 or 128x64 I2C OLED display
|
||||
- On screen IP address, SSID and controller status (e.g. ON or OFF, recent effect)
|
||||
- Auto display shutoff for saving display lifetime
|
||||
- Dallas temperature sensor
|
||||
- Reporting temperature to MQTT broker
|
||||
- Relay for energy saving
|
||||
|
||||
## Hardware
|
||||
![Shield](https://github.com/srg74/WLED-wemos-shield/blob/master/resources/Images/Assembly_8.jpg)
|
||||
|
||||
## Functionality checked with
|
||||
|
||||
- Wemos D1 mini original v3.1 and clones
|
||||
- Wemos32 mini
|
||||
- PlatformIO
|
||||
- SSD1306 128x32 I2C OLED display
|
||||
- DS18B20 (temperature sensor)
|
||||
- BME280 (temperature, humidity and pressure sensor)
|
||||
- Push button (N.O. momentary switch)
|
||||
|
||||
### Platformio requirements
|
||||
|
||||
For Dallas sensor uncomment `U8g2@~2.27.3`,`DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
; default_envs = esp07
|
||||
default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
DallasTemperature@~3.8.0
|
||||
OneWire@~2.3.5
|
||||
...
|
||||
```
|
||||
|
||||
For BME280 sensor uncomment `U8g2@~2.27.3`,`BME280@~3.0.0 under` `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
; default_envs = esp07
|
||||
default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For BME280 sensor uncomment following
|
||||
BME280@~3.0.0
|
||||
...
|
||||
```
|
246
usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod.cpp
Normal file
246
usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
#include <OneWire.h> // Dallas temperature sensor
|
||||
|
||||
//Dallas sensor quick reading. Credit to - Author: Peter Scargill, August 17th, 2013
|
||||
int16_t Dallas(int x, byte start)
|
||||
{
|
||||
OneWire DallasSensor(x);
|
||||
byte i;
|
||||
byte data[2];
|
||||
int16_t result;
|
||||
do
|
||||
{
|
||||
DallasSensor.reset();
|
||||
DallasSensor.write(0xCC);
|
||||
DallasSensor.write(0xBE);
|
||||
for ( i = 0; i < 2; i++) data[i] = DallasSensor.read();
|
||||
result=(data[1]<<8)|data[0];
|
||||
result>>=4; if (data[1]&128) result|=61440;
|
||||
if (data[0]&8) ++result;
|
||||
DallasSensor.reset();
|
||||
DallasSensor.write(0xCC);
|
||||
DallasSensor.write(0x44,1);
|
||||
if (start) delay(1000);
|
||||
} while (start--);
|
||||
return result;
|
||||
}
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
uint8_t SCL_PIN = 22;
|
||||
uint8_t SDA_PIN = 21;
|
||||
uint8_t DALLAS_PIN =23;
|
||||
#else
|
||||
uint8_t SCL_PIN = 5;
|
||||
uint8_t SDA_PIN = 4;
|
||||
uint8_t DALLAS_PIN =13;
|
||||
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
|
||||
#define U8X8_PIN_SCL SCL_PIN
|
||||
#define U8X8_PIN_SDA SDA_PIN
|
||||
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
|
||||
|
||||
// Dallas sensor reading timer
|
||||
long temptimer = millis();
|
||||
long lastMeasure = 0;
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
|
||||
// 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
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
|
||||
// gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup() {
|
||||
//Serial.begin(115200);
|
||||
|
||||
Dallas (DALLAS_PIN,1);
|
||||
u8x8.begin();
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setFlipMode(1);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
//----> Dallas temperature sensor MQTT publishing
|
||||
temptimer = millis();
|
||||
// Timer to publishe new temperature every 60 seconds
|
||||
if (temptimer - lastMeasure > 60000)
|
||||
{
|
||||
lastMeasure = temptimer;
|
||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
// Serial.println(Dallas(DALLAS_PIN,0));
|
||||
//Gets prefered temperature scale based on selection in definitions section
|
||||
#ifdef Celsius
|
||||
int16_t board_temperature = Dallas(DALLAS_PIN,0);
|
||||
#else
|
||||
int16_t board_temperature = (Dallas(DALLAS_PIN,0)* 1.8 + 32);
|
||||
#endif
|
||||
//Create character string populated with user defined device topic from the UI, and the read temperature. Then publish to MQTT server.
|
||||
String t = String(mqttDeviceTopic);
|
||||
t += "/temperature";
|
||||
mqtt->publish(t.c_str(), 0, true, String(board_temperature).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 3 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
|
||||
u8x8.setPowerSave(1);
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
u8x8.setPowerSave(0);
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
knownSsid = WiFi.SSID();
|
||||
#else
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
u8x8.clear();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
u8x8.print(apPass);
|
||||
else
|
||||
u8x8.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
u8x8.setCursor(2, 2);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
u8x8.setCursor(2, 3);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
|
||||
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
|
||||
u8x8.drawGlyph(0, 0, 80); // wifi icon
|
||||
u8x8.drawGlyph(0, 1, 68); // home icon
|
||||
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
|
||||
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
|
||||
}
|
268
usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod_bme280.cpp
Normal file
268
usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod_bme280.cpp
Normal file
@ -0,0 +1,268 @@
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
#include <Wire.h>
|
||||
#include <BME280I2C.h> //BME280 sensor
|
||||
|
||||
void UpdateBME280Data();
|
||||
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
BME280I2C bme; // Default : forced mode, standby time = 1000 ms
|
||||
// Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off,
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32 //ESP32 boards
|
||||
uint8_t SCL_PIN = 22;
|
||||
uint8_t SDA_PIN = 21;
|
||||
#else //ESP8266 boards
|
||||
uint8_t SCL_PIN = 5;
|
||||
uint8_t SDA_PIN = 4;
|
||||
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
|
||||
#define U8X8_PIN_SCL SCL_PIN
|
||||
#define U8X8_PIN_SDA SDA_PIN
|
||||
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
|
||||
|
||||
// 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
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
|
||||
// gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
|
||||
// BME280 sensor timer
|
||||
long tempTimer = millis();
|
||||
long lastMeasure = 0;
|
||||
|
||||
float SensorPressure(NAN);
|
||||
float SensorTemperature(NAN);
|
||||
float SensorHumidity(NAN);
|
||||
|
||||
void userSetup() {
|
||||
u8x8.begin();
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setFlipMode(1);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
Wire.begin(SDA_PIN,SCL_PIN);
|
||||
|
||||
while(!bme.begin())
|
||||
{
|
||||
Serial.println("Could not find BME280I2C sensor!");
|
||||
delay(1000);
|
||||
}
|
||||
switch(bme.chipModel())
|
||||
{
|
||||
case BME280::ChipModel_BME280:
|
||||
Serial.println("Found BME280 sensor! Success.");
|
||||
break;
|
||||
case BME280::ChipModel_BMP280:
|
||||
Serial.println("Found BMP280 sensor! No Humidity available.");
|
||||
break;
|
||||
default:
|
||||
Serial.println("Found UNKNOWN sensor! Error!");
|
||||
}
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
// BME280 sensor MQTT publishing
|
||||
tempTimer = millis();
|
||||
// Timer to publish new sensor data every 60 seconds
|
||||
if (tempTimer - lastMeasure > 60000)
|
||||
{
|
||||
lastMeasure = tempTimer;
|
||||
|
||||
// Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
UpdateBME280Data();
|
||||
float board_temperature = SensorTemperature;
|
||||
float board_pressure = SensorPressure;
|
||||
float board_humidity = SensorHumidity;
|
||||
|
||||
// Create string populated with user defined device topic from the UI, and the read temperature, humidity and pressure. Then publish to MQTT server.
|
||||
String t = String(mqttDeviceTopic);
|
||||
t += "/temperature";
|
||||
mqtt->publish(t.c_str(), 0, true, String(board_temperature).c_str());
|
||||
String p = String(mqttDeviceTopic);
|
||||
p += "/pressure";
|
||||
mqtt->publish(p.c_str(), 0, true, String(board_pressure).c_str());
|
||||
String h = String(mqttDeviceTopic);
|
||||
h += "/humidity";
|
||||
mqtt->publish(h.c_str(), 0, true, String(board_humidity).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 3 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
|
||||
u8x8.setPowerSave(1);
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
u8x8.setPowerSave(0);
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#if defined(ESP8266)
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#else
|
||||
knownSsid = WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
u8x8.clear();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
u8x8.print(apPass);
|
||||
else
|
||||
u8x8.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
u8x8.setCursor(2, 2);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
u8x8.setCursor(2, 3);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
|
||||
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
|
||||
u8x8.drawGlyph(0, 0, 80); // wifi icon
|
||||
u8x8.drawGlyph(0, 1, 68); // home icon
|
||||
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
|
||||
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
|
||||
}
|
||||
|
||||
void UpdateBME280Data() {
|
||||
float temp(NAN), hum(NAN), pres(NAN);
|
||||
#ifdef Celsius
|
||||
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
|
||||
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
|
||||
bme.read(pres, temp, hum, tempUnit, presUnit);
|
||||
#else
|
||||
BME280::TempUnit tempUnit(BME280::TempUnit_Fahrenheit);
|
||||
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
|
||||
bme.read(pres, temp, hum, tempUnit, presUnit);
|
||||
#endif
|
||||
SensorTemperature=temp;
|
||||
SensorHumidity=hum;
|
||||
SensorPressure=pres;
|
||||
}
|
12
usermods/battery_keypad_controller/README.md
Normal file
12
usermods/battery_keypad_controller/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# Battery powered controller with keypad
|
||||
|
||||
I'm using this controller for a festival totem. Runs on 3 18650 Cells, can deliver >5A current.
|
||||
|
||||
Via keypad one can select 8 presets, change effect, effect speed, effect intensity and palette. Brightness can be
|
||||
adjusted with a potentiometer.
|
||||
|
||||
## Pictures
|
||||
|
||||
![bat-key-ctrl-1](assets/bat-key-ctrl-1.jpg)
|
||||
![bat-key-ctrl-2](assets/bat-key-ctrl-2.jpg)
|
||||
![bat-key-ctrl-3](assets/bat-key-ctrl-3.jpg)
|
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-1.jpg
Normal file
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-1.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 319 KiB |
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-2.jpg
Normal file
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-2.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 250 KiB |
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-3.jpg
Normal file
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-3.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 344 KiB |
151
usermods/battery_keypad_controller/wled06_usermod.ino
Normal file
151
usermods/battery_keypad_controller/wled06_usermod.ino
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* WLED usermod for keypad and brightness-pot.
|
||||
* 3'2020 https://github.com/hobbyquaker
|
||||
*/
|
||||
|
||||
#include <Keypad.h>
|
||||
const byte keypad_rows = 4;
|
||||
const byte keypad_cols = 4;
|
||||
char keypad_keys[keypad_rows][keypad_cols] = {
|
||||
{'1', '2', '3', 'A'},
|
||||
{'4', '5', '6', 'B'},
|
||||
{'7', '8', '9', 'C'},
|
||||
{'*', '0', '#', 'D'}
|
||||
};
|
||||
|
||||
byte keypad_colPins[keypad_rows] = {D3, D2, D1, D0};
|
||||
byte keypad_rowPins[keypad_cols] = {D7, D6, D5, D4};
|
||||
|
||||
Keypad myKeypad = Keypad(makeKeymap(keypad_keys), keypad_rowPins, keypad_colPins, keypad_rows, keypad_cols);
|
||||
|
||||
void userSetup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void userConnected()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
long lastTime = 0;
|
||||
int delayMs = 20; //we want to do something every 2 seconds
|
||||
|
||||
void userLoop()
|
||||
{
|
||||
if (millis()-lastTime > delayMs)
|
||||
{
|
||||
|
||||
long analog = analogRead(0);
|
||||
int new_bri = 1;
|
||||
if (analog > 900) {
|
||||
new_bri = 255;
|
||||
} else if (analog > 30) {
|
||||
new_bri = dim8_video(map(analog, 31, 900, 16, 255));
|
||||
}
|
||||
if (bri != new_bri) {
|
||||
bri = new_bri;
|
||||
colorUpdated(1);
|
||||
|
||||
}
|
||||
|
||||
char myKey = myKeypad.getKey();
|
||||
if (myKey != NULL) {
|
||||
switch (myKey) {
|
||||
case '1':
|
||||
applyPreset(1);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '2':
|
||||
applyPreset(2);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '3':
|
||||
applyPreset(3);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '4':
|
||||
applyPreset(4);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '5':
|
||||
applyPreset(5);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '6':
|
||||
applyPreset(6);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case 'A':
|
||||
applyPreset(7);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case 'B':
|
||||
applyPreset(8);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case '7':
|
||||
effectCurrent += 1;
|
||||
if (effectCurrent >= MODE_COUNT) effectCurrent = 0;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '*':
|
||||
effectCurrent -= 1;
|
||||
if (effectCurrent < 0) effectCurrent = (MODE_COUNT-1);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case '8':
|
||||
if (effectSpeed < 240) {
|
||||
effectSpeed += 12;
|
||||
} else if (effectSpeed < 255) {
|
||||
effectSpeed += 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '0':
|
||||
if (effectSpeed > 15) {
|
||||
effectSpeed -= 12;
|
||||
} else if (effectSpeed > 0) {
|
||||
effectSpeed -= 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case '9':
|
||||
if (effectIntensity < 240) {
|
||||
effectIntensity += 12;
|
||||
} else if (effectIntensity < 255) {
|
||||
effectIntensity += 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '#':
|
||||
if (effectIntensity > 15) {
|
||||
effectIntensity -= 12;
|
||||
} else if (effectIntensity > 0) {
|
||||
effectIntensity -= 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
effectPalette += 1;
|
||||
if (effectPalette >= 50) effectPalette = 0;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case 'D':
|
||||
effectPalette -= 1;
|
||||
if (effectPalette <= 0) effectPalette = 50;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lastTime = millis();
|
||||
}
|
||||
|
||||
}
|
28
usermods/blynk_relay_control/README.md
Normal file
28
usermods/blynk_relay_control/README.md
Normal file
@ -0,0 +1,28 @@
|
||||
# Blynk controllable relay
|
||||
This usermod allows controlling a relay state from the user variables. It also allows the user variables to be set over Blynk.
|
||||
|
||||
Optionally, the servo can have a reset timer to go back to it's default state after an interval. This interval is set through userVar1.
|
||||
|
||||
## Instalation
|
||||
|
||||
Replace the WLED06_usermod.ino file in Aircoookies WLED folder with the one here.
|
||||
|
||||
## Customizations
|
||||
|
||||
Update the following parameters in WLED06_usermod.ino to configure the mod's behavior:
|
||||
|
||||
```cpp
|
||||
//Which pin is the relay connected to
|
||||
#define RELAY_PIN 5
|
||||
//Which pin state should the relay default to
|
||||
#define RELAY_PIN_DEFAULT LOW
|
||||
//If >0 The controller returns to RELAY_PIN_DEFAULT after this time in milliseconds
|
||||
#define RELAY_PIN_TIMER_DEFAULT 3000
|
||||
|
||||
//Blynk virtual pin for controlling relay
|
||||
#define BLYNK_USER_VAR0_PIN V9
|
||||
//Blynk virtual pin for controlling relay timer
|
||||
#define BLYNK_USER_VAR1_PIN V10
|
||||
//Number of milliseconds between updating blynk
|
||||
#define BLYNK_RELAY_UPDATE_INTERVAL 5000
|
||||
```
|
96
usermods/blynk_relay_control/wled06_usermod.ino
Normal file
96
usermods/blynk_relay_control/wled06_usermod.ino
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled_eeprom.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
*/
|
||||
|
||||
//Use userVar0 (API calls &U0=, uint16_t) to set relay state
|
||||
#define relayPinState userVar0
|
||||
//Use userVar1 (API calls &U1=, uint16_t) to set relay timer duration
|
||||
//Ignored if 0, otherwise number of milliseconds to allow relay to stay in
|
||||
//non default state.
|
||||
#define relayTimerInterval userVar1
|
||||
|
||||
//Which pin is the relay connected to
|
||||
#define RELAY_PIN 5
|
||||
//Which pin state should the relay default to
|
||||
#define RELAY_PIN_DEFAULT LOW
|
||||
//If >0 The controller returns to RELAY_PIN_DEFAULT after this time in milliseconds
|
||||
#define RELAY_PIN_TIMER_DEFAULT 3000
|
||||
|
||||
//Blynk virtual pin for controlling relay
|
||||
#define BLYNK_USER_VAR0_PIN V9
|
||||
//Blynk virtual pin for controlling relay timer
|
||||
#define BLYNK_USER_VAR1_PIN V10
|
||||
//Number of milliseconds between updating blynk
|
||||
#define BLYNK_RELAY_UPDATE_INTERVAL 5000
|
||||
|
||||
//Is the timer for resetting the relay active
|
||||
bool relayTimerStarted = false;
|
||||
//millis() time after which relay will be reset
|
||||
unsigned long relayTimeToDefault = 0;
|
||||
//millis() time after which relay vars in Blynk will be sent
|
||||
unsigned long relayBlynkUpdateTime = 0;
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup()
|
||||
{
|
||||
relayPinState = RELAY_PIN_DEFAULT;
|
||||
relayTimerInterval = RELAY_PIN_TIMER_DEFAULT;
|
||||
pinMode(RELAY_PIN, OUTPUT);
|
||||
digitalWrite(RELAY_PIN, relayPinState);
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected()
|
||||
{
|
||||
}
|
||||
|
||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
||||
void userLoop()
|
||||
{
|
||||
//Normalize relayPinState to an accepted value
|
||||
if (relayPinState != HIGH && relayPinState != LOW) {
|
||||
relayPinState = RELAY_PIN_DEFAULT;
|
||||
}
|
||||
//If relay changes and relayTimerInterval is set, start a timer to change back
|
||||
if (relayTimerInterval != 0 &&
|
||||
relayPinState != RELAY_PIN_DEFAULT &&
|
||||
!relayTimerStarted ) {
|
||||
relayTimerStarted = true;
|
||||
relayTimeToDefault = millis() + relayTimerInterval;
|
||||
}
|
||||
//If manually changed back to default, cancel timer
|
||||
if (relayTimerStarted && relayPinState == RELAY_PIN_DEFAULT ) {
|
||||
relayTimerStarted = false;
|
||||
}
|
||||
//If timer completes, set relay back to default
|
||||
if (relayTimerStarted && millis() > relayTimeToDefault) {
|
||||
relayPinState = RELAY_PIN_DEFAULT;
|
||||
relayTimerStarted = false;
|
||||
}
|
||||
digitalWrite(RELAY_PIN, relayPinState);
|
||||
updateRelayBlynk();
|
||||
}
|
||||
|
||||
//Update Blynk with state of userVars at BLYNK_RELAY_UPDATE_INTERVAL
|
||||
void updateRelayBlynk()
|
||||
{
|
||||
if (!WLED_CONNECTED) return;
|
||||
if (relayBlynkUpdateTime > millis()) return;
|
||||
Blynk.virtualWrite(BLYNK_USER_VAR0_PIN, userVar0);
|
||||
Blynk.virtualWrite(BLYNK_USER_VAR1_PIN, userVar1);
|
||||
relayBlynkUpdateTime = millis() + BLYNK_RELAY_UPDATE_INTERVAL;
|
||||
}
|
||||
|
||||
//Add Blynk callback for setting userVar0
|
||||
BLYNK_WRITE(BLYNK_USER_VAR0_PIN)
|
||||
{
|
||||
userVar0 = param.asInt();
|
||||
}
|
||||
//Add Blynk callback for setting userVar1
|
||||
BLYNK_WRITE(BLYNK_USER_VAR1_PIN)
|
||||
{
|
||||
userVar1 = param.asInt();
|
||||
}
|
23
usermods/project_cars_shiftlight/readme.md
Normal file
23
usermods/project_cars_shiftlight/readme.md
Normal file
@ -0,0 +1,23 @@
|
||||
### Shift Light for Project Cars
|
||||
|
||||
Turn your WLED lights into a rev light and shift indicator for Project Cars.
|
||||
|
||||
It is pretty straight forward to use.
|
||||
|
||||
1. Make sure, your WLED device and your PC/console are on the same network and can talk to each other
|
||||
|
||||
2. Go to the gameplay settings menu in PCARS and enable UDP. There are 9 numbers you can choose from. This is the refresh rate. The lower the number, the better. But you might run into problems at faster rates.
|
||||
|
||||
| Number | Updates/Second |
|
||||
| ------ | -------------- |
|
||||
| 1 | 60 |
|
||||
| 2 | 50 |
|
||||
| 3 | 40 |
|
||||
| 4 | 30 |
|
||||
| 5 | 20 |
|
||||
| 6 | 15 |
|
||||
| 7 | 10 |
|
||||
| 8 | 05 |
|
||||
| 9 | 1 |
|
||||
|
||||
3. once you enter a race, WLED should automatically shift to PCARS mode. Done.
|
96
usermods/project_cars_shiftlight/wled06_usermod.ino
Normal file
96
usermods/project_cars_shiftlight/wled06_usermod.ino
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Car rev display and shift indicator for Project Cars
|
||||
*
|
||||
* This works via the UDP telemetry function. You'll need to enable it in the settings of the game.
|
||||
* I've had good results with settings around 5 (20 fps).
|
||||
*
|
||||
*/
|
||||
const uint8_t PCARS_dimcolor = 20;
|
||||
WiFiUDP UDP;
|
||||
const unsigned int PCARS_localUdpPort = 5606; // local port to listen on
|
||||
char PCARS_packet[2048];
|
||||
|
||||
char PCARS_tempChar[2]; // Temporary array for u16 conversion
|
||||
|
||||
u16 PCARS_RPM;
|
||||
u16 PCARS_maxRPM;
|
||||
|
||||
long PCARS_lastRead = millis() - 2001;
|
||||
float PCARS_rpmRatio;
|
||||
|
||||
|
||||
void userSetup()
|
||||
{
|
||||
UDP.begin(PCARS_localUdpPort);
|
||||
}
|
||||
|
||||
void userConnected()
|
||||
{
|
||||
// new wifi, who dis?
|
||||
}
|
||||
|
||||
void userLoop()
|
||||
{
|
||||
PCARS_readValues();
|
||||
if (PCARS_lastRead > millis() - 2000) {
|
||||
PCARS_buildcolorbars();
|
||||
}
|
||||
}
|
||||
|
||||
void PCARS_readValues() {
|
||||
|
||||
int PCARS_packetSize = UDP.parsePacket();
|
||||
if (PCARS_packetSize) {
|
||||
int len = UDP.read(PCARS_packet, PCARS_packetSize);
|
||||
if (len > 0) {
|
||||
PCARS_packet[len] = 0;
|
||||
}
|
||||
if (len == 1367) { // Telemetry packet. Ignoring everything else.
|
||||
PCARS_lastRead = millis();
|
||||
|
||||
arlsLock(realtimeTimeoutMs, REALTIME_MODE_GENERIC);
|
||||
// current RPM
|
||||
memcpy(&PCARS_tempChar, &PCARS_packet[124], 2);
|
||||
PCARS_RPM = (PCARS_tempChar[1] << 8) + PCARS_tempChar[0];
|
||||
|
||||
// max RPM
|
||||
memcpy(&PCARS_tempChar, &PCARS_packet[126], 2);
|
||||
PCARS_maxRPM = (PCARS_tempChar[1] << 8) + PCARS_tempChar[0];
|
||||
|
||||
if (PCARS_maxRPM) {
|
||||
PCARS_rpmRatio = constrain((float)PCARS_RPM / (float)PCARS_maxRPM, 0, 1);
|
||||
} else {
|
||||
PCARS_rpmRatio = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void PCARS_buildcolorbars() {
|
||||
boolean activated = false;
|
||||
float ledratio = 0;
|
||||
|
||||
for (uint16_t i = 0; i < ledCount; i++) {
|
||||
if (PCARS_rpmRatio < .95 || (millis() % 100 > 70 )) {
|
||||
|
||||
ledratio = (float)i / (float)ledCount;
|
||||
if (ledratio < PCARS_rpmRatio) {
|
||||
activated = true;
|
||||
} else {
|
||||
activated = false;
|
||||
}
|
||||
if (ledratio > 0.66) {
|
||||
setRealtimePixel(i, 0, 0, PCARS_dimcolor + ((255 - PCARS_dimcolor)*activated), 0);
|
||||
} else if (ledratio > 0.33) {
|
||||
setRealtimePixel(i, PCARS_dimcolor + ((255 - PCARS_dimcolor)*activated), 0, 0, 0);
|
||||
} else {
|
||||
setRealtimePixel(i, 0, PCARS_dimcolor + ((255 - PCARS_dimcolor)*activated), 0, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
setRealtimePixel(i, 0, 0, 0, 0);
|
||||
|
||||
}
|
||||
}
|
||||
colorUpdated(5);
|
||||
strip.show();
|
||||
}
|
@ -1,14 +1,14 @@
|
||||
### Usermods
|
||||
|
||||
This folder serves as a repository for usermods (custom `wled06_usermod.ino` files)!
|
||||
This folder serves as a repository for usermods (custom `usermod.cpp` files)!
|
||||
|
||||
If you have created an usermod that you believe is useful (for example to support a particular sensor, display, feature...), feel free to contribute by opening a pull request!
|
||||
|
||||
In order for other people to be able to have fun with your usermod, please keep these points in mind:
|
||||
|
||||
- Create a folder in this folder with a descriptive name (for example `usermod_ds18b20_temp_sensor_mqtt`)
|
||||
- Include your custom `wled06_usermod.ino` file
|
||||
- If your usermod requieres changes to other WLED files, please write a `readme.md` outlining the steps one has to take to use the usermod
|
||||
- Include your custom `usermod.cpp` file
|
||||
- If your usermod requires changes to other WLED files, please write a `readme.md` outlining the steps one has to take to use the usermod
|
||||
- Create a pull request!
|
||||
- If your feature is useful for the majority of WLED users, I will consider adding it to the base code!
|
||||
|
||||
|
62
usermods/rotary_encoder_change_brightness/usermod.cpp
Normal file
62
usermods/rotary_encoder_change_brightness/usermod.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
*/
|
||||
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
/*
|
||||
** Rotary Encoder Example
|
||||
** Use the Sparkfun Rotary Encoder to vary brightness of LED
|
||||
**
|
||||
** Sample the encoder at 500Hz using the millis() function
|
||||
*/
|
||||
|
||||
int fadeAmount = 5; // how many points to fade the Neopixel with each step
|
||||
unsigned long currentTime;
|
||||
unsigned long loopTime;
|
||||
const int pinA = D6; // DT from encoder
|
||||
const int pinB = D7; // CLK from encoder
|
||||
|
||||
unsigned char Enc_A;
|
||||
unsigned char Enc_B;
|
||||
unsigned char Enc_A_prev = 0;
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup() {
|
||||
pinMode(pinA, INPUT_PULLUP);
|
||||
pinMode(pinB, INPUT_PULLUP);
|
||||
currentTime = millis();
|
||||
loopTime = currentTime;
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected() {
|
||||
}
|
||||
|
||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
||||
void userLoop() {
|
||||
currentTime = millis(); // get the current elapsed time
|
||||
if(currentTime >= (loopTime + 2)) // 2ms since last check of encoder = 500Hz
|
||||
{
|
||||
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
|
||||
if(bri + fadeAmount <= 255) bri += fadeAmount; // increase the brightness, dont go over 255
|
||||
|
||||
} else if (Enc_B == LOW) { // B is low so counter-clockwise
|
||||
if(bri - fadeAmount >= 0) bri -= fadeAmount; // decrease the brightness, dont go below 0
|
||||
}
|
||||
}
|
||||
Enc_A_prev = Enc_A; // Store value of A for next time
|
||||
loopTime = currentTime; // Updates loopTime
|
||||
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
colorUpdated(6);
|
||||
}
|
||||
}
|
@ -39,7 +39,7 @@ void userLoop() {
|
||||
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
colorUpdated(6);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
lastTime = millis();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled01_eeprom.h)
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled_eeprom.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
*/
|
||||
|
||||
@ -11,6 +11,9 @@ byte wipeState = 0; //0: inactive 1: wiping 2: solid
|
||||
unsigned long timeStaticStart = 0;
|
||||
uint16_t previousUserVar0 = 0;
|
||||
|
||||
//comment this out if you want the turn off effect to be just fading out instead of reverse wipe
|
||||
#define STAIRCASE_WIPE_OFF
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup()
|
||||
{
|
||||
@ -44,7 +47,7 @@ void userLoop()
|
||||
if (millis() + strip.timebase > (cycleTime - 25)) { //wipe complete
|
||||
effectCurrent = FX_MODE_STATIC;
|
||||
timeStaticStart = millis();
|
||||
colorUpdated(3);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
wipeState = 2;
|
||||
}
|
||||
} else if (wipeState == 2) { //static
|
||||
@ -52,14 +55,28 @@ void userLoop()
|
||||
{
|
||||
if (millis() - timeStaticStart > userVar1*1000) wipeState = 3;
|
||||
}
|
||||
} else { //wipeState == 3, turn off slowly
|
||||
} else if (wipeState == 3) { //switch to wipe off
|
||||
#ifdef STAIRCASE_WIPE_OFF
|
||||
effectCurrent = FX_MODE_COLOR_WIPE;
|
||||
strip.timebase = 360 + (255 - effectSpeed)*75 - millis(); //make sure wipe starts fully lit
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
wipeState = 4;
|
||||
#else
|
||||
turnOff();
|
||||
userVar0 = 0;
|
||||
wipeState = 0;
|
||||
#endif
|
||||
} else { //wiping off
|
||||
if (millis() + strip.timebase > (725 + (255 - effectSpeed)*150)) turnOff(); //wipe complete
|
||||
}
|
||||
} else {
|
||||
if (previousUserVar0) turnOff();
|
||||
wipeState = 0; //reset for next time
|
||||
if (previousUserVar0) {
|
||||
#ifdef STAIRCASE_WIPE_OFF
|
||||
userVar0 = previousUserVar0;
|
||||
wipeState = 3;
|
||||
#else
|
||||
turnOff();
|
||||
#endif
|
||||
}
|
||||
previousUserVar0 = 0;
|
||||
}
|
||||
}
|
||||
@ -76,12 +93,19 @@ void startWipe()
|
||||
bool doReverse = (userVar0 == 2);
|
||||
seg.setOption(1, doReverse);
|
||||
|
||||
colorUpdated(3);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
}
|
||||
|
||||
void turnOff()
|
||||
{
|
||||
transitionDelayTemp = 4000;
|
||||
#ifdef STAIRCASE_WIPE_OFF
|
||||
transitionDelayTemp = 0; //turn off immediately after wipe completed
|
||||
#else
|
||||
transitionDelayTemp = 4000; //fade out slowly
|
||||
#endif
|
||||
bri = 0;
|
||||
colorUpdated(3);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
wipeState = 0;
|
||||
userVar0 = 0;
|
||||
previousUserVar0 = 0;
|
||||
}
|
||||
|
902
wled00/FX.cpp
902
wled00/FX.cpp
File diff suppressed because it is too large
Load Diff
107
wled00/FX.h
107
wled00/FX.h
@ -28,6 +28,7 @@
|
||||
#define WS2812FX_h
|
||||
|
||||
#include "NpbWrapper.h"
|
||||
#include "const.h"
|
||||
|
||||
#define FASTLED_INTERNAL //remove annoying pragma messages
|
||||
#include "FastLED.h"
|
||||
@ -37,8 +38,8 @@
|
||||
#define DEFAULT_SPEED (uint8_t)128
|
||||
#define DEFAULT_COLOR (uint32_t)0xFFAA00
|
||||
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
|
||||
/* Not used in all effects yet */
|
||||
#define WLED_FPS 42
|
||||
@ -55,11 +56,14 @@
|
||||
#define MAX_SEGMENT_DATA 8192
|
||||
#endif
|
||||
|
||||
#define LED_SKIP_AMOUNT 1
|
||||
#define MIN_SHOW_DELAY 15
|
||||
|
||||
#define NUM_COLORS 3 /* number of colors per segment */
|
||||
#define SEGMENT _segments[_segment_index]
|
||||
#define SEGCOLOR(x) gamma32(_segments[_segment_index].colors[x])
|
||||
#define SEGENV _segment_runtimes[_segment_index]
|
||||
#define SEGLEN SEGMENT.length()
|
||||
#define SEGLEN _virtualSegmentLength
|
||||
#define SEGACT SEGMENT.stop
|
||||
#define SPEED_FORMULA_L 5 + (50*(255 - SEGMENT.speed))/SEGLEN
|
||||
#define RESET_RUNTIME memset(_segment_runtimes, 0, sizeof(_segment_runtimes))
|
||||
@ -80,18 +84,21 @@
|
||||
|
||||
// options
|
||||
// bit 7: segment is in transition mode
|
||||
// bits 2-6: TBD
|
||||
// bits 3-6: TBD
|
||||
// bit 2: segment is on
|
||||
// bit 1: reverse segment
|
||||
// bit 0: segment is selected
|
||||
#define NO_OPTIONS (uint8_t)0x00
|
||||
#define TRANSITIONAL (uint8_t)0x80
|
||||
#define SEGMENT_ON (uint8_t)0x04
|
||||
#define REVERSE (uint8_t)0x02
|
||||
#define SELECTED (uint8_t)0x01
|
||||
#define IS_TRANSITIONAL ((SEGMENT.options & TRANSITIONAL) == TRANSITIONAL)
|
||||
#define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE )
|
||||
#define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED )
|
||||
#define IS_SEGMENT_ON ((SEGMENT.options & SEGMENT_ON ) == SEGMENT_ON )
|
||||
#define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE )
|
||||
#define IS_SELECTED ((SEGMENT.options & SELECTED ) == SELECTED )
|
||||
|
||||
#define MODE_COUNT 97
|
||||
#define MODE_COUNT 104
|
||||
|
||||
#define FX_MODE_STATIC 0
|
||||
#define FX_MODE_BLINK 1
|
||||
@ -190,7 +197,13 @@
|
||||
#define FX_MODE_SINELON_RAINBOW 94
|
||||
#define FX_MODE_POPCORN 95
|
||||
#define FX_MODE_DRIP 96
|
||||
|
||||
#define FX_MODE_PLASMA 97
|
||||
#define FX_MODE_PERCENT 98
|
||||
#define FX_MODE_RIPPLE_RAINBOW 99
|
||||
#define FX_MODE_HEARTBEAT 100
|
||||
#define FX_MODE_PACIFICA 101
|
||||
#define FX_MODE_CANDLE_MULTI 102
|
||||
#define FX_MODE_SOLID_GLITTER 103
|
||||
|
||||
class WS2812FX {
|
||||
typedef uint16_t (WS2812FX::*mode_ptr)(void);
|
||||
@ -207,8 +220,8 @@ class WS2812FX {
|
||||
uint8_t intensity;
|
||||
uint8_t palette;
|
||||
uint8_t mode;
|
||||
uint8_t options; //bit pattern: msb first: transitional tbd tbd tbd tbd paused reverse selected
|
||||
uint8_t group, spacing;
|
||||
uint8_t options; //bit pattern: msb first: transitional needspixelstate tbd tbd (paused) on reverse selected
|
||||
uint8_t grouping, spacing;
|
||||
uint8_t opacity;
|
||||
uint32_t colors[NUM_COLORS];
|
||||
void setOption(uint8_t n, bool val)
|
||||
@ -236,6 +249,15 @@ class WS2812FX {
|
||||
{
|
||||
return stop - start;
|
||||
}
|
||||
uint16_t groupLength()
|
||||
{
|
||||
return grouping + spacing;
|
||||
}
|
||||
uint16_t virtualLength()
|
||||
{
|
||||
uint16_t groupLen = groupLength();
|
||||
return (length() + groupLen -1) / groupLen;
|
||||
}
|
||||
} segment;
|
||||
|
||||
// segment runtime parameters
|
||||
@ -367,6 +389,13 @@ class WS2812FX {
|
||||
_mode[FX_MODE_SINELON_RAINBOW] = &WS2812FX::mode_sinelon_rainbow;
|
||||
_mode[FX_MODE_POPCORN] = &WS2812FX::mode_popcorn;
|
||||
_mode[FX_MODE_DRIP] = &WS2812FX::mode_drip;
|
||||
_mode[FX_MODE_PLASMA] = &WS2812FX::mode_plasma;
|
||||
_mode[FX_MODE_PERCENT] = &WS2812FX::mode_percent;
|
||||
_mode[FX_MODE_RIPPLE_RAINBOW] = &WS2812FX::mode_ripple_rainbow;
|
||||
_mode[FX_MODE_HEARTBEAT] = &WS2812FX::mode_heartbeat;
|
||||
_mode[FX_MODE_PACIFICA] = &WS2812FX::mode_pacifica;
|
||||
_mode[FX_MODE_CANDLE_MULTI] = &WS2812FX::mode_candle_multi;
|
||||
_mode[FX_MODE_SOLID_GLITTER] = &WS2812FX::mode_solid_glitter;
|
||||
|
||||
_brightness = DEFAULT_BRIGHTNESS;
|
||||
currentPalette = CRGBPalette16(CRGB::Black);
|
||||
@ -379,7 +408,7 @@ class WS2812FX {
|
||||
}
|
||||
|
||||
void
|
||||
init(bool supportWhite, uint16_t countPixels, bool skipFirs, uint8_t disableNLeds),
|
||||
init(bool supportWhite, uint16_t countPixels, bool skipFirst),
|
||||
service(void),
|
||||
blur(uint8_t),
|
||||
fade_out(uint8_t r),
|
||||
@ -387,18 +416,16 @@ class WS2812FX {
|
||||
setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
||||
setColor(uint8_t slot, uint32_t c),
|
||||
setBrightness(uint8_t b),
|
||||
driverModeCronixie(bool b),
|
||||
setCronixieDigits(byte* d),
|
||||
setCronixieBacklight(bool b),
|
||||
setRange(uint16_t i, uint16_t i2, uint32_t col),
|
||||
setShowCallback(show_callback cb),
|
||||
setTransitionMode(bool t),
|
||||
trigger(void),
|
||||
setSegment(uint8_t n, uint16_t start, uint16_t stop),
|
||||
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 0, uint8_t spacing = 0),
|
||||
resetSegments(),
|
||||
setPixelColor(uint16_t n, uint32_t c),
|
||||
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
||||
show(void);
|
||||
show(void),
|
||||
setRgbwPwm(void);
|
||||
|
||||
bool
|
||||
reverseMode = false,
|
||||
@ -410,11 +437,11 @@ class WS2812FX {
|
||||
|
||||
uint8_t
|
||||
mainSegment = 0,
|
||||
rgbwMode = RGBW_MODE_DUAL,
|
||||
paletteFade = 0,
|
||||
paletteBlend = 0,
|
||||
colorOrder = 0,
|
||||
milliampsPerLed = 55,
|
||||
_disableNLeds = 0,
|
||||
getBrightness(void),
|
||||
getMode(void),
|
||||
getSpeed(void),
|
||||
@ -429,8 +456,7 @@ class WS2812FX {
|
||||
uint16_t
|
||||
ablMilliampsMax,
|
||||
currentMilliamps,
|
||||
triwave16(uint16_t),
|
||||
getUsableCount();
|
||||
triwave16(uint16_t);
|
||||
|
||||
uint32_t
|
||||
timebase,
|
||||
@ -538,7 +564,7 @@ class WS2812FX {
|
||||
mode_twinklecat(void),
|
||||
mode_halloween_eyes(void),
|
||||
mode_static_pattern(void),
|
||||
mode_tri_static_pattern(void),
|
||||
mode_tri_static_pattern(void),
|
||||
mode_spots(void),
|
||||
mode_spots_fade(void),
|
||||
mode_glitter(void),
|
||||
@ -550,8 +576,14 @@ class WS2812FX {
|
||||
mode_sinelon_dual(void),
|
||||
mode_sinelon_rainbow(void),
|
||||
mode_popcorn(void),
|
||||
mode_drip(void);
|
||||
|
||||
mode_drip(void),
|
||||
mode_plasma(void),
|
||||
mode_percent(void),
|
||||
mode_ripple_rainbow(void),
|
||||
mode_heartbeat(void),
|
||||
mode_pacifica(void),
|
||||
mode_candle_multi(void),
|
||||
mode_solid_glitter(void);
|
||||
|
||||
private:
|
||||
NeoPixelWrapper *bus;
|
||||
@ -562,23 +594,20 @@ class WS2812FX {
|
||||
CRGBPalette16 targetPalette;
|
||||
|
||||
uint32_t now;
|
||||
uint16_t _length, _lengthRaw, _usableCount;
|
||||
uint16_t _length, _lengthRaw, _virtualSegmentLength;
|
||||
uint16_t _rand16seed;
|
||||
uint8_t _brightness;
|
||||
static uint16_t _usedSegmentData;
|
||||
|
||||
void load_gradient_palette(uint8_t);
|
||||
void handle_palette(void);
|
||||
void fill(uint32_t);
|
||||
|
||||
bool
|
||||
_rgbwMode,
|
||||
_cronixieMode,
|
||||
_cronixieBacklightEnabled,
|
||||
_useRgbw = false,
|
||||
_skipFirstMode,
|
||||
_triggered;
|
||||
|
||||
byte _cronixieDigits[6];
|
||||
|
||||
mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element
|
||||
|
||||
show_callback _callback = nullptr;
|
||||
@ -586,6 +615,7 @@ class WS2812FX {
|
||||
// mode helper functions
|
||||
uint16_t
|
||||
blink(uint32_t, uint32_t, bool strobe, bool),
|
||||
candle(bool),
|
||||
color_wipe(bool, bool),
|
||||
scan(bool),
|
||||
theater_chase(uint32_t, uint32_t, bool),
|
||||
@ -595,25 +625,35 @@ class WS2812FX {
|
||||
dissolve(uint32_t),
|
||||
chase(uint32_t, uint32_t, uint32_t, bool),
|
||||
gradient_base(bool),
|
||||
police_base(uint32_t, uint32_t),
|
||||
ripple_base(bool),
|
||||
police_base(uint32_t, uint32_t, bool),
|
||||
running(uint32_t, uint32_t),
|
||||
tricolor_chase(uint32_t, uint32_t),
|
||||
twinklefox_base(bool),
|
||||
spots_base(uint16_t);
|
||||
|
||||
CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat);
|
||||
CRGB pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff);
|
||||
|
||||
uint32_t _lastPaletteChange = 0;
|
||||
uint32_t _lastShow = 0;
|
||||
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
uint32_t _analogLastShow = 0;
|
||||
RgbwColor _analogLastColor = 0;
|
||||
uint8_t _analogLastBri = 0;
|
||||
#endif
|
||||
|
||||
uint8_t _segment_index = 0;
|
||||
uint8_t _segment_index_palette_last = 99;
|
||||
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 24 bytes per element
|
||||
// start, stop, speed, intensity, palette, mode, options, 3 unused bytes (group, spacing, opacity), color[]
|
||||
// start, stop, speed, intensity, palette, mode, options, grouping, spacing, opacity (unused), color[]
|
||||
{ 0, 7, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}}
|
||||
};
|
||||
segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element
|
||||
friend class Segment_runtime;
|
||||
|
||||
uint16_t realPixelIndex(uint16_t i);
|
||||
};
|
||||
|
||||
|
||||
@ -628,17 +668,18 @@ const char JSON_mode_names[] PROGMEM = R"=====([
|
||||
"Scanner Dual","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise",
|
||||
"Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple",
|
||||
"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst",
|
||||
"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip"
|
||||
"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip","Plasma","Percent","Ripple Rainbow",
|
||||
"Heartbeat","Pacifica","Candle Multi", "Solid Glitter"
|
||||
])=====";
|
||||
|
||||
|
||||
const char JSON_palette_names[] PROGMEM = R"=====([
|
||||
"Default","Random Cycle","Primary Color","Based on Primary","Set Colors","Based on Set","Party","Cloud","Lava","Ocean",
|
||||
"Default","* Random Cycle","* Color 1","* Colors 1&2","* Color Gradient","* Colors Only","Party","Cloud","Lava","Ocean",
|
||||
"Forest","Rainbow","Rainbow Bands","Sunset","Rivendell","Breeze","Red & Blue","Yellowout","Analogous","Splash",
|
||||
"Pastel","Sunset 2","Beech","Vintage","Departure","Landscape","Beach","Sherbet","Hult","Hult 64",
|
||||
"Drywet","Jul","Grintage","Rewhi","Tertiary","Fire","Icefire","Cyane","Light Pink","Autumn",
|
||||
"Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery","C9","Sakura",
|
||||
"Aurora"
|
||||
"Aurora","Atlantica"
|
||||
])=====";
|
||||
|
||||
#endif
|
||||
|
@ -27,31 +27,33 @@
|
||||
#include "FX.h"
|
||||
#include "palettes.h"
|
||||
|
||||
#define LED_SKIP_AMOUNT 1
|
||||
#define MIN_SHOW_DELAY 15
|
||||
//enable custom per-LED mapping. This can allow for better effects on matrices or special displays
|
||||
//#define WLED_CUSTOM_LED_MAPPING
|
||||
|
||||
void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst, uint8_t disableNLeds)
|
||||
#ifdef WLED_CUSTOM_LED_MAPPING
|
||||
//this is just an example (30 LEDs). It will first set all even, then all uneven LEDs.
|
||||
const uint16_t customMappingTable[] = {
|
||||
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28,
|
||||
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29};
|
||||
|
||||
//another example. Switches direction every 5 LEDs.
|
||||
/*const uint16_t customMappingTable[] = {
|
||||
0, 1, 2, 3, 4, 9, 8, 7, 6, 5, 10, 11, 12, 13, 14,
|
||||
19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 29, 28, 27, 26, 25};*/
|
||||
|
||||
const uint16_t customMappingSize = sizeof(customMappingTable)/sizeof(uint16_t); //30 in example
|
||||
#endif
|
||||
|
||||
void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst)
|
||||
{
|
||||
if (supportWhite == _rgbwMode && countPixels == _length && disableNLeds == _disableNLeds) return;
|
||||
if (supportWhite == _useRgbw && countPixels == _length && _skipFirstMode == skipFirst) return;
|
||||
RESET_RUNTIME;
|
||||
_rgbwMode = supportWhite;
|
||||
_skipFirstMode = skipFirst;
|
||||
_useRgbw = supportWhite;
|
||||
_length = countPixels;
|
||||
|
||||
if (disableNLeds > 0) {
|
||||
uint16_t groupCount = disableNLeds +1;
|
||||
//since 1st led is lit, even partial group has a led lit, whereas int division truncates decimal.
|
||||
bool hasExtraLight = _length % groupCount != 0;
|
||||
_usableCount = _length/groupCount;
|
||||
_usableCount += hasExtraLight ? 1 : 0;
|
||||
} else {
|
||||
_usableCount = _length;
|
||||
}
|
||||
|
||||
_disableNLeds = disableNLeds;
|
||||
_skipFirstMode = skipFirst;
|
||||
|
||||
uint8_t ty = 1;
|
||||
if (supportWhite) ty =2;
|
||||
if (supportWhite) ty = 2;
|
||||
_lengthRaw = _length;
|
||||
if (_skipFirstMode) {
|
||||
_lengthRaw += LED_SKIP_AMOUNT;
|
||||
@ -60,7 +62,7 @@ void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst, uin
|
||||
bus->Begin((NeoPixelType)ty, _lengthRaw);
|
||||
|
||||
_segments[0].start = 0;
|
||||
_segments[0].stop = _usableCount;
|
||||
_segments[0].stop = _length;
|
||||
|
||||
setBrightness(_brightness);
|
||||
}
|
||||
@ -70,6 +72,7 @@ void WS2812FX::service() {
|
||||
now = nowUp + timebase;
|
||||
if (nowUp - _lastShow < MIN_SHOW_DELAY) return;
|
||||
bool doShow = false;
|
||||
|
||||
for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
_segment_index = i;
|
||||
@ -77,6 +80,8 @@ void WS2812FX::service() {
|
||||
{
|
||||
if(nowUp > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary
|
||||
{
|
||||
if (SEGMENT.grouping == 0) SEGMENT.grouping = 1; //sanity check
|
||||
_virtualSegmentLength = SEGMENT.virtualLength();
|
||||
doShow = true;
|
||||
handle_palette();
|
||||
uint16_t delay = (this->*_mode[SEGMENT.mode])();
|
||||
@ -85,6 +90,7 @@ void WS2812FX::service() {
|
||||
}
|
||||
}
|
||||
}
|
||||
_virtualSegmentLength = 0;
|
||||
if(doShow) {
|
||||
yield();
|
||||
show();
|
||||
@ -100,85 +106,88 @@ void WS2812FX::setPixelColor(uint16_t n, uint32_t c) {
|
||||
setPixelColor(n, r, g, b, w);
|
||||
}
|
||||
|
||||
uint16_t WS2812FX::realPixelIndex(uint16_t i) {
|
||||
int16_t iGroup = i * SEGMENT.groupLength();
|
||||
|
||||
/* reverse just an individual segment */
|
||||
int16_t realIndex = iGroup;
|
||||
if (IS_REVERSE) realIndex = SEGMENT.length() -iGroup -1;
|
||||
|
||||
realIndex += SEGMENT.start;
|
||||
/* Reverse the whole string */
|
||||
if (reverseMode) realIndex = _length - 1 - realIndex;
|
||||
|
||||
return realIndex;
|
||||
}
|
||||
|
||||
void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
|
||||
{
|
||||
i = i * (_disableNLeds+1);
|
||||
if (IS_REVERSE) i = SEGMENT.stop -1 -i + SEGMENT.start; //reverse just individual segment
|
||||
byte tmpg = g;
|
||||
switch (colorOrder) //0 = Grb, default
|
||||
{
|
||||
case 0: break; //0 = Grb, default
|
||||
case 1: g = r; r = tmpg; break; //1 = Rgb, common for WS2811
|
||||
case 2: g = b; b = tmpg; break; //2 = Brg
|
||||
case 3: g = b; b = r; r = tmpg; //3 = Rbg
|
||||
}
|
||||
if (!_cronixieMode)
|
||||
{
|
||||
if (reverseMode) i = _length -1 -i;
|
||||
if (_skipFirstMode)
|
||||
//auto calculate white channel value if enabled
|
||||
if (_useRgbw) {
|
||||
if (rgbwMode == RGBW_MODE_AUTO_BRIGHTER || (w == 0 && (rgbwMode == RGBW_MODE_DUAL || rgbwMode == RGBW_MODE_LEGACY)))
|
||||
{
|
||||
if (i < LED_SKIP_AMOUNT) bus->SetPixelColor(i, RgbwColor(0,0,0,0));
|
||||
i += LED_SKIP_AMOUNT;
|
||||
}
|
||||
if (i < _lengthRaw) bus->SetPixelColor(i, RgbwColor(r,g,b,w));
|
||||
if (_disableNLeds > 0) {
|
||||
for(uint16_t offCount=0; offCount < _disableNLeds; offCount++) {
|
||||
if (i < _lengthRaw) bus->SetPixelColor((i + offCount + 1), RgbwColor(0,0,0,0));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(i>6)return;
|
||||
byte o = 10*i;
|
||||
if (_cronixieBacklightEnabled && _cronixieDigits[i] <11)
|
||||
//white value is set to lowest RGB channel
|
||||
//thank you to @Def3nder!
|
||||
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||
} else if (rgbwMode == RGBW_MODE_AUTO_ACCURATE && w == 0)
|
||||
{
|
||||
byte r2 = _segments[0].colors[1] >>16;
|
||||
byte g2 = _segments[0].colors[1] >> 8;
|
||||
byte b2 = _segments[0].colors[1];
|
||||
byte w2 = _segments[0].colors[1] >>24;
|
||||
for (int j=o; j< o+19; j++)
|
||||
{
|
||||
bus->SetPixelColor(j, RgbwColor(r2,g2,b2,w2));
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (int j=o; j< o+19; j++)
|
||||
{
|
||||
bus->SetPixelColor(j, RgbwColor(0,0,0,0));
|
||||
}
|
||||
}
|
||||
if (_skipFirstMode) o += LED_SKIP_AMOUNT;
|
||||
switch(_cronixieDigits[i])
|
||||
{
|
||||
case 0: bus->SetPixelColor(o+5, RgbwColor(r,g,b,w)); break;
|
||||
case 1: bus->SetPixelColor(o+0, RgbwColor(r,g,b,w)); break;
|
||||
case 2: bus->SetPixelColor(o+6, RgbwColor(r,g,b,w)); break;
|
||||
case 3: bus->SetPixelColor(o+1, RgbwColor(r,g,b,w)); break;
|
||||
case 4: bus->SetPixelColor(o+7, RgbwColor(r,g,b,w)); break;
|
||||
case 5: bus->SetPixelColor(o+2, RgbwColor(r,g,b,w)); break;
|
||||
case 6: bus->SetPixelColor(o+8, RgbwColor(r,g,b,w)); break;
|
||||
case 7: bus->SetPixelColor(o+3, RgbwColor(r,g,b,w)); break;
|
||||
case 8: bus->SetPixelColor(o+9, RgbwColor(r,g,b,w)); break;
|
||||
case 9: bus->SetPixelColor(o+4, RgbwColor(r,g,b,w)); break;
|
||||
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||
r -= w; g -= w; b -= w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::driverModeCronixie(bool b)
|
||||
{
|
||||
_cronixieMode = b;
|
||||
_segments[0].stop = (b) ? 6 : _length;
|
||||
}
|
||||
|
||||
void WS2812FX::setCronixieBacklight(bool b)
|
||||
{
|
||||
_cronixieBacklightEnabled = b;
|
||||
}
|
||||
|
||||
void WS2812FX::setCronixieDigits(byte d[])
|
||||
{
|
||||
for (int i = 0; i<6; i++)
|
||||
RgbwColor col;
|
||||
switch (colorOrder)
|
||||
{
|
||||
_cronixieDigits[i] = d[i];
|
||||
case 0: col.G = g; col.R = r; col.B = b; break; //0 = GRB, default
|
||||
case 1: col.G = r; col.R = g; col.B = b; break; //1 = RGB, common for WS2811
|
||||
case 2: col.G = b; col.R = r; col.B = g; break; //2 = BRG
|
||||
case 3: col.G = r; col.R = b; col.B = g; break; //3 = RBG
|
||||
case 4: col.G = b; col.R = g; col.B = r; break; //4 = BGR
|
||||
default: col.G = g; col.R = b; col.B = r; break; //5 = GBR
|
||||
}
|
||||
col.W = w;
|
||||
|
||||
uint16_t skip = _skipFirstMode ? LED_SKIP_AMOUNT : 0;
|
||||
if (SEGLEN) {//from segment
|
||||
|
||||
//color_blend(getpixel, col, SEGMENT.opacity); (pseudocode for future blending of segments)
|
||||
if (IS_SEGMENT_ON)
|
||||
{
|
||||
if (SEGMENT.opacity < 255) {
|
||||
col.R = scale8(col.R, SEGMENT.opacity);
|
||||
col.G = scale8(col.G, SEGMENT.opacity);
|
||||
col.B = scale8(col.B, SEGMENT.opacity);
|
||||
col.W = scale8(col.W, SEGMENT.opacity);
|
||||
}
|
||||
} else {
|
||||
col = BLACK;
|
||||
}
|
||||
|
||||
/* Set all the pixels in the group, ensuring _skipFirstMode is honored */
|
||||
bool reversed = reverseMode ^ IS_REVERSE;
|
||||
uint16_t realIndex = realPixelIndex(i);
|
||||
|
||||
for (uint16_t j = 0; j < SEGMENT.grouping; j++) {
|
||||
int16_t indexSet = realIndex + (reversed ? -j : j);
|
||||
int16_t indexSetRev = indexSet;
|
||||
if (reverseMode) indexSetRev = _length - 1 - indexSet;
|
||||
#ifdef WLED_CUSTOM_LED_MAPPING
|
||||
if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet];
|
||||
#endif
|
||||
if (indexSetRev >= SEGMENT.start && indexSetRev < SEGMENT.stop) bus->SetPixelColor(indexSet + skip, col);
|
||||
}
|
||||
} else { //live data, etc.
|
||||
if (reverseMode) i = _length - 1 - i;
|
||||
#ifdef WLED_CUSTOM_LED_MAPPING
|
||||
if (i < customMappingSize) i = customMappingTable[i];
|
||||
#endif
|
||||
bus->SetPixelColor(i + skip, col);
|
||||
}
|
||||
if (skip && i == 0) {
|
||||
for (uint16_t j = 0; j < skip; j++) {
|
||||
bus->SetPixelColor(j, RgbwColor(0, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,10 +210,17 @@ void WS2812FX::show(void) {
|
||||
//each LED can draw up 195075 "power units" (approx. 53mA)
|
||||
//one PU is the power it takes to have 1 channel 1 step brighter per brightness step
|
||||
//so A=2,R=255,G=0,B=0 would use 510 PU per LED (1mA is about 3700 PU)
|
||||
bool useWackyWS2815PowerModel = false;
|
||||
byte actualMilliampsPerLed = milliampsPerLed;
|
||||
|
||||
if (ablMilliampsMax > 149 && milliampsPerLed > 0) //0 mA per LED and too low numbers turn off calculation
|
||||
if(milliampsPerLed == 255) {
|
||||
useWackyWS2815PowerModel = true;
|
||||
actualMilliampsPerLed = 12; // from testing an actual strip
|
||||
}
|
||||
|
||||
if (ablMilliampsMax > 149 && actualMilliampsPerLed > 0) //0 mA per LED and too low numbers turn off calculation
|
||||
{
|
||||
uint32_t puPerMilliamp = 195075 / milliampsPerLed;
|
||||
uint32_t puPerMilliamp = 195075 / actualMilliampsPerLed;
|
||||
uint32_t powerBudget = (ablMilliampsMax - MA_FOR_ESP) * puPerMilliamp; //100mA for ESP power
|
||||
if (powerBudget > puPerMilliamp * _length) //each LED uses about 1mA in standby, exclude that from power budget
|
||||
{
|
||||
@ -219,10 +235,20 @@ void WS2812FX::show(void) {
|
||||
for (uint16_t i = 0; i < _length; i++) //sum up the usage of each LED
|
||||
{
|
||||
RgbwColor c = bus->GetPixelColorRgbw(i);
|
||||
powerSum += (c.R + c.G + c.B + c.W);
|
||||
|
||||
if(useWackyWS2815PowerModel)
|
||||
{
|
||||
// ignore white component on WS2815 power calculation
|
||||
powerSum += (MAX(MAX(c.R,c.G),c.B)) * 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
powerSum += (c.R + c.G + c.B + c.W);
|
||||
}
|
||||
}
|
||||
|
||||
if (_rgbwMode) //RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
|
||||
|
||||
if (_useRgbw) //RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
|
||||
{
|
||||
powerSum *= 3;
|
||||
powerSum = powerSum >> 2; //same as /= 4
|
||||
@ -278,7 +304,7 @@ uint8_t WS2812FX::getModeCount()
|
||||
|
||||
uint8_t WS2812FX::getPaletteCount()
|
||||
{
|
||||
return 13 + gGradientPaletteCount;
|
||||
return 13 + GRADIENT_PALETTE_COUNT;
|
||||
}
|
||||
|
||||
//TODO transitions
|
||||
@ -289,6 +315,8 @@ bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t in, uint8_t p) {
|
||||
Segment& seg = _segments[getMainSegmentId()];
|
||||
uint8_t modePrev = seg.mode, speedPrev = seg.speed, intensityPrev = seg.intensity, palettePrev = seg.palette;
|
||||
|
||||
bool applied = false;
|
||||
|
||||
if (applyToAllSelected) {
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
@ -298,9 +326,12 @@ bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t in, uint8_t p) {
|
||||
_segments[i].intensity = in;
|
||||
_segments[i].palette = p;
|
||||
setMode(i, m);
|
||||
applied = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if (!applyToAllSelected || !applied) {
|
||||
seg.speed = s;
|
||||
seg.intensity = in;
|
||||
seg.palette = p;
|
||||
@ -317,12 +348,17 @@ void WS2812FX::setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w
|
||||
|
||||
void WS2812FX::setColor(uint8_t slot, uint32_t c) {
|
||||
if (slot >= NUM_COLORS) return;
|
||||
|
||||
bool applied = false;
|
||||
|
||||
if (applyToAllSelected) {
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isSelected()) _segments[i].colors[slot] = c;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if (!applyToAllSelected || !applied) {
|
||||
_segments[getMainSegmentId()].colors[slot] = c;
|
||||
}
|
||||
}
|
||||
@ -331,7 +367,7 @@ void WS2812FX::setBrightness(uint8_t b) {
|
||||
if (_brightness == b) return;
|
||||
_brightness = (gammaCorrectBri) ? gamma8(b) : b;
|
||||
_segment_index = 0;
|
||||
if (SEGENV.next_time > millis() + 22) show();//apply brightness change immediately if no refresh soon
|
||||
if (SEGENV.next_time > millis() + 22 && millis() - _lastShow > MIN_SHOW_DELAY) show();//apply brightness change immediately if no refresh soon
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getMode(void) {
|
||||
@ -374,40 +410,28 @@ uint32_t WS2812FX::getColor(void) {
|
||||
|
||||
uint32_t WS2812FX::getPixelColor(uint16_t i)
|
||||
{
|
||||
i = i * (_disableNLeds+1);
|
||||
if (reverseMode) i = _length- 1 -i;
|
||||
if (IS_REVERSE) i = SEGMENT.stop -1 -i + SEGMENT.start; //reverse just individual segment
|
||||
i = realPixelIndex(i);
|
||||
|
||||
#ifdef WLED_CUSTOM_LED_MAPPING
|
||||
if (i < customMappingSize) i = customMappingTable[i];
|
||||
#endif
|
||||
|
||||
if (_skipFirstMode) i += LED_SKIP_AMOUNT;
|
||||
if (_cronixieMode)
|
||||
{
|
||||
if(i>6)return 0;
|
||||
byte o = 10*i;
|
||||
switch(_cronixieDigits[i])
|
||||
{
|
||||
case 0: i=o+5; break;
|
||||
case 1: i=o+0; break;
|
||||
case 2: i=o+6; break;
|
||||
case 3: i=o+1; break;
|
||||
case 4: i=o+7; break;
|
||||
case 5: i=o+2; break;
|
||||
case 6: i=o+8; break;
|
||||
case 7: i=o+3; break;
|
||||
case 8: i=o+9; break;
|
||||
case 9: i=o+4; break;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= _lengthRaw) return 0;
|
||||
RgbwColor lColor = bus->GetPixelColorRgbw(i);
|
||||
byte r = lColor.R, g = lColor.G, b = lColor.B;
|
||||
|
||||
RgbwColor col = bus->GetPixelColorRgbw(i);
|
||||
switch (colorOrder)
|
||||
{
|
||||
case 0: break; //0 = Grb
|
||||
case 1: r = lColor.G; g = lColor.R; break; //1 = Rgb, common for WS2811
|
||||
case 2: g = lColor.B; b = lColor.G; break; //2 = Brg
|
||||
case 3: r = lColor.B; g = lColor.R; b = lColor.G; //3 = Rbg
|
||||
// W G R B
|
||||
case 0: return ((col.W << 24) | (col.G << 8) | (col.R << 16) | (col.B)); //0 = GRB, default
|
||||
case 1: return ((col.W << 24) | (col.R << 8) | (col.G << 16) | (col.B)); //1 = RGB, common for WS2811
|
||||
case 2: return ((col.W << 24) | (col.B << 8) | (col.R << 16) | (col.G)); //2 = BRG
|
||||
case 3: return ((col.W << 24) | (col.B << 8) | (col.G << 16) | (col.R)); //3 = RBG
|
||||
case 4: return ((col.W << 24) | (col.R << 8) | (col.B << 16) | (col.G)); //4 = BGR
|
||||
case 5: return ((col.W << 24) | (col.G << 8) | (col.B << 16) | (col.R)); //5 = GBR
|
||||
}
|
||||
return ( (lColor.W << 24) | (r << 16) | (g << 8) | (b) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
WS2812FX::Segment& WS2812FX::getSegment(uint8_t id) {
|
||||
@ -423,31 +447,46 @@ WS2812FX::Segment* WS2812FX::getSegments(void) {
|
||||
return _segments;
|
||||
}
|
||||
|
||||
uint16_t WS2812FX::getUsableCount(void) {
|
||||
return _usableCount;
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::getLastShow(void) {
|
||||
return _lastShow;
|
||||
}
|
||||
|
||||
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2) {
|
||||
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing) {
|
||||
if (n >= MAX_NUM_SEGMENTS) return;
|
||||
Segment& seg = _segments[n];
|
||||
if (seg.start == i1 && seg.stop == i2) return;
|
||||
|
||||
_segment_index = n; fill(0); //turn old segment range off
|
||||
//return if neither bounds nor grouping have changed
|
||||
if (seg.start == i1 && seg.stop == i2 && (!grouping || (seg.grouping == grouping && seg.spacing == spacing))) return;
|
||||
|
||||
if (seg.stop) setRange(seg.start, seg.stop -1, 0); //turn old segment range off
|
||||
if (i2 <= i1) //disable segment
|
||||
{
|
||||
seg.stop = 0; return;
|
||||
seg.stop = 0;
|
||||
if (n == mainSegment) //if main segment is deleted, set first active as main segment
|
||||
{
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isActive()) {
|
||||
mainSegment = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
mainSegment = 0; //should not happen (always at least one active segment)
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (i1 < _length) seg.start = i1;
|
||||
seg.stop = i2;
|
||||
if (i2 > _length) seg.stop = _length;
|
||||
if (grouping) {
|
||||
seg.grouping = grouping;
|
||||
seg.spacing = spacing;
|
||||
}
|
||||
_segment_runtimes[n].reset();
|
||||
}
|
||||
|
||||
void WS2812FX::resetSegments() {
|
||||
mainSegment = 0;
|
||||
memset(_segments, 0, sizeof(_segments));
|
||||
//memset(_segment_runtimes, 0, sizeof(_segment_runtimes));
|
||||
_segment_index = 0;
|
||||
@ -456,10 +495,17 @@ void WS2812FX::resetSegments() {
|
||||
_segments[0].start = 0;
|
||||
_segments[0].speed = DEFAULT_SPEED;
|
||||
_segments[0].stop = _length;
|
||||
_segments[0].setOption(0, 1); //select
|
||||
_segments[0].grouping = 1;
|
||||
_segments[0].setOption(SEG_OPTION_SELECTED, 1);
|
||||
_segments[0].setOption(SEG_OPTION_ON, 1);
|
||||
_segments[0].opacity = 255;
|
||||
|
||||
for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
_segments[i].colors[0] = color_wheel(i*51);
|
||||
_segments[i].grouping = 1;
|
||||
_segments[i].setOption(SEG_OPTION_ON, 1);
|
||||
_segments[i].opacity = 255;
|
||||
_segment_runtimes[i].reset();
|
||||
}
|
||||
_segment_runtimes[0].reset();
|
||||
@ -484,7 +530,7 @@ void WS2812FX::setShowCallback(show_callback cb)
|
||||
void WS2812FX::setTransitionMode(bool t)
|
||||
{
|
||||
_segment_index = getMainSegmentId();
|
||||
SEGMENT.setOption(7,t);
|
||||
SEGMENT.setOption(SEG_OPTION_TRANSITIONAL, t);
|
||||
if (!t) return;
|
||||
unsigned long waitMax = millis() + 20; //refresh after 20 ms if transition enabled
|
||||
if (SEGMENT.mode == FX_MODE_STATIC && SEGENV.next_time > waitMax) SEGENV.next_time = waitMax;
|
||||
@ -519,7 +565,7 @@ uint32_t WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint8_t blend)
|
||||
* Fills segment with color
|
||||
*/
|
||||
void WS2812FX::fill(uint32_t c) {
|
||||
for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) {
|
||||
for(uint16_t i = 0; i < SEGLEN; i++) {
|
||||
setPixelColor(i, c);
|
||||
}
|
||||
}
|
||||
@ -537,7 +583,7 @@ void WS2812FX::fade_out(uint8_t rate) {
|
||||
int g2 = (color >> 8) & 0xff;
|
||||
int b2 = color & 0xff;
|
||||
|
||||
for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) {
|
||||
for(uint16_t i = 0; i < SEGLEN; i++) {
|
||||
color = getPixelColor(i);
|
||||
int w1 = (color >> 24) & 0xff;
|
||||
int r1 = (color >> 16) & 0xff;
|
||||
@ -567,14 +613,14 @@ void WS2812FX::blur(uint8_t blur_amount)
|
||||
uint8_t keep = 255 - blur_amount;
|
||||
uint8_t seep = blur_amount >> 1;
|
||||
CRGB carryover = CRGB::Black;
|
||||
for(uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++)
|
||||
for(uint16_t i = 0; i < SEGLEN; i++)
|
||||
{
|
||||
CRGB cur = col_to_crgb(getPixelColor(i));
|
||||
CRGB part = cur;
|
||||
part.nscale8(seep);
|
||||
cur.nscale8(keep);
|
||||
cur += carryover;
|
||||
if(i > SEGMENT.start) {
|
||||
if(i > 0) {
|
||||
uint32_t c = getPixelColor(i-1);
|
||||
uint8_t r = (c >> 16 & 0xFF);
|
||||
uint8_t g = (c >> 8 & 0xFF);
|
||||
@ -621,7 +667,7 @@ uint8_t WS2812FX::get_random_wheel_index(uint8_t pos) {
|
||||
r = random8();
|
||||
x = abs(pos - r);
|
||||
y = 255 - x;
|
||||
d = min(x, y);
|
||||
d = MIN(x, y);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@ -643,6 +689,15 @@ CRGB WS2812FX::col_to_crgb(uint32_t color)
|
||||
}
|
||||
|
||||
|
||||
void WS2812FX::load_gradient_palette(uint8_t index)
|
||||
{
|
||||
byte i = constrain(index, 0, GRADIENT_PALETTE_COUNT -1);
|
||||
byte tcp[72]; //support gradient palettes with up to 18 entries
|
||||
memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[i])), 72);
|
||||
targetPalette.loadDynamicGradientPalette(tcp);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FastLED palette modes helper function. Limitation: Due to memory reasons, multiple active segments with FastLED will disable the Palette transitions
|
||||
*/
|
||||
@ -660,13 +715,13 @@ void WS2812FX::handle_palette(void)
|
||||
case 0: {//default palette. Differs depending on effect
|
||||
switch (SEGMENT.mode)
|
||||
{
|
||||
case FX_MODE_FIRE_2012 : targetPalette = gGradientPalettes[22]; break;//heat palette
|
||||
case FX_MODE_COLORWAVES : targetPalette = gGradientPalettes[13]; break;//landscape 33
|
||||
case FX_MODE_FIRE_2012 : load_gradient_palette(22); break;//heat palette
|
||||
case FX_MODE_COLORWAVES : load_gradient_palette(13); break;//landscape 33
|
||||
case FX_MODE_FILLNOISE8 : targetPalette = OceanColors_p; break;
|
||||
case FX_MODE_NOISE16_1 : targetPalette = gGradientPalettes[17]; break;//Drywet
|
||||
case FX_MODE_NOISE16_2 : targetPalette = gGradientPalettes[30]; break;//Blue cyan yellow
|
||||
case FX_MODE_NOISE16_3 : targetPalette = gGradientPalettes[22]; break;//heat palette
|
||||
case FX_MODE_NOISE16_4 : targetPalette = gGradientPalettes[13]; break;//landscape 33
|
||||
case FX_MODE_NOISE16_1 : load_gradient_palette(17); break;//Drywet
|
||||
case FX_MODE_NOISE16_2 : load_gradient_palette(30); break;//Blue cyan yellow
|
||||
case FX_MODE_NOISE16_3 : load_gradient_palette(22); break;//heat palette
|
||||
case FX_MODE_NOISE16_4 : load_gradient_palette(13); break;//landscape 33
|
||||
//case FX_MODE_GLITTER : targetPalette = RainbowColors_p; break;
|
||||
|
||||
default: targetPalette = PartyColors_p; break;//palette, bpm
|
||||
@ -689,25 +744,25 @@ void WS2812FX::handle_palette(void)
|
||||
case 2: {//primary color only
|
||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
||||
targetPalette = CRGBPalette16(prim); break;}
|
||||
case 3: {//based on primary
|
||||
//considering performance implications
|
||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
||||
CHSV prim_hsv = rgb2hsv_approximate(prim);
|
||||
targetPalette = CRGBPalette16(
|
||||
CHSV(prim_hsv.h, prim_hsv.s, prim_hsv.v), //color itself
|
||||
CHSV(prim_hsv.h, max(prim_hsv.s - 50,0), prim_hsv.v), //less saturated
|
||||
CHSV(prim_hsv.h, prim_hsv.s, max(prim_hsv.v - 50,0)), //darker
|
||||
CHSV(prim_hsv.h, prim_hsv.s, prim_hsv.v)); //color itself
|
||||
break;}
|
||||
case 4: {//primary + secondary
|
||||
case 3: {//primary + secondary
|
||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
||||
CRGB sec = col_to_crgb(SEGCOLOR(1));
|
||||
targetPalette = CRGBPalette16(sec,prim); break;}
|
||||
case 5: {//based on primary + secondary
|
||||
targetPalette = CRGBPalette16(prim,prim,sec,sec); break;}
|
||||
case 4: {//primary + secondary + tertiary
|
||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
||||
CRGB sec = col_to_crgb(SEGCOLOR(1));
|
||||
CRGB ter = col_to_crgb(SEGCOLOR(2));
|
||||
targetPalette = CRGBPalette16(ter,sec,prim); break;}
|
||||
case 5: {//primary + secondary (+tert if not off), more distinct
|
||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
||||
CRGB sec = col_to_crgb(SEGCOLOR(1));
|
||||
if (SEGCOLOR(2)) {
|
||||
CRGB ter = col_to_crgb(SEGCOLOR(2));
|
||||
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,ter,ter,ter,ter,ter,prim);
|
||||
} else {
|
||||
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,sec,sec,sec);
|
||||
}
|
||||
break;}
|
||||
case 6: //Party colors
|
||||
targetPalette = PartyColors_p; break;
|
||||
case 7: //Cloud colors
|
||||
@ -723,7 +778,7 @@ void WS2812FX::handle_palette(void)
|
||||
case 12: //Rainbow stripe colors
|
||||
targetPalette = RainbowStripeColors_p; break;
|
||||
default: //progmem palettes
|
||||
targetPalette = gGradientPalettes[constrain(SEGMENT.palette -13, 0, gGradientPaletteCount -1)];
|
||||
load_gradient_palette(SEGMENT.palette -13);
|
||||
}
|
||||
|
||||
if (singleSegmentMode && paletteFade) //only blend if just one segment uses FastLED mode
|
||||
@ -739,7 +794,7 @@ uint32_t WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8
|
||||
{
|
||||
if (SEGMENT.palette == 0 && mcol < 3) return SEGCOLOR(mcol); //WS2812FX default
|
||||
uint8_t paletteIndex = i;
|
||||
if (mapping) paletteIndex = map(i,SEGMENT.start,SEGMENT.stop-1,0,255);
|
||||
if (mapping) paletteIndex = (i*255)/(SEGLEN -1);
|
||||
if (!wrap) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
|
||||
CRGB fastled_col;
|
||||
fastled_col = ColorFromPalette( currentPalette, paletteIndex, pbri, (paletteBlend == 3)? NOBLEND:LINEARBLEND);
|
||||
@ -758,10 +813,46 @@ bool WS2812FX::segmentsAreIdentical(Segment* a, Segment* b)
|
||||
if (a->speed != b->speed) return false;
|
||||
if (a->intensity != b->intensity) return false;
|
||||
if (a->palette != b->palette) return false;
|
||||
//if (a->getOption(1) != b->getOption(1)) return false; //reverse
|
||||
//if (a->getOption(SEG_OPTION_REVERSED) != b->getOption(SEG_OPTION_REVERSED)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
void WS2812FX::setRgbwPwm(void) {
|
||||
uint32_t nowUp = millis(); // Be aware, millis() rolls over every 49 days
|
||||
if (nowUp - _analogLastShow < MIN_SHOW_DELAY) return;
|
||||
|
||||
_analogLastShow = nowUp;
|
||||
|
||||
RgbwColor color = bus->GetPixelColorRgbw(0);
|
||||
byte b = getBrightness();
|
||||
if (color == _analogLastColor && b == _analogLastBri) return;
|
||||
|
||||
// check color values for Warm / Cold white mix (for RGBW) // EsplanexaDevice.cpp
|
||||
#ifdef WLED_USE_5CH_LEDS
|
||||
if (color.R == 255 && color.G == 255 && color.B == 255 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, 0, color.W * b / 255);
|
||||
} else if (color.R == 127 && color.G == 127 && color.B == 127 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, color.W * b / 512, color.W * b / 255);
|
||||
} else if (color.R == 0 && color.G == 0 && color.B == 0 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
|
||||
} else if (color.R == 130 && color.G == 90 && color.B == 0 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, color.W * b / 255, color.W * b / 512);
|
||||
} else if (color.R == 255 && color.G == 153 && color.B == 0 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
|
||||
} else { // not only white colors
|
||||
bus->SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);
|
||||
}
|
||||
#else
|
||||
bus->SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);
|
||||
#endif
|
||||
_analogLastColor = color;
|
||||
_analogLastBri = b;
|
||||
}
|
||||
#else
|
||||
void WS2812FX::setRgbwPwm() {}
|
||||
#endif
|
||||
|
||||
//gamma 2.4 lookup table used for color correction
|
||||
const byte gammaT[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
@ -3,24 +3,43 @@
|
||||
#define NpbWrapper_h
|
||||
|
||||
//PIN CONFIGURATION
|
||||
#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 or 3 is recommended for ESP8266 (gpio2/3 are labeled D4/RX on NodeMCU and Wemos)
|
||||
#ifndef LEDPIN
|
||||
#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 or 3 is recommended for ESP8266 (gpio2/3 are labeled D4/RX on NodeMCU and Wemos)
|
||||
#endif
|
||||
//#define USE_APA102 // Uncomment for using APA102 LEDs.
|
||||
//#define USE_WS2801 // Uncomment for using WS2801 LEDs (make sure you have NeoPixelBus v2.5.6 or newer)
|
||||
//#define USE_LPD8806 // Uncomment for using LPD8806
|
||||
//#define USE_TM1814 // Uncomment for using TM1814 LEDs (make sure you have NeoPixelBus v2.5.7 or newer)
|
||||
//#define USE_P9813 // Uncomment for using P9813 LEDs (make sure you have NeoPixelBus v2.5.8 or newer)
|
||||
//#define WLED_USE_ANALOG_LEDS //Uncomment for using "dumb" PWM controlled LEDs (see pins below, default R: gpio5, G: 12, B: 15, W: 13)
|
||||
//#define WLED_USE_H801 //H801 controller. Please uncomment #define WLED_USE_ANALOG_LEDS as well
|
||||
//#define WLED_USE_5CH //5 Channel H801 for cold and warm white
|
||||
//#define WLED_USE_5CH_LEDS //5 Channel H801 for cold and warm white
|
||||
//#define WLED_USE_BWLT11
|
||||
//#define WLED_USE_SHOJO_PCB
|
||||
|
||||
#ifndef BTNPIN
|
||||
#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended)
|
||||
#define IR_PIN 4 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
|
||||
#define RLYPIN 12 //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,...
|
||||
#define AUXPIN -1 //debug auxiliary output pin (-1 to disable)
|
||||
#endif
|
||||
|
||||
#define RLYMDE 1 //mode for relay, 0: LOW if LEDs are on 1: HIGH if LEDs are on
|
||||
#ifndef IR_PIN
|
||||
#define IR_PIN 4 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
|
||||
#endif
|
||||
|
||||
#ifndef RLYPIN
|
||||
#define RLYPIN 12 //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,...
|
||||
#endif
|
||||
|
||||
#ifndef AUXPIN
|
||||
#define AUXPIN -1 //debug auxiliary output pin (-1 to disable)
|
||||
#endif
|
||||
|
||||
#ifndef RLYMDE
|
||||
#define RLYMDE 1 //mode for relay, 0: LOW if LEDs are on 1: HIGH if LEDs are on
|
||||
#endif
|
||||
|
||||
//END CONFIGURATION
|
||||
|
||||
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806)
|
||||
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) || defined(USE_P9813)
|
||||
#define CLKPIN 0
|
||||
#define DATAPIN 2
|
||||
#if BTNPIN == CLKPIN || BTNPIN == DATAPIN
|
||||
@ -34,17 +53,30 @@
|
||||
#define RPIN 15 //R pin for analog LED strip
|
||||
#define GPIN 13 //G pin for analog LED strip
|
||||
#define BPIN 12 //B pin for analog LED strip
|
||||
#define WPIN 14 //W pin for analog LED strip (W1: 14, W2: 04)
|
||||
#define WPIN 14 //W pin for analog LED strip
|
||||
#define W2PIN 04 //W2 pin for analog LED strip
|
||||
#undef BTNPIN
|
||||
#undef IR_PIN
|
||||
#define IR_PIN 0 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
|
||||
#elif defined(WLED_USE_BWLT11)
|
||||
//PWM pins - to use with BW-LT11
|
||||
#define RPIN 12 //R pin for analog LED strip
|
||||
#define GPIN 4 //G pin for analog LED strip
|
||||
#define BPIN 14 //B pin for analog LED strip
|
||||
#define WPIN 5 //W pin for analog LED strip
|
||||
#elif defined(WLED_USE_SHOJO_PCB)
|
||||
//PWM pins - to use with Shojo PCB (https://www.bastelbunker.de/esp-rgbww-wifi-led-controller-vbs-edition/)
|
||||
#define RPIN 14 //R pin for analog LED strip
|
||||
#define GPIN 4 //G pin for analog LED strip
|
||||
#define BPIN 5 //B pin for analog LED strip
|
||||
#define WPIN 15 //W pin for analog LED strip
|
||||
#define W2PIN 12 //W2 pin for analog LED strip
|
||||
#else
|
||||
//PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller
|
||||
#define RPIN 5 //R pin for analog LED strip
|
||||
#define GPIN 12 //G pin for analog LED strip
|
||||
#define BPIN 15 //B pin for analog LED strip
|
||||
#define WPIN 13 //W pin for analog LED strip (W1: 14, W2: 04)
|
||||
#define GPIN 12 //G pin for analog LED strip
|
||||
#define BPIN 15 //B pin for analog LED strip
|
||||
#define WPIN 13 //W pin for analog LED strip
|
||||
#endif
|
||||
#undef RLYPIN
|
||||
#define RLYPIN -1 //disable as pin 12 is used by analog LEDs
|
||||
@ -58,6 +90,10 @@
|
||||
#define PIXELMETHOD NeoWs2801Method
|
||||
#elif defined(USE_LPD8806)
|
||||
#define PIXELMETHOD Lpd8806Method
|
||||
#elif defined(USE_TM1814)
|
||||
#define PIXELMETHOD NeoTm1814Method
|
||||
#elif defined(USE_P9813)
|
||||
#define PIXELMETHOD P9813Method
|
||||
#else
|
||||
#define PIXELMETHOD NeoEsp32Rmt0Ws2812xMethod
|
||||
#endif
|
||||
@ -69,6 +105,10 @@
|
||||
#define PIXELMETHOD NeoWs2801Method
|
||||
#elif defined(USE_LPD8806)
|
||||
#define PIXELMETHOD Lpd8806Method
|
||||
#elif defined(USE_TM1814)
|
||||
#define PIXELMETHOD NeoTm1814Method
|
||||
#elif defined(USE_P9813)
|
||||
#define PIXELMETHOD P9813Method
|
||||
#elif LEDPIN == 2
|
||||
#define PIXELMETHOD NeoEsp8266Uart1Ws2813Method //if you get an error here, try to change to NeoEsp8266UartWs2813Method or update Neopixelbus
|
||||
#elif LEDPIN == 3
|
||||
@ -86,10 +126,15 @@
|
||||
#define PIXELFEATURE4 DotStarLbgrFeature
|
||||
#elif defined(USE_LPD8806)
|
||||
#define PIXELFEATURE3 Lpd8806GrbFeature
|
||||
#define PIXELFEATURE4 Lpd8806GrbFeature
|
||||
#elif defined(USE_WS2801)
|
||||
#define PIXELFEATURE3 NeoRbgFeature
|
||||
#define PIXELFEATURE4 NeoRbgFeature
|
||||
#elif defined(USE_TM1814)
|
||||
#define PIXELFEATURE3 NeoWrgbTm1814Feature
|
||||
#define PIXELFEATURE4 NeoWrgbTm1814Feature
|
||||
#elif defined(USE_P9813)
|
||||
#define PIXELFEATURE3 P9813BgrFeature
|
||||
#define PIXELFEATURE4 NeoGrbwFeature
|
||||
#else
|
||||
#define PIXELFEATURE3 NeoGrbFeature
|
||||
#define PIXELFEATURE4 NeoGrbwFeature
|
||||
@ -131,7 +176,7 @@ public:
|
||||
switch (_type)
|
||||
{
|
||||
case NeoPixelType_Grb:
|
||||
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806)
|
||||
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) || defined(USE_P9813)
|
||||
_pGrb = new NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>(countPixels, CLKPIN, DATAPIN);
|
||||
#else
|
||||
_pGrb = new NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>(countPixels, LEDPIN);
|
||||
@ -140,7 +185,7 @@ public:
|
||||
break;
|
||||
|
||||
case NeoPixelType_Grbw:
|
||||
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806)
|
||||
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) || defined(USE_P9813)
|
||||
_pGrbw = new NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>(countPixels, CLKPIN, DATAPIN);
|
||||
#else
|
||||
_pGrbw = new NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>(countPixels, LEDPIN);
|
||||
@ -167,7 +212,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
#else // ESP8266
|
||||
//init PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller
|
||||
//init PWM pins
|
||||
pinMode(RPIN, OUTPUT);
|
||||
pinMode(GPIN, OUTPUT);
|
||||
pinMode(BPIN, OUTPUT);
|
||||
@ -188,9 +233,9 @@ public:
|
||||
void SetRgbwPwm(uint8_t r, uint8_t g, uint8_t b, uint8_t w, uint8_t w2=0)
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
ledcWrite(0, r); //RPIN
|
||||
ledcWrite(1, g); //GPIN
|
||||
ledcWrite(2, b); //BPIN
|
||||
ledcWrite(0, r);
|
||||
ledcWrite(1, g);
|
||||
ledcWrite(2, b);
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: break;
|
||||
#ifdef WLED_USE_5CH_LEDS
|
||||
@ -199,7 +244,7 @@ public:
|
||||
case NeoPixelType_Grbw: ledcWrite(3, w); break;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#else // ESP8266
|
||||
analogWrite(RPIN, r);
|
||||
analogWrite(GPIN, g);
|
||||
analogWrite(BPIN, b);
|
||||
@ -230,11 +275,6 @@ public:
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: {
|
||||
_pGrb->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B));
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
if (indexPixel != 0) return; //set analog LEDs from first pixel
|
||||
byte b = _pGrb->GetBrightness();
|
||||
SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, 0);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case NeoPixelType_Grbw: {
|
||||
@ -243,28 +283,6 @@ public:
|
||||
#else
|
||||
_pGrbw->SetPixelColor(indexPixel, color);
|
||||
#endif
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
if (indexPixel != 0) return; //set analog LEDs from first pixel
|
||||
byte b = _pGrbw->GetBrightness();
|
||||
// check color values for Warm / Cold white mix (for RGBW) // EsplanexaDevice.cpp
|
||||
#ifdef WLED_USE_5CH_LEDS
|
||||
if (color.R == 255 & color.G == 255 && color.B == 255 && color.W == 255) {
|
||||
SetRgbwPwm(0, 0, 0, 0, color.W * b / 255);
|
||||
} else if (color.R == 127 & color.G == 127 && color.B == 127 && color.W == 255) {
|
||||
SetRgbwPwm(0, 0, 0, color.W * b / 512, colorW.W * b / 255);
|
||||
} else if (color.R == 0 & color.G == 0 && color.B == 0 && color.W == 255) {
|
||||
SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
|
||||
} else if (color.R == 130 & color.G == 90 && color.B == 0 && color.W == 255) {
|
||||
SetRgbwPwm(0, 0, 0, color.W * b / 255, color.W * b / 512);
|
||||
} else if (color.R == 255 & color.G == 153 && color.B == 0 && color.W == 255) {
|
||||
SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
|
||||
} else { // not only white colors
|
||||
SetRgbwPwm(color.R * b / 255, colorW.G * b / 255, colorW.B * b / 255, color.W * b / 255);
|
||||
}
|
||||
#else
|
||||
SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -290,6 +308,15 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t* GetPixels(void)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: return _pGrb->Pixels(); break;
|
||||
case NeoPixelType_Grbw: return _pGrbw->Pixels(); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
NeoPixelType _type;
|
||||
|
@ -17,8 +17,10 @@
|
||||
#define __ESP32_ESP32__
|
||||
#define ESP_PLATFORM
|
||||
#define HAVE_CONFIG_H
|
||||
#define GCC_NOT_5_2_0 0
|
||||
#define WITH_POSIX
|
||||
#define F_CPU 240000000L
|
||||
#define ARDUINO 10809
|
||||
#define ARDUINO 108011
|
||||
#define ARDUINO_ESP32_DEV
|
||||
#define ARDUINO_ARCH_ESP32
|
||||
#define ESP32
|
||||
@ -92,18 +94,11 @@ typedef long pthread_cond_t;
|
||||
#include "arduino.h"
|
||||
#include <pins_arduino.h>
|
||||
|
||||
//#include "..\generic\Common.h"
|
||||
//#include "..\generic\pins_arduino.h"
|
||||
|
||||
//#undef F
|
||||
//#define F(string_literal) ((const PROGMEM char *)(string_literal))
|
||||
//#undef PSTR
|
||||
//#define PSTR(string_literal) ((const PROGMEM char *)(string_literal))
|
||||
//current vc++ does not understand this syntax so use older arduino example for intellisense
|
||||
//todo:move to the new clang/gcc project types.
|
||||
#define interrupts() sei()
|
||||
#define noInterrupts() cli()
|
||||
|
||||
#define ESP_LOGI(tag, ...)
|
||||
|
||||
#include "wled00.ino"
|
||||
#include "wled01_eeprom.ino"
|
||||
#include "wled02_xml.ino"
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,10 +1,13 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Alexa Voice On/Off/Brightness Control. Emulates a Philips Hue bridge to Alexa.
|
||||
* Alexa Voice On/Off/Brightness/Color Control. Emulates a Philips Hue bridge to Alexa.
|
||||
*
|
||||
* This was put together from these two excellent projects:
|
||||
* https://github.com/kakopappa/arduino-esp8266-alexa-wemo-switch
|
||||
* https://github.com/probonopd/ESP8266HueEmulator
|
||||
*/
|
||||
#include "src/dependencies/espalexa/EspalexaDevice.h"
|
||||
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
void onAlexaChange(EspalexaDevice* dev);
|
||||
@ -41,7 +44,7 @@ void onAlexaChange(EspalexaDevice* dev)
|
||||
if (bri == 0)
|
||||
{
|
||||
bri = briLast;
|
||||
colorUpdated(10);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||
}
|
||||
} else applyMacro(macroAlexaOn);
|
||||
} else if (m == EspalexaDeviceProperty::off)
|
||||
@ -52,22 +55,38 @@ void onAlexaChange(EspalexaDevice* dev)
|
||||
{
|
||||
briLast = bri;
|
||||
bri = 0;
|
||||
colorUpdated(10);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||
}
|
||||
} else applyMacro(macroAlexaOff);
|
||||
} else if (m == EspalexaDeviceProperty::bri)
|
||||
{
|
||||
bri = espalexaDevice->getValue();
|
||||
colorUpdated(10);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||
} else //color
|
||||
{
|
||||
uint32_t color = espalexaDevice->getRGB();
|
||||
col[3] = ((color >> 24) & 0xFF); // white color from Alexa is "pure white only"
|
||||
col[0] = ((color >> 16) & 0xFF);
|
||||
col[1] = ((color >> 8) & 0xFF);
|
||||
col[2] = (color & 0xFF);
|
||||
if (useRGBW && col[3] == 0) colorRGBtoRGBW(col); // do not touch white value if EspalexaDevice.cpp did set the white channel
|
||||
colorUpdated(10);
|
||||
if (espalexaDevice->getColorMode() == EspalexaColorMode::ct) //shade of white
|
||||
{
|
||||
uint16_t ct = espalexaDevice->getCt();
|
||||
if (useRGBW)
|
||||
{
|
||||
switch (ct) { //these values empirically look good on RGBW
|
||||
case 199: col[0]=255; col[1]=255; col[2]=255; col[3]=255; break;
|
||||
case 234: col[0]=127; col[1]=127; col[2]=127; col[3]=255; break;
|
||||
case 284: col[0]= 0; col[1]= 0; col[2]= 0; col[3]=255; break;
|
||||
case 350: col[0]=130; col[1]= 90; col[2]= 0; col[3]=255; break;
|
||||
case 383: col[0]=255; col[1]=153; col[2]= 0; col[3]=255; break;
|
||||
}
|
||||
} else {
|
||||
colorCTtoRGB(ct, col);
|
||||
}
|
||||
} else {
|
||||
uint32_t color = espalexaDevice->getRGB();
|
||||
|
||||
col[0] = ((color >> 16) & 0xFF);
|
||||
col[1] = ((color >> 8) & 0xFF);
|
||||
col[2] = ( color & 0xFF);
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
#include "wled.h"
|
||||
#include "src/dependencies/blynk/Blynk/BlynkHandlers.h"
|
||||
|
||||
/*
|
||||
* Remote light control with the free Blynk app
|
||||
*/
|
||||
@ -41,45 +44,45 @@ void updateBlynk()
|
||||
BLYNK_WRITE(V0)
|
||||
{
|
||||
bri = param.asInt();//bri
|
||||
colorUpdated(9);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V1)
|
||||
{
|
||||
blHue = param.asInt();//hue
|
||||
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
|
||||
colorUpdated(9);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V2)
|
||||
{
|
||||
blSat = param.asInt();//sat
|
||||
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
|
||||
colorUpdated(9);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V3)
|
||||
{
|
||||
bool on = (param.asInt()>0);
|
||||
if (!on != !bri) {toggleOnOff(); colorUpdated(9);}
|
||||
if (!on != !bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BLYNK);}
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V4)
|
||||
{
|
||||
effectCurrent = param.asInt()-1;//fx
|
||||
colorUpdated(9);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V5)
|
||||
{
|
||||
effectSpeed = param.asInt();//sx
|
||||
colorUpdated(9);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V6)
|
||||
{
|
||||
effectIntensity = param.asInt();//ix
|
||||
colorUpdated(9);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V7)
|
@ -1,3 +1,5 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Physical IO
|
||||
*/
|
||||
@ -7,7 +9,7 @@ void shortPressAction()
|
||||
if (!macroButton)
|
||||
{
|
||||
toggleOnOff();
|
||||
colorUpdated(2);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
} else {
|
||||
applyMacro(macroButton);
|
||||
}
|
||||
@ -44,7 +46,7 @@ void handleButton()
|
||||
|
||||
if (dur > 6000) //long press
|
||||
{
|
||||
initAP(true);
|
||||
WLED::instance().initAP(true);
|
||||
}
|
||||
else if (!buttonLongPressed) { //short press
|
||||
if (macroDoublePress)
|
@ -1,3 +1,5 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Color conversion methods
|
||||
*/
|
||||
@ -18,7 +20,7 @@ void colorFromUint32(uint32_t in, bool secondary)
|
||||
}
|
||||
|
||||
//load a color without affecting the white channel
|
||||
void colorFromUint24(uint32_t in, bool secondary = false)
|
||||
void colorFromUint24(uint32_t in, bool secondary)
|
||||
{
|
||||
if (secondary) {
|
||||
colSec[0] = in >> 16 & 0xFF;
|
||||
@ -32,7 +34,7 @@ void colorFromUint24(uint32_t in, bool secondary = false)
|
||||
}
|
||||
|
||||
//relatively change white brightness, minumum A=5
|
||||
void relativeChangeWhite(int8_t amount, byte lowerBoundary =0)
|
||||
void relativeChangeWhite(int8_t amount, byte lowerBoundary)
|
||||
{
|
||||
int16_t new_val = (int16_t) col[3] + amount;
|
||||
if (new_val > 0xFF) new_val = 0xFF;
|
||||
@ -57,10 +59,9 @@ void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb
|
||||
case 4: rgb[0]=t,rgb[1]=p,rgb[2]=255;break;
|
||||
case 5: rgb[0]=255,rgb[1]=p,rgb[2]=q;
|
||||
}
|
||||
if (useRGBW) colorRGBtoRGBW(col);
|
||||
if (useRGBW && strip.rgbwMode == RGBW_MODE_LEGACY) colorRGBtoRGBW(col);
|
||||
}
|
||||
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
void colorCTtoRGB(uint16_t mired, byte* rgb) //white spectrum to rgb
|
||||
{
|
||||
//this is only an approximation using WS2812B with gamma correction enabled
|
||||
@ -81,9 +82,10 @@ void colorCTtoRGB(uint16_t mired, byte* rgb) //white spectrum to rgb
|
||||
} else {
|
||||
rgb[0]=237;rgb[1]=255;rgb[2]=239;//150
|
||||
}
|
||||
if (useRGBW) colorRGBtoRGBW(col);
|
||||
if (useRGBW && strip.rgbwMode == RGBW_MODE_LEGACY) colorRGBtoRGBW(col);
|
||||
}
|
||||
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
void colorXYtoRGB(float x, float y, byte* rgb) //coordinates to rgb (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
|
||||
{
|
||||
float z = 1.0f - x - y;
|
||||
@ -149,7 +151,8 @@ void colorRGBtoXY(byte* rgb, float* xy) //rgb to coordinates (https://www.develo
|
||||
xy[0] = X / (X + Y + Z);
|
||||
xy[1] = Y / (X + Y + Z);
|
||||
}
|
||||
#endif
|
||||
#endif // WLED_DISABLE_HUESYNC
|
||||
|
||||
|
||||
void colorFromDecOrHexString(byte* rgb, char* in)
|
||||
{
|
||||
@ -183,7 +186,7 @@ float maxf (float v, float w)
|
||||
return v;
|
||||
}
|
||||
|
||||
void colorRGBtoRGBW(byte* rgb) //rgb to rgbw (http://codewelt.com/rgbw)
|
||||
void colorRGBtoRGBW(byte* rgb) //rgb to rgbw (http://codewelt.com/rgbw). (RGBW_MODE_LEGACY)
|
||||
{
|
||||
float low = minf(rgb[0],minf(rgb[1],rgb[2]));
|
||||
float high = maxf(rgb[0],maxf(rgb[1],rgb[2]));
|
109
wled00/const.h
Normal file
109
wled00/const.h
Normal file
@ -0,0 +1,109 @@
|
||||
#ifndef WLED_CONST_H
|
||||
#define WLED_CONST_H
|
||||
|
||||
/*
|
||||
* Readability defines and their associated numerical values + compile-time constants
|
||||
*/
|
||||
|
||||
//Defaults
|
||||
#define DEFAULT_CLIENT_SSID "Your_Network"
|
||||
#define DEFAULT_AP_PASS "wled1234"
|
||||
#define DEFAULT_OTA_PASS "wledota"
|
||||
|
||||
//Access point behavior
|
||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||
#define AP_BEHAVIOR_NO_CONN 1 //Open when no connection (either after boot or if connection is lost)
|
||||
#define AP_BEHAVIOR_ALWAYS 2 //Always open
|
||||
#define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec
|
||||
|
||||
//Notifier callMode
|
||||
#define NOTIFIER_CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
|
||||
#define NOTIFIER_CALL_MODE_DIRECT_CHANGE 1
|
||||
#define NOTIFIER_CALL_MODE_BUTTON 2
|
||||
#define NOTIFIER_CALL_MODE_NOTIFICATION 3
|
||||
#define NOTIFIER_CALL_MODE_NIGHTLIGHT 4
|
||||
#define NOTIFIER_CALL_MODE_NO_NOTIFY 5
|
||||
#define NOTIFIER_CALL_MODE_FX_CHANGED 6 //no longer used
|
||||
#define NOTIFIER_CALL_MODE_HUE 7
|
||||
#define NOTIFIER_CALL_MODE_PRESET_CYCLE 8
|
||||
#define NOTIFIER_CALL_MODE_BLYNK 9
|
||||
#define NOTIFIER_CALL_MODE_ALEXA 10
|
||||
|
||||
//RGB to RGBW conversion mode
|
||||
#define RGBW_MODE_MANUAL_ONLY 0 //No automatic white channel calculation. Manual white channel slider
|
||||
#define RGBW_MODE_AUTO_BRIGHTER 1 //New algorithm. Adds as much white as the darkest RGBW channel
|
||||
#define RGBW_MODE_AUTO_ACCURATE 2 //New algorithm. Adds as much white as the darkest RGBW channel and subtracts this amount from each RGB channel
|
||||
#define RGBW_MODE_DUAL 3 //Manual slider + auto calculation. Automatically calculates only if manual slider is set to off (0)
|
||||
#define RGBW_MODE_LEGACY 4 //Old floating algorithm. Too slow for realtime and palette support
|
||||
|
||||
//realtime modes
|
||||
#define REALTIME_MODE_INACTIVE 0
|
||||
#define REALTIME_MODE_GENERIC 1
|
||||
#define REALTIME_MODE_UDP 2
|
||||
#define REALTIME_MODE_HYPERION 3
|
||||
#define REALTIME_MODE_E131 4
|
||||
#define REALTIME_MODE_ADALIGHT 5
|
||||
#define REALTIME_MODE_ARTNET 6
|
||||
|
||||
//realtime override modes
|
||||
#define REALTIME_OVERRIDE_NONE 0
|
||||
#define REALTIME_OVERRIDE_ONCE 1
|
||||
#define REALTIME_OVERRIDE_ALWAYS 2
|
||||
|
||||
//E1.31 DMX modes
|
||||
#define DMX_MODE_DISABLED 0 //not used
|
||||
#define DMX_MODE_SINGLE_RGB 1 //all LEDs same RGB color (3 channels)
|
||||
#define DMX_MODE_SINGLE_DRGB 2 //all LEDs same RGB color and master dimmer (4 channels)
|
||||
#define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (11 channels)
|
||||
#define DMX_MODE_MULTIPLE_RGB 4 //every LED is addressed with its own RGB (ledCount * 3 channels)
|
||||
#define DMX_MODE_MULTIPLE_DRGB 5 //every LED is addressed with its own RGB and share a master dimmer (ledCount * 3 + 1 channels)
|
||||
|
||||
//Light capability byte (unused)
|
||||
#define TYPE_NONE 0 //light is not configured
|
||||
#define TYPE_RESERVED 1 //unused. Might indicate a "virtual" light
|
||||
#define TYPE_WS2812_RGB 2
|
||||
#define TYPE_SK6812_RGBW 3
|
||||
#define TYPE_WS2812_WWA 4 //amber + warm + cold white
|
||||
#define TYPE_WS2801 5
|
||||
#define TYPE_ANALOG_1CH 6 //single channel PWM. Uses value of brightest RGBW channel
|
||||
#define TYPE_ANALOG_2CH 7 //analog WW + CW
|
||||
#define TYPE_ANALOG_3CH 8 //analog RGB
|
||||
#define TYPE_ANALOG_4CH 9 //analog RGBW
|
||||
#define TYPE_ANALOG_5CH 10 //analog RGB + WW + CW
|
||||
#define TYPE_APA102 11
|
||||
#define TYPE_LPD8806 12
|
||||
|
||||
//Hue error codes
|
||||
#define HUE_ERROR_INACTIVE 0
|
||||
#define HUE_ERROR_UNAUTHORIZED 1
|
||||
#define HUE_ERROR_LIGHTID 3
|
||||
#define HUE_ERROR_PUSHLINK 101
|
||||
#define HUE_ERROR_JSON_PARSING 250
|
||||
#define HUE_ERROR_TIMEOUT 251
|
||||
#define HUE_ERROR_ACTIVE 255
|
||||
|
||||
//Segment option byte bits
|
||||
#define SEG_OPTION_SELECTED 0
|
||||
#define SEG_OPTION_REVERSED 1
|
||||
#define SEG_OPTION_ON 2
|
||||
#define SEG_OPTION_PAUSED 3 //unused
|
||||
#define SEG_OPTION_NONUNITY 4 //Indicates that the effect does not use FRAMETIME or needs getPixelColor
|
||||
#define SEG_OPTION_TRANSITIONAL 7
|
||||
|
||||
//EEPROM size
|
||||
#define EEPSIZE 2560 //Maximum is 4096
|
||||
|
||||
#define NTP_PACKET_SIZE 48
|
||||
|
||||
// maximum number of LEDs - MAX_LEDS is coming from the JSON response getting too big, MAX_LEDS_DMA will become a timing issue
|
||||
#define MAX_LEDS 1500
|
||||
#define MAX_LEDS_DMA 500
|
||||
|
||||
// string temp buffer (now stored in stack locally)
|
||||
#define OMAX 2048
|
||||
|
||||
#define E131_MAX_UNIVERSE_COUNT 9
|
||||
|
||||
#define ABL_MILLIAMPS_DEFAULT 850; // auto lower brightness to stay close to milliampere limit
|
||||
|
||||
#endif
|
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -88,12 +88,12 @@
|
||||
<button type="button" onclick="U()">Manual OTA Update</button><br>
|
||||
Enable ArduinoOTA: <input type="checkbox" name="AO"><br>
|
||||
<h3>About</h3>
|
||||
<a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.9.0<br><br>
|
||||
<a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.10.0<br><br>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki/Contributors-&-About" target="_blank">Contributors, dependencies and special thanks</a><br>
|
||||
A huge thank you to everyone who helped me create WLED!<br><br>
|
||||
(c) 2016-2019 Christian Schwinne <br>
|
||||
<i>Licensed under the MIT license</i><br><br>
|
||||
Server message: <span class="msg"> Response error! </span><hr>
|
||||
Server message: <span class="sip"> Response error! </span><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save & Reboot</button>
|
||||
</form>
|
||||
</body>
|
||||
|
@ -1,132 +1,105 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=500">
|
||||
<title>Sync Settings</title>
|
||||
<script>
|
||||
function H()
|
||||
{
|
||||
window.open("https://github.com/Aircoookie/WLED/wiki/Settings#sync-settings");
|
||||
}
|
||||
function B()
|
||||
{
|
||||
window.open("/settings","_self");
|
||||
}
|
||||
function GetV()
|
||||
{
|
||||
//values injected by server while sending HTML
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
:root {
|
||||
--aCol: #abc;
|
||||
--bCol: #fff;
|
||||
--cCol: #ddd;
|
||||
--dCol: #000;
|
||||
--sCol: #0004;
|
||||
}
|
||||
body {
|
||||
font-family: Verdana, Helvetica, sans-serif;
|
||||
text-align: center;
|
||||
background: var(--cCol);
|
||||
color: var(--dCol);
|
||||
line-height: 200%;
|
||||
margin: 0;
|
||||
background-attachment: fixed;
|
||||
}
|
||||
hr {
|
||||
border-color: var(--dCol);
|
||||
filter: drop-shadow( -5px -5px 5px var(--sCol) );
|
||||
}
|
||||
button {
|
||||
background: var(--bCol);
|
||||
color: var(--dCol);
|
||||
border: 0.3ch solid var(--bCol);
|
||||
display: inline-block;
|
||||
filter: drop-shadow( -5px -5px 5px var(--sCol) );
|
||||
font-size: 20px;
|
||||
margin: 8px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.helpB {
|
||||
text-align: left;
|
||||
position: absolute;
|
||||
width:60px;
|
||||
}
|
||||
input {
|
||||
background: var(--bCol);
|
||||
color: var(--dCol);
|
||||
border: 0.5ch solid var(--bCol);
|
||||
filter: drop-shadow( -5px -5px 5px var(--sCol) );
|
||||
}
|
||||
input[type=number] {
|
||||
width: 3em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="GetV()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
<h2>Sync setup</h2>
|
||||
<h3>Button setup</h3>
|
||||
On/Off button enabled: <input type="checkbox" name="BT"><br>
|
||||
Infrared receiver enabled: <input type="checkbox" name="IR"><br>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a>
|
||||
<h3>WLED Sync UDP Broadcast</h3>
|
||||
UDP Port: <input name="UP" type="number" min="1" max="65535" required><br>
|
||||
Receive <input type="checkbox" name="RB">Brightness, <input type="checkbox" name="RC">Color, and <input type="checkbox" name="RX">Effects<br>
|
||||
Send notifications on direct change: <input type="checkbox" name="SD"><br>
|
||||
Send notifications on button press: <input type="checkbox" name="SB"><br>
|
||||
Send Alexa notifications: <input type="checkbox" name="SA"><br>
|
||||
Send Philips Hue change notifications: <input type="checkbox" name="SH"><br>
|
||||
Send Macro notifications: <input type="checkbox" name="SM"><br>
|
||||
Send notifications twice: <input type="checkbox" name="S2">
|
||||
<h3>Realtime</h3>
|
||||
Receive UDP realtime: <input type="checkbox" name="RD"><br><br>
|
||||
E1.31 (sACN)<br>
|
||||
Multicast mode: <input type="checkbox" name="EM"><br>
|
||||
E1.31 start universe: <input name="EU" type="number" min="1" max="63999" required><br>
|
||||
<i>Reboot required.</i> Check out <a href="https://github.com/ahodges9/LedFx" target="_blank">LedFx</a>!<br><br>
|
||||
Timeout: <input name="ET" type="number" min="100" max="65000" required> ms<br>
|
||||
Force max brightness: <input type="checkbox" name="FB"><br>
|
||||
Disable realtime gamma correction: <input type="checkbox" name="RG"><br>
|
||||
Realtime LED offset: <input name="WO" type="number" min="-255" max="255" required>
|
||||
<h3>Alexa Voice Assistant</h3>
|
||||
Emulate Alexa device: <input type="checkbox" name="AL"><br>
|
||||
Alexa invocation name: <input name="AI" maxlength="32">
|
||||
<h3>Blynk</h3>
|
||||
<b>Blynk, MQTT and Hue sync all connect to external hosts!<br>
|
||||
This may impact the responsiveness of the ESP8266.</b><br>
|
||||
For best results, only use one of these services at a time.<br>
|
||||
(alternatively, connect a second ESP to them and use the UDP sync)<br><br>
|
||||
Device Auth token: <input name="BK" maxlength="33"><br>
|
||||
<i>Clear the token field to disable. </i><a href="https://github.com/Aircoookie/WLED/wiki/Blynk" target="_blank">Setup info</a>
|
||||
<h3>MQTT</h3>
|
||||
Enable MQTT: <input type="checkbox" name="MQ"><br>
|
||||
Broker: <input name="MS" maxlength="32"><br>
|
||||
Username: <input name="MQTTUSER" maxlength="32"><br>
|
||||
Password: <input type="password" input name="MQTTPASS" maxlength="32"><br>
|
||||
Client ID: <input name="MQTTCID" maxlength="32"><br>
|
||||
Device Topic: <input name="MD" maxlength="32"><br>
|
||||
Group Topic: <input name="MG" maxlength="32"><br>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki/MQTT" target="_blank">MQTT info</a>
|
||||
<h3>Philips Hue</h3>
|
||||
<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
|
||||
Poll Hue light <input name="HL" type="number" min="1" max="99" required> every <input name="HI" type="number" min="100" max="65000" required> ms: <input type="checkbox" name="HP"><br>
|
||||
Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br>
|
||||
Hue Bridge IP:<br>
|
||||
<input name="H0" type="number" min="0" max="255" required> .
|
||||
<input name="H1" type="number" min="0" max="255" required> .
|
||||
<input name="H2" type="number" min="0" max="255" required> .
|
||||
<input name="H3" type="number" min="0" max="255" required><br>
|
||||
<b>Press the pushlink button on the bridge, after that save this page!</b><br>
|
||||
(when first connecting)<br>
|
||||
<!--Update Hue group <input name="HUEGR" type="number" min="0" max="99" required> <br>
|
||||
Send <input type="checkbox" name="HUEIO"> On/Off, <input type="checkbox" name="HUEBR"> Brightness, and <input type="checkbox" name="HUECL"> Color<br>-->
|
||||
<!--After device color update, ignore Hue updates for <input name="HUELI" type="number" min="0" max="255" required> minutes<br>-->
|
||||
Hue status: <span class="hms"> Internal ESP Error! </span><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
<html><head><meta name="viewport" content="width=500"><meta charset="utf-8"><title>Sync Settings</title>
|
||||
<script>var d=document;
|
||||
function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#sync-settings");}function B(){window.open("/settings","_self");}function GetV(){var d=document;}
|
||||
function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.DA.value == 1) d.Sf.DA.value = 0; if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
|
||||
else if (d.Sf.DI.value == 5568) {if (d.Sf.DA.value == 0) d.Sf.DA.value = 1; if (d.Sf.EU.value == 0) d.Sf.EU.value = 1;} }
|
||||
function SP(){var p = d.Sf.DI.value; d.getElementById("xp").style.display = (p > 0)?"none":"block"; if (p > 0) d.Sf.EP.value = p;}
|
||||
function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568: d.Sf.DI.value = 5568; break; case 6454: d.Sf.DI.value = 6454; break; }; SP();}
|
||||
function S(){GetV();SetVal();}
|
||||
</script>
|
||||
<style>body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%;margin:0}hr{border-color:#666}button{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}.helpB{text-align:left;position:absolute;width:60px}input{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.5ch solid #333}input[type=number]{width:4em}select{background:#333;color:#fff;font-family:Verdana,sans-serif;border:0.5ch solid #333}td{padding:2px;}.d5{width:4.5em !important;}</style></head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
<h2>Sync setup</h2>
|
||||
<h3>Button setup</h3>
|
||||
On/Off button enabled: <input type="checkbox" name="BT"><br>
|
||||
Infrared remote:
|
||||
<select name=IR>
|
||||
<option value=0>Disabled</option>
|
||||
<option value=1>24-key RGB</option>
|
||||
<option value=2>24-key with CT</option>
|
||||
<option value=3>40-key blue</option>
|
||||
<option value=4>44-key RGB</option>
|
||||
<option value=5>21-key RGB</option>
|
||||
<option value=6>6-key black</option>
|
||||
</select><br>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a>
|
||||
<h3>WLED Broadcast</h3>
|
||||
UDP Port: <input name="UP" type="number" min="1" max="65535" class="d5" required><br>
|
||||
Receive <input type="checkbox" name="RB">Brightness, <input type="checkbox" name="RC">Color, and <input type="checkbox" name="RX">Effects<br>
|
||||
Send notifications on direct change: <input type="checkbox" name="SD"><br>
|
||||
Send notifications on button press: <input type="checkbox" name="SB"><br>
|
||||
Send Alexa notifications: <input type="checkbox" name="SA"><br>
|
||||
Send Philips Hue change notifications: <input type="checkbox" name="SH"><br>
|
||||
Send Macro notifications: <input type="checkbox" name="SM"><br>
|
||||
Send notifications twice: <input type="checkbox" name="S2">
|
||||
<h3>Realtime</h3>
|
||||
Receive UDP realtime: <input type="checkbox" name="RD"><br><br>
|
||||
<i>Network DMX input</i><br>
|
||||
Type:
|
||||
<select name=DI onchange="SP(); adj();">
|
||||
<option value=5568>E1.31 (sACN)</option>
|
||||
<option value=6454>Art-Net</option>
|
||||
<option value=0 selected>Custom port</option>
|
||||
</select><br>
|
||||
<div id=xp>Port: <input name="EP" type="number" min="1" max="65535" value="5568" class="d5" required><br></div>
|
||||
Multicast: <input type="checkbox" name="EM"><br>
|
||||
Start universe: <input name="EU" type="number" min="0" max="63999" required><br>
|
||||
<i>Reboot required.</i> Check out <a href="https://github.com/ahodges9/LedFx" target="_blank">LedFx</a>!<br>
|
||||
Skip out-of-sequence packets: <input type="checkbox" name="ES"><br>
|
||||
DMX start address: <input name="DA" type="number" min="0" max="510" required><br>
|
||||
DMX mode:
|
||||
<select name=DM>
|
||||
<option value=0>Disabled</option>
|
||||
<option value=1>Single RGB</option>
|
||||
<option value=2>Single DRGB</option>
|
||||
<option value=3>Effect</option>
|
||||
<option value=4>Multi RGB</option>
|
||||
<option value=5>Multi DRGB</option>
|
||||
</select><br>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki/E1.31-DMX" target="_blank">E1.31 info</a><br>
|
||||
Timeout: <input name="ET" type="number" min="1" max="65000" required> ms<br>
|
||||
Force max brightness: <input type="checkbox" name="FB"><br>
|
||||
Disable realtime gamma correction: <input type="checkbox" name="RG"><br>
|
||||
Realtime LED offset: <input name="WO" type="number" min="-255" max="255" required>
|
||||
<h3>Alexa Voice Assistant</h3>
|
||||
Emulate Alexa device: <input type="checkbox" name="AL"><br>
|
||||
Alexa invocation name: <input name="AI" maxlength="32">
|
||||
<h3>Blynk</h3>
|
||||
<b>Blynk, MQTT and Hue sync all connect to external hosts!<br>
|
||||
This may impact the responsiveness of the ESP8266.</b><br>
|
||||
For best results, only use one of these services at a time.<br>
|
||||
(alternatively, connect a second ESP to them and use the UDP sync)<br><br>
|
||||
Device Auth token: <input name="BK" maxlength="33"><br>
|
||||
<i>Clear the token field to disable. </i><a href="https://github.com/Aircoookie/WLED/wiki/Blynk" target="_blank">Setup info</a>
|
||||
<h3>MQTT</h3>
|
||||
Enable MQTT: <input type="checkbox" name="MQ"><br>
|
||||
Broker: <input name="MS" maxlength="32">
|
||||
Port: <input name="MQPORT" type="number" min="1" max="65535" class="d5"><br>
|
||||
<b>The MQTT credentials are sent over an unsecured connection.<br>
|
||||
Never use the MQTT password for another service!</b><br>
|
||||
Username: <input name="MQUSER" maxlength="40"><br>
|
||||
Password: <input type="password" input name="MQPASS" maxlength="40"><br>
|
||||
Client ID: <input name="MQCID" maxlength="40"><br>
|
||||
Device Topic: <input name="MD" maxlength="32"><br>
|
||||
Group Topic: <input name="MG" maxlength="32"><br>
|
||||
<i>Reboot required to apply changes. </i><a href="https://github.com/Aircoookie/WLED/wiki/MQTT" target="_blank">MQTT info</a>
|
||||
<h3>Philips Hue</h3>
|
||||
<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
|
||||
Poll Hue light <input name="HL" type="number" min="1" max="99" > every <input name="HI" type="number" min="100" max="65000"> ms: <input type="checkbox" name="HP"><br>
|
||||
Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br>
|
||||
Hue Bridge IP:<br>
|
||||
<input name="H0" type="number" min="0" max="255" > .
|
||||
<input name="H1" type="number" min="0" max="255" > .
|
||||
<input name="H2" type="number" min="0" max="255" > .
|
||||
<input name="H3" type="number" min="0" max="255" ><br>
|
||||
<b>Press the pushlink button on the bridge, after that save this page!</b><br>
|
||||
(when first connecting)<br>
|
||||
Hue status: <span class="hms"> Disabled in this build </span><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
67
wled00/dmx.cpp
Normal file
67
wled00/dmx.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Support for DMX via MAX485.
|
||||
* Change the output pin in src/dependencies/ESPDMX.cpp if needed.
|
||||
* Library from:
|
||||
* https://github.com/Rickgg/ESP-Dmx
|
||||
*/
|
||||
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
#include "src/dependencies/dmx/ESPDMX.h"
|
||||
DMXESPSerial dmx;
|
||||
|
||||
void handleDMX()
|
||||
{
|
||||
// TODO: calculate brightness manually if no shutter channel is set
|
||||
|
||||
uint8_t brightness = strip.getBrightness();
|
||||
|
||||
for (int i = DMXStartLED; i < ledCount; i++) { // uses the amount of LEDs as fixture count
|
||||
|
||||
uint32_t in = strip.getPixelColor(i); // get the colors for the individual fixtures as suggested by Aircoookie in issue #462
|
||||
byte w = in >> 24 & 0xFF;
|
||||
byte r = in >> 16 & 0xFF;
|
||||
byte g = in >> 8 & 0xFF;
|
||||
byte b = in & 0xFF;
|
||||
|
||||
int DMXFixtureStart = DMXStart + (DMXGap * (i - DMXStartLED));
|
||||
for (int j = 0; j < DMXChannels; j++) {
|
||||
int DMXAddr = DMXFixtureStart + j;
|
||||
switch (DMXFixtureMap[j]) {
|
||||
case 0: // Set this channel to 0. Good way to tell strobe- and fade-functions to fuck right off.
|
||||
dmx.write(DMXAddr, 0);
|
||||
break;
|
||||
case 1: // Red
|
||||
dmx.write(DMXAddr, r);
|
||||
break;
|
||||
case 2: // Green
|
||||
dmx.write(DMXAddr, g);
|
||||
break;
|
||||
case 3: // Blue
|
||||
dmx.write(DMXAddr, b);
|
||||
break;
|
||||
case 4: // White
|
||||
dmx.write(DMXAddr, w);
|
||||
break;
|
||||
case 5: // Shutter channel. Controls the brightness.
|
||||
dmx.write(DMXAddr, brightness);
|
||||
break;
|
||||
case 6: // Sets this channel to 255. Like 0, but more wholesome.
|
||||
dmx.write(DMXAddr, 255);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dmx.update(); // update the DMX bus
|
||||
}
|
||||
|
||||
void initDMX() {
|
||||
dmx.init(512); // initialize with bus length
|
||||
}
|
||||
|
||||
#else
|
||||
void handleDMX() {}
|
||||
void initDMX() {}
|
||||
#endif
|
167
wled00/e131.cpp
Normal file
167
wled00/e131.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* E1.31 handler
|
||||
*/
|
||||
|
||||
void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet){
|
||||
//E1.31 protocol support
|
||||
|
||||
uint16_t uni = 0, dmxChannels = 0;
|
||||
uint8_t* e131_data = nullptr;
|
||||
uint8_t seq = 0, mde = REALTIME_MODE_E131;
|
||||
|
||||
if (isArtnet)
|
||||
{
|
||||
uni = p->art_universe;
|
||||
dmxChannels = htons(p->art_length);
|
||||
e131_data = p->art_data;
|
||||
seq = p->art_sequence_number;
|
||||
mde = REALTIME_MODE_ARTNET;
|
||||
} else {
|
||||
uni = htons(p->universe);
|
||||
dmxChannels = htons(p->property_value_count) -1;
|
||||
e131_data = p->property_values;
|
||||
seq = p->sequence_number;
|
||||
}
|
||||
|
||||
// only listen for universes we're handling & allocated memory
|
||||
if (uni >= (e131Universe + E131_MAX_UNIVERSE_COUNT)) return;
|
||||
|
||||
uint8_t previousUniverses = uni - e131Universe;
|
||||
uint16_t possibleLEDsInCurrentUniverse;
|
||||
|
||||
if (e131SkipOutOfSequence)
|
||||
if (seq < e131LastSequenceNumber[uni-e131Universe] && seq > 20 && e131LastSequenceNumber[uni-e131Universe] < 250){
|
||||
DEBUG_PRINT("skipping E1.31 frame (last seq=");
|
||||
DEBUG_PRINT(e131LastSequenceNumber[uni-e131Universe]);
|
||||
DEBUG_PRINT(", current seq=");
|
||||
DEBUG_PRINT(seq);
|
||||
DEBUG_PRINT(", universe=");
|
||||
DEBUG_PRINT(uni);
|
||||
DEBUG_PRINTLN(")");
|
||||
return;
|
||||
}
|
||||
e131LastSequenceNumber[uni-e131Universe] = seq;
|
||||
|
||||
// update status info
|
||||
realtimeIP = clientIP;
|
||||
byte wChannel = 0;
|
||||
|
||||
switch (DMXMode) {
|
||||
case DMX_MODE_DISABLED:
|
||||
return; // nothing to do
|
||||
break;
|
||||
|
||||
case DMX_MODE_SINGLE_RGB:
|
||||
if (uni != e131Universe) return;
|
||||
if (dmxChannels-DMXAddress+1 < 3) return;
|
||||
realtimeLock(realtimeTimeoutMs, mde);
|
||||
if (realtimeOverride) return;
|
||||
wChannel = (dmxChannels-DMXAddress+1 > 3) ? e131_data[DMXAddress+3] : 0;
|
||||
for (uint16_t i = 0; i < ledCount; i++)
|
||||
setRealtimePixel(i, e131_data[DMXAddress+0], e131_data[DMXAddress+1], e131_data[DMXAddress+2], wChannel);
|
||||
break;
|
||||
|
||||
case DMX_MODE_SINGLE_DRGB:
|
||||
if (uni != e131Universe) return;
|
||||
if (dmxChannels-DMXAddress+1 < 4) return;
|
||||
realtimeLock(realtimeTimeoutMs, mde);
|
||||
if (realtimeOverride) return;
|
||||
wChannel = (dmxChannels-DMXAddress+1 > 4) ? e131_data[DMXAddress+4] : 0;
|
||||
if (DMXOldDimmer != e131_data[DMXAddress+0]) {
|
||||
DMXOldDimmer = e131_data[DMXAddress+0];
|
||||
bri = e131_data[DMXAddress+0];
|
||||
strip.setBrightness(bri);
|
||||
}
|
||||
for (uint16_t i = 0; i < ledCount; i++)
|
||||
setRealtimePixel(i, e131_data[DMXAddress+1], e131_data[DMXAddress+2], e131_data[DMXAddress+3], wChannel);
|
||||
break;
|
||||
|
||||
case DMX_MODE_EFFECT:
|
||||
if (uni != e131Universe) return;
|
||||
if (dmxChannels-DMXAddress+1 < 11) return;
|
||||
if (DMXOldDimmer != e131_data[DMXAddress+0]) {
|
||||
DMXOldDimmer = e131_data[DMXAddress+0];
|
||||
bri = e131_data[DMXAddress+0];
|
||||
}
|
||||
if (e131_data[DMXAddress+1] < MODE_COUNT)
|
||||
effectCurrent = e131_data[DMXAddress+ 1];
|
||||
effectSpeed = e131_data[DMXAddress+ 2]; // flickers
|
||||
effectIntensity = e131_data[DMXAddress+ 3];
|
||||
effectPalette = e131_data[DMXAddress+ 4];
|
||||
col[0] = e131_data[DMXAddress+ 5];
|
||||
col[1] = e131_data[DMXAddress+ 6];
|
||||
col[2] = e131_data[DMXAddress+ 7];
|
||||
colSec[0] = e131_data[DMXAddress+ 8];
|
||||
colSec[1] = e131_data[DMXAddress+ 9];
|
||||
colSec[2] = e131_data[DMXAddress+10];
|
||||
if (dmxChannels-DMXAddress+1 > 11)
|
||||
{
|
||||
col[3] = e131_data[DMXAddress+11]; //white
|
||||
colSec[3] = e131_data[DMXAddress+12];
|
||||
}
|
||||
transitionDelayTemp = 0; // act fast
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); // don't send UDP
|
||||
return; // don't activate realtime live mode
|
||||
break;
|
||||
|
||||
case DMX_MODE_MULTIPLE_RGB:
|
||||
realtimeLock(realtimeTimeoutMs, mde);
|
||||
if (realtimeOverride) return;
|
||||
if (previousUniverses == 0) {
|
||||
// first universe of this fixture
|
||||
possibleLEDsInCurrentUniverse = (dmxChannels - DMXAddress + 1) / 3;
|
||||
for (uint16_t i = 0; i < ledCount; i++) {
|
||||
if (i >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
|
||||
setRealtimePixel(i, e131_data[DMXAddress+i*3+0], e131_data[DMXAddress+i*3+1], e131_data[DMXAddress+i*3+2], 0);
|
||||
}
|
||||
} else if (previousUniverses > 0 && uni < (e131Universe + E131_MAX_UNIVERSE_COUNT)) {
|
||||
// additional universe(s) of this fixture
|
||||
uint16_t numberOfLEDsInPreviousUniverses = ((512 - DMXAddress + 1) / 3); // first universe
|
||||
if (previousUniverses > 1) numberOfLEDsInPreviousUniverses += (512 / 3) * (previousUniverses - 1); // extended universe(s) before current
|
||||
possibleLEDsInCurrentUniverse = dmxChannels / 3;
|
||||
for (uint16_t i = numberOfLEDsInPreviousUniverses; i < ledCount; i++) {
|
||||
uint8_t j = i - numberOfLEDsInPreviousUniverses;
|
||||
if (j >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
|
||||
setRealtimePixel(i, e131_data[j*3+1], e131_data[j*3+2], e131_data[j*3+3], 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DMX_MODE_MULTIPLE_DRGB:
|
||||
realtimeLock(realtimeTimeoutMs, mde);
|
||||
if (realtimeOverride) return;
|
||||
if (previousUniverses == 0) {
|
||||
// first universe of this fixture
|
||||
if (DMXOldDimmer != e131_data[DMXAddress+0]) {
|
||||
DMXOldDimmer = e131_data[DMXAddress+0];
|
||||
bri = e131_data[DMXAddress+0];
|
||||
strip.setBrightness(bri);
|
||||
}
|
||||
possibleLEDsInCurrentUniverse = (dmxChannels - DMXAddress) / 3;
|
||||
for (uint16_t i = 0; i < ledCount; i++) {
|
||||
if (i >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
|
||||
setRealtimePixel(i, e131_data[DMXAddress+i*3+1], e131_data[DMXAddress+i*3+2], e131_data[DMXAddress+i*3+3], 0);
|
||||
}
|
||||
} else if (previousUniverses > 0 && uni < (e131Universe + E131_MAX_UNIVERSE_COUNT)) {
|
||||
// additional universe(s) of this fixture
|
||||
uint16_t numberOfLEDsInPreviousUniverses = ((512 - DMXAddress + 1) / 3); // first universe
|
||||
if (previousUniverses > 1) numberOfLEDsInPreviousUniverses += (512 / 3) * (previousUniverses - 1); // extended universe(s) before current
|
||||
possibleLEDsInCurrentUniverse = dmxChannels / 3;
|
||||
for (uint16_t i = numberOfLEDsInPreviousUniverses; i < ledCount; i++) {
|
||||
uint8_t j = i - numberOfLEDsInPreviousUniverses;
|
||||
if (j >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
|
||||
setRealtimePixel(i, e131_data[j*3+1], e131_data[j*3+2], e131_data[j*3+3], 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_PRINTLN("unknown E1.31 DMX mode");
|
||||
return; // nothing to do
|
||||
break;
|
||||
}
|
||||
|
||||
e131NewData = true;
|
||||
}
|
184
wled00/fcn_declare.h
Normal file
184
wled00/fcn_declare.h
Normal file
@ -0,0 +1,184 @@
|
||||
#ifndef WLED_FCN_DECLARE_H
|
||||
#define WLED_FCN_DECLARE_H
|
||||
#include <Arduino.h>
|
||||
#include "src/dependencies/espalexa/EspalexaDevice.h"
|
||||
#include "src/dependencies/e131/ESPAsyncE131.h"
|
||||
|
||||
/*
|
||||
* All globally accessible functions are declared here
|
||||
*/
|
||||
|
||||
//alexa.cpp
|
||||
void onAlexaChange(EspalexaDevice* dev);
|
||||
void alexaInit();
|
||||
void handleAlexa();
|
||||
void onAlexaChange(EspalexaDevice* dev);
|
||||
|
||||
//blynk.cpp
|
||||
void initBlynk(const char* auth);
|
||||
void handleBlynk();
|
||||
void updateBlynk();
|
||||
|
||||
//button.cpp
|
||||
void shortPressAction();
|
||||
void handleButton();
|
||||
void handleIO();
|
||||
|
||||
//colors.cpp
|
||||
void colorFromUint32(uint32_t in, bool secondary = false);
|
||||
void colorFromUint24(uint32_t in, bool secondary = false);
|
||||
void relativeChangeWhite(int8_t amount, byte lowerBoundary = 0);
|
||||
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb); //hue, sat to rgb
|
||||
void colorCTtoRGB(uint16_t mired, byte* rgb); //white spectrum to rgb
|
||||
|
||||
void colorXYtoRGB(float x, float y, byte* rgb); // only defined if huesync disabled TODO
|
||||
void colorRGBtoXY(byte* rgb, float* xy); // only defined if huesync disabled TODO
|
||||
|
||||
void colorFromDecOrHexString(byte* rgb, char* in);
|
||||
void colorRGBtoRGBW(byte* rgb); //rgb to rgbw (http://codewelt.com/rgbw). (RGBW_MODE_LEGACY)
|
||||
|
||||
//dmx.cpp
|
||||
void initDMX();
|
||||
void handleDMX();
|
||||
|
||||
//e131.cpp
|
||||
void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet);
|
||||
|
||||
//file.cpp
|
||||
bool handleFileRead(AsyncWebServerRequest*, String path);
|
||||
|
||||
//hue.cpp
|
||||
void handleHue();
|
||||
void reconnectHue();
|
||||
void onHueError(void* arg, AsyncClient* client, int8_t error);
|
||||
void onHueConnect(void* arg, AsyncClient* client);
|
||||
void sendHuePoll();
|
||||
void onHueData(void* arg, AsyncClient* client, void *data, size_t len);
|
||||
|
||||
//ir.cpp
|
||||
bool decodeIRCustom(uint32_t code);
|
||||
void relativeChange(byte* property, int8_t amount, byte lowerBoundary = 0, byte higherBoundary = 0xFF);
|
||||
void changeEffectSpeed(int8_t amount);
|
||||
void changeEffectIntensity(int8_t amount);
|
||||
void decodeIR(uint32_t code);
|
||||
void decodeIR24(uint32_t code);
|
||||
void decodeIR24OLD(uint32_t code);
|
||||
void decodeIR24CT(uint32_t code);
|
||||
void decodeIR40(uint32_t code);
|
||||
void decodeIR44(uint32_t code);
|
||||
void decodeIR21(uint32_t code);
|
||||
void decodeIR6(uint32_t code);
|
||||
|
||||
void initIR();
|
||||
void handleIR();
|
||||
|
||||
//json.cpp
|
||||
#include "ESPAsyncWebServer.h"
|
||||
#include "src/dependencies/json/ArduinoJson-v6.h"
|
||||
#include "src/dependencies/json/AsyncJson-v6.h"
|
||||
#include "FX.h"
|
||||
// TODO: AsynicWebServerRequest conflict?
|
||||
|
||||
void deserializeSegment(JsonObject elem, byte it);
|
||||
bool deserializeState(JsonObject root);
|
||||
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id);
|
||||
void serializeState(JsonObject root);
|
||||
void serializeInfo(JsonObject root);
|
||||
void serveJson(AsyncWebServerRequest* request);
|
||||
void serveLiveLeds(AsyncWebServerRequest* request);
|
||||
|
||||
//led.cpp
|
||||
void setValuesFromMainSeg();
|
||||
void resetTimebase();
|
||||
void toggleOnOff();
|
||||
void setAllLeds();
|
||||
void setLedsStandard(bool justColors = false);
|
||||
bool colorChanged();
|
||||
void colorUpdated(int callMode);
|
||||
void updateInterfaces(uint8_t callMode);
|
||||
void handleTransitions();
|
||||
void handleNightlight();
|
||||
|
||||
//mqtt.cpp
|
||||
bool initMqtt();
|
||||
void publishMqtt();
|
||||
|
||||
//ntp.cpp
|
||||
void handleNetworkTime();
|
||||
void sendNTPPacket();
|
||||
bool checkNTPResponse();
|
||||
void updateLocalTime();
|
||||
void getTimeString(char* out);
|
||||
bool checkCountdown();
|
||||
void setCountdown();
|
||||
byte weekdayMondayFirst();
|
||||
void checkTimers();
|
||||
|
||||
//overlay.cpp
|
||||
void initCronixie();
|
||||
void handleOverlays();
|
||||
void handleOverlayDraw();
|
||||
void _overlayAnalogCountdown();
|
||||
void _overlayAnalogClock();
|
||||
|
||||
byte getSameCodeLength(char code, int index, char const cronixieDisplay[]);
|
||||
void setCronixie();
|
||||
void _overlayCronixie();
|
||||
void _drawOverlayCronixie();
|
||||
|
||||
//set.cpp
|
||||
void _setRandomColor(bool _sec,bool fromButton=false);
|
||||
bool isAsterisksOnly(const char* str, byte maxLen);
|
||||
void handleSettingsSet(AsyncWebServerRequest *request, byte subPage);
|
||||
bool handleSet(AsyncWebServerRequest *request, const String& req);
|
||||
int getNumVal(const String* req, uint16_t pos);
|
||||
bool updateVal(const String* req, const char* key, byte* val, byte minv=0, byte maxv=255);
|
||||
|
||||
//udp.cpp
|
||||
void notify(byte callMode, bool followUp=false);
|
||||
void realtimeLock(uint32_t timeoutMs, byte md = REALTIME_MODE_GENERIC);
|
||||
void handleNotifications();
|
||||
void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w);
|
||||
|
||||
//usermod.cpp
|
||||
void userSetup();
|
||||
void userConnected();
|
||||
void userLoop();
|
||||
|
||||
//wled_eeprom.cpp
|
||||
void commit();
|
||||
void clearEEPROM();
|
||||
void writeStringToEEPROM(uint16_t pos, char* str, uint16_t len);
|
||||
void readStringFromEEPROM(uint16_t pos, char* str, uint16_t len);
|
||||
void saveSettingsToEEPROM();
|
||||
void loadSettingsFromEEPROM(bool first);
|
||||
void savedToPresets();
|
||||
bool applyPreset(byte index, bool loadBri = true);
|
||||
void savePreset(byte index, bool persist = true);
|
||||
void loadMacro(byte index, char* m);
|
||||
void applyMacro(byte index);
|
||||
void saveMacro(byte index, String mc, bool persist = true); //only commit on single save, not in settings
|
||||
|
||||
//wled_serial.cpp
|
||||
void handleSerial();
|
||||
|
||||
//wled_server.cpp
|
||||
bool isIp(String str);
|
||||
bool captivePortal(AsyncWebServerRequest *request);
|
||||
void initServer();
|
||||
void serveIndexOrWelcome(AsyncWebServerRequest *request);
|
||||
void serveIndex(AsyncWebServerRequest* request);
|
||||
String msgProcessor(const String& var);
|
||||
void serveMessage(AsyncWebServerRequest* request, uint16_t code, String headl, String subl="", byte optionT=255);
|
||||
String settingsProcessor(const String& var);
|
||||
String dmxProcessor(const String& var);
|
||||
void serveSettings(AsyncWebServerRequest* request);
|
||||
|
||||
//xml.cpp
|
||||
char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr);
|
||||
char* URL_response(AsyncWebServerRequest *request);
|
||||
void sappend(char stype, const char* key, int val);
|
||||
void sappends(char stype, const char* key, char* val);
|
||||
void getSettingsJS(byte subPage, char* dest);
|
||||
|
||||
#endif
|
55
wled00/file.cpp
Normal file
55
wled00/file.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Utility for SPIFFS filesystem
|
||||
*/
|
||||
|
||||
//filesystem
|
||||
#ifndef WLED_DISABLE_FILESYSTEM
|
||||
#include <FS.h>
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include "SPIFFS.h"
|
||||
#endif
|
||||
#include "SPIFFSEditor.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined WLED_DISABLE_FILESYSTEM && defined WLED_ENABLE_FS_SERVING
|
||||
//Un-comment any file types you need
|
||||
String getContentType(AsyncWebServerRequest* request, String filename){
|
||||
if(request->hasArg("download")) return "application/octet-stream";
|
||||
else if(filename.endsWith(".htm")) return "text/html";
|
||||
else if(filename.endsWith(".html")) return "text/html";
|
||||
// else if(filename.endsWith(".css")) return "text/css";
|
||||
// else if(filename.endsWith(".js")) return "application/javascript";
|
||||
else if(filename.endsWith(".json")) return "application/json";
|
||||
else if(filename.endsWith(".png")) return "image/png";
|
||||
// else if(filename.endsWith(".gif")) return "image/gif";
|
||||
else if(filename.endsWith(".jpg")) return "image/jpeg";
|
||||
else if(filename.endsWith(".ico")) return "image/x-icon";
|
||||
// else if(filename.endsWith(".xml")) return "text/xml";
|
||||
// else if(filename.endsWith(".pdf")) return "application/x-pdf";
|
||||
// else if(filename.endsWith(".zip")) return "application/x-zip";
|
||||
// else if(filename.endsWith(".gz")) return "application/x-gzip";
|
||||
return "text/plain";
|
||||
}
|
||||
|
||||
bool handleFileRead(AsyncWebServerRequest* request, String path){
|
||||
DEBUG_PRINTLN("FileRead: " + path);
|
||||
if(path.endsWith("/")) path += "index.htm";
|
||||
String contentType = getContentType(request, path);
|
||||
String pathWithGz = path + ".gz";
|
||||
if(SPIFFS.exists(pathWithGz)){
|
||||
request->send(SPIFFS, pathWithGz, contentType);
|
||||
return true;
|
||||
}
|
||||
if(SPIFFS.exists(path)) {
|
||||
request->send(SPIFFS, path, contentType);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
bool handleFileRead(AsyncWebServerRequest*, String path){return false;}
|
||||
#endif
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Various pages
|
||||
* Various web pages
|
||||
*/
|
||||
|
||||
//USER HTML HERE (/u subpage)
|
||||
@ -15,12 +15,42 @@ const char PAGE_msg[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<style>.bt{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%%;margin:0}</style></head>
|
||||
<body><h2>%MSG%</body></html>)=====";
|
||||
|
||||
//DMX channel map
|
||||
const char PAGE_dmxmap[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta content='width=device-width' name='viewport'>
|
||||
<title>DMX Map</title>
|
||||
<script>function B(){window.history.back()};function RS(){window.location = "/settings";}function RP(){top.location.href="/";}function FM() {%DMXVARS%
|
||||
var dmxlabels = ["SET 0","RED","GREEN","BLUE","WHITE","SHUTTER","SET 255", "DISABLED"];
|
||||
var dmxchans = [];
|
||||
for (i=0;i<512;i++) {
|
||||
dmxchans.push(7); // set all to DISABLED
|
||||
}
|
||||
for (i=0;i<LC;i++) {
|
||||
FS = CS + (CG * i);
|
||||
for (j=0;j<CN;j++) {
|
||||
DA=FS+j;
|
||||
dmxchans[DA-1] = CH[j];
|
||||
}
|
||||
}
|
||||
DMXMap = "";
|
||||
for (i=0;i<512;i++) {
|
||||
isstart = "";
|
||||
if ((i+1) % 10 == 0) {
|
||||
isstart="S"
|
||||
}
|
||||
DMXMap += "<div class=\"anytype " + isstart + " type" + dmxchans[i] + "\">" + String(i+1) + "<br />" + dmxlabels[dmxchans[i]] + "</div>";
|
||||
}
|
||||
document.getElementById("map").innerHTML = DMXMap;
|
||||
}</script>
|
||||
<style>.anytype{border: 1px solid white; margin: 1px; float: left; width: 100px; height: 100px;}.S { margin: 0px; border: 2px solid white;} .type7{color: #888; border: 1px dotted grey;}.type6{color: #FFF;}.type4{color: #FFF; font-weight: bold; }.type3{color: #00F; font-weight: bold; }.type2{color: #0F0; font-weight: bold; }.type1{color: #F00; font-weight: bold; } .bt{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%%;margin:0}</style></head>
|
||||
<body onload="FM();"><div id="map">...</div></body></html>)=====";
|
||||
|
||||
|
||||
//firmware update page
|
||||
const char PAGE_update[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta content='width=device-width' name='viewport'><title>WLED Update</title><script>function B(){window.history.back()}</script>
|
||||
<style>.bt{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}input[type=file]{font-size:16px}body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%}</style></head>
|
||||
<body><h2>WLED Software Update</h2>Installed version: 0.9.0-b1<br>Download the latest binary: <a href="https://github.com/Aircoookie/WLED/releases"><img src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square"></a><br><form method='POST' action='/update' enctype='multipart/form-data'><input type='file' class="bt" name='update' required><br><input type='submit' class="bt" value='Update!'></form><button type="button" class="bt" onclick="B()">Back</button></body></html>)=====";
|
||||
<body><h2>WLED Software Update</h2>Installed version: 0.10.0<br>Download the latest binary: <a href="https://github.com/Aircoookie/WLED/releases"><img src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square"></a><br><form method='POST' action='/update' enctype='multipart/form-data'><input type='file' class="bt" name='update' required><br><input type='submit' class="bt" value='Update!'></form><button type="button" class="bt" onclick="B()">Back</button></body></html>)=====";
|
||||
|
||||
|
||||
//new user welcome page
|
||||
|
@ -1,23 +1,23 @@
|
||||
/*
|
||||
* Settings html
|
||||
* Settings html
|
||||
*/
|
||||
|
||||
//common CSS of settings pages
|
||||
const char PAGE_settingsCss[] PROGMEM = R"=====(<style>body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%%;margin:0}hr{border-color:#666}button{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}.helpB{text-align:left;position:absolute;width:60px}input{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.5ch solid #333}input[type=number]{width:4em}select{background:#333;color:#fff;font-family:Verdana,sans-serif;border:0.5ch solid #333}td{padding:2px;}</style>)=====";
|
||||
|
||||
const char PAGE_settingsCss[] PROGMEM = R"=====(<style>body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%%;margin:0}hr{border-color:#666}button{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}.helpB{text-align:left;position:absolute;width:60px}input{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.5ch solid #333}input[type=number]{width:4em}select{background:#333;color:#fff;font-family:Verdana,sans-serif;border:0.5ch solid #333}td{padding:2px;}.d5{width:4.5em !important;}</style>)=====";
|
||||
|
||||
//settings menu
|
||||
const char PAGE_settings[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><title>WLED Settings</title><style>body{text-align:center;background:#222;height:100%;margin:0}html{--h:11.55vh}button{background:#333;color:#fff;font-family:Verdana,Helvetica,sans-serif;border:.3ch solid #333;display:inline-block;font-size:8vmin;height:var(--h);width:95%;margin-top:2.4vh}</style>
|
||||
<html><head><title>WLED Settings</title><style>body{text-align:center;background:#222;height:100%%;margin:0}html{--h:11.55vh}button{background:#333;color:#fff;font-family:Verdana,Helvetica,sans-serif;border:.3ch solid #333;display:inline-block;font-size:8vmin;height:var(--h);width:95%%;margin-top:2.4vh}</style>
|
||||
<script>function BB(){if(window.frameElement){document.getElementById("b").style.display="none";document.documentElement.style.setProperty("--h","13.86vh")}};</script></head>
|
||||
<body onload=BB()>
|
||||
<form action=/><button type=submit id=b>Back</button></form>
|
||||
<form action=/settings/wifi><button type=submit>WiFi Setup</button></form>
|
||||
<form action=/settings/leds><button type=submit>LED Preferences</button></form>
|
||||
<form action=/settings/ui><button type=submit>User Interface</button></form>
|
||||
<form action=/settings/ui><button type=submit>User Interface</button></form>%DMXMENU%
|
||||
<form action=/settings/sync><button type=submit>Sync Interfaces</button></form>
|
||||
<form action=/settings/time><button type=submit>Time & Macros</button></form>
|
||||
<form action=/settings/sec><button type=submit>Security & Updates</button></form>
|
||||
|
||||
</body></html>)=====";
|
||||
|
||||
|
||||
@ -62,7 +62,12 @@ AP opens:
|
||||
<option value="1">Disconnected</option>
|
||||
<option value="2">Always</option>
|
||||
<option value="3">Never (not recommended)</option></select><br>
|
||||
AP IP: <span class="sip"> Not active </span><hr>
|
||||
AP IP: <span class="sip"> Not active </span><br>
|
||||
<h3>Experimental</h3>
|
||||
Disable WiFi sleep: <input type="checkbox" name="WS"><br>
|
||||
<i>Can help with connectivity issues.<br>
|
||||
Do not enable if WiFi is working correctly, increases power consumption.</i>
|
||||
<hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save & Connect</button>
|
||||
</form>
|
||||
</body>
|
||||
@ -75,7 +80,8 @@ const char PAGE_settings_leds[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<meta name=viewport content="width=500">
|
||||
<title>LED Settings</title>
|
||||
<script>var d=document,laprev=55;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#led-settings")}function B(){window.open("/settings","_self")}function S(){GetV();setABL()}function enABL(){var a=d.getElementById("able").checked;d.Sf.LA.value=(a)?laprev:0;d.getElementById("abl").style.display=(a)?"inline":"none";d.getElementById("psu2").style.display=(a)?"inline":"none";if(d.Sf.LA.value>0){setABL()}}function enLA(){var a=d.Sf.LAsel.value;d.Sf.LA.value=a;d.getElementById("LAdis").style.display=(a==50)?"inline":"none";UI()}function setABL(){d.getElementById("able").checked=true;d.Sf.LAsel.value=50;switch(parseInt(d.Sf.LA.value)){case 0:d.getElementById("able").checked=false;enABL();break;case 30:d.Sf.LAsel.value=30;break;case 35:d.Sf.LAsel.value=35;break;case 55:d.Sf.LAsel.value=55;break;default:d.getElementById("LAdis").style.display="inline"}UI()}function UI(){var b=d.querySelectorAll(".wc"),a=b.length;for(i=0;i<a;i++){b[i].style.display=(d.getElementById("rgbw").checked)?"inline":"none"}d.getElementById("ledwarning").style.display=(d.Sf.LC.value>1000)?"inline":"none";d.getElementById("ampwarning").style.display=(d.Sf.MA.value>7200)?"inline":"none";if(d.Sf.LA.value>0){laprev=d.Sf.LA.value}var j=Math.ceil((100+d.Sf.LC.value*laprev)/500)/2;j=(j>5)?Math.ceil(j):j;var g="";var e=(d.Sf.LAsel.value==30);if(j<1.02&&!e){g="ESP 5V pin with 1A USB supply"}else{g+=e?"12V ":"5V ";g+=j;g+="A supply connected to LEDs"}var h=Math.ceil((100+d.Sf.LC.value*laprev)/1500)/2;h=(h>5)?Math.ceil(h):h;var c="(for most effects, ~";c+=h;c+="A is enough)<br>";d.getElementById("psu").innerHTML=g;d.getElementById("psu2").innerHTML=c}function GetV(){var d=document;
|
||||
<script>var d=document,laprev=55;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#led-settings")}function B(){window.open("/settings","_self")}function S(){GetV();setABL()}
|
||||
function enABL(){var a=d.getElementById("able").checked;d.Sf.LA.value=(a)?laprev:0;d.getElementById("abl").style.display=(a)?"inline":"none";d.getElementById("psu2").style.display=(a)?"inline":"none";if(d.Sf.LA.value>0){setABL()}}function enLA(){var a=d.Sf.LAsel.value;d.Sf.LA.value=a;d.getElementById("LAdis").style.display=(a==50)?"inline":"none";UI()}function setABL(){d.getElementById("able").checked=true;d.Sf.LAsel.value=50;switch(parseInt(d.Sf.LA.value)){case 0:d.getElementById("able").checked=false;enABL();break;case 30:d.Sf.LAsel.value=30;break;case 35:d.Sf.LAsel.value=35;break;case 55:d.Sf.LAsel.value=55;break;case 255:d.Sf.LAsel.value=255;break;default:d.getElementById("LAdis").style.display="inline"}UI()}function UI(){var b=d.querySelectorAll(".wc"),a=b.length;for(i=0;i<a;i++){b[i].style.display=(d.getElementById("rgbw").checked)?"inline":"none"}d.getElementById("ledwarning").style.display=(d.Sf.LC.value>1000)?"inline":"none";d.getElementById("ampwarning").style.display=(d.Sf.MA.value>7200)?"inline":"none";if(d.Sf.LA.value==255){laprev=12} else if(d.Sf.LA.value>0){laprev=d.Sf.LA.value}var j=Math.ceil((100+d.Sf.LC.value*laprev)/500)/2;j=(j>5)?Math.ceil(j):j;var g="";var e=(d.Sf.LAsel.value==30);var i=(d.Sf.LAsel.value==255);if(j<1.02&&!e&&!i){g="ESP 5V pin with 1A USB supply"}else{g+=e?"12V ":i?"WS2815 12V ":"5V ";g+=j;g+="A supply connected to LEDs"}var h=Math.ceil((100+d.Sf.LC.value*laprev)/1500)/2;h=(h>5)?Math.ceil(h):h;var c="(for most effects, ~";c+=h;c+="A is enough)<br>";d.getElementById("psu").innerHTML=g;d.getElementById("psu2").innerHTML=i?"":c}function GetV(){var d=document;
|
||||
%CSS%%SCSS%</head><body onload=S()>
|
||||
<form id=form_s name=Sf method=post>
|
||||
<div class=helpB><button type=button onclick=H()>?</button></div>
|
||||
@ -108,6 +114,7 @@ LED voltage (Max. current for a single LED):<br>
|
||||
<option value=55 selected>5V default (55mA)</option>
|
||||
<option value=35>5V efficient (35mA)</option>
|
||||
<option value=30>12V (30mA)</option>
|
||||
<option value=255>WS2815 (12mA)</option>
|
||||
<option value=50>Custom</option>
|
||||
</select><br>
|
||||
<span id=LAdis style=display:none>Custom max. current per LED: <input name=LA type=number min=0 max=255 id=la oninput=UI() required> mA<br></span>
|
||||
@ -116,13 +123,23 @@ LED voltage (Max. current for a single LED):<br>
|
||||
<br>
|
||||
LEDs are 4-channel type (RGBW): <input type=checkbox name=EW onchange=UI() id=rgbw><br>
|
||||
<span class=wc>
|
||||
Auto-calculate white channel from RGB: <input type=checkbox name=AW><br></span>
|
||||
Auto-calculate white channel from RGB:<br>
|
||||
<select name=AW>
|
||||
<option value=0>None</option>
|
||||
<option value=1>Brighter</option>
|
||||
<option value=2>Accurate</option>
|
||||
<option value=3>Dual</option>
|
||||
<option value=4>Legacy</option>
|
||||
</select>
|
||||
<br></span>
|
||||
Color order:
|
||||
<select name=CO>
|
||||
<option value=0>GRB</option>
|
||||
<option value=1>RGB</option>
|
||||
<option value=2>BRG</option>
|
||||
<option value=3>RBG</option>
|
||||
<option value=4>BGR</option>
|
||||
<option value=5>GBR</option>
|
||||
</select>
|
||||
<h3>Defaults</h3>
|
||||
Turn LEDs on after power up/reset: <input type=checkbox name=BO><br>
|
||||
@ -150,13 +167,70 @@ Palette blending:
|
||||
<option value=3>None (not recommended)</option>
|
||||
</select><br>
|
||||
Reverse LED order (rotate 180): <input type=checkbox name=RV><br>
|
||||
Skip first LED: <input type=checkbox name=SL><br>
|
||||
Disable repeating N LEDs: <input type=number min=0 max=255 name=DL><br>
|
||||
(Turns off N LEDs between each lit one, spacing out effects)<hr>
|
||||
Skip first LED: <input type=checkbox name=SL><hr>
|
||||
<button type=button onclick=B()>Back</button><button type=submit>Save</button>
|
||||
</form></body></html>)=====";
|
||||
|
||||
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
//DMX Output settings
|
||||
const char PAGE_settings_dmx[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500"><meta charset="utf-8"><title>DMX Settings</title><script>
|
||||
function GCH(num) {
|
||||
d=document;
|
||||
|
||||
d.getElementById('dmxchannels').innerHTML += "";
|
||||
for (i=0;i<num;i++) {
|
||||
d.getElementById('dmxchannels').innerHTML += "<span id=CH" + (i+1) + "s >Channel " + (i+1) + ": <select name=CH" + (i+1) + " id=\"CH" + (i+1) + "\"><option value=0>Set to 0</option><option value=1>Red</option><option value=2>Green</option><option value=3>Blue</option><option value=4>White</option><option value=5>Shutter (Brightness)</option><option value=6>Set to 255</option></select></span><br />\n";
|
||||
}
|
||||
}
|
||||
function mMap(){
|
||||
d=document;
|
||||
numCh=document.Sf.CN.value;
|
||||
numGap=document.Sf.CG.value;
|
||||
if (parseInt(numCh)>parseInt(numGap)) {
|
||||
d.getElementById("gapwarning").style.display="block";
|
||||
} else {
|
||||
d.getElementById("gapwarning").style.display="none";
|
||||
}
|
||||
for (i=0;i<15;i++) {
|
||||
if (i>=numCh) {
|
||||
d.getElementById("CH"+(i+1) + "s").style.opacity = "0.5";
|
||||
d.getElementById("CH"+(i+1)).disabled = true;
|
||||
|
||||
} else {
|
||||
d.getElementById("CH"+(i+1) + "s").style.opacity = "1";
|
||||
d.getElementById("CH"+(i+1)).disabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
function S(){GCH(15);GetV();mMap();}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}function B(){window.history.back();}function GetV(){var d=document;
|
||||
%CSS%%SCSS%</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
<h2>Imma firin ma lazer (if it has DMX support)</h2><!-- TODO: Change to something less-meme-related //-->
|
||||
|
||||
<i>Number of fixtures is taken from LED config page</i><br>
|
||||
|
||||
Channels per fixture (15 max): <input type="number" min="1" max="15" name="CN" maxlength="2" onchange="mMap();"><br />
|
||||
Start channel: <input type="number" min="1" max="512" name="CS" maxlength="2"><br />
|
||||
Spacing between start channels: <input type="number" min="1" max="512" name="CG" maxlength="2" onchange="mMap();"> [ <a href="javascript:alert('if set to 10, first fixture will start at 10,\nsecond will start at 20 etc.\nRegardless of the channel count.\nMakes memorizing channel numbers easier.');">info</a> ]<br>
|
||||
<div id="gapwarning" style="color: orange; display: none;">WARNING: Channel gap is lower than channels per fixture.<br />This will cause overlap.</div>
|
||||
<button type="button" onclick="location.href='/dmxmap';">DMX Map</button><br>
|
||||
DMX fixtures start LED: <input type="number" min="0" max="1500" name="SL">
|
||||
<h3>channel functions</h3>
|
||||
<div id="dmxchannels"></div>
|
||||
<hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>)=====";
|
||||
|
||||
#else
|
||||
const char PAGE_settings_dmx[] PROGMEM = R"=====()=====";
|
||||
#endif
|
||||
|
||||
//User Interface settings
|
||||
const char PAGE_settings_ui[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500"><meta charset="utf-8"><title>UI Settings</title><script>
|
||||
@ -175,77 +249,105 @@ Sync button toggles both send and receive: <input type="checkbox" name="ST"><br>
|
||||
</html>)=====";
|
||||
|
||||
|
||||
|
||||
//sync settings
|
||||
const char PAGE_settings_sync[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500"><meta charset="utf-8"><title>Sync Settings</title>
|
||||
<script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#sync-settings");}function B(){window.open("/settings","_self");}function GetV(){var d=document;
|
||||
<html><head><meta name=viewport content="width=500"><meta charset=utf-8><title>Sync Settings</title>
|
||||
<script>var d=document;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#sync-settings")}function B(){window.open("/settings","_self")}function adj(){if(d.Sf.DI.value==6454){if(d.Sf.DA.value==1){d.Sf.DA.value=0}if(d.Sf.EU.value==1){d.Sf.EU.value=0}}else{if(d.Sf.DI.value==5568){if(d.Sf.DA.value==0){d.Sf.DA.value=1}if(d.Sf.EU.value==0){d.Sf.EU.value=1}}}}function SP(){var a=d.Sf.DI.value;d.getElementById("xp").style.display=(a>0)?"none":"block";if(a>0){d.Sf.EP.value=a}}function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568:d.Sf.DI.value=5568;break;case 6454:d.Sf.DI.value=6454;break}SP()}function S(){GetV();SetVal()};function GetV(){
|
||||
%CSS%%SCSS%</head>
|
||||
<body onload="GetV()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
<body onload=S()>
|
||||
<form id=form_s name=Sf method=post>
|
||||
<div class=helpB><button type=button onclick=H()>?</button></div>
|
||||
<button type=button onclick=B()>Back</button><button type=submit>Save</button><hr>
|
||||
<h2>Sync setup</h2>
|
||||
<h3>Button setup</h3>
|
||||
On/Off button enabled: <input type="checkbox" name="BT"><br>
|
||||
Infrared receiver type (0 = disabled): <input name="IR" type="number" min="0" max="4" required><br>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a>
|
||||
On/Off button enabled: <input type=checkbox name=BT><br>
|
||||
Infrared remote:
|
||||
<select name=IR>
|
||||
<option value=0>Disabled</option>
|
||||
<option value=1>24-key RGB</option>
|
||||
<option value=2>24-key with CT</option>
|
||||
<option value=3>40-key blue</option>
|
||||
<option value=4>44-key RGB</option>
|
||||
<option value=5>21-key RGB</option>
|
||||
<option value=6>6-key black</option>
|
||||
</select><br>
|
||||
<a href=https://github.com/Aircoookie/WLED/wiki/Infrared-Control target=_blank>IR info</a>
|
||||
<h3>WLED Broadcast</h3>
|
||||
UDP Port: <input name="UP" type="number" min="1" max="65535" required><br>
|
||||
Receive <input type="checkbox" name="RB">Brightness, <input type="checkbox" name="RC">Color, and <input type="checkbox" name="RX">Effects<br>
|
||||
Send notifications on direct change: <input type="checkbox" name="SD"><br>
|
||||
Send notifications on button press: <input type="checkbox" name="SB"><br>
|
||||
Send Alexa notifications: <input type="checkbox" name="SA"><br>
|
||||
Send Philips Hue change notifications: <input type="checkbox" name="SH"><br>
|
||||
Send Macro notifications: <input type="checkbox" name="SM"><br>
|
||||
Send notifications twice: <input type="checkbox" name="S2">
|
||||
UDP Port: <input name=UP type=number min=1 max=65535 class=d5 required><br>
|
||||
Receive <input type=checkbox name=RB>Brightness, <input type=checkbox name=RC>Color, and <input type=checkbox name=RX>Effects<br>
|
||||
Send notifications on direct change: <input type=checkbox name=SD><br>
|
||||
Send notifications on button press: <input type=checkbox name=SB><br>
|
||||
Send Alexa notifications: <input type=checkbox name=SA><br>
|
||||
Send Philips Hue change notifications: <input type=checkbox name=SH><br>
|
||||
Send Macro notifications: <input type=checkbox name=SM><br>
|
||||
Send notifications twice: <input type=checkbox name=S2>
|
||||
<h3>Realtime</h3>
|
||||
Receive UDP realtime: <input type="checkbox" name="RD"><br><br>
|
||||
<i>E1.31 (sACN)</i><br>
|
||||
Use E1.31 multicast: <input type="checkbox" name="EM"><br>
|
||||
E1.31 start universe: <input name="EU" type="number" min="1" max="63999" required><br>
|
||||
<i>Reboot required.</i> Check out <a href="https://github.com/ahodges9/LedFx" target="_blank">LedFx</a>!<br><br>
|
||||
Timeout: <input name="ET" type="number" min="1" max="65000" required> ms<br>
|
||||
Force max brightness: <input type="checkbox" name="FB"><br>
|
||||
Disable realtime gamma correction: <input type="checkbox" name="RG"><br>
|
||||
Realtime LED offset: <input name="WO" type="number" min="-255" max="255" required>
|
||||
Receive UDP realtime: <input type=checkbox name=RD><br><br>
|
||||
<i>Network DMX input</i><br>
|
||||
Type:
|
||||
<select name=DI onchange=SP();adj()>
|
||||
<option value=5568>E1.31 (sACN)</option>
|
||||
<option value=6454>Art-Net</option>
|
||||
<option value=0 selected>Custom port</option>
|
||||
</select><br>
|
||||
<div id=xp>Port: <input name=EP type=number min=1 max=65535 value=5568 class=d5 required><br></div>
|
||||
Multicast: <input type=checkbox name=EM><br>
|
||||
Start universe: <input name=EU type=number min=0 max=63999 required><br>
|
||||
<i>Reboot required.</i> Check out <a href=https://github.com/ahodges9/LedFx target=_blank>LedFx</a>!<br>
|
||||
Skip out-of-sequence packets: <input type=checkbox name=ES><br>
|
||||
DMX start address: <input name=DA type=number min=0 max=510 required><br>
|
||||
DMX mode:
|
||||
<select name=DM>
|
||||
<option value=0>Disabled</option>
|
||||
<option value=1>Single RGB</option>
|
||||
<option value=2>Single DRGB</option>
|
||||
<option value=3>Effect</option>
|
||||
<option value=4>Multi RGB</option>
|
||||
<option value=5>Multi DRGB</option>
|
||||
</select><br>
|
||||
<a href=https://github.com/Aircoookie/WLED/wiki/E1.31-DMX target=_blank>E1.31 info</a><br>
|
||||
Timeout: <input name=ET type=number min=1 max=65000 required> ms<br>
|
||||
Force max brightness: <input type=checkbox name=FB><br>
|
||||
Disable realtime gamma correction: <input type=checkbox name=RG><br>
|
||||
Realtime LED offset: <input name=WO type=number min=-255 max=255 required>
|
||||
<h3>Alexa Voice Assistant</h3>
|
||||
Emulate Alexa device: <input type="checkbox" name="AL"><br>
|
||||
Alexa invocation name: <input name="AI" maxlength="32">
|
||||
Emulate Alexa device: <input type=checkbox name=AL><br>
|
||||
Alexa invocation name: <input name=AI maxlength=32>
|
||||
<h3>Blynk</h3>
|
||||
<b>Blynk, MQTT and Hue sync all connect to external hosts!<br>
|
||||
This may impact the responsiveness of the ESP8266.</b><br>
|
||||
For best results, only use one of these services at a time.<br>
|
||||
(alternatively, connect a second ESP to them and use the UDP sync)<br><br>
|
||||
Device Auth token: <input name="BK" maxlength="33"><br>
|
||||
<i>Clear the token field to disable. </i><a href="https://github.com/Aircoookie/WLED/wiki/Blynk" target="_blank">Setup info</a>
|
||||
Device Auth token: <input name=BK maxlength=33><br>
|
||||
<i>Clear the token field to disable. </i><a href=https://github.com/Aircoookie/WLED/wiki/Blynk target=_blank>Setup info</a>
|
||||
<h3>MQTT</h3>
|
||||
Enable MQTT: <input type="checkbox" name="MQ"><br>
|
||||
Broker: <input name="MS" maxlength="32">
|
||||
Port: <input name="MQPORT" type="number" min="1" max="65535" required><br>
|
||||
Enable MQTT: <input type=checkbox name=MQ><br>
|
||||
Broker: <input name=MS maxlength=32>
|
||||
Port: <input name=MQPORT type=number min=1 max=65535 class=d5><br>
|
||||
<b>The MQTT credentials are sent over an unsecured connection.<br>
|
||||
Never use the MQTT password for another service!</b><br>
|
||||
Username: <input name="MQUSER" maxlength="40"><br>
|
||||
Password: <input type="password" input name="MQPASS" maxlength="40"><br>
|
||||
Client ID: <input name="MQCID" maxlength="40"><br>
|
||||
Device Topic: <input name="MD" maxlength="32"><br>
|
||||
Group Topic: <input name="MG" maxlength="32"><br>
|
||||
<i>Reboot required to apply changes. </i><a href="https://github.com/Aircoookie/WLED/wiki/MQTT" target="_blank">MQTT info</a>
|
||||
Username: <input name=MQUSER maxlength=40><br>
|
||||
Password: <input type=password input name=MQPASS maxlength=40><br>
|
||||
Client ID: <input name=MQCID maxlength=40><br>
|
||||
Device Topic: <input name=MD maxlength=32><br>
|
||||
Group Topic: <input name=MG maxlength=32><br>
|
||||
<i>Reboot required to apply changes. </i><a href=https://github.com/Aircoookie/WLED/wiki/MQTT target=_blank>MQTT info</a>
|
||||
<h3>Philips Hue</h3>
|
||||
<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
|
||||
Poll Hue light <input name="HL" type="number" min="1" max="99" required> every <input name="HI" type="number" min="100" max="65000" required> ms: <input type="checkbox" name="HP"><br>
|
||||
Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br>
|
||||
Poll Hue light <input name=HL type=number min=1 max=99> every <input name=HI type=number min=100 max=65000> ms: <input type=checkbox name=HP><br>
|
||||
Then, receive <input type=checkbox name=HO> On/Off, <input type=checkbox name=HB> Brightness, and <input type=checkbox name=HC> Color<br>
|
||||
Hue Bridge IP:<br>
|
||||
<input name="H0" type="number" min="0" max="255" required> .
|
||||
<input name="H1" type="number" min="0" max="255" required> .
|
||||
<input name="H2" type="number" min="0" max="255" required> .
|
||||
<input name="H3" type="number" min="0" max="255" required><br>
|
||||
<input name=H0 type=number min=0 max=255> .
|
||||
<input name=H1 type=number min=0 max=255> .
|
||||
<input name=H2 type=number min=0 max=255> .
|
||||
<input name=H3 type=number min=0 max=255><br>
|
||||
<b>Press the pushlink button on the bridge, after that save this page!</b><br>
|
||||
(when first connecting)<br>
|
||||
Hue status: <span class="hms"> Internal ESP Error! </span><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
Hue status: <span class=sip> Disabled in this build </span><hr>
|
||||
<button type=button onclick=B()>Back</button><button type=submit>Save</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>)=====";
|
||||
</body></html>)=====";
|
||||
|
||||
|
||||
//time and macro settings
|
||||
@ -282,6 +384,8 @@ Time zone:
|
||||
<option value="13">North Korea</option>
|
||||
<option value="14">IST (India)</option>
|
||||
<option value="15">CA-Saskatchewan</option>
|
||||
<option value="16">ACST</option>
|
||||
<option value="17">ACST/ACDT</option>
|
||||
</select><br>
|
||||
UTC offset: <input name="UO" type="number" min="-65500" max="65500" required> seconds (max. 18 hours)<br>
|
||||
Current local time is <span class="times">unknown</span>.
|
||||
@ -368,12 +472,12 @@ HTTP traffic is unencrypted. An attacker in the same network can intercept form
|
||||
<button type="button" onclick="U()">Manual OTA Update</button><br>
|
||||
Enable ArduinoOTA: <input type="checkbox" name="AO"><br>
|
||||
<h3>About</h3>
|
||||
<a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.9.0-b2<br><br>
|
||||
<a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.10.0<br><br>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki/Contributors-&-About" target="_blank">Contributors, dependencies and special thanks</a><br>
|
||||
A huge thank you to everyone who helped me create WLED!<br><br>
|
||||
(c) 2016-2020 Christian Schwinne <br>
|
||||
<i>Licensed under the MIT license</i><br><br>
|
||||
Server message: <span class="msg"> Response error! </span><hr>
|
||||
Server message: <span class="sip"> Response error! </span><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save & Reboot</button>
|
||||
</form>
|
||||
</body>
|
||||
|
3126
wled00/html_ui.h
3126
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,16 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Sync to Philips hue lights
|
||||
*/
|
||||
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
|
||||
void handleHue()
|
||||
{
|
||||
if (hueReceived)
|
||||
{
|
||||
colorUpdated(7); hueReceived = false;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_HUE); hueReceived = false;
|
||||
if (hueStoreAllowed && hueNewKey)
|
||||
{
|
||||
saveSettingsToEEPROM(); //save api key
|
||||
@ -23,7 +27,7 @@ void handleHue()
|
||||
reconnectHue();
|
||||
} else {
|
||||
hueClient->close();
|
||||
if (hueError[0] == 'A') strcpy(hueError,"Inactive");
|
||||
if (hueError == HUE_ERROR_ACTIVE) hueError = HUE_ERROR_INACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +48,7 @@ void reconnectHue()
|
||||
void onHueError(void* arg, AsyncClient* client, int8_t error)
|
||||
{
|
||||
DEBUG_PRINTLN("Hue err");
|
||||
strcpy(hueError,"Request timeout");
|
||||
hueError = HUE_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
void onHueConnect(void* arg, AsyncClient* client)
|
||||
@ -59,15 +63,15 @@ void sendHuePoll()
|
||||
String req = "";
|
||||
if (hueAuthRequired)
|
||||
{
|
||||
req += "POST /api HTTP/1.1\r\nHost: ";
|
||||
req += F("POST /api HTTP/1.1\r\nHost: ");
|
||||
req += hueIP.toString();
|
||||
req += "\r\nContent-Length: 25\r\n\r\n{\"devicetype\":\"wled#esp\"}";
|
||||
req += F("\r\nContent-Length: 25\r\n\r\n{\"devicetype\":\"wled#esp\"}");
|
||||
} else
|
||||
{
|
||||
req += "GET /api/";
|
||||
req += hueApiKey;
|
||||
req += "/lights/" + String(huePollLightId);
|
||||
req += " HTTP/1.1\r\nHost: ";
|
||||
req += F(" HTTP/1.1\r\nHost: ");
|
||||
req += hueIP.toString();
|
||||
req += "\r\n\r\n";
|
||||
}
|
||||
@ -93,21 +97,18 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
|
||||
auto error = deserializeJson(root, str);
|
||||
if (error)
|
||||
{
|
||||
strcpy(hueError,"JSON parsing error"); return;
|
||||
hueError = HUE_ERROR_JSON_PARSING; return;
|
||||
}
|
||||
|
||||
int hueErrorCode = root[0]["error"]["type"];
|
||||
if (hueErrorCode)//hue bridge returned error
|
||||
{
|
||||
hueError = hueErrorCode;
|
||||
switch (hueErrorCode)
|
||||
{
|
||||
case 1: strcpy(hueError,"Unauthorized"); hueAuthRequired = true; break;
|
||||
case 3: strcpy(hueError,"Invalid light ID"); huePollingEnabled = false; break;
|
||||
case 101: strcpy(hueError,"Link button not pressed"); hueAuthRequired = true; break;
|
||||
default:
|
||||
char coerr[18];
|
||||
sprintf(coerr,"Bridge Error %i",hueErrorCode);
|
||||
strcpy(hueError,coerr);
|
||||
case 1: hueAuthRequired = true; break; //Unauthorized user
|
||||
case 3: huePollingEnabled = false; break; //Invalid light ID
|
||||
case 101: hueAuthRequired = true; break; //link button not presset
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -133,7 +134,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
|
||||
auto error = deserializeJson(root, str);
|
||||
if (error)
|
||||
{
|
||||
strcpy(hueError,"JSON parsing error"); return;
|
||||
hueError = HUE_ERROR_JSON_PARSING; return;
|
||||
}
|
||||
|
||||
float hueX=0, hueY=0;
|
||||
@ -173,7 +174,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
|
||||
hueBri = 0;
|
||||
}
|
||||
|
||||
strcpy(hueError,"Active");
|
||||
hueError = HUE_ERROR_ACTIVE;
|
||||
|
||||
//apply vals
|
||||
if (hueBri != hueBriLast)
|
@ -1,3 +1,5 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Infrared sensor support for generic 24/40/44 key RGB remotes
|
||||
*/
|
||||
@ -14,6 +16,7 @@ decode_results results;
|
||||
unsigned long irCheckedTime = 0;
|
||||
uint32_t lastValidCode = 0;
|
||||
uint16_t irTimesRepeated = 0;
|
||||
uint8_t lastIR6ColourIdx = 0;
|
||||
|
||||
|
||||
//Add what your custom IR codes should trigger here. Guide: https://github.com/Aircoookie/WLED/wiki/Infrared-Control
|
||||
@ -28,20 +31,61 @@ bool decodeIRCustom(uint32_t code)
|
||||
|
||||
default: return false;
|
||||
}
|
||||
if (code != IRCUSTOM_MACRO1) colorUpdated(2); //don't update color again if we apply macro, it already does it
|
||||
if (code != IRCUSTOM_MACRO1) colorUpdated(NOTIFIER_CALL_MODE_BUTTON); //don't update color again if we apply macro, it already does it
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//relatively change brightness, minumum A=5
|
||||
void relativeChange(byte* property, int8_t amount, byte lowerBoundary =0)
|
||||
void relativeChange(byte* property, int8_t amount, byte lowerBoundary, byte higherBoundary)
|
||||
{
|
||||
int16_t new_val = (int16_t) *property + amount;
|
||||
if (new_val > 0xFF) new_val = 0xFF;
|
||||
if (new_val > higherBoundary) new_val = higherBoundary;
|
||||
else if (new_val < lowerBoundary) new_val = lowerBoundary;
|
||||
*property = new_val;
|
||||
*property = (byte)constrain(new_val,0.1,255.1);
|
||||
}
|
||||
|
||||
void changeEffectSpeed(int8_t amount)
|
||||
{
|
||||
if (effectCurrent != 0) {
|
||||
int16_t new_val = (int16_t) effectSpeed + amount;
|
||||
effectSpeed = (byte)constrain(new_val,0.1,255.1);
|
||||
} else { // if Effect == "solid Color", change the hue of the primary color
|
||||
CRGB fastled_col;
|
||||
fastled_col.red = col[0];
|
||||
fastled_col.green = col[1];
|
||||
fastled_col.blue = col[2];
|
||||
CHSV prim_hsv = rgb2hsv_approximate(fastled_col);
|
||||
int16_t new_val = (int16_t) prim_hsv.h + amount;
|
||||
if (new_val > 255) new_val -= 255; // roll-over if bigger than 255
|
||||
if (new_val < 0) new_val += 255; // roll-over if smaller than 0
|
||||
prim_hsv.h = (byte)new_val;
|
||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||
col[0] = fastled_col.red;
|
||||
col[1] = fastled_col.green;
|
||||
col[2] = fastled_col.blue;
|
||||
}
|
||||
}
|
||||
|
||||
void changeEffectIntensity(int8_t amount)
|
||||
{
|
||||
if (effectCurrent != 0) {
|
||||
int16_t new_val = (int16_t) effectIntensity + amount;
|
||||
effectIntensity = (byte)constrain(new_val,0.1,255.1);
|
||||
} else { // if Effect == "solid Color", change the saturation of the primary color
|
||||
CRGB fastled_col;
|
||||
fastled_col.red = col[0];
|
||||
fastled_col.green = col[1];
|
||||
fastled_col.blue = col[2];
|
||||
CHSV prim_hsv = rgb2hsv_approximate(fastled_col);
|
||||
int16_t new_val = (int16_t) prim_hsv.s + amount;
|
||||
prim_hsv.s = (byte)constrain(new_val,0.1,255.1); // constrain to 0-255
|
||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||
col[0] = fastled_col.red;
|
||||
col[1] = fastled_col.green;
|
||||
col[2] = fastled_col.blue;
|
||||
}
|
||||
}
|
||||
|
||||
void decodeIR(uint32_t code)
|
||||
{
|
||||
@ -50,25 +94,25 @@ void decodeIR(uint32_t code)
|
||||
irTimesRepeated++;
|
||||
if (lastValidCode == IR24_BRIGHTER || lastValidCode == IR40_BPLUS )
|
||||
{
|
||||
relativeChange(&bri, 10); colorUpdated(2);
|
||||
relativeChange(&bri, 10); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
else if (lastValidCode == IR24_DARKER || lastValidCode == IR40_BMINUS )
|
||||
{
|
||||
relativeChange(&bri, -10, 5); colorUpdated(2);
|
||||
relativeChange(&bri, -10, 5); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
if (lastValidCode == IR40_WPLUS)
|
||||
{
|
||||
relativeChangeWhite(10); colorUpdated(2);
|
||||
relativeChangeWhite(10); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
else if (lastValidCode == IR40_WMINUS)
|
||||
{
|
||||
relativeChangeWhite(-10, 5); colorUpdated(2);
|
||||
relativeChangeWhite(-10, 5); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
else if ((lastValidCode == IR24_ON || lastValidCode == IR40_ON) && irTimesRepeated > 7 )
|
||||
{
|
||||
nightlightActive = true;
|
||||
nightlightStartTime = millis();
|
||||
colorUpdated(2);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -83,9 +127,15 @@ void decodeIR(uint32_t code)
|
||||
case 2: decodeIR24CT(code); break; // white 24-key remote with CW, WW, CT+ and CT- keys
|
||||
case 3: decodeIR40(code); break; // blue 40-key remote with 25%, 50%, 75% and 100% keys
|
||||
case 4: decodeIR44(code); break; // white 44-key remote with color-up/down keys and DIY1 to 6 keys
|
||||
case 5: decodeIR21(code); break; // white 21-key remote
|
||||
case 6: decodeIR6(code); break; // black 6-key learning remote defaults: "CH" controls brightness,
|
||||
// "VOL +" controls effect, "VOL -" controls colour/palette, "MUTE"
|
||||
// sets bright plain white
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
if (nightlightActive && bri == 0) nightlightActive = false;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON); //for notifier, IR is considered a button input
|
||||
//code <= 0xF70000 also invalid
|
||||
}
|
||||
|
||||
@ -120,7 +170,6 @@ void decodeIR24(uint32_t code)
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
colorUpdated(2); //for notifier, IR is considered a button input
|
||||
}
|
||||
|
||||
void decodeIR24OLD(uint32_t code)
|
||||
@ -146,14 +195,13 @@ void decodeIR24OLD(uint32_t code)
|
||||
case IR24_OLD_MAGENTA : colorFromUint32(COLOR_MAGENTA); break;
|
||||
case IR24_OLD_PINK : colorFromUint32(COLOR_PINK); break;
|
||||
case IR24_OLD_WHITE : colorFromUint32(COLOR_WHITE); effectCurrent = 0; break;
|
||||
case IR24_OLD_FLASH : if (!applyPreset(1)) effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; break;
|
||||
case IR24_OLD_STROBE : if (!applyPreset(2)) effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; break;
|
||||
case IR24_OLD_FADE : if (!applyPreset(3)) effectCurrent = FX_MODE_BREATH; effectPalette = 0; break;
|
||||
case IR24_OLD_SMOOTH : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; break;
|
||||
case IR24_OLD_FLASH : if (!applyPreset(1)) { effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; } break;
|
||||
case IR24_OLD_STROBE : if (!applyPreset(2)) { effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; } break;
|
||||
case IR24_OLD_FADE : if (!applyPreset(3)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
|
||||
case IR24_OLD_SMOOTH : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
colorUpdated(2); //for notifier, IR is considered a button input
|
||||
}
|
||||
|
||||
|
||||
@ -179,17 +227,16 @@ void decodeIR24CT(uint32_t code)
|
||||
case IR24_CT_PURPLE : colorFromUint32(COLOR_PURPLE); break;
|
||||
case IR24_CT_MAGENTA : colorFromUint32(COLOR_MAGENTA); break;
|
||||
case IR24_CT_PINK : colorFromUint32(COLOR_PINK); break;
|
||||
case IR24_CT_COLDWHITE : colorFromUint32(COLOR_COLDWHITE); effectCurrent = 0; break;
|
||||
case IR24_CT_WARMWHITE : colorFromUint32(COLOR_WARMWHITE); effectCurrent = 0; break;
|
||||
case IR24_CT_CTPLUS : colorFromUint32(COLOR_COLDWHITE2); effectCurrent = 0; break;
|
||||
case IR24_CT_CTMINUS : colorFromUint32(COLOR_WARMWHITE2); effectCurrent = 0; break;
|
||||
case IR24_CT_COLDWHITE : colorFromUint32(COLOR2_COLDWHITE); effectCurrent = 0; break;
|
||||
case IR24_CT_WARMWHITE : colorFromUint32(COLOR2_WARMWHITE); effectCurrent = 0; break;
|
||||
case IR24_CT_CTPLUS : colorFromUint32(COLOR2_COLDWHITE2); effectCurrent = 0; break;
|
||||
case IR24_CT_CTMINUS : colorFromUint32(COLOR2_WARMWHITE2); effectCurrent = 0; break;
|
||||
case IR24_CT_MEMORY : {
|
||||
if (col[3] > 0) col[3] = 0;
|
||||
else colorFromUint32(COLOR_NEUTRALWHITE); effectCurrent = 0; } break;
|
||||
else colorFromUint32(COLOR2_NEUTRALWHITE); effectCurrent = 0; } break;
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
colorUpdated(2); //for notifier, IR is considered a button input
|
||||
}
|
||||
|
||||
|
||||
@ -238,17 +285,16 @@ void decodeIR40(uint32_t code)
|
||||
case IR40_W50 : bri = 127; break;
|
||||
case IR40_W75 : bri = 191; break;
|
||||
case IR40_W100 : bri = 255; break;
|
||||
case IR40_QUICK : relativeChange(&effectSpeed, 10); break;
|
||||
case IR40_SLOW : relativeChange(&effectSpeed, -10, 5); break;
|
||||
case IR40_JUMP7 : relativeChange(&effectIntensity, 10); break;
|
||||
case IR40_AUTO : relativeChange(&effectIntensity, -10, 5); break;
|
||||
case IR40_JUMP3 : if (!applyPreset(1)) effectCurrent = FX_MODE_STATIC; effectPalette = 0; break;
|
||||
case IR40_FADE3 : if (!applyPreset(2)) effectCurrent = FX_MODE_BREATH; effectPalette = 0; break;
|
||||
case IR40_FADE7 : if (!applyPreset(3)) effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; break;
|
||||
case IR40_FLASH : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; break;
|
||||
case IR40_QUICK : changeEffectSpeed( 16); break;
|
||||
case IR40_SLOW : changeEffectSpeed(-16); break;
|
||||
case IR40_JUMP7 : changeEffectIntensity( 16); break;
|
||||
case IR40_AUTO : changeEffectIntensity(-16); break;
|
||||
case IR40_JUMP3 : if (!applyPreset(1)) { effectCurrent = FX_MODE_STATIC; effectPalette = 0; } break;
|
||||
case IR40_FADE3 : if (!applyPreset(2)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
|
||||
case IR40_FADE7 : if (!applyPreset(3)) { effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; } break;
|
||||
case IR40_FLASH : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
|
||||
}
|
||||
lastValidCode = code;
|
||||
colorUpdated(2); //for notifier, IR is considered a button input
|
||||
}
|
||||
|
||||
void decodeIR44(uint32_t code)
|
||||
@ -290,20 +336,20 @@ void decodeIR44(uint32_t code)
|
||||
case IR44_COLDWHITE2 : {
|
||||
if (useRGBW) { colorFromUint32(COLOR2_COLDWHITE2); effectCurrent = 0; }
|
||||
else colorFromUint24(COLOR_COLDWHITE2); } break;
|
||||
case IR44_REDPLUS : relativeChange(&effectCurrent, 1); break;
|
||||
case IR44_REDPLUS : relativeChange(&effectCurrent, 1, 0, MODE_COUNT); break;
|
||||
case IR44_REDMINUS : relativeChange(&effectCurrent, -1, 0); break;
|
||||
case IR44_GREENPLUS : relativeChange(&effectPalette, 1); break;
|
||||
case IR44_GREENPLUS : relativeChange(&effectPalette, 1, 0, strip.getPaletteCount() -1); break;
|
||||
case IR44_GREENMINUS : relativeChange(&effectPalette, -1, 0); break;
|
||||
case IR44_BLUEPLUS : relativeChange(&effectIntensity, 10); break;
|
||||
case IR44_BLUEMINUS : relativeChange(&effectIntensity, -10, 5); break;
|
||||
case IR44_QUICK : relativeChange(&effectSpeed, 10); break;
|
||||
case IR44_SLOW : relativeChange(&effectSpeed, -10, 5); break;
|
||||
case IR44_DIY1 : if (!applyPreset(1)) effectCurrent = FX_MODE_STATIC; effectPalette = 0; break;
|
||||
case IR44_DIY2 : if (!applyPreset(2)) effectCurrent = FX_MODE_BREATH; effectPalette = 0; break;
|
||||
case IR44_DIY3 : if (!applyPreset(3)) effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; break;
|
||||
case IR44_DIY4 : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; break;
|
||||
case IR44_DIY5 : if (!applyPreset(5)) effectCurrent = FX_MODE_METEOR_SMOOTH; effectPalette = 0; break;
|
||||
case IR44_DIY6 : if (!applyPreset(6)) effectCurrent = FX_MODE_RAIN; effectPalette = 0; break;
|
||||
case IR44_BLUEPLUS : changeEffectIntensity( 16); break;
|
||||
case IR44_BLUEMINUS : changeEffectIntensity(-16); break;
|
||||
case IR44_QUICK : changeEffectSpeed( 16); break;
|
||||
case IR44_SLOW : changeEffectSpeed(-16); break;
|
||||
case IR44_DIY1 : if (!applyPreset(1)) { effectCurrent = FX_MODE_STATIC; effectPalette = 0; } break;
|
||||
case IR44_DIY2 : if (!applyPreset(2)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
|
||||
case IR44_DIY3 : if (!applyPreset(3)) { effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; } break;
|
||||
case IR44_DIY4 : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
|
||||
case IR44_DIY5 : if (!applyPreset(5)) { effectCurrent = FX_MODE_METEOR_SMOOTH; effectPalette = 0; } break;
|
||||
case IR44_DIY6 : if (!applyPreset(6)) { effectCurrent = FX_MODE_RAIN; effectPalette = 0; } break;
|
||||
case IR44_AUTO : effectCurrent = FX_MODE_STATIC; break;
|
||||
case IR44_FLASH : effectCurrent = FX_MODE_PALETTE; break;
|
||||
case IR44_JUMP3 : bri = 63; break;
|
||||
@ -312,7 +358,67 @@ void decodeIR44(uint32_t code)
|
||||
case IR44_FADE7 : bri = 255; break;
|
||||
}
|
||||
lastValidCode = code;
|
||||
colorUpdated(2); //for notifier, IR is considered a button input
|
||||
}
|
||||
|
||||
void decodeIR21(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR21_BRIGHTER: relativeChange(&bri, 10); break;
|
||||
case IR21_DARKER: relativeChange(&bri, -10, 5); break;
|
||||
case IR21_OFF: briLast = bri; bri = 0; break;
|
||||
case IR21_ON: bri = briLast; break;
|
||||
case IR21_RED: colorFromUint32(COLOR_RED); break;
|
||||
case IR21_REDDISH: colorFromUint32(COLOR_REDDISH); break;
|
||||
case IR21_ORANGE: colorFromUint32(COLOR_ORANGE); break;
|
||||
case IR21_YELLOWISH: colorFromUint32(COLOR_YELLOWISH); break;
|
||||
case IR21_GREEN: colorFromUint32(COLOR_GREEN); break;
|
||||
case IR21_GREENISH: colorFromUint32(COLOR_GREENISH); break;
|
||||
case IR21_TURQUOISE: colorFromUint32(COLOR_TURQUOISE); break;
|
||||
case IR21_CYAN: colorFromUint32(COLOR_CYAN); break;
|
||||
case IR21_BLUE: colorFromUint32(COLOR_BLUE); break;
|
||||
case IR21_DEEPBLUE: colorFromUint32(COLOR_DEEPBLUE); break;
|
||||
case IR21_PURPLE: colorFromUint32(COLOR_PURPLE); break;
|
||||
case IR21_PINK: colorFromUint32(COLOR_PINK); break;
|
||||
case IR21_WHITE: colorFromUint32(COLOR_WHITE); effectCurrent = 0; break;
|
||||
case IR21_FLASH: if (!applyPreset(1)) { effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; } break;
|
||||
case IR21_STROBE: if (!applyPreset(2)) { effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; } break;
|
||||
case IR21_FADE: if (!applyPreset(3)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
|
||||
case IR21_SMOOTH: if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
}
|
||||
|
||||
void decodeIR6(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR6_POWER: toggleOnOff(); break;
|
||||
case IR6_CHANNEL_UP: relativeChange(&bri, 10); break;
|
||||
case IR6_CHANNEL_DOWN: relativeChange(&bri, -10, 5); break;
|
||||
case IR6_VOLUME_UP: relativeChange(&effectCurrent, 1, 0, MODE_COUNT); break; // next effect
|
||||
case IR6_VOLUME_DOWN: // next palette
|
||||
relativeChange(&effectPalette, 1, 0, strip.getPaletteCount() -1);
|
||||
switch(lastIR6ColourIdx) {
|
||||
case 0: colorFromUint32(COLOR_RED); break;
|
||||
case 1: colorFromUint32(COLOR_REDDISH); break;
|
||||
case 2: colorFromUint32(COLOR_ORANGE); break;
|
||||
case 3: colorFromUint32(COLOR_YELLOWISH); break;
|
||||
case 4: colorFromUint32(COLOR_GREEN); break;
|
||||
case 5: colorFromUint32(COLOR_GREENISH); break;
|
||||
case 6: colorFromUint32(COLOR_TURQUOISE); break;
|
||||
case 7: colorFromUint32(COLOR_CYAN); break;
|
||||
case 8: colorFromUint32(COLOR_BLUE); break;
|
||||
case 9: colorFromUint32(COLOR_DEEPBLUE); break;
|
||||
case 10:colorFromUint32(COLOR_PURPLE); break;
|
||||
case 11:colorFromUint32(COLOR_PINK); break;
|
||||
case 12:colorFromUint32(COLOR_WHITE); break;
|
||||
default: break;
|
||||
}
|
||||
lastIR6ColourIdx++;
|
||||
if(lastIR6ColourIdx > 12) lastIR6ColourIdx = 0; break;
|
||||
case IR6_MUTE: effectCurrent = 0; effectPalette = 0; colorFromUint32(COLOR_WHITE); bri=255; break;
|
||||
}
|
||||
lastValidCode = code;
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,16 @@
|
||||
#define IRCUSTOM_ONOFF 0xA55AEA15 //Pioneer RC-975R "+FAV" button (example)
|
||||
#define IRCUSTOM_MACRO1 0xFFFFFFFF //placeholder, will never be checked for
|
||||
|
||||
// Default IR codes for 6-key learning remote https://www.aliexpress.com/item/4000307837886.html
|
||||
// This cheap remote has the advantage of being more powerful (longer range) than cheap credit-card remotes
|
||||
#define IR6_POWER 0xFF0FF0
|
||||
#define IR6_CHANNEL_UP 0xFF8F70
|
||||
#define IR6_CHANNEL_DOWN 0xFF4FB0
|
||||
#define IR6_VOLUME_UP 0xFFCF30
|
||||
#define IR6_VOLUME_DOWN 0xFF2FD0
|
||||
#define IR6_MUTE 0xFFAF50
|
||||
|
||||
|
||||
//Infrared codes for 24-key remote from http://woodsgood.ca/projects/2015/02/13/rgb-led-strip-controllers-ir-codes/
|
||||
#define IR24_BRIGHTER 0xF700FF
|
||||
#define IR24_DARKER 0xF7807F
|
||||
@ -170,6 +180,29 @@
|
||||
#define IR44_FADE3 0xFF609F //
|
||||
#define IR44_FADE7 0xFFE01F //
|
||||
|
||||
//Infrared codes for 21-key remote https://images-na.ssl-images-amazon.com/images/I/51NMA0XucnL.jpg
|
||||
#define IR21_BRIGHTER 0xFFE01F
|
||||
#define IR21_DARKER 0xFFA857
|
||||
#define IR21_OFF 0xFF629D
|
||||
#define IR21_ON 0xFFA25D
|
||||
#define IR21_RED 0xFF6897
|
||||
#define IR21_REDDISH 0xFF30CF
|
||||
#define IR21_ORANGE 0xFF10EF
|
||||
#define IR21_YELLOWISH 0xFF42BD
|
||||
#define IR21_GREEN 0xFF9867
|
||||
#define IR21_GREENISH 0xFF18E7
|
||||
#define IR21_TURQUOISE 0xFF38C7
|
||||
#define IR21_CYAN 0xFF4AB5
|
||||
#define IR21_BLUE 0xFFB04F
|
||||
#define IR21_DEEPBLUE 0xFF7A85
|
||||
#define IR21_PURPLE 0xFF5AA5
|
||||
#define IR21_PINK 0xFF52AD
|
||||
#define IR21_WHITE 0xFF906F
|
||||
#define IR21_FLASH 0xFFE21D
|
||||
#define IR21_STROBE 0xFF22DD
|
||||
#define IR21_FADE 0xFF02FD
|
||||
#define IR21_SMOOTH 0xFFC23D
|
||||
|
||||
#define COLOR_RED 0xFF0000
|
||||
#define COLOR_REDDISH 0xFF7800
|
||||
#define COLOR_ORANGE 0xFFA000
|
||||
|
@ -1,3 +1,5 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* JSON API (De)serialization
|
||||
*/
|
||||
@ -15,7 +17,19 @@ void deserializeSegment(JsonObject elem, byte it)
|
||||
uint16_t len = elem["len"];
|
||||
stop = (len > 0) ? start + len : seg.stop;
|
||||
}
|
||||
strip.setSegment(id, start, stop);
|
||||
uint16_t grp = elem["grp"] | seg.grouping;
|
||||
uint16_t spc = elem["spc"] | seg.spacing;
|
||||
strip.setSegment(id, start, stop, grp, spc);
|
||||
|
||||
int segbri = elem["bri"] | -1;
|
||||
if (segbri == 0) {
|
||||
seg.setOption(SEG_OPTION_ON, 0);
|
||||
} else if (segbri > 0) {
|
||||
seg.opacity = segbri;
|
||||
seg.setOption(SEG_OPTION_ON, 1);
|
||||
}
|
||||
|
||||
seg.setOption(SEG_OPTION_ON, elem["on"] | seg.getOption(SEG_OPTION_ON));
|
||||
|
||||
JsonArray colarr = elem["col"];
|
||||
if (!colarr.isNull())
|
||||
@ -29,21 +43,23 @@ void deserializeSegment(JsonObject elem, byte it)
|
||||
{
|
||||
int rgbw[] = {0,0,0,0};
|
||||
byte cp = copyArray(colX, rgbw);
|
||||
seg.colors[i] = ((rgbw[3] << 24) | ((rgbw[0]&0xFF) << 16) | ((rgbw[1]&0xFF) << 8) | ((rgbw[2]&0xFF)));
|
||||
|
||||
if (cp == 1 && rgbw[0] == 0) seg.colors[i] = 0;
|
||||
if (id == strip.getMainSegmentId()) //temporary
|
||||
if (id == strip.getMainSegmentId() && i < 2) //temporary, to make transition work on main segment
|
||||
{
|
||||
if (i == 0) {col[0] = rgbw[0]; col[1] = rgbw[1]; col[2] = rgbw[2]; col[3] = rgbw[3];}
|
||||
if (i == 1) {colSec[0] = rgbw[0]; colSec[1] = rgbw[1]; colSec[2] = rgbw[2]; colSec[3] = rgbw[3];}
|
||||
} else {
|
||||
seg.colors[i] = ((rgbw[3] << 24) | ((rgbw[0]&0xFF) << 16) | ((rgbw[1]&0xFF) << 8) | ((rgbw[2]&0xFF)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal);
|
||||
seg.setOption(0, elem["sel"] | seg.getOption(0)); //selected
|
||||
seg.setOption(1, elem["rev"] | seg.getOption(1)); //reverse
|
||||
//int cln = seg_0["cln"];
|
||||
seg.setOption(SEG_OPTION_SELECTED, elem["sel"] | seg.getOption(SEG_OPTION_SELECTED));
|
||||
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
|
||||
|
||||
//temporary, strip object gets updated via colorUpdated()
|
||||
if (id == strip.getMainSegmentId()) {
|
||||
effectCurrent = elem["fx"] | effectCurrent;
|
||||
@ -65,6 +81,9 @@ bool deserializeState(JsonObject root)
|
||||
strip.applyToAllSelected = false;
|
||||
bool stateResponse = root["v"] | false;
|
||||
|
||||
int ps = root["ps"] | -1;
|
||||
if (ps >= 0) applyPreset(ps);
|
||||
|
||||
bri = root["bri"] | bri;
|
||||
|
||||
bool on = root["on"] | (bri > 0);
|
||||
@ -85,9 +104,6 @@ bool deserializeState(JsonObject root)
|
||||
jsonTransitionOnce = true;
|
||||
}
|
||||
|
||||
int ps = root["ps"] | -1;
|
||||
if (ps >= 0) applyPreset(ps);
|
||||
|
||||
int cy = root["pl"] | -2;
|
||||
if (cy > -2) presetCyclingEnabled = (cy >= 0);
|
||||
JsonObject ccnf = root["ccnf"];
|
||||
@ -113,6 +129,10 @@ bool deserializeState(JsonObject root)
|
||||
|
||||
int timein = root["time"] | -1;
|
||||
if (timein != -1) setTime(timein);
|
||||
doReboot = root["rb"] | doReboot;
|
||||
|
||||
realtimeOverride = root["lor"] | realtimeOverride;
|
||||
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
|
||||
|
||||
byte prevMain = strip.getMainSegmentId();
|
||||
strip.mainSegment = root["mainseg"] | prevMain;
|
||||
@ -152,10 +172,13 @@ bool deserializeState(JsonObject root)
|
||||
}
|
||||
}
|
||||
|
||||
colorUpdated(noNotification ? 5:1);
|
||||
colorUpdated(noNotification ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
|
||||
//write presets to flash directly?
|
||||
bool persistSaves = !(root["np"] | false);
|
||||
|
||||
ps = root["psave"] | -1;
|
||||
if (ps >= 0) savePreset(ps);
|
||||
if (ps >= 0) savePreset(ps, persistSaves);
|
||||
|
||||
return stateResponse;
|
||||
}
|
||||
@ -166,17 +189,31 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id)
|
||||
root["start"] = seg.start;
|
||||
root["stop"] = seg.stop;
|
||||
root["len"] = seg.stop - seg.start;
|
||||
root["grp"] = seg.grouping;
|
||||
root["spc"] = seg.spacing;
|
||||
root["on"] = seg.getOption(SEG_OPTION_ON);
|
||||
byte segbri = seg.opacity;
|
||||
root["bri"] = (segbri) ? segbri : 255;
|
||||
|
||||
JsonArray colarr = root.createNestedArray("col");
|
||||
|
||||
for (uint8_t i = 0; i < 3; i++)
|
||||
{
|
||||
JsonArray colX = colarr.createNestedArray();
|
||||
colX.add((seg.colors[i] >> 16) & 0xFF);
|
||||
colX.add((seg.colors[i] >> 8) & 0xFF);
|
||||
colX.add((seg.colors[i]) & 0xFF);
|
||||
if (useRGBW)
|
||||
colX.add((seg.colors[i] >> 24) & 0xFF);
|
||||
if (id == strip.getMainSegmentId() && i < 2) //temporary, to make transition work on main segment
|
||||
{
|
||||
if (i == 0) {
|
||||
colX.add(col[0]); colX.add(col[1]); colX.add(col[2]); if (useRGBW) colX.add(col[3]);
|
||||
} else {
|
||||
colX.add(colSec[0]); colX.add(colSec[1]); colX.add(colSec[2]); if (useRGBW) colX.add(colSec[3]);
|
||||
}
|
||||
} else {
|
||||
colX.add((seg.colors[i] >> 16) & 0xFF);
|
||||
colX.add((seg.colors[i] >> 8) & 0xFF);
|
||||
colX.add((seg.colors[i]) & 0xFF);
|
||||
if (useRGBW)
|
||||
colX.add((seg.colors[i] >> 24) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
root["fx"] = seg.mode;
|
||||
@ -184,7 +221,7 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id)
|
||||
root["ix"] = seg.intensity;
|
||||
root["pal"] = seg.palette;
|
||||
root["sel"] = seg.isSelected();
|
||||
root["rev"] = seg.getOption(1);
|
||||
root["rev"] = seg.getOption(SEG_OPTION_REVERSED);
|
||||
}
|
||||
|
||||
|
||||
@ -216,6 +253,8 @@ void serializeState(JsonObject root)
|
||||
udpn["send"] = notifyDirect;
|
||||
udpn["recv"] = receiveNotifications;
|
||||
|
||||
root["lor"] = realtimeOverride;
|
||||
|
||||
root["mainseg"] = strip.getMainSegmentId();
|
||||
|
||||
JsonArray seg = root.createNestedArray("seg");
|
||||
@ -230,15 +269,36 @@ void serializeState(JsonObject root)
|
||||
}
|
||||
}
|
||||
|
||||
//by https://github.com/tzapu/WiFiManager/blob/master/WiFiManager.cpp
|
||||
int getSignalQuality(int rssi)
|
||||
{
|
||||
int quality = 0;
|
||||
|
||||
if (rssi <= -100)
|
||||
{
|
||||
quality = 0;
|
||||
}
|
||||
else if (rssi >= -50)
|
||||
{
|
||||
quality = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
quality = 2 * (rssi + 100);
|
||||
}
|
||||
return quality;
|
||||
}
|
||||
|
||||
void serializeInfo(JsonObject root)
|
||||
{
|
||||
root["ver"] = versionString;
|
||||
root["vid"] = VERSION;
|
||||
//root["cn"] = WLED_CODENAME;
|
||||
|
||||
JsonObject leds = root.createNestedObject("leds");
|
||||
leds["count"] = ledCount;
|
||||
leds["rgbw"] = useRGBW;
|
||||
leds["wv"] = useRGBW && !autoRGBtoRGBW; //should a white channel slider be displayed?
|
||||
leds["wv"] = useRGBW && (strip.rgbwMode == RGBW_MODE_MANUAL_ONLY || strip.rgbwMode == RGBW_MODE_DUAL); //should a white channel slider be displayed?
|
||||
JsonArray leds_pin = leds.createNestedArray("pin");
|
||||
leds_pin.add(LEDPIN);
|
||||
|
||||
@ -251,7 +311,25 @@ void serializeInfo(JsonObject root)
|
||||
|
||||
root["name"] = serverDescription;
|
||||
root["udpport"] = udpPort;
|
||||
root["live"] = realtimeActive;
|
||||
root["live"] = (bool)realtimeMode;
|
||||
|
||||
switch (realtimeMode) {
|
||||
case REALTIME_MODE_INACTIVE: root["lm"] = ""; break;
|
||||
case REALTIME_MODE_GENERIC: root["lm"] = ""; break;
|
||||
case REALTIME_MODE_UDP: root["lm"] = "UDP"; break;
|
||||
case REALTIME_MODE_HYPERION: root["lm"] = "Hyperion"; break;
|
||||
case REALTIME_MODE_E131: root["lm"] = "E1.31"; break;
|
||||
case REALTIME_MODE_ADALIGHT: root["lm"] = F("USB Adalight");
|
||||
case REALTIME_MODE_ARTNET: root["lm"] = "Art-Net"; break;
|
||||
}
|
||||
|
||||
if (realtimeIP[0] == 0)
|
||||
{
|
||||
root["lip"] = "";
|
||||
} else {
|
||||
root["lip"] = realtimeIP.toString();
|
||||
}
|
||||
|
||||
root["fxcount"] = strip.getModeCount();
|
||||
root["palcount"] = strip.getPaletteCount();
|
||||
|
||||
@ -263,19 +341,30 @@ void serializeInfo(JsonObject root)
|
||||
wifi_info["channel"] = WiFi.channel();
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifdef WLED_DEBUG
|
||||
wifi_info["txPower"] = (int) WiFi.getTxPower();
|
||||
wifi_info["sleep"] = (bool) WiFi.getSleep();
|
||||
#endif
|
||||
root["arch"] = "esp32";
|
||||
root["core"] = ESP.getSdkVersion();
|
||||
//root["maxalloc"] = ESP.getMaxAllocHeap();
|
||||
#ifdef WLED_DEBUG
|
||||
root["resetReason0"] = (int)rtc_get_reset_reason(0);
|
||||
root["resetReason1"] = (int)rtc_get_reset_reason(1);
|
||||
#endif
|
||||
root["lwip"] = 0;
|
||||
#else
|
||||
root["arch"] = "esp8266";
|
||||
root["core"] = ESP.getCoreVersion();
|
||||
//root["maxalloc"] = ESP.getMaxFreeBlockSize();
|
||||
#ifdef WLED_DEBUG
|
||||
root["resetReason"] = (int)ESP.getResetInfoPtr()->reason;
|
||||
#endif
|
||||
root["lwip"] = LWIP_VERSION_MAJOR;
|
||||
#endif
|
||||
|
||||
root["freeheap"] = ESP.getFreeHeap();
|
||||
root["uptime"] = millis()/1000;
|
||||
root["uptime"] = millis()/1000 + rolloverMillis*4294967;
|
||||
|
||||
byte os = 0;
|
||||
#ifdef WLED_DEBUG
|
||||
@ -305,8 +394,7 @@ void serializeInfo(JsonObject root)
|
||||
root["opt"] = os;
|
||||
|
||||
root["brand"] = "WLED";
|
||||
root["product"] = "DIY light";
|
||||
root["btype"] = "src";
|
||||
root["product"] = "FOSS";
|
||||
root["mac"] = escapedMac;
|
||||
}
|
||||
|
||||
@ -316,6 +404,7 @@ void serveJson(AsyncWebServerRequest* request)
|
||||
const String& url = request->url();
|
||||
if (url.indexOf("state") > 0) subJson = 1;
|
||||
else if (url.indexOf("info") > 0) subJson = 2;
|
||||
else if (url.indexOf("si") > 0) subJson = 3;
|
||||
else if (url.indexOf("live") > 0) {
|
||||
serveLiveLeds(request);
|
||||
return;
|
||||
@ -329,7 +418,7 @@ void serveJson(AsyncWebServerRequest* request)
|
||||
return;
|
||||
}
|
||||
else if (url.length() > 6) { //not just /json
|
||||
request->send( 501, "application/json", "{\"error\":\"Not implemented\"}");
|
||||
request->send( 501, "application/json", F("{\"error\":\"Not implemented\"}"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -347,8 +436,11 @@ void serveJson(AsyncWebServerRequest* request)
|
||||
serializeState(state);
|
||||
JsonObject info = doc.createNestedObject("info");
|
||||
serializeInfo(info);
|
||||
doc["effects"] = serialized((const __FlashStringHelper*)JSON_mode_names);
|
||||
doc["palettes"] = serialized((const __FlashStringHelper*)JSON_palette_names);
|
||||
if (subJson != 3)
|
||||
{
|
||||
doc["effects"] = serialized((const __FlashStringHelper*)JSON_mode_names);
|
||||
doc["palettes"] = serialized((const __FlashStringHelper*)JSON_palette_names);
|
||||
}
|
||||
}
|
||||
|
||||
response->setLength();
|
||||
@ -359,8 +451,8 @@ void serveJson(AsyncWebServerRequest* request)
|
||||
|
||||
void serveLiveLeds(AsyncWebServerRequest* request)
|
||||
{
|
||||
byte used = strip.getUsableCount();
|
||||
byte n = (used -1) /MAX_LIVE_LEDS +1; //only serve every n'th LED if count over MAX_LIVE_LEDS
|
||||
uint16_t used = ledCount;
|
||||
uint16_t n = (used -1) /MAX_LIVE_LEDS +1; //only serve every n'th LED if count over MAX_LIVE_LEDS
|
||||
char buffer[2000] = "{\"leds\":[";
|
||||
olen = 9;
|
||||
obuf = buffer;
|
@ -1,6 +1,9 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* LED methods
|
||||
*/
|
||||
|
||||
void setValuesFromMainSeg()
|
||||
{
|
||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
@ -33,21 +36,14 @@ void toggleOnOff()
|
||||
|
||||
|
||||
void setAllLeds() {
|
||||
if (!realtimeActive || !arlsForceMaxBri)
|
||||
if (!realtimeMode || !arlsForceMaxBri)
|
||||
{
|
||||
double d = briT*briMultiplier;
|
||||
int val = d/100;
|
||||
if (val > 255) val = 255;
|
||||
strip.setBrightness(val);
|
||||
}
|
||||
if (!enableSecTransition)
|
||||
{
|
||||
for (byte i = 0; i<4; i++)
|
||||
{
|
||||
colSecT[i] = colSec[i];
|
||||
}
|
||||
}
|
||||
if (useRGBW && autoRGBtoRGBW)
|
||||
if (useRGBW && strip.rgbwMode == RGBW_MODE_LEGACY)
|
||||
{
|
||||
colorRGBtoRGBW(colT);
|
||||
colorRGBtoRGBW(colSecT);
|
||||
@ -57,7 +53,7 @@ void setAllLeds() {
|
||||
}
|
||||
|
||||
|
||||
void setLedsStandard()
|
||||
void setLedsStandard(bool justColors)
|
||||
{
|
||||
for (byte i=0; i<4; i++)
|
||||
{
|
||||
@ -66,6 +62,7 @@ void setLedsStandard()
|
||||
colSecOld[i] = colSec[i];
|
||||
colSecT[i] = colSec[i];
|
||||
}
|
||||
if (justColors) return;
|
||||
briOld = bri;
|
||||
briT = bri;
|
||||
setAllLeds();
|
||||
@ -88,28 +85,36 @@ void colorUpdated(int callMode)
|
||||
{
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
if (callMode != 0 && callMode != 1 && callMode != 5) strip.applyToAllSelected = true; //if not from JSON api, which directly sets segments
|
||||
if (callMode != NOTIFIER_CALL_MODE_INIT &&
|
||||
callMode != NOTIFIER_CALL_MODE_DIRECT_CHANGE &&
|
||||
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY) strip.applyToAllSelected = true; //if not from JSON api, which directly sets segments
|
||||
|
||||
bool fxChanged = strip.setEffectConfig(effectCurrent, effectSpeed, effectIntensity, effectPalette);
|
||||
if (!colorChanged())
|
||||
bool colChanged = colorChanged();
|
||||
|
||||
if (fxChanged || colChanged)
|
||||
{
|
||||
if (nightlightActive && !nightlightActiveOld && callMode != 3 && callMode != 5)
|
||||
if (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
|
||||
if (isPreset) {isPreset = false;}
|
||||
else {currentPreset = -1;}
|
||||
|
||||
notify(callMode);
|
||||
|
||||
//set flag to update blynk and mqtt
|
||||
if (callMode != NOTIFIER_CALL_MODE_PRESET_CYCLE) interfaceUpdateCallMode = callMode;
|
||||
} else {
|
||||
if (nightlightActive && !nightlightActiveOld &&
|
||||
callMode != NOTIFIER_CALL_MODE_NOTIFICATION &&
|
||||
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY)
|
||||
{
|
||||
notify(4); interfaceUpdateCallMode = 4; return;
|
||||
notify(NOTIFIER_CALL_MODE_NIGHTLIGHT);
|
||||
interfaceUpdateCallMode = NOTIFIER_CALL_MODE_NIGHTLIGHT;
|
||||
}
|
||||
else if (fxChanged) {
|
||||
notify(6);
|
||||
if (callMode != 8) interfaceUpdateCallMode = 6;
|
||||
if (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
|
||||
if (isPreset) {isPreset = false;}
|
||||
else {currentPreset = -1;}
|
||||
}
|
||||
return; //no change
|
||||
}
|
||||
if (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
|
||||
if (isPreset) {isPreset = false;}
|
||||
else {currentPreset = -1;}
|
||||
if (callMode != 5 && nightlightActive && nightlightFade)
|
||||
|
||||
if (!colChanged) return; //following code is for e.g. initiating transitions
|
||||
|
||||
if (callMode != NOTIFIER_CALL_MODE_NO_NOTIFY && nightlightActive && nightlightFade)
|
||||
{
|
||||
briNlT = bri;
|
||||
nightlightDelayMs -= (millis() - nightlightStartTime);
|
||||
@ -120,16 +125,19 @@ void colorUpdated(int callMode)
|
||||
colIT[i] = col[i];
|
||||
colSecIT[i] = colSec[i];
|
||||
}
|
||||
if (briT == 0 && callMode != 3) resetTimebase();
|
||||
if (briT == 0)
|
||||
{
|
||||
setLedsStandard(true); //do not color transition if starting from off
|
||||
if (callMode != NOTIFIER_CALL_MODE_NOTIFICATION) resetTimebase(); //effect start from beginning
|
||||
}
|
||||
|
||||
briIT = bri;
|
||||
if (bri > 0) briLast = bri;
|
||||
|
||||
notify(callMode);
|
||||
|
||||
if (fadeTransition)
|
||||
{
|
||||
//set correct delay if not using notification delay
|
||||
if (callMode != 3 && !jsonTransitionOnce) transitionDelayTemp = transitionDelay;
|
||||
if (callMode != NOTIFIER_CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay;
|
||||
jsonTransitionOnce = false;
|
||||
if (transitionDelayTemp == 0) {setLedsStandard(); strip.trigger(); return;}
|
||||
|
||||
@ -151,22 +159,19 @@ void colorUpdated(int callMode)
|
||||
setLedsStandard();
|
||||
strip.trigger();
|
||||
}
|
||||
|
||||
if (callMode == 8) return;
|
||||
//set flag to update blynk and mqtt
|
||||
interfaceUpdateCallMode = callMode;
|
||||
}
|
||||
|
||||
|
||||
void updateInterfaces(uint8_t callMode)
|
||||
{
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
if (espalexaDevice != nullptr && callMode != 10) {
|
||||
if (espalexaDevice != nullptr && callMode != NOTIFIER_CALL_MODE_ALEXA) {
|
||||
espalexaDevice->setValue(bri);
|
||||
espalexaDevice->setColor(col[0], col[1], col[2]);
|
||||
}
|
||||
#endif
|
||||
if (callMode != 9 && callMode != 5) updateBlynk();
|
||||
if (callMode != NOTIFIER_CALL_MODE_BLYNK &&
|
||||
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY) updateBlynk();
|
||||
doPublishMqtt = true;
|
||||
lastInterfaceUpdate = millis();
|
||||
}
|
||||
@ -217,17 +222,17 @@ void handleNightlight()
|
||||
nightlightDelayMs = (int)(nightlightDelayMins*60000);
|
||||
nightlightActiveOld = true;
|
||||
briNlT = bri;
|
||||
for (byte i=0; i<4; i++) colNlT[i] = col[i]; // remember starting color
|
||||
for (byte i=0; i<4; i++) colNlT[i] = col[i]; // remember starting color
|
||||
}
|
||||
float nper = (millis() - nightlightStartTime)/((float)nightlightDelayMs);
|
||||
if (nightlightFade)
|
||||
{
|
||||
bri = briNlT + ((nightlightTargetBri - briNlT)*nper);
|
||||
if (nightlightColorFade) // color fading only is enabled with "NF=2"
|
||||
if (nightlightColorFade) // color fading only is enabled with "NF=2"
|
||||
{
|
||||
for (byte i=0; i<4; i++) col[i] = colNlT[i]+ ((colSec[i] - colNlT[i])*nper); // fading from actual color to secondary color
|
||||
for (byte i=0; i<4; i++) col[i] = colNlT[i]+ ((colSec[i] - colNlT[i])*nper); // fading from actual color to secondary color
|
||||
}
|
||||
colorUpdated(5);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NO_NOTIFY);
|
||||
}
|
||||
if (nper >= 1)
|
||||
{
|
||||
@ -235,7 +240,7 @@ void handleNightlight()
|
||||
if (!nightlightFade)
|
||||
{
|
||||
bri = nightlightTargetBri;
|
||||
colorUpdated(5);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NO_NOTIFY);
|
||||
}
|
||||
updateBlynk();
|
||||
if (bri == 0) briLast = briNlT;
|
||||
@ -248,10 +253,10 @@ void handleNightlight()
|
||||
//also handle preset cycle here
|
||||
if (presetCyclingEnabled && (millis() - presetCycledTime > presetCycleTime))
|
||||
{
|
||||
applyPreset(presetCycCurr,presetApplyBri,presetApplyCol,presetApplyFx);
|
||||
applyPreset(presetCycCurr,presetApplyBri);
|
||||
presetCycCurr++; if (presetCycCurr > presetCycleMax) presetCycCurr = presetCycleMin;
|
||||
if (presetCycCurr > 25) presetCycCurr = 1;
|
||||
colorUpdated(8);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_PRESET_CYCLE);
|
||||
presetCycledTime = millis();
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* MQTT communication protocol for home automation
|
||||
*/
|
||||
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
#define MQTT_KEEP_ALIVE_TIME 60 // contact the MQTT broker every 60 seconds
|
||||
|
||||
void parseMQTTBriPayload(char* payload)
|
||||
{
|
||||
@ -12,7 +15,7 @@ void parseMQTTBriPayload(char* payload)
|
||||
uint8_t in = strtoul(payload, NULL, 10);
|
||||
if (in == 0 && bri > 0) briLast = bri;
|
||||
bri = in;
|
||||
colorUpdated(1);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +63,7 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
|
||||
if (strstr(topic, "/col"))
|
||||
{
|
||||
colorFromDecOrHexString(col, (char*)payload);
|
||||
colorUpdated(1);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
} else if (strstr(topic, "/api"))
|
||||
{
|
||||
String apireq = "win&";
|
||||
@ -129,6 +132,7 @@ bool initMqtt()
|
||||
strcpy(mqttStatusTopic, mqttDeviceTopic);
|
||||
strcat(mqttStatusTopic, "/status");
|
||||
mqtt->setWill(mqttStatusTopic, 0, true, "offline");
|
||||
mqtt->setKeepAlive(MQTT_KEEP_ALIVE_TIME);
|
||||
mqtt->connect();
|
||||
return true;
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
#include "src/dependencies/timezone/Timezone.h"
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Acquires time from NTP server
|
||||
*/
|
||||
@ -57,7 +60,13 @@ Timezone tzNK(NKST, NKST);
|
||||
TimeChangeRule IST = {Last, Sun, Mar, 1, 330}; // India Standard Time = UTC + 5.5 hours
|
||||
Timezone tzIndia(IST, IST);
|
||||
|
||||
Timezone* timezones[] = {&tzUTC, &tzUK, &tzEUCentral, &tzEUEastern, &tzUSEastern, &tzUSCentral, &tzUSMountain, &tzUSArizona, &tzUSPacific, &tzChina, &tzJapan, &tzAUEastern, &tzNZ, &tzNK, &tzIndia, &tzCASaskatchewan};
|
||||
TimeChangeRule ACST = {First, Sun, Apr, 3, 570}; //Australian Central Standard = UTC + 9.5 hours
|
||||
TimeChangeRule ACDT = {First, Sun, Oct, 2, 630}; //Australian Central Daylight = UTC + 10.5 hours
|
||||
Timezone tzAUNorthern(ACST, ACST);
|
||||
Timezone tzAUSouthern(ACDT, ACST);
|
||||
|
||||
// Pick your timezone from here.
|
||||
Timezone* timezones[] = {&tzUTC, &tzUK, &tzEUCentral, &tzEUEastern, &tzUSEastern, &tzUSCentral, &tzUSMountain, &tzUSArizona, &tzUSPacific, &tzChina, &tzJapan, &tzAUEastern, &tzNZ, &tzNK, &tzIndia, &tzCASaskatchewan, &tzAUNorthern, &tzAUSouthern};
|
||||
|
||||
void handleNetworkTime()
|
||||
{
|
||||
@ -164,9 +173,9 @@ void setCountdown()
|
||||
bool checkCountdown()
|
||||
{
|
||||
unsigned long n = now();
|
||||
local = countdownTime - n;
|
||||
if (countdownMode) local = countdownTime - n + utcOffsetSecs;
|
||||
if (n > countdownTime) {
|
||||
local = n - countdownTime;
|
||||
if (countdownMode) local = n - countdownTime + utcOffsetSecs;
|
||||
if (!countdownOverTriggered)
|
||||
{
|
||||
if (macroCountdown != 0) applyMacro(macroCountdown);
|
@ -1,6 +1,142 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Used to draw clock overlays over the strip
|
||||
*/
|
||||
|
||||
void initCronixie()
|
||||
{
|
||||
if (overlayCurrent == 3 && !cronixieInit)
|
||||
{
|
||||
setCronixie();
|
||||
strip.getSegment(0).grouping = 10; //10 LEDs per digit
|
||||
cronixieInit = true;
|
||||
} else if (cronixieInit && overlayCurrent != 3)
|
||||
{
|
||||
strip.getSegment(0).grouping = 1;
|
||||
cronixieInit = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleOverlays()
|
||||
{
|
||||
if (millis() - overlayRefreshedTime > overlayRefreshMs)
|
||||
{
|
||||
initCronixie();
|
||||
updateLocalTime();
|
||||
checkTimers();
|
||||
checkCountdown();
|
||||
if (overlayCurrent == 3) _overlayCronixie();//Diamex cronixie clock kit
|
||||
overlayRefreshedTime = millis();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _overlayAnalogClock()
|
||||
{
|
||||
int overlaySize = overlayMax - overlayMin +1;
|
||||
if (countdownMode)
|
||||
{
|
||||
_overlayAnalogCountdown(); return;
|
||||
}
|
||||
double hourP = ((double)(hour(local)%12))/12;
|
||||
double minuteP = ((double)minute(local))/60;
|
||||
hourP = hourP + minuteP/12;
|
||||
double secondP = ((double)second(local))/60;
|
||||
int hourPixel = floor(analogClock12pixel + overlaySize*hourP);
|
||||
if (hourPixel > overlayMax) hourPixel = overlayMin -1 + hourPixel - overlayMax;
|
||||
int minutePixel = floor(analogClock12pixel + overlaySize*minuteP);
|
||||
if (minutePixel > overlayMax) minutePixel = overlayMin -1 + minutePixel - overlayMax;
|
||||
int secondPixel = floor(analogClock12pixel + overlaySize*secondP);
|
||||
if (secondPixel > overlayMax) secondPixel = overlayMin -1 + secondPixel - overlayMax;
|
||||
if (analogClockSecondsTrail)
|
||||
{
|
||||
if (secondPixel < analogClock12pixel)
|
||||
{
|
||||
strip.setRange(analogClock12pixel, overlayMax, 0xFF0000);
|
||||
strip.setRange(overlayMin, secondPixel, 0xFF0000);
|
||||
} else
|
||||
{
|
||||
strip.setRange(analogClock12pixel, secondPixel, 0xFF0000);
|
||||
}
|
||||
}
|
||||
if (analogClock5MinuteMarks)
|
||||
{
|
||||
int pix;
|
||||
for (int i = 0; i <= 12; i++)
|
||||
{
|
||||
pix = analogClock12pixel + round((overlaySize / 12.0) *i);
|
||||
if (pix > overlayMax) pix -= overlaySize;
|
||||
strip.setPixelColor(pix, 0x00FFAA);
|
||||
}
|
||||
}
|
||||
if (!analogClockSecondsTrail) strip.setPixelColor(secondPixel, 0xFF0000);
|
||||
strip.setPixelColor(minutePixel, 0x00FF00);
|
||||
strip.setPixelColor(hourPixel, 0x0000FF);
|
||||
overlayRefreshMs = 998;
|
||||
}
|
||||
|
||||
|
||||
void _overlayAnalogCountdown()
|
||||
{
|
||||
if (now() < countdownTime)
|
||||
{
|
||||
long diff = countdownTime - now();
|
||||
double pval = 60;
|
||||
if (diff > 31557600L) //display in years if more than 365 days
|
||||
{
|
||||
pval = 315576000L; //10 years
|
||||
} else if (diff > 2592000L) //display in months if more than a month
|
||||
{
|
||||
pval = 31557600L; //1 year
|
||||
} else if (diff > 604800) //display in weeks if more than a week
|
||||
{
|
||||
pval = 2592000L; //1 month
|
||||
} else if (diff > 86400) //display in days if more than 24 hours
|
||||
{
|
||||
pval = 604800; //1 week
|
||||
} else if (diff > 3600) //display in hours if more than 60 minutes
|
||||
{
|
||||
pval = 86400; //1 day
|
||||
} else if (diff > 60) //display in minutes if more than 60 seconds
|
||||
{
|
||||
pval = 3600; //1 hour
|
||||
}
|
||||
int overlaySize = overlayMax - overlayMin +1;
|
||||
double perc = (pval-(double)diff)/pval;
|
||||
if (perc > 1.0) perc = 1.0;
|
||||
byte pixelCnt = perc*overlaySize;
|
||||
if (analogClock12pixel + pixelCnt > overlayMax)
|
||||
{
|
||||
strip.setRange(analogClock12pixel, overlayMax, ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
|
||||
strip.setRange(overlayMin, overlayMin +pixelCnt -(1+ overlayMax -analogClock12pixel), ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
|
||||
} else
|
||||
{
|
||||
strip.setRange(analogClock12pixel, analogClock12pixel + pixelCnt, ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
|
||||
}
|
||||
}
|
||||
overlayRefreshMs = 998;
|
||||
}
|
||||
|
||||
|
||||
void handleOverlayDraw() {
|
||||
if (!overlayCurrent) return;
|
||||
switch (overlayCurrent)
|
||||
{
|
||||
case 1: _overlayAnalogClock(); break;
|
||||
case 3: _drawOverlayCronixie(); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Support for the Cronixie clock
|
||||
*/
|
||||
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
byte _digitOut[6] = {10,10,10,10,10,10};
|
||||
|
||||
byte getSameCodeLength(char code, int index, char const cronixieDisplay[])
|
||||
{
|
||||
byte counter = 0;
|
||||
@ -19,7 +155,6 @@ byte getSameCodeLength(char code, int index, char const cronixieDisplay[])
|
||||
|
||||
void setCronixie()
|
||||
{
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
/*
|
||||
* digit purpose index
|
||||
* 0-9 | 0-9 (incl. random)
|
||||
@ -97,8 +232,8 @@ void setCronixie()
|
||||
case '-': dP[i] = 11; break;
|
||||
case 'r': dP[i] = random(1,7); break; //random btw. 1-6
|
||||
case 'R': dP[i] = random(0,10); break; //random btw. 0-9
|
||||
case 't': break; //Test upw.
|
||||
case 'T': break; //Test dnw.
|
||||
//case 't': break; //Test upw.
|
||||
//case 'T': break; //Test dnw.
|
||||
case 'b': dP[i] = 14 + getSameCodeLength('b',i,cronixieDisplay); i = i+dP[i]-14; break;
|
||||
case 'B': dP[i] = 14 + getSameCodeLength('B',i,cronixieDisplay); i = i+dP[i]-14; break;
|
||||
case 'h': dP[i] = 70 + getSameCodeLength('h',i,cronixieDisplay); i = i+dP[i]-70; break;
|
||||
@ -113,8 +248,8 @@ void setCronixie()
|
||||
case 'y': dP[i] = 86 + getSameCodeLength('y',i,cronixieDisplay); i = i+dP[i]-86; break;
|
||||
case 'I': dP[i] = 39 + getSameCodeLength('I',i,cronixieDisplay); i = i+dP[i]-39; break; //Month. Don't ask me why month and minute both start with M.
|
||||
case 'i': dP[i] = 89 + getSameCodeLength('i',i,cronixieDisplay); i = i+dP[i]-89; break;
|
||||
case 'W': break;
|
||||
case 'w': break;
|
||||
//case 'W': break;
|
||||
//case 'w': break;
|
||||
case 'D': dP[i] = 43 + getSameCodeLength('D',i,cronixieDisplay); i = i+dP[i]-43; break;
|
||||
case 'd': dP[i] = 93 + getSameCodeLength('d',i,cronixieDisplay); i = i+dP[i]-93; break;
|
||||
case '0': dP[i] = 0; break;
|
||||
@ -127,8 +262,8 @@ void setCronixie()
|
||||
case '7': dP[i] = 7; break;
|
||||
case '8': dP[i] = 8; break;
|
||||
case '9': dP[i] = 9; break;
|
||||
case 'V': break; //user var0
|
||||
case 'v': break; //user var1
|
||||
//case 'V': break; //user var0
|
||||
//case 'v': break; //user var1
|
||||
}
|
||||
}
|
||||
DEBUG_PRINT("result ");
|
||||
@ -140,12 +275,10 @@ void setCronixie()
|
||||
DEBUG_PRINTLN((int)dP[5]);
|
||||
|
||||
_overlayCronixie(); //refresh
|
||||
#endif
|
||||
}
|
||||
|
||||
void _overlayCronixie()
|
||||
{
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
byte h = hour(local);
|
||||
byte h0 = h;
|
||||
byte m = minute(local);
|
||||
@ -161,7 +294,6 @@ void _overlayCronixie()
|
||||
if (h>12) h-=12;
|
||||
else if (h==0) h+=12;
|
||||
}
|
||||
byte _digitOut[]{10,10,10,10,10,10};
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (dP[i] < 12) _digitOut[i] = dP[i];
|
||||
@ -184,8 +316,8 @@ void _overlayCronixie()
|
||||
case 37: _digitOut[i] = y/10; _digitOut[i+1] = y- _digitOut[i]*10; i++; break; //YY
|
||||
case 39: _digitOut[i] = 2; _digitOut[i+1] = 0; _digitOut[i+2] = y/10; _digitOut[i+3] = y- _digitOut[i+2]*10; i+=3; break; //YYYY
|
||||
|
||||
case 16: _digitOut[i+2] = ((h0/3)&1)?1:0; i++; //BBB (BBBB NI)
|
||||
case 15: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:0; i++; //BB
|
||||
//case 16: _digitOut[i+2] = ((h0/3)&1)?1:0; i++; //BBB (BBBB NI)
|
||||
//case 15: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:0; i++; //BB
|
||||
case 14: _digitOut[i] = (h0>11)?1:0; break; //B
|
||||
}
|
||||
} else
|
||||
@ -195,8 +327,8 @@ void _overlayCronixie()
|
||||
case 71: _digitOut[i] = h/10; _digitOut[i+1] = h- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //hh
|
||||
case 75: _digitOut[i] = m/10; _digitOut[i+1] = m- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //mm
|
||||
case 81: _digitOut[i] = s/10; _digitOut[i+1] = s- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //ss
|
||||
case 66: _digitOut[i+2] = ((h0/3)&1)?1:10; i++; //bbb (bbbb NI)
|
||||
case 65: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:10; i++; //bb
|
||||
//case 66: _digitOut[i+2] = ((h0/3)&1)?1:10; i++; //bbb (bbbb NI)
|
||||
//case 65: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:10; i++; //bb
|
||||
case 64: _digitOut[i] = (h0>11)?1:10; break; //b
|
||||
|
||||
case 93: _digitOut[i] = weekday(local); _digitOut[i]--; if (_digitOut[i]<1) _digitOut[i]= 7; break; //d
|
||||
@ -208,7 +340,37 @@ void _overlayCronixie()
|
||||
}
|
||||
}
|
||||
}
|
||||
strip.setCronixieDigits(_digitOut);
|
||||
//strip.trigger(); //this has a drawback, no effects slower than RefreshMs. advantage: Quick update, not dependant on effect time
|
||||
#endif
|
||||
}
|
||||
|
||||
void _drawOverlayCronixie()
|
||||
{
|
||||
byte offsets[] = {5, 0, 6, 1, 7, 2, 8, 3, 9, 4};
|
||||
|
||||
for (uint16_t i = 0; i < 6; i++)
|
||||
{
|
||||
byte o = 10*i;
|
||||
byte excl = 10;
|
||||
if(_digitOut[i] < 10) excl = offsets[_digitOut[i]];
|
||||
excl += o;
|
||||
|
||||
if (cronixieBacklight && _digitOut[i] <11)
|
||||
{
|
||||
uint32_t col = strip.gamma32(strip.getSegment(0).colors[1]);
|
||||
for (uint16_t j=o; j< o+10; j++) {
|
||||
if (j != excl) strip.setPixelColor(j, col);
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (uint16_t j=o; j< o+10; j++) {
|
||||
if (j != excl) strip.setPixelColor(j, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else // WLED_DISABLE_CRONIXIE
|
||||
byte getSameCodeLength(char code, int index, char const cronixieDisplay[]) {}
|
||||
void setCronixie() {}
|
||||
void _overlayCronixie() {}
|
||||
void _drawOverlayCronixie() {}
|
||||
#endif
|
@ -13,7 +13,9 @@
|
||||
#ifndef PalettesWLED_h
|
||||
#define PalettesWLED_h
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( ib_jul01_gp ) {
|
||||
#define GRADIENT_PALETTE_COUNT 39
|
||||
|
||||
const byte ib_jul01_gp[] PROGMEM = {
|
||||
0, 194, 1, 1,
|
||||
94, 1, 29, 18,
|
||||
132, 57,131, 28,
|
||||
@ -24,7 +26,7 @@ DEFINE_GRADIENT_PALETTE( ib_jul01_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_vintage_57_gp ) {
|
||||
const byte es_vintage_57_gp[] PROGMEM = {
|
||||
0, 2, 1, 1,
|
||||
53, 18, 1, 0,
|
||||
104, 69, 29, 1,
|
||||
@ -37,7 +39,7 @@ DEFINE_GRADIENT_PALETTE( es_vintage_57_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 32 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_vintage_01_gp ) {
|
||||
const byte es_vintage_01_gp[] PROGMEM = {
|
||||
0, 4, 1, 1,
|
||||
51, 16, 0, 1,
|
||||
76, 97,104, 3,
|
||||
@ -53,7 +55,7 @@ DEFINE_GRADIENT_PALETTE( es_vintage_01_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_rivendell_15_gp ) {
|
||||
const byte es_rivendell_15_gp[] PROGMEM = {
|
||||
0, 1, 14, 5,
|
||||
101, 16, 36, 14,
|
||||
165, 56, 68, 30,
|
||||
@ -67,7 +69,7 @@ DEFINE_GRADIENT_PALETTE( es_rivendell_15_gp ) {
|
||||
// Size: 36 bytes of program space.
|
||||
// Edited to be brighter
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( rgi_15_gp ) {
|
||||
const byte rgi_15_gp[] PROGMEM = {
|
||||
0, 4, 1, 70,
|
||||
31, 55, 1, 30,
|
||||
63, 255, 4, 7,
|
||||
@ -84,7 +86,7 @@ DEFINE_GRADIENT_PALETTE( rgi_15_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 8 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( retro2_16_gp ) {
|
||||
const byte retro2_16_gp[] PROGMEM = {
|
||||
0, 188,135, 1,
|
||||
255, 46, 7, 1};
|
||||
|
||||
@ -94,7 +96,7 @@ DEFINE_GRADIENT_PALETTE( retro2_16_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Analogous_1_gp ) {
|
||||
const byte Analogous_1_gp[] PROGMEM = {
|
||||
0, 3, 0,255,
|
||||
63, 23, 0,255,
|
||||
127, 67, 0,255,
|
||||
@ -107,7 +109,7 @@ DEFINE_GRADIENT_PALETTE( Analogous_1_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_pinksplash_08_gp ) {
|
||||
const byte es_pinksplash_08_gp[] PROGMEM = {
|
||||
0, 126, 11,255,
|
||||
127, 197, 1, 22,
|
||||
175, 210,157,172,
|
||||
@ -120,7 +122,7 @@ DEFINE_GRADIENT_PALETTE( es_pinksplash_08_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 16 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_ocean_breeze_036_gp ) {
|
||||
const byte es_ocean_breeze_036_gp[] PROGMEM = {
|
||||
0, 1, 6, 7,
|
||||
89, 1, 99,111,
|
||||
153, 144,209,255,
|
||||
@ -132,7 +134,7 @@ DEFINE_GRADIENT_PALETTE( es_ocean_breeze_036_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 88 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( departure_gp ) {
|
||||
const byte departure_gp[] PROGMEM = {
|
||||
0, 8, 3, 0,
|
||||
42, 23, 7, 0,
|
||||
63, 75, 38, 6,
|
||||
@ -152,7 +154,7 @@ DEFINE_GRADIENT_PALETTE( departure_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 36 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_landscape_64_gp ) {
|
||||
const byte es_landscape_64_gp[] PROGMEM = {
|
||||
0, 0, 0, 0,
|
||||
37, 2, 25, 1,
|
||||
76, 15,115, 5,
|
||||
@ -169,7 +171,7 @@ DEFINE_GRADIENT_PALETTE( es_landscape_64_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 24 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_landscape_33_gp ) {
|
||||
const byte es_landscape_33_gp[] PROGMEM = {
|
||||
0, 1, 5, 0,
|
||||
19, 32, 23, 1,
|
||||
38, 161, 55, 1,
|
||||
@ -183,7 +185,7 @@ DEFINE_GRADIENT_PALETTE( es_landscape_33_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 28 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( rainbowsherbet_gp ) {
|
||||
const byte rainbowsherbet_gp[] PROGMEM = {
|
||||
0, 255, 33, 4,
|
||||
43, 255, 68, 25,
|
||||
86, 255, 7, 25,
|
||||
@ -198,7 +200,7 @@ DEFINE_GRADIENT_PALETTE( rainbowsherbet_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 24 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( gr65_hult_gp ) {
|
||||
const byte gr65_hult_gp[] PROGMEM = {
|
||||
0, 247,176,247,
|
||||
48, 255,136,255,
|
||||
89, 220, 29,226,
|
||||
@ -212,7 +214,7 @@ DEFINE_GRADIENT_PALETTE( gr65_hult_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 32 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( gr64_hult_gp ) {
|
||||
const byte gr64_hult_gp[] PROGMEM = {
|
||||
0, 1,124,109,
|
||||
66, 1, 93, 79,
|
||||
104, 52, 65, 1,
|
||||
@ -228,7 +230,7 @@ DEFINE_GRADIENT_PALETTE( gr64_hult_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 28 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( GMT_drywet_gp ) {
|
||||
const byte GMT_drywet_gp[] PROGMEM = {
|
||||
0, 47, 30, 2,
|
||||
42, 213,147, 24,
|
||||
84, 103,219, 52,
|
||||
@ -243,7 +245,7 @@ DEFINE_GRADIENT_PALETTE( GMT_drywet_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 24 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( ib15_gp ) {
|
||||
const byte ib15_gp[] PROGMEM = {
|
||||
0, 113, 91,147,
|
||||
72, 157, 88, 78,
|
||||
89, 208, 85, 33,
|
||||
@ -257,7 +259,7 @@ DEFINE_GRADIENT_PALETTE( ib15_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Tertiary_01_gp ) {
|
||||
const byte Tertiary_01_gp[] PROGMEM = {
|
||||
0, 0, 1,255,
|
||||
63, 3, 68, 45,
|
||||
127, 23,255, 0,
|
||||
@ -270,7 +272,7 @@ DEFINE_GRADIENT_PALETTE( Tertiary_01_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 52 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( lava_gp ) {
|
||||
const byte lava_gp[] PROGMEM = {
|
||||
0, 0, 0, 0,
|
||||
46, 18, 0, 0,
|
||||
96, 113, 0, 0,
|
||||
@ -291,7 +293,7 @@ DEFINE_GRADIENT_PALETTE( lava_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 28 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( fierce_ice_gp ) {
|
||||
const byte fierce_ice_gp[] PROGMEM = {
|
||||
0, 0, 0, 0,
|
||||
59, 0, 9, 45,
|
||||
119, 0, 38,255,
|
||||
@ -306,7 +308,7 @@ DEFINE_GRADIENT_PALETTE( fierce_ice_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 44 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Colorfull_gp ) {
|
||||
const byte Colorfull_gp[] PROGMEM = {
|
||||
0, 10, 85, 5,
|
||||
25, 29,109, 18,
|
||||
60, 59,138, 42,
|
||||
@ -325,7 +327,7 @@ DEFINE_GRADIENT_PALETTE( Colorfull_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 44 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Pink_Purple_gp ) {
|
||||
const byte Pink_Purple_gp[] PROGMEM = {
|
||||
0, 19, 2, 39,
|
||||
25, 26, 4, 45,
|
||||
51, 33, 6, 52,
|
||||
@ -344,7 +346,7 @@ DEFINE_GRADIENT_PALETTE( Pink_Purple_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 28 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Sunset_Real_gp ) {
|
||||
const byte Sunset_Real_gp[] PROGMEM = {
|
||||
0, 120, 0, 0,
|
||||
22, 179, 22, 0,
|
||||
51, 255,104, 0,
|
||||
@ -359,7 +361,7 @@ DEFINE_GRADIENT_PALETTE( Sunset_Real_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 44 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Sunset_Yellow_gp ) {
|
||||
const byte Sunset_Yellow_gp[] PROGMEM = {
|
||||
0, 10, 62,123,
|
||||
36, 56,130,103,
|
||||
87, 153,225, 85,
|
||||
@ -378,7 +380,7 @@ DEFINE_GRADIENT_PALETTE( Sunset_Yellow_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 60 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Beech_gp ) {
|
||||
const byte Beech_gp[] PROGMEM = {
|
||||
0, 255,252,214,
|
||||
12, 255,252,214,
|
||||
22, 255,252,214,
|
||||
@ -401,7 +403,7 @@ DEFINE_GRADIENT_PALETTE( Beech_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 32 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Another_Sunset_gp ) {
|
||||
const byte Another_Sunset_gp[] PROGMEM = {
|
||||
0, 110, 49, 11,
|
||||
29, 55, 34, 10,
|
||||
68, 22, 22, 9,
|
||||
@ -420,7 +422,7 @@ DEFINE_GRADIENT_PALETTE( Another_Sunset_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 52 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_autumn_19_gp ) {
|
||||
const byte es_autumn_19_gp[] PROGMEM = {
|
||||
0, 26, 1, 1,
|
||||
51, 67, 4, 1,
|
||||
84, 118, 14, 1,
|
||||
@ -441,7 +443,7 @@ DEFINE_GRADIENT_PALETTE( es_autumn_19_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 28 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( BlacK_Blue_Magenta_White_gp ) {
|
||||
const byte BlacK_Blue_Magenta_White_gp[] PROGMEM = {
|
||||
0, 0, 0, 0,
|
||||
42, 0, 0, 45,
|
||||
84, 0, 0,255,
|
||||
@ -456,7 +458,7 @@ DEFINE_GRADIENT_PALETTE( BlacK_Blue_Magenta_White_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( BlacK_Magenta_Red_gp ) {
|
||||
const byte BlacK_Magenta_Red_gp[] PROGMEM = {
|
||||
0, 0, 0, 0,
|
||||
63, 42, 0, 45,
|
||||
127, 255, 0,255,
|
||||
@ -469,7 +471,7 @@ DEFINE_GRADIENT_PALETTE( BlacK_Magenta_Red_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 28 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( BlacK_Red_Magenta_Yellow_gp ) {
|
||||
const byte BlacK_Red_Magenta_Yellow_gp[] PROGMEM = {
|
||||
0, 0, 0, 0,
|
||||
42, 42, 0, 0,
|
||||
84, 255, 0, 0,
|
||||
@ -484,7 +486,7 @@ DEFINE_GRADIENT_PALETTE( BlacK_Red_Magenta_Yellow_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Blue_Cyan_Yellow_gp ) {
|
||||
const byte Blue_Cyan_Yellow_gp[] PROGMEM = {
|
||||
0, 0, 0,255,
|
||||
63, 0, 55,255,
|
||||
127, 0,255,255,
|
||||
@ -494,7 +496,7 @@ DEFINE_GRADIENT_PALETTE( Blue_Cyan_Yellow_gp ) {
|
||||
|
||||
//Custom palette by Aircoookie
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Orange_Teal_gp ) {
|
||||
const byte Orange_Teal_gp[] PROGMEM = {
|
||||
0, 0,150, 92,
|
||||
55, 0,150, 92,
|
||||
200, 255, 72, 0,
|
||||
@ -502,7 +504,7 @@ DEFINE_GRADIENT_PALETTE( Orange_Teal_gp ) {
|
||||
|
||||
//Custom palette by Aircoookie
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Tiamat_gp ) {
|
||||
const byte Tiamat_gp[] PROGMEM = {
|
||||
0, 1, 2, 14, //gc
|
||||
33, 2, 5, 35, //gc from 47, 61,126
|
||||
100, 13,135, 92, //gc from 88,242,247
|
||||
@ -517,7 +519,7 @@ DEFINE_GRADIENT_PALETTE( Tiamat_gp ) {
|
||||
|
||||
//Custom palette by Aircoookie
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( April_Night_gp ) {
|
||||
const byte April_Night_gp[] PROGMEM = {
|
||||
0, 1, 5, 45, //deep blue
|
||||
10, 1, 5, 45,
|
||||
25, 5,169,175, //light blue
|
||||
@ -536,7 +538,7 @@ DEFINE_GRADIENT_PALETTE( April_Night_gp ) {
|
||||
244, 1, 5, 45,
|
||||
255, 1, 5, 45};
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Orangery_gp ) {
|
||||
const byte Orangery_gp[] PROGMEM = {
|
||||
0, 255, 95, 23,
|
||||
30, 255, 82, 0,
|
||||
60, 223, 13, 8,
|
||||
@ -548,7 +550,7 @@ DEFINE_GRADIENT_PALETTE( Orangery_gp ) {
|
||||
255, 213, 37, 4};
|
||||
|
||||
//inspired by Mark Kriegsman https://gist.github.com/kriegsman/756ea6dcae8e30845b5a
|
||||
DEFINE_GRADIENT_PALETTE( C9_gp ) {
|
||||
const byte C9_gp[] PROGMEM = {
|
||||
0, 184, 4, 0, //red
|
||||
60, 184, 4, 0,
|
||||
65, 144, 44, 2, //amber
|
||||
@ -558,14 +560,14 @@ DEFINE_GRADIENT_PALETTE( C9_gp ) {
|
||||
195, 7, 7, 88, //blue
|
||||
255, 7, 7, 88};
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Sakura_gp ) {
|
||||
const byte Sakura_gp[] PROGMEM = {
|
||||
0, 196, 19, 10,
|
||||
65, 255, 69, 45,
|
||||
130, 223, 45, 72,
|
||||
195, 255, 82,103,
|
||||
255, 223, 13, 17};
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Aurora_gp ) {
|
||||
const byte Aurora_gp[] PROGMEM = {
|
||||
0, 1, 5, 45, //deep blue
|
||||
64, 0,200, 23,
|
||||
128, 0,255, 0, //green
|
||||
@ -573,18 +575,20 @@ DEFINE_GRADIENT_PALETTE( Aurora_gp ) {
|
||||
200, 0,135, 7,
|
||||
255, 1, 5, 45};//deep blue
|
||||
|
||||
const byte Atlantica_gp[] PROGMEM = {
|
||||
0, 0, 28,112, //#001C70
|
||||
50, 32, 96,255, //#2060FF
|
||||
100, 0,243, 45,
|
||||
150, 12, 95, 82, //#0C5F52
|
||||
200, 25,190, 95, //#19BE5F
|
||||
255, 40,170, 80};//#28AA50
|
||||
|
||||
|
||||
// Single array of defined cpt-city color palettes.
|
||||
// This will let us programmatically choose one based on
|
||||
// a number, rather than having to activate each explicitly
|
||||
// by name every time.
|
||||
// Since it is const, this array could also be moved
|
||||
// into PROGMEM to save SRAM, but for simplicity of illustration
|
||||
// we'll keep it in a regular SRAM array.
|
||||
//
|
||||
// This list of color palettes acts as a "playlist"; you can
|
||||
// add or delete, or re-arrange as you wish.
|
||||
const TProgmemRGBGradientPalettePtr gGradientPalettes[] = {
|
||||
const byte* const gGradientPalettes[] PROGMEM = {
|
||||
Sunset_Real_gp, //13-00 Sunset
|
||||
es_rivendell_15_gp, //14-01 Rivendell
|
||||
es_ocean_breeze_036_gp, //15-02 Breeze
|
||||
@ -623,11 +627,7 @@ const TProgmemRGBGradientPalettePtr gGradientPalettes[] = {
|
||||
C9_gp, //48-35 C9
|
||||
Sakura_gp, //49-36 Sakura
|
||||
Aurora_gp, //50-37 Aurora
|
||||
Atlantica_gp, //51-38 Atlantica
|
||||
};
|
||||
|
||||
|
||||
// Count of how many cpt-city gradients are defined:
|
||||
const uint8_t gGradientPaletteCount =
|
||||
sizeof( gGradientPalettes) / sizeof( TProgmemRGBGradientPalettePtr );
|
||||
|
||||
#endif
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Receives client input
|
||||
*/
|
||||
|
||||
void _setRandomColor(bool _sec,bool fromButton=false)
|
||||
void _setRandomColor(bool _sec,bool fromButton)
|
||||
{
|
||||
lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex);
|
||||
if (_sec){
|
||||
@ -27,8 +29,9 @@ bool isAsterisksOnly(const char* str, byte maxLen)
|
||||
//called upon POST settings form submit
|
||||
void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
{
|
||||
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec
|
||||
if (subPage <1 || subPage >6) return;
|
||||
|
||||
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX
|
||||
if (subPage <1 || subPage >7) return;
|
||||
|
||||
//WIFI SETTINGS
|
||||
if (subPage == 1)
|
||||
@ -46,6 +49,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (passlen == 0 || (passlen > 7 && !isAsterisksOnly(request->arg("AP").c_str(), 65))) strlcpy(apPass, request->arg("AP").c_str(), 65);
|
||||
int t = request->arg("AC").toInt(); if (t > 0 && t < 14) apChannel = t;
|
||||
|
||||
noWifiSleep = request->hasArg("WS");
|
||||
|
||||
char k[3]; k[2] = 0;
|
||||
for (int i = 0; i<4; i++)
|
||||
{
|
||||
@ -77,7 +82,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
|
||||
useRGBW = request->hasArg("EW");
|
||||
strip.colorOrder = request->arg("CO").toInt();
|
||||
autoRGBtoRGBW = request->hasArg("AW");
|
||||
strip.rgbwMode = request->arg("AW").toInt();
|
||||
|
||||
briS = request->arg("CA").toInt();
|
||||
|
||||
@ -104,7 +109,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (t >= 0 && t < 4) strip.paletteBlend = t;
|
||||
strip.reverseMode = request->hasArg("RV");
|
||||
skipFirstLed = request->hasArg("SL");
|
||||
disableNLeds = request->arg("DL").toInt();
|
||||
t = request->arg("BF").toInt();
|
||||
if (t > 0) briMultiplier = t;
|
||||
}
|
||||
@ -136,9 +140,16 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
notifyTwice = request->hasArg("S2");
|
||||
|
||||
receiveDirect = request->hasArg("RD");
|
||||
e131SkipOutOfSequence = request->hasArg("ES");
|
||||
e131Multicast = request->hasArg("EM");
|
||||
t = request->arg("EP").toInt();
|
||||
if (t > 0) e131Port = t;
|
||||
t = request->arg("EU").toInt();
|
||||
if (t > 0 && t <= 63999) e131Universe = t;
|
||||
if (t >= 0 && t <= 63999) e131Universe = t;
|
||||
t = request->arg("DA").toInt();
|
||||
if (t >= 0 && t <= 510) DMXAddress = t;
|
||||
t = request->arg("DM").toInt();
|
||||
if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_MULTIPLE_DRGB) DMXMode = t;
|
||||
t = request->arg("ET").toInt();
|
||||
if (t > 99 && t <= 65000) realtimeTimeoutMs = t;
|
||||
arlsForceMaxBri = request->hasArg("FB");
|
||||
@ -210,12 +221,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
analogClockSecondsTrail = request->hasArg("OS");
|
||||
|
||||
strcpy(cronixieDisplay,request->arg("CX").c_str());
|
||||
bool cbOld = cronixieBacklight;
|
||||
cronixieBacklight = request->hasArg("CB");
|
||||
if (cbOld != cronixieBacklight && overlayCurrent == 3)
|
||||
{
|
||||
strip.setCronixieBacklight(cronixieBacklight); overlayRefreshedTime = 0;
|
||||
}
|
||||
countdownMode = request->hasArg("CE");
|
||||
countdownYear = request->arg("CY").toInt();
|
||||
countdownMonth = request->arg("CI").toInt();
|
||||
@ -288,9 +294,36 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
aOtaEnabled = request->hasArg("AO");
|
||||
}
|
||||
}
|
||||
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
|
||||
if (subPage == 7)
|
||||
{
|
||||
int t = request->arg("CN").toInt();
|
||||
if (t>0 && t<16) {
|
||||
DMXChannels = t;
|
||||
}
|
||||
t = request->arg("CS").toInt();
|
||||
if (t>0 && t<513) {
|
||||
DMXStart = t;
|
||||
}
|
||||
t = request->arg("CG").toInt();
|
||||
if (t>0 && t<513) {
|
||||
DMXGap = t;
|
||||
}
|
||||
t = request->arg("SL").toInt();
|
||||
if (t>=0 && t < MAX_LEDS) {
|
||||
DMXStartLED = t;
|
||||
}
|
||||
for (int i=0; i<15; i++) {
|
||||
String argname = "CH" + String((i+1));
|
||||
t = request->arg(argname).toInt();
|
||||
DMXFixtureMap[i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
if (subPage != 6 || !doReboot) saveSettingsToEEPROM(); //do not save if factory reset
|
||||
if (subPage == 2) {
|
||||
strip.init(useRGBW,ledCount,skipFirstLed,disableNLeds);
|
||||
strip.init(useRGBW,ledCount,skipFirstLed);
|
||||
}
|
||||
if (subPage == 4) alexaInit();
|
||||
}
|
||||
@ -305,7 +338,7 @@ int getNumVal(const String* req, uint16_t pos)
|
||||
|
||||
|
||||
//helper to get int value at a position in string
|
||||
bool updateVal(const String* req, const char* key, byte* val, byte minv=0, byte maxv=255)
|
||||
bool updateVal(const String* req, const char* key, byte* val, byte minv, byte maxv)
|
||||
{
|
||||
int pos = req->indexOf(key);
|
||||
if (pos < 1) return false;
|
||||
@ -343,6 +376,13 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
DEBUG_PRINT("API req: ");
|
||||
DEBUG_PRINTLN(req);
|
||||
|
||||
//write presets and macros saved to flash directly?
|
||||
bool persistSaves = true;
|
||||
pos = req.indexOf("NP");
|
||||
if (pos > 0) {
|
||||
persistSaves = false;
|
||||
}
|
||||
|
||||
//save macro, requires &MS=<slot>(<macro>) format
|
||||
pos = req.indexOf("&MS=");
|
||||
if (pos > 0) {
|
||||
@ -352,7 +392,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
int en = req.indexOf(')');
|
||||
String mc = req.substring(pos);
|
||||
if (en > 0) mc = req.substring(pos, en);
|
||||
saveMacro(i, mc);
|
||||
saveMacro(i, mc, persistSaves);
|
||||
}
|
||||
|
||||
pos = req.indexOf("IN");
|
||||
@ -378,11 +418,14 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
if (t < strip.getMaxSegments()) main = t;
|
||||
}
|
||||
|
||||
WS2812FX::Segment& mainseg = strip.getSegment(main);
|
||||
pos = req.indexOf("SV="); //segment selected
|
||||
if (pos > 0) strip.getSegment(main).setOption(0, (req.charAt(pos+3) != '0'));
|
||||
if (pos > 0) mainseg.setOption(SEG_OPTION_SELECTED, (req.charAt(pos+3) != '0'));
|
||||
|
||||
uint16_t startI = strip.getSegment(main).start;
|
||||
uint16_t stopI = strip.getSegment(main).stop;
|
||||
uint16_t startI = mainseg.start;
|
||||
uint16_t stopI = mainseg.stop;
|
||||
uint8_t grpI = mainseg.grouping;
|
||||
uint16_t spcI = mainseg.spacing;
|
||||
pos = req.indexOf("&S="); //segment start
|
||||
if (pos > 0) {
|
||||
startI = getNumVal(&req, pos);
|
||||
@ -391,10 +434,51 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
if (pos > 0) {
|
||||
stopI = getNumVal(&req, pos);
|
||||
}
|
||||
strip.setSegment(main, startI, stopI);
|
||||
pos = req.indexOf("GP="); //segment grouping
|
||||
if (pos > 0) {
|
||||
grpI = getNumVal(&req, pos);
|
||||
if (grpI == 0) grpI = 1;
|
||||
}
|
||||
pos = req.indexOf("SP="); //segment spacing
|
||||
if (pos > 0) {
|
||||
spcI = getNumVal(&req, pos);
|
||||
}
|
||||
strip.setSegment(main, startI, stopI, grpI, spcI);
|
||||
|
||||
main = strip.getMainSegmentId();
|
||||
|
||||
//set presets
|
||||
pos = req.indexOf("P1="); //sets first preset for cycle
|
||||
if (pos > 0) presetCycleMin = getNumVal(&req, pos);
|
||||
|
||||
pos = req.indexOf("P2="); //sets last preset for cycle
|
||||
if (pos > 0) presetCycleMax = getNumVal(&req, pos);
|
||||
|
||||
//preset cycle
|
||||
pos = req.indexOf("CY=");
|
||||
if (pos > 0)
|
||||
{
|
||||
presetCyclingEnabled = (req.charAt(pos+3) != '0');
|
||||
presetCycCurr = presetCycleMin;
|
||||
}
|
||||
|
||||
pos = req.indexOf("PT="); //sets cycle time in ms
|
||||
if (pos > 0) {
|
||||
int v = getNumVal(&req, pos);
|
||||
if (v > 49) presetCycleTime = v;
|
||||
}
|
||||
|
||||
pos = req.indexOf("PA="); //apply brightness from preset
|
||||
if (pos > 0) presetApplyBri = (req.charAt(pos+3) != '0');
|
||||
|
||||
pos = req.indexOf("PS="); //saves current in preset
|
||||
if (pos > 0) savePreset(getNumVal(&req, pos), persistSaves);
|
||||
|
||||
//apply preset
|
||||
if (updateVal(&req, "PL=", &presetCycCurr, presetCycleMin, presetCycleMax)) {
|
||||
applyPreset(presetCycCurr, presetApplyBri);
|
||||
}
|
||||
|
||||
//set brightness
|
||||
updateVal(&req, "&A=", &bri);
|
||||
|
||||
@ -429,6 +513,12 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
if (pos > 0) {
|
||||
colorFromDecOrHexString(colSec, (char*)req.substring(pos + 3).c_str());
|
||||
}
|
||||
pos = req.indexOf("C3=");
|
||||
if (pos > 0) {
|
||||
byte t[4];
|
||||
colorFromDecOrHexString(t, (char*)req.substring(pos + 3).c_str());
|
||||
strip.setColor(2, t[0], t[1], t[2], t[3]);
|
||||
}
|
||||
|
||||
//set to random hue SR=0->1st SR=1->2nd
|
||||
pos = req.indexOf("SR");
|
||||
@ -542,7 +632,17 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
|
||||
//Segment reverse
|
||||
pos = req.indexOf("RV=");
|
||||
if (pos > 0) strip.getSegment(main).setOption(1, req.charAt(pos+3) != '0');
|
||||
if (pos > 0) strip.getSegment(main).setOption(SEG_OPTION_REVERSED, req.charAt(pos+3) != '0');
|
||||
|
||||
//Segment brightness/opacity
|
||||
pos = req.indexOf("SB=");
|
||||
if (pos > 0) {
|
||||
byte segbri = getNumVal(&req, pos);
|
||||
strip.getSegment(main).setOption(SEG_OPTION_ON, segbri);
|
||||
if (segbri) {
|
||||
strip.getSegment(main).opacity = segbri;
|
||||
}
|
||||
}
|
||||
|
||||
//deactivate nightlight if target brightness is reached
|
||||
if (bri == nightlightTargetBri) nightlightActive = false;
|
||||
@ -559,43 +659,8 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
if (countdownTime - now() > 0) countdownOverTriggered = false;
|
||||
}
|
||||
|
||||
//set presets
|
||||
pos = req.indexOf("P1="); //sets first preset for cycle
|
||||
if (pos > 0) presetCycleMin = getNumVal(&req, pos);
|
||||
|
||||
pos = req.indexOf("P2="); //sets last preset for cycle
|
||||
if (pos > 0) presetCycleMax = getNumVal(&req, pos);
|
||||
|
||||
//preset cycle
|
||||
pos = req.indexOf("CY=");
|
||||
if (pos > 0)
|
||||
{
|
||||
presetCyclingEnabled = (req.charAt(pos+3) != '0');
|
||||
presetCycCurr = presetCycleMin;
|
||||
}
|
||||
|
||||
pos = req.indexOf("PT="); //sets cycle time in ms
|
||||
if (pos > 0) {
|
||||
int v = getNumVal(&req, pos);
|
||||
if (v > 49) presetCycleTime = v;
|
||||
}
|
||||
|
||||
pos = req.indexOf("PA="); //apply brightness from preset
|
||||
if (pos > 0) presetApplyBri = (req.charAt(pos+3) != '0');
|
||||
|
||||
pos = req.indexOf("PC="); //apply color from preset
|
||||
if (pos > 0) presetApplyCol = (req.charAt(pos+3) != '0');
|
||||
|
||||
pos = req.indexOf("PX="); //apply effects from preset
|
||||
if (pos > 0) presetApplyFx = (req.charAt(pos+3) != '0');
|
||||
|
||||
pos = req.indexOf("PS="); //saves current in preset
|
||||
if (pos > 0) savePreset(getNumVal(&req, pos));
|
||||
|
||||
//apply preset
|
||||
if (updateVal(&req, "PL=", &presetCycCurr, presetCycleMin, presetCycleMax)) {
|
||||
applyPreset(presetCycCurr, presetApplyBri, presetApplyCol, presetApplyFx);
|
||||
}
|
||||
pos = req.indexOf("RB");
|
||||
if (pos > 0) doReboot = true;
|
||||
|
||||
//cronixie
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
@ -612,8 +677,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
pos = req.indexOf("NB=");
|
||||
if (pos > 0) //sets backlight
|
||||
{
|
||||
presetApplyFx = (req.charAt(pos+3) != '0');
|
||||
if (overlayCurrent == 3) strip.setCronixieBacklight(cronixieBacklight);
|
||||
cronixieBacklight = (req.charAt(pos+3) != '0');
|
||||
overlayRefreshedTime = 0;
|
||||
}
|
||||
#endif
|
||||
@ -634,7 +698,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
if (pos < 1) XML_response(request);
|
||||
|
||||
pos = req.indexOf("&NN"); //do not send UDP notifications this time
|
||||
colorUpdated((pos > 0) ? 5:1);
|
||||
colorUpdated((pos > 0) ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
|
||||
return true;
|
||||
}
|
5
wled00/src/dependencies/blynk/BlynkSimpleEsp.cpp
Normal file
5
wled00/src/dependencies/blynk/BlynkSimpleEsp.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "BlynkSimpleEsp.h"
|
||||
|
||||
WiFiClient _blynkWifiClient;
|
||||
BlynkArduinoClient _blynkTransport(_blynkWifiClient);
|
||||
BlynkWifi Blynk(_blynkTransport);
|
@ -89,8 +89,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
static WiFiClient _blynkWifiClient;
|
||||
static BlynkArduinoClient _blynkTransport(_blynkWifiClient);
|
||||
BlynkWifi Blynk(_blynkTransport);
|
||||
extern BlynkWifi Blynk;
|
||||
|
||||
#endif
|
||||
|
106
wled00/src/dependencies/dmx/ESPDMX.cpp
Normal file
106
wled00/src/dependencies/dmx/ESPDMX.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
// - - - - -
|
||||
// ESPDMX - A Arduino library for sending and receiving DMX using the builtin serial hardware port.
|
||||
// ESPDMX.cpp: Library implementation file
|
||||
//
|
||||
// Copyright (C) 2015 Rick <ricardogg95@gmail.com>
|
||||
// This work is licensed under a GNU style license.
|
||||
//
|
||||
// Last change: Marcel Seerig <https://github.com/mseerig>
|
||||
//
|
||||
// Documentation and samples are available at https://github.com/Rickgg/ESP-Dmx
|
||||
// - - - - -
|
||||
|
||||
/* ----- LIBRARIES ----- */
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "ESPDMX.h"
|
||||
|
||||
|
||||
|
||||
#define dmxMaxChannel 512
|
||||
#define defaultMax 32
|
||||
|
||||
#define DMXSPEED 250000
|
||||
#define DMXFORMAT SERIAL_8N2
|
||||
#define BREAKSPEED 83333
|
||||
#define BREAKFORMAT SERIAL_8N1
|
||||
|
||||
bool dmxStarted = false;
|
||||
int sendPin = 2; //dafault on ESP8266
|
||||
|
||||
//DMX value array and size. Entry 0 will hold startbyte
|
||||
uint8_t dmxData[dmxMaxChannel] = {};
|
||||
int chanSize;
|
||||
|
||||
|
||||
void DMXESPSerial::init() {
|
||||
chanSize = defaultMax;
|
||||
|
||||
Serial1.begin(DMXSPEED);
|
||||
pinMode(sendPin, OUTPUT);
|
||||
dmxStarted = true;
|
||||
}
|
||||
|
||||
// Set up the DMX-Protocol
|
||||
void DMXESPSerial::init(int chanQuant) {
|
||||
|
||||
if (chanQuant > dmxMaxChannel || chanQuant <= 0) {
|
||||
chanQuant = defaultMax;
|
||||
}
|
||||
|
||||
chanSize = chanQuant;
|
||||
|
||||
Serial1.begin(DMXSPEED);
|
||||
pinMode(sendPin, OUTPUT);
|
||||
dmxStarted = true;
|
||||
}
|
||||
|
||||
// Function to read DMX data
|
||||
uint8_t DMXESPSerial::read(int Channel) {
|
||||
if (dmxStarted == false) init();
|
||||
|
||||
if (Channel < 1) Channel = 1;
|
||||
if (Channel > dmxMaxChannel) Channel = dmxMaxChannel;
|
||||
return(dmxData[Channel]);
|
||||
}
|
||||
|
||||
// Function to send DMX data
|
||||
void DMXESPSerial::write(int Channel, uint8_t value) {
|
||||
if (dmxStarted == false) init();
|
||||
|
||||
if (Channel < 1) Channel = 1;
|
||||
if (Channel > chanSize) Channel = chanSize;
|
||||
if (value < 0) value = 0;
|
||||
if (value > 255) value = 255;
|
||||
|
||||
dmxData[Channel] = value;
|
||||
}
|
||||
|
||||
void DMXESPSerial::end() {
|
||||
delete dmxData;
|
||||
chanSize = 0;
|
||||
Serial1.end();
|
||||
dmxStarted == false;
|
||||
}
|
||||
|
||||
void DMXESPSerial::update() {
|
||||
if (dmxStarted == false) init();
|
||||
|
||||
//Send break
|
||||
digitalWrite(sendPin, HIGH);
|
||||
Serial1.begin(BREAKSPEED, BREAKFORMAT);
|
||||
Serial1.write(0);
|
||||
Serial1.flush();
|
||||
delay(1);
|
||||
Serial1.end();
|
||||
|
||||
//send data
|
||||
Serial1.begin(DMXSPEED, DMXFORMAT);
|
||||
digitalWrite(sendPin, LOW);
|
||||
Serial1.write(dmxData, chanSize);
|
||||
Serial1.flush();
|
||||
delay(1);
|
||||
Serial1.end();
|
||||
}
|
||||
|
||||
// Function to update the DMX bus
|
31
wled00/src/dependencies/dmx/ESPDMX.h
Normal file
31
wled00/src/dependencies/dmx/ESPDMX.h
Normal file
@ -0,0 +1,31 @@
|
||||
// - - - - -
|
||||
// ESPDMX - A Arduino library for sending and receiving DMX using the builtin serial hardware port.
|
||||
// ESPDMX.cpp: Library implementation file
|
||||
//
|
||||
// Copyright (C) 2015 Rick <ricardogg95@gmail.com>
|
||||
// This work is licensed under a GNU style license.
|
||||
//
|
||||
// Last change: Marcel Seerig <https://github.com/mseerig>
|
||||
//
|
||||
// Documentation and samples are available at https://github.com/Rickgg/ESP-Dmx
|
||||
// - - - - -
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
#ifndef ESPDMX_h
|
||||
#define ESPDMX_h
|
||||
|
||||
// ---- Methods ----
|
||||
|
||||
class DMXESPSerial {
|
||||
public:
|
||||
void init();
|
||||
void init(int MaxChan);
|
||||
uint8_t read(int Channel);
|
||||
void write(int channel, uint8_t value);
|
||||
void update();
|
||||
void end();
|
||||
};
|
||||
|
||||
#endif
|
@ -23,6 +23,9 @@
|
||||
// E1.17 ACN Packet Identifier
|
||||
const byte ESPAsyncE131::ACN_ID[12] = { 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00 };
|
||||
|
||||
// Art-Net Packet Identifier
|
||||
const byte ESPAsyncE131::ART_ID[8] = { 0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00 };
|
||||
|
||||
// Constructor
|
||||
ESPAsyncE131::ESPAsyncE131(e131_packet_callback_function callback) {
|
||||
_callback = callback;
|
||||
@ -34,13 +37,14 @@ ESPAsyncE131::ESPAsyncE131(e131_packet_callback_function callback) {
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool ESPAsyncE131::begin(e131_listen_t type, uint16_t universe, uint8_t n) {
|
||||
bool ESPAsyncE131::begin(bool multicast, uint16_t port, uint16_t universe, uint8_t n) {
|
||||
bool success = false;
|
||||
|
||||
if (type == E131_UNICAST)
|
||||
success = initUnicast();
|
||||
if (type == E131_MULTICAST)
|
||||
success = initMulticast(universe, n);
|
||||
if (multicast) {
|
||||
success = initMulticast(port, universe, n);
|
||||
} else {
|
||||
success = initUnicast(port);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
@ -51,10 +55,10 @@ bool ESPAsyncE131::begin(e131_listen_t type, uint16_t universe, uint8_t n) {
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool ESPAsyncE131::initUnicast() {
|
||||
bool ESPAsyncE131::initUnicast(uint16_t port) {
|
||||
bool success = false;
|
||||
|
||||
if (udp.listen(E131_DEFAULT_PORT)) {
|
||||
if (udp.listen(port)) {
|
||||
udp.onPacket(std::bind(&ESPAsyncE131::parsePacket, this,
|
||||
std::placeholders::_1));
|
||||
success = true;
|
||||
@ -62,13 +66,13 @@ bool ESPAsyncE131::initUnicast() {
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ESPAsyncE131::initMulticast(uint16_t universe, uint8_t n) {
|
||||
bool ESPAsyncE131::initMulticast(uint16_t port, uint16_t universe, uint8_t n) {
|
||||
bool success = false;
|
||||
|
||||
IPAddress address = IPAddress(239, 255, ((universe >> 8) & 0xff),
|
||||
((universe >> 0) & 0xff));
|
||||
|
||||
if (udp.listenMulticast(address, E131_DEFAULT_PORT)) {
|
||||
if (udp.listenMulticast(address, port)) {
|
||||
ip4_addr_t ifaddr;
|
||||
ip4_addr_t multicast_addr;
|
||||
|
||||
@ -95,22 +99,31 @@ bool ESPAsyncE131::initMulticast(uint16_t universe, uint8_t n) {
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void ESPAsyncE131::parsePacket(AsyncUDPPacket _packet) {
|
||||
e131_error_t error = ERROR_NONE;
|
||||
bool error = false, isArtnet = false;
|
||||
|
||||
sbuff = reinterpret_cast<e131_packet_t *>(_packet.data());
|
||||
|
||||
//E1.31 packet identifier ("ACS-E1.17")
|
||||
if (memcmp(sbuff->acn_id, ESPAsyncE131::ACN_ID, sizeof(sbuff->acn_id)))
|
||||
error = ERROR_ACN_ID;
|
||||
if (htonl(sbuff->root_vector) != ESPAsyncE131::VECTOR_ROOT)
|
||||
error = ERROR_VECTOR_ROOT;
|
||||
if (htonl(sbuff->frame_vector) != ESPAsyncE131::VECTOR_FRAME)
|
||||
error = ERROR_VECTOR_FRAME;
|
||||
if (sbuff->dmp_vector != ESPAsyncE131::VECTOR_DMP)
|
||||
error = ERROR_VECTOR_DMP;
|
||||
if (sbuff->property_values[0] != 0)
|
||||
error = ERROR_IGNORE;
|
||||
isArtnet = true; //not E1.31
|
||||
|
||||
if (isArtnet) {
|
||||
if (memcmp(sbuff->art_id, ESPAsyncE131::ART_ID, sizeof(sbuff->art_id)))
|
||||
error = true; //not "Art-Net"
|
||||
if (sbuff->art_opcode != ARTNET_OPCODE_OPDMX)
|
||||
error = true; //not a DMX packet
|
||||
} else { //E1.31 error handling
|
||||
if (htonl(sbuff->root_vector) != ESPAsyncE131::VECTOR_ROOT)
|
||||
error = true;
|
||||
if (htonl(sbuff->frame_vector) != ESPAsyncE131::VECTOR_FRAME)
|
||||
error = true;
|
||||
if (sbuff->dmp_vector != ESPAsyncE131::VECTOR_DMP)
|
||||
error = true;
|
||||
if (sbuff->property_values[0] != 0)
|
||||
error = true;
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
_callback(sbuff, _packet.remoteIP());
|
||||
_callback(sbuff, _packet.remoteIP(), isArtnet);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,12 @@
|
||||
* Author shall not be liable in any event for incidental or consequential
|
||||
* damages in connection with, or arising out of, the furnishing, performance
|
||||
* or use of these programs.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Inspired by https://github.com/hideakitai/ArtNet for ArtNet support
|
||||
*/
|
||||
|
||||
#ifndef ESPASYNCE131_H_
|
||||
#define ESPASYNCE131_H_
|
||||
|
||||
@ -40,7 +43,10 @@ typedef struct ip_addr ip4_addr_t;
|
||||
#endif
|
||||
|
||||
// Defaults
|
||||
#define E131_DEFAULT_PORT 5568
|
||||
#define E131_DEFAULT_PORT 5568
|
||||
#define ARTNET_DEFAULT_PORT 6454
|
||||
|
||||
#define ARTNET_OPCODE_OPDMX 0x5000
|
||||
|
||||
// E1.31 Packet Offsets
|
||||
#define E131_ROOT_PREAMBLE_SIZE 0
|
||||
@ -69,7 +75,7 @@ typedef struct ip_addr ip4_addr_t;
|
||||
|
||||
// E1.31 Packet Structure
|
||||
typedef union {
|
||||
struct {
|
||||
struct { //E1.31 packet
|
||||
// Root Layer
|
||||
uint16_t preamble_size;
|
||||
uint16_t postamble_size;
|
||||
@ -98,33 +104,29 @@ typedef union {
|
||||
uint8_t property_values[513];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct { //Art-Net packet
|
||||
uint8_t art_id[8];
|
||||
uint16_t art_opcode;
|
||||
uint16_t art_protocol_ver;
|
||||
uint8_t art_sequence_number;
|
||||
uint8_t art_physical;
|
||||
uint16_t art_universe;
|
||||
uint16_t art_length;
|
||||
|
||||
uint8_t art_data[512];
|
||||
} __attribute__((packed));
|
||||
|
||||
uint8_t raw[638];
|
||||
} e131_packet_t;
|
||||
|
||||
// Error Types
|
||||
typedef enum {
|
||||
ERROR_NONE,
|
||||
ERROR_IGNORE,
|
||||
ERROR_ACN_ID,
|
||||
ERROR_PACKET_SIZE,
|
||||
ERROR_VECTOR_ROOT,
|
||||
ERROR_VECTOR_FRAME,
|
||||
ERROR_VECTOR_DMP
|
||||
} e131_error_t;
|
||||
|
||||
// E1.31 Listener Types
|
||||
typedef enum {
|
||||
E131_UNICAST,
|
||||
E131_MULTICAST
|
||||
} e131_listen_t;
|
||||
|
||||
// new packet callback
|
||||
typedef void (*e131_packet_callback_function) (e131_packet_t* p, IPAddress clientIP);
|
||||
typedef void (*e131_packet_callback_function) (e131_packet_t* p, IPAddress clientIP, bool isArtnet);
|
||||
|
||||
class ESPAsyncE131 {
|
||||
private:
|
||||
// Constants for packet validation
|
||||
static const uint8_t ACN_ID[];
|
||||
static const uint8_t ART_ID[];
|
||||
static const uint32_t VECTOR_ROOT = 4;
|
||||
static const uint32_t VECTOR_FRAME = 2;
|
||||
static const uint8_t VECTOR_DMP = 2;
|
||||
@ -133,8 +135,8 @@ class ESPAsyncE131 {
|
||||
AsyncUDP udp; // AsyncUDP
|
||||
|
||||
// Internal Initializers
|
||||
bool initUnicast();
|
||||
bool initMulticast(uint16_t universe, uint8_t n = 1);
|
||||
bool initUnicast(uint16_t port);
|
||||
bool initMulticast(uint16_t port, uint16_t universe, uint8_t n = 1);
|
||||
|
||||
// Packet parser callback
|
||||
void parsePacket(AsyncUDPPacket _packet);
|
||||
@ -145,7 +147,7 @@ class ESPAsyncE131 {
|
||||
ESPAsyncE131(e131_packet_callback_function callback);
|
||||
|
||||
// Generic UDP listener, no physical or IP configuration
|
||||
bool begin(e131_listen_t type, uint16_t universe = 1, uint8_t n = 1);
|
||||
bool begin(bool multicast, uint16_t port = E131_DEFAULT_PORT, uint16_t universe = 1, uint8_t n = 1);
|
||||
};
|
||||
|
||||
#endif // ESPASYNCE131_H_
|
@ -10,7 +10,7 @@
|
||||
*/
|
||||
/*
|
||||
* @title Espalexa library
|
||||
* @version 2.4.4
|
||||
* @version 2.4.6
|
||||
* @author Christian Schwinne
|
||||
* @license MIT
|
||||
* @contributors d-999
|
||||
@ -49,7 +49,7 @@
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
#ifdef ESPALEXA_DEBUG
|
||||
#pragma message "Espalexa 2.4.4 debug mode"
|
||||
#pragma message "Espalexa 2.4.6 debug mode"
|
||||
#define EA_DEBUG(x) Serial.print (x)
|
||||
#define EA_DEBUGLN(x) Serial.println (x)
|
||||
#else
|
||||
@ -81,35 +81,29 @@ private:
|
||||
WiFiUDP espalexaUdp;
|
||||
IPAddress ipMulti;
|
||||
bool udpConnected = false;
|
||||
char packetBuffer[255]; //buffer to hold incoming udp packet
|
||||
String escapedMac=""; //lowercase mac address
|
||||
|
||||
//private member functions
|
||||
String boolString(bool st)
|
||||
{
|
||||
return(st)?"true":"false";
|
||||
}
|
||||
|
||||
String modeString(EspalexaColorMode m)
|
||||
const char* modeString(EspalexaColorMode m)
|
||||
{
|
||||
if (m == EspalexaColorMode::xy) return "xy";
|
||||
if (m == EspalexaColorMode::hs) return "hs";
|
||||
return "ct";
|
||||
}
|
||||
|
||||
String typeString(EspalexaDeviceType t)
|
||||
const char* typeString(EspalexaDeviceType t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case EspalexaDeviceType::dimmable: return "Dimmable light";
|
||||
case EspalexaDeviceType::whitespectrum: return "Color temperature light";
|
||||
case EspalexaDeviceType::color: return "Color light";
|
||||
case EspalexaDeviceType::extendedcolor: return "Extended color light";
|
||||
case EspalexaDeviceType::dimmable: return PSTR("Dimmable light");
|
||||
case EspalexaDeviceType::whitespectrum: return PSTR("Color temperature light");
|
||||
case EspalexaDeviceType::color: return PSTR("Color light");
|
||||
case EspalexaDeviceType::extendedcolor: return PSTR("Extended color light");
|
||||
}
|
||||
return "Light";
|
||||
return "";
|
||||
}
|
||||
|
||||
String modelidString(EspalexaDeviceType t)
|
||||
const char* modelidString(EspalexaDeviceType t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
@ -118,7 +112,7 @@ private:
|
||||
case EspalexaDeviceType::color: return "LST001";
|
||||
case EspalexaDeviceType::extendedcolor: return "LCT015";
|
||||
}
|
||||
return "Plug";
|
||||
return "";
|
||||
}
|
||||
|
||||
//Workaround functions courtesy of Sonoff-Tasmota
|
||||
@ -135,38 +129,38 @@ private:
|
||||
}
|
||||
|
||||
//device JSON string: color+temperature device emulates LCT015, dimmable device LWB010, (TODO: on/off Plug 01, color temperature device LWT010, color device LST001)
|
||||
String deviceJsonString(uint8_t deviceId)
|
||||
void deviceJsonString(uint8_t deviceId, char* buf)
|
||||
{
|
||||
deviceId--;
|
||||
if (deviceId >= currentDeviceCount) return "{}"; //error
|
||||
if (deviceId >= currentDeviceCount) {strcpy(buf,"{}"); return;} //error
|
||||
EspalexaDevice* dev = devices[deviceId];
|
||||
|
||||
String json = "{\"state\":{\"on\":";
|
||||
json += boolString(dev->getValue());
|
||||
if (dev->getType() != EspalexaDeviceType::onoff) //bri support
|
||||
{
|
||||
json += ",\"bri\":" + String(dev->getLastValue()-1);
|
||||
if (static_cast<uint8_t>(dev->getType()) > 2) //color support
|
||||
{
|
||||
json += ",\"hue\":" + String(dev->getHue()) + ",\"sat\":" + String(dev->getSat());
|
||||
json += ",\"effect\":\"none\",\"xy\":[" + String(dev->getX()) + "," + String(dev->getY()) + "]";
|
||||
}
|
||||
if (static_cast<uint8_t>(dev->getType()) > 1 && dev->getType() != EspalexaDeviceType::color) //white spectrum support
|
||||
{
|
||||
json += ",\"ct\":" + String(dev->getCt());
|
||||
}
|
||||
}
|
||||
json += ",\"alert\":\"none";
|
||||
if (static_cast<uint8_t>(dev->getType()) > 1) json += "\",\"colormode\":\"" + modeString(dev->getColorMode());
|
||||
json += "\",\"mode\":\"homeautomation\",\"reachable\":true},";
|
||||
json += "\"type\":\"" + typeString(dev->getType());
|
||||
json += "\",\"name\":\"" + dev->getName();
|
||||
json += "\",\"modelid\":\"" + modelidString(dev->getType());
|
||||
json += "\",\"manufacturername\":\"Philips\",\"productname\":\"E" + String(static_cast<uint8_t>(dev->getType()));
|
||||
json += "\",\"uniqueid\":\"" + String(encodeLightId(deviceId+1));
|
||||
json += "\",\"swversion\":\"espalexa-2.4.4\"}";
|
||||
//char buf_bri[12] = "";
|
||||
//brightness support, add "bri" to JSON
|
||||
//if (dev->getType() != EspalexaDeviceType::onoff)
|
||||
// sprintf(buf_bri,",\"bri\":%u", dev->getLastValue()-1);
|
||||
|
||||
return json;
|
||||
char buf_col[80] = "";
|
||||
//color support
|
||||
if (static_cast<uint8_t>(dev->getType()) > 2)
|
||||
sprintf_P(buf_col,PSTR(",\"hue\":%u,\"sat\":%u,\"effect\":\"none\",\"xy\":[%f,%f]")
|
||||
,dev->getHue(), dev->getSat(), dev->getX(), dev->getY());
|
||||
|
||||
char buf_ct[16] = "";
|
||||
//white spectrum support
|
||||
if (static_cast<uint8_t>(dev->getType()) > 1 && dev->getType() != EspalexaDeviceType::color)
|
||||
sprintf(buf_ct, ",\"ct\":%u", dev->getCt());
|
||||
|
||||
char buf_cm[20] = "";
|
||||
if (static_cast<uint8_t>(dev->getType()) > 1)
|
||||
sprintf(buf_cm,PSTR("\",\"colormode\":\"%s"), modeString(dev->getColorMode()));
|
||||
|
||||
sprintf_P(buf, PSTR("{\"state\":{\"on\":%s,\"bri\":%u%s%s,\"alert\":\"none%s\",\"mode\":\"homeautomation\",\"reachable\":true},"
|
||||
"\"type\":\"%s\",\"name\":\"%s\",\"modelid\":\"%s\",\"manufacturername\":\"Philips\",\"productname\":\"E%u"
|
||||
"\",\"uniqueid\":\"%u\",\"swversion\":\"espalexa-2.4.6\"}")
|
||||
|
||||
, (dev->getValue())?"true":"false", dev->getLastValue()-1, buf_col, buf_ct, buf_cm, typeString(dev->getType()),
|
||||
dev->getName().c_str(), modelidString(dev->getType()), static_cast<uint8_t>(dev->getType()), encodeLightId(deviceId+1));
|
||||
}
|
||||
|
||||
//Espalexa status page /espalexa
|
||||
@ -181,14 +175,14 @@ private:
|
||||
res += "Value of device " + String(i+1) + " (" + dev->getName() + "): " + String(dev->getValue()) + " (" + typeString(dev->getType());
|
||||
if (static_cast<uint8_t>(dev->getType()) > 1) //color support
|
||||
{
|
||||
res += ", colormode=" + modeString(dev->getColorMode()) + ", r=" + String(dev->getR()) + ", g=" + String(dev->getG()) + ", b=" + String(dev->getB());
|
||||
res += ", colormode=" + String(modeString(dev->getColorMode())) + ", r=" + String(dev->getR()) + ", g=" + String(dev->getG()) + ", b=" + String(dev->getB());
|
||||
res +=", ct=" + String(dev->getCt()) + ", hue=" + String(dev->getHue()) + ", sat=" + String(dev->getSat()) + ", x=" + String(dev->getX()) + ", y=" + String(dev->getY());
|
||||
}
|
||||
res += ")\r\n";
|
||||
}
|
||||
res += "\r\nFree Heap: " + (String)ESP.getFreeHeap();
|
||||
res += "\r\nUptime: " + (String)millis();
|
||||
res += "\r\n\r\nEspalexa library v2.4.4 by Christian Schwinne 2020";
|
||||
res += "\r\n\r\nEspalexa library v2.4.6 by Christian Schwinne 2020";
|
||||
server->send(200, "text/plain", res);
|
||||
}
|
||||
#endif
|
||||
@ -206,7 +200,7 @@ private:
|
||||
EA_DEBUGLN("Body: " + body);
|
||||
if(!handleAlexaApiCall(server))
|
||||
#endif
|
||||
server->send(404, "text/plain", "Not Found (espalexa-internal)");
|
||||
server->send(404, "text/plain", "Not Found (espalexa)");
|
||||
}
|
||||
|
||||
//send description.xml device property page
|
||||
@ -216,30 +210,31 @@ private:
|
||||
IPAddress localIP = WiFi.localIP();
|
||||
char s[16];
|
||||
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
||||
char buf[1024];
|
||||
|
||||
String setup_xml = "<?xml version=\"1.0\" ?>"
|
||||
sprintf_P(buf,PSTR("<?xml version=\"1.0\" ?>"
|
||||
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
|
||||
"<specVersion><major>1</major><minor>0</minor></specVersion>"
|
||||
"<URLBase>http://"+ String(s) +":80/</URLBase>"
|
||||
"<URLBase>http://%s:80/</URLBase>"
|
||||
"<device>"
|
||||
"<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>"
|
||||
"<friendlyName>Espalexa ("+ String(s) +")</friendlyName>"
|
||||
"<friendlyName>Espalexa (%s)</friendlyName>"
|
||||
"<manufacturer>Royal Philips Electronics</manufacturer>"
|
||||
"<manufacturerURL>http://www.philips.com</manufacturerURL>"
|
||||
"<modelDescription>Philips hue Personal Wireless Lighting</modelDescription>"
|
||||
"<modelName>Philips hue bridge 2012</modelName>"
|
||||
"<modelNumber>929000226503</modelNumber>"
|
||||
"<modelURL>http://www.meethue.com</modelURL>"
|
||||
"<serialNumber>"+ escapedMac +"</serialNumber>"
|
||||
"<UDN>uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"</UDN>"
|
||||
"<serialNumber>%s</serialNumber>"
|
||||
"<UDN>uuid:2f402f80-da50-11e1-9b23-%s</UDN>"
|
||||
"<presentationURL>index.html</presentationURL>"
|
||||
"</device>"
|
||||
"</root>";
|
||||
"</root>"),s,s,escapedMac.c_str(),escapedMac.c_str());
|
||||
|
||||
server->send(200, "text/xml", setup_xml.c_str());
|
||||
server->send(200, "text/xml", buf);
|
||||
|
||||
EA_DEBUG("Sending :");
|
||||
EA_DEBUGLN(setup_xml);
|
||||
EA_DEBUG("Send setup.xml");
|
||||
//EA_DEBUGLN(setup_xml);
|
||||
}
|
||||
|
||||
//init the server
|
||||
@ -290,22 +285,23 @@ private:
|
||||
char s[16];
|
||||
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
||||
|
||||
String response =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
char buf[1024];
|
||||
|
||||
sprintf_P(buf,PSTR("HTTP/1.1 200 OK\r\n"
|
||||
"EXT:\r\n"
|
||||
"CACHE-CONTROL: max-age=100\r\n" // SSDP_INTERVAL
|
||||
"LOCATION: http://"+ String(s) +":80/description.xml\r\n"
|
||||
"LOCATION: http://%s:80/description.xml\r\n"
|
||||
"SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.17.0\r\n" // _modelName, _modelNumber
|
||||
"hue-bridgeid: "+ escapedMac +"\r\n"
|
||||
"hue-bridgeid: %s\r\n"
|
||||
"ST: urn:schemas-upnp-org:device:basic:1\r\n" // _deviceType
|
||||
"USN: uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"::ssdp:all\r\n" // _uuid::_deviceType
|
||||
"\r\n";
|
||||
"USN: uuid:2f402f80-da50-11e1-9b23-%s::ssdp:all\r\n" // _uuid::_deviceType
|
||||
"\r\n"),s,escapedMac.c_str(),escapedMac.c_str());
|
||||
|
||||
espalexaUdp.beginPacket(espalexaUdp.remoteIP(), espalexaUdp.remotePort());
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
espalexaUdp.write((uint8_t*)response.c_str(), response.length());
|
||||
espalexaUdp.write((uint8_t*)buf, strlen(buf));
|
||||
#else
|
||||
espalexaUdp.write(response.c_str());
|
||||
espalexaUdp.write(buf);
|
||||
#endif
|
||||
espalexaUdp.endPacket();
|
||||
}
|
||||
@ -362,7 +358,8 @@ public:
|
||||
if (!packetSize) return; //no new udp packet
|
||||
|
||||
EA_DEBUGLN("Got UDP!");
|
||||
int len = espalexaUdp.read(packetBuffer, 254);
|
||||
char packetBuffer[255]; //buffer to hold incoming udp packet
|
||||
uint16_t len = espalexaUdp.read(packetBuffer, 254);
|
||||
if (len > 0) {
|
||||
packetBuffer[len] = 0;
|
||||
}
|
||||
@ -447,13 +444,13 @@ public:
|
||||
{
|
||||
EA_DEBUGLN("devType");
|
||||
body = "";
|
||||
server->send(200, "application/json", "[{\"success\":{\"username\":\"2WLEDHardQrI3WHYTHoMcXHgEspsM8ZZRpSKtBQr\"}}]");
|
||||
server->send(200, "application/json", F("[{\"success\":{\"username\":\"2WLEDHardQrI3WHYTHoMcXHgEspsM8ZZRpSKtBQr\"}}]"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (req.indexOf("state") > 0) //client wants to control light
|
||||
{
|
||||
server->send(200, "application/json", "[{\"success\":{\"/lights/1/state/\": true}}]");
|
||||
server->send(200, "application/json", F("[{\"success\":{\"/lights/1/state/\": true}}]"));
|
||||
|
||||
uint32_t devId = req.substring(req.indexOf("lights")+7).toInt();
|
||||
EA_DEBUG("ls"); EA_DEBUGLN(devId);
|
||||
@ -530,7 +527,9 @@ public:
|
||||
for (int i = 0; i<currentDeviceCount; i++)
|
||||
{
|
||||
jsonTemp += "\"" + String(encodeLightId(i+1)) + "\":";
|
||||
jsonTemp += deviceJsonString(i+1);
|
||||
char buf[512];
|
||||
deviceJsonString(i+1, buf);
|
||||
jsonTemp += buf;
|
||||
if (i < currentDeviceCount-1) jsonTemp += ",";
|
||||
}
|
||||
jsonTemp += "}";
|
||||
@ -543,7 +542,9 @@ public:
|
||||
{
|
||||
server->send(200, "application/json", "{}");
|
||||
} else {
|
||||
server->send(200, "application/json", deviceJsonString(devId));
|
||||
char buf[512];
|
||||
deviceJsonString(devId, buf);
|
||||
server->send(200, "application/json", buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ EspalexaDevice::EspalexaDevice(String deviceName, DeviceCallbackFunction gnCallb
|
||||
_callbackDev = gnCallback;
|
||||
_type = t;
|
||||
if (t == EspalexaDeviceType::onoff) _type = EspalexaDeviceType::dimmable; //on/off is broken, so make dimmable device instead
|
||||
if (t == EspalexaDeviceType::whitespectrum) _mode = EspalexaColorMode::ct;
|
||||
_val = initialValue;
|
||||
_val_last = _val;
|
||||
}
|
||||
@ -122,37 +123,28 @@ uint32_t EspalexaDevice::getRGB()
|
||||
float temp = 10000/ _ct; //kelvins = 1,000,000/mired (and that /100)
|
||||
float r, g, b;
|
||||
|
||||
// Cold white to warm white receiving from Alexa: _ct = 199, 234, 284, 350, 383 (from cold white to warm white)
|
||||
switch (_ct) {
|
||||
case 199: rgb[0]=255,rgb[1]=255,rgb[2]=255;rgb[3]=255;break;
|
||||
case 234: rgb[0]=127,rgb[1]=127,rgb[2]=127;rgb[3]=255;break;
|
||||
case 284: rgb[0]=0,rgb[1]=0,rgb[2]=0;rgb[3]=255;break;
|
||||
case 350: rgb[0]=130,rgb[1]=90,rgb[2]=0;rgb[3]=255;break;
|
||||
case 383: rgb[0]=255,rgb[1]=153,rgb[2]=0;rgb[3]=255;break;
|
||||
default: {
|
||||
if( temp <= 66 ){
|
||||
r = 255;
|
||||
g = temp;
|
||||
g = 99.470802 * log(g) - 161.119568;
|
||||
if( temp <= 19){
|
||||
b = 0;
|
||||
} else {
|
||||
b = temp-10;
|
||||
b = 138.517731 * log(b) - 305.044793;
|
||||
}
|
||||
} else {
|
||||
r = temp - 60;
|
||||
r = 329.698727 * pow(r, -0.13320476);
|
||||
g = temp - 60;
|
||||
g = 288.12217 * pow(g, -0.07551485 );
|
||||
b = 255;
|
||||
}
|
||||
|
||||
rgb[0] = (byte)constrain(r,0.1,255.1);
|
||||
rgb[1] = (byte)constrain(g,0.1,255.1);
|
||||
rgb[2] = (byte)constrain(b,0.1,255.1);
|
||||
if (temp <= 66) {
|
||||
r = 255;
|
||||
g = temp;
|
||||
g = 99.470802 * log(g) - 161.119568;
|
||||
if (temp <= 19) {
|
||||
b = 0;
|
||||
} else {
|
||||
b = temp-10;
|
||||
b = 138.517731 * log(b) - 305.044793;
|
||||
}
|
||||
} else {
|
||||
r = temp - 60;
|
||||
r = 329.698727 * pow(r, -0.13320476);
|
||||
g = temp - 60;
|
||||
g = 288.12217 * pow(g, -0.07551485 );
|
||||
b = 255;
|
||||
}
|
||||
|
||||
rgb[0] = (byte)constrain(r,0.1,255.1);
|
||||
rgb[1] = (byte)constrain(g,0.1,255.1);
|
||||
rgb[2] = (byte)constrain(b,0.1,255.1);
|
||||
|
||||
} else if (_mode == EspalexaColorMode::hs)
|
||||
{
|
||||
float h = ((float)_hue)/65535.0;
|
||||
@ -226,7 +218,7 @@ uint32_t EspalexaDevice::getRGB()
|
||||
rgb[1] = 255.0*g;
|
||||
rgb[2] = 255.0*b;
|
||||
}
|
||||
_rgb = ((rgb[3] << 24) | (rgb[0] << 16) | (rgb[1] << 8) | (rgb[2])); //white value is only >0 if Alexa did provide a CT value, RGB colors will not be touched.
|
||||
_rgb = ((rgb[0] << 16) | (rgb[1] << 8) | (rgb[2]));
|
||||
return _rgb;
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,13 @@
|
||||
#define EspalexaDevice_h
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <functional>
|
||||
|
||||
typedef class EspalexaDevice;
|
||||
|
||||
typedef void (*BrightnessCallbackFunction) (uint8_t b);
|
||||
typedef void (*DeviceCallbackFunction) (EspalexaDevice* d);
|
||||
typedef void (*ColorCallbackFunction) (uint8_t br, uint32_t col);
|
||||
typedef std::function<void(uint8_t b)> BrightnessCallbackFunction;
|
||||
typedef std::function<void(EspalexaDevice* d)> DeviceCallbackFunction;
|
||||
typedef std::function<void(uint8_t br, uint32_t col)> ColorCallbackFunction;
|
||||
|
||||
enum class EspalexaColorMode : uint8_t { none = 0, ct = 1, hs = 2, xy = 3 };
|
||||
enum class EspalexaDeviceType : uint8_t { onoff = 0, dimmable = 1, whitespectrum = 2, color = 3, extendedcolor = 4 };
|
||||
|
@ -1,25 +1,25 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* UDP notifier
|
||||
* UDP sync notifier
|
||||
*/
|
||||
|
||||
#define WLEDPACKETSIZE 29
|
||||
#define UDP_IN_MAXSIZE 1472
|
||||
|
||||
|
||||
void notify(byte callMode, bool followUp=false)
|
||||
void notify(byte callMode, bool followUp)
|
||||
{
|
||||
if (!udpConnected) return;
|
||||
switch (callMode)
|
||||
{
|
||||
case 0: return;
|
||||
case 1: if (!notifyDirect) return; break;
|
||||
case 2: if (!notifyButton) return; break;
|
||||
case 4: if (!notifyDirect) return; break;
|
||||
case 6: if (!notifyDirect) return; break; //fx change
|
||||
case 7: if (!notifyHue) return; break;
|
||||
case 8: if (!notifyDirect) return; break;
|
||||
case 9: if (!notifyDirect) return; break;
|
||||
case 10: if (!notifyAlexa) return; break;
|
||||
case NOTIFIER_CALL_MODE_INIT: return;
|
||||
case NOTIFIER_CALL_MODE_DIRECT_CHANGE: if (!notifyDirect) return; break;
|
||||
case NOTIFIER_CALL_MODE_BUTTON: if (!notifyButton) return; break;
|
||||
case NOTIFIER_CALL_MODE_NIGHTLIGHT: if (!notifyDirect) return; break;
|
||||
case NOTIFIER_CALL_MODE_HUE: if (!notifyHue) return; break;
|
||||
case NOTIFIER_CALL_MODE_PRESET_CYCLE: if (!notifyDirect) return; break;
|
||||
case NOTIFIER_CALL_MODE_BLYNK: if (!notifyDirect) return; break;
|
||||
case NOTIFIER_CALL_MODE_ALEXA: if (!notifyAlexa) return; break;
|
||||
default: return;
|
||||
}
|
||||
byte udpOut[WLEDPACKETSIZE];
|
||||
@ -72,41 +72,20 @@ void notify(byte callMode, bool followUp=false)
|
||||
}
|
||||
|
||||
|
||||
void arlsLock(uint32_t timeoutMs)
|
||||
void realtimeLock(uint32_t timeoutMs, byte md)
|
||||
{
|
||||
if (!realtimeActive){
|
||||
if (!realtimeMode && !realtimeOverride){
|
||||
for (uint16_t i = 0; i < ledCount; i++)
|
||||
{
|
||||
strip.setPixelColor(i,0,0,0,0);
|
||||
}
|
||||
realtimeActive = true;
|
||||
}
|
||||
|
||||
realtimeTimeout = millis() + timeoutMs;
|
||||
if (timeoutMs == 255001 || timeoutMs == 65000) realtimeTimeout = UINT32_MAX;
|
||||
if (arlsForceMaxBri) strip.setBrightness(255);
|
||||
}
|
||||
realtimeMode = md;
|
||||
|
||||
|
||||
void handleE131Packet(e131_packet_t* p, IPAddress clientIP){
|
||||
//E1.31 protocol support
|
||||
uint16_t uni = htons(p->universe);
|
||||
if (uni < e131Universe || uni >= e131Universe + E131_MAX_UNIVERSE_COUNT) return;
|
||||
|
||||
uint16_t len = htons(p->property_value_count) -1;
|
||||
len /= 3; //one LED is 3 DMX channels
|
||||
|
||||
uint16_t multipacketOffset = (uni - e131Universe)*170; //if more than 170 LEDs (510 channels), client will send in next higher universe
|
||||
if (ledCount <= multipacketOffset) return;
|
||||
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
if (len + multipacketOffset > ledCount) len = ledCount - multipacketOffset;
|
||||
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
int j = i * 3 +1;
|
||||
setRealtimePixel(i + multipacketOffset, p->property_values[j], p->property_values[j+1], p->property_values[j+2], 0);
|
||||
}
|
||||
|
||||
e131NewData = true;
|
||||
if (arlsForceMaxBri && !realtimeOverride) strip.setBrightness(255);
|
||||
}
|
||||
|
||||
|
||||
@ -124,11 +103,11 @@ void handleNotifications()
|
||||
}
|
||||
|
||||
//unlock strip when realtime UDP times out
|
||||
if (realtimeActive && millis() > realtimeTimeout)
|
||||
if (realtimeMode && millis() > realtimeTimeout)
|
||||
{
|
||||
if (realtimeOverride == REALTIME_OVERRIDE_ONCE) realtimeOverride = REALTIME_OVERRIDE_NONE;
|
||||
strip.setBrightness(bri);
|
||||
realtimeActive = false;
|
||||
//strip.setMode(effectCurrent);
|
||||
realtimeMode = REALTIME_MODE_INACTIVE;
|
||||
realtimeIP[0] = 0;
|
||||
}
|
||||
|
||||
@ -146,7 +125,8 @@ void handleNotifications()
|
||||
DEBUG_PRINTLN(rgbUdp.remoteIP());
|
||||
uint8_t lbuf[packetSize];
|
||||
rgbUdp.read(lbuf, packetSize);
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_HYPERION);
|
||||
if (realtimeOverride) return;
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 0; i < packetSize -2; i += 3)
|
||||
{
|
||||
@ -166,7 +146,7 @@ void handleNotifications()
|
||||
notifierUdp.read(udpIn, packetSize);
|
||||
|
||||
//wled notifier, block if realtime packets active
|
||||
if (udpIn[0] == 0 && !realtimeActive && receiveNotifications)
|
||||
if (udpIn[0] == 0 && !realtimeMode && receiveNotifications)
|
||||
{
|
||||
//ignore notification if received within a second after sending a notification ourselves
|
||||
if (millis() - notificationSentTime < 1000) return;
|
||||
@ -221,56 +201,58 @@ void handleNotifications()
|
||||
if (nightlightActive) nightlightDelayMins = udpIn[7];
|
||||
|
||||
if (receiveNotificationBrightness || !someSel) bri = udpIn[2];
|
||||
colorUpdated(3);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
|
||||
} else if (udpIn[0] > 0 && udpIn[0] < 5 && receiveDirect) //1 warls //2 drgb //3 drgbw
|
||||
{
|
||||
realtimeIP = notifierUdp.remoteIP();
|
||||
DEBUG_PRINTLN(notifierUdp.remoteIP());
|
||||
if (packetSize > 1) {
|
||||
if (udpIn[1] == 0)
|
||||
{
|
||||
realtimeTimeout = 0;
|
||||
return;
|
||||
} else {
|
||||
arlsLock(udpIn[1]*1000 +1);
|
||||
}
|
||||
if (udpIn[0] == 1) //warls
|
||||
{
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0);
|
||||
}
|
||||
} else if (udpIn[0] == 2) //drgb
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -2; i += 3)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
if (packetSize < 2) return;
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 3) //drgbw
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 4) //dnrgb
|
||||
{
|
||||
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
|
||||
for (uint16_t i = 4; i < packetSize -2; i += 3)
|
||||
{
|
||||
if (id >= ledCount) break;
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
id++;
|
||||
}
|
||||
}
|
||||
strip.show();
|
||||
if (udpIn[1] == 0)
|
||||
{
|
||||
realtimeTimeout = 0;
|
||||
return;
|
||||
} else {
|
||||
realtimeLock(udpIn[1]*1000 +1, REALTIME_MODE_UDP);
|
||||
}
|
||||
if (realtimeOverride) return;
|
||||
|
||||
if (udpIn[0] == 1) //warls
|
||||
{
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0);
|
||||
}
|
||||
} else if (udpIn[0] == 2) //drgb
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -2; i += 3)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 3) //drgbw
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 4) //dnrgb
|
||||
{
|
||||
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
|
||||
for (uint16_t i = 4; i < packetSize -2; i += 3)
|
||||
{
|
||||
if (id >= ledCount) break;
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
id++;
|
||||
}
|
||||
}
|
||||
strip.show();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled01_eeprom.h)
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
*/
|
||||
|
461
wled00/wled.cpp
Normal file
461
wled00/wled.cpp
Normal file
@ -0,0 +1,461 @@
|
||||
#define WLED_DEFINE_GLOBAL_VARS //only in one source file, wled.cpp!
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
/*
|
||||
* Main WLED class implementation. Mostly initialization and connection logic
|
||||
*/
|
||||
|
||||
WLED::WLED()
|
||||
{
|
||||
}
|
||||
|
||||
// turns all LEDs off and restarts ESP
|
||||
void WLED::reset()
|
||||
{
|
||||
briT = 0;
|
||||
long dly = millis();
|
||||
while (millis() - dly < 250) {
|
||||
yield(); // enough time to send response to client
|
||||
}
|
||||
setAllLeds();
|
||||
DEBUG_PRINTLN("MODULE RESET");
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
bool oappendi(int i)
|
||||
{
|
||||
char s[11];
|
||||
sprintf(s, "%ld", i);
|
||||
return oappend(s);
|
||||
}
|
||||
|
||||
bool oappend(const char* txt)
|
||||
{
|
||||
uint16_t len = strlen(txt);
|
||||
if (olen + len >= OMAX)
|
||||
return false; // buffer full
|
||||
strcpy(obuf + olen, txt);
|
||||
olen += len;
|
||||
return true;
|
||||
}
|
||||
|
||||
void WLED::loop()
|
||||
{
|
||||
handleIR(); // 2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too
|
||||
handleConnection();
|
||||
handleSerial();
|
||||
handleNotifications();
|
||||
handleTransitions();
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
handleDMX();
|
||||
#endif
|
||||
userLoop();
|
||||
|
||||
yield();
|
||||
handleIO();
|
||||
handleIR();
|
||||
handleNetworkTime();
|
||||
handleAlexa();
|
||||
|
||||
handleOverlays();
|
||||
yield();
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
strip.setRgbwPwm();
|
||||
#endif
|
||||
|
||||
if (doReboot)
|
||||
reset();
|
||||
|
||||
if (!realtimeMode || realtimeOverride) // block stuff if WARLS/Adalight is enabled
|
||||
{
|
||||
if (apActive)
|
||||
dnsServer.processNextRequest();
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (WLED_CONNECTED && aOtaEnabled)
|
||||
ArduinoOTA.handle();
|
||||
#endif
|
||||
handleNightlight();
|
||||
yield();
|
||||
|
||||
handleHue();
|
||||
handleBlynk();
|
||||
|
||||
yield();
|
||||
if (!offMode)
|
||||
strip.service();
|
||||
}
|
||||
yield();
|
||||
#ifdef ESP8266
|
||||
MDNS.update();
|
||||
#endif
|
||||
if (millis() - lastMqttReconnectAttempt > 30000) {
|
||||
if (lastMqttReconnectAttempt > millis()) rolloverMillis++; //millis() rolls over every 50 days
|
||||
initMqtt();
|
||||
}
|
||||
|
||||
// DEBUG serial logging
|
||||
#ifdef WLED_DEBUG
|
||||
if (millis() - debugTime > 9999) {
|
||||
DEBUG_PRINTLN("---DEBUG INFO---");
|
||||
DEBUG_PRINT("Runtime: ");
|
||||
DEBUG_PRINTLN(millis());
|
||||
DEBUG_PRINT("Unix time: ");
|
||||
DEBUG_PRINTLN(now());
|
||||
DEBUG_PRINT("Free heap: ");
|
||||
DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
DEBUG_PRINT("Wifi state: ");
|
||||
DEBUG_PRINTLN(WiFi.status());
|
||||
if (WiFi.status() != lastWifiState) {
|
||||
wifiStateChangedTime = millis();
|
||||
}
|
||||
lastWifiState = WiFi.status();
|
||||
DEBUG_PRINT("State time: ");
|
||||
DEBUG_PRINTLN(wifiStateChangedTime);
|
||||
DEBUG_PRINT("NTP last sync: ");
|
||||
DEBUG_PRINTLN(ntpLastSyncTime);
|
||||
DEBUG_PRINT("Client IP: ");
|
||||
DEBUG_PRINTLN(WiFi.localIP());
|
||||
DEBUG_PRINT("Loops/sec: ");
|
||||
DEBUG_PRINTLN(loops / 10);
|
||||
loops = 0;
|
||||
debugTime = millis();
|
||||
}
|
||||
loops++;
|
||||
#endif // WLED_DEBU
|
||||
}
|
||||
|
||||
void WLED::setup()
|
||||
{
|
||||
EEPROM.begin(EEPSIZE);
|
||||
ledCount = EEPROM.read(229) + ((EEPROM.read(398) << 8) & 0xFF00);
|
||||
if (ledCount > MAX_LEDS || ledCount == 0)
|
||||
ledCount = 30;
|
||||
|
||||
#ifdef ESP8266
|
||||
#if LEDPIN == 3
|
||||
if (ledCount > MAX_LEDS_DMA)
|
||||
ledCount = MAX_LEDS_DMA; // DMA method uses too much ram
|
||||
#endif
|
||||
#endif
|
||||
Serial.begin(115200);
|
||||
Serial.setTimeout(50);
|
||||
DEBUG_PRINTLN();
|
||||
DEBUG_PRINT("---WLED ");
|
||||
DEBUG_PRINT(versionString);
|
||||
DEBUG_PRINT(" ");
|
||||
DEBUG_PRINT(VERSION);
|
||||
DEBUG_PRINTLN(" INIT---");
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
DEBUG_PRINT("esp32 ");
|
||||
DEBUG_PRINTLN(ESP.getSdkVersion());
|
||||
#else
|
||||
DEBUG_PRINT("esp8266 ");
|
||||
DEBUG_PRINTLN(ESP.getCoreVersion());
|
||||
#endif
|
||||
int heapPreAlloc = ESP.getFreeHeap();
|
||||
DEBUG_PRINT("heap ");
|
||||
DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
|
||||
strip.init(EEPROM.read(372), ledCount, EEPROM.read(2204)); // init LEDs quickly
|
||||
strip.setBrightness(0);
|
||||
|
||||
DEBUG_PRINT("LEDs inited. heap usage ~");
|
||||
DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
|
||||
|
||||
#ifndef WLED_DISABLE_FILESYSTEM
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
SPIFFS.begin(true);
|
||||
#endif
|
||||
SPIFFS.begin();
|
||||
#endif
|
||||
|
||||
DEBUG_PRINTLN("Load EEPROM");
|
||||
loadSettingsFromEEPROM(true);
|
||||
beginStrip();
|
||||
userSetup();
|
||||
if (strcmp(clientSSID, DEFAULT_CLIENT_SSID) == 0)
|
||||
showWelcomePage = true;
|
||||
WiFi.persistent(false);
|
||||
|
||||
if (macroBoot > 0)
|
||||
applyMacro(macroBoot);
|
||||
Serial.println("Ada");
|
||||
|
||||
// generate module IDs
|
||||
escapedMac = WiFi.macAddress();
|
||||
escapedMac.replace(":", "");
|
||||
escapedMac.toLowerCase();
|
||||
if (strcmp(cmDNS, "x") == 0) // fill in unique mdns default
|
||||
{
|
||||
strcpy(cmDNS, "wled-");
|
||||
sprintf(cmDNS + 5, "%*s", 6, escapedMac.c_str() + 6);
|
||||
}
|
||||
if (mqttDeviceTopic[0] == 0) {
|
||||
strcpy(mqttDeviceTopic, "wled/");
|
||||
sprintf(mqttDeviceTopic + 5, "%*s", 6, escapedMac.c_str() + 6);
|
||||
}
|
||||
if (mqttClientID[0] == 0) {
|
||||
strcpy(mqttClientID, "WLED-");
|
||||
sprintf(mqttClientID + 5, "%*s", 6, escapedMac.c_str() + 6);
|
||||
}
|
||||
|
||||
strip.service();
|
||||
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (aOtaEnabled) {
|
||||
ArduinoOTA.onStart([]() {
|
||||
#ifdef ESP8266
|
||||
wifi_set_sleep_type(NONE_SLEEP_T);
|
||||
#endif
|
||||
DEBUG_PRINTLN("Start ArduinoOTA");
|
||||
});
|
||||
if (strlen(cmDNS) > 0)
|
||||
ArduinoOTA.setHostname(cmDNS);
|
||||
}
|
||||
#endif
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
initDMX();
|
||||
#endif
|
||||
// HTTP server page init
|
||||
initServer();
|
||||
}
|
||||
|
||||
void WLED::beginStrip()
|
||||
{
|
||||
// Initialize NeoPixel Strip and button
|
||||
strip.setShowCallback(handleOverlayDraw);
|
||||
|
||||
#ifdef BTNPIN
|
||||
pinMode(BTNPIN, INPUT_PULLUP);
|
||||
#endif
|
||||
|
||||
if (bootPreset > 0)
|
||||
applyPreset(bootPreset, turnOnAtBoot);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_INIT);
|
||||
|
||||
// init relay pin
|
||||
#if RLYPIN >= 0
|
||||
pinMode(RLYPIN, OUTPUT);
|
||||
#if RLYMDE
|
||||
digitalWrite(RLYPIN, bri);
|
||||
#else
|
||||
digitalWrite(RLYPIN, !bri);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// disable button if it is "pressed" unintentionally
|
||||
#ifdef BTNPIN
|
||||
if (digitalRead(BTNPIN) == LOW)
|
||||
buttonEnabled = false;
|
||||
#else
|
||||
buttonEnabled = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void WLED::initAP(bool resetAP)
|
||||
{
|
||||
if (apBehavior == AP_BEHAVIOR_BUTTON_ONLY && !resetAP)
|
||||
return;
|
||||
|
||||
if (!apSSID[0] || resetAP)
|
||||
strcpy(apSSID, "WLED-AP");
|
||||
if (resetAP)
|
||||
strcpy(apPass, DEFAULT_AP_PASS);
|
||||
DEBUG_PRINT("Opening access point ");
|
||||
DEBUG_PRINTLN(apSSID);
|
||||
WiFi.softAPConfig(IPAddress(4, 3, 2, 1), IPAddress(4, 3, 2, 1), IPAddress(255, 255, 255, 0));
|
||||
WiFi.softAP(apSSID, apPass, apChannel, apHide);
|
||||
|
||||
if (!apActive) // start captive portal if AP active
|
||||
{
|
||||
DEBUG_PRINTLN("Init AP interfaces");
|
||||
server.begin();
|
||||
if (udpPort > 0 && udpPort != ntpLocalPort) {
|
||||
udpConnected = notifierUdp.begin(udpPort);
|
||||
}
|
||||
if (udpRgbPort > 0 && udpRgbPort != ntpLocalPort && udpRgbPort != udpPort) {
|
||||
udpRgbConnected = rgbUdp.begin(udpRgbPort);
|
||||
}
|
||||
|
||||
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
|
||||
dnsServer.start(53, "*", WiFi.softAPIP());
|
||||
}
|
||||
apActive = true;
|
||||
}
|
||||
|
||||
void WLED::initConnection()
|
||||
{
|
||||
WiFi.disconnect(true); // close old connections
|
||||
#ifdef ESP8266
|
||||
WiFi.setPhyMode(WIFI_PHY_MODE_11N);
|
||||
#endif
|
||||
|
||||
if (staticIP[0] != 0 && staticGateway[0] != 0) {
|
||||
WiFi.config(staticIP, staticGateway, staticSubnet, IPAddress(8, 8, 8, 8));
|
||||
} else {
|
||||
WiFi.config(0U, 0U, 0U);
|
||||
}
|
||||
|
||||
lastReconnectAttempt = millis();
|
||||
|
||||
if (!WLED_WIFI_CONFIGURED) {
|
||||
DEBUG_PRINT("No connection configured. ");
|
||||
if (!apActive)
|
||||
initAP(); // instantly go to ap mode
|
||||
return;
|
||||
} else if (!apActive) {
|
||||
if (apBehavior == AP_BEHAVIOR_ALWAYS) {
|
||||
initAP();
|
||||
} else {
|
||||
DEBUG_PRINTLN("Access point disabled.");
|
||||
WiFi.softAPdisconnect(true);
|
||||
WiFi.mode(WIFI_STA);
|
||||
}
|
||||
}
|
||||
showWelcomePage = false;
|
||||
|
||||
DEBUG_PRINT("Connecting to ");
|
||||
DEBUG_PRINT(clientSSID);
|
||||
DEBUG_PRINTLN("...");
|
||||
|
||||
#ifdef ESP8266
|
||||
WiFi.hostname(serverDescription);
|
||||
#endif
|
||||
|
||||
WiFi.begin(clientSSID, clientPass);
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
WiFi.setSleep(!noWifiSleep);
|
||||
WiFi.setHostname(serverDescription);
|
||||
#else
|
||||
wifi_set_sleep_type((noWifiSleep) ? NONE_SLEEP_T : MODEM_SLEEP_T);
|
||||
#endif
|
||||
}
|
||||
|
||||
void WLED::initInterfaces()
|
||||
{
|
||||
DEBUG_PRINTLN("Init STA interfaces");
|
||||
|
||||
if (hueIP[0] == 0) {
|
||||
hueIP[0] = WiFi.localIP()[0];
|
||||
hueIP[1] = WiFi.localIP()[1];
|
||||
hueIP[2] = WiFi.localIP()[2];
|
||||
}
|
||||
|
||||
// init Alexa hue emulation
|
||||
if (alexaEnabled)
|
||||
alexaInit();
|
||||
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (aOtaEnabled)
|
||||
ArduinoOTA.begin();
|
||||
#endif
|
||||
|
||||
strip.service();
|
||||
// Set up mDNS responder:
|
||||
if (strlen(cmDNS) > 0) {
|
||||
if (!aOtaEnabled)
|
||||
MDNS.begin(cmDNS);
|
||||
|
||||
DEBUG_PRINTLN("mDNS started");
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
MDNS.addService("wled", "tcp", 80);
|
||||
MDNS.addServiceTxt("wled", "tcp", "mac", escapedMac.c_str());
|
||||
}
|
||||
server.begin();
|
||||
|
||||
if (udpPort > 0 && udpPort != ntpLocalPort) {
|
||||
udpConnected = notifierUdp.begin(udpPort);
|
||||
if (udpConnected && udpRgbPort != udpPort)
|
||||
udpRgbConnected = rgbUdp.begin(udpRgbPort);
|
||||
}
|
||||
if (ntpEnabled)
|
||||
ntpConnected = ntpUdp.begin(ntpLocalPort);
|
||||
|
||||
initBlynk(blynkApiKey);
|
||||
e131.begin(e131Multicast, e131Port, e131Universe, E131_MAX_UNIVERSE_COUNT);
|
||||
reconnectHue();
|
||||
initMqtt();
|
||||
interfacesInited = true;
|
||||
wasConnected = true;
|
||||
}
|
||||
|
||||
byte stacO = 0;
|
||||
uint32_t lastHeap;
|
||||
unsigned long heapTime = 0;
|
||||
|
||||
void WLED::handleConnection()
|
||||
{
|
||||
if (millis() < 2000 && (!WLED_WIFI_CONFIGURED || apBehavior == AP_BEHAVIOR_ALWAYS))
|
||||
return;
|
||||
if (lastReconnectAttempt == 0)
|
||||
initConnection();
|
||||
|
||||
// reconnect WiFi to clear stale allocations if heap gets too low
|
||||
if (millis() - heapTime > 5000) {
|
||||
uint32_t heap = ESP.getFreeHeap();
|
||||
if (heap < 9000 && lastHeap < 9000) {
|
||||
DEBUG_PRINT("Heap too low! ");
|
||||
DEBUG_PRINTLN(heap);
|
||||
forceReconnect = true;
|
||||
}
|
||||
lastHeap = heap;
|
||||
heapTime = millis();
|
||||
}
|
||||
|
||||
byte stac = 0;
|
||||
if (apActive) {
|
||||
#ifdef ESP8266
|
||||
stac = wifi_softap_get_station_num();
|
||||
#else
|
||||
wifi_sta_list_t stationList;
|
||||
esp_wifi_ap_get_sta_list(&stationList);
|
||||
stac = stationList.num;
|
||||
#endif
|
||||
if (stac != stacO) {
|
||||
stacO = stac;
|
||||
DEBUG_PRINT("Connected AP clients: ");
|
||||
DEBUG_PRINTLN(stac);
|
||||
if (!WLED_CONNECTED && WLED_WIFI_CONFIGURED) { // trying to connect, but not connected
|
||||
if (stac)
|
||||
WiFi.disconnect(); // disable search so that AP can work
|
||||
else
|
||||
initConnection(); // restart search
|
||||
}
|
||||
}
|
||||
}
|
||||
if (forceReconnect) {
|
||||
DEBUG_PRINTLN("Forcing reconnect.");
|
||||
initConnection();
|
||||
interfacesInited = false;
|
||||
forceReconnect = false;
|
||||
wasConnected = false;
|
||||
return;
|
||||
}
|
||||
if (!WLED_CONNECTED) {
|
||||
if (interfacesInited) {
|
||||
DEBUG_PRINTLN("Disconnected!");
|
||||
interfacesInited = false;
|
||||
initConnection();
|
||||
}
|
||||
if (millis() - lastReconnectAttempt > ((stac) ? 300000 : 20000) && WLED_WIFI_CONFIGURED)
|
||||
initConnection();
|
||||
if (!apActive && millis() - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == AP_BEHAVIOR_NO_CONN))
|
||||
initAP();
|
||||
} else if (!interfacesInited) { // newly connected
|
||||
DEBUG_PRINTLN("");
|
||||
DEBUG_PRINT("Connected! IP address: ");
|
||||
DEBUG_PRINTLN(WiFi.localIP());
|
||||
initInterfaces();
|
||||
userConnected();
|
||||
|
||||
// shut down AP
|
||||
if (apBehavior != AP_BEHAVIOR_ALWAYS && apActive) {
|
||||
dnsServer.stop();
|
||||
WiFi.softAPdisconnect(true);
|
||||
apActive = false;
|
||||
DEBUG_PRINTLN("Access point disabled.");
|
||||
}
|
||||
}
|
||||
}
|
523
wled00/wled.h
Normal file
523
wled00/wled.h
Normal file
@ -0,0 +1,523 @@
|
||||
#ifndef WLED_H
|
||||
#define WLED_H
|
||||
/*
|
||||
Main sketch, global variable declarations
|
||||
@title WLED project sketch
|
||||
@version 0.10.0
|
||||
@author Christian Schwinne
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2005100
|
||||
|
||||
// ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS).
|
||||
|
||||
// ESP8266-01 (black) has 1MB flash and can thus fit the whole program. Use 1M(64K SPIFFS).
|
||||
// Uncomment some of the following lines to disable features to compile for ESP8266-01 (max flash size 434kB):
|
||||
// Alternatively, with platformio pass your chosen flags to your custom build target in platformio.ini.override
|
||||
|
||||
// You are required to disable over-the-air updates:
|
||||
//#define WLED_DISABLE_OTA // saves 14kb
|
||||
|
||||
// You need to choose some of these features to disable:
|
||||
//#define WLED_DISABLE_ALEXA // saves 11kb
|
||||
//#define WLED_DISABLE_BLYNK // saves 6kb
|
||||
//#define WLED_DISABLE_CRONIXIE // saves 3kb
|
||||
//#define WLED_DISABLE_HUESYNC // saves 4kb
|
||||
//#define WLED_DISABLE_INFRARED // there is no pin left for this on ESP8266-01, saves 12kb
|
||||
#define WLED_ENABLE_MQTT // saves 12kb
|
||||
#define WLED_ENABLE_ADALIGHT // saves 500b only
|
||||
//#define WLED_ENABLE_DMX // uses 3.5kb (use LEDPIN other than 2)
|
||||
|
||||
#define WLED_DISABLE_FILESYSTEM // SPIFFS is not used by any WLED feature yet
|
||||
//#define WLED_ENABLE_FS_SERVING // Enable sending html file from SPIFFS before serving progmem version
|
||||
//#define WLED_ENABLE_FS_EDITOR // enable /edit page for editing SPIFFS content. Will also be disabled with OTA lock
|
||||
|
||||
// to toggle usb serial debug (un)comment the following line
|
||||
//#define WLED_DEBUG
|
||||
|
||||
// Library inclusions.
|
||||
#include <Arduino.h>
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <ESPAsyncTCP.h>
|
||||
extern "C"
|
||||
{
|
||||
#include <user_interface.h>
|
||||
}
|
||||
#else // ESP32
|
||||
#include <WiFi.h>
|
||||
#include "esp_wifi.h"
|
||||
#include <ESPmDNS.h>
|
||||
#include <AsyncTCP.h>
|
||||
#include "SPIFFS.h"
|
||||
#endif
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <EEPROM.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <DNSServer.h>
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
#include <ArduinoOTA.h>
|
||||
#endif
|
||||
#include <SPIFFSEditor.h>
|
||||
#include "src/dependencies/time/TimeLib.h"
|
||||
#include "src/dependencies/timezone/Timezone.h"
|
||||
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
#define ESPALEXA_ASYNC
|
||||
#define ESPALEXA_NO_SUBPAGE
|
||||
#define ESPALEXA_MAXDEVICES 1
|
||||
// #define ESPALEXA_DEBUG
|
||||
#include "src/dependencies/espalexa/Espalexa.h"
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
#include "src/dependencies/blynk/BlynkSimpleEsp.h"
|
||||
#endif
|
||||
|
||||
#include "src/dependencies/e131/ESPAsyncE131.h"
|
||||
#include "src/dependencies/async-mqtt-client/AsyncMqttClient.h"
|
||||
#include "src/dependencies/json/AsyncJson-v6.h"
|
||||
#include "src/dependencies/json/ArduinoJson-v6.h"
|
||||
|
||||
#include "fcn_declare.h"
|
||||
#include "html_ui.h"
|
||||
#include "html_settings.h"
|
||||
#include "html_other.h"
|
||||
#include "FX.h"
|
||||
#include "ir_codes.h"
|
||||
#include "const.h"
|
||||
|
||||
#ifndef CLIENT_SSID
|
||||
#define CLIENT_SSID DEFAULT_CLIENT_SSID
|
||||
#endif
|
||||
|
||||
#ifndef CLIENT_PASS
|
||||
#define CLIENT_PASS ""
|
||||
#endif
|
||||
|
||||
#if IR_PIN < 0
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
#define WLED_DISABLE_INFRARED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
#include <IRremoteESP8266.h>
|
||||
#include <IRrecv.h>
|
||||
#include <IRutils.h>
|
||||
#endif
|
||||
|
||||
// remove flicker because PWM signal of RGB channels can become out of phase (part of core as of Arduino core v2.7.0)
|
||||
//#if defined(WLED_USE_ANALOG_LEDS) && defined(ESP8266)
|
||||
// #include "src/dependencies/arduino/core_esp8266_waveform.h"
|
||||
//#endif
|
||||
|
||||
// enable additional debug output
|
||||
#ifdef WLED_DEBUG
|
||||
#ifndef ESP8266
|
||||
#include <rom/rtc.h>
|
||||
#endif
|
||||
#define DEBUG_PRINT(x) Serial.print(x)
|
||||
#define DEBUG_PRINTLN(x) Serial.println(x)
|
||||
#define DEBUG_PRINTF(x) Serial.printf(x)
|
||||
#else
|
||||
#define DEBUG_PRINT(x)
|
||||
#define DEBUG_PRINTLN(x)
|
||||
#define DEBUG_PRINTF(x)
|
||||
#endif
|
||||
|
||||
// GLOBAL VARIABLES
|
||||
// both declared and defined in header (solution from http://www.keil.com/support/docs/1868.htm)
|
||||
//
|
||||
//e.g. byte test = 2 becomes WLED_GLOBAL byte test _INIT(2);
|
||||
// int arr[]{0,1,2} becomes WLED_GLOBAL int arr[] _INIT_N(({0,1,2}));
|
||||
|
||||
#ifndef WLED_DEFINE_GLOBAL_VARS
|
||||
# define WLED_GLOBAL extern
|
||||
# define _INIT(x)
|
||||
# define _INIT_N(x)
|
||||
#else
|
||||
# define WLED_GLOBAL
|
||||
# define _INIT(x) = x
|
||||
|
||||
//needed to ignore commas in array definitions
|
||||
#define UNPACK( ... ) __VA_ARGS__
|
||||
# define _INIT_N(x) UNPACK x
|
||||
#endif
|
||||
|
||||
// Global Variable definitions
|
||||
WLED_GLOBAL char versionString[] _INIT("0.10.0");
|
||||
#define WLED_CODENAME "Namigai"
|
||||
|
||||
// AP and OTA default passwords (for maximum security change them!)
|
||||
WLED_GLOBAL char apPass[65] _INIT(DEFAULT_AP_PASS);
|
||||
WLED_GLOBAL char otaPass[33] _INIT(DEFAULT_OTA_PASS);
|
||||
|
||||
// Hardware CONFIG (only changeble HERE, not at runtime)
|
||||
// LED strip pin, button pin and IR pin changeable in NpbWrapper.h!
|
||||
|
||||
WLED_GLOBAL byte auxDefaultState _INIT(0); // 0: input 1: high 2: low
|
||||
WLED_GLOBAL byte auxTriggeredState _INIT(0); // 0: input 1: high 2: low
|
||||
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)
|
||||
WLED_GLOBAL char clientSSID[33] _INIT(CLIENT_SSID);
|
||||
WLED_GLOBAL char clientPass[65] _INIT(CLIENT_PASS);
|
||||
WLED_GLOBAL char cmDNS[33] _INIT("x"); // mDNS address (placeholder, is replaced by wledXXXXXX.local)
|
||||
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 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 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
|
||||
WLED_GLOBAL bool noWifiSleep _INIT(false); // disabling modem sleep modes will increase heat output and power usage, but may help with connection issues
|
||||
|
||||
// LED CONFIG
|
||||
WLED_GLOBAL uint16_t ledCount _INIT(30); // overcurrent prevented by ABL
|
||||
WLED_GLOBAL bool useRGBW _INIT(false); // SK6812 strips can contain an extra White channel
|
||||
WLED_GLOBAL bool turnOnAtBoot _INIT(true); // turn on LEDs at power-up
|
||||
WLED_GLOBAL byte bootPreset _INIT(0); // save preset to load after power-up
|
||||
|
||||
WLED_GLOBAL byte col[] _INIT_N(({ 255, 160, 0, 0 })); // current RGB(W) primary color. col[] should be updated if you want to change the color.
|
||||
WLED_GLOBAL byte colSec[] _INIT_N(({ 0, 0, 0, 0 })); // current RGB(W) secondary color
|
||||
WLED_GLOBAL byte briS _INIT(128); // default brightness
|
||||
|
||||
WLED_GLOBAL byte nightlightTargetBri _INIT(0); // brightness after nightlight is over
|
||||
WLED_GLOBAL byte nightlightDelayMins _INIT(60);
|
||||
WLED_GLOBAL bool nightlightFade _INIT(true); // if enabled, light will gradually dim towards the target bri. Otherwise, it will instantly set after delay over
|
||||
WLED_GLOBAL bool nightlightColorFade _INIT(false); // if enabled, light will gradually fade color from primary to secondary color.
|
||||
WLED_GLOBAL bool fadeTransition _INIT(true); // enable crossfading color transition
|
||||
WLED_GLOBAL uint16_t transitionDelay _INIT(750); // default crossfade duration in ms
|
||||
|
||||
WLED_GLOBAL bool skipFirstLed _INIT(false); // ignore first LED in strip (useful if you need the LED as signal repeater)
|
||||
WLED_GLOBAL byte briMultiplier _INIT(100); // % of brightness to set (to limit power, if you set it to 50 and set bri to 255, actual brightness will be 127)
|
||||
|
||||
// User Interface CONFIG
|
||||
WLED_GLOBAL char serverDescription[33] _INIT("WLED"); // Name of module
|
||||
WLED_GLOBAL bool syncToggleReceive _INIT(false); // UIs which only have a single button for sync should toggle send+receive if this is true, only send otherwise
|
||||
|
||||
// Sync CONFIG
|
||||
WLED_GLOBAL bool buttonEnabled _INIT(true);
|
||||
WLED_GLOBAL byte irEnabled _INIT(0); // Infrared receiver
|
||||
|
||||
WLED_GLOBAL uint16_t udpPort _INIT(21324); // WLED notifier default port
|
||||
WLED_GLOBAL uint16_t udpRgbPort _INIT(19446); // Hyperion port
|
||||
|
||||
WLED_GLOBAL bool receiveNotificationBrightness _INIT(true); // apply brightness from incoming notifications
|
||||
WLED_GLOBAL bool receiveNotificationColor _INIT(true); // apply color
|
||||
WLED_GLOBAL bool receiveNotificationEffects _INIT(true); // apply effects setup
|
||||
WLED_GLOBAL bool notifyDirect _INIT(false); // send notification if change via UI or HTTP API
|
||||
WLED_GLOBAL bool notifyButton _INIT(false); // send if updated by button or infrared remote
|
||||
WLED_GLOBAL bool notifyAlexa _INIT(false); // send notification if updated via Alexa
|
||||
WLED_GLOBAL bool notifyMacro _INIT(false); // send notification for macro
|
||||
WLED_GLOBAL bool notifyHue _INIT(true); // send notification if Hue light changes
|
||||
WLED_GLOBAL bool notifyTwice _INIT(false); // notifications use UDP: enable if devices don't sync reliably
|
||||
|
||||
WLED_GLOBAL bool alexaEnabled _INIT(false); // enable device discovery by Amazon Echo
|
||||
WLED_GLOBAL char alexaInvocationName[33] _INIT("Light"); // speech control name of device. Choose something voice-to-text can understand
|
||||
|
||||
WLED_GLOBAL char blynkApiKey[36] _INIT(""); // Auth token for Blynk server. If empty, no connection will be made
|
||||
|
||||
WLED_GLOBAL uint16_t realtimeTimeoutMs _INIT(2500); // ms timeout of realtime mode before returning to normal mode
|
||||
WLED_GLOBAL int arlsOffset _INIT(0); // realtime LED offset
|
||||
WLED_GLOBAL bool receiveDirect _INIT(true); // receive UDP realtime
|
||||
WLED_GLOBAL bool arlsDisableGammaCorrection _INIT(true); // activate if gamma correction is handled by the source
|
||||
WLED_GLOBAL bool arlsForceMaxBri _INIT(false); // enable to force max brightness if source has very dark colors that would be black
|
||||
|
||||
WLED_GLOBAL uint16_t e131Universe _INIT(1); // settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consequtive universes)
|
||||
WLED_GLOBAL uint16_t e131Port _INIT(5568); // DMX in port. E1.31 default is 5568, Art-Net is 6454
|
||||
WLED_GLOBAL byte DMXMode _INIT(DMX_MODE_MULTIPLE_RGB); // DMX mode (s.a.)
|
||||
WLED_GLOBAL uint16_t DMXAddress _INIT(1); // DMX start address of fixture, a.k.a. first Channel [for E1.31 (sACN) protocol]
|
||||
WLED_GLOBAL byte DMXOldDimmer _INIT(0); // only update brightness on change
|
||||
WLED_GLOBAL byte e131LastSequenceNumber[E131_MAX_UNIVERSE_COUNT]; // to detect packet loss
|
||||
WLED_GLOBAL bool e131Multicast _INIT(false); // multicast or unicast
|
||||
WLED_GLOBAL bool e131SkipOutOfSequence _INIT(false); // freeze instead of flickering
|
||||
|
||||
WLED_GLOBAL bool mqttEnabled _INIT(false);
|
||||
WLED_GLOBAL char mqttDeviceTopic[33] _INIT(""); // main MQTT topic (individual per device, default is wled/mac)
|
||||
WLED_GLOBAL char mqttGroupTopic[33] _INIT("wled/all"); // second MQTT topic (for example to group devices)
|
||||
WLED_GLOBAL char mqttServer[33] _INIT(""); // both domains and IPs should work (no SSL)
|
||||
WLED_GLOBAL char mqttUser[41] _INIT(""); // optional: username for MQTT auth
|
||||
WLED_GLOBAL char mqttPass[41] _INIT(""); // optional: password for MQTT auth
|
||||
WLED_GLOBAL char mqttClientID[41] _INIT(""); // override the client ID
|
||||
WLED_GLOBAL uint16_t mqttPort _INIT(1883);
|
||||
|
||||
WLED_GLOBAL bool huePollingEnabled _INIT(false); // poll hue bridge for light state
|
||||
WLED_GLOBAL uint16_t huePollIntervalMs _INIT(2500); // low values (< 1sec) may cause lag but offer quicker response
|
||||
WLED_GLOBAL char hueApiKey[47] _INIT("api"); // key token will be obtained from bridge
|
||||
WLED_GLOBAL byte huePollLightId _INIT(1); // ID of hue lamp to sync to. Find the ID in the hue app ("about" section)
|
||||
WLED_GLOBAL IPAddress hueIP _INIT((0, 0, 0, 0)); // IP address of the bridge
|
||||
WLED_GLOBAL bool hueApplyOnOff _INIT(true);
|
||||
WLED_GLOBAL bool hueApplyBri _INIT(true);
|
||||
WLED_GLOBAL bool hueApplyColor _INIT(true);
|
||||
|
||||
// Time CONFIG
|
||||
WLED_GLOBAL bool ntpEnabled _INIT(false); // get internet time. Only required if you use clock overlays or time-activated macros
|
||||
WLED_GLOBAL bool useAMPM _INIT(false); // 12h/24h clock format
|
||||
WLED_GLOBAL byte currentTimezone _INIT(0); // Timezone ID. Refer to timezones array in wled10_ntp.ino
|
||||
WLED_GLOBAL int utcOffsetSecs _INIT(0); // Seconds to offset from UTC before timzone calculation
|
||||
|
||||
WLED_GLOBAL byte overlayDefault _INIT(0); // 0: no overlay 1: analog clock 2: single-digit clocl 3: cronixie
|
||||
WLED_GLOBAL byte overlayMin _INIT(0), overlayMax _INIT(ledCount - 1); // boundaries of overlay mode
|
||||
|
||||
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 analogClock5MinuteMarks _INIT(false); // Light pixels at every 5-minute position
|
||||
|
||||
WLED_GLOBAL char cronixieDisplay[7] _INIT("HHMMSS"); // Cronixie Display mask. See wled13_cronixie.ino
|
||||
WLED_GLOBAL bool cronixieBacklight _INIT(true); // Allow digits to be back-illuminated
|
||||
|
||||
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 countdownDay _INIT(1) , countdownHour _INIT(0);
|
||||
WLED_GLOBAL byte countdownMin _INIT(0) , countdownSec _INIT(0);
|
||||
|
||||
WLED_GLOBAL byte macroBoot _INIT(0); // macro loaded after startup
|
||||
WLED_GLOBAL byte macroNl _INIT(0); // after nightlight delay over
|
||||
WLED_GLOBAL byte macroCountdown _INIT(0);
|
||||
WLED_GLOBAL byte macroAlexaOn _INIT(0), macroAlexaOff _INIT(0);
|
||||
WLED_GLOBAL byte macroButton _INIT(0), macroLongPress _INIT(0), macroDoublePress _INIT(0);
|
||||
|
||||
// Security CONFIG
|
||||
WLED_GLOBAL bool otaLock _INIT(false); // prevents OTA firmware updates without password. ALWAYS enable if system exposed to any public networks
|
||||
WLED_GLOBAL bool wifiLock _INIT(false); // prevents access to WiFi settings when OTA lock is enabled
|
||||
WLED_GLOBAL bool aOtaEnabled _INIT(true); // ArduinoOTA allows easy updates directly from the IDE. Careful, it does not auto-disable when OTA lock is on
|
||||
|
||||
WLED_GLOBAL uint16_t userVar0 _INIT(0), userVar1 _INIT(0); //available for use in usermod
|
||||
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
// dmx CONFIG
|
||||
WLED_GLOBAL byte DMXChannels _INIT(7); // number of channels per fixture
|
||||
WLED_GLOBAL byte DMXFixtureMap[15] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }));
|
||||
// assigns the different channels to different functions. See wled21_dmx.ino for more information.
|
||||
WLED_GLOBAL uint16_t DMXGap _INIT(10); // gap between the fixtures. makes addressing easier because you don't have to memorize odd numbers when climbing up onto a rig.
|
||||
WLED_GLOBAL uint16_t DMXStart _INIT(10); // start address of the first fixture
|
||||
WLED_GLOBAL uint16_t DMXStartLED _INIT(0); // LED from which DMX fixtures start
|
||||
#endif
|
||||
|
||||
// internal global variable declarations
|
||||
// wifi
|
||||
WLED_GLOBAL bool apActive _INIT(false);
|
||||
WLED_GLOBAL bool forceReconnect _INIT(false);
|
||||
WLED_GLOBAL uint32_t lastReconnectAttempt _INIT(0);
|
||||
WLED_GLOBAL bool interfacesInited _INIT(false);
|
||||
WLED_GLOBAL bool wasConnected _INIT(false);
|
||||
|
||||
// color
|
||||
WLED_GLOBAL byte colOld[] _INIT_N(({ 0, 0, 0, 0 })); // color before transition
|
||||
WLED_GLOBAL byte colT[] _INIT_N(({ 0, 0, 0, 0 })); // color that is currently displayed on the LEDs
|
||||
WLED_GLOBAL byte colIT[] _INIT_N(({ 0, 0, 0, 0 })); // color that was last sent to LEDs
|
||||
WLED_GLOBAL byte colSecT[] _INIT_N(({ 0, 0, 0, 0 }));
|
||||
WLED_GLOBAL byte colSecOld[] _INIT_N(({ 0, 0, 0, 0 }));
|
||||
WLED_GLOBAL byte colSecIT[] _INIT_N(({ 0, 0, 0, 0 }));
|
||||
|
||||
WLED_GLOBAL byte lastRandomIndex _INIT(0); // used to save last random color so the new one is not the same
|
||||
|
||||
// transitions
|
||||
WLED_GLOBAL bool transitionActive _INIT(false);
|
||||
WLED_GLOBAL uint16_t transitionDelayDefault _INIT(transitionDelay);
|
||||
WLED_GLOBAL uint16_t transitionDelayTemp _INIT(transitionDelay);
|
||||
WLED_GLOBAL unsigned long transitionStartTime;
|
||||
WLED_GLOBAL float tperLast _INIT(0); // crossfade transition progress, 0.0f - 1.0f
|
||||
WLED_GLOBAL bool jsonTransitionOnce _INIT(false);
|
||||
|
||||
// nightlight
|
||||
WLED_GLOBAL bool nightlightActive _INIT(false);
|
||||
WLED_GLOBAL bool nightlightActiveOld _INIT(false);
|
||||
WLED_GLOBAL uint32_t nightlightDelayMs _INIT(10);
|
||||
WLED_GLOBAL byte nightlightDelayMinsDefault _INIT(nightlightDelayMins);
|
||||
WLED_GLOBAL unsigned long nightlightStartTime;
|
||||
WLED_GLOBAL byte briNlT _INIT(0); // current nightlight brightness
|
||||
WLED_GLOBAL byte colNlT[] _INIT_N(({ 0, 0, 0, 0 })); // current nightlight color
|
||||
|
||||
// brightness
|
||||
WLED_GLOBAL unsigned long lastOnTime _INIT(0);
|
||||
WLED_GLOBAL bool offMode _INIT(!turnOnAtBoot);
|
||||
WLED_GLOBAL byte bri _INIT(briS);
|
||||
WLED_GLOBAL byte briOld _INIT(0);
|
||||
WLED_GLOBAL byte briT _INIT(0);
|
||||
WLED_GLOBAL byte briIT _INIT(0);
|
||||
WLED_GLOBAL byte briLast _INIT(128); // brightness before turned off. Used for toggle function
|
||||
WLED_GLOBAL byte whiteLast _INIT(128); // white channel before turned off. Used for toggle function
|
||||
|
||||
// button
|
||||
WLED_GLOBAL bool buttonPressedBefore _INIT(false);
|
||||
WLED_GLOBAL bool buttonLongPressed _INIT(false);
|
||||
WLED_GLOBAL unsigned long buttonPressedTime _INIT(0);
|
||||
WLED_GLOBAL unsigned long buttonWaitTime _INIT(0);
|
||||
|
||||
// notifications
|
||||
WLED_GLOBAL bool notifyDirectDefault _INIT(notifyDirect);
|
||||
WLED_GLOBAL bool receiveNotifications _INIT(true);
|
||||
WLED_GLOBAL unsigned long notificationSentTime _INIT(0);
|
||||
WLED_GLOBAL byte notificationSentCallMode _INIT(NOTIFIER_CALL_MODE_INIT);
|
||||
WLED_GLOBAL bool notificationTwoRequired _INIT(false);
|
||||
|
||||
// effects
|
||||
WLED_GLOBAL byte effectCurrent _INIT(0);
|
||||
WLED_GLOBAL byte effectSpeed _INIT(128);
|
||||
WLED_GLOBAL byte effectIntensity _INIT(128);
|
||||
WLED_GLOBAL byte effectPalette _INIT(0);
|
||||
|
||||
// network
|
||||
WLED_GLOBAL bool udpConnected _INIT(false), udpRgbConnected _INIT(false);
|
||||
|
||||
// ui style
|
||||
WLED_GLOBAL bool showWelcomePage _INIT(false);
|
||||
|
||||
// hue
|
||||
WLED_GLOBAL byte hueError _INIT(HUE_ERROR_INACTIVE);
|
||||
// WLED_GLOBAL uint16_t hueFailCount _INIT(0);
|
||||
WLED_GLOBAL float hueXLast _INIT(0), hueYLast _INIT(0);
|
||||
WLED_GLOBAL uint16_t hueHueLast _INIT(0), hueCtLast _INIT(0);
|
||||
WLED_GLOBAL byte hueSatLast _INIT(0), hueBriLast _INIT(0);
|
||||
WLED_GLOBAL unsigned long hueLastRequestSent _INIT(0);
|
||||
WLED_GLOBAL bool hueAuthRequired _INIT(false);
|
||||
WLED_GLOBAL bool hueReceived _INIT(false);
|
||||
WLED_GLOBAL bool hueStoreAllowed _INIT(false), hueNewKey _INIT(false);
|
||||
|
||||
// overlays
|
||||
WLED_GLOBAL byte overlayCurrent _INIT(overlayDefault);
|
||||
WLED_GLOBAL byte overlaySpeed _INIT(200);
|
||||
WLED_GLOBAL unsigned long overlayRefreshMs _INIT(200);
|
||||
WLED_GLOBAL unsigned long overlayRefreshedTime;
|
||||
|
||||
// cronixie
|
||||
WLED_GLOBAL byte dP[] _INIT_N(({ 0, 0, 0, 0, 0, 0 }));
|
||||
WLED_GLOBAL bool cronixieInit _INIT(false);
|
||||
|
||||
// countdown
|
||||
WLED_GLOBAL unsigned long countdownTime _INIT(1514764800L);
|
||||
WLED_GLOBAL bool countdownOverTriggered _INIT(true);
|
||||
|
||||
// timer
|
||||
WLED_GLOBAL byte lastTimerMinute _INIT(0);
|
||||
WLED_GLOBAL byte timerHours[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0 }));
|
||||
WLED_GLOBAL byte timerMinutes[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0 }));
|
||||
WLED_GLOBAL byte timerMacro[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0 }));
|
||||
WLED_GLOBAL byte timerWeekday[] _INIT_N(({ 255, 255, 255, 255, 255, 255, 255, 255 })); // weekdays to activate on
|
||||
// bit pattern of arr elem: 0b11111111: sun,sat,fri,thu,wed,tue,mon,validity
|
||||
|
||||
// blynk
|
||||
WLED_GLOBAL bool blynkEnabled _INIT(false);
|
||||
|
||||
// preset cycling
|
||||
WLED_GLOBAL bool presetCyclingEnabled _INIT(false);
|
||||
WLED_GLOBAL byte presetCycleMin _INIT(1), presetCycleMax _INIT(5);
|
||||
WLED_GLOBAL uint16_t presetCycleTime _INIT(1250);
|
||||
WLED_GLOBAL unsigned long presetCycledTime _INIT(0);
|
||||
WLED_GLOBAL byte presetCycCurr _INIT(presetCycleMin);
|
||||
WLED_GLOBAL bool presetApplyBri _INIT(true);
|
||||
WLED_GLOBAL bool saveCurrPresetCycConf _INIT(false);
|
||||
|
||||
// realtime
|
||||
WLED_GLOBAL byte realtimeMode _INIT(REALTIME_MODE_INACTIVE);
|
||||
WLED_GLOBAL byte realtimeOverride _INIT(REALTIME_OVERRIDE_NONE);
|
||||
WLED_GLOBAL IPAddress realtimeIP _INIT((0, 0, 0, 0));
|
||||
WLED_GLOBAL unsigned long realtimeTimeout _INIT(0);
|
||||
|
||||
// mqtt
|
||||
WLED_GLOBAL long lastMqttReconnectAttempt _INIT(0);
|
||||
WLED_GLOBAL long lastInterfaceUpdate _INIT(0);
|
||||
WLED_GLOBAL byte interfaceUpdateCallMode _INIT(NOTIFIER_CALL_MODE_INIT);
|
||||
WLED_GLOBAL char mqttStatusTopic[40] _INIT(""); // this must be global because of async handlers
|
||||
|
||||
#if AUXPIN >= 0
|
||||
// auxiliary debug pin
|
||||
WLED_GLOBAL byte auxTime _INIT(0);
|
||||
WLED_GLOBAL unsigned long auxStartTime _INIT(0);
|
||||
WLED_GLOBAL bool auxActive _INIT(false, auxActiveBefore _INIT(false);
|
||||
#endif
|
||||
|
||||
// alexa udp
|
||||
WLED_GLOBAL String escapedMac;
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
WLED_GLOBAL Espalexa espalexa;
|
||||
WLED_GLOBAL EspalexaDevice* espalexaDevice;
|
||||
#endif
|
||||
|
||||
// dns server
|
||||
WLED_GLOBAL DNSServer dnsServer;
|
||||
|
||||
// network time
|
||||
WLED_GLOBAL bool ntpConnected _INIT(false);
|
||||
WLED_GLOBAL time_t local _INIT(0);
|
||||
WLED_GLOBAL unsigned long ntpLastSyncTime _INIT(999000000L);
|
||||
WLED_GLOBAL unsigned long ntpPacketSentTime _INIT(999000000L);
|
||||
WLED_GLOBAL IPAddress ntpServerIP;
|
||||
WLED_GLOBAL uint16_t ntpLocalPort _INIT(2390);
|
||||
WLED_GLOBAL uint16_t rolloverMillis _INIT(0);
|
||||
|
||||
// Temp buffer
|
||||
WLED_GLOBAL char* obuf;
|
||||
WLED_GLOBAL uint16_t olen _INIT(0);
|
||||
|
||||
// presets
|
||||
WLED_GLOBAL uint16_t savedPresets _INIT(0);
|
||||
WLED_GLOBAL int8_t currentPreset _INIT(-1);
|
||||
WLED_GLOBAL bool isPreset _INIT(false);
|
||||
|
||||
WLED_GLOBAL byte errorFlag _INIT(0);
|
||||
|
||||
WLED_GLOBAL String messageHead, messageSub;
|
||||
WLED_GLOBAL byte optionType;
|
||||
|
||||
WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers
|
||||
WLED_GLOBAL bool doPublishMqtt _INIT(false);
|
||||
|
||||
// server library objects
|
||||
WLED_GLOBAL AsyncWebServer server _INIT_N(((80)));
|
||||
WLED_GLOBAL AsyncClient* hueClient _INIT(NULL);
|
||||
WLED_GLOBAL AsyncMqttClient* mqtt _INIT(NULL);
|
||||
|
||||
// udp interface objects
|
||||
WLED_GLOBAL WiFiUDP notifierUdp, rgbUdp;
|
||||
WLED_GLOBAL WiFiUDP ntpUdp;
|
||||
WLED_GLOBAL ESPAsyncE131 e131 _INIT_N(((handleE131Packet)));
|
||||
WLED_GLOBAL bool e131NewData _INIT(false);
|
||||
|
||||
// led fx library object
|
||||
WLED_GLOBAL WS2812FX strip _INIT(WS2812FX());
|
||||
|
||||
// debug macro variable definitions
|
||||
#ifdef WLED_DEBUG
|
||||
WLED_GLOBAL unsigned long debugTime _INIT(0);
|
||||
WLED_GLOBAL int lastWifiState _INIT(3);
|
||||
WLED_GLOBAL unsigned long wifiStateChangedTime _INIT(0);
|
||||
WLED_GLOBAL int loops _INIT(0);
|
||||
#endif
|
||||
|
||||
|
||||
#define WLED_CONNECTED (WiFi.status() == WL_CONNECTED)
|
||||
#define WLED_WIFI_CONFIGURED (strlen(clientSSID) >= 1 && strcmp(clientSSID, DEFAULT_CLIENT_SSID) != 0)
|
||||
|
||||
// append new c string to temp buffer efficiently
|
||||
bool oappend(const char* txt);
|
||||
// append new number to temp buffer efficiently
|
||||
bool oappendi(int i);
|
||||
|
||||
class WLED {
|
||||
public:
|
||||
WLED();
|
||||
static WLED& instance()
|
||||
{
|
||||
static WLED instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
// boot starts here
|
||||
void setup();
|
||||
|
||||
void loop();
|
||||
void reset();
|
||||
|
||||
void beginStrip();
|
||||
void handleConnection();
|
||||
void initAP(bool resetAP = false);
|
||||
void initConnection();
|
||||
void initInterfaces();
|
||||
};
|
||||
#endif // WLED_H
|
@ -1,563 +1,21 @@
|
||||
/*
|
||||
* Main sketch, global variable declarations
|
||||
*/
|
||||
/*
|
||||
* @title WLED project sketch
|
||||
* @version 0.9.0-b2
|
||||
* @author Christian Schwinne
|
||||
* WLED Arduino IDE compatibility file.
|
||||
*
|
||||
* Where has everything gone?
|
||||
*
|
||||
* In April 2020, the project's structure underwent a major change.
|
||||
* Global variables are now found in file "wled.h"
|
||||
* Global function declarations are found in "fcn_declare.h"
|
||||
*
|
||||
* Usermod compatibility: Existing wled06_usermod.ino mods should continue to work. Delete usermod.cpp.
|
||||
* New usermods should use usermod.cpp instead.
|
||||
*/
|
||||
#include "wled.h"
|
||||
|
||||
|
||||
//ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS).
|
||||
|
||||
//ESP8266-01 (black) has 1MB flash and can thus fit the whole program. Use 1M(64K SPIFFS).
|
||||
//Uncomment some of the following lines to disable features to compile for ESP8266-01 (max flash size 434kB):
|
||||
|
||||
//You are required to disable over-the-air updates:
|
||||
//#define WLED_DISABLE_OTA //saves 14kb
|
||||
|
||||
//You need to choose some of these features to disable:
|
||||
//#define WLED_DISABLE_ALEXA //saves 11kb
|
||||
//#define WLED_DISABLE_BLYNK //saves 6kb
|
||||
//#define WLED_DISABLE_CRONIXIE //saves 3kb
|
||||
//#define WLED_DISABLE_HUESYNC //saves 4kb
|
||||
//#define WLED_DISABLE_INFRARED //there is no pin left for this on ESP8266-01, saves 25kb (!)
|
||||
#define WLED_ENABLE_MQTT //saves 12kb
|
||||
#define WLED_ENABLE_ADALIGHT //saves 500b only
|
||||
|
||||
#define WLED_DISABLE_FILESYSTEM //SPIFFS is not used by any WLED feature yet
|
||||
//#define WLED_ENABLE_FS_SERVING //Enable sending html file from SPIFFS before serving progmem version
|
||||
//#define WLED_ENABLE_FS_EDITOR //enable /edit page for editing SPIFFS content. Will also be disabled with OTA lock
|
||||
|
||||
//to toggle usb serial debug (un)comment the following line
|
||||
//#define WLED_DEBUG
|
||||
|
||||
//library inclusions
|
||||
#include <Arduino.h>
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <ESPAsyncTCP.h>
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#include "esp_wifi.h"
|
||||
#include <ESPmDNS.h>
|
||||
#include <AsyncTCP.h>
|
||||
#include "SPIFFS.h"
|
||||
#endif
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <EEPROM.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <DNSServer.h>
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
#include <ArduinoOTA.h>
|
||||
#endif
|
||||
#include <SPIFFSEditor.h>
|
||||
#include "src/dependencies/time/TimeLib.h"
|
||||
#include "src/dependencies/timezone/Timezone.h"
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
#define ESPALEXA_ASYNC
|
||||
#define ESPALEXA_NO_SUBPAGE
|
||||
#define ESPALEXA_MAXDEVICES 1
|
||||
//#define ESPALEXA_DEBUG
|
||||
#include "src/dependencies/espalexa/Espalexa.h"
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
#include "src/dependencies/blynk/BlynkSimpleEsp.h"
|
||||
#endif
|
||||
#include "src/dependencies/e131/ESPAsyncE131.h"
|
||||
#include "src/dependencies/async-mqtt-client/AsyncMqttClient.h"
|
||||
#include "src/dependencies/json/AsyncJson-v6.h"
|
||||
#include "src/dependencies/json/ArduinoJson-v6.h"
|
||||
#include "html_ui.h"
|
||||
#include "html_settings.h"
|
||||
#include "html_other.h"
|
||||
#include "FX.h"
|
||||
#include "ir_codes.h"
|
||||
|
||||
|
||||
#if IR_PIN < 0
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
#define WLED_DISABLE_INFRARED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
#include <IRremoteESP8266.h>
|
||||
#include <IRrecv.h>
|
||||
#include <IRutils.h>
|
||||
#endif
|
||||
|
||||
//version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2001131
|
||||
char versionString[] = "0.9.0-b2";
|
||||
|
||||
|
||||
//AP and OTA default passwords (for maximum change them!)
|
||||
char apPass[65] = "wled1234";
|
||||
char otaPass[33] = "wledota";
|
||||
|
||||
|
||||
//Hardware CONFIG (only changeble HERE, not at runtime)
|
||||
//LED strip pin, button pin and IR pin changeable in NpbWrapper.h!
|
||||
|
||||
byte auxDefaultState = 0; //0: input 1: high 2: low
|
||||
byte auxTriggeredState = 0; //0: input 1: high 2: low
|
||||
char ntpServerName[33] = "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)
|
||||
char clientSSID[33] = "Your_Network";
|
||||
char clientPass[65] = "";
|
||||
char cmDNS[33] = "x"; //mDNS address (placeholder, will be replaced by wledXXXXXXXXXXXX.local)
|
||||
char apSSID[33] = ""; //AP off by default (unless setup)
|
||||
byte apChannel = 1; //2.4GHz WiFi AP channel (1-13)
|
||||
byte apHide = 0; //hidden AP SSID
|
||||
//byte apWaitTimeSecs = 32; //time to wait for connection before opening AP
|
||||
byte apBehavior = 0; //0: Open AP when no connection after boot 1: Open when no connection 2: Always open 3: Only when button pressed for 6 sec
|
||||
//bool recoveryAPDisabled = false; //never open AP (not recommended)
|
||||
IPAddress staticIP(0, 0, 0, 0); //static IP of ESP
|
||||
IPAddress staticGateway(0, 0, 0, 0); //gateway (router) IP
|
||||
IPAddress staticSubnet(255, 255, 255, 0); //most common subnet in home networks
|
||||
|
||||
//LED CONFIG
|
||||
uint16_t ledCount = 30; //overcurrent prevented by ABL
|
||||
bool useRGBW = false; //SK6812 strips can contain an extra White channel
|
||||
bool autoRGBtoRGBW = false; //if RGBW enabled, calculate White channel from RGB
|
||||
#define ABL_MILLIAMPS_DEFAULT 850; //auto lower brightness to stay close to milliampere limit
|
||||
bool turnOnAtBoot = true; //turn on LEDs at power-up
|
||||
byte bootPreset = 0; //save preset to load after power-up
|
||||
|
||||
byte col[]{255, 160, 0, 0}; //default RGB(W) color
|
||||
byte colSec[]{0, 0, 0, 0}; //default RGB(W) secondary color
|
||||
byte briS = 128; //default brightness
|
||||
|
||||
byte nightlightTargetBri = 0; //brightness after nightlight is over
|
||||
byte nightlightDelayMins = 60;
|
||||
bool nightlightFade = true; //if enabled, light will gradually dim towards the target bri. Otherwise, it will instantly set after delay over
|
||||
bool nightlightColorFade = false; //if enabled, light will gradually fade color from primary to secondary color.
|
||||
bool fadeTransition = true; //enable crossfading color transition
|
||||
bool enableSecTransition = true; //also enable transition for secondary color
|
||||
uint16_t transitionDelay = 750; //default crossfade duration in ms
|
||||
|
||||
bool skipFirstLed = false; //ignore first LED in strip (useful if you need the LED as signal repeater)
|
||||
uint8_t disableNLeds = 0; //disables N LEDs between active nodes. (Useful for spacing out lights for more traditional christmas light look)
|
||||
byte briMultiplier = 100; //% of brightness to set (to limit power, if you set it to 50 and set bri to 255, actual brightness will be 127)
|
||||
|
||||
|
||||
//User Interface CONFIG
|
||||
char serverDescription[33] = "WLED"; //Name of module
|
||||
bool syncToggleReceive = false; //UIs which only have a single button for sync should toggle send+receive if this is true, only send otherwise
|
||||
|
||||
|
||||
//Sync CONFIG
|
||||
bool buttonEnabled = true;
|
||||
byte irEnabled = 0; //Infrared receiver
|
||||
|
||||
uint16_t udpPort = 21324; //WLED notifier default port
|
||||
uint16_t udpRgbPort = 19446; //Hyperion port
|
||||
|
||||
bool receiveNotificationBrightness = true; //apply brightness from incoming notifications
|
||||
bool receiveNotificationColor = true; //apply color
|
||||
bool receiveNotificationEffects = true; //apply effects setup
|
||||
bool notifyDirect = false; //send notification if change via UI or HTTP API
|
||||
bool notifyButton = false; //send if updated by button or infrared remote
|
||||
bool notifyAlexa = false; //send notification if updated via Alexa
|
||||
bool notifyMacro = false; //send notification for macro
|
||||
bool notifyHue = true; //send notification if Hue light changes
|
||||
bool notifyTwice = false; //notifications use UDP: enable if devices don't sync reliably
|
||||
|
||||
bool alexaEnabled = true; //enable device discovery by Amazon Echo
|
||||
char alexaInvocationName[33] = "Light"; //speech control name of device. Choose something voice-to-text can understand
|
||||
|
||||
char blynkApiKey[36] = ""; //Auth token for Blynk server. If empty, no connection will be made
|
||||
|
||||
uint16_t realtimeTimeoutMs = 2500; //ms timeout of realtime mode before returning to normal mode
|
||||
int arlsOffset = 0; //realtime LED offset
|
||||
bool receiveDirect = true; //receive UDP realtime
|
||||
bool arlsDisableGammaCorrection = true; //activate if gamma correction is handled by the source
|
||||
bool arlsForceMaxBri = false; //enable to force max brightness if source has very dark colors that would be black
|
||||
|
||||
uint16_t e131Universe = 1; //settings for E1.31 (sACN) protocol
|
||||
bool e131Multicast = false;
|
||||
|
||||
bool mqttEnabled = false;
|
||||
char mqttDeviceTopic[33] = ""; //main MQTT topic (individual per device, default is wled/mac)
|
||||
char mqttGroupTopic[33] = "wled/all"; //second MQTT topic (for example to group devices)
|
||||
char mqttServer[33] = ""; //both domains and IPs should work (no SSL)
|
||||
char mqttUser[41] = ""; //optional: username for MQTT auth
|
||||
char mqttPass[41] = ""; //optional: password for MQTT auth
|
||||
char mqttClientID[41] = ""; //override the client ID
|
||||
uint16_t mqttPort = 1883;
|
||||
|
||||
bool huePollingEnabled = false; //poll hue bridge for light state
|
||||
uint16_t huePollIntervalMs = 2500; //low values (< 1sec) may cause lag but offer quicker response
|
||||
char hueApiKey[47] = "api"; //key token will be obtained from bridge
|
||||
byte huePollLightId = 1; //ID of hue lamp to sync to. Find the ID in the hue app ("about" section)
|
||||
IPAddress hueIP = (0,0,0,0); //IP address of the bridge
|
||||
bool hueApplyOnOff = true;
|
||||
bool hueApplyBri = true;
|
||||
bool hueApplyColor = true;
|
||||
|
||||
|
||||
//Time CONFIG
|
||||
bool ntpEnabled = false; //get internet time. Only required if you use clock overlays or time-activated macros
|
||||
bool useAMPM = false; //12h/24h clock format
|
||||
byte currentTimezone = 0; //Timezone ID. Refer to timezones array in wled10_ntp.ino
|
||||
int utcOffsetSecs = 0; //Seconds to offset from UTC before timzone calculation
|
||||
|
||||
byte overlayDefault = 0; //0: no overlay 1: analog clock 2: single-digit clocl 3: cronixie
|
||||
byte overlayMin = 0, overlayMax = ledCount-1; //boundaries of overlay mode
|
||||
|
||||
byte analogClock12pixel = 0; //The pixel in your strip where "midnight" would be
|
||||
bool analogClockSecondsTrail = false; //Display seconds as trail of LEDs instead of a single pixel
|
||||
bool analogClock5MinuteMarks = false; //Light pixels at every 5-minute position
|
||||
|
||||
char cronixieDisplay[7] = "HHMMSS"; //Cronixie Display mask. See wled13_cronixie.ino
|
||||
bool cronixieBacklight = true; //Allow digits to be back-illuminated
|
||||
|
||||
bool countdownMode = false; //Clock will count down towards date
|
||||
byte countdownYear = 20, countdownMonth = 1; //Countdown target date, year is last two digits
|
||||
byte countdownDay = 1, countdownHour = 0;
|
||||
byte countdownMin = 0, countdownSec = 0;
|
||||
|
||||
|
||||
byte macroBoot = 0; //macro loaded after startup
|
||||
byte macroNl = 0; //after nightlight delay over
|
||||
byte macroCountdown = 0;
|
||||
byte macroAlexaOn = 0, macroAlexaOff = 0;
|
||||
byte macroButton = 0, macroLongPress = 0, macroDoublePress = 0;
|
||||
|
||||
|
||||
//Security CONFIG
|
||||
bool otaLock = false; //prevents OTA firmware updates without password. ALWAYS enable if system exposed to any public networks
|
||||
bool wifiLock = false; //prevents access to WiFi settings when OTA lock is enabled
|
||||
bool aOtaEnabled = true; //ArduinoOTA allows easy updates directly from the IDE. Careful, it does not auto-disable when OTA lock is on
|
||||
|
||||
|
||||
uint16_t userVar0 = 0, userVar1 = 0;
|
||||
|
||||
|
||||
//internal global variable declarations
|
||||
//wifi
|
||||
bool apActive = false;
|
||||
bool forceReconnect = false;
|
||||
uint32_t lastReconnectAttempt = 0;
|
||||
bool interfacesInited = false;
|
||||
bool wasConnected = false;
|
||||
|
||||
//color
|
||||
byte colOld[]{0, 0, 0, 0}; //color before transition
|
||||
byte colT[]{0, 0, 0, 0}; //current color
|
||||
byte colIT[]{0, 0, 0, 0}; //color that was last sent to LEDs
|
||||
byte colSecT[]{0, 0, 0, 0};
|
||||
byte colSecOld[]{0, 0, 0, 0};
|
||||
byte colSecIT[]{0, 0, 0, 0};
|
||||
|
||||
byte lastRandomIndex = 0; //used to save last random color so the new one is not the same
|
||||
|
||||
//transitions
|
||||
bool transitionActive = false;
|
||||
uint16_t transitionDelayDefault = transitionDelay;
|
||||
uint16_t transitionDelayTemp = transitionDelay;
|
||||
unsigned long transitionStartTime;
|
||||
float tperLast = 0; //crossfade transition progress, 0.0f - 1.0f
|
||||
bool jsonTransitionOnce = false;
|
||||
|
||||
//nightlight
|
||||
bool nightlightActive = false;
|
||||
bool nightlightActiveOld = false;
|
||||
uint32_t nightlightDelayMs = 10;
|
||||
uint8_t nightlightDelayMinsDefault = nightlightDelayMins;
|
||||
unsigned long nightlightStartTime;
|
||||
byte briNlT = 0; //current nightlight brightness
|
||||
byte colNlT[]{0, 0, 0, 0}; //current nightlight color
|
||||
|
||||
//brightness
|
||||
unsigned long lastOnTime = 0;
|
||||
bool offMode = !turnOnAtBoot;
|
||||
byte bri = briS;
|
||||
byte briOld = 0;
|
||||
byte briT = 0;
|
||||
byte briIT = 0;
|
||||
byte briLast = 128; //brightness before turned off. Used for toggle function
|
||||
byte whiteLast = 128; //white channel before turned off. Used for toggle function
|
||||
|
||||
//button
|
||||
bool buttonPressedBefore = false;
|
||||
bool buttonLongPressed = false;
|
||||
unsigned long buttonPressedTime = 0;
|
||||
unsigned long buttonWaitTime = 0;
|
||||
|
||||
//notifications
|
||||
bool notifyDirectDefault = notifyDirect;
|
||||
bool receiveNotifications = true;
|
||||
unsigned long notificationSentTime = 0;
|
||||
byte notificationSentCallMode = 0;
|
||||
bool notificationTwoRequired = false;
|
||||
|
||||
//effects
|
||||
byte effectCurrent = 0;
|
||||
byte effectSpeed = 128;
|
||||
byte effectIntensity = 128;
|
||||
byte effectPalette = 0;
|
||||
|
||||
//network
|
||||
bool udpConnected = false, udpRgbConnected = false;
|
||||
|
||||
//ui style
|
||||
bool showWelcomePage = false;
|
||||
|
||||
//hue
|
||||
char hueError[25] = "Inactive";
|
||||
//uint16_t hueFailCount = 0;
|
||||
float hueXLast=0, hueYLast=0;
|
||||
uint16_t hueHueLast=0, hueCtLast=0;
|
||||
byte hueSatLast=0, hueBriLast=0;
|
||||
unsigned long hueLastRequestSent = 0;
|
||||
bool hueAuthRequired = false;
|
||||
bool hueReceived = false;
|
||||
bool hueStoreAllowed = false, hueNewKey = false;
|
||||
|
||||
//overlays
|
||||
byte overlayCurrent = overlayDefault;
|
||||
byte overlaySpeed = 200;
|
||||
unsigned long overlayRefreshMs = 200;
|
||||
unsigned long overlayRefreshedTime;
|
||||
|
||||
//cronixie
|
||||
byte dP[]{0,0,0,0,0,0};
|
||||
bool cronixieInit = false;
|
||||
|
||||
//countdown
|
||||
unsigned long countdownTime = 1514764800L;
|
||||
bool countdownOverTriggered = true;
|
||||
|
||||
//timer
|
||||
byte lastTimerMinute = 0;
|
||||
byte timerHours[] = {0,0,0,0,0,0,0,0};
|
||||
byte timerMinutes[] = {0,0,0,0,0,0,0,0};
|
||||
byte timerMacro[] = {0,0,0,0,0,0,0,0};
|
||||
byte timerWeekday[] = {255,255,255,255,255,255,255,255}; //weekdays to activate on
|
||||
//bit pattern of arr elem: 0b11111111: sun,sat,fri,thu,wed,tue,mon,validity
|
||||
|
||||
//blynk
|
||||
bool blynkEnabled = false;
|
||||
|
||||
//preset cycling
|
||||
bool presetCyclingEnabled = false;
|
||||
byte presetCycleMin = 1, presetCycleMax = 5;
|
||||
uint16_t presetCycleTime = 1250;
|
||||
unsigned long presetCycledTime = 0; byte presetCycCurr = presetCycleMin;
|
||||
bool presetApplyBri = false, presetApplyCol = true, presetApplyFx = true;
|
||||
bool saveCurrPresetCycConf = false;
|
||||
|
||||
//realtime
|
||||
bool realtimeActive = false;
|
||||
IPAddress realtimeIP = (0,0,0,0);
|
||||
unsigned long realtimeTimeout = 0;
|
||||
|
||||
//mqtt
|
||||
long lastMqttReconnectAttempt = 0;
|
||||
long lastInterfaceUpdate = 0;
|
||||
byte interfaceUpdateCallMode = 0;
|
||||
char mqttStatusTopic[40] = ""; //this must be global because of async handlers
|
||||
|
||||
#if AUXPIN >= 0
|
||||
//auxiliary debug pin
|
||||
byte auxTime = 0;
|
||||
unsigned long auxStartTime = 0;
|
||||
bool auxActive = false, auxActiveBefore = false;
|
||||
#endif
|
||||
|
||||
//alexa udp
|
||||
String escapedMac;
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
Espalexa espalexa;
|
||||
EspalexaDevice* espalexaDevice;
|
||||
#endif
|
||||
|
||||
//dns server
|
||||
DNSServer dnsServer;
|
||||
|
||||
//network time
|
||||
bool ntpConnected = false;
|
||||
time_t local = 0;
|
||||
unsigned long ntpLastSyncTime = 999000000L;
|
||||
unsigned long ntpPacketSentTime = 999000000L;
|
||||
IPAddress ntpServerIP;
|
||||
uint16_t ntpLocalPort = 2390;
|
||||
#define NTP_PACKET_SIZE 48
|
||||
|
||||
#define MAX_LEDS 1500
|
||||
#define MAX_LEDS_DMA 500
|
||||
|
||||
//string temp buffer (now stored in stack locally)
|
||||
#define OMAX 2048
|
||||
char* obuf;
|
||||
uint16_t olen = 0;
|
||||
|
||||
uint16_t savedPresets = 0;
|
||||
int8_t currentPreset = -1;
|
||||
bool isPreset = false;
|
||||
|
||||
byte errorFlag = 0;
|
||||
|
||||
String messageHead, messageSub;
|
||||
byte optionType;
|
||||
|
||||
bool doReboot = false; //flag to initiate reboot from async handlers
|
||||
bool doPublishMqtt = false;
|
||||
|
||||
//server library objects
|
||||
AsyncWebServer server(80);
|
||||
AsyncClient* hueClient = NULL;
|
||||
AsyncMqttClient* mqtt = NULL;
|
||||
|
||||
//function prototypes
|
||||
void colorFromUint32(uint32_t,bool=false);
|
||||
void serveMessage(AsyncWebServerRequest*,uint16_t,String,String,byte);
|
||||
void handleE131Packet(e131_packet_t*, IPAddress);
|
||||
void handleOverlayDraw();
|
||||
|
||||
#define E131_MAX_UNIVERSE_COUNT 9
|
||||
|
||||
//udp interface objects
|
||||
WiFiUDP notifierUdp, rgbUdp;
|
||||
WiFiUDP ntpUdp;
|
||||
ESPAsyncE131 e131(handleE131Packet);
|
||||
bool e131NewData = false;
|
||||
|
||||
//led fx library object
|
||||
WS2812FX strip = WS2812FX();
|
||||
|
||||
#define WLED_CONNECTED (WiFi.status() == WL_CONNECTED)
|
||||
#define WLED_WIFI_CONFIGURED (strlen(clientSSID) >= 1 && strcmp(clientSSID,"Your_Network") != 0)
|
||||
|
||||
//debug macros
|
||||
#ifdef WLED_DEBUG
|
||||
#define DEBUG_PRINT(x) Serial.print (x)
|
||||
#define DEBUG_PRINTLN(x) Serial.println (x)
|
||||
#define DEBUG_PRINTF(x) Serial.printf (x)
|
||||
unsigned long debugTime = 0;
|
||||
int lastWifiState = 3;
|
||||
unsigned long wifiStateChangedTime = 0;
|
||||
int loops = 0;
|
||||
#else
|
||||
#define DEBUG_PRINT(x)
|
||||
#define DEBUG_PRINTLN(x)
|
||||
#define DEBUG_PRINTF(x)
|
||||
#endif
|
||||
|
||||
//filesystem
|
||||
#ifndef WLED_DISABLE_FILESYSTEM
|
||||
#include <FS.h>
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include "SPIFFS.h"
|
||||
#endif
|
||||
#include "SPIFFSEditor.h"
|
||||
#endif
|
||||
|
||||
//turns all LEDs off and restarts ESP
|
||||
void reset()
|
||||
{
|
||||
briT = 0;
|
||||
long dly = millis();
|
||||
while(millis() - dly < 250)
|
||||
{
|
||||
yield(); //enough time to send response to client
|
||||
}
|
||||
setAllLeds();
|
||||
DEBUG_PRINTLN("MODULE RESET");
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
|
||||
//append new c string to temp buffer efficiently
|
||||
bool oappend(const char* txt)
|
||||
{
|
||||
uint16_t len = strlen(txt);
|
||||
if (olen + len >= OMAX) return false; //buffer full
|
||||
strcpy(obuf + olen, txt);
|
||||
olen += len;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//append new number to temp buffer efficiently
|
||||
bool oappendi(int i)
|
||||
{
|
||||
char s[11];
|
||||
sprintf(s,"%ld", i);
|
||||
return oappend(s);
|
||||
}
|
||||
|
||||
|
||||
//boot starts here
|
||||
void setup() {
|
||||
wledInit();
|
||||
WLED::instance().setup();
|
||||
}
|
||||
|
||||
|
||||
//main program loop
|
||||
void loop() {
|
||||
handleIR(); //2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too
|
||||
handleConnection();
|
||||
handleSerial();
|
||||
handleNotifications();
|
||||
handleTransitions();
|
||||
userLoop();
|
||||
|
||||
yield();
|
||||
handleIO();
|
||||
handleIR();
|
||||
handleNetworkTime();
|
||||
handleAlexa();
|
||||
|
||||
handleOverlays();
|
||||
yield();
|
||||
if (doReboot) reset();
|
||||
|
||||
if (!realtimeActive) //block stuff if WARLS/Adalight is enabled
|
||||
{
|
||||
if (apActive) dnsServer.processNextRequest();
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (WLED_CONNECTED && aOtaEnabled) ArduinoOTA.handle();
|
||||
#endif
|
||||
handleNightlight();
|
||||
yield();
|
||||
|
||||
handleHue();
|
||||
handleBlynk();
|
||||
|
||||
yield();
|
||||
if (!offMode) strip.service();
|
||||
}
|
||||
yield();
|
||||
if (millis() - lastMqttReconnectAttempt > 30000) initMqtt();
|
||||
|
||||
//DEBUG serial logging
|
||||
#ifdef WLED_DEBUG
|
||||
if (millis() - debugTime > 9999)
|
||||
{
|
||||
DEBUG_PRINTLN("---DEBUG INFO---");
|
||||
DEBUG_PRINT("Runtime: "); DEBUG_PRINTLN(millis());
|
||||
DEBUG_PRINT("Unix time: "); DEBUG_PRINTLN(now());
|
||||
DEBUG_PRINT("Free heap: "); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
DEBUG_PRINT("Wifi state: "); DEBUG_PRINTLN(WiFi.status());
|
||||
if (WiFi.status() != lastWifiState)
|
||||
{
|
||||
wifiStateChangedTime = millis();
|
||||
}
|
||||
lastWifiState = WiFi.status();
|
||||
DEBUG_PRINT("State time: "); DEBUG_PRINTLN(wifiStateChangedTime);
|
||||
DEBUG_PRINT("NTP last sync: "); DEBUG_PRINTLN(ntpLastSyncTime);
|
||||
DEBUG_PRINT("Client IP: "); DEBUG_PRINTLN(WiFi.localIP());
|
||||
DEBUG_PRINT("Loops/sec: "); DEBUG_PRINTLN(loops/10);
|
||||
loops = 0;
|
||||
debugTime = millis();
|
||||
}
|
||||
loops++;
|
||||
#endif
|
||||
WLED::instance().loop();
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@ -13,29 +13,15 @@
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Dependencies">
|
||||
<UniqueIdentifier>{72fe60da-ba26-45b4-82c1-bdff809975da}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Dependencies">
|
||||
<UniqueIdentifier>{8880888d-efea-4189-a25a-834b7b3bb756}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="wled00.ino" />
|
||||
<None Include="wled01_eeprom.ino" />
|
||||
<None Include="wled02_xml.ino" />
|
||||
<None Include="wled03_set.ino" />
|
||||
<None Include="wled04_file.ino" />
|
||||
<None Include="wled05_init.ino" />
|
||||
<None Include="wled06_usermod.ino" />
|
||||
<None Include="wled07_notify.ino" />
|
||||
<None Include="wled08_led.ino" />
|
||||
<None Include="wled09_button.ino" />
|
||||
<None Include="wled10_ntp.ino" />
|
||||
<None Include="wled11_ol.ino" />
|
||||
<None Include="wled12_alexa.ino" />
|
||||
<None Include="wled13_cronixie.ino" />
|
||||
<None Include="wled14_colors.ino" />
|
||||
<None Include="wled15_hue.ino" />
|
||||
<None Include="wled16_blynk.ino" />
|
||||
<None Include="wled17_mqtt.ino" />
|
||||
<None Include="wled18_server.ino" />
|
||||
<None Include="wled19_json.ino" />
|
||||
<None Include="wled20_ir.ino" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="__vm\.wled00.vsarduino.h">
|
||||
@ -53,219 +39,348 @@
|
||||
<ClInclude Include="html_settings.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ir_codes.h">
|
||||
<ClInclude Include="FX.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\json\ArduinoJson-v6.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\json\AsyncJson-v6.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkApi.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkApiArduino.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkArduinoClient.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkConfig.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkDateTime.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkDebug.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkDetectDevice.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkEveryN.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkFifo.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkHandlers.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkParam.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkProtocol.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkProtocolDefs.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\BlynkSimpleEsp.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkTemplates.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkTimer.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkUtility.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkWidgetBase.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkWiFiCommon.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Callbacks.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\ConnAckPacket.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\DisconnectReasons.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\espalexa\Espalexa.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\espalexa\EspalexaDevice.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\e131\ESPAsyncE131.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Flags.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Helpers.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\MessageProperties.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NpbWrapper.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\Packet.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\ParsingInformation.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PingRespPacket.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubAckPacket.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubCompPacket.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PublishPacket.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRecPacket.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRelPacket.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Storage.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\SubAckPacket.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\time\Time.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\time\TimeLib.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\timezone\Timezone.h">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\UnsubAckPacket.hpp">
|
||||
<Filter>Header Files\Dependencies</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="alexa.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="blynk.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="button.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="colors.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="const.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="cronixie.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dmx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="file.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="html_ui.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="hue.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ir.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="json.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="led.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mqtt.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="notify.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ntp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="overlay.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="set.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="usermod.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wled.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wled_eeprom.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wled_server.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="xml.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ir_codes.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="palettes.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Callbacks.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\DisconnectReasons.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Flags.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Helpers.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\MessageProperties.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\ParsingInformation.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Storage.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\ConnAckPacket.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\Packet.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PingRespPacket.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubAckPacket.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubCompPacket.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PublishPacket.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRecPacket.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRelPacket.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\SubAckPacket.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\UnsubAckPacket.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\BlynkSimpleEsp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkApi.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkApiArduino.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkArduinoClient.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkConfig.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkDateTime.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkDebug.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkDetectDevice.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkEveryN.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkFifo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkHandlers.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkParam.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkProtocol.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkProtocolDefs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkTemplates.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkTimer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkUtility.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkWidgetBase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkWiFiCommon.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\espalexa\Espalexa.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\espalexa\EspalexaDevice.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\json\ArduinoJson-v6.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\json\AsyncJson-v6.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\time\Time.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\time\TimeLib.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\timezone\Timezone.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FX.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\dependencies\e131\ESPAsyncE131.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\ConnAckPacket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PingRespPacket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubAckPacket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubCompPacket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PublishPacket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRecPacket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRelPacket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\SubAckPacket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\UnsubAckPacket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\blynk\Blynk\BlynkDebug.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\blynk\Blynk\BlynkHandlers.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\blynk\Blynk\BlynkTimer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\blynk\Blynk\utility.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\espalexa\EspalexaDevice.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\time\DateStrings.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\time\Time.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\timezone\Timezone.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FX.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FX_fcn.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\blynk\Blynk\utility.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\blynk\Blynk\BlynkDebug.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\blynk\Blynk\BlynkHandlers.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\blynk\Blynk\BlynkTimer.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\ConnAckPacket.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\time\DateStrings.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\espalexa\EspalexaDevice.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\e131\ESPAsyncE131.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PingRespPacket.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubAckPacket.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubCompPacket.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PublishPacket.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRecPacket.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRelPacket.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\SubAckPacket.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\time\Time.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\timezone\Timezone.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\UnsubAckPacket.cpp">
|
||||
<Filter>Source Files\Dependencies</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="alexa.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="blynk.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="button.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="colors.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cronixie.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="file.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="hue.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ir.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="json.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="led.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="mqtt.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="notify.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ntp.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="overlay.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="set.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="usermod.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wled.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wled_eeprom.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wled_server.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="xml.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Utility for SPIFFS filesystem & Serial console
|
||||
*/
|
||||
enum class AdaState {
|
||||
Header_A,
|
||||
Header_d,
|
||||
Header_a,
|
||||
Header_CountHi,
|
||||
Header_CountLo,
|
||||
Header_CountCheck,
|
||||
Data_Red,
|
||||
Data_Green,
|
||||
Data_Blue
|
||||
};
|
||||
|
||||
void handleSerial()
|
||||
{
|
||||
#ifdef WLED_ENABLE_ADALIGHT
|
||||
static auto state = AdaState::Header_A;
|
||||
static uint16_t count = 0;
|
||||
static uint16_t pixel = 0;
|
||||
static byte check = 0x00;
|
||||
static byte red = 0x00;
|
||||
static byte green = 0x00;
|
||||
|
||||
while (Serial.available() > 0)
|
||||
{
|
||||
yield();
|
||||
byte next = Serial.read();
|
||||
switch (state) {
|
||||
case AdaState::Header_A:
|
||||
if (next == 'A') state = AdaState::Header_d;
|
||||
break;
|
||||
case AdaState::Header_d:
|
||||
if (next == 'd') state = AdaState::Header_a;
|
||||
else state = AdaState::Header_A;
|
||||
break;
|
||||
case AdaState::Header_a:
|
||||
if (next == 'a') state = AdaState::Header_CountHi;
|
||||
else state = AdaState::Header_A;
|
||||
break;
|
||||
case AdaState::Header_CountHi:
|
||||
pixel = 0;
|
||||
count = next * 0x100;
|
||||
check = next;
|
||||
state = AdaState::Header_CountLo;
|
||||
break;
|
||||
case AdaState::Header_CountLo:
|
||||
count += next + 1;
|
||||
check = check ^ next ^ 0x55;
|
||||
state = AdaState::Header_CountCheck;
|
||||
break;
|
||||
case AdaState::Header_CountCheck:
|
||||
if (check == next) state = AdaState::Data_Red;
|
||||
else state = AdaState::Header_A;
|
||||
break;
|
||||
case AdaState::Data_Red:
|
||||
red = next;
|
||||
state = AdaState::Data_Green;
|
||||
break;
|
||||
case AdaState::Data_Green:
|
||||
green = next;
|
||||
state = AdaState::Data_Blue;
|
||||
break;
|
||||
case AdaState::Data_Blue:
|
||||
byte blue = next;
|
||||
setRealtimePixel(pixel++, red, green, blue, 0);
|
||||
if (--count > 0) state = AdaState::Data_Red;
|
||||
else {
|
||||
if (!realtimeActive && bri == 0) strip.setBrightness(briLast);
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
|
||||
strip.show();
|
||||
state = AdaState::Header_A;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if !defined WLED_DISABLE_FILESYSTEM && defined WLED_ENABLE_FS_SERVING
|
||||
//Un-comment any file types you need
|
||||
String getContentType(AsyncWebServerRequest* request, String filename){
|
||||
if(request->hasArg("download")) return "application/octet-stream";
|
||||
else if(filename.endsWith(".htm")) return "text/html";
|
||||
else if(filename.endsWith(".html")) return "text/html";
|
||||
// else if(filename.endsWith(".css")) return "text/css";
|
||||
// else if(filename.endsWith(".js")) return "application/javascript";
|
||||
else if(filename.endsWith(".json")) return "application/json";
|
||||
else if(filename.endsWith(".png")) return "image/png";
|
||||
// else if(filename.endsWith(".gif")) return "image/gif";
|
||||
else if(filename.endsWith(".jpg")) return "image/jpeg";
|
||||
else if(filename.endsWith(".ico")) return "image/x-icon";
|
||||
// else if(filename.endsWith(".xml")) return "text/xml";
|
||||
// else if(filename.endsWith(".pdf")) return "application/x-pdf";
|
||||
// else if(filename.endsWith(".zip")) return "application/x-zip";
|
||||
// else if(filename.endsWith(".gz")) return "application/x-gzip";
|
||||
return "text/plain";
|
||||
}
|
||||
|
||||
bool handleFileRead(AsyncWebServerRequest* request, String path){
|
||||
DEBUG_PRINTLN("FileRead: " + path);
|
||||
if(path.endsWith("/")) path += "index.htm";
|
||||
String contentType = getContentType(request, path);
|
||||
String pathWithGz = path + ".gz";
|
||||
if(SPIFFS.exists(pathWithGz)){
|
||||
request->send(SPIFFS, pathWithGz, contentType);
|
||||
return true;
|
||||
}
|
||||
if(SPIFFS.exists(path)) {
|
||||
request->send(SPIFFS, path, contentType);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
bool handleFileRead(AsyncWebServerRequest*, String path){return false;}
|
||||
#endif
|
@ -1,333 +0,0 @@
|
||||
/*
|
||||
* Setup code
|
||||
*/
|
||||
|
||||
void wledInit()
|
||||
{
|
||||
EEPROM.begin(EEPSIZE);
|
||||
ledCount = EEPROM.read(229) + ((EEPROM.read(398) << 8) & 0xFF00);
|
||||
if (ledCount > MAX_LEDS || ledCount == 0) ledCount = 30;
|
||||
|
||||
disableNLeds = EEPROM.read(2213);
|
||||
//this was reading 255 after inital flash causing bootloop. Don't know why.
|
||||
disableNLeds = disableNLeds != 255 ? disableNLeds : 0;
|
||||
|
||||
#ifdef ESP8266
|
||||
#if LEDPIN == 3
|
||||
if (ledCount > MAX_LEDS_DMA) ledCount = MAX_LEDS_DMA; //DMA method uses too much ram
|
||||
#endif
|
||||
#endif
|
||||
Serial.begin(115200);
|
||||
Serial.setTimeout(50);
|
||||
DEBUG_PRINTLN();
|
||||
DEBUG_PRINT("---WLED "); DEBUG_PRINT(versionString); DEBUG_PRINT(" "); DEBUG_PRINT(VERSION); DEBUG_PRINTLN(" INIT---");
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
DEBUG_PRINT("esp32 "); DEBUG_PRINTLN(ESP.getSdkVersion());
|
||||
#else
|
||||
DEBUG_PRINT("esp8266 "); DEBUG_PRINTLN(ESP.getCoreVersion());
|
||||
#endif
|
||||
int heapPreAlloc = ESP.getFreeHeap();
|
||||
DEBUG_PRINT("heap ");
|
||||
DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
|
||||
strip.init(EEPROM.read(372),ledCount,EEPROM.read(2204),disableNLeds); //init LEDs quickly
|
||||
strip.setBrightness(0);
|
||||
|
||||
DEBUG_PRINT("LEDs inited. heap usage ~");
|
||||
DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
|
||||
|
||||
#ifndef WLED_DISABLE_FILESYSTEM
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
SPIFFS.begin(true);
|
||||
#endif
|
||||
SPIFFS.begin();
|
||||
#endif
|
||||
|
||||
DEBUG_PRINTLN("Load EEPROM");
|
||||
loadSettingsFromEEPROM(true);
|
||||
beginStrip();
|
||||
userSetup();
|
||||
if (strcmp(clientSSID,"Your_Network") == 0) showWelcomePage = true;
|
||||
WiFi.persistent(false);
|
||||
|
||||
if (macroBoot>0) applyMacro(macroBoot);
|
||||
Serial.println("Ada");
|
||||
|
||||
//generate module IDs
|
||||
escapedMac = WiFi.macAddress();
|
||||
escapedMac.replace(":", "");
|
||||
escapedMac.toLowerCase();
|
||||
if (strcmp(cmDNS,"x") == 0) //fill in unique mdns default
|
||||
{
|
||||
strcpy(cmDNS, "wled-");
|
||||
sprintf(cmDNS+5, "%*s", 6, escapedMac.c_str()+6);
|
||||
}
|
||||
if (mqttDeviceTopic[0] == 0)
|
||||
{
|
||||
strcpy(mqttDeviceTopic, "wled/");
|
||||
sprintf(mqttDeviceTopic+5, "%*s", 6, escapedMac.c_str()+6);
|
||||
}
|
||||
if (mqttClientID[0] == 0)
|
||||
{
|
||||
strcpy(mqttClientID, "WLED-");
|
||||
sprintf(mqttClientID+5, "%*s", 6, escapedMac.c_str()+6);
|
||||
}
|
||||
|
||||
strip.service();
|
||||
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (aOtaEnabled)
|
||||
{
|
||||
ArduinoOTA.onStart([]() {
|
||||
#ifdef ESP8266
|
||||
wifi_set_sleep_type(NONE_SLEEP_T);
|
||||
#endif
|
||||
DEBUG_PRINTLN("Start ArduinoOTA");
|
||||
});
|
||||
if (strlen(cmDNS) > 0) ArduinoOTA.setHostname(cmDNS);
|
||||
}
|
||||
#endif
|
||||
|
||||
//HTTP server page init
|
||||
initServer();
|
||||
}
|
||||
|
||||
|
||||
void beginStrip()
|
||||
{
|
||||
// Initialize NeoPixel Strip and button
|
||||
strip.setShowCallback(handleOverlayDraw);
|
||||
|
||||
#ifdef BTNPIN
|
||||
pinMode(BTNPIN, INPUT_PULLUP);
|
||||
#endif
|
||||
|
||||
if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true);
|
||||
colorUpdated(0);
|
||||
|
||||
//init relay pin
|
||||
#if RLYPIN >= 0
|
||||
pinMode(RLYPIN, OUTPUT);
|
||||
#if RLYMDE
|
||||
digitalWrite(RLYPIN, bri);
|
||||
#else
|
||||
digitalWrite(RLYPIN, !bri);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//disable button if it is "pressed" unintentionally
|
||||
#ifdef BTNPIN
|
||||
if(digitalRead(BTNPIN) == LOW) buttonEnabled = false;
|
||||
#else
|
||||
buttonEnabled = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void initAP(bool resetAP=false){
|
||||
if (apBehavior == 3 && !resetAP) return;
|
||||
|
||||
if (!apSSID[0] || resetAP) strcpy(apSSID, "WLED-AP");
|
||||
if (resetAP) strcpy(apPass,"wled1234");
|
||||
DEBUG_PRINT("Opening access point ");
|
||||
DEBUG_PRINTLN(apSSID);
|
||||
WiFi.softAPConfig(IPAddress(4, 3, 2, 1), IPAddress(4, 3, 2, 1), IPAddress(255,255,255,0));
|
||||
WiFi.softAP(apSSID, apPass, apChannel, apHide);
|
||||
|
||||
if (!apActive) //start captive portal if AP active
|
||||
{
|
||||
DEBUG_PRINTLN("Init AP interfaces");
|
||||
server.begin();
|
||||
if (udpPort > 0 && udpPort != ntpLocalPort)
|
||||
{
|
||||
udpConnected = notifierUdp.begin(udpPort);
|
||||
}
|
||||
if (udpRgbPort > 0 && udpRgbPort != ntpLocalPort && udpRgbPort != udpPort)
|
||||
{
|
||||
udpRgbConnected = rgbUdp.begin(udpRgbPort);
|
||||
}
|
||||
|
||||
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
|
||||
dnsServer.start(53, "*", WiFi.softAPIP());
|
||||
}
|
||||
apActive = true;
|
||||
}
|
||||
|
||||
void initConnection()
|
||||
{
|
||||
WiFi.disconnect(); //close old connections
|
||||
|
||||
if (staticIP[0] != 0 && staticGateway[0] != 0)
|
||||
{
|
||||
WiFi.config(staticIP, staticGateway, staticSubnet, IPAddress(8,8,8,8));
|
||||
} else
|
||||
{
|
||||
WiFi.config(0U, 0U, 0U);
|
||||
}
|
||||
|
||||
lastReconnectAttempt = millis();
|
||||
|
||||
if (!WLED_WIFI_CONFIGURED)
|
||||
{
|
||||
DEBUG_PRINT("No connection configured. ");
|
||||
if (!apActive) initAP(); //instantly go to ap mode
|
||||
return;
|
||||
} else if (!apActive) {
|
||||
if (apBehavior == 2)
|
||||
{
|
||||
initAP();
|
||||
} else
|
||||
{
|
||||
DEBUG_PRINTLN("Access point disabled.");
|
||||
WiFi.softAPdisconnect(true);
|
||||
}
|
||||
}
|
||||
showWelcomePage = false;
|
||||
|
||||
DEBUG_PRINT("Connecting to ");
|
||||
DEBUG_PRINT(clientSSID);
|
||||
DEBUG_PRINTLN("...");
|
||||
|
||||
#ifdef ESP8266
|
||||
WiFi.hostname(serverDescription);
|
||||
#endif
|
||||
WiFi.begin(clientSSID, clientPass);
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
WiFi.setHostname(serverDescription);
|
||||
#endif
|
||||
}
|
||||
|
||||
void initInterfaces() {
|
||||
DEBUG_PRINTLN("Init STA interfaces");
|
||||
|
||||
if (hueIP[0] == 0)
|
||||
{
|
||||
hueIP[0] = WiFi.localIP()[0];
|
||||
hueIP[1] = WiFi.localIP()[1];
|
||||
hueIP[2] = WiFi.localIP()[2];
|
||||
}
|
||||
|
||||
//init Alexa hue emulation
|
||||
if (alexaEnabled) alexaInit();
|
||||
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (aOtaEnabled) ArduinoOTA.begin();
|
||||
#endif
|
||||
|
||||
strip.service();
|
||||
// Set up mDNS responder:
|
||||
if (strlen(cmDNS) > 0)
|
||||
{
|
||||
if (!aOtaEnabled) MDNS.begin(cmDNS);
|
||||
|
||||
DEBUG_PRINTLN("mDNS started");
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
MDNS.addService("wled", "tcp", 80);
|
||||
MDNS.addServiceTxt("wled", "tcp", "mac", escapedMac.c_str());
|
||||
}
|
||||
server.begin();
|
||||
|
||||
if (udpPort > 0 && udpPort != ntpLocalPort)
|
||||
{
|
||||
udpConnected = notifierUdp.begin(udpPort);
|
||||
if (udpConnected && udpRgbPort != udpPort) udpRgbConnected = rgbUdp.begin(udpRgbPort);
|
||||
}
|
||||
if (ntpEnabled) ntpConnected = ntpUdp.begin(ntpLocalPort);
|
||||
|
||||
initBlynk(blynkApiKey);
|
||||
e131.begin((e131Multicast) ? E131_MULTICAST : E131_UNICAST , e131Universe, E131_MAX_UNIVERSE_COUNT);
|
||||
reconnectHue();
|
||||
initMqtt();
|
||||
interfacesInited = true;
|
||||
wasConnected = true;
|
||||
}
|
||||
|
||||
byte stacO = 0;
|
||||
uint32_t lastHeap;
|
||||
unsigned long heapTime = 0;
|
||||
|
||||
void handleConnection() {
|
||||
if (millis() < 2000 && (!WLED_WIFI_CONFIGURED || apBehavior == 2)) return;
|
||||
if (lastReconnectAttempt == 0) initConnection();
|
||||
|
||||
//reconnect WiFi to clear stale allocations if heap gets too low
|
||||
if (millis() - heapTime > 5000)
|
||||
{
|
||||
uint32_t heap = ESP.getFreeHeap();
|
||||
if (heap < 9000 && lastHeap < 9000) {
|
||||
DEBUG_PRINT("Heap too low! ");
|
||||
DEBUG_PRINTLN(heap);
|
||||
forceReconnect = true;
|
||||
}
|
||||
lastHeap = heap;
|
||||
heapTime = millis();
|
||||
}
|
||||
|
||||
byte stac = 0;
|
||||
if (apActive) {
|
||||
#ifdef ESP8266
|
||||
stac = wifi_softap_get_station_num();
|
||||
#else
|
||||
wifi_sta_list_t stationList;
|
||||
esp_wifi_ap_get_sta_list(&stationList);
|
||||
stac = stationList.num;
|
||||
#endif
|
||||
if (stac != stacO)
|
||||
{
|
||||
stacO = stac;
|
||||
DEBUG_PRINT("Connected AP clients: ");
|
||||
DEBUG_PRINTLN(stac);
|
||||
if (!WLED_CONNECTED && WLED_WIFI_CONFIGURED) { //trying to connect, but not connected
|
||||
if (stac) WiFi.disconnect(); //disable search so that AP can work
|
||||
else initConnection(); //restart search
|
||||
}
|
||||
}
|
||||
}
|
||||
if (forceReconnect) {
|
||||
DEBUG_PRINTLN("Forcing reconnect.");
|
||||
initConnection();
|
||||
interfacesInited = false;
|
||||
forceReconnect = false;
|
||||
wasConnected = false;
|
||||
return;
|
||||
}
|
||||
if (!WLED_CONNECTED) {
|
||||
if (interfacesInited) {
|
||||
DEBUG_PRINTLN("Disconnected!");
|
||||
interfacesInited = false;
|
||||
initConnection();
|
||||
}
|
||||
if (millis() - lastReconnectAttempt > ((stac) ? 300000 : 20000) && WLED_WIFI_CONFIGURED) initConnection();
|
||||
if (!apActive && millis() - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == 1)) initAP();
|
||||
} else if (!interfacesInited) { //newly connected
|
||||
DEBUG_PRINTLN("");
|
||||
DEBUG_PRINT("Connected! IP address: ");
|
||||
DEBUG_PRINTLN(WiFi.localIP());
|
||||
initInterfaces();
|
||||
userConnected();
|
||||
|
||||
//shut down AP
|
||||
if (apBehavior != 2 && apActive)
|
||||
{
|
||||
dnsServer.stop();
|
||||
WiFi.softAPdisconnect(true);
|
||||
apActive = false;
|
||||
DEBUG_PRINTLN("Access point disabled.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//by https://github.com/tzapu/WiFiManager/blob/master/WiFiManager.cpp
|
||||
int getSignalQuality(int rssi)
|
||||
{
|
||||
int quality = 0;
|
||||
|
||||
if (rssi <= -100) {
|
||||
quality = 0;
|
||||
} else if (rssi >= -50) {
|
||||
quality = 100;
|
||||
} else {
|
||||
quality = 2 * (rssi + 100);
|
||||
}
|
||||
return quality;
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Used to draw clock overlays over the strip
|
||||
*/
|
||||
|
||||
void initCronixie()
|
||||
{
|
||||
if (overlayCurrent == 3 && !cronixieInit)
|
||||
{
|
||||
strip.driverModeCronixie(true);
|
||||
strip.setCronixieBacklight(cronixieBacklight);
|
||||
setCronixie();
|
||||
cronixieInit = true;
|
||||
} else if (cronixieInit && overlayCurrent != 3)
|
||||
{
|
||||
strip.driverModeCronixie(false);
|
||||
cronixieInit = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleOverlays()
|
||||
{
|
||||
if (millis() - overlayRefreshedTime > overlayRefreshMs)
|
||||
{
|
||||
initCronixie();
|
||||
updateLocalTime();
|
||||
checkTimers();
|
||||
checkCountdown();
|
||||
if (overlayCurrent == 3) _overlayCronixie();//Diamex cronixie clock kit
|
||||
overlayRefreshedTime = millis();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _overlayAnalogClock()
|
||||
{
|
||||
int overlaySize = overlayMax - overlayMin +1;
|
||||
if (countdownMode)
|
||||
{
|
||||
_overlayAnalogCountdown(); return;
|
||||
}
|
||||
double hourP = ((double)(hour(local)%12))/12;
|
||||
double minuteP = ((double)minute(local))/60;
|
||||
hourP = hourP + minuteP/12;
|
||||
double secondP = ((double)second(local))/60;
|
||||
int hourPixel = floor(analogClock12pixel + overlaySize*hourP);
|
||||
if (hourPixel > overlayMax) hourPixel = overlayMin -1 + hourPixel - overlayMax;
|
||||
int minutePixel = floor(analogClock12pixel + overlaySize*minuteP);
|
||||
if (minutePixel > overlayMax) minutePixel = overlayMin -1 + minutePixel - overlayMax;
|
||||
int secondPixel = floor(analogClock12pixel + overlaySize*secondP);
|
||||
if (secondPixel > overlayMax) secondPixel = overlayMin -1 + secondPixel - overlayMax;
|
||||
if (analogClockSecondsTrail)
|
||||
{
|
||||
if (secondPixel < analogClock12pixel)
|
||||
{
|
||||
strip.setRange(analogClock12pixel, overlayMax, 0xFF0000);
|
||||
strip.setRange(overlayMin, secondPixel, 0xFF0000);
|
||||
} else
|
||||
{
|
||||
strip.setRange(analogClock12pixel, secondPixel, 0xFF0000);
|
||||
}
|
||||
}
|
||||
if (analogClock5MinuteMarks)
|
||||
{
|
||||
int pix;
|
||||
for (int i = 0; i <= 12; i++)
|
||||
{
|
||||
pix = analogClock12pixel + round((overlaySize / 12.0) *i);
|
||||
if (pix > overlayMax) pix -= overlaySize;
|
||||
strip.setPixelColor(pix, 0x00FFAA);
|
||||
}
|
||||
}
|
||||
if (!analogClockSecondsTrail) strip.setPixelColor(secondPixel, 0xFF0000);
|
||||
strip.setPixelColor(minutePixel, 0x00FF00);
|
||||
strip.setPixelColor(hourPixel, 0x0000FF);
|
||||
overlayRefreshMs = 998;
|
||||
}
|
||||
|
||||
|
||||
void _overlayAnalogCountdown()
|
||||
{
|
||||
if (now() < countdownTime)
|
||||
{
|
||||
long diff = countdownTime - now();
|
||||
double pval = 60;
|
||||
if (diff > 31557600L) //display in years if more than 365 days
|
||||
{
|
||||
pval = 315576000L; //10 years
|
||||
} else if (diff > 2592000L) //display in months if more than a month
|
||||
{
|
||||
pval = 31557600L; //1 year
|
||||
} else if (diff > 604800) //display in weeks if more than a week
|
||||
{
|
||||
pval = 2592000L; //1 month
|
||||
} else if (diff > 86400) //display in days if more than 24 hours
|
||||
{
|
||||
pval = 604800; //1 week
|
||||
} else if (diff > 3600) //display in hours if more than 60 minutes
|
||||
{
|
||||
pval = 86400; //1 day
|
||||
} else if (diff > 60) //display in minutes if more than 60 seconds
|
||||
{
|
||||
pval = 3600; //1 hour
|
||||
}
|
||||
int overlaySize = overlayMax - overlayMin +1;
|
||||
double perc = (pval-(double)diff)/pval;
|
||||
if (perc > 1.0) perc = 1.0;
|
||||
byte pixelCnt = perc*overlaySize;
|
||||
if (analogClock12pixel + pixelCnt > overlayMax)
|
||||
{
|
||||
strip.setRange(analogClock12pixel, overlayMax, ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
|
||||
strip.setRange(overlayMin, overlayMin +pixelCnt -(1+ overlayMax -analogClock12pixel), ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
|
||||
} else
|
||||
{
|
||||
strip.setRange(analogClock12pixel, analogClock12pixel + pixelCnt, ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
|
||||
}
|
||||
}
|
||||
overlayRefreshMs = 998;
|
||||
}
|
||||
|
||||
|
||||
void handleOverlayDraw() {
|
||||
if (overlayCurrent != 1) return; //only analog clock
|
||||
_overlayAnalogClock();
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
#include <EEPROM.h>
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Methods to handle saving and loading to non-volatile memory
|
||||
* EEPROM Map: https://github.com/Aircoookie/WLED/wiki/EEPROM-Map
|
||||
*/
|
||||
|
||||
#define EEPSIZE 2560
|
||||
|
||||
//eeprom Version code, enables default settings instead of 0 init on update
|
||||
#define EEPVER 14
|
||||
#define EEPVER 19
|
||||
//0 -> old version, default
|
||||
//1 -> 0.4p 1711272 and up
|
||||
//2 -> 0.4p 1711302 and up
|
||||
@ -22,6 +23,11 @@
|
||||
//12-> 0.8.7-dev
|
||||
//13-> 0.9.0-dev
|
||||
//14-> 0.9.0-b1
|
||||
//15-> 0.9.0-b3
|
||||
//16-> 0.9.1
|
||||
//17-> 0.9.1-dmx
|
||||
//18-> 0.9.1-e131
|
||||
//19-> 0.9.1n
|
||||
|
||||
void commit()
|
||||
{
|
||||
@ -61,7 +67,6 @@ void readStringFromEEPROM(uint16_t pos, char* str, uint16_t len)
|
||||
str[len] = 0; //make sure every string is properly terminated. str must be at least len +1 big.
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write configuration to flash
|
||||
*/
|
||||
@ -130,6 +135,8 @@ void saveSettingsToEEPROM()
|
||||
EEPROM.write(368, abs(arlsOffset));
|
||||
EEPROM.write(369, turnOnAtBoot);
|
||||
|
||||
EEPROM.write(370, noWifiSleep);
|
||||
|
||||
EEPROM.write(372, useRGBW);
|
||||
EEPROM.write(374, strip.paletteFade);
|
||||
EEPROM.write(375, strip.milliampsPerLed); //was apWaitTimeSecs up to 0.8.5
|
||||
@ -155,7 +162,7 @@ void saveSettingsToEEPROM()
|
||||
EEPROM.write(396, (utcOffsetSecs<0)); //is negative
|
||||
EEPROM.write(397, syncToggleReceive);
|
||||
EEPROM.write(398, (ledCount >> 8) & 0xFF);
|
||||
EEPROM.write(399, !enableSecTransition);
|
||||
//EEPROM.write(399, was !enableSecTransition);
|
||||
|
||||
//favorite setting (preset) memory (25 slots/ each 20byte)
|
||||
//400 - 940 reserved
|
||||
@ -204,6 +211,10 @@ void saveSettingsToEEPROM()
|
||||
EEPROM.write(2181, macroNl);
|
||||
EEPROM.write(2182, macroDoublePress);
|
||||
|
||||
EEPROM.write(2187, e131Port & 0xFF);
|
||||
EEPROM.write(2188, (e131Port >> 8) & 0xFF);
|
||||
|
||||
EEPROM.write(2189, e131SkipOutOfSequence);
|
||||
EEPROM.write(2190, e131Universe & 0xFF);
|
||||
EEPROM.write(2191, (e131Universe >> 8) & 0xFF);
|
||||
EEPROM.write(2192, e131Multicast);
|
||||
@ -211,10 +222,13 @@ void saveSettingsToEEPROM()
|
||||
EEPROM.write(2194, (realtimeTimeoutMs >> 8) & 0xFF);
|
||||
EEPROM.write(2195, arlsForceMaxBri);
|
||||
EEPROM.write(2196, arlsDisableGammaCorrection);
|
||||
EEPROM.write(2197, DMXAddress & 0xFF);
|
||||
EEPROM.write(2198, (DMXAddress >> 8) & 0xFF);
|
||||
EEPROM.write(2199, DMXMode);
|
||||
|
||||
EEPROM.write(2200, !receiveDirect);
|
||||
EEPROM.write(2201, notifyMacro); //was enableRealtime
|
||||
EEPROM.write(2203, autoRGBtoRGBW);
|
||||
EEPROM.write(2203, strip.rgbwMode);
|
||||
EEPROM.write(2204, skipFirstLed);
|
||||
|
||||
if (saveCurrPresetCycConf)
|
||||
@ -225,13 +239,11 @@ void saveSettingsToEEPROM()
|
||||
EEPROM.write(2208, presetCycleMin);
|
||||
EEPROM.write(2209, presetCycleMax);
|
||||
EEPROM.write(2210, presetApplyBri);
|
||||
EEPROM.write(2211, presetApplyCol);
|
||||
EEPROM.write(2212, presetApplyFx);
|
||||
// was EEPROM.write(2211, presetApplyCol);
|
||||
// was EEPROM.write(2212, presetApplyFx);
|
||||
saveCurrPresetCycConf = false;
|
||||
}
|
||||
|
||||
EEPROM.write(2213, disableNLeds);
|
||||
|
||||
writeStringToEEPROM(2220, blynkApiKey, 35);
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
@ -252,6 +264,19 @@ void saveSettingsToEEPROM()
|
||||
EEPROM.write(2522, mqttPort & 0xFF);
|
||||
EEPROM.write(2523, (mqttPort >> 8) & 0xFF);
|
||||
|
||||
// DMX (2530 - 2549)
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
EEPROM.write(2530, DMXChannels);
|
||||
EEPROM.write(2531, DMXGap & 0xFF);
|
||||
EEPROM.write(2532, (DMXGap >> 8) & 0xFF);
|
||||
EEPROM.write(2533, DMXStart & 0xFF);
|
||||
EEPROM.write(2534, (DMXStart >> 8) & 0xFF);
|
||||
|
||||
for (int i=0; i<15; i++) {
|
||||
EEPROM.write(2535+i, DMXFixtureMap[i]);
|
||||
} // last used: 2549. maybe leave a few bytes for future expansion and go on with 2600 kthxbye.
|
||||
#endif
|
||||
|
||||
commit();
|
||||
}
|
||||
|
||||
@ -473,10 +498,36 @@ void loadSettingsFromEEPROM(bool first)
|
||||
syncToggleReceive = false;
|
||||
}
|
||||
|
||||
if (lastEEPROMversion > 14)
|
||||
{
|
||||
DMXAddress = EEPROM.read(2197) + ((EEPROM.read(2198) << 8) & 0xFF00);
|
||||
DMXMode = EEPROM.read(2199);
|
||||
} else {
|
||||
DMXAddress = 1;
|
||||
DMXMode = DMX_MODE_MULTIPLE_RGB;
|
||||
}
|
||||
|
||||
//if (lastEEPROMversion > 15)
|
||||
//{
|
||||
noWifiSleep = EEPROM.read(370);
|
||||
//}
|
||||
|
||||
if (lastEEPROMversion > 17)
|
||||
{
|
||||
e131SkipOutOfSequence = EEPROM.read(2189);
|
||||
} else {
|
||||
e131SkipOutOfSequence = true;
|
||||
}
|
||||
|
||||
if (lastEEPROMversion > 18)
|
||||
{
|
||||
e131Port = EEPROM.read(2187) + ((EEPROM.read(2188) << 8) & 0xFF00);
|
||||
}
|
||||
|
||||
receiveDirect = !EEPROM.read(2200);
|
||||
notifyMacro = EEPROM.read(2201);
|
||||
|
||||
autoRGBtoRGBW = EEPROM.read(2203);
|
||||
strip.rgbwMode = EEPROM.read(2203);
|
||||
skipFirstLed = EEPROM.read(2204);
|
||||
|
||||
if (EEPROM.read(2210) || EEPROM.read(2211) || EEPROM.read(2212))
|
||||
@ -486,17 +537,15 @@ void loadSettingsFromEEPROM(bool first)
|
||||
presetCycleMin = EEPROM.read(2208);
|
||||
presetCycleMax = EEPROM.read(2209);
|
||||
presetApplyBri = EEPROM.read(2210);
|
||||
presetApplyCol = EEPROM.read(2211);
|
||||
presetApplyFx = EEPROM.read(2212);
|
||||
//was presetApplyCol = EEPROM.read(2211);
|
||||
//was presetApplyFx = EEPROM.read(2212);
|
||||
}
|
||||
|
||||
disableNLeds = EEPROM.read(2213);
|
||||
|
||||
bootPreset = EEPROM.read(389);
|
||||
wifiLock = EEPROM.read(393);
|
||||
utcOffsetSecs = EEPROM.read(394) + ((EEPROM.read(395) << 8) & 0xFF00);
|
||||
if (EEPROM.read(396)) utcOffsetSecs = -utcOffsetSecs; //negative
|
||||
enableSecTransition = !EEPROM.read(399);
|
||||
//!EEPROM.read(399); was enableSecTransition
|
||||
|
||||
//favorite setting (preset) memory (25 slots/ each 20byte)
|
||||
//400 - 899 reserved
|
||||
@ -507,6 +556,18 @@ void loadSettingsFromEEPROM(bool first)
|
||||
readStringFromEEPROM(2220, blynkApiKey, 35);
|
||||
if (strlen(blynkApiKey) < 25) blynkApiKey[0] = 0;
|
||||
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
// DMX (2530 - 2549)2535
|
||||
DMXChannels = EEPROM.read(2530);
|
||||
DMXGap = EEPROM.read(2531) + ((EEPROM.read(2532) << 8) & 0xFF00);
|
||||
DMXStart = EEPROM.read(2533) + ((EEPROM.read(2534) << 8) & 0xFF00);
|
||||
|
||||
for (int i=0;i<15;i++) {
|
||||
DMXFixtureMap[i] = EEPROM.read(2535+i);
|
||||
} //last used: 2549
|
||||
EEPROM.write(2550, DMXStartLED);
|
||||
#endif
|
||||
|
||||
//user MOD memory
|
||||
//2944 - 3071 reserved
|
||||
|
||||
@ -533,7 +594,7 @@ void savedToPresets()
|
||||
savedPresets &= ~(0x01 << (index-1));
|
||||
}
|
||||
}
|
||||
if (EEPROM.read(700) == 2) {
|
||||
if (EEPROM.read(700) == 2 || EEPROM.read(700) == 3) {
|
||||
savedPresets |= 0x01 << 15;
|
||||
} else
|
||||
{
|
||||
@ -541,7 +602,7 @@ void savedToPresets()
|
||||
}
|
||||
}
|
||||
|
||||
bool applyPreset(byte index, bool loadBri = true, bool loadCol = true, bool loadFX = true)
|
||||
bool applyPreset(byte index, bool loadBri)
|
||||
{
|
||||
if (index == 255 || index == 0)
|
||||
{
|
||||
@ -550,32 +611,37 @@ bool applyPreset(byte index, bool loadBri = true, bool loadCol = true, bool load
|
||||
}
|
||||
if (index > 16 || index < 1) return false;
|
||||
uint16_t i = 380 + index*20;
|
||||
byte ver = EEPROM.read(i);
|
||||
|
||||
if (index < 16) {
|
||||
if (EEPROM.read(i) != 1) return false;
|
||||
if (ver != 1) return false;
|
||||
strip.applyToAllSelected = true;
|
||||
if (loadBri) bri = EEPROM.read(i+1);
|
||||
if (loadCol)
|
||||
|
||||
for (byte j=0; j<4; j++)
|
||||
{
|
||||
for (byte j=0; j<4; j++)
|
||||
{
|
||||
col[j] = EEPROM.read(i+j+2);
|
||||
colSec[j] = EEPROM.read(i+j+6);
|
||||
}
|
||||
strip.setColor(2, EEPROM.read(i+12), EEPROM.read(i+13), EEPROM.read(i+14), EEPROM.read(i+15)); //tertiary color
|
||||
}
|
||||
if (loadFX)
|
||||
{
|
||||
effectCurrent = EEPROM.read(i+10);
|
||||
effectSpeed = EEPROM.read(i+11);
|
||||
effectIntensity = EEPROM.read(i+16);
|
||||
effectPalette = EEPROM.read(i+17);
|
||||
col[j] = EEPROM.read(i+j+2);
|
||||
colSec[j] = EEPROM.read(i+j+6);
|
||||
}
|
||||
strip.setColor(2, EEPROM.read(i+12), EEPROM.read(i+13), EEPROM.read(i+14), EEPROM.read(i+15)); //tertiary color
|
||||
|
||||
effectCurrent = EEPROM.read(i+10);
|
||||
effectSpeed = EEPROM.read(i+11);
|
||||
effectIntensity = EEPROM.read(i+16);
|
||||
effectPalette = EEPROM.read(i+17);
|
||||
} else {
|
||||
if (EEPROM.read(i) != 2) return false;
|
||||
if (ver != 2 && ver != 3) return false;
|
||||
strip.applyToAllSelected = false;
|
||||
if (loadBri) bri = EEPROM.read(i+1);
|
||||
WS2812FX::Segment* seg = strip.getSegments();
|
||||
memcpy(seg, EEPROM.getDataPtr() +i+2, 240);
|
||||
if (ver == 2) { //versions before 2004230 did not have opacity
|
||||
for (byte j = 0; j < strip.getMaxSegments(); j++)
|
||||
{
|
||||
strip.getSegment(j).opacity = 255;
|
||||
strip.getSegment(j).setOption(SEG_OPTION_ON, 1);
|
||||
}
|
||||
}
|
||||
setValuesFromMainSeg();
|
||||
}
|
||||
currentPreset = index;
|
||||
@ -583,7 +649,7 @@ bool applyPreset(byte index, bool loadBri = true, bool loadCol = true, bool load
|
||||
return true;
|
||||
}
|
||||
|
||||
void savePreset(byte index)
|
||||
void savePreset(byte index, bool persist)
|
||||
{
|
||||
if (index > 16) return;
|
||||
if (index < 1) {saveSettingsToEEPROM();return;}
|
||||
@ -609,13 +675,13 @@ void savePreset(byte index)
|
||||
EEPROM.write(i+16, effectIntensity);
|
||||
EEPROM.write(i+17, effectPalette);
|
||||
} else { //segment 16 can save segments
|
||||
EEPROM.write(i, 2);
|
||||
EEPROM.write(i, 3);
|
||||
EEPROM.write(i+1, bri);
|
||||
WS2812FX::Segment* seg = strip.getSegments();
|
||||
memcpy(EEPROM.getDataPtr() +i+2, seg, 240);
|
||||
}
|
||||
|
||||
commit();
|
||||
if (persist) commit();
|
||||
savedToPresets();
|
||||
currentPreset = index;
|
||||
isPreset = true;
|
||||
@ -651,7 +717,7 @@ void applyMacro(byte index)
|
||||
}
|
||||
|
||||
|
||||
void saveMacro(byte index, String mc, bool sing=true) //only commit on single save, not in settings
|
||||
void saveMacro(byte index, String mc, bool persist) //only commit on single save, not in settings
|
||||
{
|
||||
index-=1;
|
||||
if (index > 15) return;
|
||||
@ -660,5 +726,5 @@ void saveMacro(byte index, String mc, bool sing=true) //only commit on single sa
|
||||
{
|
||||
EEPROM.write(i, mc.charAt(i-s));
|
||||
}
|
||||
if (sing) commit();
|
||||
if (persist) commit();
|
||||
}
|
83
wled00/wled_serial.cpp
Normal file
83
wled00/wled_serial.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Adalight handler
|
||||
*/
|
||||
|
||||
enum class AdaState {
|
||||
Header_A,
|
||||
Header_d,
|
||||
Header_a,
|
||||
Header_CountHi,
|
||||
Header_CountLo,
|
||||
Header_CountCheck,
|
||||
Data_Red,
|
||||
Data_Green,
|
||||
Data_Blue
|
||||
};
|
||||
|
||||
void handleSerial()
|
||||
{
|
||||
#ifdef WLED_ENABLE_ADALIGHT
|
||||
static auto state = AdaState::Header_A;
|
||||
static uint16_t count = 0;
|
||||
static uint16_t pixel = 0;
|
||||
static byte check = 0x00;
|
||||
static byte red = 0x00;
|
||||
static byte green = 0x00;
|
||||
|
||||
while (Serial.available() > 0)
|
||||
{
|
||||
yield();
|
||||
byte next = Serial.read();
|
||||
switch (state) {
|
||||
case AdaState::Header_A:
|
||||
if (next == 'A') state = AdaState::Header_d;
|
||||
break;
|
||||
case AdaState::Header_d:
|
||||
if (next == 'd') state = AdaState::Header_a;
|
||||
else state = AdaState::Header_A;
|
||||
break;
|
||||
case AdaState::Header_a:
|
||||
if (next == 'a') state = AdaState::Header_CountHi;
|
||||
else state = AdaState::Header_A;
|
||||
break;
|
||||
case AdaState::Header_CountHi:
|
||||
pixel = 0;
|
||||
count = next * 0x100;
|
||||
check = next;
|
||||
state = AdaState::Header_CountLo;
|
||||
break;
|
||||
case AdaState::Header_CountLo:
|
||||
count += next + 1;
|
||||
check = check ^ next ^ 0x55;
|
||||
state = AdaState::Header_CountCheck;
|
||||
break;
|
||||
case AdaState::Header_CountCheck:
|
||||
if (check == next) state = AdaState::Data_Red;
|
||||
else state = AdaState::Header_A;
|
||||
break;
|
||||
case AdaState::Data_Red:
|
||||
red = next;
|
||||
state = AdaState::Data_Green;
|
||||
break;
|
||||
case AdaState::Data_Green:
|
||||
green = next;
|
||||
state = AdaState::Data_Blue;
|
||||
break;
|
||||
case AdaState::Data_Blue:
|
||||
byte blue = next;
|
||||
if (!realtimeOverride) setRealtimePixel(pixel++, red, green, blue, 0);
|
||||
if (--count > 0) state = AdaState::Data_Red;
|
||||
else {
|
||||
if (!realtimeMode && bri == 0) strip.setBrightness(briLast);
|
||||
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_ADALIGHT);
|
||||
|
||||
if (!realtimeOverride) strip.show();
|
||||
state = AdaState::Header_A;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Server page definitions
|
||||
* Integrated HTTP web server page declarations
|
||||
*/
|
||||
|
||||
//Is this an IP?
|
||||
@ -62,39 +64,44 @@ void initServer()
|
||||
});
|
||||
|
||||
server.on("/reset", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
serveMessage(request, 200,"Rebooting now...","Please wait ~10 seconds...",129);
|
||||
serveMessage(request, 200,"Rebooting now...",F("Please wait ~10 seconds..."),129);
|
||||
doReboot = true;
|
||||
});
|
||||
|
||||
server.on("/settings/wifi", HTTP_POST, [](AsyncWebServerRequest *request){
|
||||
if (!(wifiLock && otaLock)) handleSettingsSet(request, 1);
|
||||
serveMessage(request, 200,"WiFi settings saved.","Please connect to the new IP (if changed)",129);
|
||||
serveMessage(request, 200,F("WiFi settings saved."),F("Please connect to the new IP (if changed)"),129);
|
||||
forceReconnect = true;
|
||||
});
|
||||
|
||||
server.on("/settings/leds", HTTP_POST, [](AsyncWebServerRequest *request){
|
||||
handleSettingsSet(request, 2);
|
||||
serveMessage(request, 200,"LED settings saved.","Redirecting...",1);
|
||||
serveMessage(request, 200,F("LED settings saved."),"Redirecting...",1);
|
||||
});
|
||||
|
||||
server.on("/settings/ui", HTTP_POST, [](AsyncWebServerRequest *request){
|
||||
handleSettingsSet(request, 3);
|
||||
serveMessage(request, 200,"UI settings saved.","Redirecting...",1);
|
||||
serveMessage(request, 200,F("UI settings saved."),"Redirecting...",1);
|
||||
});
|
||||
|
||||
server.on("/settings/dmx", HTTP_POST, [](AsyncWebServerRequest *request){
|
||||
handleSettingsSet(request, 7);
|
||||
serveMessage(request, 200,F("UI settings saved."),"Redirecting...",1);
|
||||
});
|
||||
|
||||
server.on("/settings/sync", HTTP_POST, [](AsyncWebServerRequest *request){
|
||||
handleSettingsSet(request, 4);
|
||||
serveMessage(request, 200,"Sync settings saved.","Redirecting...",1);
|
||||
serveMessage(request, 200,F("Sync settings saved."),"Redirecting...",1);
|
||||
});
|
||||
|
||||
server.on("/settings/time", HTTP_POST, [](AsyncWebServerRequest *request){
|
||||
handleSettingsSet(request, 5);
|
||||
serveMessage(request, 200,"Time settings saved.","Redirecting...",1);
|
||||
serveMessage(request, 200,F("Time settings saved."),"Redirecting...",1);
|
||||
});
|
||||
|
||||
server.on("/settings/sec", HTTP_POST, [](AsyncWebServerRequest *request){
|
||||
handleSettingsSet(request, 6);
|
||||
if (!doReboot) serveMessage(request, 200,"Security settings saved.","Rebooting, please wait ~10 seconds...",129);
|
||||
if (!doReboot) serveMessage(request, 200,F("Security settings saved."),F("Rebooting, please wait ~10 seconds..."),129);
|
||||
doReboot = true;
|
||||
});
|
||||
|
||||
@ -138,8 +145,12 @@ void initServer()
|
||||
request->send_P(200, "text/html", PAGE_usermod);
|
||||
});
|
||||
|
||||
server.on("/url", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
URL_response(request);
|
||||
});
|
||||
|
||||
server.on("/teapot", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
serveMessage(request, 418, "418. I'm a teapot.", "(Tangible Embedded Advanced Project Of Twinkling)", 254);
|
||||
serveMessage(request, 418, F("418. I'm a teapot."), F("(Tangible Embedded Advanced Project Of Twinkling)"), 254);
|
||||
});
|
||||
|
||||
//if OTA is allowed
|
||||
@ -152,7 +163,7 @@ void initServer()
|
||||
#endif
|
||||
#else
|
||||
server.on("/edit", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
serveMessage(request, 501, "Not implemented", "The SPIFFS editor is disabled in this build.", 254);
|
||||
serveMessage(request, 501, "Not implemented", F("The SPIFFS editor is disabled in this build."), 254);
|
||||
});
|
||||
#endif
|
||||
//init ota page
|
||||
@ -164,9 +175,9 @@ void initServer()
|
||||
server.on("/update", HTTP_POST, [](AsyncWebServerRequest *request){
|
||||
if (Update.hasError())
|
||||
{
|
||||
serveMessage(request, 500, "Failed updating firmware!", "Please check your file and retry!", 254); return;
|
||||
serveMessage(request, 500, F("Failed updating firmware!"), F("Please check your file and retry!"), 254); return;
|
||||
}
|
||||
serveMessage(request, 200, "Successfully updated firmware!", "Please wait while the module reboots...", 131);
|
||||
serveMessage(request, 200, F("Successfully updated firmware!"), F("Please wait while the module reboots..."), 131);
|
||||
doReboot = true;
|
||||
},[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
|
||||
if(!index){
|
||||
@ -188,7 +199,7 @@ void initServer()
|
||||
|
||||
#else
|
||||
server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
serveMessage(request, 501, "Not implemented", "OTA updates are disabled in this build.", 254);
|
||||
serveMessage(request, 501, "Not implemented", F("OTA updates are disabled in this build."), 254);
|
||||
});
|
||||
#endif
|
||||
} else
|
||||
@ -201,6 +212,16 @@ void initServer()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
server.on("/dmxmap", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
request->send_P(200, "text/html", PAGE_dmxmap , dmxProcessor);
|
||||
});
|
||||
#else
|
||||
server.on("/dmxmap", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
serveMessage(request, 501, "Not implemented", F("DMX support is not enabled in this build."), 254);
|
||||
});
|
||||
#endif
|
||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
|
||||
if (captivePortal(request)) return;
|
||||
serveIndexOrWelcome(request);
|
||||
@ -273,10 +294,10 @@ String msgProcessor(const String& var)
|
||||
messageBody += "<script>setTimeout(RP," + String((optt-120)*1000) + ")</script>";
|
||||
} else if (optt == 253)
|
||||
{
|
||||
messageBody += "<br><br><form action=/settings><button class=\"bt\" type=submit>Back</button></form>"; //button to settings
|
||||
messageBody += F("<br><br><form action=/settings><button class=\"bt\" type=submit>Back</button></form>"); //button to settings
|
||||
} else if (optt == 254)
|
||||
{
|
||||
messageBody += "<br><br><button type=\"button\" class=\"bt\" onclick=\"B()\">Back</button>";
|
||||
messageBody += F("<br><br><button type=\"button\" class=\"bt\" onclick=\"B()\">Back</button>");
|
||||
}
|
||||
return messageBody;
|
||||
}
|
||||
@ -284,7 +305,7 @@ String msgProcessor(const String& var)
|
||||
}
|
||||
|
||||
|
||||
void serveMessage(AsyncWebServerRequest* request, uint16_t code, String headl, String subl="", byte optionT=255)
|
||||
void serveMessage(AsyncWebServerRequest* request, uint16_t code, String headl, String subl, byte optionT)
|
||||
{
|
||||
messageHead = headl;
|
||||
messageSub = subl;
|
||||
@ -301,10 +322,38 @@ String settingsProcessor(const String& var)
|
||||
getSettingsJS(optionType, buf);
|
||||
return String(buf);
|
||||
}
|
||||
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
|
||||
if (var == "DMXMENU") {
|
||||
return String(F("<form action=/settings/dmx><button type=submit>DMX Output</button></form>"));
|
||||
}
|
||||
|
||||
#endif
|
||||
if (var == "SCSS") return String(FPSTR(PAGE_settingsCss));
|
||||
return String();
|
||||
}
|
||||
|
||||
String dmxProcessor(const String& var)
|
||||
{
|
||||
String mapJS;
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
if (var == "DMXVARS") {
|
||||
mapJS += "\nCN=" + String(DMXChannels) + ";\n";
|
||||
mapJS += "CS=" + String(DMXStart) + ";\n";
|
||||
mapJS += "CG=" + String(DMXGap) + ";\n";
|
||||
mapJS += "LC=" + String(ledCount) + ";\n";
|
||||
mapJS += "var CH=[";
|
||||
for (int i=0;i<15;i++) {
|
||||
mapJS += String(DMXFixtureMap[i]) + ",";
|
||||
}
|
||||
mapJS += "0];";
|
||||
}
|
||||
#endif
|
||||
|
||||
return mapJS;
|
||||
}
|
||||
|
||||
|
||||
void serveSettings(AsyncWebServerRequest* request)
|
||||
{
|
||||
@ -318,6 +367,9 @@ void serveSettings(AsyncWebServerRequest* request)
|
||||
else if (url.indexOf("sync") > 0) subPage = 4;
|
||||
else if (url.indexOf("time") > 0) subPage = 5;
|
||||
else if (url.indexOf("sec") > 0) subPage = 6;
|
||||
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
|
||||
else if (url.indexOf("dmx") > 0) subPage = 7;
|
||||
#endif
|
||||
} else subPage = 255; //welcome page
|
||||
|
||||
if (subPage == 1 && wifiLock && otaLock)
|
||||
@ -339,7 +391,8 @@ void serveSettings(AsyncWebServerRequest* request)
|
||||
case 4: request->send_P(200, "text/html", PAGE_settings_sync, settingsProcessor); break;
|
||||
case 5: request->send_P(200, "text/html", PAGE_settings_time, settingsProcessor); break;
|
||||
case 6: request->send_P(200, "text/html", PAGE_settings_sec , settingsProcessor); break;
|
||||
case 7: request->send_P(200, "text/html", PAGE_settings_dmx , settingsProcessor); break;
|
||||
case 255: request->send_P(200, "text/html", PAGE_welcome); break;
|
||||
default: request->send_P(200, "text/html", PAGE_settings);
|
||||
default: request->send_P(200, "text/html", PAGE_settings , settingsProcessor);
|
||||
}
|
||||
}
|
@ -1,15 +1,17 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Sending XML status files to client
|
||||
*/
|
||||
|
||||
//build XML response to HTTP /win API request
|
||||
char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr)
|
||||
char* XML_response(AsyncWebServerRequest *request, char* dest)
|
||||
{
|
||||
char sbuf[(dest == nullptr)?1024:1]; //allocate local buffer if none passed
|
||||
obuf = (dest == nullptr)? sbuf:dest;
|
||||
|
||||
olen = 0;
|
||||
oappend("<?xml version=\"1.0\" ?><vs><ac>");
|
||||
oappend((const char*)F("<?xml version=\"1.0\" ?><vs><ac>"));
|
||||
oappendi((nightlightActive && nightlightFade) ? briT : bri);
|
||||
oappend("</ac>");
|
||||
|
||||
@ -46,23 +48,36 @@ char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr)
|
||||
oappend("</ix><fp>");
|
||||
oappendi(effectPalette);
|
||||
oappend("</fp><wv>");
|
||||
if (useRGBW && !autoRGBtoRGBW) {
|
||||
if (strip.rgbwMode) {
|
||||
oappendi(col[3]);
|
||||
} else {
|
||||
oappend("-1");
|
||||
}
|
||||
oappend("</wv><ws>");
|
||||
oappendi(colSec[3]);
|
||||
oappend("</ws><cy>");
|
||||
oappend("</ws><ps>");
|
||||
oappendi((currentPreset < 1) ? 0:currentPreset);
|
||||
oappend("</ps><cy>");
|
||||
oappendi(presetCyclingEnabled);
|
||||
oappend("</cy><ds>");
|
||||
if (realtimeActive)
|
||||
if (realtimeMode)
|
||||
{
|
||||
String mesg = "Live ";
|
||||
if (realtimeIP[0] == 0)
|
||||
if (realtimeMode == REALTIME_MODE_E131 || realtimeMode == REALTIME_MODE_ARTNET)
|
||||
{
|
||||
mesg += "E1.31 mode";
|
||||
} else {
|
||||
mesg += (realtimeMode == REALTIME_MODE_E131) ? "E1.31" : "Art-Net";
|
||||
mesg += " mode ";
|
||||
mesg += DMXMode;
|
||||
mesg += F(" at DMX Address ");
|
||||
mesg += DMXAddress;
|
||||
mesg += " from ";
|
||||
mesg += realtimeIP[0];
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
mesg += ".";
|
||||
mesg += realtimeIP[i];
|
||||
}
|
||||
} else if (realtimeMode == REALTIME_MODE_UDP || realtimeMode == REALTIME_MODE_HYPERION) {
|
||||
mesg += "UDP from ";
|
||||
mesg += realtimeIP[0];
|
||||
for (int i = 1; i < 4; i++)
|
||||
@ -70,6 +85,10 @@ char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr)
|
||||
mesg += ".";
|
||||
mesg += realtimeIP[i];
|
||||
}
|
||||
} else if (realtimeMode == REALTIME_MODE_ADALIGHT) {
|
||||
mesg += F("USB Adalight");
|
||||
} else { //generic
|
||||
mesg += "data";
|
||||
}
|
||||
oappend((char*)mesg.c_str());
|
||||
} else {
|
||||
@ -81,6 +100,53 @@ char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr)
|
||||
if (request != nullptr) request->send(200, "text/xml", obuf);
|
||||
}
|
||||
|
||||
char* URL_response(AsyncWebServerRequest *request)
|
||||
{
|
||||
char sbuf[256]; //allocate local buffer if none passed
|
||||
char s2buf[100];
|
||||
obuf = s2buf;
|
||||
olen = 0;
|
||||
|
||||
char s[16];
|
||||
oappend("http://");
|
||||
IPAddress localIP = WiFi.localIP();
|
||||
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
||||
oappend(s);
|
||||
oappend("/win&A=");
|
||||
oappendi(bri);
|
||||
oappend("&CL=h");
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
sprintf(s,"%02X", col[i]);
|
||||
oappend(s);
|
||||
}
|
||||
oappend("&C2=h");
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
sprintf(s,"%02X", colSec[i]);
|
||||
oappend(s);
|
||||
}
|
||||
oappend("&FX=");
|
||||
oappendi(effectCurrent);
|
||||
oappend("&SX=");
|
||||
oappendi(effectSpeed);
|
||||
oappend("&IX=");
|
||||
oappendi(effectIntensity);
|
||||
oappend("&FP=");
|
||||
oappendi(effectPalette);
|
||||
|
||||
obuf = sbuf;
|
||||
olen = 0;
|
||||
|
||||
oappend((const char*)F("<html><body><a href=\""));
|
||||
oappend(s2buf);
|
||||
oappend((const char*)F("\" target=\"_blank\">"));
|
||||
oappend(s2buf);
|
||||
oappend((const char*)F("</a></body></html>"));
|
||||
|
||||
if (request != nullptr) request->send(200, "text/html", obuf);
|
||||
}
|
||||
|
||||
//append a numeric setting to string buffer
|
||||
void sappend(char stype, const char* key, int val)
|
||||
{
|
||||
@ -144,7 +210,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
obuf = dest;
|
||||
olen = 0;
|
||||
|
||||
if (subPage <1 || subPage >6) return;
|
||||
if (subPage <1 || subPage >7) return;
|
||||
|
||||
if (subPage == 1) {
|
||||
sappends('s',"CS",clientSSID);
|
||||
@ -176,6 +242,8 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappends('s',"AP",fapass);
|
||||
|
||||
sappend('v',"AC",apChannel);
|
||||
sappend('c',"WS",noWifiSleep);
|
||||
|
||||
|
||||
if (WiFi.localIP()[0] != 0) //is connected
|
||||
{
|
||||
@ -220,7 +288,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('v',"CA",briS);
|
||||
sappend('c',"EW",useRGBW);
|
||||
sappend('i',"CO",strip.colorOrder);
|
||||
sappend('c',"AW",autoRGBtoRGBW);
|
||||
sappend('v',"AW",strip.rgbwMode);
|
||||
|
||||
sappend('c',"BO",turnOnAtBoot);
|
||||
sappend('v',"BP",bootPreset);
|
||||
@ -237,7 +305,6 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('i',"PB",strip.paletteBlend);
|
||||
sappend('c',"RV",strip.reverseMode);
|
||||
sappend('c',"SL",skipFirstLed);
|
||||
sappend('v',"DL",disableNLeds);
|
||||
}
|
||||
|
||||
if (subPage == 3)
|
||||
@ -260,8 +327,12 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('c',"SM",notifyMacro);
|
||||
sappend('c',"S2",notifyTwice);
|
||||
sappend('c',"RD",receiveDirect);
|
||||
sappend('v',"EP",e131Port);
|
||||
sappend('c',"ES",e131SkipOutOfSequence);
|
||||
sappend('c',"EM",e131Multicast);
|
||||
sappend('v',"EU",e131Universe);
|
||||
sappend('v',"DA",DMXAddress);
|
||||
sappend('v',"DM",DMXMode);
|
||||
sappend('v',"ET",realtimeTimeoutMs);
|
||||
sappend('c',"FB",arlsForceMaxBri);
|
||||
sappend('c',"RG",arlsDisableGammaCorrection);
|
||||
@ -287,9 +358,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappends('s',"MG",mqttGroupTopic);
|
||||
#endif
|
||||
|
||||
#ifdef WLED_DISABLE_HUESYNC
|
||||
sappends('m',"(\"hms\")[0]","Unsupported in build");
|
||||
#else
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
sappend('v',"H0",hueIP[0]);
|
||||
sappend('v',"H1",hueIP[1]);
|
||||
sappend('v',"H2",hueIP[2]);
|
||||
@ -300,7 +369,20 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('c',"HO",hueApplyOnOff);
|
||||
sappend('c',"HB",hueApplyBri);
|
||||
sappend('c',"HC",hueApplyColor);
|
||||
sappends('m',"(\"hms\")[0]",hueError);
|
||||
char hueErrorString[25];
|
||||
switch (hueError)
|
||||
{
|
||||
case HUE_ERROR_INACTIVE : strcpy(hueErrorString,(char*)F("Inactive")); break;
|
||||
case HUE_ERROR_ACTIVE : strcpy(hueErrorString,(char*)F("Active")); break;
|
||||
case HUE_ERROR_UNAUTHORIZED : strcpy(hueErrorString,(char*)F("Unauthorized")); break;
|
||||
case HUE_ERROR_LIGHTID : strcpy(hueErrorString,(char*)F("Invalid light ID")); break;
|
||||
case HUE_ERROR_PUSHLINK : strcpy(hueErrorString,(char*)F("Link button not pressed")); break;
|
||||
case HUE_ERROR_JSON_PARSING : strcpy(hueErrorString,(char*)F("JSON parsing error")); break;
|
||||
case HUE_ERROR_TIMEOUT : strcpy(hueErrorString,(char*)F("Timeout")); break;
|
||||
default: sprintf(hueErrorString,"Bridge Error %i",hueError);
|
||||
}
|
||||
|
||||
sappends('m',"(\"sip\")[0]",hueErrorString);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -363,12 +445,38 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('c',"NO",otaLock);
|
||||
sappend('c',"OW",wifiLock);
|
||||
sappend('c',"AO",aOtaEnabled);
|
||||
sappends('m',"(\"msg\")[0]","WLED ");
|
||||
sappends('m',"(\"sip\")[0]","WLED ");
|
||||
olen -= 2; //delete ";
|
||||
oappend(versionString);
|
||||
oappend(" (build ");
|
||||
oappendi(VERSION);
|
||||
oappend(") OK\";");
|
||||
oappend(")\";");
|
||||
}
|
||||
|
||||
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
|
||||
if (subPage == 7)
|
||||
{
|
||||
sappend('v',"CN",DMXChannels);
|
||||
sappend('v',"CG",DMXGap);
|
||||
sappend('v',"CS",DMXStart);
|
||||
sappend('v',"SL",DMXStartLED);
|
||||
|
||||
sappend('i',"CH1",DMXFixtureMap[0]);
|
||||
sappend('i',"CH2",DMXFixtureMap[1]);
|
||||
sappend('i',"CH3",DMXFixtureMap[2]);
|
||||
sappend('i',"CH4",DMXFixtureMap[3]);
|
||||
sappend('i',"CH5",DMXFixtureMap[4]);
|
||||
sappend('i',"CH6",DMXFixtureMap[5]);
|
||||
sappend('i',"CH7",DMXFixtureMap[6]);
|
||||
sappend('i',"CH8",DMXFixtureMap[7]);
|
||||
sappend('i',"CH9",DMXFixtureMap[8]);
|
||||
sappend('i',"CH10",DMXFixtureMap[9]);
|
||||
sappend('i',"CH11",DMXFixtureMap[10]);
|
||||
sappend('i',"CH12",DMXFixtureMap[11]);
|
||||
sappend('i',"CH13",DMXFixtureMap[12]);
|
||||
sappend('i',"CH14",DMXFixtureMap[13]);
|
||||
sappend('i',"CH15",DMXFixtureMap[14]);
|
||||
}
|
||||
#endif
|
||||
oappend("}</script>");
|
||||
}
|
Loading…
Reference in New Issue
Block a user