Merge branch 'Aircoookie:main' into patch-1
This commit is contained in:
commit
567daf9946
3
.gitignore
vendored
3
.gitignore
vendored
@ -17,4 +17,5 @@ node_modules
|
||||
wled-update.sh
|
||||
esp01-update.sh
|
||||
/wled00/LittleFS
|
||||
replace_fs.py
|
||||
replace_fs.py
|
||||
wled00/wled00.ino.cpp
|
||||
|
82
CHANGELOG.md
82
CHANGELOG.md
@ -1,11 +1,91 @@
|
||||
## WLED changelog
|
||||
|
||||
#### Build 2303240
|
||||
- Peek scaling of large 2D matrices
|
||||
- Added 0D (1 pixel) metadata for effects & enhance 0D (analog strip) UI handling
|
||||
- Added ability to disable ADAlight (-D WLED_DISABLE_ADALIGHT)
|
||||
- Fixed APA102 output on Ethernet enabled controllers
|
||||
- Added ArtNet virtual/network output (#3121)
|
||||
- Klipper usermod (#3106)
|
||||
- Remove DST from CST timezone
|
||||
- various fixes and enhancements
|
||||
|
||||
#### Build 2302180
|
||||
|
||||
- Removed Blynk support (servers shut down on 31st Dec 2022)
|
||||
- Added `ledgap.json` to complement ledmaps for 2D matrices
|
||||
- Added support for white addressable strips (#3073)
|
||||
- Ability to use SHT temperature usermod with PWM fan usermod
|
||||
- Added `onStateChange()` callback to usermods (#3081)
|
||||
- Refactored `bus_manager` [internal]
|
||||
- Dual 1D & 2D mode (add 1D strip after the matrix)
|
||||
- Removed 1D -> 2D mapping for individual pixel control
|
||||
- effect tweak: Fireworks 1D
|
||||
- various bugfixes
|
||||
|
||||
#### Build 2301240
|
||||
|
||||
- Version bump to v0.14.0-b2 "Hoshi"
|
||||
- PixelArt converter (convert any image to pixel art and display it on a matrix) (PR #3042)
|
||||
- various effect updates and optimisations
|
||||
- added Overlay option to some effects (allows overlapping segments)
|
||||
- added gradient text on Scrolling Text
|
||||
- added #DDMM, #MMDD & #HHMM date and time options for Scrolling Text effect (PR #2990)
|
||||
- deprecated: Dynamic Smooth, Dissolve Rnd, Solid Glitter
|
||||
- optimised & enhanced loading of default values
|
||||
- new effect: Distortion Waves (2D)
|
||||
- 2D support for Ripple effect
|
||||
- slower minimum speed for Railway effect
|
||||
- DMX effect mode & segment controls (PR #2891)
|
||||
- Optimisations for conditional compiles (further reduction of code size)
|
||||
- better UX with effect sliders (PR #3012)
|
||||
- enhanced support for ESP32 variants: C3, S2 & S3
|
||||
- usermod enhancements (PIR, Temperature, Battery (PR #2975), Analog Clock (PR #2993))
|
||||
- new usermod SHT (PR #2963)
|
||||
- 2D matrix set up with gaps or irregular panels (breaking change!) (PR #2892)
|
||||
- palette blending/transitions
|
||||
- random palette smooth changes
|
||||
- hex color notations in custom palettes
|
||||
- allow more virtual buses
|
||||
- plethora of bugfixes
|
||||
|
||||
### WLED release 0.14.0-b1
|
||||
|
||||
#### Build 2212222
|
||||
|
||||
- Version bump to v0.14.0-b1 "Hoshi"
|
||||
- Full changelog TBD
|
||||
- 2D matrix support (including mapping 1D effects to 2D and 2D peek)
|
||||
- [internal] completely rewritten Segment & WS2812FX handling code
|
||||
- [internal] ability to add custom effects via usermods
|
||||
- [internal] set of 2D drawing functions
|
||||
- transitions on every segment (including ESP8266)
|
||||
- enhanced old and new 2D effects (metadata: default values)
|
||||
- custom palettes (up to 10; upload palette0.json, palette1.json, ...)
|
||||
- custom effect sliders and options, quick filters
|
||||
- global I2C and SPI GPIO allocation (for usermods)
|
||||
- usermod settings page enhancements (dropdown & info)
|
||||
- asynchronous preset loading (and added "pd" JSON API call for direct preset apply)
|
||||
- new usermod Boblight (PR #2917)
|
||||
- new usermod PWM Outputs (PR #2912)
|
||||
- new usermod Audioreactive
|
||||
- new usermod Word Clock Matrix (PR #2743)
|
||||
- new usermod Ping Pong Clock (PR #2746)
|
||||
- new usermod ADS1115 (PR #2752)
|
||||
- new usermod Analog Clock (PR #2736)
|
||||
- various usermod enhancements and updates
|
||||
- allow disabling pull-up resistors on buttons
|
||||
- SD card support (PR #2877)
|
||||
- enhanced HTTP API to support custom effect sliders & options (X1, X2, X3, M1, M2, M3)
|
||||
- multiple UDP sync message retries (PR #2830)
|
||||
- network debug printer (PR #2870)
|
||||
- automatic UI PC mode on large displays
|
||||
- removed support for upgrading from pre-0.10 (EEPROM)
|
||||
- support for setting GPIO level when LEDs are off (RMT idle level, ESP32 only) (PR #2478)
|
||||
- Pakistan time-zone (PKT)
|
||||
- ArtPoll support
|
||||
- TM1829 LED support
|
||||
- experimental support for ESP32 S2, S3 and C3
|
||||
- general improvements and bugfixes
|
||||
|
||||
### WLED release 0.13.3
|
||||
|
||||
|
723
package-lock.json
generated
723
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wled",
|
||||
"version": "0.14.0-b1",
|
||||
"version": "0.14.0-b2",
|
||||
"description": "Tools for WLED project",
|
||||
"main": "tools/cdata.js",
|
||||
"directories": {
|
||||
@ -25,7 +25,7 @@
|
||||
"clean-css": "^4.2.3",
|
||||
"html-minifier-terser": "^5.1.1",
|
||||
"inliner": "^1.13.1",
|
||||
"nodemon": "^2.0.4",
|
||||
"nodemon": "^2.0.20",
|
||||
"zlib": "^1.0.5"
|
||||
}
|
||||
}
|
||||
|
245
platformio.ini
245
platformio.ini
@ -10,7 +10,7 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Release / CI binaries
|
||||
default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, esp32s2_saola, esp32c3, esp32s3dev_8MB
|
||||
default_envs = nodemcuv2, esp8266_2m, esp01_1m_full, esp32dev, esp32_eth, esp32s2_saola, lolin_s2_mini, esp32c3dev, esp32s3dev_8MB
|
||||
|
||||
# Build everything
|
||||
; default_envs = esp32dev, esp8285_4CH_MagicHome, codm-controller-0.6-rev2, codm-controller-0.6, esp32s2_saola, d1_mini_5CH_Shojo_PCB, d1_mini, sp501e, nodemcuv2, esp32_eth, anavi_miracle_controller, esp07, esp01_1m_full, m5atom, h803wf, d1_mini_ota, heltec_wifi_kit_8, esp8285_H801, d1_mini_debug, wemos_shield_esp32, elekstube_ips
|
||||
@ -55,18 +55,28 @@ arduino_core_2_6_3 = espressif8266@2.3.3
|
||||
arduino_core_2_7_4 = espressif8266@2.6.2
|
||||
arduino_core_3_0_0 = espressif8266@3.0.0
|
||||
arduino_core_3_2_0 = espressif8266@3.2.0
|
||||
arduino_core_4_1_0 = espressif8266@4.1.0
|
||||
|
||||
# Development platforms
|
||||
arduino_core_develop = https://github.com/platformio/platform-espressif8266#develop
|
||||
arduino_core_git = https://github.com/platformio/platform-espressif8266#feature/stage
|
||||
|
||||
# Platform to use for ESP8266
|
||||
platform_wled_default = ${common.arduino_core_3_2_0}
|
||||
platform_wled_default = ${common.arduino_core_4_1_0}
|
||||
# We use 2.7.4.7 for all, includes PWM flicker fix and Wstring optimization
|
||||
platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
|
||||
platformio/toolchain-xtensa @ ~2.40802.200502
|
||||
platformio/tool-esptool @ ~1.413.0
|
||||
platformio/tool-esptoolpy @ ~1.30000.0
|
||||
#platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
|
||||
platform_packages = platformio/framework-arduinoespressif8266
|
||||
platformio/toolchain-xtensa @ ~2.100300.220621 #2.40802.200502
|
||||
platformio/tool-esptool #@ ~1.413.0
|
||||
platformio/tool-esptoolpy #@ ~1.30000.0
|
||||
|
||||
## previous platform for 8266, in case of problems with the new one
|
||||
## you'll need makuna/NeoPixelBus@ 2.6.9 for arduino_core_3_2_0, which does not support Ucs890x
|
||||
;; platform_wled_default = ${common.arduino_core_3_2_0}
|
||||
;; platform_packages = tasmota/framework-arduinoespressif8266 @ 3.20704.7
|
||||
;; platformio/toolchain-xtensa @ ~2.40802.200502
|
||||
;; platformio/tool-esptool @ ~1.413.0
|
||||
;; platformio/tool-esptoolpy @ ~1.30000.0
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# FLAGS: DEBUG
|
||||
@ -104,6 +114,7 @@ build_flags =
|
||||
-DBEARSSL_SSL_BASIC
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
-D NDEBUG
|
||||
-Wno-attributes ;; silence warnings about unknown attribute 'maybe_unused' in NeoPixelBus
|
||||
#build_flags for the IRremoteESP8266 library (enabled decoders have to appear here)
|
||||
-D _IR_ENABLE_DEFAULT_=false
|
||||
-D DECODE_HASH=true
|
||||
@ -111,7 +122,7 @@ build_flags =
|
||||
-D DECODE_SONY=true
|
||||
-D DECODE_SAMSUNG=true
|
||||
-D DECODE_LG=true
|
||||
; -Dregister= # remove warnings in C++17 due to use of deprecated register keyword by the FastLED library
|
||||
;-Dregister= # remove warnings in C++17 due to use of deprecated register keyword by the FastLED library ;; warning: this breaks framework code on ESP32-C3 and ESP32-S2
|
||||
-DWLED_USE_MY_CONFIG
|
||||
; -D USERMOD_SENSORSTOMQTT
|
||||
#For ADS1115 sensor uncomment following
|
||||
@ -121,6 +132,7 @@ build_unflags =
|
||||
|
||||
build_flags_esp8266 = ${common.build_flags} ${esp8266.build_flags}
|
||||
build_flags_esp32 = ${common.build_flags} ${esp32.build_flags}
|
||||
build_flags_esp32_V4= ${common.build_flags} ${esp32_idf_V4.build_flags}
|
||||
|
||||
ldscript_1m128k = eagle.flash.1m128.ld
|
||||
ldscript_2m512k = eagle.flash.2m512.ld
|
||||
@ -150,8 +162,8 @@ upload_speed = 115200
|
||||
# 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
|
||||
# The following libraries have been included (and some of them changed) in the source:
|
||||
# ArduinoJson@5.13.5, E131@1.0.0(changed), Time@1.5, Timezone@1.2.1
|
||||
# ------------------------------------------------------------------------------
|
||||
lib_compat_mode = strict
|
||||
lib_deps =
|
||||
@ -182,25 +194,26 @@ build_flags =
|
||||
-DESP8266
|
||||
-DFP_IN_IROM
|
||||
;-Wno-deprecated-declarations
|
||||
;-Wno-register
|
||||
;-Wno-misleading-indentation
|
||||
; NONOSDK22x_190703 = 2.2.2-dev(38a443e)
|
||||
-Wno-register ;; leaves some warnings when compiling C files: command-line option '-Wno-register' is valid for C++/ObjC++ but not for C
|
||||
;-Dregister= # remove warnings in C++17 due to use of deprecated register keyword by the FastLED library ;; warning: this can be dangerous
|
||||
-Wno-misleading-indentation
|
||||
; NONOSDK22x_190703 = 2.2.2-dev(38a443e)
|
||||
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
|
||||
; lwIP 2 - Higher Bandwidth no Features
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
|
||||
; lwIP 1.4 - Higher Bandwidth (Aircoookie has)
|
||||
-DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
||||
; VTABLES in Flash
|
||||
; lwIP 2 - Higher Bandwidth no Features
|
||||
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
|
||||
; lwIP 1.4 - Higher Bandwidth (Aircoookie has)
|
||||
-DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
||||
; VTABLES in Flash
|
||||
-DVTABLES_IN_FLASH
|
||||
; restrict to minimal mime-types
|
||||
; restrict to minimal mime-types
|
||||
-DMIMETYPE_MINIMAL
|
||||
|
||||
lib_deps =
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
#https://github.com/lorol/LITTLEFS.git
|
||||
ESPAsyncTCP @ 1.2.2
|
||||
ESPAsyncUDP
|
||||
makuna/NeoPixelBus @ 2.6.9
|
||||
makuna/NeoPixelBus @ 2.7.3
|
||||
|
||||
[esp32]
|
||||
#platform = https://github.com/tasmota/platform-espressif32/releases/download/v2.0.2.3/platform-espressif32-2.0.2.3.zip
|
||||
@ -212,9 +225,9 @@ build_flags = -g
|
||||
-DARDUINO_ARCH_ESP32
|
||||
#-DCONFIG_LITTLEFS_FOR_IDF_3_2
|
||||
-D CONFIG_ASYNC_TCP_USE_WDT=0
|
||||
#use LITTLEFS library by lorol in ESP32 core 1.x.x instead of built-in in 2.x.x
|
||||
#use LITTLEFS library by lorol in ESP32 core 1.x.x instead of built-in in 2.x.x
|
||||
-D LOROL_LITTLEFS
|
||||
; -DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when builing with arduino-esp32 >=2.0.3
|
||||
; -DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
|
||||
|
||||
default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
|
||||
|
||||
@ -224,27 +237,54 @@ lib_deps =
|
||||
makuna/NeoPixelBus @ 2.6.9
|
||||
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0
|
||||
|
||||
|
||||
[esp32_idf_V4]
|
||||
;; experimental build environment for ESP32 using ESP-IDF 4.4.x / arduino-esp32 v2.0.5
|
||||
;; very similar to the normal ESP32 flags, but omitting Lorol LittleFS, as littlefs is included in the new framework already.
|
||||
;;
|
||||
;; please note that you can NOT update existing ESP32 installs with a "V4" build. Also updating by OTA will not work properly.
|
||||
;; You need to completely erase your device (esptool erase_flash) first, then install the "V4" build from VSCode+platformio.
|
||||
platform = espressif32@5.2.0
|
||||
platform_packages =
|
||||
build_flags = -g
|
||||
-DARDUINO_ARCH_ESP32 -DESP32
|
||||
#-DCONFIG_LITTLEFS_FOR_IDF_3_2
|
||||
-D CONFIG_ASYNC_TCP_USE_WDT=0
|
||||
-DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3
|
||||
default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
makuna/NeoPixelBus @ 2.7.3
|
||||
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0
|
||||
|
||||
[esp32s2]
|
||||
;; generic definitions for all ESP32-S2 boards
|
||||
platform = espressif32@5.2.0
|
||||
platform_packages =
|
||||
build_flags = -g
|
||||
-DARDUINO_ARCH_ESP32
|
||||
-DARDUINO_ARCH_ESP32S2
|
||||
-DCONFIG_IDF_TARGET_ESP32S2
|
||||
-DCONFIG_IDF_TARGET_ESP32S2=1
|
||||
-D CONFIG_ASYNC_TCP_USE_WDT=0
|
||||
-DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0
|
||||
-DCO
|
||||
-DARDUINO_USB_MODE=0 ;; this flag is mandatory for ESP32-S2 !
|
||||
;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry:
|
||||
;; ARDUINO_USB_CDC_ON_BOOT, ARDUINO_USB_MSC_ON_BOOT, ARDUINO_USB_DFU_ON_BOOT
|
||||
;; ARDUINO_USB_CDC_ON_BOOT
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
makuna/NeoPixelBus @ 2.6.9
|
||||
makuna/NeoPixelBus @ 2.7.3
|
||||
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0
|
||||
|
||||
[esp32c3]
|
||||
;; generic definitions for all ESP32-C3 boards
|
||||
platform = espressif32@5.2.0
|
||||
platform_packages =
|
||||
build_flags = -g
|
||||
-DARDUINO_ARCH_ESP32
|
||||
-DARDUINO_ARCH_ESP32C3
|
||||
-DCONFIG_IDF_TARGET_ESP32C3
|
||||
-DCONFIG_IDF_TARGET_ESP32C3=1
|
||||
-D CONFIG_ASYNC_TCP_USE_WDT=0
|
||||
-DCO
|
||||
-DARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C3
|
||||
@ -253,25 +293,28 @@ build_flags = -g
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
makuna/NeoPixelBus @ 2.6.9
|
||||
makuna/NeoPixelBus @ 2.7.3
|
||||
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0
|
||||
|
||||
[esp32s3]
|
||||
;; generic definitions for all ESP32-S3 boards
|
||||
platform = espressif32@5.2.0
|
||||
platform_packages =
|
||||
build_flags = -g
|
||||
-DESP32
|
||||
-DARDUINO_ARCH_ESP32
|
||||
-DARDUINO_ARCH_ESP32S3
|
||||
-DCONFIG_IDF_TARGET_ESP32S3
|
||||
-DCONFIG_IDF_TARGET_ESP32S3=1
|
||||
-D CONFIG_ASYNC_TCP_USE_WDT=0
|
||||
-DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_DFU_ON_BOOT=0
|
||||
-DCO
|
||||
;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry:
|
||||
;; ARDUINO_USB_MODE, ARDUINO_USB_CDC_ON_BOOT, ARDUINO_USB_MSC_ON_BOOT, ARDUINO_USB_DFU_ON_BOOT
|
||||
;; ARDUINO_USB_MODE, ARDUINO_USB_CDC_ON_BOOT
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
;; NeoPixelBus 2.7.1 is the first that has official support for ESP32-S3
|
||||
makuna/NeoPixelBus @ ~2.7.1
|
||||
makuna/NeoPixelBus @ ~2.7.3
|
||||
https://github.com/pbolduc/AsyncTCP.git @ 1.2.0
|
||||
|
||||
|
||||
@ -285,7 +328,7 @@ platform = ${common.platform_wled_default}
|
||||
platform_packages = ${common.platform_packages}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D WLED_DISABLE_BLYNK #-DWLED_DISABLE_2D
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 #-DWLED_DISABLE_2D
|
||||
lib_deps = ${esp8266.lib_deps}
|
||||
monitor_filters = esp8266_exception_decoder
|
||||
|
||||
@ -295,7 +338,7 @@ platform = ${common.platform_wled_default}
|
||||
platform_packages = ${common.platform_packages}
|
||||
board_build.ldscript = ${common.ldscript_2m512k}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP02 -D WLED_DISABLE_BLYNK
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP02
|
||||
lib_deps = ${esp8266.lib_deps}
|
||||
|
||||
[env:esp01_1m_full]
|
||||
@ -304,7 +347,7 @@ platform = ${common.platform_wled_default}
|
||||
platform_packages = ${common.platform_packages}
|
||||
board_build.ldscript = ${common.ldscript_1m128k}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_DISABLE_OTA -D WLED_DISABLE_BLYNK
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_DISABLE_OTA
|
||||
lib_deps = ${esp8266.lib_deps}
|
||||
|
||||
[env:esp07]
|
||||
@ -350,7 +393,7 @@ board = esp32dev
|
||||
platform = ${esp32.platform}
|
||||
platform_packages = ${esp32.platform_packages}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 -D WLED_DISABLE_BLYNK #-D WLED_DISABLE_BROWNOUT_DET
|
||||
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 #-D WLED_DISABLE_BROWNOUT_DET
|
||||
lib_deps = ${esp32.lib_deps}
|
||||
monitor_filters = esp32_exception_decoder
|
||||
board_build.partitions = ${esp32.default_partitions}
|
||||
@ -360,20 +403,35 @@ board = esp32dev
|
||||
platform = ${esp32.platform}
|
||||
platform_packages = ${esp32.platform_packages}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_qio80 -D WLED_DISABLE_BLYNK #-D WLED_DISABLE_BROWNOUT_DET
|
||||
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_qio80 #-D WLED_DISABLE_BROWNOUT_DET
|
||||
lib_deps = ${esp32.lib_deps}
|
||||
monitor_filters = esp32_exception_decoder
|
||||
board_build.partitions = ${esp32.default_partitions}
|
||||
board_build.f_flash = 80000000L
|
||||
board_build.flash_mode = qio
|
||||
|
||||
[env:esp32dev_V4_dio80]
|
||||
;; experimental ESP32 env using ESP-IDF V4.4.x
|
||||
;; Warning: this build environment is not stable!!
|
||||
;; please erase your device before installing.
|
||||
board = esp32dev
|
||||
platform = ${esp32_idf_V4.platform}
|
||||
platform_packages = ${esp32_idf_V4.platform_packages}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=ESP32_V4_qio80 #-D WLED_DISABLE_BROWNOUT_DET
|
||||
lib_deps = ${esp32_idf_V4.lib_deps}
|
||||
monitor_filters = esp32_exception_decoder
|
||||
board_build.partitions = ${esp32_idf_V4.default_partitions}
|
||||
board_build.f_flash = 80000000L
|
||||
board_build.flash_mode = dio
|
||||
|
||||
[env:esp32_eth]
|
||||
board = esp32-poe
|
||||
platform = ${esp32.platform}
|
||||
platform_packages = ${esp32.platform_packages}
|
||||
upload_speed = 921600
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 -D WLED_DISABLE_BLYNK
|
||||
build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1
|
||||
lib_deps = ${esp32.lib_deps}
|
||||
board_build.partitions = ${esp32.default_partitions}
|
||||
|
||||
@ -387,17 +445,20 @@ board_build.flash_mode = qio
|
||||
upload_speed = 460800
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} ${esp32s2.build_flags} #-D WLED_RELEASE_NAME=S2_saola
|
||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||
lib_deps = ${esp32s2.lib_deps}
|
||||
|
||||
[env:esp32c3]
|
||||
platform = espressif32@5.1.1 ;; well-tested on -C3, good compatibility with WLED
|
||||
; platform = espressif32@~5.2.0 ;; might help in case you experience bootloops due to corrupted flash filesystem
|
||||
[env:esp32c3dev]
|
||||
extends = esp32c3
|
||||
platform = ${esp32c3.platform}
|
||||
platform_packages = ${esp32c3.platform_packages}
|
||||
framework = arduino
|
||||
board = esp32-c3-devkitm-1
|
||||
board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
|
||||
build_flags = ${common.build_flags} ${esp32c3.build_flags} #-D WLED_RELEASE_NAME=ESP32-C3
|
||||
-D WLED_WATCHDOG_TIMEOUT=0
|
||||
; -DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual USB
|
||||
; -DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB
|
||||
-DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip
|
||||
upload_speed = 460800
|
||||
build_unflags = ${common.build_unflags}
|
||||
lib_deps = ${esp32c3.lib_deps}
|
||||
@ -405,14 +466,14 @@ lib_deps = ${esp32c3.lib_deps}
|
||||
[env:esp32s3dev_8MB]
|
||||
;; ESP32-S3-DevKitC-1 development board, with 8MB FLASH, no PSRAM (flash_mode: qio)
|
||||
board = esp32-s3-devkitc-1
|
||||
platform = espressif32@5.1.1
|
||||
platform_packages =
|
||||
platform = ${esp32s3.platform}
|
||||
platform_packages = ${esp32s3.platform_packages}
|
||||
upload_speed = 921600 ; or 460800
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} ${esp32s3.build_flags}
|
||||
build_flags = ${common.build_flags} ${esp32s3.build_flags}
|
||||
-D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=0 -D ARDUINO_USB_MSC_ON_BOOT=0 -D ARDUINO_DFU_ON_BOOT=0 -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
|
||||
;-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MSC_ON_BOOT=0 -D ARDUINO_DFU_ON_BOOT=0 ; -D ARDUINO_USB_MODE=0 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
|
||||
;-D ARDUINO_USB_CDC_ON_BOOT=1 ;; -D ARDUINO_USB_MODE=0 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
|
||||
;-D WLED_DEBUG
|
||||
lib_deps = ${esp32s3.lib_deps}
|
||||
board_build.partitions = tools/WLED_ESP32_8MB.csv
|
||||
@ -426,13 +487,14 @@ monitor_filters = esp32_exception_decoder
|
||||
;board = um_tinys3 ; -> needs workaround from https://github.com/Aircoookie/WLED/pull/2905#issuecomment-1328049860
|
||||
;board = esp32s3box ; -> error: 'esp32_adc2gpio' was not declared in this scope
|
||||
board = esp32-s3-devkitc-1 ; -> compiles, but does not support PSRAM
|
||||
platform = espressif32 @ ~5.2.0
|
||||
platform_packages =
|
||||
platform = ${esp32s3.platform}
|
||||
platform_packages = ${esp32s3.platform_packages}
|
||||
upload_speed = 921600
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} ${esp32s3.build_flags}
|
||||
build_flags = ${common.build_flags} ${esp32s3.build_flags}
|
||||
-D CONFIG_LITTLEFS_FOR_IDF_3_2 -D WLED_WATCHDOG_TIMEOUT=0
|
||||
-D ARDUINO_USB_MODE=1 -D ARDUINO_USB_MSC_ON_BOOT=0 ; -D ARDUINO_USB_CDC_ON_BOOT=0
|
||||
;-D ARDUINO_USB_CDC_ON_BOOT=0 ;; -D ARDUINO_USB_MODE=1 ;; for boards with serial-to-USB chip
|
||||
-D ARDUINO_USB_CDC_ON_BOOT=1 ;; -D ARDUINO_USB_MODE=0 ;; for boards with USB-OTG connector only (USBCDC or "TinyUSB")
|
||||
; -D WLED_RELEASE_NAME=ESP32-S3_PSRAM
|
||||
-D WLED_USE_PSRAM -DBOARD_HAS_PSRAM ; tells WLED that PSRAM shall be used
|
||||
lib_deps = ${esp32s3.lib_deps}
|
||||
@ -504,13 +566,14 @@ build_flags = ${common.build_flags_esp8266} -D LEDPIN=12 -D IRPIN=-1 -D RLYPIN=2
|
||||
lib_deps = ${esp8266.lib_deps}
|
||||
|
||||
[env:lolin_s2_mini]
|
||||
platform = espressif32@5.1.1
|
||||
platform = ${esp32s2.platform}
|
||||
platform_packages = ${esp32s2.platform_packages}
|
||||
board = lolin_s2_mini
|
||||
board_build.partitions = tools/WLED_ESP32_4MB_1MB_FS.csv
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_unflags = ${common.build_unflags} -DARDUINO_USB_CDC_ON_BOOT=1
|
||||
build_flags = ${common.build_flags} ${esp32s2.build_flags} #-D WLED_RELEASE_NAME=LolinS2
|
||||
-DBOARD_HAS_PSRAM
|
||||
-D ARDUINO_USB_CDC_ON_BOOT
|
||||
-DARDUINO_USB_CDC_ON_BOOT=0
|
||||
-D WLED_USE_PSRAM
|
||||
-D WLED_WATCHDOG_TIMEOUT=0
|
||||
-D CONFIG_ASYNC_TCP_USE_WDT=0
|
||||
@ -530,9 +593,28 @@ lib_deps = ${esp32s2.lib_deps}
|
||||
# custom board configurations
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
[env:esp32c3dev_2MB]
|
||||
;; for ESP32-C3 boards with 2MB flash (instead of 4MB).
|
||||
;; this board need a specific partition file. OTA not possible.
|
||||
extends = esp32c3
|
||||
platform = ${esp32c3.platform}
|
||||
platform_packages = ${esp32c3.platform_packages}
|
||||
board = esp32-c3-devkitm-1
|
||||
build_flags = ${common.build_flags} ${esp32c3.build_flags} #-D WLED_RELEASE_NAME=ESP32-C3
|
||||
-D WLED_WATCHDOG_TIMEOUT=0
|
||||
-D WLED_DISABLE_OTA
|
||||
; -DARDUINO_USB_CDC_ON_BOOT=1 ;; for virtual CDC USB
|
||||
-DARDUINO_USB_CDC_ON_BOOT=0 ;; for serial-to-USB chip
|
||||
build_unflags = ${common.build_unflags}
|
||||
upload_speed = 115200
|
||||
lib_deps = ${esp32c3.lib_deps}
|
||||
board_build.partitions = tools/WLED_ESP32_2MB_noOTA.csv
|
||||
board_build.flash_mode = dio
|
||||
|
||||
[env:wemos_shield_esp32]
|
||||
board = esp32dev
|
||||
platform = espressif32@3.2
|
||||
platform = ${esp32.platform}
|
||||
platform_packages = ${esp32.platform_packages}
|
||||
upload_speed = 460800
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp32}
|
||||
@ -557,7 +639,8 @@ board = esp32dev
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp32} -D LEDPIN=27 -D BTNPIN=39
|
||||
lib_deps = ${esp32.lib_deps}
|
||||
platform = espressif32@3.2
|
||||
platform = ${esp32.platform}
|
||||
platform_packages = ${esp32.platform_packages}
|
||||
board_build.partitions = ${esp32.default_partitions}
|
||||
|
||||
[env:sp501e]
|
||||
@ -574,20 +657,58 @@ board_build.ldscript = ${common.ldscript_2m512k}
|
||||
build_flags = ${common.build_flags_esp8266} -D LEDPIN=3 -D BTNPIN=2 -D IRPIN=5 -D WLED_MAX_BUTTONS=3
|
||||
lib_deps = ${esp8266.lib_deps}
|
||||
|
||||
[env:athom7w]
|
||||
board = esp_wroom_02
|
||||
[env:Athom_RGBCW] ;7w and 5w(GU10) bulbs
|
||||
board = esp8285
|
||||
platform = ${common.platform_wled_default}
|
||||
platform_packages = ${common.platform_packages}
|
||||
board_build.ldscript = ${common.ldscript_2m512k}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_MAX_CCT_BLEND=0 -D BTNPIN=-1 -D IRPIN=-1 -D WLED_DISABLE_INFRARED
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=-1 -D RLYPIN=-1 -D DATA_PINS=4,12,14,13,5
|
||||
-D DEFAULT_LED_TYPE=TYPE_ANALOG_5CH -D WLED_DISABLE_INFRARED -D WLED_MAX_CCT_BLEND=0
|
||||
lib_deps = ${esp8266.lib_deps}
|
||||
|
||||
[env:athom15w]
|
||||
board = esp_wroom_02
|
||||
|
||||
[env:Athom_15w_RGBCW] ;15w bulb
|
||||
board = esp8285
|
||||
platform = ${common.platform_wled_default}
|
||||
platform_packages = ${common.platform_packages}
|
||||
board_build.ldscript = ${common.ldscript_2m512k}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_USE_IC_CCT -D BTNPIN=-1 -D IRPIN=-1 -D WLED_DISABLE_INFRARED
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=-1 -D RLYPIN=-1 -D DATA_PINS=4,12,14,5,13
|
||||
-D DEFAULT_LED_TYPE=TYPE_ANALOG_5CH -D WLED_DISABLE_INFRARED -D WLED_MAX_CCT_BLEND=0 -D WLED_USE_IC_CCT
|
||||
lib_deps = ${esp8266.lib_deps}
|
||||
|
||||
|
||||
[env:Athom_3Pin_Controller] ;small controller with only data
|
||||
board = esp8285
|
||||
platform = ${common.platform_wled_default}
|
||||
platform_packages = ${common.platform_packages}
|
||||
board_build.ldscript = ${common.ldscript_2m512k}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=0 -D RLYPIN=-1 -D LEDPIN=1 -D WLED_DISABLE_INFRARED
|
||||
lib_deps = ${esp8266.lib_deps}
|
||||
|
||||
|
||||
[env:Athom_4Pin_Controller] ; With clock and data interface
|
||||
board = esp8285
|
||||
platform = ${common.platform_wled_default}
|
||||
platform_packages = ${common.platform_packages}
|
||||
board_build.ldscript = ${common.ldscript_2m512k}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=0 -D RLYPIN=12 -D LEDPIN=1 -D WLED_DISABLE_INFRARED
|
||||
lib_deps = ${esp8266.lib_deps}
|
||||
|
||||
|
||||
[env:Athom_5Pin_Controller] ;Analog light strip controller
|
||||
board = esp8285
|
||||
platform = ${common.platform_wled_default}
|
||||
platform_packages = ${common.platform_packages}
|
||||
board_build.ldscript = ${common.ldscript_2m512k}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=0 -D RLYPIN=-1 DATA_PINS=4,12,14,13 -D WLED_DISABLE_INFRARED
|
||||
lib_deps = ${esp8266.lib_deps}
|
||||
|
||||
|
||||
[env:MY9291]
|
||||
board = esp01_1m
|
||||
platform = ${common.platform_wled_default}
|
||||
@ -625,7 +746,8 @@ lib_deps = ${esp8266.lib_deps}
|
||||
# ------------------------------------------------------------------------------
|
||||
[env:elekstube_ips]
|
||||
board = esp32dev
|
||||
platform = espressif32@3.2
|
||||
platform = ${esp32.platform}
|
||||
platform_packages = ${esp32.platform_packages}
|
||||
upload_speed = 921600
|
||||
build_flags = ${common.build_flags_esp32} -D WLED_DISABLE_BROWNOUT_DET -D WLED_DISABLE_INFRARED
|
||||
-D USERMOD_RTC
|
||||
@ -633,7 +755,6 @@ build_flags = ${common.build_flags_esp32} -D WLED_DISABLE_BROWNOUT_DET -D WLED_D
|
||||
-D LEDPIN=12
|
||||
-D RLYPIN=27
|
||||
-D BTNPIN=34
|
||||
-D WLED_DISABLE_BLYNK
|
||||
-D DEFAULT_LED_COUNT=6
|
||||
# Display config
|
||||
-D ST7789_DRIVER
|
||||
|
@ -26,7 +26,6 @@ build_flags = ${common.build_flags_esp8266}
|
||||
; disable specific features
|
||||
; -D WLED_DISABLE_OTA
|
||||
; -D WLED_DISABLE_ALEXA
|
||||
; -D WLED_DISABLE_BLYNK
|
||||
; -D WLED_DISABLE_HUESYNC
|
||||
; -D WLED_DISABLE_INFRARED
|
||||
; -D WLED_DISABLE_WEBSOCKETS
|
||||
|
@ -34,8 +34,7 @@ A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control
|
||||
## 💡 Supported light control interfaces
|
||||
- WLED app for [Android](https://play.google.com/store/apps/details?id=com.aircoookie.WLED) and [iOS](https://apps.apple.com/us/app/wled/id1475695033)
|
||||
- JSON and HTTP request APIs
|
||||
- MQTT
|
||||
- Blynk IoT
|
||||
- MQTT
|
||||
- E1.31, Art-Net, DDP and TPM2.net
|
||||
- [diyHue](https://github.com/diyhue/diyHue) (Wled is supported by diyHue, including Hue Sync Entertainment under udp. Thanks to [Gregory Mallios](https://github.com/gmallios))
|
||||
- [Hyperion](https://github.com/hyperion-project/hyperion.ng)
|
||||
|
5
tools/WLED_ESP32_2MB_noOTA.csv
Normal file
5
tools/WLED_ESP32_2MB_noOTA.csv
Normal file
@ -0,0 +1,5 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 20K,
|
||||
otadata, data, ota, 0xe000, 8K,
|
||||
app0, app, ota_0, 0x10000, 1536K,
|
||||
spiffs, data, spiffs, 0x190000, 384K,
|
|
@ -22,8 +22,12 @@
|
||||
|
||||
//class name. Use something descriptive and leave the ": public Usermod" part :)
|
||||
class MyExampleUsermod : public Usermod {
|
||||
|
||||
private:
|
||||
//Private class members. You can declare variables and functions only accessible to your usermod here
|
||||
|
||||
// Private class members. You can declare variables and functions only accessible to your usermod here
|
||||
bool enabled = false;
|
||||
bool initDone = false;
|
||||
unsigned long lastTime = 0;
|
||||
|
||||
// set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer)
|
||||
@ -37,15 +41,56 @@ class MyExampleUsermod : public Usermod {
|
||||
long testLong;
|
||||
int8_t testPins[2];
|
||||
|
||||
// string that are used multiple time (this will save some flash memory)
|
||||
static const char _name[];
|
||||
static const char _enabled[];
|
||||
|
||||
|
||||
// any private methods should go here (non-inline methosd should be defined out of class)
|
||||
void publishMqtt(const char* state, bool retain = false); // example for publishing MQTT message
|
||||
|
||||
|
||||
public:
|
||||
//Functions called by WLED
|
||||
|
||||
// non WLED related methods, may be used for data exchange between usermods (non-inline methods should be defined out of class)
|
||||
|
||||
/**
|
||||
* Enable/Disable the usermod
|
||||
*/
|
||||
inline void enable(bool enable) { enabled = enable; }
|
||||
|
||||
/**
|
||||
* Get usermod enabled/disabled state
|
||||
*/
|
||||
inline bool isEnabled() { return enabled; }
|
||||
|
||||
// in such case add the following to another usermod:
|
||||
// in private vars:
|
||||
// #ifdef USERMOD_EXAMPLE
|
||||
// MyExampleUsermod* UM;
|
||||
// #endif
|
||||
// in setup()
|
||||
// #ifdef USERMOD_EXAMPLE
|
||||
// UM = (MyExampleUsermod*) usermods.lookup(USERMOD_ID_EXAMPLE);
|
||||
// #endif
|
||||
// somewhere in loop() or other member method
|
||||
// #ifdef USERMOD_EXAMPLE
|
||||
// if (UM != nullptr) isExampleEnabled = UM->isEnabled();
|
||||
// if (!isExampleEnabled) UM->enable(true);
|
||||
// #endif
|
||||
|
||||
|
||||
// methods called by WLED (can be inlined as they are called only once but if you call them explicitly define them out of class)
|
||||
|
||||
/*
|
||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||
* readFromConfig() is called prior to setup()
|
||||
* You can use it to initialize variables, sensors or similar.
|
||||
*/
|
||||
void setup() {
|
||||
// do your set-up here
|
||||
//Serial.println("Hello from my usermod!");
|
||||
initDone = true;
|
||||
}
|
||||
|
||||
|
||||
@ -69,6 +114,11 @@ class MyExampleUsermod : public Usermod {
|
||||
* Instead, use a timer check as shown here.
|
||||
*/
|
||||
void loop() {
|
||||
// if usermod is disabled or called during strip updating just exit
|
||||
// NOTE: on very long strips strip.isUpdating() may always return true so update accordingly
|
||||
if (!enabled || strip.isUpdating()) return;
|
||||
|
||||
// do your magic here
|
||||
if (millis() - lastTime > 1000) {
|
||||
//Serial.println("I'm alive!");
|
||||
lastTime = millis();
|
||||
@ -81,19 +131,25 @@ class MyExampleUsermod : public Usermod {
|
||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||
* Below it is shown how this could be used for e.g. a light sensor
|
||||
*/
|
||||
/*
|
||||
void addToJsonInfo(JsonObject& root)
|
||||
{
|
||||
int reading = 20;
|
||||
//this code adds "u":{"Light":[20," lux"]} to the info object
|
||||
// if "u" object does not exist yet wee need to create it
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray lightArr = user.createNestedArray("Light"); //name
|
||||
lightArr.add(reading); //value
|
||||
lightArr.add(" lux"); //unit
|
||||
//this code adds "u":{"ExampleUsermod":[20," lux"]} to the info object
|
||||
//int reading = 20;
|
||||
//JsonArray lightArr = user.createNestedArray(FPSTR(_name))); //name
|
||||
//lightArr.add(reading); //value
|
||||
//lightArr.add(F(" lux")); //unit
|
||||
|
||||
// if you are implementing a sensor usermod, you may publish sensor data
|
||||
//JsonObject sensor = root[F("sensor")];
|
||||
//if (sensor.isNull()) sensor = root.createNestedObject(F("sensor"));
|
||||
//temp = sensor.createNestedArray(F("light"));
|
||||
//temp.add(reading);
|
||||
//temp.add(F("lux"));
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
@ -102,7 +158,12 @@ class MyExampleUsermod : public Usermod {
|
||||
*/
|
||||
void addToJsonState(JsonObject& root)
|
||||
{
|
||||
//root["user0"] = userVar0;
|
||||
if (!initDone || !enabled) return; // prevent crash on boot applyPreset()
|
||||
|
||||
JsonObject usermod = root[FPSTR(_name)];
|
||||
if (usermod.isNull()) usermod = root.createNestedObject(FPSTR(_name));
|
||||
|
||||
//usermod["user0"] = userVar0;
|
||||
}
|
||||
|
||||
|
||||
@ -112,7 +173,14 @@ class MyExampleUsermod : public Usermod {
|
||||
*/
|
||||
void readFromJsonState(JsonObject& root)
|
||||
{
|
||||
userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
|
||||
if (!initDone) return; // prevent crash on boot applyPreset()
|
||||
|
||||
JsonObject usermod = root[FPSTR(_name)];
|
||||
if (!usermod.isNull()) {
|
||||
// expect JSON usermod data in usermod name object: {"ExampleUsermod:{"user0":10}"}
|
||||
userVar0 = usermod["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
|
||||
}
|
||||
// you can as well check WLED state JSON keys
|
||||
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
|
||||
}
|
||||
|
||||
@ -154,8 +222,10 @@ class MyExampleUsermod : public Usermod {
|
||||
*/
|
||||
void addToConfig(JsonObject& root)
|
||||
{
|
||||
JsonObject top = root.createNestedObject("exampleUsermod");
|
||||
top["great"] = userVar0; //save these vars persistently whenever settings are saved
|
||||
JsonObject top = root.createNestedObject(FPSTR(_name));
|
||||
top[FPSTR(_enabled)] = enabled;
|
||||
//save these vars persistently whenever settings are saved
|
||||
top["great"] = userVar0;
|
||||
top["testBool"] = testBool;
|
||||
top["testInt"] = testInt;
|
||||
top["testLong"] = testLong;
|
||||
@ -188,7 +258,7 @@ class MyExampleUsermod : public Usermod {
|
||||
// default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor
|
||||
// setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed)
|
||||
|
||||
JsonObject top = root["exampleUsermod"];
|
||||
JsonObject top = root[FPSTR(_name)];
|
||||
|
||||
bool configComplete = !top.isNull();
|
||||
|
||||
@ -201,6 +271,8 @@ class MyExampleUsermod : public Usermod {
|
||||
// A 3-argument getJsonValue() assigns the 3rd argument as a default value if the Json value is missing
|
||||
configComplete &= getJsonValue(top["testInt"], testInt, 42);
|
||||
configComplete &= getJsonValue(top["testLong"], testLong, -42424242);
|
||||
|
||||
// "pin" fields have special handling in settings page (or some_pin as well)
|
||||
configComplete &= getJsonValue(top["pin"][0], testPins[0], -1);
|
||||
configComplete &= getJsonValue(top["pin"][1], testPins[1], -1);
|
||||
|
||||
@ -208,6 +280,21 @@ class MyExampleUsermod : public Usermod {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* appendConfigData() is called when user enters usermod settings page
|
||||
* it may add additional metadata for certain entry fields (adding drop down is possible)
|
||||
* be careful not to add too much as oappend() buffer is limited to 3k
|
||||
*/
|
||||
void appendConfigData()
|
||||
{
|
||||
oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":great")); oappend(SET_F("',1,'<i>(this is a great config value)</i>');"));
|
||||
oappend(SET_F("addInfo('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F(":testString")); oappend(SET_F("',1,'enter any string you want');"));
|
||||
oappend(SET_F("dd=addDropdown('")); oappend(String(FPSTR(_name)).c_str()); oappend(SET_F("','testInt');"));
|
||||
oappend(SET_F("addOption(dd,'Nothing',0);"));
|
||||
oappend(SET_F("addOption(dd,'Everything',42);"));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* handleOverlayDraw() is called just before every show() (LED strip update frame) after effects have set the colors.
|
||||
* Use this to blank out some LEDs or set them to a different color regardless of the set effect mode.
|
||||
@ -218,7 +305,72 @@ class MyExampleUsermod : public Usermod {
|
||||
//strip.setPixelColor(0, RGBW32(0,0,0,0)) // set the first pixel to black
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* handleButton() can be used to override default button behaviour. Returning true
|
||||
* will prevent button working in a default way.
|
||||
* Replicating button.cpp
|
||||
*/
|
||||
bool handleButton(uint8_t b) {
|
||||
yield();
|
||||
// ignore certain button types as they may have other consequences
|
||||
if (!enabled
|
||||
|| buttonType[b] == BTN_TYPE_NONE
|
||||
|| buttonType[b] == BTN_TYPE_RESERVED
|
||||
|| buttonType[b] == BTN_TYPE_PIR_SENSOR
|
||||
|| buttonType[b] == BTN_TYPE_ANALOG
|
||||
|| buttonType[b] == BTN_TYPE_ANALOG_INVERTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool handled = false;
|
||||
// do your button handling here
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
||||
#ifndef WLED_DISABLE_MQTT
|
||||
/**
|
||||
* handling of MQTT message
|
||||
* topic only contains stripped topic (part after /wled/MAC)
|
||||
*/
|
||||
bool onMqttMessage(char* topic, char* payload) {
|
||||
// check if we received a command
|
||||
//if (strlen(topic) == 8 && strncmp_P(topic, PSTR("/command"), 8) == 0) {
|
||||
// String action = payload;
|
||||
// if (action == "on") {
|
||||
// enabled = true;
|
||||
// return true;
|
||||
// } else if (action == "off") {
|
||||
// enabled = false;
|
||||
// return true;
|
||||
// } else if (action == "toggle") {
|
||||
// enabled = !enabled;
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* onMqttConnect() is called when MQTT connection is established
|
||||
*/
|
||||
void onMqttConnect(bool sessionPresent) {
|
||||
// do any MQTT related initialisation here
|
||||
//publishMqtt("I am alive!");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* onStateChanged() is used to detect WLED state change
|
||||
* @mode parameter is CALL_MODE_... parameter used for notifications
|
||||
*/
|
||||
void onStateChange(uint8_t mode) {
|
||||
// do something if WLED state changed (color, brightness, effect, preset, etc)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
||||
@ -230,4 +382,25 @@ class MyExampleUsermod : public Usermod {
|
||||
|
||||
//More methods can be added in the future, this example will then be extended.
|
||||
//Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// add more strings here to reduce flash memory usage
|
||||
const char MyExampleUsermod::_name[] PROGMEM = "ExampleUsermod";
|
||||
const char MyExampleUsermod::_enabled[] PROGMEM = "enabled";
|
||||
|
||||
|
||||
// implementation of non-inline member methods
|
||||
|
||||
void MyExampleUsermod::publishMqtt(const char* state, bool retain)
|
||||
{
|
||||
#ifndef WLED_DISABLE_MQTT
|
||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (WLED_MQTT_CONNECTED) {
|
||||
char subuf[64];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat_P(subuf, PSTR("/example"));
|
||||
mqtt->publish(subuf, 0, retain, state);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -114,6 +114,7 @@ private:
|
||||
if (m_offOnly && bri && (switchOn || (!PIRtriggered && !switchOn))) return; //if lights on and off only, do nothing
|
||||
if (PIRtriggered && switchOn) return; //if already on and triggered before, do nothing
|
||||
PIRtriggered = switchOn;
|
||||
DEBUG_PRINT(F("PIR: strip=")); DEBUG_PRINTLN(switchOn?"on":"off");
|
||||
if (switchOn) {
|
||||
if (m_onPreset) {
|
||||
if (currentPlaylist>0 && !offMode) {
|
||||
@ -370,6 +371,20 @@ public:
|
||||
sensor[F("motion")] = sensorPinState || offTimerStart>0 ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* onStateChanged() is used to detect WLED state change
|
||||
*/
|
||||
void onStateChange(uint8_t mode) {
|
||||
if (!initDone) return;
|
||||
DEBUG_PRINT(F("PIR: offTimerStart=")); DEBUG_PRINTLN(offTimerStart);
|
||||
if (PIRtriggered && offTimerStart) {
|
||||
// checking PIRtriggered and offTimerStart will prevent cancellation upon On trigger
|
||||
DEBUG_PRINTLN(F("PIR: Canceled."));
|
||||
offTimerStart = 0;
|
||||
PIRtriggered = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
||||
* Values in the state object may be modified by connected clients
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef USERMOD_DALLASTEMPERATURE
|
||||
#error The "PWM fan" usermod requires "Dallas Temeprature" usermod to function properly.
|
||||
#if !defined(USERMOD_DALLASTEMPERATURE) && !defined(USERMOD_SHT)
|
||||
#error The "PWM fan" usermod requires "Dallas Temeprature" or "SHT" usermod to function properly.
|
||||
#endif
|
||||
|
||||
#include "wled.h"
|
||||
@ -42,6 +42,8 @@ class PWMFanUsermod : public Usermod {
|
||||
|
||||
#ifdef USERMOD_DALLASTEMPERATURE
|
||||
UsermodTemperature* tempUM;
|
||||
#elif defined(USERMOD_SHT)
|
||||
ShtUsermod* tempUM;
|
||||
#endif
|
||||
|
||||
// configurable parameters
|
||||
@ -145,7 +147,7 @@ class PWMFanUsermod : public Usermod {
|
||||
}
|
||||
|
||||
float getActualTemperature(void) {
|
||||
#ifdef USERMOD_DALLASTEMPERATURE
|
||||
#if defined(USERMOD_DALLASTEMPERATURE) || defined(USERMOD_SHT)
|
||||
if (tempUM != nullptr)
|
||||
return tempUM->getTemperatureC();
|
||||
#endif
|
||||
@ -189,6 +191,8 @@ class PWMFanUsermod : public Usermod {
|
||||
#ifdef USERMOD_DALLASTEMPERATURE
|
||||
// This Usermod requires Temperature usermod
|
||||
tempUM = (UsermodTemperature*) usermods.lookup(USERMOD_ID_TEMPERATURE);
|
||||
#elif defined(USERMOD_SHT)
|
||||
tempUM = (ShtUsermod*) usermods.lookup(USERMOD_ID_SHT);
|
||||
#endif
|
||||
initTacho();
|
||||
initPWMfan();
|
||||
|
@ -1,28 +0,0 @@
|
||||
# Blynk controllable relay
|
||||
Enables controlling a relay state via user variables. Allows the user variables to be set via Blynk.
|
||||
|
||||
Optionally, the servo can have a reset timer to return to its default state after a user definable interval. The interval is set via 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 Blynk updates
|
||||
#define BLYNK_RELAY_UPDATE_INTERVAL 5000
|
||||
```
|
@ -1,96 +0,0 @@
|
||||
/*
|
||||
* 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();
|
||||
}
|
@ -209,7 +209,7 @@ class MPU6050Driver : public Usermod {
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull()) user = root.createNestedObject("u");
|
||||
|
||||
JsonArray imu_meas = user.createNestedObject("IMU");
|
||||
JsonObject imu_meas = user.createNestedObject("IMU");
|
||||
JsonArray quat_json = imu_meas.createNestedArray("Quat");
|
||||
quat_json.add(qat.w);
|
||||
quat_json.add(qat.x);
|
||||
@ -287,4 +287,4 @@ class MPU6050Driver : public Usermod {
|
||||
return USERMOD_ID_IMU;
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
@ -62,9 +62,9 @@ class ShtUsermod : public Usermod
|
||||
bool isEnabled() { return enabled; }
|
||||
|
||||
float getTemperature();
|
||||
float getTemperatureC() { return shtCurrentTempC; }
|
||||
float getTemperatureF() { return (shtCurrentTempC * 1.8f) + 32.0f; }
|
||||
float getHumidity() { return shtCurrentHumidity; }
|
||||
float getTemperatureC() { return roundf(shtCurrentTempC * 10.0f) / 10.0f; }
|
||||
float getTemperatureF() { return (getTemperatureC() * 1.8f) + 32.0f; }
|
||||
float getHumidity() { return roundf(shtCurrentHumidity * 10.0f) / 10.0f; }
|
||||
const char* getUnitString();
|
||||
|
||||
uint16_t getId() { return USERMOD_ID_SHT; }
|
||||
|
@ -106,6 +106,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
static FourLineDisplayUsermod *instance;
|
||||
bool initDone = false;
|
||||
volatile bool drawing = false;
|
||||
volatile bool lockRedraw = false;
|
||||
|
||||
// HW interface & configuration
|
||||
U8X8 *u8x8 = nullptr; // pointer to U8X8 display object
|
||||
@ -198,25 +199,33 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
}
|
||||
void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false) {
|
||||
if (type == NONE || !enabled) return;
|
||||
drawing = true;
|
||||
u8x8->setFont(u8x8_font_chroma48medium8_r);
|
||||
if (!ignoreLH && lineHeight==2) u8x8->draw1x2String(col, row, string);
|
||||
else u8x8->drawString(col, row, string);
|
||||
drawing = false;
|
||||
}
|
||||
void draw2x2String(uint8_t col, uint8_t row, const char *string) {
|
||||
if (type == NONE || !enabled) return;
|
||||
drawing = true;
|
||||
u8x8->setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8->draw2x2String(col, row, string);
|
||||
drawing = false;
|
||||
}
|
||||
void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false) {
|
||||
if (type == NONE || !enabled) return;
|
||||
drawing = true;
|
||||
u8x8->setFont(font);
|
||||
if (!ignoreLH && lineHeight==2) u8x8->draw1x2Glyph(col, row, glyph);
|
||||
else u8x8->drawGlyph(col, row, glyph);
|
||||
drawing = false;
|
||||
}
|
||||
void draw2x2Glyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font) {
|
||||
if (type == NONE || !enabled) return;
|
||||
drawing = true;
|
||||
u8x8->setFont(font);
|
||||
u8x8->draw2x2Glyph(col, row, glyph);
|
||||
drawing = false;
|
||||
}
|
||||
uint8_t getCols() {
|
||||
if (type==NONE || !enabled) return 0;
|
||||
@ -224,7 +233,9 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
}
|
||||
void clear() {
|
||||
if (type == NONE || !enabled) return;
|
||||
drawing = true;
|
||||
u8x8->clear();
|
||||
drawing = false;
|
||||
}
|
||||
void setPowerSave(uint8_t save) {
|
||||
if (type == NONE || !enabled) return;
|
||||
@ -238,6 +249,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
}
|
||||
|
||||
void draw2x2GlyphIcons() {
|
||||
drawing = true;
|
||||
if (lineHeight == 2) {
|
||||
drawGlyph( 1, 0, 1, u8x8_4LineDisplay_WLED_icons_2x2, true); //brightness icon
|
||||
drawGlyph( 5, 0, 2, u8x8_4LineDisplay_WLED_icons_2x2, true); //speed icon
|
||||
@ -251,6 +263,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
drawGlyph(15, 2, 4, u8x8_4LineDisplay_WLED_icons_1x1); //palette icon
|
||||
drawGlyph(15, 3, 5, u8x8_4LineDisplay_WLED_icons_1x1); //effect icon
|
||||
}
|
||||
drawing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -262,8 +275,8 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
if (type == NONE || !enabled || !displayTurnedOff) return;
|
||||
|
||||
unsigned long now = millis();
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
drawing = true;
|
||||
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||
if (drawing) return;
|
||||
|
||||
char lineBuffer[LINE_BUFFER_SIZE];
|
||||
static byte lastSecond;
|
||||
@ -299,7 +312,23 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
sprintf_P(lineBuffer, PSTR("%02d"), secondCurrent);
|
||||
drawString(12, lineHeight*2+1, lineBuffer, true); // even with double sized rows print seconds in 1 line
|
||||
}
|
||||
drawing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable sleep (turn the display off) or clock mode.
|
||||
*/
|
||||
void sleepOrClock(bool enabled) {
|
||||
if (enabled) {
|
||||
displayTurnedOff = true;
|
||||
if (clockMode && ntpEnabled) {
|
||||
knownMinute = knownHour = 99;
|
||||
showTime();
|
||||
} else
|
||||
setPowerSave(1);
|
||||
} else {
|
||||
displayTurnedOff = false;
|
||||
setPowerSave(0);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
@ -483,7 +512,8 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
}
|
||||
}
|
||||
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
while (drawing && millis()-now < 25) delay(1); // wait if someone else is drawing
|
||||
if (drawing || lockRedraw) return;
|
||||
|
||||
if (apActive && WLED_WIFI_CONFIGURED && now<15000) {
|
||||
knownSsid = apSSID;
|
||||
@ -546,7 +576,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
}
|
||||
|
||||
lastRedraw = now;
|
||||
|
||||
|
||||
// Turn the display back on
|
||||
wakeDisplay();
|
||||
|
||||
@ -580,44 +610,49 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
void updateBrightness() {
|
||||
knownBrightness = bri;
|
||||
if (overlayUntil == 0) {
|
||||
lockRedraw = true;
|
||||
brightness100 = ((uint16_t)bri*100)/255;
|
||||
char lineBuffer[4];
|
||||
sprintf_P(lineBuffer, PSTR("%-3d"), brightness100);
|
||||
drawString(1, lineHeight, lineBuffer);
|
||||
//lastRedraw = millis();
|
||||
lockRedraw = false;
|
||||
}
|
||||
}
|
||||
|
||||
void updateSpeed() {
|
||||
knownEffectSpeed = effectSpeed;
|
||||
if (overlayUntil == 0) {
|
||||
lockRedraw = true;
|
||||
fxspeed100 = ((uint16_t)effectSpeed*100)/255;
|
||||
char lineBuffer[4];
|
||||
sprintf_P(lineBuffer, PSTR("%-3d"), fxspeed100);
|
||||
drawString(5, lineHeight, lineBuffer);
|
||||
//lastRedraw = millis();
|
||||
lockRedraw = false;
|
||||
}
|
||||
}
|
||||
|
||||
void updateIntensity() {
|
||||
knownEffectIntensity = effectIntensity;
|
||||
if (overlayUntil == 0) {
|
||||
lockRedraw = true;
|
||||
fxintensity100 = ((uint16_t)effectIntensity*100)/255;
|
||||
char lineBuffer[4];
|
||||
sprintf_P(lineBuffer, PSTR("%-3d"), fxintensity100);
|
||||
drawString(9, lineHeight, lineBuffer);
|
||||
//lastRedraw = millis();
|
||||
lockRedraw = false;
|
||||
}
|
||||
}
|
||||
|
||||
void drawStatusIcons() {
|
||||
uint8_t col = 15;
|
||||
uint8_t row = 0;
|
||||
lockRedraw = true;
|
||||
drawGlyph(col, row, (wificonnected ? 20 : 0), u8x8_4LineDisplay_WLED_icons_1x1, true); // wifi icon
|
||||
if (lineHeight==2) { col--; } else { row++; }
|
||||
drawGlyph(col, row, (bri > 0 ? 9 : 0), u8x8_4LineDisplay_WLED_icons_1x1, true); // power icon
|
||||
if (lineHeight==2) { col--; } else { col = row = 0; }
|
||||
drawGlyph(col, row, (nightlightActive ? 6 : 0), u8x8_4LineDisplay_WLED_icons_1x1, true); // moon icon for nighlight mode
|
||||
lockRedraw = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -632,7 +667,9 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
|
||||
//Draw the arrow for the current setting beiong changed
|
||||
void drawArrow() {
|
||||
lockRedraw = true;
|
||||
if (markColNum != 255 && markLineNum !=255) drawGlyph(markColNum, markLineNum*lineHeight, 21, u8x8_4LineDisplay_WLED_icons_1x1);
|
||||
lockRedraw = false;
|
||||
}
|
||||
|
||||
//Display the current effect or palette (desiredEntry)
|
||||
@ -640,6 +677,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
void showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) {
|
||||
char lineBuffer[MAX_JSON_CHARS];
|
||||
if (overlayUntil == 0) {
|
||||
lockRedraw = true;
|
||||
// Find the mode name in JSON
|
||||
uint8_t printedChars = extractModeName(inputEffPal, qstring, lineBuffer, MAX_JSON_CHARS-1);
|
||||
if (lineBuffer[0]=='*' && lineBuffer[1]==' ') {
|
||||
@ -692,6 +730,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
smallBuffer3[smallChars3] = 0;
|
||||
drawString(1, row*lineHeight, smallBuffer3, true);
|
||||
}
|
||||
lockRedraw = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -706,12 +745,12 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
if (displayTurnedOff) {
|
||||
unsigned long now = millis();
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
drawing = true;
|
||||
if (drawing) return false;
|
||||
lockRedraw = true;
|
||||
clear();
|
||||
// Turn the display back on
|
||||
sleepOrClock(false);
|
||||
//lastRedraw = millis();
|
||||
drawing = false;
|
||||
lockRedraw = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -724,8 +763,9 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
*/
|
||||
void overlay(const char* line1, long showHowLong, byte glyphType) {
|
||||
unsigned long now = millis();
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
drawing = true;
|
||||
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||
if (drawing) return;
|
||||
lockRedraw = true;
|
||||
// Turn the display back on
|
||||
if (!wakeDisplay()) clear();
|
||||
// Print the overlay
|
||||
@ -739,7 +779,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
drawString(0, (glyphType<255?3:0)*lineHeight, buf.c_str());
|
||||
}
|
||||
overlayUntil = millis() + showHowLong;
|
||||
drawing = false;
|
||||
lockRedraw = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -748,8 +788,9 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
*/
|
||||
void overlayLogo(long showHowLong) {
|
||||
unsigned long now = millis();
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
drawing = true;
|
||||
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||
if (drawing) return;
|
||||
lockRedraw = true;
|
||||
// Turn the display back on
|
||||
if (!wakeDisplay()) clear();
|
||||
// Print the overlay
|
||||
@ -799,7 +840,7 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
}
|
||||
}
|
||||
overlayUntil = millis() + showHowLong;
|
||||
drawing = false;
|
||||
lockRedraw = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -809,8 +850,9 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
*/
|
||||
void overlay(const char* line1, const char* line2, long showHowLong) {
|
||||
unsigned long now = millis();
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
drawing = true;
|
||||
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||
if (drawing) return;
|
||||
lockRedraw = true;
|
||||
// Turn the display back on
|
||||
if (!wakeDisplay()) clear();
|
||||
// Print the overlay
|
||||
@ -825,13 +867,14 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
drawString(0, 2*lineHeight, buf.c_str());
|
||||
}
|
||||
overlayUntil = millis() + showHowLong;
|
||||
drawing = false;
|
||||
lockRedraw = false;
|
||||
}
|
||||
|
||||
void networkOverlay(const char* line1, long showHowLong) {
|
||||
unsigned long now = millis();
|
||||
while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing
|
||||
drawing = true;
|
||||
while (drawing && millis()-now < 125) delay(1); // wait if someone else is drawing
|
||||
if (drawing) return;
|
||||
lockRedraw = true;
|
||||
|
||||
String line;
|
||||
// Turn the display back on
|
||||
@ -863,27 +906,10 @@ class FourLineDisplayUsermod : public Usermod {
|
||||
center(line, getCols());
|
||||
drawString(0, lineHeight*3, line.c_str());
|
||||
overlayUntil = millis() + showHowLong;
|
||||
drawing = false;
|
||||
lockRedraw = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enable sleep (turn the display off) or clock mode.
|
||||
*/
|
||||
void sleepOrClock(bool enabled) {
|
||||
if (enabled) {
|
||||
displayTurnedOff = true;
|
||||
if (clockMode && ntpEnabled) {
|
||||
knownMinute = knownHour = 99;
|
||||
showTime();
|
||||
} else
|
||||
setPowerSave(1);
|
||||
} else {
|
||||
displayTurnedOff = false;
|
||||
setPowerSave(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handleButton() can be used to override default button behaviour. Returning true
|
||||
* will prevent button working in a default way.
|
||||
|
40
usermods/usermod_v2_klipper_percentage/readme.md
Normal file
40
usermods/usermod_v2_klipper_percentage/readme.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Klipper Percentage Usermod
|
||||
This usermod polls the Klipper API every 10s for the progressvalue.
|
||||
The leds are then filled with a solid color according to that progress percentage.
|
||||
the solid color is the secondary color of the segment.
|
||||
|
||||
A corresponding curl command would be:
|
||||
```
|
||||
curl --location --request GET 'http://[]/printer/objects/query?virtual_sdcard=progress'
|
||||
```
|
||||
## Usage
|
||||
Compile the source with the buildflag `-D USERMOD_KLIPPER_PERCENTAGE` added.
|
||||
|
||||
You can also use the WLBD bot in the Discord by simply extending an exsisting build enviroment:
|
||||
```
|
||||
[env:esp32klipper]
|
||||
extends = env:esp32dev
|
||||
build_flags = ${common.build_flags_esp32} -D USERMOD_KLIPPER_PERCENTAGE
|
||||
```
|
||||
|
||||
## Settings
|
||||
|
||||
### Enabled:
|
||||
Checkbox to enable or disable the overlay
|
||||
|
||||
### Klipper IP:
|
||||
IP adress of your Klipper instance you want to poll. ESP has to be restarted after change
|
||||
|
||||
### Direction :
|
||||
0 = normal
|
||||
|
||||
1 = reversed
|
||||
|
||||
2 = center
|
||||
|
||||
-----
|
||||
Author:
|
||||
|
||||
Sören Willrodt
|
||||
|
||||
Discord: Sören#5281
|
@ -0,0 +1,222 @@
|
||||
#pragma once
|
||||
|
||||
#include "wled.h"
|
||||
|
||||
class klipper_percentage : public Usermod
|
||||
{
|
||||
private:
|
||||
unsigned long lastTime = 0;
|
||||
String ip = "192.168.25.207";
|
||||
WiFiClient wifiClient;
|
||||
char errorMessage[100] = "";
|
||||
int printPercent = 0;
|
||||
int direction = 0; // 0 for along the strip, 1 for reversed direction
|
||||
|
||||
static const char _name[];
|
||||
static const char _enabled[];
|
||||
bool enabled = false;
|
||||
|
||||
void httpGet(WiFiClient &client, char *errorMessage)
|
||||
{
|
||||
// https://arduinojson.org/v6/example/http-client/
|
||||
// is this the most compact way to do http get and put it in arduinojson object???
|
||||
// would like async response ... ???
|
||||
client.setTimeout(10000);
|
||||
if (!client.connect(ip.c_str(), 80))
|
||||
{
|
||||
strcat(errorMessage, PSTR("Connection failed"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send HTTP request
|
||||
client.println(F("GET /printer/objects/query?virtual_sdcard=progress HTTP/1.0"));
|
||||
client.println("Host: " + ip);
|
||||
client.println(F("Connection: close"));
|
||||
if (client.println() == 0)
|
||||
{
|
||||
strcat(errorMessage, PSTR("Failed to send request"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check HTTP status
|
||||
char status[32] = {0};
|
||||
client.readBytesUntil('\r', status, sizeof(status));
|
||||
if (strcmp(status, "HTTP/1.1 200 OK") != 0)
|
||||
{
|
||||
strcat(errorMessage, PSTR("Unexpected response: "));
|
||||
strcat(errorMessage, status);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip HTTP headers
|
||||
char endOfHeaders[] = "\r\n\r\n";
|
||||
if (!client.find(endOfHeaders))
|
||||
{
|
||||
strcat(errorMessage, PSTR("Invalid response"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void setup()
|
||||
{
|
||||
}
|
||||
|
||||
void connected()
|
||||
{
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
if (WLED_CONNECTED)
|
||||
{
|
||||
if (millis() - lastTime > 10000)
|
||||
{
|
||||
httpGet(wifiClient, errorMessage);
|
||||
if (strcmp(errorMessage, "") == 0)
|
||||
{
|
||||
PSRAMDynamicJsonDocument klipperDoc(4096); // in practive about 2673
|
||||
DeserializationError error = deserializeJson(klipperDoc, wifiClient);
|
||||
if (error)
|
||||
{
|
||||
strcat(errorMessage, PSTR("deserializeJson() failed: "));
|
||||
strcat(errorMessage, error.c_str());
|
||||
}
|
||||
printPercent = (int)(klipperDoc["result"]["status"]["virtual_sdcard"]["progress"].as<float>() * 100);
|
||||
|
||||
DEBUG_PRINT("Percent: ");
|
||||
DEBUG_PRINTLN((int)(klipperDoc["result"]["status"]["virtual_sdcard"]["progress"].as<float>() * 100));
|
||||
DEBUG_PRINT("LEDs: ");
|
||||
DEBUG_PRINTLN(direction == 2 ? (strip.getLengthTotal() / 2) * printPercent / 100 : strip.getLengthTotal() * printPercent / 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_PRINTLN(errorMessage);
|
||||
DEBUG_PRINTLN(ip);
|
||||
}
|
||||
lastTime = millis();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addToConfig(JsonObject &root)
|
||||
{
|
||||
JsonObject top = root.createNestedObject("Klipper Printing Percentage");
|
||||
top["Enabled"] = enabled;
|
||||
top["Klipper IP"] = ip;
|
||||
top["Direction"] = direction;
|
||||
}
|
||||
|
||||
bool readFromConfig(JsonObject &root)
|
||||
{
|
||||
// default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor
|
||||
// setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed)
|
||||
|
||||
JsonObject top = root["Klipper Printing Percentage"];
|
||||
|
||||
bool configComplete = !top.isNull();
|
||||
configComplete &= getJsonValue(top["Klipper IP"], ip);
|
||||
configComplete &= getJsonValue(top["Enabled"], enabled);
|
||||
configComplete &= getJsonValue(top["Direction"], direction);
|
||||
return configComplete;
|
||||
}
|
||||
|
||||
/*
|
||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||
* Below it is shown how this could be used for e.g. a light sensor
|
||||
*/
|
||||
void addToJsonInfo(JsonObject &root)
|
||||
{
|
||||
JsonObject user = root["u"];
|
||||
if (user.isNull())
|
||||
user = root.createNestedObject("u");
|
||||
|
||||
JsonArray infoArr = user.createNestedArray(FPSTR(_name));
|
||||
String uiDomString = F("<button class=\"btn btn-xs\" onclick=\"requestJson({");
|
||||
uiDomString += FPSTR(_name);
|
||||
uiDomString += F(":{");
|
||||
uiDomString += FPSTR(_enabled);
|
||||
uiDomString += enabled ? F(":false}});\">") : F(":true}});\">");
|
||||
uiDomString += F("<i class=\"icons");
|
||||
uiDomString += enabled ? F(" on") : F(" off");
|
||||
uiDomString += F("\"></i>");
|
||||
uiDomString += F("</button>");
|
||||
infoArr.add(uiDomString);
|
||||
}
|
||||
|
||||
void addToJsonState(JsonObject &root)
|
||||
{
|
||||
JsonObject usermod = root[FPSTR(_name)];
|
||||
if (usermod.isNull())
|
||||
{
|
||||
usermod = root.createNestedObject(FPSTR(_name));
|
||||
}
|
||||
usermod["on"] = enabled;
|
||||
}
|
||||
void readFromJsonState(JsonObject &root)
|
||||
{
|
||||
JsonObject usermod = root[FPSTR(_name)];
|
||||
if (!usermod.isNull())
|
||||
{
|
||||
if (usermod[FPSTR(_enabled)].is<bool>())
|
||||
{
|
||||
enabled = usermod[FPSTR(_enabled)].as<bool>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* handleOverlayDraw() is called just before every show() (LED strip update frame) after effects have set the colors.
|
||||
* Use this to blank out some LEDs or set them to a different color regardless of the set effect mode.
|
||||
* Commonly used for custom clocks (Cronixie, 7 segment)
|
||||
*/
|
||||
void handleOverlayDraw()
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
if (direction == 0) // normal
|
||||
{
|
||||
for (int i = 0; i < strip.getLengthTotal() * printPercent / 100; i++)
|
||||
{
|
||||
strip.setPixelColor(i, strip.getSegment(0).colors[1]);
|
||||
}
|
||||
}
|
||||
else if (direction == 1) // reversed
|
||||
{
|
||||
for (int i = 0; i < strip.getLengthTotal() * printPercent / 100; i++)
|
||||
{
|
||||
strip.setPixelColor(strip.getLengthTotal() - i, strip.getSegment(0).colors[1]);
|
||||
}
|
||||
}
|
||||
else if (direction == 2) // center
|
||||
{
|
||||
for (int i = 0; i < (strip.getLengthTotal() / 2) * printPercent / 100; i++)
|
||||
{
|
||||
strip.setPixelColor((strip.getLengthTotal() / 2) + i, strip.getSegment(0).colors[1]);
|
||||
strip.setPixelColor((strip.getLengthTotal() / 2) - i, strip.getSegment(0).colors[1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
direction = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
||||
*/
|
||||
uint16_t getId()
|
||||
{
|
||||
return USERMOD_ID_KLIPPER;
|
||||
}
|
||||
};
|
||||
const char klipper_percentage::_name[] PROGMEM = "Klipper_Percentage";
|
||||
const char klipper_percentage::_enabled[] PROGMEM = "enabled";
|
@ -25,6 +25,7 @@ class WordClockUsermod : public Usermod
|
||||
bool displayItIs = false;
|
||||
int ledOffset = 100;
|
||||
bool meander = false;
|
||||
bool nord = false;
|
||||
|
||||
// defines for mask sizes
|
||||
#define maskSizeLeds 114
|
||||
@ -37,7 +38,7 @@ class WordClockUsermod : public Usermod
|
||||
|
||||
// "minute" masks
|
||||
// Normal wiring
|
||||
const int maskMinutes[12][maskSizeMinutes] =
|
||||
const int maskMinutes[14][maskSizeMinutes] =
|
||||
{
|
||||
{107, 108, 109, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // :00
|
||||
{ 7, 8, 9, 10, 40, 41, 42, 43, -1, -1, -1, -1}, // :05 fünf nach
|
||||
@ -50,11 +51,13 @@ class WordClockUsermod : public Usermod
|
||||
{ 15, 16, 17, 18, 19, 20, 21, 33, 34, 35, -1, -1}, // :40 zwanzig vor
|
||||
{ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1}, // :45 dreiviertel
|
||||
{ 11, 12, 13, 14, 33, 34, 35, -1, -1, -1, -1, -1}, // :50 zehn vor
|
||||
{ 7, 8, 9, 10, 33, 34, 35, -1, -1, -1, -1, -1} // :55 fünf vor
|
||||
{ 7, 8, 9, 10, 33, 34, 35, -1, -1, -1, -1, -1}, // :55 fünf vor
|
||||
{ 26, 27, 28, 29, 30, 31, 32, 40, 41, 42, 43, -1}, // :15 alternative viertel nach
|
||||
{ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1} // :45 alternative viertel vor
|
||||
};
|
||||
|
||||
// Meander wiring
|
||||
const int maskMinutesMea[12][maskSizeMinutesMea] =
|
||||
const int maskMinutesMea[14][maskSizeMinutesMea] =
|
||||
{
|
||||
{ 99, 100, 101, -1, -1, -1, -1, -1, -1, -1, -1, -1}, // :00
|
||||
{ 7, 8, 9, 10, 33, 34, 35, 36, -1, -1, -1, -1}, // :05 fünf nach
|
||||
@ -67,9 +70,12 @@ class WordClockUsermod : public Usermod
|
||||
{ 11, 12, 13, 14, 15, 16, 17, 41, 42, 43, -1, -1}, // :40 zwanzig vor
|
||||
{ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1}, // :45 dreiviertel
|
||||
{ 18, 19, 20, 21, 41, 42, 43, -1, -1, -1, -1, -1}, // :50 zehn vor
|
||||
{ 7, 8, 9, 10, 41, 42, 43, -1, -1, -1, -1, -1} // :55 fünf vor
|
||||
{ 7, 8, 9, 10, 41, 42, 43, -1, -1, -1, -1, -1}, // :55 fünf vor
|
||||
{ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1}, // :15 alternative viertel nach
|
||||
{ 26, 27, 28, 29, 30, 31, 32, 41, 42, 43, -1, -1} // :45 alternative viertel vor
|
||||
};
|
||||
|
||||
|
||||
// hour masks
|
||||
// Normal wiring
|
||||
const int maskHours[13][maskSizeHours] =
|
||||
@ -242,9 +248,15 @@ class WordClockUsermod : public Usermod
|
||||
setHours(hours, false);
|
||||
break;
|
||||
case 3:
|
||||
// viertel
|
||||
setMinutes(3);
|
||||
setHours(hours + 1, false);
|
||||
if (nord) {
|
||||
// viertel nach
|
||||
setMinutes(12);
|
||||
setHours(hours, false);
|
||||
} else {
|
||||
// viertel
|
||||
setMinutes(3);
|
||||
setHours(hours + 1, false);
|
||||
};
|
||||
break;
|
||||
case 4:
|
||||
// 20 nach
|
||||
@ -272,8 +284,13 @@ class WordClockUsermod : public Usermod
|
||||
setHours(hours + 1, false);
|
||||
break;
|
||||
case 9:
|
||||
// viertel vor
|
||||
setMinutes(9);
|
||||
// viertel vor bzw dreiviertel
|
||||
if (nord) {
|
||||
setMinutes(9);
|
||||
}
|
||||
else {
|
||||
setMinutes(12);
|
||||
}
|
||||
setHours(hours + 1, false);
|
||||
break;
|
||||
case 10:
|
||||
@ -410,6 +427,7 @@ class WordClockUsermod : public Usermod
|
||||
top["displayItIs"] = displayItIs;
|
||||
top["ledOffset"] = ledOffset;
|
||||
top["Meander wiring?"] = meander;
|
||||
top["Norddeutsch"] = nord;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -440,6 +458,7 @@ class WordClockUsermod : public Usermod
|
||||
configComplete &= getJsonValue(top["displayItIs"], displayItIs);
|
||||
configComplete &= getJsonValue(top["ledOffset"], ledOffset);
|
||||
configComplete &= getJsonValue(top["Meander wiring?"], meander);
|
||||
configComplete &= getJsonValue(top["Norddeutsch"], nord);
|
||||
|
||||
return configComplete;
|
||||
}
|
||||
|
157
wled00/FX.cpp
157
wled00/FX.cpp
@ -29,7 +29,11 @@
|
||||
#include "fcn_declare.h"
|
||||
|
||||
#define IBN 5100
|
||||
#define PALETTE_SOLID_WRAP (strip.paletteBlend == 1 || strip.paletteBlend == 3)
|
||||
|
||||
// paletteBlend: 0 - wrap when moving, 1 - always wrap, 2 - never wrap, 3 - none (undefined)
|
||||
#define PALETTE_SOLID_WRAP (strip.paletteBlend == 1 || strip.paletteBlend == 3)
|
||||
#define PALETTE_MOVING_WRAP !(strip.paletteBlend == 2 || (strip.paletteBlend == 0 && SEGMENT.speed == 0))
|
||||
|
||||
#define indexToVStrip(index, stripNr) ((index) | (int((stripNr)+1)<<16))
|
||||
|
||||
// effect utility functions
|
||||
@ -120,7 +124,7 @@ uint16_t blink(uint32_t color1, uint32_t color2, bool strobe, bool do_palette) {
|
||||
uint16_t mode_blink(void) {
|
||||
return blink(SEGCOLOR(0), SEGCOLOR(1), false, true);
|
||||
}
|
||||
static const char _data_FX_MODE_BLINK[] PROGMEM = "Blink@!,Duty cycle;!,!;!";
|
||||
static const char _data_FX_MODE_BLINK[] PROGMEM = "Blink@!,Duty cycle;!,!;!;01";
|
||||
|
||||
|
||||
/*
|
||||
@ -129,7 +133,7 @@ static const char _data_FX_MODE_BLINK[] PROGMEM = "Blink@!,Duty cycle;!,!;!";
|
||||
uint16_t mode_blink_rainbow(void) {
|
||||
return blink(SEGMENT.color_wheel(SEGENV.call & 0xFF), SEGCOLOR(1), false, false);
|
||||
}
|
||||
static const char _data_FX_MODE_BLINK_RAINBOW[] PROGMEM = "Blink Rainbow@Frequency,Blink duration;!,!;!";
|
||||
static const char _data_FX_MODE_BLINK_RAINBOW[] PROGMEM = "Blink Rainbow@Frequency,Blink duration;!,!;!;01";
|
||||
|
||||
|
||||
/*
|
||||
@ -138,7 +142,7 @@ static const char _data_FX_MODE_BLINK_RAINBOW[] PROGMEM = "Blink Rainbow@Frequen
|
||||
uint16_t mode_strobe(void) {
|
||||
return blink(SEGCOLOR(0), SEGCOLOR(1), true, true);
|
||||
}
|
||||
static const char _data_FX_MODE_STROBE[] PROGMEM = "Strobe@!;!,!;!";
|
||||
static const char _data_FX_MODE_STROBE[] PROGMEM = "Strobe@!;!,!;!;01";
|
||||
|
||||
|
||||
/*
|
||||
@ -147,7 +151,7 @@ static const char _data_FX_MODE_STROBE[] PROGMEM = "Strobe@!;!,!;!";
|
||||
uint16_t mode_strobe_rainbow(void) {
|
||||
return blink(SEGMENT.color_wheel(SEGENV.call & 0xFF), SEGCOLOR(1), true, false);
|
||||
}
|
||||
static const char _data_FX_MODE_STROBE_RAINBOW[] PROGMEM = "Strobe Rainbow@!;,!;!";
|
||||
static const char _data_FX_MODE_STROBE_RAINBOW[] PROGMEM = "Strobe Rainbow@!;,!;!;01";
|
||||
|
||||
|
||||
/*
|
||||
@ -346,7 +350,7 @@ uint16_t mode_breath(void) {
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_BREATH[] PROGMEM = "Breathe@!;!,!;!";
|
||||
static const char _data_FX_MODE_BREATH[] PROGMEM = "Breathe@!;!,!;!;01";
|
||||
|
||||
|
||||
/*
|
||||
@ -362,7 +366,7 @@ uint16_t mode_fade(void) {
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_FADE[] PROGMEM = "Fade@!;!,!;!";
|
||||
static const char _data_FX_MODE_FADE[] PROGMEM = "Fade@!;!,!;!;01";
|
||||
|
||||
|
||||
/*
|
||||
@ -750,7 +754,7 @@ uint16_t mode_multi_strobe(void) {
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_MULTI_STROBE[] PROGMEM = "Strobe Mega@!,!;!,!;!";
|
||||
static const char _data_FX_MODE_MULTI_STROBE[] PROGMEM = "Strobe Mega@!,!;!,!;!;01";
|
||||
|
||||
|
||||
/*
|
||||
@ -972,6 +976,7 @@ static const char _data_FX_MODE_COLORFUL[] PROGMEM = "Colorful@!,Saturation;1,2,
|
||||
* Emulates a traffic light.
|
||||
*/
|
||||
uint16_t mode_traffic_light(void) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
for (int i=0; i < SEGLEN; i++)
|
||||
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 1));
|
||||
uint32_t mdelay = 500;
|
||||
@ -1004,6 +1009,7 @@ static const char _data_FX_MODE_TRAFFIC_LIGHT[] PROGMEM = "Traffic Light@!,US st
|
||||
*/
|
||||
#define FLASH_COUNT 4
|
||||
uint16_t mode_chase_flash(void) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
uint8_t flash_step = SEGENV.call % ((FLASH_COUNT * 2) + 1);
|
||||
|
||||
for (int i = 0; i < SEGLEN; i++) {
|
||||
@ -1033,6 +1039,7 @@ static const char _data_FX_MODE_CHASE_FLASH[] PROGMEM = "Chase Flash@!;Bg,Fx;!";
|
||||
* Prim flashes running, followed by random color.
|
||||
*/
|
||||
uint16_t mode_chase_flash_random(void) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
uint8_t flash_step = SEGENV.call % ((FLASH_COUNT * 2) + 1);
|
||||
|
||||
for (int i = 0; i < SEGENV.aux1; i++) {
|
||||
@ -1166,6 +1173,7 @@ static const char _data_FX_MODE_DUAL_LARSON_SCANNER[] PROGMEM = "Scanner Dual@!,
|
||||
* Firing comets from one end. "Lighthouse"
|
||||
*/
|
||||
uint16_t mode_comet(void) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
uint16_t counter = strip.now * ((SEGMENT.speed >>2) +1);
|
||||
uint16_t index = (counter * SEGLEN) >> 16;
|
||||
if (SEGENV.call == 0) SEGENV.aux0 = index;
|
||||
@ -1193,7 +1201,8 @@ static const char _data_FX_MODE_COMET[] PROGMEM = "Lighthouse@!,Fade rate;!,!;!"
|
||||
* Fireworks function.
|
||||
*/
|
||||
uint16_t mode_fireworks() {
|
||||
const uint16_t width = strip.isMatrix ? SEGMENT.virtualWidth() : SEGMENT.virtualLength();
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
const uint16_t width = SEGMENT.is2D() ? SEGMENT.virtualWidth() : SEGMENT.virtualLength();
|
||||
const uint16_t height = SEGMENT.virtualHeight();
|
||||
|
||||
if (SEGENV.call == 0) {
|
||||
@ -1207,18 +1216,18 @@ uint16_t mode_fireworks() {
|
||||
bool valid1 = (SEGENV.aux0 < width*height);
|
||||
bool valid2 = (SEGENV.aux1 < width*height);
|
||||
uint32_t sv1 = 0, sv2 = 0;
|
||||
if (valid1) sv1 = strip.isMatrix ? SEGMENT.getPixelColorXY(SEGENV.aux0%width, SEGENV.aux0/width) : SEGMENT.getPixelColor(SEGENV.aux0); // get spark color
|
||||
if (valid2) sv2 = strip.isMatrix ? SEGMENT.getPixelColorXY(SEGENV.aux1%width, SEGENV.aux1/width) : SEGMENT.getPixelColor(SEGENV.aux1);
|
||||
if (valid1) sv1 = SEGMENT.is2D() ? SEGMENT.getPixelColorXY(SEGENV.aux0%width, SEGENV.aux0/width) : SEGMENT.getPixelColor(SEGENV.aux0); // get spark color
|
||||
if (valid2) sv2 = SEGMENT.is2D() ? SEGMENT.getPixelColorXY(SEGENV.aux1%width, SEGENV.aux1/width) : SEGMENT.getPixelColor(SEGENV.aux1);
|
||||
if (!SEGENV.step) SEGMENT.blur(16);
|
||||
if (valid1) { if (strip.isMatrix) SEGMENT.setPixelColorXY(SEGENV.aux0%width, SEGENV.aux0/width, sv1); else SEGMENT.setPixelColor(SEGENV.aux0, sv1); } // restore spark color after blur
|
||||
if (valid2) { if (strip.isMatrix) SEGMENT.setPixelColorXY(SEGENV.aux1%width, SEGENV.aux1/width, sv2); else SEGMENT.setPixelColor(SEGENV.aux1, sv2); } // restore old spark color after blur
|
||||
if (valid1) { if (SEGMENT.is2D()) SEGMENT.setPixelColorXY(SEGENV.aux0%width, SEGENV.aux0/width, sv1); else SEGMENT.setPixelColor(SEGENV.aux0, sv1); } // restore spark color after blur
|
||||
if (valid2) { if (SEGMENT.is2D()) SEGMENT.setPixelColorXY(SEGENV.aux1%width, SEGENV.aux1/width, sv2); else SEGMENT.setPixelColor(SEGENV.aux1, sv2); } // restore old spark color after blur
|
||||
|
||||
for (int i=0; i<MAX(1, width/20); i++) {
|
||||
if (random8(129 - (SEGMENT.intensity >> 1)) == 0) {
|
||||
uint16_t index = random16(width*height);
|
||||
uint16_t j = index % width, k = index / width;
|
||||
uint32_t col = SEGMENT.color_from_palette(random8(), false, false, 0);
|
||||
if (strip.isMatrix) SEGMENT.setPixelColorXY(j, k, col);
|
||||
if (SEGMENT.is2D()) SEGMENT.setPixelColorXY(j, k, col);
|
||||
else SEGMENT.setPixelColor(index, col);
|
||||
SEGENV.aux1 = SEGENV.aux0; // old spark
|
||||
SEGENV.aux0 = index; // remember where spark occured
|
||||
@ -1230,8 +1239,8 @@ static const char _data_FX_MODE_FIREWORKS[] PROGMEM = "Fireworks@,Frequency;!,!;
|
||||
|
||||
|
||||
//Twinkling LEDs running. Inspired by https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/Rain.h
|
||||
uint16_t mode_rain()
|
||||
{
|
||||
uint16_t mode_rain() {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
const uint16_t width = SEGMENT.virtualWidth();
|
||||
const uint16_t height = SEGMENT.virtualHeight();
|
||||
SEGENV.step += FRAMETIME;
|
||||
@ -1290,7 +1299,7 @@ uint16_t mode_fire_flicker(void) {
|
||||
SEGENV.step = it;
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_FIRE_FLICKER[] PROGMEM = "Fire Flicker@!,!;!;!";
|
||||
static const char _data_FX_MODE_FIRE_FLICKER[] PROGMEM = "Fire Flicker@!,!;!;!;01";
|
||||
|
||||
|
||||
/*
|
||||
@ -1341,8 +1350,8 @@ static const char _data_FX_MODE_LOADING[] PROGMEM = "Loading@!,Fade;!,!;!;;ix=16
|
||||
|
||||
|
||||
//American Police Light with all LEDs Red and Blue
|
||||
uint16_t police_base(uint32_t color1, uint32_t color2)
|
||||
{
|
||||
uint16_t police_base(uint32_t color1, uint32_t color2) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
uint16_t delay = 1 + (FRAMETIME<<3) / SEGLEN; // longer segments should change faster
|
||||
uint32_t it = strip.now / map(SEGMENT.speed, 0, 255, delay<<4, delay);
|
||||
uint16_t offset = it % SEGLEN;
|
||||
@ -1790,9 +1799,9 @@ uint16_t mode_oscillate(void) {
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i < SEGLEN; i++) {
|
||||
for (int i = 0; i < SEGLEN; i++) {
|
||||
uint32_t color = BLACK;
|
||||
for (int j=0; j < numOscillators; j++) {
|
||||
for (int j = 0; j < numOscillators; j++) {
|
||||
if(i >= oscillators[j].pos - oscillators[j].size && i <= oscillators[j].pos + oscillators[j].size) {
|
||||
color = (color == BLACK) ? SEGCOLOR(j) : color_blend(color, SEGCOLOR(j), 128);
|
||||
}
|
||||
@ -1808,6 +1817,7 @@ static const char _data_FX_MODE_OSCILLATE[] PROGMEM = "Oscillate";
|
||||
|
||||
//TODO
|
||||
uint16_t mode_lightning(void) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
uint16_t ledstart = random16(SEGLEN); // Determine starting location of flash
|
||||
uint16_t ledlen = 1 + random16(SEGLEN -ledstart); // Determine length of flash (not to go beyond NUM_LEDS-1)
|
||||
uint8_t bri = 255/random8(1, 3);
|
||||
@ -1868,7 +1878,6 @@ uint16_t mode_pride_2015(void) {
|
||||
sPseudotime += duration * msmultiplier;
|
||||
sHue16 += duration * beatsin88( 400, 5,9);
|
||||
uint16_t brightnesstheta16 = sPseudotime;
|
||||
CRGB fastled_col;
|
||||
|
||||
for (int i = 0 ; i < SEGLEN; i++) {
|
||||
hue16 += hueinc16;
|
||||
@ -1894,6 +1903,7 @@ static const char _data_FX_MODE_PRIDE_2015[] PROGMEM = "Pride 2015@!;;";
|
||||
|
||||
//eight colored dots, weaving in and out of sync with each other
|
||||
uint16_t mode_juggle(void) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
if (SEGENV.call == 0) {
|
||||
SEGMENT.setUpLeds(); //lossless getPixelColor()
|
||||
SEGMENT.fill(BLACK);
|
||||
@ -1923,11 +1933,10 @@ uint16_t mode_palette() {
|
||||
counter = counter >> 8;
|
||||
}
|
||||
|
||||
bool noWrap = (strip.paletteBlend == 2 || (strip.paletteBlend == 0 && SEGMENT.speed == 0));
|
||||
for (int i = 0; i < SEGLEN; i++)
|
||||
{
|
||||
uint8_t colorIndex = (i * 255 / SEGLEN) - counter;
|
||||
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(colorIndex, false, noWrap, 255));
|
||||
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(colorIndex, false, PALETTE_MOVING_WRAP, 255));
|
||||
}
|
||||
|
||||
return FRAMETIME;
|
||||
@ -1964,41 +1973,42 @@ static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Cycle speed;;!;;c3=
|
||||
// feel of your fire: COOLING (used in step 1 above) (Speed = COOLING), and SPARKING (used
|
||||
// in step 3 above) (Effect Intensity = Sparking).
|
||||
uint16_t mode_fire_2012() {
|
||||
uint16_t strips = SEGMENT.nrOfVStrips();
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
const uint16_t strips = SEGMENT.nrOfVStrips();
|
||||
if (!SEGENV.allocateData(strips * SEGLEN)) return mode_static(); //allocation failed
|
||||
byte* heat = SEGENV.data;
|
||||
|
||||
uint32_t it = strip.now >> 5; //div 32
|
||||
const uint32_t it = strip.now >> 6; //div 64
|
||||
|
||||
struct virtualStrip {
|
||||
static void runStrip(uint16_t stripNr, byte* heat, uint32_t it) {
|
||||
|
||||
const uint8_t ignition = max(3,SEGLEN/10); // ignition area: 10% of segment length or minimum 3 pixels
|
||||
|
||||
// Step 1. Cool down every cell a little
|
||||
for (int i = 0; i < SEGLEN; i++) {
|
||||
uint8_t cool = (it != SEGENV.step) ? random8((((20 + SEGMENT.speed/3) * 16) / SEGLEN)+2) : random(8);
|
||||
uint8_t minTemp = 0;
|
||||
if (i<ignition) {
|
||||
minTemp = (ignition-i)/4 + 16; // and should not become black
|
||||
}
|
||||
uint8_t temp = qsub8(heat[i], cool);
|
||||
heat[i] = temp<minTemp ? minTemp : temp;
|
||||
}
|
||||
|
||||
if (it != SEGENV.step)
|
||||
{
|
||||
uint8_t ignition = max(3,SEGLEN/10); // ignition area: 10% of segment length or minimum 3 pixels
|
||||
|
||||
// Step 1. Cool down every cell a little
|
||||
for (int i = 0; i < SEGLEN; i++) {
|
||||
uint8_t cool = random8((((20 + SEGMENT.speed/3) * 16) / SEGLEN)+2);
|
||||
uint8_t minTemp = 0;
|
||||
if (i<ignition) {
|
||||
//cool /= (ignition-i)/3 + 1; // ignition area cools slower
|
||||
minTemp = (ignition-i)/4 + 16; // and should not become black
|
||||
}
|
||||
uint8_t temp = qsub8(heat[i], cool);
|
||||
heat[i] = temp<minTemp ? minTemp : temp;
|
||||
}
|
||||
|
||||
// Step 2. Heat from each cell drifts 'up' and diffuses a little
|
||||
for (int k = SEGLEN -1; k > 1; k--) {
|
||||
heat[k] = (heat[k - 1] + (heat[k - 2]<<1) ) / 3; // heat[k-2] multiplied by 2
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3. Randomly ignite new 'sparks' of heat near the bottom
|
||||
if (random8() <= SEGMENT.intensity) {
|
||||
uint8_t y = random8(ignition);
|
||||
heat[y] = qadd8(heat[y], random8(160,255));
|
||||
}
|
||||
// Step 3. Randomly ignite new 'sparks' of heat near the bottom
|
||||
if (random8() <= SEGMENT.intensity) {
|
||||
uint8_t y = random8(ignition);
|
||||
uint8_t boost = (32+SEGMENT.custom3*2) * (2*ignition-y) / (2*ignition);
|
||||
heat[y] = qadd8(heat[y], random8(64+boost,128+boost));
|
||||
}
|
||||
|
||||
// Step 4. Map from heat cells to LED colors
|
||||
@ -2011,12 +2021,14 @@ uint16_t mode_fire_2012() {
|
||||
for (int stripNr=0; stripNr<strips; stripNr++)
|
||||
virtualStrip::runStrip(stripNr, &heat[stripNr * SEGLEN], it);
|
||||
|
||||
if (SEGMENT.is2D()) SEGMENT.blur(32);
|
||||
|
||||
if (it != SEGENV.step)
|
||||
SEGENV.step = it;
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate;;!;1;sx=120,ix=64,m12=1"; // bars
|
||||
static const char _data_FX_MODE_FIRE_2012[] PROGMEM = "Fire 2012@Cooling,Spark rate,,,Boost;;!;1;sx=120,ix=64,m12=1"; // bars
|
||||
|
||||
|
||||
// ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb
|
||||
@ -2262,6 +2274,7 @@ static const char _data_FX_MODE_LAKE[] PROGMEM = "Lake@!;Fx;!";
|
||||
// send a meteor from begining to to the end of the strip with a trail that randomly decays.
|
||||
// adapted from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain
|
||||
uint16_t mode_meteor() {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
if (!SEGENV.allocateData(SEGLEN)) return mode_static(); //allocation failed
|
||||
|
||||
byte* trail = SEGENV.data;
|
||||
@ -2299,6 +2312,7 @@ static const char _data_FX_MODE_METEOR[] PROGMEM = "Meteor@!,Trail length;!;!";
|
||||
// send a meteor from begining to to the end of the strip with a trail that randomly decays.
|
||||
// adapted from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain
|
||||
uint16_t mode_meteor_smooth() {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
if (!SEGENV.allocateData(SEGLEN)) return mode_static(); //allocation failed
|
||||
|
||||
byte* trail = SEGENV.data;
|
||||
@ -2336,6 +2350,7 @@ static const char _data_FX_MODE_METEOR_SMOOTH[] PROGMEM = "Meteor Smooth@!,Trail
|
||||
|
||||
//Railway Crossing / Christmas Fairy lights
|
||||
uint16_t mode_railway() {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
uint16_t dur = (256 - SEGMENT.speed) * 40;
|
||||
uint16_t rampdur = (dur * SEGMENT.intensity) >> 8;
|
||||
if (SEGENV.step > dur)
|
||||
@ -2436,6 +2451,7 @@ uint16_t ripple_base()
|
||||
|
||||
|
||||
uint16_t mode_ripple(void) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
if (!SEGMENT.check2) SEGMENT.fill(SEGCOLOR(1));
|
||||
return ripple_base();
|
||||
}
|
||||
@ -2443,6 +2459,7 @@ static const char _data_FX_MODE_RIPPLE[] PROGMEM = "Ripple@!,Wave #,,,,,Overlay;
|
||||
|
||||
|
||||
uint16_t mode_ripple_rainbow(void) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
if (SEGENV.call ==0) {
|
||||
SEGENV.aux0 = random8();
|
||||
SEGENV.aux1 = random8();
|
||||
@ -2607,6 +2624,7 @@ static const char _data_FX_MODE_TWINKLECAT[] PROGMEM = "Twinklecat@!,Twinkle rat
|
||||
//inspired by https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectBlinkingHalloweenEyes
|
||||
uint16_t mode_halloween_eyes()
|
||||
{
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
const uint16_t maxWidth = strip.isMatrix ? SEGMENT.virtualWidth() : SEGLEN;
|
||||
const uint16_t HALLOWEEN_EYE_SPACE = MAX(2, strip.isMatrix ? SEGMENT.virtualWidth()>>4: SEGLEN>>5);
|
||||
const uint16_t HALLOWEEN_EYE_WIDTH = HALLOWEEN_EYE_SPACE/2;
|
||||
@ -2716,6 +2734,7 @@ static const char _data_FX_MODE_TRI_STATIC_PATTERN[] PROGMEM = "Solid Pattern Tr
|
||||
|
||||
uint16_t spots_base(uint16_t threshold)
|
||||
{
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
if (!SEGMENT.check2) SEGMENT.fill(SEGCOLOR(1));
|
||||
|
||||
uint16_t maxZones = SEGLEN >> 2;
|
||||
@ -2771,6 +2790,7 @@ typedef struct Ball {
|
||||
* Bouncing Balls Effect
|
||||
*/
|
||||
uint16_t mode_bouncing_balls(void) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
//allocate segment data
|
||||
const uint16_t strips = SEGMENT.nrOfVStrips(); // adapt for 2D
|
||||
const size_t maxNumBalls = 16;
|
||||
@ -2843,6 +2863,7 @@ static const char _data_FX_MODE_BOUNCINGBALLS[] PROGMEM = "Bouncing Balls@Gravit
|
||||
* Sinelon stolen from FASTLED examples
|
||||
*/
|
||||
uint16_t sinelon_base(bool dual, bool rainbow=false) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
SEGMENT.fade_out(SEGMENT.intensity);
|
||||
uint16_t pos = beatsin16(SEGMENT.speed/10,0,SEGLEN-1);
|
||||
if (SEGENV.call == 0) SEGENV.aux0 = pos;
|
||||
@ -2940,6 +2961,7 @@ typedef struct Spark {
|
||||
* modified from https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/Popcorn.h
|
||||
*/
|
||||
uint16_t mode_popcorn(void) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
//allocate segment data
|
||||
uint16_t strips = SEGMENT.nrOfVStrips();
|
||||
uint16_t dataSize = sizeof(spark) * maxNumPopcorn;
|
||||
@ -3082,7 +3104,7 @@ uint16_t mode_candle()
|
||||
{
|
||||
return candle(false);
|
||||
}
|
||||
static const char _data_FX_MODE_CANDLE[] PROGMEM = "Candle@!,!;!,!;!;1;sx=96,ix=224,pal=0";
|
||||
static const char _data_FX_MODE_CANDLE[] PROGMEM = "Candle@!,!;!,!;!;01;sx=96,ix=224,pal=0";
|
||||
|
||||
|
||||
uint16_t mode_candle_multi()
|
||||
@ -3113,6 +3135,7 @@ typedef struct particle {
|
||||
} star;
|
||||
|
||||
uint16_t mode_starburst(void) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
uint16_t maxData = FAIR_DATA_PER_SEG; //ESP8266: 256 ESP32: 640
|
||||
uint8_t segs = strip.getActiveSegmentsNum();
|
||||
if (segs <= (strip.getMaxSegments() /2)) maxData *= 2; //ESP8266: 512 if <= 8 segs ESP32: 1280 if <= 16 segs
|
||||
@ -3232,6 +3255,7 @@ static const char _data_FX_MODE_STARBURST[] PROGMEM = "Fireworks Starburst@Chanc
|
||||
*/
|
||||
uint16_t mode_exploding_fireworks(void)
|
||||
{
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : 1;
|
||||
const uint16_t rows = strip.isMatrix ? SEGMENT.virtualHeight() : SEGMENT.virtualLength();
|
||||
|
||||
@ -3264,11 +3288,11 @@ uint16_t mode_exploding_fireworks(void)
|
||||
if (SEGENV.aux0 < 2) { //FLARE
|
||||
if (SEGENV.aux0 == 0) { //init flare
|
||||
flare->pos = 0;
|
||||
flare->posX = strip.isMatrix ? random16(2,cols-1) : (SEGMENT.intensity > random8()); // will enable random firing side on 1D
|
||||
flare->posX = strip.isMatrix ? random16(2,cols-3) : (SEGMENT.intensity > random8()); // will enable random firing side on 1D
|
||||
uint16_t peakHeight = 75 + random8(180); //0-255
|
||||
peakHeight = (peakHeight * (rows -1)) >> 8;
|
||||
flare->vel = sqrtf(-2.0f * gravity * peakHeight);
|
||||
flare->velX = strip.isMatrix ? (random8(8)-4)/32.f : 0; // no X velocity on 1D
|
||||
flare->velX = strip.isMatrix ? (random8(9)-4)/32.f : 0; // no X velocity on 1D
|
||||
flare->col = 255; //brightness
|
||||
SEGENV.aux0 = 1;
|
||||
}
|
||||
@ -3295,16 +3319,16 @@ uint16_t mode_exploding_fireworks(void)
|
||||
* Size is proportional to the height.
|
||||
*/
|
||||
int nSparks = flare->pos + random8(4);
|
||||
nSparks = constrain(nSparks, 1, numSparks);
|
||||
nSparks = constrain(nSparks, 4, numSparks);
|
||||
|
||||
// initialize sparks
|
||||
if (SEGENV.aux0 == 2) {
|
||||
for (int i = 1; i < nSparks; i++) {
|
||||
sparks[i].pos = flare->pos;
|
||||
sparks[i].posX = flare->posX;
|
||||
sparks[i].vel = (float(random16(0, 20000)) / 10000.0f) - 0.9f; // from -0.9 to 1.1
|
||||
sparks[i].vel = (float(random16(20001)) / 10000.0f) - 0.9f; // from -0.9 to 1.1
|
||||
sparks[i].vel *= rows<32 ? 0.5f : 1; // reduce velocity for smaller strips
|
||||
sparks[i].velX = strip.isMatrix ? (float(random16(0, 4000)) / 10000.0f) - 0.2f : 0; // from -0.2 to 0.2
|
||||
sparks[i].velX = strip.isMatrix ? (float(random16(10001)) / 10000.0f) - 0.5f : 0; // from -0.5 to 0.5
|
||||
sparks[i].col = 345;//abs(sparks[i].vel * 750.0); // set colors before scaling velocity to keep them bright
|
||||
//sparks[i].col = constrain(sparks[i].col, 0, 345);
|
||||
sparks[i].colIndex = random8();
|
||||
@ -3366,6 +3390,7 @@ static const char _data_FX_MODE_EXPLODING_FIREWORKS[] PROGMEM = "Fireworks 1D@Gr
|
||||
*/
|
||||
uint16_t mode_drip(void)
|
||||
{
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
//allocate segment data
|
||||
uint16_t strips = SEGMENT.nrOfVStrips();
|
||||
const int maxNumDrops = 4;
|
||||
@ -3461,6 +3486,7 @@ typedef struct Tetris {
|
||||
} tetris;
|
||||
|
||||
uint16_t mode_tetrix(void) {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
uint16_t strips = SEGMENT.nrOfVStrips(); // allow running on virtual strips (columns in 2D segment)
|
||||
uint16_t dataSize = sizeof(tetris);
|
||||
if (!SEGENV.allocateData(dataSize * strips)) return mode_static(); //allocation failed
|
||||
@ -3503,7 +3529,7 @@ uint16_t mode_tetrix(void) {
|
||||
if (drop->pos > drop->stack) { // fall until top of stack
|
||||
drop->pos -= drop->speed; // may add gravity as: speed += gravity
|
||||
if (int(drop->pos) < int(drop->stack)) drop->pos = drop->stack;
|
||||
for (int i=int(drop->pos); i<SEGLEN; i++) {
|
||||
for (int i = int(drop->pos); i < SEGLEN; i++) {
|
||||
uint32_t col = i<int(drop->pos)+drop->brick ? SEGMENT.color_from_palette(drop->col, false, false, 0) : SEGCOLOR(1);
|
||||
SEGMENT.setPixelColor(indexToVStrip(i, stripNr), col);
|
||||
}
|
||||
@ -3518,7 +3544,7 @@ uint16_t mode_tetrix(void) {
|
||||
drop->brick = 0; // reset brick size (no more growing)
|
||||
if (drop->step > millis()) {
|
||||
// allow fading of virtual strip
|
||||
for (int i=0; i<SEGLEN; i++) SEGMENT.blendPixelColor(indexToVStrip(i, stripNr), SEGCOLOR(1), 25); // 10% blend
|
||||
for (int i = 0; i < SEGLEN; i++) SEGMENT.blendPixelColor(indexToVStrip(i, stripNr), SEGCOLOR(1), 25); // 10% blend
|
||||
} else {
|
||||
drop->stack = 0; // reset brick stack size
|
||||
drop->step = 0; // proceed with next brick
|
||||
@ -3645,7 +3671,7 @@ uint16_t mode_heartbeat(void) {
|
||||
|
||||
return FRAMETIME;
|
||||
}
|
||||
static const char _data_FX_MODE_HEARTBEAT[] PROGMEM = "Heartbeat@!,!;!,!;!;;m12=1";
|
||||
static const char _data_FX_MODE_HEARTBEAT[] PROGMEM = "Heartbeat@!,!;!,!;!;01;m12=1";
|
||||
|
||||
|
||||
// "Pacifica"
|
||||
@ -3769,6 +3795,7 @@ static const char _data_FX_MODE_PACIFICA[] PROGMEM = "Pacifica@!,Angle;;!;;pal=5
|
||||
* Mode simulates a gradual sunrise
|
||||
*/
|
||||
uint16_t mode_sunrise() {
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
//speed 0 - static sun
|
||||
//speed 1 - 60: sunrise time in minutes
|
||||
//speed 60 - 120 : sunset time in minutes - 60;
|
||||
@ -3862,7 +3889,7 @@ static const char _data_FX_MODE_PHASEDNOISE[] PROGMEM = "Phased Noise@!,!;!,!;!"
|
||||
uint16_t mode_twinkleup(void) { // A very short twinkle routine with fade-in and dual controls. By Andrew Tuline.
|
||||
random16_set_seed(535); // The randomizer needs to be re-set each time through the loop in order for the same 'random' numbers to be the same each time through.
|
||||
|
||||
for (int i = 0; i<SEGLEN; i++) {
|
||||
for (int i = 0; i < SEGLEN; i++) {
|
||||
uint8_t ranstart = random8(); // The starting value (aka brightness) for each pixel. Must be consistent each time through the loop for this to work.
|
||||
uint8_t pixBri = sin8(ranstart + 16 * strip.now/(256-SEGMENT.speed));
|
||||
if (random8() > SEGMENT.intensity) pixBri = 0;
|
||||
@ -3924,7 +3951,7 @@ uint16_t mode_sinewave(void) { // Adjustable sinewave. By Andrew Tul
|
||||
SEGENV.step += SEGMENT.speed/16; // Speed of animation.
|
||||
uint16_t freq = SEGMENT.intensity/4;//SEGMENT.fft2/8; // Frequency of the signal.
|
||||
|
||||
for (int i=0; i<SEGLEN; i++) { // For each of the LED's in the strand, set a brightness based on a wave as follows:
|
||||
for (int i = 0; i < SEGLEN; i++) { // For each of the LED's in the strand, set a brightness based on a wave as follows:
|
||||
int pixBri = cubicwave8((i*freq)+SEGENV.step);//qsuba(cubicwave8((i*freq)+SEGENV.step), (255-SEGMENT.intensity)); // qsub sets a minimum value called thiscutoff. If < thiscutoff, then bright = 0. Otherwise, bright = 128 (as defined in qsub)..
|
||||
//setPixCol(i, i*colorIndex/255, pixBri);
|
||||
SEGMENT.setPixelColor(i, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(i*colorIndex/255, false, PALETTE_SOLID_WRAP, 0), pixBri));
|
||||
@ -3979,6 +4006,7 @@ static const char _data_FX_MODE_FLOW[] PROGMEM = "Flow@!,Zones;;!;;m12=1"; //ver
|
||||
*/
|
||||
uint16_t mode_chunchun(void)
|
||||
{
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
SEGMENT.fade_out(254); // add a bit of trail
|
||||
uint16_t counter = strip.now * (6 + (SEGMENT.speed >> 4));
|
||||
uint16_t numBirds = 2 + (SEGLEN >> 3); // 2 + 1/8 of a segment
|
||||
@ -4030,6 +4058,7 @@ typedef struct Spotlight {
|
||||
*/
|
||||
uint16_t mode_dancing_shadows(void)
|
||||
{
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
uint8_t numSpotlights = map(SEGMENT.intensity, 0, 255, 2, SPOT_MAX_COUNT); // 49 on 32 segment ESP32, 17 on 16 segment ESP8266
|
||||
bool initialize = SEGENV.aux0 != numSpotlights;
|
||||
SEGENV.aux0 = numSpotlights;
|
||||
@ -4156,7 +4185,7 @@ uint16_t mode_washing_machine(void) {
|
||||
|
||||
SEGENV.step += (speed * 128.0f);
|
||||
|
||||
for (int i=0; i<SEGLEN; i++) {
|
||||
for (int i = 0; i < SEGLEN; i++) {
|
||||
uint8_t col = sin8(((SEGMENT.intensity / 25 + 1) * 255 * i / SEGLEN) + (SEGENV.step >> 7));
|
||||
SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(col, false, PALETTE_SOLID_WRAP, 3));
|
||||
}
|
||||
@ -4493,7 +4522,7 @@ static const char _data_FX_MODE_AURORA[] PROGMEM = "Aurora@!,!;1,2,3;!;;sx=24,pa
|
||||
// 16 bit perlinmove. Use Perlin Noise instead of sinewaves for movement. By Andrew Tuline.
|
||||
// Controls are speed, # of pixels, faderate.
|
||||
uint16_t mode_perlinmove(void) {
|
||||
|
||||
if (SEGLEN == 1) return mode_static();
|
||||
SEGMENT.fade_out(255-SEGMENT.custom1);
|
||||
for (int i = 0; i < SEGMENT.intensity/16 + 1; i++) {
|
||||
uint16_t locn = inoise16(millis()*128/(260-SEGMENT.speed)+i*15000, millis()*128/(260-SEGMENT.speed)); // Get a new pixel location from moving noise.
|
||||
@ -5787,8 +5816,8 @@ uint16_t mode_2Dfloatingblobs(void) {
|
||||
}
|
||||
}
|
||||
uint32_t c = SEGMENT.color_from_palette(blob->color[i], false, false, 0);
|
||||
if (blob->r[i] > 1.f) SEGMENT.fill_circle(blob->y[i], blob->x[i], roundf(blob->r[i]), c);
|
||||
else SEGMENT.setPixelColorXY(blob->y[i], blob->x[i], c);
|
||||
if (blob->r[i] > 1.f) SEGMENT.fill_circle(blob->x[i], blob->y[i], roundf(blob->r[i]), c);
|
||||
else SEGMENT.setPixelColorXY(blob->x[i], blob->y[i], c);
|
||||
// move x
|
||||
if (blob->x[i] + blob->r[i] >= cols - 1) blob->x[i] += (blob->sX[i] * ((cols - 1 - blob->x[i]) / blob->r[i] + 0.005f));
|
||||
else if (blob->x[i] - blob->r[i] <= 0) blob->x[i] += (blob->sX[i] * (blob->x[i] / blob->r[i] + 0.005f));
|
||||
@ -6349,7 +6378,7 @@ uint16_t mode_matripix(void) { // Matripix. By Andrew Tuline.
|
||||
SEGENV.aux0 = secondHand;
|
||||
|
||||
int pixBri = volumeRaw * SEGMENT.intensity / 64;
|
||||
for (int i=0; i<SEGLEN-1; i++) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i+1)); // shift left
|
||||
for (int i = 0; i < SEGLEN-1; i++) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i+1)); // shift left
|
||||
SEGMENT.setPixelColor(SEGLEN-1, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(millis(), false, PALETTE_SOLID_WRAP, 0), pixBri));
|
||||
}
|
||||
|
||||
@ -6520,7 +6549,7 @@ uint16_t mode_plasmoid(void) { // Plasmoid. By Andrew Tuline.
|
||||
plasmoip->thisphase += beatsin8(6,-4,4); // You can change direction and speed individually.
|
||||
plasmoip->thatphase += beatsin8(7,-4,4); // Two phase values to make a complex pattern. By Andrew Tuline.
|
||||
|
||||
for (int i=0; i<SEGLEN; i++) { // For each of the LED's in the strand, set a brightness based on a wave as follows.
|
||||
for (int i = 0; i < SEGLEN; i++) { // For each of the LED's in the strand, set a brightness based on a wave as follows.
|
||||
// updated, similar to "plasma" effect - softhack007
|
||||
uint8_t thisbright = cubicwave8(((i*(1 + (3*SEGMENT.speed/32)))+plasmoip->thisphase) & 0xFF)/2;
|
||||
thisbright += cos8(((i*(97 +(5*SEGMENT.speed/32)))+plasmoip->thatphase) & 0xFF)/2; // Let's munge the brightness a bit and animate it all with the phases.
|
||||
@ -7073,7 +7102,7 @@ uint16_t mode_waterfall(void) { // Waterfall. By: Andrew Tulin
|
||||
} else {
|
||||
SEGMENT.setPixelColor(SEGLEN-1, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(pixCol+SEGMENT.intensity, false, PALETTE_SOLID_WRAP, 0), (int)my_magnitude));
|
||||
}
|
||||
for (int i=0; i<SEGLEN-1; i++) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i+1)); // shift left
|
||||
for (int i = 0; i < SEGLEN-1; i++) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i+1)); // shift left
|
||||
}
|
||||
|
||||
return FRAMETIME;
|
||||
|
38
wled00/FX.h
38
wled00/FX.h
@ -72,7 +72,11 @@
|
||||
#ifndef MAX_NUM_SEGMENTS
|
||||
#define MAX_NUM_SEGMENTS 32
|
||||
#endif
|
||||
#define MAX_SEGMENT_DATA 32767
|
||||
#if defined(ARDUINO_ARCH_ESP32S2)
|
||||
#define MAX_SEGMENT_DATA 24576
|
||||
#else
|
||||
#define MAX_SEGMENT_DATA 32767
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* How much data bytes each segment should max allocate to leave enough space for other segments,
|
||||
@ -460,7 +464,7 @@ typedef struct Segment {
|
||||
_dataLen(0),
|
||||
_t(nullptr)
|
||||
{
|
||||
refreshLightCapabilities();
|
||||
//refreshLightCapabilities();
|
||||
}
|
||||
|
||||
Segment(uint16_t sStartX, uint16_t sStopX, uint16_t sStartY, uint16_t sStopY) : Segment(sStartX, sStopX) {
|
||||
@ -496,6 +500,9 @@ typedef struct Segment {
|
||||
inline bool isSelected(void) const { return selected; }
|
||||
inline bool isActive(void) const { return stop > start; }
|
||||
inline bool is2D(void) const { return (width()>1 && height()>1); }
|
||||
inline bool hasRGB(void) const { return _isRGB; }
|
||||
inline bool hasWhite(void) const { return _hasW; }
|
||||
inline bool isCCT(void) const { return _isCCT; }
|
||||
inline uint16_t width(void) const { return stop - start; } // segment width in physical pixels (length if 1D)
|
||||
inline uint16_t height(void) const { return stopY - startY; } // segment height (if 2D) in physical pixels
|
||||
inline uint16_t length(void) const { return width() * height(); } // segment length (count) in physical pixels
|
||||
@ -659,7 +666,6 @@ class WS2812FX { // 96 bytes
|
||||
isMatrix(false),
|
||||
#ifndef WLED_DISABLE_2D
|
||||
panels(1),
|
||||
matrix{0,0,0,0},
|
||||
#endif
|
||||
// semi-private (just obscured) used in effect functions through macros
|
||||
_currentPalette(CRGBPalette16(CRGB::Black)),
|
||||
@ -712,7 +718,6 @@ class WS2812FX { // 96 bytes
|
||||
finalizeInit(),
|
||||
service(void),
|
||||
setMode(uint8_t segid, uint8_t m),
|
||||
setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
||||
setColor(uint8_t slot, uint32_t c),
|
||||
setCCT(uint16_t k),
|
||||
setBrightness(uint8_t b, bool direct = false),
|
||||
@ -727,10 +732,10 @@ class WS2812FX { // 96 bytes
|
||||
fixInvalidSegments(),
|
||||
setPixelColor(int n, uint32_t c),
|
||||
show(void),
|
||||
setTargetFps(uint8_t fps),
|
||||
deserializeMap(uint8_t n=0);
|
||||
setTargetFps(uint8_t fps);
|
||||
|
||||
void fill(uint32_t c) { for (int i = 0; i < _length; i++) setPixelColor(i, c); } // fill whole strip with color (inline)
|
||||
void setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setColor(slot, RGBW32(r,g,b,w)); }
|
||||
void fill(uint32_t c) { for (int i = 0; i < getLengthTotal(); i++) setPixelColor(i, c); } // fill whole strip with color (inline)
|
||||
void addEffect(uint8_t id, mode_ptr mode_fn, const char *mode_name); // add effect to the list; defined in FX.cpp
|
||||
void setupEffectData(void); // add default effects to the list; defined in FX.cpp
|
||||
|
||||
@ -748,6 +753,7 @@ class WS2812FX { // 96 bytes
|
||||
hasCCTBus(void),
|
||||
// return true if the strip is being sent pixel updates
|
||||
isUpdating(void),
|
||||
deserializeMap(uint8_t n=0),
|
||||
useLedsArray = false;
|
||||
|
||||
inline bool isServicing(void) { return _isServicing; }
|
||||
@ -777,17 +783,17 @@ class WS2812FX { // 96 bytes
|
||||
ablMilliampsMax,
|
||||
currentMilliamps,
|
||||
getLengthPhysical(void),
|
||||
getLengthTotal(void), // will include virtual/nonexistent pixels in matrix
|
||||
getFps();
|
||||
|
||||
inline uint16_t getFrameTime(void) { return _frametime; }
|
||||
inline uint16_t getMinShowDelay(void) { return MIN_SHOW_DELAY; }
|
||||
inline uint16_t getLengthTotal(void) { return _length; }
|
||||
inline uint16_t getLength(void) { return _length; } // 2D matrix may have less pixels than W*H
|
||||
inline uint16_t getTransition(void) { return _transitionDur; }
|
||||
|
||||
uint32_t
|
||||
now,
|
||||
timebase,
|
||||
currentColor(uint32_t colorNew, uint8_t tNr),
|
||||
getPixelColor(uint16_t);
|
||||
|
||||
inline uint32_t getLastShow(void) { return _lastShow; }
|
||||
@ -813,13 +819,6 @@ class WS2812FX { // 96 bytes
|
||||
uint8_t
|
||||
panels;
|
||||
|
||||
struct {
|
||||
bool bottomStart : 1;
|
||||
bool rightStart : 1;
|
||||
bool vertical : 1;
|
||||
bool serpentine : 1;
|
||||
} matrix;
|
||||
|
||||
typedef struct panel_t {
|
||||
uint16_t xOffset; // x offset relative to the top left of matrix in LEDs
|
||||
uint16_t yOffset; // y offset relative to the top left of matrix in LEDs
|
||||
@ -834,6 +833,13 @@ class WS2812FX { // 96 bytes
|
||||
bool serpentine : 1; // is serpentine?
|
||||
};
|
||||
};
|
||||
panel_t()
|
||||
: xOffset(0)
|
||||
, yOffset(0)
|
||||
, width(8)
|
||||
, height(8)
|
||||
, options(0)
|
||||
{}
|
||||
} Panel;
|
||||
std::vector<Panel> panel;
|
||||
#endif
|
||||
|
@ -78,21 +78,60 @@ void WS2812FX::setUpMatrix() {
|
||||
customMappingTable[i] = (uint16_t)-1;
|
||||
}
|
||||
|
||||
// we will try to load a "gap" array (a JSON file)
|
||||
// the array has to have the same amount of values as mapping array (or larger)
|
||||
// "gap" array is used while building ledmap (mapping array)
|
||||
// and discarded afterwards as it has no meaning after the process
|
||||
// content of the file is just raw JSON array in the form of [val1,val2,val3,...]
|
||||
// there are no other "key":"value" pairs in it
|
||||
// allowed values are: -1 (missing pixel/no LED attached), 0 (inactive/unused pixel), 1 (active/used pixel)
|
||||
char fileName[32]; strcpy_P(fileName, PSTR("/2d-gaps.json")); // reduce flash footprint
|
||||
bool isFile = WLED_FS.exists(fileName);
|
||||
size_t gapSize = 0;
|
||||
int8_t *gapTable = nullptr;
|
||||
|
||||
if (isFile && requestJSONBufferLock(20)) {
|
||||
DEBUG_PRINT(F("Reading LED gap from "));
|
||||
DEBUG_PRINTLN(fileName);
|
||||
// read the array into global JSON buffer
|
||||
if (readObjectFromFile(fileName, nullptr, &doc)) {
|
||||
// the array is similar to ledmap, except it has only 3 values:
|
||||
// -1 ... missing pixel (do not increase pixel count)
|
||||
// 0 ... inactive pixel (it does count, but should be mapped out (-1))
|
||||
// 1 ... active pixel (it will count and will be mapped)
|
||||
JsonArray map = doc.as<JsonArray>();
|
||||
gapSize = map.size();
|
||||
if (!map.isNull() && gapSize >= customMappingSize) { // not an empty map
|
||||
gapTable = new int8_t[gapSize];
|
||||
if (gapTable) for (size_t i = 0; i < gapSize; i++) {
|
||||
gapTable[i] = constrain(map[i], -1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUG_PRINTLN(F("Gaps loaded."));
|
||||
releaseJSONBufferLock();
|
||||
}
|
||||
|
||||
uint16_t x, y, pix=0; //pixel
|
||||
for (size_t pan = 0; pan < panel.size(); pan++) {
|
||||
Panel &p = panel[pan];
|
||||
uint16_t h = p.vertical ? p.height : p.width;
|
||||
uint16_t v = p.vertical ? p.width : p.height;
|
||||
for (size_t j = 0; j < v; j++){
|
||||
for(size_t i = 0; i < h; i++, pix++) {
|
||||
for(size_t i = 0; i < h; i++) {
|
||||
y = (p.vertical?p.rightStart:p.bottomStart) ? v-j-1 : j;
|
||||
x = (p.vertical?p.bottomStart:p.rightStart) ? h-i-1 : i;
|
||||
x = p.serpentine && j%2 ? h-x-1 : x;
|
||||
customMappingTable[(p.yOffset + (p.vertical?x:y)) * Segment::maxWidth + p.xOffset + (p.vertical?y:x)] = pix;
|
||||
size_t index = (p.yOffset + (p.vertical?x:y)) * Segment::maxWidth + p.xOffset + (p.vertical?y:x);
|
||||
if (!gapTable || (gapTable && gapTable[index] > 0)) customMappingTable[index] = pix; // a useful pixel (otherwise -1 is retained)
|
||||
if (!gapTable || (gapTable && gapTable[index] >= 0)) pix++; // not a missing pixel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// delete gap array as we no longer need it
|
||||
if (gapTable) delete[] gapTable;
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("Matrix ledmap:"));
|
||||
for (uint16_t i=0; i<customMappingSize; i++) {
|
||||
@ -108,8 +147,8 @@ void WS2812FX::setUpMatrix() {
|
||||
panel.clear();
|
||||
Segment::maxWidth = _length;
|
||||
Segment::maxHeight = 1;
|
||||
resetSegments();
|
||||
}
|
||||
resetSegments();
|
||||
}
|
||||
#else
|
||||
isMatrix = false; // no matter what config says
|
||||
@ -117,17 +156,16 @@ void WS2812FX::setUpMatrix() {
|
||||
}
|
||||
|
||||
// absolute matrix version of setPixelColor()
|
||||
void IRAM_ATTR WS2812FX::setPixelColorXY(int x, int y, uint32_t col)
|
||||
void /*IRAM_ATTR*/ WS2812FX::setPixelColorXY(int x, int y, uint32_t col)
|
||||
{
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (!isMatrix) return; // not a matrix set-up
|
||||
uint16_t index = y * Segment::maxWidth + x;
|
||||
if (index >= customMappingSize) return;
|
||||
#else
|
||||
uint16_t index = x;
|
||||
if (index >= _length) return;
|
||||
#endif
|
||||
if (index < customMappingSize) index = customMappingTable[index];
|
||||
if (index >= _length) return;
|
||||
busses.setPixelColor(index, col);
|
||||
}
|
||||
|
||||
@ -135,12 +173,11 @@ void IRAM_ATTR WS2812FX::setPixelColorXY(int x, int y, uint32_t col)
|
||||
uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
||||
#ifndef WLED_DISABLE_2D
|
||||
uint16_t index = (y * Segment::maxWidth + x);
|
||||
if (index >= customMappingSize) return 0; // customMappingSize is always W * H of matrix in 2D setup
|
||||
#else
|
||||
uint16_t index = x;
|
||||
if (index >= _length) return 0;
|
||||
#endif
|
||||
if (index < customMappingSize) index = customMappingTable[index];
|
||||
if (index >= _length) return 0;
|
||||
return busses.getPixelColor(index);
|
||||
}
|
||||
|
||||
@ -151,13 +188,13 @@ uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
||||
#ifndef WLED_DISABLE_2D
|
||||
|
||||
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
||||
uint16_t IRAM_ATTR Segment::XY(uint16_t x, uint16_t y) {
|
||||
uint16_t /*IRAM_ATTR*/ Segment::XY(uint16_t x, uint16_t y) {
|
||||
uint16_t width = virtualWidth(); // segment width in logical pixels
|
||||
uint16_t height = virtualHeight(); // segment height in logical pixels
|
||||
return (x%width) + (y%height) * width;
|
||||
}
|
||||
|
||||
void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
|
||||
void /*IRAM_ATTR*/ Segment::setPixelColorXY(int x, int y, uint32_t col)
|
||||
{
|
||||
if (Segment::maxHeight==1) return; // not a matrix set-up
|
||||
if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit
|
||||
|
@ -81,7 +81,7 @@ uint16_t Segment::maxHeight = 1;
|
||||
// copy constructor
|
||||
Segment::Segment(const Segment &orig) {
|
||||
//DEBUG_PRINTLN(F("-- Copy segment constructor --"));
|
||||
memcpy(this, &orig, sizeof(Segment));
|
||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||
name = nullptr;
|
||||
data = nullptr;
|
||||
_dataLen = 0;
|
||||
@ -96,7 +96,7 @@ Segment::Segment(const Segment &orig) {
|
||||
// move constructor
|
||||
Segment::Segment(Segment &&orig) noexcept {
|
||||
//DEBUG_PRINTLN(F("-- Move segment constructor --"));
|
||||
memcpy(this, &orig, sizeof(Segment));
|
||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||
orig.name = nullptr;
|
||||
orig.data = nullptr;
|
||||
orig._dataLen = 0;
|
||||
@ -114,7 +114,7 @@ Segment& Segment::operator= (const Segment &orig) {
|
||||
if (leds && !Segment::_globalLeds) free(leds);
|
||||
deallocateData();
|
||||
// copy source
|
||||
memcpy(this, &orig, sizeof(Segment));
|
||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||
// erase pointers to allocated data
|
||||
name = nullptr;
|
||||
data = nullptr;
|
||||
@ -138,7 +138,7 @@ Segment& Segment::operator= (Segment &&orig) noexcept {
|
||||
deallocateData(); // free old runtime data
|
||||
if (_t) delete _t;
|
||||
if (leds && !Segment::_globalLeds) free(leds);
|
||||
memcpy(this, &orig, sizeof(Segment));
|
||||
memcpy((void*)this, (void*)&orig, sizeof(Segment));
|
||||
orig.name = nullptr;
|
||||
orig.data = nullptr;
|
||||
orig._dataLen = 0;
|
||||
@ -184,7 +184,8 @@ void Segment::deallocateData() {
|
||||
void Segment::resetIfRequired() {
|
||||
if (reset) {
|
||||
if (leds && !Segment::_globalLeds) { free(leds); leds = nullptr; }
|
||||
//if (_t) { delete _t; _t = nullptr; transitional = false; }
|
||||
if (transitional && _t) { transitional = false; delete _t; _t = nullptr; }
|
||||
deallocateData();
|
||||
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
||||
reset = false; // setOption(SEG_OPTION_RESET, false);
|
||||
}
|
||||
@ -226,14 +227,14 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) {
|
||||
case FX_MODE_NOISE16_4 : pal = 26; break; // landscape 33
|
||||
case FX_MODE_GLITTER : pal = 11; break; // rainbow colors
|
||||
case FX_MODE_SUNRISE : pal = 35; break; // heat palette
|
||||
case FX_MODE_FLOW : pal = 6; break; // party
|
||||
case FX_MODE_RAILWAY : pal = 3; break; // prim + sec
|
||||
}
|
||||
switch (pal) {
|
||||
case 0: //default palette. Exceptions for specific effects above
|
||||
targetPalette = PartyColors_p; break;
|
||||
case 1: {//periodically replace palette with a random one. Transition palette change in 500ms
|
||||
uint32_t timeSinceLastChange = millis() - _lastPaletteChange;
|
||||
if (timeSinceLastChange > 5000 /*+ ((uint32_t)(255-intensity))*100*/) {
|
||||
if (timeSinceLastChange > randomPaletteChangeTime * 1000U) {
|
||||
prevRandomPalette = randomPalette;
|
||||
randomPalette = CRGBPalette16(
|
||||
CHSV(random8(), random8(160, 255), random8(128, 255)),
|
||||
@ -393,8 +394,8 @@ void Segment::set(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t o
|
||||
markForReset();
|
||||
return;
|
||||
}
|
||||
if (i1 < Segment::maxWidth) start = i1; // Segment::maxWidth equals strip.getLengthTotal() for 1D
|
||||
stop = i2 > Segment::maxWidth ? Segment::maxWidth : MAX(1,i2);
|
||||
if (i1 < Segment::maxWidth || (i1 >= Segment::maxWidth*Segment::maxHeight && i1 < strip.getLengthTotal())) start = i1; // Segment::maxWidth equals strip.getLengthTotal() for 1D
|
||||
stop = i2 > Segment::maxWidth*Segment::maxHeight ? MIN(i2,strip.getLengthTotal()) : (i2 > Segment::maxWidth ? Segment::maxWidth : MAX(1,i2));
|
||||
startY = 0;
|
||||
stopY = 1;
|
||||
#ifndef WLED_DISABLE_2D
|
||||
@ -415,6 +416,10 @@ void Segment::set(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t o
|
||||
|
||||
bool Segment::setColor(uint8_t slot, uint32_t c) { //returns true if changed
|
||||
if (slot >= NUM_COLORS || c == colors[slot]) return false;
|
||||
if (!_isRGB && !_hasW) {
|
||||
if (slot == 0 && c == BLACK) return false; // on/off segment cannot have primary color black
|
||||
if (slot == 1 && c != BLACK) return false; // on/off segment cannot have secondary color non black
|
||||
}
|
||||
if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change
|
||||
colors[slot] = c;
|
||||
stateChanged = true; // send UDP/WS broadcast
|
||||
@ -546,7 +551,9 @@ uint16_t Segment::virtualLength() const {
|
||||
|
||||
void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
||||
{
|
||||
#ifndef WLED_DISABLE_2D
|
||||
int vStrip = i>>16; // hack to allow running on virtual strips (2D segment columns/rows)
|
||||
#endif
|
||||
i &= 0xFFFF;
|
||||
|
||||
if (i >= virtualLength() || i<0) return; // if pixel would fall out of segment just exit
|
||||
@ -600,12 +607,14 @@ void IRAM_ATTR Segment::setPixelColor(int i, uint32_t col)
|
||||
}
|
||||
return;
|
||||
} else if (Segment::maxHeight!=1 && (width()==1 || height()==1)) {
|
||||
// we have a vertical or horizontal 1D segment (WARNING: virtual...() may be transposed)
|
||||
int x = 0, y = 0;
|
||||
if (virtualHeight()>1) y = i;
|
||||
if (virtualWidth() >1) x = i;
|
||||
setPixelColorXY(x, y, col);
|
||||
return;
|
||||
if (start < Segment::maxWidth*Segment::maxHeight) {
|
||||
// we have a vertical or horizontal 1D segment (WARNING: virtual...() may be transposed)
|
||||
int x = 0, y = 0;
|
||||
if (virtualHeight()>1) y = i;
|
||||
if (virtualWidth() >1) x = i;
|
||||
setPixelColorXY(x, y, col);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -684,7 +693,9 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa)
|
||||
|
||||
uint32_t Segment::getPixelColor(int i)
|
||||
{
|
||||
#ifndef WLED_DISABLE_2D
|
||||
int vStrip = i>>16;
|
||||
#endif
|
||||
i &= 0xFFFF;
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
@ -747,29 +758,46 @@ uint8_t Segment::differs(Segment& b) const {
|
||||
}
|
||||
|
||||
void Segment::refreshLightCapabilities() {
|
||||
uint8_t capabilities = 0x01;
|
||||
uint8_t capabilities = 0;
|
||||
uint16_t segStartIdx = 0xFFFFU;
|
||||
uint16_t segStopIdx = 0;
|
||||
|
||||
if (start < Segment::maxWidth * Segment::maxHeight) {
|
||||
// we are withing 2D matrix (includes 1D segments)
|
||||
for (int y = startY; y < stopY; y++) for (int x = start; x < stop; x++) {
|
||||
uint16_t index = x + Segment::maxWidth * y;
|
||||
if (index < strip.customMappingSize) index = strip.customMappingTable[index]; // convert logical address to physical
|
||||
if (index < 0xFFFFU) {
|
||||
if (segStartIdx > index) segStartIdx = index;
|
||||
if (segStopIdx < index) segStopIdx = index;
|
||||
}
|
||||
if (segStartIdx == segStopIdx) segStopIdx++; // we only have 1 pixel segment
|
||||
}
|
||||
} else {
|
||||
// we are on the strip located after the matrix
|
||||
segStartIdx = start;
|
||||
segStopIdx = stop;
|
||||
}
|
||||
|
||||
for (uint8_t b = 0; b < busses.getNumBusses(); b++) {
|
||||
Bus *bus = busses.getBus(b);
|
||||
if (bus == nullptr || bus->getLength()==0) break;
|
||||
if (!bus->isOk()) continue;
|
||||
if (bus->getStart() >= stop) continue;
|
||||
if (bus->getStart() + bus->getLength() <= start) continue;
|
||||
if (bus->getStart() >= segStopIdx) continue;
|
||||
if (bus->getStart() + bus->getLength() <= segStartIdx) continue;
|
||||
|
||||
uint8_t type = bus->getType();
|
||||
if (type == TYPE_ONOFF || type == TYPE_ANALOG_1CH || (!cctFromRgb && type == TYPE_ANALOG_2CH)) capabilities &= 0xFE; // does not support RGB
|
||||
if (bus->isRgbw()) capabilities |= 0x02; // segment supports white channel
|
||||
if (!cctFromRgb) {
|
||||
switch (type) {
|
||||
case TYPE_ANALOG_5CH:
|
||||
case TYPE_ANALOG_2CH:
|
||||
capabilities |= 0x04; //segment supports white CCT
|
||||
}
|
||||
//uint8_t type = bus->getType();
|
||||
if (bus->hasRGB() || (cctFromRgb && bus->hasCCT())) capabilities |= SEG_CAPABILITY_RGB;
|
||||
if (!cctFromRgb && bus->hasCCT()) capabilities |= SEG_CAPABILITY_CCT;
|
||||
if (correctWB && (bus->hasRGB() || bus->hasCCT())) capabilities |= SEG_CAPABILITY_CCT; //white balance correction (CCT slider)
|
||||
if (bus->hasWhite()) {
|
||||
uint8_t aWM = Bus::getGlobalAWMode() == AW_GLOBAL_DISABLED ? bus->getAutoWhiteMode() : Bus::getGlobalAWMode();
|
||||
bool whiteSlider = (aWM == RGBW_MODE_DUAL || aWM == RGBW_MODE_MANUAL_ONLY); // white slider allowed
|
||||
// if auto white calculation from RGB is active (Accurate/Brighter), force RGB controls even if there are no RGB busses
|
||||
if (!whiteSlider) capabilities |= SEG_CAPABILITY_RGB;
|
||||
// if auto white calculation from RGB is disabled/optional (None/Dual), allow white channel adjustments
|
||||
if ( whiteSlider) capabilities |= SEG_CAPABILITY_W;
|
||||
}
|
||||
if (correctWB && !(type == TYPE_ANALOG_1CH || type == TYPE_ONOFF)) capabilities |= 0x04; //white balance correction (uses CCT slider)
|
||||
uint8_t aWM = Bus::getAutoWhiteMode()<255 ? Bus::getAutoWhiteMode() : bus->getAWMode();
|
||||
bool whiteSlider = (aWM == RGBW_MODE_DUAL || aWM == RGBW_MODE_MANUAL_ONLY); // white slider allowed
|
||||
if (bus->isRgbw() && (whiteSlider || !(capabilities & 0x01))) capabilities |= 0x08; // allow white channel adjustments (AWM allows or is not RGB)
|
||||
}
|
||||
_capabilities = capabilities;
|
||||
}
|
||||
@ -998,7 +1026,7 @@ void WS2812FX::finalizeInit(void)
|
||||
if (bus == nullptr) continue;
|
||||
if (bus->getStart() + bus->getLength() > MAX_LEDS) break;
|
||||
//RGBW mode is enabled if at least one of the strips is RGBW
|
||||
_hasWhiteChannel |= bus->isRgbw();
|
||||
_hasWhiteChannel |= bus->hasWhite();
|
||||
//refresh is required to remain off if at least one of the strips requires the refresh.
|
||||
_isOffRefreshRequired |= bus->isOffRefreshRequired();
|
||||
uint16_t busEnd = bus->getStart() + bus->getLength();
|
||||
@ -1012,10 +1040,11 @@ void WS2812FX::finalizeInit(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!isMatrix) { // if 2D then max values defined in setUpMatrix() using panel set-up
|
||||
if (isMatrix) setUpMatrix();
|
||||
else {
|
||||
Segment::maxWidth = _length;
|
||||
Segment::maxHeight = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//initialize leds array. TBD: realloc if nr of leds change
|
||||
if (Segment::_globalLeds) {
|
||||
@ -1024,17 +1053,20 @@ void WS2812FX::finalizeInit(void)
|
||||
Segment::_globalLeds = nullptr;
|
||||
}
|
||||
if (useLedsArray) {
|
||||
size_t arrSize = sizeof(CRGB) * getLengthTotal();
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
if (psramFound())
|
||||
Segment::_globalLeds = (CRGB*) ps_malloc(sizeof(CRGB) * _length);
|
||||
Segment::_globalLeds = (CRGB*) ps_malloc(arrSize);
|
||||
else
|
||||
#endif
|
||||
Segment::_globalLeds = (CRGB*) malloc(sizeof(CRGB) * _length);
|
||||
memset(Segment::_globalLeds, 0, sizeof(CRGB) * _length);
|
||||
Segment::_globalLeds = (CRGB*) malloc(arrSize);
|
||||
memset(Segment::_globalLeds, 0, arrSize);
|
||||
}
|
||||
|
||||
//segments are created in makeAutoSegments();
|
||||
DEBUG_PRINTLN(F("Loading custom palettes"));
|
||||
loadCustomPalettes(); // (re)load all custom palettes
|
||||
DEBUG_PRINTLN(F("Loading custom ledmaps"));
|
||||
deserializeMap(); // (re)load default ledmap
|
||||
}
|
||||
|
||||
@ -1095,15 +1127,15 @@ void WS2812FX::service() {
|
||||
|
||||
void IRAM_ATTR WS2812FX::setPixelColor(int i, uint32_t col)
|
||||
{
|
||||
if (i >= _length) return;
|
||||
if (i < customMappingSize) i = customMappingTable[i];
|
||||
if (i >= _length) return;
|
||||
busses.setPixelColor(i, col);
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::getPixelColor(uint16_t i)
|
||||
{
|
||||
if (i >= _length) return 0;
|
||||
if (i < customMappingSize) i = customMappingTable[i];
|
||||
if (i >= _length) return 0;
|
||||
return busses.getPixelColor(i);
|
||||
}
|
||||
|
||||
@ -1165,7 +1197,7 @@ void WS2812FX::estimateCurrentAndLimitBri() {
|
||||
}
|
||||
}
|
||||
|
||||
if (bus->isRgbw()) { //RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
|
||||
if (bus->hasWhite()) { //RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
|
||||
busPowerSum *= 3;
|
||||
busPowerSum = busPowerSum >> 2; //same as /= 4
|
||||
}
|
||||
@ -1316,6 +1348,12 @@ uint8_t WS2812FX::getActiveSegmentsNum(void) {
|
||||
return c;
|
||||
}
|
||||
|
||||
uint16_t WS2812FX::getLengthTotal(void) {
|
||||
uint16_t len = Segment::maxWidth * Segment::maxHeight; // will be _length for 1D (see finalizeInit()) but should cover whole matrix for 2D
|
||||
if (isMatrix && _length > len) len = _length; // for 2D with trailing strip
|
||||
return len;
|
||||
}
|
||||
|
||||
uint16_t WS2812FX::getLengthPhysical(void) {
|
||||
uint16_t len = 0;
|
||||
for (size_t b = 0; b < busses.getNumBusses(); b++) {
|
||||
@ -1333,12 +1371,7 @@ bool WS2812FX::hasRGBWBus(void) {
|
||||
for (size_t b = 0; b < busses.getNumBusses(); b++) {
|
||||
Bus *bus = busses.getBus(b);
|
||||
if (bus == nullptr || bus->getLength()==0) break;
|
||||
switch (bus->getType()) {
|
||||
case TYPE_SK6812_RGBW:
|
||||
case TYPE_TM1814:
|
||||
case TYPE_ANALOG_4CH:
|
||||
return true;
|
||||
}
|
||||
if (bus->hasRGB() && bus->hasWhite()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -1363,7 +1396,6 @@ void WS2812FX::purgeSegments(bool force) {
|
||||
if (_segments.size() <= 1) return;
|
||||
for (size_t i = _segments.size()-1; i > 0; i--)
|
||||
if (_segments[i].stop == 0 || force) {
|
||||
DEBUG_PRINT(F("Purging segment segment: ")); DEBUG_PRINTLN(i);
|
||||
deleted++;
|
||||
_segments.erase(_segments.begin() + i);
|
||||
}
|
||||
@ -1398,31 +1430,31 @@ void WS2812FX::resetSegments() {
|
||||
}
|
||||
|
||||
void WS2812FX::makeAutoSegments(bool forceReset) {
|
||||
if (isMatrix) {
|
||||
#ifndef WLED_DISABLE_2D
|
||||
// only create 1 2D segment
|
||||
if (forceReset || getSegmentsNum() == 0) resetSegments(); // initialises 1 segment
|
||||
else if (getActiveSegmentsNum() == 1) {
|
||||
size_t i = getLastActiveSegmentId();
|
||||
_segments[i].start = 0;
|
||||
_segments[i].stop = Segment::maxWidth;
|
||||
_segments[i].startY = 0;
|
||||
_segments[i].stopY = Segment::maxHeight;
|
||||
_segments[i].grouping = 1;
|
||||
_segments[i].spacing = 0;
|
||||
_mainSegment = i;
|
||||
}
|
||||
#endif
|
||||
} else if (autoSegments) { //make one segment per bus
|
||||
if (autoSegments) { //make one segment per bus
|
||||
uint16_t segStarts[MAX_NUM_SEGMENTS] = {0};
|
||||
uint16_t segStops [MAX_NUM_SEGMENTS] = {0};
|
||||
uint8_t s = 0;
|
||||
for (uint8_t i = 0; i < busses.getNumBusses(); i++) {
|
||||
size_t s = 0;
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
// 2D segment is the 1st one using entire matrix
|
||||
if (isMatrix) {
|
||||
segStarts[0] = 0;
|
||||
segStops[0] = Segment::maxWidth*Segment::maxHeight;
|
||||
s++;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (size_t i = s; i < busses.getNumBusses(); i++) {
|
||||
Bus* b = busses.getBus(i);
|
||||
|
||||
segStarts[s] = b->getStart();
|
||||
segStops[s] = segStarts[s] + b->getLength();
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (isMatrix && segStops[s] < Segment::maxWidth*Segment::maxHeight) continue; // ignore buses comprising matrix
|
||||
if (isMatrix && segStarts[s] < Segment::maxWidth*Segment::maxHeight) segStarts[s] = Segment::maxWidth*Segment::maxHeight;
|
||||
#endif
|
||||
|
||||
//check for overlap with previous segments
|
||||
for (size_t j = 0; j < s; j++) {
|
||||
if (segStops[j] > segStarts[s] && segStarts[j] < segStops[s]) {
|
||||
@ -1434,23 +1466,40 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
|
||||
}
|
||||
s++;
|
||||
}
|
||||
|
||||
_segments.clear();
|
||||
for (size_t i = 0; i < s; i++) {
|
||||
Segment seg = Segment(segStarts[i], segStops[i]);
|
||||
seg.selected = true;
|
||||
_segments.push_back(seg);
|
||||
_segments.reserve(s); // prevent reallocations
|
||||
// there is always at least one segment (but we need to differentiate between 1D and 2D)
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (isMatrix)
|
||||
_segments.push_back(Segment(0, Segment::maxWidth, 0, Segment::maxHeight));
|
||||
else
|
||||
#endif
|
||||
_segments.push_back(Segment(segStarts[0], segStops[0]));
|
||||
for (size_t i = 1; i < s; i++) {
|
||||
_segments.push_back(Segment(segStarts[i], segStops[i]));
|
||||
}
|
||||
_mainSegment = 0;
|
||||
|
||||
} else {
|
||||
|
||||
if (forceReset || getSegmentsNum() == 0) resetSegments();
|
||||
//expand the main seg to the entire length, but only if there are no other segments, or reset is forced
|
||||
else if (getActiveSegmentsNum() == 1) {
|
||||
size_t i = getLastActiveSegmentId();
|
||||
#ifndef WLED_DISABLE_2D
|
||||
_segments[i].start = 0;
|
||||
_segments[i].stop = Segment::maxWidth;
|
||||
_segments[i].startY = 0;
|
||||
_segments[i].stopY = Segment::maxHeight;
|
||||
_segments[i].grouping = 1;
|
||||
_segments[i].spacing = 0;
|
||||
#else
|
||||
_segments[i].start = 0;
|
||||
_segments[i].stop = _length;
|
||||
_mainSegment = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
_mainSegment = 0;
|
||||
|
||||
fixInvalidSegments();
|
||||
}
|
||||
@ -1458,14 +1507,30 @@ void WS2812FX::makeAutoSegments(bool forceReset) {
|
||||
void WS2812FX::fixInvalidSegments() {
|
||||
//make sure no segment is longer than total (sanity check)
|
||||
for (size_t i = getSegmentsNum()-1; i > 0; i--) {
|
||||
if (_segments[i].start >= _length) { _segments.erase(_segments.begin()+i); continue; }
|
||||
if (_segments[i].stop > _length) _segments[i].stop = _length;
|
||||
// this is always called as the last step after finalizeInit(), update covered bus types
|
||||
_segments[i].refreshLightCapabilities();
|
||||
if (isMatrix) {
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (_segments[i].start >= Segment::maxWidth * Segment::maxHeight) {
|
||||
// 1D segment at the end of matrix
|
||||
if (_segments[i].start >= _length || _segments[i].startY > 0 || _segments[i].stopY > 1) { _segments.erase(_segments.begin()+i); continue; }
|
||||
if (_segments[i].stop > _length) _segments[i].stop = _length;
|
||||
continue;
|
||||
}
|
||||
if (_segments[i].start >= Segment::maxWidth || _segments[i].startY >= Segment::maxHeight) { _segments.erase(_segments.begin()+i); continue; }
|
||||
if (_segments[i].stop > Segment::maxWidth) _segments[i].stop = Segment::maxWidth;
|
||||
if (_segments[i].stopY > Segment::maxHeight) _segments[i].stopY = Segment::maxHeight;
|
||||
#endif
|
||||
} else {
|
||||
if (_segments[i].start >= _length) { _segments.erase(_segments.begin()+i); continue; }
|
||||
if (_segments[i].stop > _length) _segments[i].stop = _length;
|
||||
}
|
||||
}
|
||||
// this is always called as the last step after finalizeInit(), update covered bus types
|
||||
for (segment &seg : _segments)
|
||||
seg.refreshLightCapabilities();
|
||||
}
|
||||
|
||||
//true if all segments align with a bus, or if a segment covers the total length
|
||||
//irrelevant in 2D set-up
|
||||
bool WS2812FX::checkSegmentAlignment() {
|
||||
bool aligned = false;
|
||||
for (segment &seg : _segments) {
|
||||
@ -1482,8 +1547,7 @@ bool WS2812FX::checkSegmentAlignment() {
|
||||
//After this function is called, setPixelColor() will use that segment (offsets, grouping, ... will apply)
|
||||
//Note: If called in an interrupt (e.g. JSON API), original segment must be restored,
|
||||
//otherwise it can lead to a crash on ESP32 because _segment_index is modified while in use by the main thread
|
||||
uint8_t WS2812FX::setPixelSegment(uint8_t n)
|
||||
{
|
||||
uint8_t WS2812FX::setPixelSegment(uint8_t n) {
|
||||
uint8_t prevSegId = _segment_index;
|
||||
if (n < _segments.size()) {
|
||||
_segment_index = n;
|
||||
@ -1492,8 +1556,7 @@ uint8_t WS2812FX::setPixelSegment(uint8_t n)
|
||||
return prevSegId;
|
||||
}
|
||||
|
||||
void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col)
|
||||
{
|
||||
void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col) {
|
||||
if (i2 >= i)
|
||||
{
|
||||
for (uint16_t x = i; x <= i2; x++) setPixelColor(x, col);
|
||||
@ -1503,26 +1566,24 @@ void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col)
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::setTransitionMode(bool t)
|
||||
{
|
||||
void WS2812FX::setTransitionMode(bool t) {
|
||||
for (segment &seg : _segments) if (!seg.transitional) seg.startTransition(t ? _transitionDur : 0);
|
||||
}
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
void WS2812FX::printSize()
|
||||
{
|
||||
void WS2812FX::printSize() {
|
||||
size_t size = 0;
|
||||
for (const Segment &seg : _segments) size += seg.getSize();
|
||||
DEBUG_PRINTF("Segments: %d -> %uB\n", _segments.size(), size);
|
||||
DEBUG_PRINTF("Modes: %d*%d=%uB\n", sizeof(mode_ptr), _mode.size(), (_mode.capacity()*sizeof(mode_ptr)));
|
||||
DEBUG_PRINTF("Data: %d*%d=%uB\n", sizeof(const char *), _modeData.size(), (_modeData.capacity()*sizeof(const char *)));
|
||||
DEBUG_PRINTF("Map: %d*%d=%uB\n", sizeof(uint16_t), (int)customMappingSize, customMappingSize*sizeof(uint16_t));
|
||||
if (useLedsArray) DEBUG_PRINTF("Buffer: %d*%d=%uB\n", sizeof(CRGB), (int)_length, _length*sizeof(CRGB));
|
||||
size = getLengthTotal();
|
||||
if (useLedsArray) DEBUG_PRINTF("Buffer: %d*%u=%uB\n", sizeof(CRGB), size, size*sizeof(CRGB));
|
||||
}
|
||||
#endif
|
||||
|
||||
void WS2812FX::loadCustomPalettes()
|
||||
{
|
||||
void WS2812FX::loadCustomPalettes() {
|
||||
byte tcp[72]; //support gradient palettes with up to 18 entries
|
||||
CRGBPalette16 targetPalette;
|
||||
customPalettes.clear(); // start fresh
|
||||
@ -1570,8 +1631,8 @@ void WS2812FX::loadCustomPalettes()
|
||||
}
|
||||
|
||||
//load custom mapping table from JSON file (called from finalizeInit() or deserializeState())
|
||||
void WS2812FX::deserializeMap(uint8_t n) {
|
||||
if (isMatrix) return; // 2D support creates its own ledmap
|
||||
bool WS2812FX::deserializeMap(uint8_t n) {
|
||||
// 2D support creates its own ledmap (on the fly) if a ledmap.json exists it will overwrite built one.
|
||||
|
||||
char fileName[32];
|
||||
strcpy_P(fileName, PSTR("/ledmap"));
|
||||
@ -1581,24 +1642,24 @@ void WS2812FX::deserializeMap(uint8_t n) {
|
||||
|
||||
if (!isFile) {
|
||||
// erase custom mapping if selecting nonexistent ledmap.json (n==0)
|
||||
if (!n && customMappingTable != nullptr) {
|
||||
if (!isMatrix && !n && customMappingTable != nullptr) {
|
||||
customMappingSize = 0;
|
||||
delete[] customMappingTable;
|
||||
customMappingTable = nullptr;
|
||||
}
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!requestJSONBufferLock(7)) return;
|
||||
|
||||
DEBUG_PRINT(F("Reading LED map from "));
|
||||
DEBUG_PRINTLN(fileName);
|
||||
if (!requestJSONBufferLock(7)) return false;
|
||||
|
||||
if (!readObjectFromFile(fileName, nullptr, &doc)) {
|
||||
releaseJSONBufferLock();
|
||||
return; //if file does not exist just exit
|
||||
return false; //if file does not exist just exit
|
||||
}
|
||||
|
||||
DEBUG_PRINT(F("Reading LED map from "));
|
||||
DEBUG_PRINTLN(fileName);
|
||||
|
||||
// erase old custom ledmap
|
||||
if (customMappingTable != nullptr) {
|
||||
customMappingSize = 0;
|
||||
@ -1611,21 +1672,17 @@ void WS2812FX::deserializeMap(uint8_t n) {
|
||||
customMappingSize = map.size();
|
||||
customMappingTable = new uint16_t[customMappingSize];
|
||||
for (uint16_t i=0; i<customMappingSize; i++) {
|
||||
customMappingTable[i] = (uint16_t) map[i];
|
||||
customMappingTable[i] = (uint16_t) (map[i]<0 ? 0xFFFFU : map[i]);
|
||||
}
|
||||
}
|
||||
|
||||
releaseJSONBufferLock();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
WS2812FX* WS2812FX::instance = nullptr;
|
||||
|
||||
//Bus static member definition, would belong in bus_manager.cpp
|
||||
int16_t Bus::_cct = -1;
|
||||
uint8_t Bus::_cctBlend = 0;
|
||||
uint8_t Bus::_gAWM = 255;
|
||||
|
||||
const char JSON_mode_names[] PROGMEM = R"=====(["FX names moved"])=====";
|
||||
const char JSON_palette_names[] PROGMEM = R"=====([
|
||||
"Default","* Random Cycle","* Color 1","* Colors 1&2","* Color Gradient","* Colors Only","Party","Cloud","Lava","Ocean",
|
||||
|
@ -1,99 +0,0 @@
|
||||
#include "wled.h"
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
#include "src/dependencies/blynk/Blynk/BlynkHandlers.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Remote light control with the free Blynk app
|
||||
*/
|
||||
|
||||
uint16_t blHue = 0;
|
||||
byte blSat = 255;
|
||||
|
||||
void initBlynk(const char *auth, const char *host, uint16_t port)
|
||||
{
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
if (!WLED_CONNECTED) return;
|
||||
blynkEnabled = (auth[0] != 0);
|
||||
if (blynkEnabled) Blynk.config(auth, host, port);
|
||||
#endif
|
||||
}
|
||||
|
||||
void handleBlynk()
|
||||
{
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
if (WLED_CONNECTED && blynkEnabled)
|
||||
Blynk.run();
|
||||
#endif
|
||||
}
|
||||
|
||||
void updateBlynk()
|
||||
{
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
if (!WLED_CONNECTED) return;
|
||||
Blynk.virtualWrite(V0, bri);
|
||||
//we need a RGB -> HSB convert here
|
||||
Blynk.virtualWrite(V3, bri? 1:0);
|
||||
Blynk.virtualWrite(V4, effectCurrent);
|
||||
Blynk.virtualWrite(V5, effectSpeed);
|
||||
Blynk.virtualWrite(V6, effectIntensity);
|
||||
Blynk.virtualWrite(V7, nightlightActive);
|
||||
Blynk.virtualWrite(V8, notifyDirect);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
BLYNK_WRITE(V0)
|
||||
{
|
||||
bri = param.asInt();//bri
|
||||
stateUpdated(CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V1)
|
||||
{
|
||||
blHue = param.asInt();//hue
|
||||
colorHStoRGB(blHue*10,blSat,col);
|
||||
colorUpdated(CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V2)
|
||||
{
|
||||
blSat = param.asInt();//sat
|
||||
colorHStoRGB(blHue*10,blSat,col);
|
||||
colorUpdated(CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V3)
|
||||
{
|
||||
bool on = (param.asInt()>0);
|
||||
if (!on != !bri) {toggleOnOff(); stateUpdated(CALL_MODE_BLYNK);}
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V4)
|
||||
{
|
||||
effectCurrent = param.asInt()-1;//fx
|
||||
colorUpdated(CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V5)
|
||||
{
|
||||
effectSpeed = param.asInt();//sx
|
||||
colorUpdated(CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V6)
|
||||
{
|
||||
effectIntensity = param.asInt();//ix
|
||||
colorUpdated(CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V7)
|
||||
{
|
||||
nightlightActive = (param.asInt()>0);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V8)
|
||||
{
|
||||
notifyDirect = (param.asInt()>0); //send notifications
|
||||
}
|
||||
#endif
|
562
wled00/bus_manager.cpp
Normal file
562
wled00/bus_manager.cpp
Normal file
@ -0,0 +1,562 @@
|
||||
/*
|
||||
* Class implementation for addressing various light types
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <IPAddress.h>
|
||||
#include "const.h"
|
||||
#include "pin_manager.h"
|
||||
#include "bus_wrapper.h"
|
||||
#include "bus_manager.h"
|
||||
|
||||
//colors.cpp
|
||||
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
|
||||
uint16_t approximateKelvinFromRGB(uint32_t rgb);
|
||||
void colorRGBtoRGBW(byte* rgb);
|
||||
|
||||
//udp.cpp
|
||||
uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte *buffer, uint8_t bri=255, bool isRGBW=false);
|
||||
|
||||
// enable additional debug output
|
||||
#if defined(WLED_DEBUG_HOST)
|
||||
#include "net_debug.h"
|
||||
#define DEBUGOUT NetDebug
|
||||
#else
|
||||
#define DEBUGOUT Serial
|
||||
#endif
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
#ifndef ESP8266
|
||||
#include <rom/rtc.h>
|
||||
#endif
|
||||
#define DEBUG_PRINT(x) DEBUGOUT.print(x)
|
||||
#define DEBUG_PRINTLN(x) DEBUGOUT.println(x)
|
||||
#define DEBUG_PRINTF(x...) DEBUGOUT.printf(x)
|
||||
#else
|
||||
#define DEBUG_PRINT(x)
|
||||
#define DEBUG_PRINTLN(x)
|
||||
#define DEBUG_PRINTF(x...)
|
||||
#endif
|
||||
|
||||
//color mangling macros
|
||||
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
|
||||
#define R(c) (byte((c) >> 16))
|
||||
#define G(c) (byte((c) >> 8))
|
||||
#define B(c) (byte(c))
|
||||
#define W(c) (byte((c) >> 24))
|
||||
|
||||
|
||||
void ColorOrderMap::add(uint16_t start, uint16_t len, uint8_t colorOrder) {
|
||||
if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) {
|
||||
return;
|
||||
}
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
if (colorOrder > COL_ORDER_MAX) {
|
||||
return;
|
||||
}
|
||||
_mappings[_count].start = start;
|
||||
_mappings[_count].len = len;
|
||||
_mappings[_count].colorOrder = colorOrder;
|
||||
_count++;
|
||||
}
|
||||
|
||||
uint8_t IRAM_ATTR ColorOrderMap::getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const {
|
||||
if (_count == 0) return defaultColorOrder;
|
||||
// upper nibble containd W swap information
|
||||
uint8_t swapW = defaultColorOrder >> 4;
|
||||
for (uint8_t i = 0; i < _count; i++) {
|
||||
if (pix >= _mappings[i].start && pix < (_mappings[i].start + _mappings[i].len)) {
|
||||
return _mappings[i].colorOrder | (swapW << 4);
|
||||
}
|
||||
}
|
||||
return defaultColorOrder;
|
||||
}
|
||||
|
||||
|
||||
uint32_t Bus::autoWhiteCalc(uint32_t c) {
|
||||
uint8_t aWM = _autoWhiteMode;
|
||||
if (_gAWM < 255) aWM = _gAWM;
|
||||
if (aWM == RGBW_MODE_MANUAL_ONLY) return c;
|
||||
uint8_t w = W(c);
|
||||
//ignore auto-white calculation if w>0 and mode DUAL (DUAL behaves as BRIGHTER if w==0)
|
||||
if (w > 0 && aWM == RGBW_MODE_DUAL) return c;
|
||||
uint8_t r = R(c);
|
||||
uint8_t g = G(c);
|
||||
uint8_t b = B(c);
|
||||
if (aWM == RGBW_MODE_MAX) return RGBW32(r, g, b, r > g ? (r > b ? r : b) : (g > b ? g : b)); // brightest RGB channel
|
||||
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||
if (aWM == RGBW_MODE_AUTO_ACCURATE) { r -= w; g -= w; b -= w; } //subtract w in ACCURATE mode
|
||||
return RGBW32(r, g, b, w);
|
||||
}
|
||||
|
||||
|
||||
BusDigital::BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com) : Bus(bc.type, bc.start, bc.autoWhite), _colorOrderMap(com) {
|
||||
if (!IS_DIGITAL(bc.type) || !bc.count) return;
|
||||
if (!pinManager.allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return;
|
||||
_pins[0] = bc.pins[0];
|
||||
if (IS_2PIN(bc.type)) {
|
||||
if (!pinManager.allocatePin(bc.pins[1], true, PinOwner::BusDigital)) {
|
||||
cleanup(); return;
|
||||
}
|
||||
_pins[1] = bc.pins[1];
|
||||
}
|
||||
reversed = bc.reversed;
|
||||
_needsRefresh = bc.refreshReq || bc.type == TYPE_TM1814;
|
||||
_skip = bc.skipAmount; //sacrificial pixels
|
||||
_len = bc.count + _skip;
|
||||
_iType = PolyBus::getI(bc.type, _pins, nr);
|
||||
if (_iType == I_NONE) return;
|
||||
uint16_t lenToCreate = _len;
|
||||
if (bc.type == TYPE_WS2812_1CH_X3) lenToCreate = NUM_ICS_WS2812_1CH_3X(_len); // only needs a third of "RGB" LEDs for NeoPixelBus
|
||||
_busPtr = PolyBus::create(_iType, _pins, lenToCreate, nr);
|
||||
_valid = (_busPtr != nullptr);
|
||||
_colorOrder = bc.colorOrder;
|
||||
DEBUG_PRINTF("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n", _valid?"S":"Uns", nr, _len, bc.type, _pins[0],_pins[1],_iType);
|
||||
}
|
||||
|
||||
void BusDigital::show() {
|
||||
PolyBus::show(_busPtr, _iType);
|
||||
}
|
||||
|
||||
bool BusDigital::canShow() {
|
||||
return PolyBus::canShow(_busPtr, _iType);
|
||||
}
|
||||
|
||||
void BusDigital::setBrightness(uint8_t b) {
|
||||
//Fix for turning off onboard LED breaking bus
|
||||
#ifdef LED_BUILTIN
|
||||
if (_bri == 0 && b > 0) {
|
||||
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) PolyBus::begin(_busPtr, _iType, _pins);
|
||||
}
|
||||
#endif
|
||||
Bus::setBrightness(b);
|
||||
PolyBus::setBrightness(_busPtr, _iType, b);
|
||||
}
|
||||
|
||||
//If LEDs are skipped, it is possible to use the first as a status LED.
|
||||
//TODO only show if no new show due in the next 50ms
|
||||
void BusDigital::setStatusPixel(uint32_t c) {
|
||||
if (_skip && canShow()) {
|
||||
PolyBus::setPixelColor(_busPtr, _iType, 0, c, _colorOrderMap.getPixelColorOrder(_start, _colorOrder));
|
||||
PolyBus::show(_busPtr, _iType);
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR BusDigital::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
if (_type == TYPE_SK6812_RGBW || _type == TYPE_TM1814 || _type == TYPE_WS2812_1CH_X3) c = autoWhiteCalc(c);
|
||||
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
||||
if (reversed) pix = _len - pix -1;
|
||||
else pix += _skip;
|
||||
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
||||
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs
|
||||
uint16_t pOld = pix;
|
||||
pix = IC_INDEX_WS2812_1CH_3X(pix);
|
||||
uint32_t cOld = PolyBus::getPixelColor(_busPtr, _iType, pix, co);
|
||||
switch (pOld % 3) { // change only the single channel (TODO: this can cause loss because of get/set)
|
||||
case 0: c = RGBW32(R(cOld), W(c) , B(cOld), 0); break;
|
||||
case 1: c = RGBW32(W(c) , G(cOld), B(cOld), 0); break;
|
||||
case 2: c = RGBW32(R(cOld), G(cOld), W(c) , 0); break;
|
||||
}
|
||||
}
|
||||
PolyBus::setPixelColor(_busPtr, _iType, pix, c, co);
|
||||
}
|
||||
|
||||
uint32_t BusDigital::getPixelColor(uint16_t pix) {
|
||||
if (reversed) pix = _len - pix -1;
|
||||
else pix += _skip;
|
||||
uint8_t co = _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder);
|
||||
if (_type == TYPE_WS2812_1CH_X3) { // map to correct IC, each controls 3 LEDs
|
||||
uint16_t pOld = pix;
|
||||
pix = IC_INDEX_WS2812_1CH_3X(pix);
|
||||
uint32_t c = PolyBus::getPixelColor(_busPtr, _iType, pix, co);
|
||||
switch (pOld % 3) { // get only the single channel
|
||||
case 0: c = RGBW32(G(c), G(c), G(c), G(c)); break;
|
||||
case 1: c = RGBW32(R(c), R(c), R(c), R(c)); break;
|
||||
case 2: c = RGBW32(B(c), B(c), B(c), B(c)); break;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
return PolyBus::getPixelColor(_busPtr, _iType, pix, co);
|
||||
}
|
||||
|
||||
uint8_t BusDigital::getPins(uint8_t* pinArray) {
|
||||
uint8_t numPins = IS_2PIN(_type) ? 2 : 1;
|
||||
for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i];
|
||||
return numPins;
|
||||
}
|
||||
|
||||
void BusDigital::setColorOrder(uint8_t colorOrder) {
|
||||
// upper nibble contains W swap information
|
||||
if ((colorOrder & 0x0F) > 5) return;
|
||||
_colorOrder = colorOrder;
|
||||
}
|
||||
|
||||
void BusDigital::reinit() {
|
||||
PolyBus::begin(_busPtr, _iType, _pins);
|
||||
}
|
||||
|
||||
void BusDigital::cleanup() {
|
||||
DEBUG_PRINTLN(F("Digital Cleanup."));
|
||||
PolyBus::cleanup(_busPtr, _iType);
|
||||
_iType = I_NONE;
|
||||
_valid = false;
|
||||
_busPtr = nullptr;
|
||||
pinManager.deallocatePin(_pins[1], PinOwner::BusDigital);
|
||||
pinManager.deallocatePin(_pins[0], PinOwner::BusDigital);
|
||||
}
|
||||
|
||||
|
||||
BusPwm::BusPwm(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
_valid = false;
|
||||
if (!IS_PWM(bc.type)) return;
|
||||
uint8_t numPins = NUM_PWM_PINS(bc.type);
|
||||
|
||||
#ifdef ESP8266
|
||||
analogWriteRange(255); //same range as one RGB channel
|
||||
analogWriteFreq(WLED_PWM_FREQ);
|
||||
#else
|
||||
_ledcStart = pinManager.allocateLedc(numPins);
|
||||
if (_ledcStart == 255) { //no more free LEDC channels
|
||||
deallocatePins(); return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint8_t i = 0; i < numPins; i++) {
|
||||
uint8_t currentPin = bc.pins[i];
|
||||
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusPwm)) {
|
||||
deallocatePins(); return;
|
||||
}
|
||||
_pins[i] = currentPin; //store only after allocatePin() succeeds
|
||||
#ifdef ESP8266
|
||||
pinMode(_pins[i], OUTPUT);
|
||||
#else
|
||||
ledcSetup(_ledcStart + i, WLED_PWM_FREQ, 8);
|
||||
ledcAttachPin(_pins[i], _ledcStart + i);
|
||||
#endif
|
||||
}
|
||||
reversed = bc.reversed;
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
if (pix != 0 || !_valid) return; //only react to first pixel
|
||||
if (_type != TYPE_ANALOG_3CH) c = autoWhiteCalc(c);
|
||||
if (_cct >= 1900 && (_type == TYPE_ANALOG_3CH || _type == TYPE_ANALOG_4CH)) {
|
||||
c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
||||
}
|
||||
uint8_t r = R(c);
|
||||
uint8_t g = G(c);
|
||||
uint8_t b = B(c);
|
||||
uint8_t w = W(c);
|
||||
uint8_t cct = 0; //0 - full warm white, 255 - full cold white
|
||||
if (_cct > -1) {
|
||||
if (_cct >= 1900) cct = (_cct - 1900) >> 5;
|
||||
else if (_cct < 256) cct = _cct;
|
||||
} else {
|
||||
cct = (approximateKelvinFromRGB(c) - 1900) >> 5;
|
||||
}
|
||||
|
||||
uint8_t ww, cw;
|
||||
#ifdef WLED_USE_IC_CCT
|
||||
ww = w;
|
||||
cw = cct;
|
||||
#else
|
||||
//0 - linear (CCT 127 = 50% warm, 50% cold), 127 - additive CCT blending (CCT 127 = 100% warm, 100% cold)
|
||||
if (cct < _cctBlend) ww = 255;
|
||||
else ww = ((255-cct) * 255) / (255 - _cctBlend);
|
||||
|
||||
if ((255-cct) < _cctBlend) cw = 255;
|
||||
else cw = (cct * 255) / (255 - _cctBlend);
|
||||
|
||||
ww = (w * ww) / 255; //brightness scaling
|
||||
cw = (w * cw) / 255;
|
||||
#endif
|
||||
|
||||
switch (_type) {
|
||||
case TYPE_ANALOG_1CH: //one channel (white), relies on auto white calculation
|
||||
_data[0] = w;
|
||||
break;
|
||||
case TYPE_ANALOG_2CH: //warm white + cold white
|
||||
_data[1] = cw;
|
||||
_data[0] = ww;
|
||||
break;
|
||||
case TYPE_ANALOG_5CH: //RGB + warm white + cold white
|
||||
_data[4] = cw;
|
||||
w = ww;
|
||||
case TYPE_ANALOG_4CH: //RGBW
|
||||
_data[3] = w;
|
||||
case TYPE_ANALOG_3CH: //standard dumb RGB
|
||||
_data[0] = r; _data[1] = g; _data[2] = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//does no index check
|
||||
uint32_t BusPwm::getPixelColor(uint16_t pix) {
|
||||
if (!_valid) return 0;
|
||||
return RGBW32(_data[0], _data[1], _data[2], _data[3]);
|
||||
}
|
||||
|
||||
void BusPwm::show() {
|
||||
if (!_valid) return;
|
||||
uint8_t numPins = NUM_PWM_PINS(_type);
|
||||
for (uint8_t i = 0; i < numPins; i++) {
|
||||
uint8_t scaled = (_data[i] * _bri) / 255;
|
||||
if (reversed) scaled = 255 - scaled;
|
||||
#ifdef ESP8266
|
||||
analogWrite(_pins[i], scaled);
|
||||
#else
|
||||
ledcWrite(_ledcStart + i, scaled);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t BusPwm::getPins(uint8_t* pinArray) {
|
||||
if (!_valid) return 0;
|
||||
uint8_t numPins = NUM_PWM_PINS(_type);
|
||||
for (uint8_t i = 0; i < numPins; i++) {
|
||||
pinArray[i] = _pins[i];
|
||||
}
|
||||
return numPins;
|
||||
}
|
||||
|
||||
void BusPwm::deallocatePins() {
|
||||
uint8_t numPins = NUM_PWM_PINS(_type);
|
||||
for (uint8_t i = 0; i < numPins; i++) {
|
||||
pinManager.deallocatePin(_pins[i], PinOwner::BusPwm);
|
||||
if (!pinManager.isPinOk(_pins[i])) continue;
|
||||
#ifdef ESP8266
|
||||
digitalWrite(_pins[i], LOW); //turn off PWM interrupt
|
||||
#else
|
||||
if (_ledcStart < 16) ledcDetachPin(_pins[i]);
|
||||
#endif
|
||||
}
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
pinManager.deallocateLedc(_ledcStart, numPins);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
BusOnOff::BusOnOff(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
_valid = false;
|
||||
if (bc.type != TYPE_ONOFF) return;
|
||||
|
||||
uint8_t currentPin = bc.pins[0];
|
||||
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusOnOff)) {
|
||||
return;
|
||||
}
|
||||
_pin = currentPin; //store only after allocatePin() succeeds
|
||||
pinMode(_pin, OUTPUT);
|
||||
reversed = bc.reversed;
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void BusOnOff::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
if (pix != 0 || !_valid) return; //only react to first pixel
|
||||
c = autoWhiteCalc(c);
|
||||
uint8_t r = R(c);
|
||||
uint8_t g = G(c);
|
||||
uint8_t b = B(c);
|
||||
uint8_t w = W(c);
|
||||
|
||||
_data = bool(r|g|b|w) && bool(_bri) ? 0xFF : 0;
|
||||
}
|
||||
|
||||
uint32_t BusOnOff::getPixelColor(uint16_t pix) {
|
||||
if (!_valid) return 0;
|
||||
return RGBW32(_data, _data, _data, _data);
|
||||
}
|
||||
|
||||
void BusOnOff::show() {
|
||||
if (!_valid) return;
|
||||
digitalWrite(_pin, reversed ? !(bool)_data : (bool)_data);
|
||||
}
|
||||
|
||||
uint8_t BusOnOff::getPins(uint8_t* pinArray) {
|
||||
if (!_valid) return 0;
|
||||
pinArray[0] = _pin;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
BusNetwork::BusNetwork(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
_valid = false;
|
||||
switch (bc.type) {
|
||||
case TYPE_NET_ARTNET_RGB:
|
||||
_rgbw = false;
|
||||
_UDPtype = 2;
|
||||
break;
|
||||
case TYPE_NET_E131_RGB:
|
||||
_rgbw = false;
|
||||
_UDPtype = 1;
|
||||
break;
|
||||
default: // TYPE_NET_DDP_RGB / TYPE_NET_DDP_RGBW
|
||||
_rgbw = bc.type == TYPE_NET_DDP_RGBW;
|
||||
_UDPtype = 0;
|
||||
break;
|
||||
}
|
||||
_UDPchannels = _rgbw ? 4 : 3;
|
||||
_data = (byte *)malloc(bc.count * _UDPchannels);
|
||||
if (_data == nullptr) return;
|
||||
memset(_data, 0, bc.count * _UDPchannels);
|
||||
_len = bc.count;
|
||||
_client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]);
|
||||
_broadcastLock = false;
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void BusNetwork::setPixelColor(uint16_t pix, uint32_t c) {
|
||||
if (!_valid || pix >= _len) return;
|
||||
if (hasWhite()) c = autoWhiteCalc(c);
|
||||
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
||||
uint16_t offset = pix * _UDPchannels;
|
||||
_data[offset] = R(c);
|
||||
_data[offset+1] = G(c);
|
||||
_data[offset+2] = B(c);
|
||||
if (_rgbw) _data[offset+3] = W(c);
|
||||
}
|
||||
|
||||
uint32_t BusNetwork::getPixelColor(uint16_t pix) {
|
||||
if (!_valid || pix >= _len) return 0;
|
||||
uint16_t offset = pix * _UDPchannels;
|
||||
return RGBW32(_data[offset], _data[offset+1], _data[offset+2], _rgbw ? (_data[offset+3] << 24) : 0);
|
||||
}
|
||||
|
||||
void BusNetwork::show() {
|
||||
if (!_valid || !canShow()) return;
|
||||
_broadcastLock = true;
|
||||
realtimeBroadcast(_UDPtype, _client, _len, _data, _bri, _rgbw);
|
||||
_broadcastLock = false;
|
||||
}
|
||||
|
||||
uint8_t BusNetwork::getPins(uint8_t* pinArray) {
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
pinArray[i] = _client[i];
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
void BusNetwork::cleanup() {
|
||||
_type = I_NONE;
|
||||
_valid = false;
|
||||
if (_data != nullptr) free(_data);
|
||||
_data = nullptr;
|
||||
}
|
||||
|
||||
|
||||
//utility to get the approx. memory usage of a given BusConfig
|
||||
uint32_t BusManager::memUsage(BusConfig &bc) {
|
||||
uint8_t type = bc.type;
|
||||
uint16_t len = bc.count + bc.skipAmount;
|
||||
if (type > 15 && type < 32) {
|
||||
#ifdef ESP8266
|
||||
if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem
|
||||
if (type > 29) return len*20; //RGBW
|
||||
return len*15;
|
||||
}
|
||||
if (type > 29) return len*4; //RGBW
|
||||
return len*3;
|
||||
#else //ESP32 RMT uses double buffer?
|
||||
if (type > 29) return len*8; //RGBW
|
||||
return len*6;
|
||||
#endif
|
||||
}
|
||||
if (type > 31 && type < 48) return 5;
|
||||
if (type == 44 || type == 45) return len*4; //RGBW
|
||||
return len*3; //RGB
|
||||
}
|
||||
|
||||
int BusManager::add(BusConfig &bc) {
|
||||
if (getNumBusses() - getNumVirtualBusses() >= WLED_MAX_BUSSES) return -1;
|
||||
if (bc.type >= TYPE_NET_DDP_RGB && bc.type < 96) {
|
||||
busses[numBusses] = new BusNetwork(bc);
|
||||
} else if (IS_DIGITAL(bc.type)) {
|
||||
busses[numBusses] = new BusDigital(bc, numBusses, colorOrderMap);
|
||||
} else if (bc.type == TYPE_ONOFF) {
|
||||
busses[numBusses] = new BusOnOff(bc);
|
||||
} else {
|
||||
busses[numBusses] = new BusPwm(bc);
|
||||
}
|
||||
return numBusses++;
|
||||
}
|
||||
|
||||
//do not call this method from system context (network callback)
|
||||
void BusManager::removeAll() {
|
||||
DEBUG_PRINTLN(F("Removing all."));
|
||||
//prevents crashes due to deleting busses while in use.
|
||||
while (!canAllShow()) yield();
|
||||
for (uint8_t i = 0; i < numBusses; i++) delete busses[i];
|
||||
numBusses = 0;
|
||||
}
|
||||
|
||||
void BusManager::show() {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
busses[i]->show();
|
||||
}
|
||||
}
|
||||
|
||||
void BusManager::setStatusPixel(uint32_t c) {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
busses[i]->setStatusPixel(c);
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR BusManager::setPixelColor(uint16_t pix, uint32_t c, int16_t cct) {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
Bus* b = busses[i];
|
||||
uint16_t bstart = b->getStart();
|
||||
if (pix < bstart || pix >= bstart + b->getLength()) continue;
|
||||
busses[i]->setPixelColor(pix - bstart, c);
|
||||
}
|
||||
}
|
||||
|
||||
void BusManager::setBrightness(uint8_t b) {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
busses[i]->setBrightness(b);
|
||||
}
|
||||
}
|
||||
|
||||
void BusManager::setSegmentCCT(int16_t cct, bool allowWBCorrection) {
|
||||
if (cct > 255) cct = 255;
|
||||
if (cct >= 0) {
|
||||
//if white balance correction allowed, save as kelvin value instead of 0-255
|
||||
if (allowWBCorrection) cct = 1900 + (cct << 5);
|
||||
} else cct = -1;
|
||||
Bus::setCCT(cct);
|
||||
}
|
||||
|
||||
uint32_t BusManager::getPixelColor(uint16_t pix) {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
Bus* b = busses[i];
|
||||
uint16_t bstart = b->getStart();
|
||||
if (pix < bstart || pix >= bstart + b->getLength()) continue;
|
||||
return b->getPixelColor(pix - bstart);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool BusManager::canAllShow() {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
if (!busses[i]->canShow()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Bus* BusManager::getBus(uint8_t busNr) {
|
||||
if (busNr >= numBusses) return nullptr;
|
||||
return busses[busNr];
|
||||
}
|
||||
|
||||
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
|
||||
uint16_t BusManager::getTotalLength() {
|
||||
uint16_t len = 0;
|
||||
for (uint8_t i=0; i<numBusses; i++) len += busses[i]->getLength();
|
||||
return len;
|
||||
}
|
||||
|
||||
// Bus static member definition
|
||||
int16_t Bus::_cct = -1;
|
||||
uint8_t Bus::_cctBlend = 0;
|
||||
uint8_t Bus::_gAWM = 255;
|
@ -6,44 +6,17 @@
|
||||
*/
|
||||
|
||||
#include "const.h"
|
||||
#include "pin_manager.h"
|
||||
#include "bus_wrapper.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
//colors.cpp
|
||||
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb);
|
||||
void colorRGBtoRGBW(byte* rgb);
|
||||
|
||||
// enable additional debug output
|
||||
#if defined(WLED_DEBUG_HOST)
|
||||
#define DEBUGOUT NetDebug
|
||||
#else
|
||||
#define DEBUGOUT Serial
|
||||
#endif
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
#ifndef ESP8266
|
||||
#include <rom/rtc.h>
|
||||
#endif
|
||||
#define DEBUG_PRINT(x) DEBUGOUT.print(x)
|
||||
#define DEBUG_PRINTLN(x) DEBUGOUT.println(x)
|
||||
#define DEBUG_PRINTF(x...) DEBUGOUT.printf(x)
|
||||
#else
|
||||
#define DEBUG_PRINT(x)
|
||||
#define DEBUG_PRINTLN(x)
|
||||
#define DEBUG_PRINTF(x...)
|
||||
#endif
|
||||
|
||||
#define GET_BIT(var,bit) (((var)>>(bit))&0x01)
|
||||
#define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit)))
|
||||
#define UNSET_BIT(var,bit) ((var)&=(~(uint16_t)(0x0001<<(bit))))
|
||||
|
||||
//color mangling macros
|
||||
#define RGBW32(r,g,b,w) (uint32_t((byte(w) << 24) | (byte(r) << 16) | (byte(g) << 8) | (byte(b))))
|
||||
#define R(c) (byte((c) >> 16))
|
||||
#define G(c) (byte((c) >> 8))
|
||||
#define B(c) (byte(c))
|
||||
#define W(c) (byte((c) >> 24))
|
||||
#define NUM_ICS_WS2812_1CH_3X(len) (((len)+2)/3) // 1 WS2811 IC controls 3 zones (each zone has 1 LED, W)
|
||||
#define IC_INDEX_WS2812_1CH_3X(i) ((i)/3)
|
||||
|
||||
#define NUM_ICS_WS2812_2CH_3X(len) (((len)+1)*2/3) // 2 WS2811 ICs control 3 zones (each zone has 2 LEDs, CW and WW)
|
||||
#define IC_INDEX_WS2812_2CH_3X(i) ((i)*2/3)
|
||||
#define WS2812_2CH_3X_SPANS_2_ICS(i) ((i)&0x01) // every other LED zone is on two different ICs
|
||||
|
||||
//temporary struct for passing bus configuration to bus
|
||||
struct BusConfig {
|
||||
@ -88,53 +61,29 @@ struct ColorOrderMapEntry {
|
||||
};
|
||||
|
||||
struct ColorOrderMap {
|
||||
void add(uint16_t start, uint16_t len, uint8_t colorOrder) {
|
||||
if (_count >= WLED_MAX_COLOR_ORDER_MAPPINGS) {
|
||||
return;
|
||||
}
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
if (colorOrder > COL_ORDER_MAX) {
|
||||
return;
|
||||
}
|
||||
_mappings[_count].start = start;
|
||||
_mappings[_count].len = len;
|
||||
_mappings[_count].colorOrder = colorOrder;
|
||||
_count++;
|
||||
}
|
||||
void add(uint16_t start, uint16_t len, uint8_t colorOrder);
|
||||
|
||||
uint8_t count() const {
|
||||
return _count;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
_count = 0;
|
||||
memset(_mappings, 0, sizeof(_mappings));
|
||||
}
|
||||
|
||||
const ColorOrderMapEntry* get(uint8_t n) const {
|
||||
if (n > _count) {
|
||||
return nullptr;
|
||||
uint8_t count() const {
|
||||
return _count;
|
||||
}
|
||||
return &(_mappings[n]);
|
||||
}
|
||||
|
||||
inline uint8_t IRAM_ATTR getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const {
|
||||
if (_count == 0) return defaultColorOrder;
|
||||
// upper nibble containd W swap information
|
||||
uint8_t swapW = defaultColorOrder >> 4;
|
||||
for (uint8_t i = 0; i < _count; i++) {
|
||||
if (pix >= _mappings[i].start && pix < (_mappings[i].start + _mappings[i].len)) {
|
||||
return _mappings[i].colorOrder | (swapW << 4);
|
||||
void reset() {
|
||||
_count = 0;
|
||||
memset(_mappings, 0, sizeof(_mappings));
|
||||
}
|
||||
|
||||
const ColorOrderMapEntry* get(uint8_t n) const {
|
||||
if (n > _count) {
|
||||
return nullptr;
|
||||
}
|
||||
return &(_mappings[n]);
|
||||
}
|
||||
return defaultColorOrder;
|
||||
}
|
||||
|
||||
uint8_t getPixelColorOrder(uint16_t pix, uint8_t defaultColorOrder) const;
|
||||
|
||||
private:
|
||||
uint8_t _count;
|
||||
ColorOrderMapEntry _mappings[WLED_MAX_COLOR_ORDER_MAPPINGS];
|
||||
uint8_t _count;
|
||||
ColorOrderMapEntry _mappings[WLED_MAX_COLOR_ORDER_MAPPINGS];
|
||||
};
|
||||
|
||||
//parent class of BusDigital, BusPwm, and BusNetwork
|
||||
@ -148,7 +97,7 @@ class Bus {
|
||||
{
|
||||
_type = type;
|
||||
_start = start;
|
||||
_autoWhiteMode = Bus::isRgbw(_type) ? aw : RGBW_MODE_MANUAL_ONLY;
|
||||
_autoWhiteMode = Bus::hasWhite(_type) ? aw : RGBW_MODE_MANUAL_ONLY;
|
||||
};
|
||||
|
||||
virtual ~Bus() {} //throw the bus under the bus
|
||||
@ -172,37 +121,37 @@ class Bus {
|
||||
inline bool isOffRefreshRequired() { return _needsRefresh; }
|
||||
bool containsPixel(uint16_t pix) { return pix >= _start && pix < _start+_len; }
|
||||
|
||||
virtual bool isRgbw() { return Bus::isRgbw(_type); }
|
||||
static bool isRgbw(uint8_t type) {
|
||||
if (type == TYPE_SK6812_RGBW || type == TYPE_TM1814) return true;
|
||||
if (type > TYPE_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true;
|
||||
if (type == TYPE_NET_DDP_RGBW) return true;
|
||||
return false;
|
||||
}
|
||||
virtual bool hasRGB() {
|
||||
if (_type == TYPE_WS2812_1CH || _type == TYPE_WS2812_WWA || _type == TYPE_ANALOG_1CH || _type == TYPE_ANALOG_2CH || _type == TYPE_ONOFF) return false;
|
||||
if ((_type >= TYPE_WS2812_1CH && _type <= TYPE_WS2812_WWA) || _type == TYPE_ANALOG_1CH || _type == TYPE_ANALOG_2CH || _type == TYPE_ONOFF) return false;
|
||||
return true;
|
||||
}
|
||||
virtual bool hasWhite() {
|
||||
if (_type == TYPE_SK6812_RGBW || _type == TYPE_TM1814 || _type == TYPE_WS2812_1CH || _type == TYPE_WS2812_WWA ||
|
||||
_type == TYPE_ANALOG_1CH || _type == TYPE_ANALOG_2CH || _type == TYPE_ANALOG_4CH || _type == TYPE_ANALOG_5CH || _type == TYPE_NET_DDP_RGBW) return true;
|
||||
virtual bool hasWhite() { return Bus::hasWhite(_type); }
|
||||
static bool hasWhite(uint8_t type) {
|
||||
if ((type >= TYPE_WS2812_1CH && type <= TYPE_WS2812_WWA) || type == TYPE_SK6812_RGBW || type == TYPE_TM1814) return true; // digital types with white channel
|
||||
if (type > TYPE_ONOFF && type <= TYPE_ANALOG_5CH && type != TYPE_ANALOG_3CH) return true; // analog types with white channel
|
||||
if (type == TYPE_NET_DDP_RGBW) return true; // network types with white channel
|
||||
return false;
|
||||
}
|
||||
virtual bool hasCCT() {
|
||||
if (_type == TYPE_WS2812_2CH_X3 || _type == TYPE_WS2812_WWA ||
|
||||
_type == TYPE_ANALOG_2CH || _type == TYPE_ANALOG_5CH) return true;
|
||||
return false;
|
||||
}
|
||||
static void setCCT(uint16_t cct) {
|
||||
_cct = cct;
|
||||
}
|
||||
static void setCCTBlend(uint8_t b) {
|
||||
if (b > 100) b = 100;
|
||||
_cctBlend = (b * 127) / 100;
|
||||
//compile-time limiter for hardware that can't power both white channels at max
|
||||
#ifdef WLED_MAX_CCT_BLEND
|
||||
if (_cctBlend > WLED_MAX_CCT_BLEND) _cctBlend = WLED_MAX_CCT_BLEND;
|
||||
#endif
|
||||
}
|
||||
inline void setAWMode(uint8_t m) { if (m < 4) _autoWhiteMode = m; }
|
||||
inline uint8_t getAWMode() { return _autoWhiteMode; }
|
||||
inline static void setAutoWhiteMode(uint8_t m) { if (m < 4) _gAWM = m; else _gAWM = 255; }
|
||||
inline static uint8_t getAutoWhiteMode() { return _gAWM; }
|
||||
static void setCCTBlend(uint8_t b) {
|
||||
if (b > 100) b = 100;
|
||||
_cctBlend = (b * 127) / 100;
|
||||
//compile-time limiter for hardware that can't power both white channels at max
|
||||
#ifdef WLED_MAX_CCT_BLEND
|
||||
if (_cctBlend > WLED_MAX_CCT_BLEND) _cctBlend = WLED_MAX_CCT_BLEND;
|
||||
#endif
|
||||
}
|
||||
inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; }
|
||||
inline uint8_t getAutoWhiteMode() { return _autoWhiteMode; }
|
||||
inline static void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; }
|
||||
inline static uint8_t getGlobalAWMode() { return _gAWM; }
|
||||
|
||||
bool reversed = false;
|
||||
|
||||
@ -214,440 +163,151 @@ class Bus {
|
||||
bool _valid;
|
||||
bool _needsRefresh;
|
||||
uint8_t _autoWhiteMode;
|
||||
static uint8_t _gAWM; // definition in FX_fcn.cpp
|
||||
static int16_t _cct; // definition in FX_fcn.cpp
|
||||
static uint8_t _cctBlend; // definition in FX_fcn.cpp
|
||||
static uint8_t _gAWM;
|
||||
static int16_t _cct;
|
||||
static uint8_t _cctBlend;
|
||||
|
||||
uint32_t autoWhiteCalc(uint32_t c) {
|
||||
uint8_t aWM = _autoWhiteMode;
|
||||
if (_gAWM < 255) aWM = _gAWM;
|
||||
if (aWM == RGBW_MODE_MANUAL_ONLY) return c;
|
||||
uint8_t w = W(c);
|
||||
//ignore auto-white calculation if w>0 and mode DUAL (DUAL behaves as BRIGHTER if w==0)
|
||||
if (w > 0 && aWM == RGBW_MODE_DUAL) return c;
|
||||
uint8_t r = R(c);
|
||||
uint8_t g = G(c);
|
||||
uint8_t b = B(c);
|
||||
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||
if (aWM == RGBW_MODE_AUTO_ACCURATE) { r -= w; g -= w; b -= w; } //subtract w in ACCURATE mode
|
||||
return RGBW32(r, g, b, w);
|
||||
}
|
||||
uint32_t autoWhiteCalc(uint32_t c);
|
||||
};
|
||||
|
||||
|
||||
class BusDigital : public Bus {
|
||||
public:
|
||||
BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com) : Bus(bc.type, bc.start, bc.autoWhite), _colorOrderMap(com) {
|
||||
if (!IS_DIGITAL(bc.type) || !bc.count) return;
|
||||
if (!pinManager.allocatePin(bc.pins[0], true, PinOwner::BusDigital)) return;
|
||||
_pins[0] = bc.pins[0];
|
||||
if (IS_2PIN(bc.type)) {
|
||||
if (!pinManager.allocatePin(bc.pins[1], true, PinOwner::BusDigital)) {
|
||||
cleanup(); return;
|
||||
}
|
||||
_pins[1] = bc.pins[1];
|
||||
BusDigital(BusConfig &bc, uint8_t nr, const ColorOrderMap &com);
|
||||
|
||||
inline void show();
|
||||
|
||||
bool canShow();
|
||||
|
||||
void setBrightness(uint8_t b);
|
||||
|
||||
void setStatusPixel(uint32_t c);
|
||||
|
||||
void setPixelColor(uint16_t pix, uint32_t c);
|
||||
|
||||
uint32_t getPixelColor(uint16_t pix);
|
||||
|
||||
uint8_t getColorOrder() {
|
||||
return _colorOrder;
|
||||
}
|
||||
reversed = bc.reversed;
|
||||
_needsRefresh = bc.refreshReq || bc.type == TYPE_TM1814;
|
||||
_skip = bc.skipAmount; //sacrificial pixels
|
||||
_len = bc.count + _skip;
|
||||
_iType = PolyBus::getI(bc.type, _pins, nr);
|
||||
if (_iType == I_NONE) return;
|
||||
_busPtr = PolyBus::create(_iType, _pins, _len, nr);
|
||||
_valid = (_busPtr != nullptr);
|
||||
_colorOrder = bc.colorOrder;
|
||||
DEBUG_PRINTF("%successfully inited strip %u (len %u) with type %u and pins %u,%u (itype %u)\n", _valid?"S":"Uns", nr, _len, bc.type, _pins[0],_pins[1],_iType);
|
||||
};
|
||||
|
||||
inline void show() {
|
||||
PolyBus::show(_busPtr, _iType);
|
||||
}
|
||||
|
||||
inline bool canShow() {
|
||||
return PolyBus::canShow(_busPtr, _iType);
|
||||
}
|
||||
|
||||
void setBrightness(uint8_t b) {
|
||||
//Fix for turning off onboard LED breaking bus
|
||||
#ifdef LED_BUILTIN
|
||||
if (_bri == 0 && b > 0) {
|
||||
if (_pins[0] == LED_BUILTIN || _pins[1] == LED_BUILTIN) PolyBus::begin(_busPtr, _iType, _pins);
|
||||
uint16_t getLength() {
|
||||
return _len - _skip;
|
||||
}
|
||||
#endif
|
||||
Bus::setBrightness(b);
|
||||
PolyBus::setBrightness(_busPtr, _iType, b);
|
||||
}
|
||||
|
||||
//If LEDs are skipped, it is possible to use the first as a status LED.
|
||||
//TODO only show if no new show due in the next 50ms
|
||||
void setStatusPixel(uint32_t c) {
|
||||
if (_skip && canShow()) {
|
||||
PolyBus::setPixelColor(_busPtr, _iType, 0, c, _colorOrderMap.getPixelColorOrder(_start, _colorOrder));
|
||||
PolyBus::show(_busPtr, _iType);
|
||||
uint8_t getPins(uint8_t* pinArray);
|
||||
|
||||
void setColorOrder(uint8_t colorOrder);
|
||||
|
||||
uint8_t skippedLeds() {
|
||||
return _skip;
|
||||
}
|
||||
}
|
||||
|
||||
void setPixelColor(uint16_t pix, uint32_t c) {
|
||||
if (_type == TYPE_SK6812_RGBW || _type == TYPE_TM1814) c = autoWhiteCalc(c);
|
||||
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
||||
if (reversed) pix = _len - pix -1;
|
||||
else pix += _skip;
|
||||
PolyBus::setPixelColor(_busPtr, _iType, pix, c, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder));
|
||||
}
|
||||
void reinit();
|
||||
|
||||
uint32_t getPixelColor(uint16_t pix) {
|
||||
if (reversed) pix = _len - pix -1;
|
||||
else pix += _skip;
|
||||
return PolyBus::getPixelColor(_busPtr, _iType, pix, _colorOrderMap.getPixelColorOrder(pix+_start, _colorOrder));
|
||||
}
|
||||
void cleanup();
|
||||
|
||||
inline uint8_t getColorOrder() {
|
||||
return _colorOrder;
|
||||
}
|
||||
|
||||
uint16_t getLength() {
|
||||
return _len - _skip;
|
||||
}
|
||||
|
||||
uint8_t getPins(uint8_t* pinArray) {
|
||||
uint8_t numPins = IS_2PIN(_type) ? 2 : 1;
|
||||
for (uint8_t i = 0; i < numPins; i++) pinArray[i] = _pins[i];
|
||||
return numPins;
|
||||
}
|
||||
|
||||
void setColorOrder(uint8_t colorOrder) {
|
||||
// upper nibble contains W swap information
|
||||
if ((colorOrder & 0x0F) > 5) return;
|
||||
_colorOrder = colorOrder;
|
||||
}
|
||||
|
||||
inline uint8_t skippedLeds() {
|
||||
return _skip;
|
||||
}
|
||||
|
||||
inline void reinit() {
|
||||
PolyBus::begin(_busPtr, _iType, _pins);
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
DEBUG_PRINTLN(F("Digital Cleanup."));
|
||||
PolyBus::cleanup(_busPtr, _iType);
|
||||
_iType = I_NONE;
|
||||
_valid = false;
|
||||
_busPtr = nullptr;
|
||||
pinManager.deallocatePin(_pins[1], PinOwner::BusDigital);
|
||||
pinManager.deallocatePin(_pins[0], PinOwner::BusDigital);
|
||||
}
|
||||
|
||||
~BusDigital() {
|
||||
cleanup();
|
||||
}
|
||||
~BusDigital() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t _colorOrder = COL_ORDER_GRB;
|
||||
uint8_t _pins[2] = {255, 255};
|
||||
uint8_t _iType = I_NONE;
|
||||
uint8_t _skip = 0;
|
||||
void * _busPtr = nullptr;
|
||||
const ColorOrderMap &_colorOrderMap;
|
||||
uint8_t _colorOrder = COL_ORDER_GRB;
|
||||
uint8_t _pins[2] = {255, 255};
|
||||
uint8_t _iType = 0; //I_NONE;
|
||||
uint8_t _skip = 0;
|
||||
void * _busPtr = nullptr;
|
||||
const ColorOrderMap &_colorOrderMap;
|
||||
};
|
||||
|
||||
|
||||
class BusPwm : public Bus {
|
||||
public:
|
||||
BusPwm(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
_valid = false;
|
||||
if (!IS_PWM(bc.type)) return;
|
||||
uint8_t numPins = NUM_PWM_PINS(bc.type);
|
||||
BusPwm(BusConfig &bc);
|
||||
|
||||
#ifdef ESP8266
|
||||
analogWriteRange(255); //same range as one RGB channel
|
||||
analogWriteFreq(WLED_PWM_FREQ);
|
||||
#else
|
||||
_ledcStart = pinManager.allocateLedc(numPins);
|
||||
if (_ledcStart == 255) { //no more free LEDC channels
|
||||
deallocatePins(); return;
|
||||
}
|
||||
#endif
|
||||
void setPixelColor(uint16_t pix, uint32_t c);
|
||||
|
||||
for (uint8_t i = 0; i < numPins; i++) {
|
||||
uint8_t currentPin = bc.pins[i];
|
||||
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusPwm)) {
|
||||
deallocatePins(); return;
|
||||
}
|
||||
_pins[i] = currentPin; //store only after allocatePin() succeeds
|
||||
#ifdef ESP8266
|
||||
pinMode(_pins[i], OUTPUT);
|
||||
#else
|
||||
ledcSetup(_ledcStart + i, WLED_PWM_FREQ, 8);
|
||||
ledcAttachPin(_pins[i], _ledcStart + i);
|
||||
#endif
|
||||
}
|
||||
reversed = bc.reversed;
|
||||
_valid = true;
|
||||
};
|
||||
//does no index check
|
||||
uint32_t getPixelColor(uint16_t pix);
|
||||
|
||||
void setPixelColor(uint16_t pix, uint32_t c) {
|
||||
if (pix != 0 || !_valid) return; //only react to first pixel
|
||||
if (_type != TYPE_ANALOG_3CH) c = autoWhiteCalc(c);
|
||||
if (_cct >= 1900 && (_type == TYPE_ANALOG_3CH || _type == TYPE_ANALOG_4CH)) {
|
||||
c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
||||
}
|
||||
uint8_t r = R(c);
|
||||
uint8_t g = G(c);
|
||||
uint8_t b = B(c);
|
||||
uint8_t w = W(c);
|
||||
uint8_t cct = 0; //0 - full warm white, 255 - full cold white
|
||||
if (_cct > -1) {
|
||||
if (_cct >= 1900) cct = (_cct - 1900) >> 5;
|
||||
else if (_cct < 256) cct = _cct;
|
||||
} else {
|
||||
cct = (approximateKelvinFromRGB(c) - 1900) >> 5;
|
||||
void show();
|
||||
|
||||
uint8_t getPins(uint8_t* pinArray);
|
||||
|
||||
void cleanup() {
|
||||
deallocatePins();
|
||||
}
|
||||
|
||||
uint8_t ww, cw;
|
||||
#ifdef WLED_USE_IC_CCT
|
||||
ww = w;
|
||||
cw = cct;
|
||||
#else
|
||||
//0 - linear (CCT 127 = 50% warm, 50% cold), 127 - additive CCT blending (CCT 127 = 100% warm, 100% cold)
|
||||
if (cct < _cctBlend) ww = 255;
|
||||
else ww = ((255-cct) * 255) / (255 - _cctBlend);
|
||||
|
||||
if ((255-cct) < _cctBlend) cw = 255;
|
||||
else cw = (cct * 255) / (255 - _cctBlend);
|
||||
|
||||
ww = (w * ww) / 255; //brightness scaling
|
||||
cw = (w * cw) / 255;
|
||||
#endif
|
||||
|
||||
switch (_type) {
|
||||
case TYPE_ANALOG_1CH: //one channel (white), relies on auto white calculation
|
||||
_data[0] = w;
|
||||
break;
|
||||
case TYPE_ANALOG_2CH: //warm white + cold white
|
||||
_data[1] = cw;
|
||||
_data[0] = ww;
|
||||
break;
|
||||
case TYPE_ANALOG_5CH: //RGB + warm white + cold white
|
||||
_data[4] = cw;
|
||||
w = ww;
|
||||
case TYPE_ANALOG_4CH: //RGBW
|
||||
_data[3] = w;
|
||||
case TYPE_ANALOG_3CH: //standard dumb RGB
|
||||
_data[0] = r; _data[1] = g; _data[2] = b;
|
||||
break;
|
||||
~BusPwm() {
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
//does no index check
|
||||
uint32_t getPixelColor(uint16_t pix) {
|
||||
if (!_valid) return 0;
|
||||
return RGBW32(_data[0], _data[1], _data[2], _data[3]);
|
||||
}
|
||||
|
||||
void show() {
|
||||
if (!_valid) return;
|
||||
uint8_t numPins = NUM_PWM_PINS(_type);
|
||||
for (uint8_t i = 0; i < numPins; i++) {
|
||||
uint8_t scaled = (_data[i] * _bri) / 255;
|
||||
if (reversed) scaled = 255 - scaled;
|
||||
#ifdef ESP8266
|
||||
analogWrite(_pins[i], scaled);
|
||||
#else
|
||||
ledcWrite(_ledcStart + i, scaled);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t getPins(uint8_t* pinArray) {
|
||||
if (!_valid) return 0;
|
||||
uint8_t numPins = NUM_PWM_PINS(_type);
|
||||
for (uint8_t i = 0; i < numPins; i++) {
|
||||
pinArray[i] = _pins[i];
|
||||
}
|
||||
return numPins;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
deallocatePins();
|
||||
}
|
||||
|
||||
~BusPwm() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t _pins[5] = {255, 255, 255, 255, 255};
|
||||
uint8_t _data[5] = {0};
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
uint8_t _ledcStart = 255;
|
||||
#endif
|
||||
|
||||
void deallocatePins() {
|
||||
uint8_t numPins = NUM_PWM_PINS(_type);
|
||||
for (uint8_t i = 0; i < numPins; i++) {
|
||||
pinManager.deallocatePin(_pins[i], PinOwner::BusPwm);
|
||||
if (!pinManager.isPinOk(_pins[i])) continue;
|
||||
#ifdef ESP8266
|
||||
digitalWrite(_pins[i], LOW); //turn off PWM interrupt
|
||||
#else
|
||||
if (_ledcStart < 16) ledcDetachPin(_pins[i]);
|
||||
#endif
|
||||
}
|
||||
uint8_t _pins[5] = {255, 255, 255, 255, 255};
|
||||
uint8_t _data[5] = {0};
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
pinManager.deallocateLedc(_ledcStart, numPins);
|
||||
uint8_t _ledcStart = 255;
|
||||
#endif
|
||||
}
|
||||
|
||||
void deallocatePins();
|
||||
};
|
||||
|
||||
|
||||
class BusOnOff : public Bus {
|
||||
public:
|
||||
BusOnOff(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
_valid = false;
|
||||
if (bc.type != TYPE_ONOFF) return;
|
||||
BusOnOff(BusConfig &bc);
|
||||
|
||||
uint8_t currentPin = bc.pins[0];
|
||||
if (!pinManager.allocatePin(currentPin, true, PinOwner::BusOnOff)) {
|
||||
return;
|
||||
void setPixelColor(uint16_t pix, uint32_t c);
|
||||
|
||||
uint32_t getPixelColor(uint16_t pix);
|
||||
|
||||
void show();
|
||||
|
||||
uint8_t getPins(uint8_t* pinArray);
|
||||
|
||||
void cleanup() {
|
||||
pinManager.deallocatePin(_pin, PinOwner::BusOnOff);
|
||||
}
|
||||
_pin = currentPin; //store only after allocatePin() succeeds
|
||||
pinMode(_pin, OUTPUT);
|
||||
reversed = bc.reversed;
|
||||
_valid = true;
|
||||
};
|
||||
|
||||
void setPixelColor(uint16_t pix, uint32_t c) {
|
||||
if (pix != 0 || !_valid) return; //only react to first pixel
|
||||
c = autoWhiteCalc(c);
|
||||
uint8_t r = R(c);
|
||||
uint8_t g = G(c);
|
||||
uint8_t b = B(c);
|
||||
uint8_t w = W(c);
|
||||
|
||||
_data = bool((r+g+b+w) && _bri) ? 0xFF : 0;
|
||||
}
|
||||
|
||||
uint32_t getPixelColor(uint16_t pix) {
|
||||
if (!_valid) return 0;
|
||||
return RGBW32(_data, _data, _data, _data);
|
||||
}
|
||||
|
||||
void show() {
|
||||
if (!_valid) return;
|
||||
digitalWrite(_pin, reversed ? !(bool)_data : (bool)_data);
|
||||
}
|
||||
|
||||
uint8_t getPins(uint8_t* pinArray) {
|
||||
if (!_valid) return 0;
|
||||
pinArray[0] = _pin;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
pinManager.deallocatePin(_pin, PinOwner::BusOnOff);
|
||||
}
|
||||
|
||||
~BusOnOff() {
|
||||
cleanup();
|
||||
}
|
||||
~BusOnOff() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t _pin = 255;
|
||||
uint8_t _data = 0;
|
||||
uint8_t _pin = 255;
|
||||
uint8_t _data = 0;
|
||||
};
|
||||
|
||||
|
||||
class BusNetwork : public Bus {
|
||||
public:
|
||||
BusNetwork(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) {
|
||||
_valid = false;
|
||||
// switch (bc.type) {
|
||||
// case TYPE_NET_ARTNET_RGB:
|
||||
// _rgbw = false;
|
||||
// _UDPtype = 2;
|
||||
// break;
|
||||
// case TYPE_NET_E131_RGB:
|
||||
// _rgbw = false;
|
||||
// _UDPtype = 1;
|
||||
// break;
|
||||
// case TYPE_NET_DDP_RGB:
|
||||
// _rgbw = false;
|
||||
// _UDPtype = 0;
|
||||
// break;
|
||||
// default: // TYPE_NET_DDP_RGB / TYPE_NET_DDP_RGBW
|
||||
_rgbw = bc.type == TYPE_NET_DDP_RGBW;
|
||||
_UDPtype = 0;
|
||||
// break;
|
||||
// }
|
||||
_UDPchannels = _rgbw ? 4 : 3;
|
||||
_data = (byte *)malloc(bc.count * _UDPchannels);
|
||||
if (_data == nullptr) return;
|
||||
memset(_data, 0, bc.count * _UDPchannels);
|
||||
_len = bc.count;
|
||||
_client = IPAddress(bc.pins[0],bc.pins[1],bc.pins[2],bc.pins[3]);
|
||||
_broadcastLock = false;
|
||||
_valid = true;
|
||||
};
|
||||
BusNetwork(BusConfig &bc);
|
||||
|
||||
bool hasRGB() { return true; }
|
||||
bool hasWhite() { return _rgbw; }
|
||||
bool hasRGB() { return true; }
|
||||
bool hasWhite() { return _rgbw; }
|
||||
|
||||
void setPixelColor(uint16_t pix, uint32_t c) {
|
||||
if (!_valid || pix >= _len) return;
|
||||
if (isRgbw()) c = autoWhiteCalc(c);
|
||||
if (_cct >= 1900) c = colorBalanceFromKelvin(_cct, c); //color correction from CCT
|
||||
uint16_t offset = pix * _UDPchannels;
|
||||
_data[offset] = R(c);
|
||||
_data[offset+1] = G(c);
|
||||
_data[offset+2] = B(c);
|
||||
if (_rgbw) _data[offset+3] = W(c);
|
||||
}
|
||||
void setPixelColor(uint16_t pix, uint32_t c);
|
||||
|
||||
uint32_t getPixelColor(uint16_t pix) {
|
||||
if (!_valid || pix >= _len) return 0;
|
||||
uint16_t offset = pix * _UDPchannels;
|
||||
return RGBW32(_data[offset], _data[offset+1], _data[offset+2], _rgbw ? (_data[offset+3] << 24) : 0);
|
||||
}
|
||||
uint32_t getPixelColor(uint16_t pix);
|
||||
|
||||
void show() {
|
||||
if (!_valid || !canShow()) return;
|
||||
_broadcastLock = true;
|
||||
realtimeBroadcast(_UDPtype, _client, _len, _data, _bri, _rgbw);
|
||||
_broadcastLock = false;
|
||||
}
|
||||
void show();
|
||||
|
||||
inline bool canShow() {
|
||||
// this should be a return value from UDP routine if it is still sending data out
|
||||
return !_broadcastLock;
|
||||
}
|
||||
|
||||
uint8_t getPins(uint8_t* pinArray) {
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
pinArray[i] = _client[i];
|
||||
bool canShow() {
|
||||
// this should be a return value from UDP routine if it is still sending data out
|
||||
return !_broadcastLock;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
inline bool isRgbw() {
|
||||
return _rgbw;
|
||||
}
|
||||
uint8_t getPins(uint8_t* pinArray);
|
||||
|
||||
inline uint16_t getLength() {
|
||||
return _len;
|
||||
}
|
||||
uint16_t getLength() {
|
||||
return _len;
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
_type = I_NONE;
|
||||
_valid = false;
|
||||
if (_data != nullptr) free(_data);
|
||||
_data = nullptr;
|
||||
}
|
||||
void cleanup();
|
||||
|
||||
~BusNetwork() {
|
||||
cleanup();
|
||||
}
|
||||
~BusNetwork() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private:
|
||||
IPAddress _client;
|
||||
@ -661,154 +321,56 @@ class BusNetwork : public Bus {
|
||||
|
||||
class BusManager {
|
||||
public:
|
||||
BusManager() {};
|
||||
BusManager() {};
|
||||
|
||||
//utility to get the approx. memory usage of a given BusConfig
|
||||
static uint32_t memUsage(BusConfig &bc) {
|
||||
uint8_t type = bc.type;
|
||||
uint16_t len = bc.count + bc.skipAmount;
|
||||
if (type > 15 && type < 32) {
|
||||
#ifdef ESP8266
|
||||
if (bc.pins[0] == 3) { //8266 DMA uses 5x the mem
|
||||
if (type > 29) return len*20; //RGBW
|
||||
return len*15;
|
||||
}
|
||||
if (type > 29) return len*4; //RGBW
|
||||
return len*3;
|
||||
#else //ESP32 RMT uses double buffer?
|
||||
if (type > 29) return len*8; //RGBW
|
||||
return len*6;
|
||||
#endif
|
||||
//utility to get the approx. memory usage of a given BusConfig
|
||||
static uint32_t memUsage(BusConfig &bc);
|
||||
|
||||
int add(BusConfig &bc);
|
||||
|
||||
//do not call this method from system context (network callback)
|
||||
void removeAll();
|
||||
|
||||
void show();
|
||||
|
||||
void setStatusPixel(uint32_t c);
|
||||
|
||||
void IRAM_ATTR setPixelColor(uint16_t pix, uint32_t c, int16_t cct=-1);
|
||||
|
||||
void setBrightness(uint8_t b);
|
||||
|
||||
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
|
||||
|
||||
uint32_t getPixelColor(uint16_t pix);
|
||||
|
||||
bool canAllShow();
|
||||
|
||||
Bus* getBus(uint8_t busNr);
|
||||
|
||||
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
|
||||
uint16_t getTotalLength();
|
||||
|
||||
inline void updateColorOrderMap(const ColorOrderMap &com) {
|
||||
memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap));
|
||||
}
|
||||
if (type > 31 && type < 48) return 5;
|
||||
if (type == 44 || type == 45) return len*4; //RGBW
|
||||
return len*3; //RGB
|
||||
}
|
||||
|
||||
/*
|
||||
int add(BusConfig &bc);
|
||||
void removeAll(); //do not call this method from system context (network callback)
|
||||
void setStatusPixel(uint32_t c);
|
||||
void setPixelColor(uint16_t pix, uint32_t c, int16_t cct=-1);
|
||||
void setBrightness(uint8_t b);
|
||||
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false);
|
||||
uint32_t getPixelColor(uint16_t pix);
|
||||
bool canAllShow();
|
||||
Bus* getBus(uint8_t busNr);
|
||||
void show();
|
||||
uint16_t getTotalLength(); //semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
|
||||
*/
|
||||
// the following functions are inlined by compiler since they are defined within class definition
|
||||
// they should be placed in cpp file instead
|
||||
int add(BusConfig &bc) {
|
||||
if (getNumBusses() - getNumVirtualBusses() >= WLED_MAX_BUSSES) return -1;
|
||||
if (bc.type >= TYPE_NET_DDP_RGB && bc.type < 96) {
|
||||
busses[numBusses] = new BusNetwork(bc);
|
||||
} else if (IS_DIGITAL(bc.type)) {
|
||||
busses[numBusses] = new BusDigital(bc, numBusses, colorOrderMap);
|
||||
} else if (bc.type == TYPE_ONOFF) {
|
||||
busses[numBusses] = new BusOnOff(bc);
|
||||
} else {
|
||||
busses[numBusses] = new BusPwm(bc);
|
||||
inline const ColorOrderMap& getColorOrderMap() const {
|
||||
return colorOrderMap;
|
||||
}
|
||||
return numBusses++;
|
||||
}
|
||||
|
||||
//do not call this method from system context (network callback)
|
||||
void removeAll() {
|
||||
DEBUG_PRINTLN(F("Removing all."));
|
||||
//prevents crashes due to deleting busses while in use.
|
||||
while (!canAllShow()) yield();
|
||||
for (uint8_t i = 0; i < numBusses; i++) delete busses[i];
|
||||
numBusses = 0;
|
||||
}
|
||||
|
||||
void show() {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
busses[i]->show();
|
||||
inline uint8_t getNumBusses() {
|
||||
return numBusses;
|
||||
}
|
||||
}
|
||||
|
||||
void setStatusPixel(uint32_t c) {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
busses[i]->setStatusPixel(c);
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR setPixelColor(uint16_t pix, uint32_t c, int16_t cct=-1) {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
Bus* b = busses[i];
|
||||
uint16_t bstart = b->getStart();
|
||||
if (pix < bstart || pix >= bstart + b->getLength()) continue;
|
||||
busses[i]->setPixelColor(pix - bstart, c);
|
||||
}
|
||||
}
|
||||
|
||||
void setBrightness(uint8_t b) {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
busses[i]->setBrightness(b);
|
||||
}
|
||||
}
|
||||
|
||||
void setSegmentCCT(int16_t cct, bool allowWBCorrection = false) {
|
||||
if (cct > 255) cct = 255;
|
||||
if (cct >= 0) {
|
||||
//if white balance correction allowed, save as kelvin value instead of 0-255
|
||||
if (allowWBCorrection) cct = 1900 + (cct << 5);
|
||||
} else cct = -1;
|
||||
Bus::setCCT(cct);
|
||||
}
|
||||
|
||||
uint32_t getPixelColor(uint16_t pix) {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
Bus* b = busses[i];
|
||||
uint16_t bstart = b->getStart();
|
||||
if (pix < bstart || pix >= bstart + b->getLength()) continue;
|
||||
return b->getPixelColor(pix - bstart);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool canAllShow() {
|
||||
for (uint8_t i = 0; i < numBusses; i++) {
|
||||
if (!busses[i]->canShow()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Bus* getBus(uint8_t busNr) {
|
||||
if (busNr >= numBusses) return nullptr;
|
||||
return busses[busNr];
|
||||
}
|
||||
|
||||
//semi-duplicate of strip.getLengthTotal() (though that just returns strip._length, calculated in finalizeInit())
|
||||
uint16_t getTotalLength() {
|
||||
uint16_t len = 0;
|
||||
for (uint8_t i=0; i<numBusses; i++) len += busses[i]->getLength();
|
||||
return len;
|
||||
}
|
||||
|
||||
inline void updateColorOrderMap(const ColorOrderMap &com) {
|
||||
memcpy(&colorOrderMap, &com, sizeof(ColorOrderMap));
|
||||
}
|
||||
|
||||
inline const ColorOrderMap& getColorOrderMap() const {
|
||||
return colorOrderMap;
|
||||
}
|
||||
|
||||
inline uint8_t getNumBusses() {
|
||||
return numBusses;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t numBusses = 0;
|
||||
Bus* busses[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES];
|
||||
ColorOrderMap colorOrderMap;
|
||||
uint8_t numBusses = 0;
|
||||
Bus* busses[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES];
|
||||
ColorOrderMap colorOrderMap;
|
||||
|
||||
inline uint8_t getNumVirtualBusses() {
|
||||
int j = 0;
|
||||
for (int i=0; i<numBusses; i++) if (busses[i]->getType() >= TYPE_NET_DDP_RGB && busses[i]->getType() < 96) j++;
|
||||
return j;
|
||||
}
|
||||
inline uint8_t getNumVirtualBusses() {
|
||||
int j = 0;
|
||||
for (int i=0; i<numBusses; i++) if (busses[i]->getType() >= TYPE_NET_DDP_RGB && busses[i]->getType() < 96) j++;
|
||||
return j;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#endif
|
@ -182,7 +182,12 @@
|
||||
#endif
|
||||
|
||||
//APA102
|
||||
#define B_HS_DOT_3 NeoPixelBrightnessBus<DotStarBgrFeature, DotStarSpi5MhzMethod> //hardware SPI
|
||||
#ifdef WLED_USE_ETHERNET
|
||||
// fix for #2542 (by @BlackBird77)
|
||||
#define B_HS_DOT_3 NeoPixelBrightnessBus<DotStarBgrFeature, DotStarEsp32DmaHspi5MhzMethod> //hardware HSPI with DMA (ESP32 only)
|
||||
#else
|
||||
#define B_HS_DOT_3 NeoPixelBrightnessBus<DotStarBgrFeature, DotStarSpi5MhzMethod> //hardware HSPI
|
||||
#endif
|
||||
#define B_SS_DOT_3 NeoPixelBrightnessBus<DotStarBgrFeature, DotStarMethod> //soft SPI
|
||||
|
||||
//LPD8806
|
||||
@ -894,6 +899,8 @@ class PolyBus {
|
||||
uint8_t offset = pins[0] -1; //for driver: 0 = uart0, 1 = uart1, 2 = dma, 3 = bitbang
|
||||
if (offset > 3) offset = 3;
|
||||
switch (busType) {
|
||||
case TYPE_WS2812_1CH_X3:
|
||||
case TYPE_WS2812_2CH_X3:
|
||||
case TYPE_WS2812_RGB:
|
||||
case TYPE_WS2812_WWA:
|
||||
return I_8266_U0_NEO_3 + offset;
|
||||
@ -926,6 +933,8 @@ class PolyBus {
|
||||
if (num > 7) offset = num -7;
|
||||
#endif
|
||||
switch (busType) {
|
||||
case TYPE_WS2812_1CH_X3:
|
||||
case TYPE_WS2812_2CH_X3:
|
||||
case TYPE_WS2812_RGB:
|
||||
case TYPE_WS2812_WWA:
|
||||
return I_32_RN_NEO_3 + offset;
|
||||
|
@ -84,7 +84,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
uint8_t autoWhiteMode = RGBW_MODE_MANUAL_ONLY;
|
||||
CJSON(strip.ablMilliampsMax, hw_led[F("maxpwr")]);
|
||||
CJSON(strip.milliampsPerLed, hw_led[F("ledma")]);
|
||||
Bus::setAutoWhiteMode(hw_led[F("rgbwm")] | 255);
|
||||
Bus::setGlobalAWMode(hw_led[F("rgbwm")] | 255);
|
||||
CJSON(correctWB, hw_led["cct"]);
|
||||
CJSON(cctFromRgb, hw_led[F("cr")]);
|
||||
CJSON(strip.cctBlending, hw_led[F("cb")]);
|
||||
@ -97,12 +97,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
JsonObject matrix = hw_led[F("matrix")];
|
||||
if (!matrix.isNull()) {
|
||||
strip.isMatrix = true;
|
||||
CJSON(strip.panels, matrix[F("mpc")]);
|
||||
CJSON(strip.matrix.bottomStart, matrix[F("pb")]);
|
||||
CJSON(strip.matrix.rightStart, matrix[F("pr")]);
|
||||
CJSON(strip.matrix.vertical, matrix[F("pv")]);
|
||||
CJSON(strip.matrix.serpentine, matrix["ps"]);
|
||||
|
||||
CJSON(strip.panels, matrix[F("mpc")]);
|
||||
strip.panel.clear();
|
||||
JsonArray panels = matrix[F("panels")];
|
||||
uint8_t s = 0;
|
||||
@ -130,8 +125,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
p.options = 0;
|
||||
strip.panel.push_back(p);
|
||||
}
|
||||
|
||||
strip.setUpMatrix();
|
||||
// cannot call strip.setUpMatrix() here due to already locked JSON buffer
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -333,18 +327,27 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
CJSON(strip.paletteBlend, light[F("pal-mode")]);
|
||||
CJSON(autoSegments, light[F("aseg")]);
|
||||
|
||||
CJSON(gammaCorrectVal, light["gc"]["val"]); // default 2.8
|
||||
float light_gc_bri = light["gc"]["bri"];
|
||||
float light_gc_col = light["gc"]["col"]; // 2.8
|
||||
if (light_gc_bri > 1.5) gammaCorrectBri = true;
|
||||
else if (light_gc_bri > 0.5) gammaCorrectBri = false;
|
||||
if (light_gc_col > 1.5) gammaCorrectCol = true;
|
||||
else if (light_gc_col > 0.5) gammaCorrectCol = false;
|
||||
float light_gc_col = light["gc"]["col"];
|
||||
if (light_gc_bri > 1.0f) gammaCorrectBri = true;
|
||||
else gammaCorrectBri = false;
|
||||
if (light_gc_col > 1.0f) gammaCorrectCol = true;
|
||||
else gammaCorrectCol = false;
|
||||
if (gammaCorrectVal > 1.0f && gammaCorrectVal <= 3) {
|
||||
if (gammaCorrectVal != 2.8f) calcGammaTable(gammaCorrectVal);
|
||||
} else {
|
||||
gammaCorrectVal = 1.0f; // no gamma correction
|
||||
gammaCorrectBri = false;
|
||||
gammaCorrectCol = false;
|
||||
}
|
||||
|
||||
JsonObject light_tr = light["tr"];
|
||||
CJSON(fadeTransition, light_tr["mode"]);
|
||||
int tdd = light_tr["dur"] | -1;
|
||||
if (tdd >= 0) transitionDelay = transitionDelayDefault = tdd * 100;
|
||||
CJSON(strip.paletteFade, light_tr["pal"]);
|
||||
CJSON(randomPaletteChangeTime, light_tr[F("rpc")]);
|
||||
|
||||
JsonObject light_nl = light["nl"];
|
||||
CJSON(nightlightMode, light_nl["mode"]);
|
||||
@ -406,6 +409,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
if (!DMXAddress || DMXAddress > 510) DMXAddress = 1;
|
||||
CJSON(DMXSegmentSpacing, if_live_dmx[F("dss")]);
|
||||
if (DMXSegmentSpacing > 150) DMXSegmentSpacing = 0;
|
||||
CJSON(e131Priority, if_live_dmx[F("e131prio")]);
|
||||
if (e131Priority > 200) e131Priority = 200;
|
||||
CJSON(DMXMode, if_live_dmx["mode"]);
|
||||
|
||||
tdd = if_live[F("timeout")] | -1;
|
||||
@ -421,17 +426,6 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
||||
|
||||
CJSON(alexaNumPresets, interfaces["va"]["p"]);
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
const char* apikey = interfaces["blynk"][F("token")] | "Hidden";
|
||||
tdd = strnlen(apikey, 36);
|
||||
if (tdd > 20 || tdd == 0)
|
||||
getStringFromJson(blynkApiKey, apikey, 36); //normally not present due to security
|
||||
|
||||
JsonObject if_blynk = interfaces["blynk"];
|
||||
getStringFromJson(blynkHost, if_blynk[F("host")], 33);
|
||||
CJSON(blynkPort, if_blynk["port"]);
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
JsonObject if_mqtt = interfaces["mqtt"];
|
||||
CJSON(mqttEnabled, if_mqtt["en"]);
|
||||
@ -700,7 +694,7 @@ void serializeConfig() {
|
||||
hw_led[F("cr")] = cctFromRgb;
|
||||
hw_led[F("cb")] = strip.cctBlending;
|
||||
hw_led["fps"] = strip.getTargetFps();
|
||||
hw_led[F("rgbwm")] = Bus::getAutoWhiteMode(); // global override
|
||||
hw_led[F("rgbwm")] = Bus::getGlobalAWMode(); // global auto white mode override
|
||||
hw_led[F("ld")] = strip.useLedsArray;
|
||||
|
||||
#ifndef WLED_DISABLE_2D
|
||||
@ -708,11 +702,6 @@ void serializeConfig() {
|
||||
if (strip.isMatrix) {
|
||||
JsonObject matrix = hw_led.createNestedObject(F("matrix"));
|
||||
matrix[F("mpc")] = strip.panels;
|
||||
matrix[F("pb")] = strip.matrix.bottomStart;
|
||||
matrix[F("pr")] = strip.matrix.rightStart;
|
||||
matrix[F("pv")] = strip.matrix.vertical;
|
||||
matrix["ps"] = strip.matrix.serpentine;
|
||||
|
||||
JsonArray panels = matrix.createNestedArray(F("panels"));
|
||||
for (uint8_t i=0; i<strip.panel.size(); i++) {
|
||||
JsonObject pnl = panels.createNestedObject();
|
||||
@ -745,7 +734,7 @@ void serializeConfig() {
|
||||
ins[F("skip")] = bus->skippedLeds();
|
||||
ins["type"] = bus->getType() & 0x7F;
|
||||
ins["ref"] = bus->isOffRefreshRequired();
|
||||
ins[F("rgbwm")] = bus->getAWMode();
|
||||
ins[F("rgbwm")] = bus->getAutoWhiteMode();
|
||||
}
|
||||
|
||||
JsonArray hw_com = hw.createNestedArray(F("com"));
|
||||
@ -810,13 +799,15 @@ void serializeConfig() {
|
||||
light[F("aseg")] = autoSegments;
|
||||
|
||||
JsonObject light_gc = light.createNestedObject("gc");
|
||||
light_gc["bri"] = (gammaCorrectBri) ? 2.8 : 1.0;
|
||||
light_gc["col"] = (gammaCorrectCol) ? 2.8 : 1.0;
|
||||
light_gc["bri"] = (gammaCorrectBri) ? gammaCorrectVal : 1.0f; // keep compatibility
|
||||
light_gc["col"] = (gammaCorrectCol) ? gammaCorrectVal : 1.0f; // keep compatibility
|
||||
light_gc["val"] = gammaCorrectVal;
|
||||
|
||||
JsonObject light_tr = light.createNestedObject("tr");
|
||||
light_tr["mode"] = fadeTransition;
|
||||
light_tr["dur"] = transitionDelayDefault / 100;
|
||||
light_tr["pal"] = strip.paletteFade;
|
||||
light_tr[F("rpc")] = randomPaletteChangeTime;
|
||||
|
||||
JsonObject light_nl = light.createNestedObject("nl");
|
||||
light_nl["mode"] = nightlightMode;
|
||||
@ -865,6 +856,7 @@ void serializeConfig() {
|
||||
JsonObject if_live_dmx = if_live.createNestedObject("dmx");
|
||||
if_live_dmx[F("uni")] = e131Universe;
|
||||
if_live_dmx[F("seqskip")] = e131SkipOutOfSequence;
|
||||
if_live_dmx[F("e131prio")] = e131Priority;
|
||||
if_live_dmx[F("addr")] = DMXAddress;
|
||||
if_live_dmx[F("dss")] = DMXSegmentSpacing;
|
||||
if_live_dmx["mode"] = DMXMode;
|
||||
@ -883,13 +875,6 @@ void serializeConfig() {
|
||||
|
||||
if_va["p"] = alexaNumPresets;
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
JsonObject if_blynk = interfaces.createNestedObject("blynk");
|
||||
if_blynk[F("token")] = strlen(blynkApiKey) ? "Hidden":"";
|
||||
if_blynk[F("host")] = blynkHost;
|
||||
if_blynk["port"] = blynkPort;
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
JsonObject if_mqtt = interfaces.createNestedObject("mqtt");
|
||||
if_mqtt["en"] = mqttEnabled;
|
||||
@ -1020,13 +1005,6 @@ bool deserializeConfigSec() {
|
||||
|
||||
JsonObject interfaces = doc["if"];
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
const char* apikey = interfaces["blynk"][F("token")] | "Hidden";
|
||||
int tdd = strnlen(apikey, 36);
|
||||
if (tdd > 20 || tdd == 0)
|
||||
getStringFromJson(blynkApiKey, apikey, 36);
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
JsonObject if_mqtt = interfaces["mqtt"];
|
||||
getStringFromJson(mqttPass, if_mqtt["psk"], 65);
|
||||
@ -1065,10 +1043,6 @@ void serializeConfigSec() {
|
||||
ap["psk"] = apPass;
|
||||
|
||||
JsonObject interfaces = doc.createNestedObject("if");
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
JsonObject if_blynk = interfaces.createNestedObject("blynk");
|
||||
if_blynk[F("token")] = blynkApiKey;
|
||||
#endif
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
JsonObject if_mqtt = interfaces.createNestedObject("mqtt");
|
||||
if_mqtt["psk"] = mqttPass;
|
||||
|
@ -57,39 +57,42 @@ void setRandomColor(byte* rgb)
|
||||
|
||||
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb
|
||||
{
|
||||
float h = ((float)hue)/65535.0;
|
||||
float s = ((float)sat)/255.0;
|
||||
byte i = floor(h*6);
|
||||
float f = h * 6-i;
|
||||
float p = 255 * (1-s);
|
||||
float q = 255 * (1-f*s);
|
||||
float t = 255 * (1-(1-f)*s);
|
||||
float h = ((float)hue)/65535.0f;
|
||||
float s = ((float)sat)/255.0f;
|
||||
int i = floorf(h*6);
|
||||
float f = h * 6.0f - i;
|
||||
int p = int(255.0f * (1.0f-s));
|
||||
int q = int(255.0f * (1.0f-f*s));
|
||||
int t = int(255.0f * (1.0f-(1.0f-f)*s));
|
||||
p = constrain(p, 0, 255);
|
||||
q = constrain(q, 0, 255);
|
||||
t = constrain(t, 0, 255);
|
||||
switch (i%6) {
|
||||
case 0: rgb[0]=255,rgb[1]=t,rgb[2]=p;break;
|
||||
case 1: rgb[0]=q,rgb[1]=255,rgb[2]=p;break;
|
||||
case 2: rgb[0]=p,rgb[1]=255,rgb[2]=t;break;
|
||||
case 3: rgb[0]=p,rgb[1]=q,rgb[2]=255;break;
|
||||
case 4: rgb[0]=t,rgb[1]=p,rgb[2]=255;break;
|
||||
case 5: rgb[0]=255,rgb[1]=p,rgb[2]=q;
|
||||
case 0: rgb[0]=255,rgb[1]=t, rgb[2]=p; break;
|
||||
case 1: rgb[0]=q, rgb[1]=255,rgb[2]=p; break;
|
||||
case 2: rgb[0]=p, rgb[1]=255,rgb[2]=t; break;
|
||||
case 3: rgb[0]=p, rgb[1]=q, rgb[2]=255;break;
|
||||
case 4: rgb[0]=t, rgb[1]=p, rgb[2]=255;break;
|
||||
case 5: rgb[0]=255,rgb[1]=p, rgb[2]=q; break;
|
||||
}
|
||||
}
|
||||
|
||||
//get RGB values from color temperature in K (https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html)
|
||||
void colorKtoRGB(uint16_t kelvin, byte* rgb) //white spectrum to rgb, calc
|
||||
{
|
||||
float r = 0, g = 0, b = 0;
|
||||
float temp = kelvin / 100;
|
||||
if (temp <= 66) {
|
||||
int r = 0, g = 0, b = 0;
|
||||
float temp = kelvin / 100.0f;
|
||||
if (temp <= 66.0f) {
|
||||
r = 255;
|
||||
g = round(99.4708025861 * log(temp) - 161.1195681661);
|
||||
if (temp <= 19) {
|
||||
g = roundf(99.4708025861f * logf(temp) - 161.1195681661f);
|
||||
if (temp <= 19.0f) {
|
||||
b = 0;
|
||||
} else {
|
||||
b = round(138.5177312231 * log((temp - 10)) - 305.0447927307);
|
||||
b = roundf(138.5177312231f * logf((temp - 10.0f)) - 305.0447927307f);
|
||||
}
|
||||
} else {
|
||||
r = round(329.698727446 * pow((temp - 60), -0.1332047592));
|
||||
g = round(288.1221695283 * pow((temp - 60), -0.0755148492));
|
||||
r = roundf(329.698727446f * powf((temp - 60.0f), -0.1332047592f));
|
||||
g = roundf(288.1221695283f * powf((temp - 60.0f), -0.0755148492f));
|
||||
b = 255;
|
||||
}
|
||||
//g += 12; //mod by Aircoookie, a bit less accurate but visibly less pinkish
|
||||
@ -147,9 +150,9 @@ void colorXYtoRGB(float x, float y, byte* rgb) //coordinates to rgb (https://www
|
||||
b = 1.0f;
|
||||
}
|
||||
// Apply gamma correction
|
||||
r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * pow(r, (1.0f / 2.4f)) - 0.055f;
|
||||
g = g <= 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * pow(g, (1.0f / 2.4f)) - 0.055f;
|
||||
b = b <= 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * pow(b, (1.0f / 2.4f)) - 0.055f;
|
||||
r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * powf(r, (1.0f / 2.4f)) - 0.055f;
|
||||
g = g <= 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * powf(g, (1.0f / 2.4f)) - 0.055f;
|
||||
b = b <= 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * powf(b, (1.0f / 2.4f)) - 0.055f;
|
||||
|
||||
if (r > b && r > g) {
|
||||
// red is biggest
|
||||
@ -173,9 +176,9 @@ void colorXYtoRGB(float x, float y, byte* rgb) //coordinates to rgb (https://www
|
||||
b = 1.0f;
|
||||
}
|
||||
}
|
||||
rgb[0] = 255.0*r;
|
||||
rgb[1] = 255.0*g;
|
||||
rgb[2] = 255.0*b;
|
||||
rgb[0] = byte(255.0f*r);
|
||||
rgb[1] = byte(255.0f*g);
|
||||
rgb[2] = byte(255.0f*b);
|
||||
}
|
||||
|
||||
void colorRGBtoXY(byte* rgb, float* xy) //rgb to coordinates (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
|
||||
@ -242,35 +245,13 @@ float maxf (float v, float w)
|
||||
return v;
|
||||
}
|
||||
|
||||
/*
|
||||
uint32_t colorRGBtoRGBW(uint32_t c)
|
||||
{
|
||||
byte rgb[4];
|
||||
rgb[0] = R(c);
|
||||
rgb[1] = G(c);
|
||||
rgb[2] = B(c);
|
||||
rgb[3] = W(c);
|
||||
colorRGBtoRGBW(rgb);
|
||||
return RGBW32(rgb[0], rgb[1], rgb[2], rgb[3]);
|
||||
}
|
||||
|
||||
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]));
|
||||
if (high < 0.1f) return;
|
||||
float sat = 100.0f * ((high - low) / high); // maximum saturation is 100 (corrected from 255)
|
||||
rgb[3] = (byte)((255.0f - sat) / 255.0f * (rgb[0] + rgb[1] + rgb[2]) / 3);
|
||||
}
|
||||
*/
|
||||
|
||||
byte correctionRGB[4] = {0,0,0,0};
|
||||
uint16_t lastKelvin = 0;
|
||||
|
||||
// adjust RGB values based on color temperature in K (range [2800-10200]) (https://en.wikipedia.org/wiki/Color_balance)
|
||||
// called from bus manager when color correction is enabled!
|
||||
uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb)
|
||||
{
|
||||
//remember so that slow colorKtoRGB() doesn't have to run for every setPixelColor()
|
||||
static byte correctionRGB[4] = {0,0,0,0};
|
||||
static uint16_t lastKelvin = 0;
|
||||
if (lastKelvin != kelvin) colorKtoRGB(kelvin, correctionRGB); // convert Kelvin to RGB
|
||||
lastKelvin = kelvin;
|
||||
byte rgbw[4];
|
||||
|
@ -79,6 +79,17 @@
|
||||
#define WLED_MAX_COLOR_ORDER_MAPPINGS 10
|
||||
#endif
|
||||
|
||||
#if defined(WLED_MAX_LEDMAPS) && (WLED_MAX_LEDMAPS > 32 || WLED_MAX_LEDMAPS < 10)
|
||||
#undef WLED_MAX_LEDMAPS
|
||||
#endif
|
||||
#ifndef WLED_MAX_LEDMAPS
|
||||
#ifdef ESP8266
|
||||
#define WLED_MAX_LEDMAPS 10
|
||||
#else
|
||||
#define WLED_MAX_LEDMAPS 16
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//Usermod IDs
|
||||
#define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present
|
||||
#define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID
|
||||
@ -120,6 +131,7 @@
|
||||
#define USERMOD_ID_SD_CARD 37 //Usermod "usermod_sd_card.h"
|
||||
#define USERMOD_ID_PWM_OUTPUTS 38 //Usermod "usermod_pwm_outputs.h
|
||||
#define USERMOD_ID_SHT 39 //Usermod "usermod_sht.h
|
||||
#define USERMOD_ID_KLIPPER 40 // Usermod Klipper percentage
|
||||
|
||||
//Access point behavior
|
||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||
@ -137,17 +149,19 @@
|
||||
#define CALL_MODE_FX_CHANGED 6 //no longer used
|
||||
#define CALL_MODE_HUE 7
|
||||
#define CALL_MODE_PRESET_CYCLE 8
|
||||
#define CALL_MODE_BLYNK 9
|
||||
#define CALL_MODE_BLYNK 9 //no longer used
|
||||
#define CALL_MODE_ALEXA 10
|
||||
#define CALL_MODE_WS_SEND 11 //special call mode, not for notifier, updates websocket only
|
||||
#define CALL_MODE_BUTTON_PRESET 12 //button/IR JSON preset/macro
|
||||
|
||||
//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
|
||||
#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_MAX 4 // Sets white to the value of the brightest RGB channel (good for white-only LEDs without any RGB)
|
||||
//#define RGBW_MODE_LEGACY 4 // Old floating algorithm. Too slow for realtime and palette support (unused)
|
||||
#define AW_GLOBAL_DISABLED 255 // Global auto white mode override disabled. Per-bus setting is used
|
||||
|
||||
//realtime modes
|
||||
#define REALTIME_MODE_INACTIVE 0
|
||||
@ -193,7 +207,9 @@
|
||||
#define TYPE_NONE 0 //light is not configured
|
||||
#define TYPE_RESERVED 1 //unused. Might indicate a "virtual" light
|
||||
//Digital types (data pin only) (16-31)
|
||||
#define TYPE_WS2812_1CH 20 //white-only chips
|
||||
#define TYPE_WS2812_1CH 18 //white-only chips (1 channel per IC) (unused)
|
||||
#define TYPE_WS2812_1CH_X3 19 //white-only chips (3 channels per IC)
|
||||
#define TYPE_WS2812_2CH_X3 20 //CCT chips (1st IC controls WW + CW of 1st zone and CW of 2nd zone, 2nd IC controls WW of 2nd zone and WW + CW of 3rd zone)
|
||||
#define TYPE_WS2812_WWA 21 //amber + warm + cold white
|
||||
#define TYPE_WS2812_RGB 22
|
||||
#define TYPE_GS8608 23 //same driver as WS2812, but will require signal 2x per second (else displays test pattern)
|
||||
@ -290,6 +306,11 @@
|
||||
//Playlist option byte
|
||||
#define PL_OPTION_SHUFFLE 0x01
|
||||
|
||||
// Segment capability byte
|
||||
#define SEG_CAPABILITY_RGB 0x01
|
||||
#define SEG_CAPABILITY_W 0x02
|
||||
#define SEG_CAPABILITY_CCT 0x04
|
||||
|
||||
// WLED Error modes
|
||||
#define ERR_NONE 0 // All good :)
|
||||
#define ERR_EEP_COMMIT 2 // Could not commit to EEPROM (wrong flash layout?)
|
||||
@ -383,8 +404,8 @@
|
||||
#define JSON_BUFFER_SIZE 24576
|
||||
#endif
|
||||
|
||||
//#define MIN_HEAP_SIZE (MAX_LED_MEMORY+2048)
|
||||
#define MIN_HEAP_SIZE (8192)
|
||||
//#define MIN_HEAP_SIZE (8k for AsyncWebServer)
|
||||
#define MIN_HEAP_SIZE 8192
|
||||
|
||||
// Maximum size of node map (list of other WLED instances)
|
||||
#ifdef ESP8266
|
||||
|
@ -392,12 +392,16 @@ button {
|
||||
}
|
||||
|
||||
.slider {
|
||||
background-color: var(--c-2);
|
||||
max-width: 300px;
|
||||
min-width: 280px;
|
||||
min-width: 260px;
|
||||
margin: 0 auto; /* add 5px; if you want some vertical space but looks ugly */
|
||||
border-radius: 24px;
|
||||
position: relative;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
#sliders .slider, #info .slider {
|
||||
background-color: var(--c-2);
|
||||
}
|
||||
|
||||
.filter, .option {
|
||||
@ -425,14 +429,14 @@ button {
|
||||
box-shadow: 4px 4px 10px 4px var(--c-1);
|
||||
color: var(--c-f);
|
||||
text-align: center;
|
||||
padding: 5px 10px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 6px;
|
||||
|
||||
/* Position the tooltip text */
|
||||
width: 160px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 100%;
|
||||
bottom: 80%;
|
||||
left: 50%;
|
||||
margin-left: -92px;
|
||||
|
||||
@ -647,7 +651,7 @@ img {
|
||||
#wbal .sliderdisplay { background: linear-gradient(90deg, #ff8f1f 0%, #fff 50%, #cbdbff); }
|
||||
|
||||
/* wrapper divs hidden by default */
|
||||
#rgbwrap, #kwrap, #wwrap, #wbal, #qcs-w, #hexw {
|
||||
#rgbwrap, #swrap, #hwrap, #kwrap, #wwrap, #wbal, #qcs-w, #hexw {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -731,7 +735,11 @@ input[type=range]::-moz-range-thumb {
|
||||
|
||||
#Colors .sliderwrap {
|
||||
width: 260px;
|
||||
margin: 10px 0 0;
|
||||
margin: 4px 0 0;
|
||||
}
|
||||
|
||||
#Colors {
|
||||
padding-top: 18px;
|
||||
}
|
||||
|
||||
/* Dynamically hide brightness slider label */
|
||||
@ -744,13 +752,14 @@ input[type=range]::-moz-range-thumb {
|
||||
margin-top: var(--bmt);
|
||||
}
|
||||
|
||||
#picker, #rgbwrap, #kwrap, #wwrap, #wbal, #vwrap, #qcs-w, #hexw, #pall, #ledmap {
|
||||
#picker, #qcs-w, #hexw, #pall, #ledmap {
|
||||
margin: 0 auto;
|
||||
width: 260px;
|
||||
/*background-color: unset;*/
|
||||
}
|
||||
|
||||
#picker {
|
||||
margin-top: 10px;
|
||||
margin-top: -10px !important;
|
||||
}
|
||||
|
||||
/* buttons */
|
||||
@ -1409,6 +1418,9 @@ TD .checkmark, TD .radiomark {
|
||||
.expanded {
|
||||
display: inline-block !important;
|
||||
}
|
||||
.expanded .segin.hide, .expanded .presin.hide, .expanded .sbs.hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.m6 {
|
||||
margin: 6px 0;
|
||||
|
@ -88,68 +88,73 @@
|
||||
<div class ="container">
|
||||
<div id="Colors" class="tabcontent">
|
||||
<div id="picker" class="noslide"></div>
|
||||
<div id="hwrap">
|
||||
<!--p class="labels hd">Hue</p-->
|
||||
<div id="hwrap" class="slider">
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderH" class="noslide" oninput="fromH()" onchange="setColor(0)" max="359" min="0" type="range" value="0" step="any">
|
||||
<div class="sliderdisplay" style="background: linear-gradient(90deg, #f00 2%, #ff0 19%, #0f0 35%, #0ff 52%, #00f 68%, #f0f 85%, #f00)"></div>
|
||||
</div><br>
|
||||
</div>
|
||||
<span class="tooltiptext">Hue</span>
|
||||
</div>
|
||||
<div id="swrap">
|
||||
<!--p class="labels hd">Saturation</p-->
|
||||
<div id="swrap" class="slider">
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderS" class="noslide" oninput="fromS()" onchange="setColor(0)" max="100" min="0" type="range" value="100" step="any">
|
||||
<div class="sliderdisplay" style="background: linear-gradient(90deg, #aaa 0%, #f00)"></div>
|
||||
</div><br>
|
||||
</div>
|
||||
<span class="tooltiptext">Saturation</span>
|
||||
</div>
|
||||
<div id="vwrap">
|
||||
<!--p class="labels hd">Value</p-->
|
||||
<div id="vwrap" class="slider">
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderV" class="noslide" oninput="fromV()" onchange="setColor(0)" max="100" min="0" type="range" value="100" step="any" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div><br>
|
||||
</div>
|
||||
<span class="tooltiptext">Value/Brightness</span>
|
||||
</div>
|
||||
<div id="kwrap">
|
||||
<!--p class="labels hd">Temperature</p-->
|
||||
<div id="kwrap" class="slider">
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderK" class="noslide" oninput="fromK()" onchange="setColor(0)" max="10091" min="1900" type="range" value="6550" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<span class="tooltiptext">Kelvin/Temperature</span>
|
||||
</div>
|
||||
<div id="rgbwrap">
|
||||
<p class="labels hd">RGB color</p>
|
||||
<div id="rwrap" class="il">
|
||||
<!--p class="labels hd">RGB color</p-->
|
||||
<div id="rwrap" class="slider">
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderR" class="noslide" oninput="fromRgb()" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<span class="tooltiptext">Red channel</span>
|
||||
</div>
|
||||
<div id="gwrap" class="il">
|
||||
<div id="gwrap" class="slider">
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderG" class="noslide" oninput="fromRgb()" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<span class="tooltiptext">Green channel</span>
|
||||
</div>
|
||||
<div id="bwrap" class="il">
|
||||
<div id="bwrap" class="slider">
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderB" class="noslide" oninput="fromRgb()" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<span class="tooltiptext">Blue channel</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="wwrap">
|
||||
<p class="labels hd">White channel</p>
|
||||
<div id="wwrap" class="slider">
|
||||
<!--p class="labels hd">White channel</p-->
|
||||
<div id="whibri" class="sliderwrap il">
|
||||
<input id="sliderW" class="noslide" oninput="fromW()" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<span class="tooltiptext">White channel</span>
|
||||
</div>
|
||||
<div id="wbal">
|
||||
<p class="labels hd">White balance</p>
|
||||
<div id="wbal" class="slider">
|
||||
<!--p class="labels hd">White balance</p-->
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderA" class="noslide" onchange="setBalance(this.value)" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<span class="tooltiptext">White balance</span>
|
||||
</div>
|
||||
<div id="qcs-w">
|
||||
<div class="qcs" onclick="pC('#ff0000');" title="Red" style="background-color:#ff0000;"></div>
|
||||
@ -310,7 +315,7 @@
|
||||
<div id="segutil2">
|
||||
<button class="btn btn-s" id="rsbtn" onclick="rSegs()">Reset segments</button>
|
||||
</div>
|
||||
<p>Transition: <input id="tt" class="noslide" type="number" min="0" max="65.5" step="0.1" value="0.7"> s</p>
|
||||
<p>Transition: <input id="tt" type="number" min="0" max="65.5" step="0.1" value="0.7"> s</p>
|
||||
<p id="ledmap" class="hide"></p>
|
||||
</div>
|
||||
|
||||
|
@ -4,6 +4,7 @@ var isOn = false, nlA = false, isLv = false, isInfo = false, isNodes = false, sy
|
||||
var hasWhite = false, hasRGB = false, hasCCT = false;
|
||||
var nlDur = 60, nlTar = 0;
|
||||
var nlMode = false;
|
||||
var segLmax = 0; // size (in pixels) of largest selected segment
|
||||
var selectedFx = 0;
|
||||
var selectedPal = 0;
|
||||
var csel = 0; // selected color slot (0-2)
|
||||
@ -60,13 +61,10 @@ function setCSL(cs)
|
||||
let w = cs.dataset.w ? parseInt(cs.dataset.w) : 0;
|
||||
let hasShadow = getComputedStyle(cs).textShadow !== "none";
|
||||
if (hasRGB && !isRgbBlack(cs.dataset)) {
|
||||
cs.style.backgroundColor = rgbStr(cs.dataset);
|
||||
if (!hasShadow) cs.style.color = rgbBri(cs.dataset) > 127 ? "#000":"#fff"; // if text has no CSS "shadow"
|
||||
if (hasWhite && w > 0) {
|
||||
cs.style.background = `linear-gradient(180deg, ${rgbStr(cs.dataset)} 30%, rgb(${w},${w},${w}))`;
|
||||
}
|
||||
cs.style.background = (hasWhite && w > 0) ? `linear-gradient(180deg, ${rgbStr(cs.dataset)} 30%, rgb(${w},${w},${w}))` : rgbStr(cs.dataset);
|
||||
} else {
|
||||
if (!hasWhite) w = 0;
|
||||
if (hasRGB && !hasWhite) w = 0;
|
||||
cs.style.background = `rgb(${w},${w},${w})`;
|
||||
if (!hasShadow) cs.style.color = w > 127 ? "#000":"#fff";
|
||||
}
|
||||
@ -713,7 +711,7 @@ function populateSegments(s)
|
||||
let rvXck = `<label class="check revchkl">Reverse ${isM?'':'direction'}<input type="checkbox" id="seg${i}rev" onchange="setRev(${i})" ${inst.rev?"checked":""}><span class="checkmark"></span></label>`;
|
||||
let miXck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mi" onchange="setMi(${i})" ${inst.mi?"checked":""}><span class="checkmark"></span></label>`;
|
||||
let rvYck = "", miYck ="";
|
||||
if (isM) {
|
||||
if (isM && staX<mw*mh) {
|
||||
rvYck = `<label class="check revchkl">Reverse<input type="checkbox" id="seg${i}rY" onchange="setRevY(${i})" ${inst.rY?"checked":""}><span class="checkmark"></span></label>`;
|
||||
miYck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mY" onchange="setMiY(${i})" ${inst.mY?"checked":""}><span class="checkmark"></span></label>`;
|
||||
}
|
||||
@ -746,42 +744,43 @@ function populateSegments(s)
|
||||
<i class="icons e-icon flr" id="sege${i}" onclick="expand(${i})"></i>
|
||||
${cfg.comp.segpwr?segp:''}
|
||||
<div class="segin" id="seg${i}in">
|
||||
<input type="text" class="ptxt noslide" id="seg${i}t" autocomplete="off" maxlength=32 value="${inst.n?inst.n:""}" placeholder="Enter name..."/>
|
||||
<input type="text" class="ptxt" id="seg${i}t" autocomplete="off" maxlength=32 value="${inst.n?inst.n:""}" placeholder="Enter name..."/>
|
||||
<table class="infot segt">
|
||||
<tr>
|
||||
<td>${isM?'Start X':'Start LED'}</td>
|
||||
<td>${isM?(cfg.comp.seglen?"Width":"Stop X"):(cfg.comp.seglen?"LED count":"Stop LED")}</td>
|
||||
<td>${isM?'':'Offset'}</td>
|
||||
<td>${isM&&staX<mw*mh?'Start X':'Start LED'}</td>
|
||||
<td>${isM&&staX<mw*mh?(cfg.comp.seglen?"Width":"Stop X"):(cfg.comp.seglen?"LED count":"Stop LED")}</td>
|
||||
<td>${isM&&staX<mw*mh?'':'Offset'}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input class="noslide segn" id="seg${i}s" type="number" min="0" max="${(isM?mw:ledCount)-1}" value="${staX}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
|
||||
<td><input class="noslide segn" id="seg${i}e" type="number" min="0" max="${(isM?mw:ledCount)-(cfg.comp.seglen?staX:0)}" value="${stoX-(cfg.comp.seglen?staX:0)}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
|
||||
<td style="text-align:revert;">${isM?miXck+'<br>'+rvXck:''}<input class="noslide segn ${isM?'hide':''}" id="seg${i}of" type="number" value="${inst.of}" oninput="updateLen(${i})"></td>
|
||||
<td><input class="segn" id="seg${i}s" type="number" min="0" max="${(isM&&staX<mw*mh?mw:ledCount)-1}" value="${staX}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
|
||||
<td><input class="segn" id="seg${i}e" type="number" min="0" max="${(isM&&staX<mw*mh?mw:ledCount)}" value="${stoX-(cfg.comp.seglen?staX:0)}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
|
||||
<td style="text-align:revert;">${isM&&staX<mw*mh?miXck+'<br>'+rvXck:''}<input class="segn ${isM&&staX<mw*mh?'hide':''}" id="seg${i}of" type="number" value="${inst.of}" oninput="updateLen(${i})"></td>
|
||||
</tr>
|
||||
${isM ? '<tr><td>Start Y</td><td>'+(cfg.comp.seglen?'Height':'Stop Y')+'</td><td></td></tr>'+
|
||||
${isM&&staX<mw*mh ? '<tr><td>Start Y</td><td>'+(cfg.comp.seglen?'Height':'Stop Y')+'</td><td></td></tr>'+
|
||||
'<tr>'+
|
||||
'<td><input class="noslide segn" id="seg'+i+'sY" type="number" min="0" max="'+(mh-1)+'" value="'+staY+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+
|
||||
'<td><input class="noslide segn" id="seg'+i+'eY" type="number" min="0" max="'+(mh-(cfg.comp.seglen?staY:0))+'" value="'+(stoY-(cfg.comp.seglen?staY:0))+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+
|
||||
'<td><input class="segn" id="seg'+i+'sY" type="number" min="0" max="'+(mh-1)+'" value="'+staY+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+
|
||||
'<td><input class="segn" id="seg'+i+'eY" type="number" min="0" max="'+mh+'" value="'+(stoY-(cfg.comp.seglen?staY:0))+'" oninput="updateLen('+i+')" onkeydown="segEnter('+i+')"></td>'+
|
||||
'<td style="text-align:revert;">'+miYck+'<br>'+rvYck+'</td>'+
|
||||
'</tr>':''}
|
||||
<tr>
|
||||
<td>Grouping</td>
|
||||
<td>Spacing</td>
|
||||
<td><!--Apply--></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input class="noslide segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
|
||||
<td><input class="noslide segn" id="seg${i}spc" type="number" min="0" max="255" value="${inst.spc}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
|
||||
<td style="text-align:left;"><button class="btn btn-xs" onclick="setSeg(${i})"><i class="icons btn-icon" id="segc${i}"></i></button></td>
|
||||
<td><input class="segn" id="seg${i}grp" type="number" min="1" max="255" value="${inst.grp}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
|
||||
<td><input class="segn" id="seg${i}spc" type="number" min="0" max="255" value="${inst.spc}" oninput="updateLen(${i})" onkeydown="segEnter(${i})"></td>
|
||||
<td style="text-align:revert;"><button class="btn btn-xs" onclick="setSeg(${i})"><i class="icons btn-icon" id="segc${i}"></i></button></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="h bp" id="seg${i}len"></div>
|
||||
${!isM?rvXck:''}
|
||||
${isM&&stoY-staY>1&&stoX-staX>1?map2D:''}
|
||||
${!(isM&&staX<mw*mh)?rvXck:''}
|
||||
${isM&&staX<mw*mh&&stoY-staY>1&&stoX-staX>1?map2D:''}
|
||||
${s.AudioReactive && s.AudioReactive.on ? "" : sndSim}
|
||||
<label class="check revchkl" id="seg${i}lbtm">
|
||||
${isM?'Transpose':'Mirror effect'}
|
||||
<input type="checkbox" id="seg${i}${isM?'tp':'mi'}" onchange="${(isM?'setTp(':'setMi(')+i})" ${isM?(inst.tp?"checked":""):(inst.mi?"checked":"")}>
|
||||
${isM&&staX<mw*mh?'Transpose':'Mirror effect'}${isM&&staX<mw*mh?
|
||||
'<input type="checkbox" id="seg'+i+'tp" onchange="setTp('+i+')" '+(inst.tp?"checked":"")+'>':
|
||||
'<input type="checkbox" id="seg'+i+'mi" onchange="setMi('+i+')" '+(inst.mi?"checked":"")+'>'}
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<div class="del">
|
||||
@ -800,16 +799,19 @@ function populateSegments(s)
|
||||
for (var i = 0; i <= lSeg; i++) {
|
||||
updateLen(i);
|
||||
updateTrail(gId(`seg${i}bri`));
|
||||
gId(`segr${i}`).style.display = "none";
|
||||
gId(`segr${i}`).classList.add("hide");
|
||||
if (!gId(`seg${i}sel`).checked && gId('selall')) gId('selall').checked = false; // uncheck if at least one is unselected.
|
||||
}
|
||||
if (segCount < 2) gId(`segd${lSeg}`).style.display = "none";
|
||||
if (segCount < 2) {
|
||||
gId(`segd${lSeg}`).classList.add("hide");
|
||||
gId(`segp0`).classList.add("hide");
|
||||
}
|
||||
if (!isM && !noNewSegs && (cfg.comp.seglen?parseInt(gId(`seg${lSeg}s`).value):0)+parseInt(gId(`seg${lSeg}e`).value)<ledCount) gId(`segr${lSeg}`).style.display = "inline";
|
||||
gId('segutil2').style.display = (segCount > 1) ? "block":"none"; // rsbtn parent
|
||||
|
||||
if (!isM && Array.isArray(li.maps) && li.maps.length>1) {
|
||||
if (Array.isArray(li.maps) && li.maps.length>1) {
|
||||
let cont = `Ledmap: <select class="sel-sg" onchange="requestJson({'ledmap':parseInt(this.value)})"><option value="" selected>Unchanged</option>`;
|
||||
for (const k of (li.maps||[])) cont += `<option value="${k}">${k==0?'Default':'ledmap'+k+'.json'}</option>`;
|
||||
for (const k of (li.maps||[])) cont += `<option value="${k.id}">${k.id==0?'Default':(k.n?k.n:'ledmap'+k.id+'.json')}</option>`;
|
||||
cont += "</select></div>";
|
||||
gId("ledmap").innerHTML = cont;
|
||||
gId("ledmap").classList.remove('hide');
|
||||
@ -851,6 +853,7 @@ function populateEffects()
|
||||
let m = (eP.length<4 || eP[3]==='')?'1':eP[3]; // flags
|
||||
if (id == 0) m = ''; // solid has no flags
|
||||
if (m.length>0) {
|
||||
if (m.includes('0')) nm += "•"; // 0D effects (PWM & On/Off)
|
||||
if (m.includes('1')) nm += "⋮"; // 1D effects
|
||||
if (m.includes('2')) nm += "▦"; // 2D effects
|
||||
if (m.includes('v')) nm += "♪"; // volume effects
|
||||
@ -1049,29 +1052,50 @@ function updateLen(s)
|
||||
var start = parseInt(gId(`seg${s}s`).value);
|
||||
var stop = parseInt(gId(`seg${s}e`).value) + (cfg.comp.seglen?start:0);
|
||||
var len = stop - start;
|
||||
let sY = gId(`seg${s}sY`);
|
||||
let eY = gId(`seg${s}eY`);
|
||||
let sX = gId(`seg${s}s`);
|
||||
let eX = gId(`seg${s}e`);
|
||||
let of = gId(`seg${s}of`);
|
||||
let mySH = gId("mkSYH");
|
||||
let mySD = gId("mkSYD");
|
||||
if (isM) {
|
||||
// matrix setup
|
||||
let startY = parseInt(gId(`seg${s}sY`).value);
|
||||
let stopY = parseInt(gId(`seg${s}eY`).value) + (cfg.comp.seglen?startY:0);
|
||||
len *= (stopY-startY);
|
||||
let tPL = gId(`seg${s}lbtm`);
|
||||
if (stop-start>1 && stopY-startY>1) {
|
||||
// 2D segment
|
||||
if (tPL) tPL.classList.remove('hide'); // unhide transpose checkbox
|
||||
let sE = gId('fxlist').querySelector(`.lstI[data-id="${selectedFx}"]`);
|
||||
if (sE) {
|
||||
let sN = sE.querySelector(".lstIname").innerText;
|
||||
let seg = gId(`seg${s}map2D`);
|
||||
if (seg) {
|
||||
if(sN.indexOf("\u25A6")<0) seg.classList.remove('hide'); // unhide mapping for 1D effects (| in name)
|
||||
else seg.classList.add('hide'); // hide mapping otherwise
|
||||
}
|
||||
}
|
||||
// do we have 1D segment *after* the matrix?
|
||||
if (start >= mw*mh) {
|
||||
if (sY) { sY.value = 0; sY.max = 0; sY.min = 0; }
|
||||
if (eY) { eY.value = 1; eY.max = 1; eY.min = 0; }
|
||||
sX.min = mw*mh; sX.max = ledCount-1;
|
||||
eX.min = mw*mh+1; eX.max = ledCount;
|
||||
if (mySH) mySH.classList.add("hide");
|
||||
if (mySD) mySD.classList.add("hide");
|
||||
if (of) of.classList.remove("hide");
|
||||
} else {
|
||||
// 1D segment in 2D set-up
|
||||
if (tPL) {
|
||||
tPL.classList.add('hide'); // hide transpose checkbox
|
||||
gId(`seg${s}tp`).checked = false; // and uncheck it
|
||||
// matrix setup
|
||||
if (mySH) mySH.classList.remove("hide");
|
||||
if (mySD) mySD.classList.remove("hide");
|
||||
if (of) of.classList.add("hide");
|
||||
let startY = parseInt(sY.value);
|
||||
let stopY = parseInt(eY.value) + (cfg.comp.seglen?startY:0);
|
||||
len *= (stopY-startY);
|
||||
let tPL = gId(`seg${s}lbtm`);
|
||||
if (stop-start>1 && stopY-startY>1) {
|
||||
// 2D segment
|
||||
if (tPL) tPL.classList.remove('hide'); // unhide transpose checkbox
|
||||
let sE = gId('fxlist').querySelector(`.lstI[data-id="${selectedFx}"]`);
|
||||
if (sE) {
|
||||
let sN = sE.querySelector(".lstIname").innerText;
|
||||
let seg = gId(`seg${s}map2D`);
|
||||
if (seg) {
|
||||
if(sN.indexOf("\u25A6")<0) seg.classList.remove('hide'); // unhide mapping for 1D effects (| in name)
|
||||
else seg.classList.add('hide'); // hide mapping otherwise
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 1D segment in 2D set-up
|
||||
if (tPL) {
|
||||
tPL.classList.add('hide'); // hide transpose checkbox
|
||||
gId(`seg${s}tp`).checked = false; // and uncheck it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1090,6 +1114,7 @@ function updateLen(s)
|
||||
var virt = Math.ceil(len/(grp + spc));
|
||||
if (!isNaN(virt) && (grp > 1 || spc > 0)) out += ` (${virt} virtual)`;
|
||||
}
|
||||
if (isM && start >= mw*mh) out += " [strip]";
|
||||
|
||||
gId(`seg${s}len`).innerHTML = out;
|
||||
}
|
||||
@ -1142,18 +1167,19 @@ function updateUI()
|
||||
}
|
||||
if (hasWhite) updateTrail(gId('sliderW'));
|
||||
|
||||
gId('wwrap').style.display = (hasWhite) ? "block":"none"; // white channel
|
||||
gId('wbal').style.display = (hasCCT) ? "block":"none"; // white balance
|
||||
var ccfg = cfg.comp.colors;
|
||||
gId('hexw').style.display = ccfg.hex ? "block":"none"; // HEX input
|
||||
gId('picker').style.display = (hasRGB && ccfg.picker) ? "block":"none"; // color picker wheel
|
||||
gId('hwrap').style.display = (hasRGB && !ccfg.picker) ? "block":"none"; // color picker wheel
|
||||
gId('swrap').style.display = (hasRGB && !ccfg.picker) ? "block":"none"; // color picker wheel
|
||||
gId('vwrap').style.display = (hasRGB /*&& ccfg.picker*/) ? "block":"none"; // brightness (value) slider
|
||||
gId('kwrap').style.display = (hasRGB && !hasCCT /*&& ccfg.picker*/) ? "block":"none"; // Kelvin slider
|
||||
gId('rgbwrap').style.display = (hasRGB && ccfg.rgb) ? "block":"none"; // RGB sliders
|
||||
gId('qcs-w').style.display = (hasRGB && ccfg.quick) ? "block":"none"; // quick selection
|
||||
//gId('palw').style.display = hasRGB ? "block":"none"; // palettes
|
||||
gId('wwrap').style.display = (hasWhite) ? "block":"none"; // white channel
|
||||
gId('wbal').style.display = (hasCCT) ? "block":"none"; // white balance
|
||||
gId('hexw').style.display = (ccfg.hex) ? "block":"none"; // HEX input
|
||||
gId('picker').style.display = (hasRGB && ccfg.picker) ? "block":"none"; // color picker wheel
|
||||
gId('hwrap').style.display = (hasRGB && !ccfg.picker) ? "block":"none"; // hue slider
|
||||
gId('swrap').style.display = (hasRGB && !ccfg.picker) ? "block":"none"; // saturation slider
|
||||
gId('vwrap').style.display = (hasRGB) ? "block":"none"; // brightness (value) slider
|
||||
gId('kwrap').style.display = (hasRGB && !hasCCT) ? "block":"none"; // Kelvin slider
|
||||
gId('rgbwrap').style.display = (hasRGB && ccfg.rgb) ? "block":"none"; // RGB sliders
|
||||
gId('qcs-w').style.display = (hasRGB && ccfg.quick) ? "block":"none"; // quick selection
|
||||
//gId('csl').style.display = (hasRGB || hasWhite) ? "block":"none"; // color selectors (hide for On/Off bus)
|
||||
//gId('palw').style.display = (hasRGB) ? "inline-block":"none"; // palettes are shown/hidden in setEffectParameters()
|
||||
|
||||
updatePA();
|
||||
updatePSliders();
|
||||
@ -1198,7 +1224,19 @@ function updateSelectedFx()
|
||||
if (selectedEffect) {
|
||||
selectedEffect.classList.add('selected');
|
||||
setEffectParameters(selectedFx);
|
||||
|
||||
// hide non-0D effects if segment only has 1 pixel (0D)
|
||||
var fxs = parent.querySelectorAll('.lstI');
|
||||
for (const fx of fxs) {
|
||||
let opts = fx.dataset.opt.split(";");
|
||||
if (fx.dataset.id>0) {
|
||||
if (segLmax==0) fx.classList.add('hide'); // none of the segments selected (hide all effects)
|
||||
else {
|
||||
if (segLmax==1 && (!opts[3] || opts[3].indexOf("0")<0)) fx.classList.add('hide');
|
||||
else fx.classList.remove('hide');
|
||||
}
|
||||
}
|
||||
}
|
||||
// hide 2D mapping and/or sound simulation options
|
||||
var selectedName = selectedEffect.querySelector(".lstIname").innerText;
|
||||
var segs = gId("segcont").querySelectorAll(`div[data-map="map2D"]`);
|
||||
for (const seg of segs) if (selectedName.indexOf("\u25A6")<0) seg.classList.remove('hide'); else seg.classList.add('hide');
|
||||
@ -1285,6 +1323,7 @@ function readState(s,command=false)
|
||||
var selc=0;
|
||||
var sellvl=0; // 0: selc is invalid, 1: selc is mainseg, 2: selc is first selected
|
||||
hasRGB = hasWhite = hasCCT = false;
|
||||
segLmax = 0;
|
||||
for (let i = 0; i < (s.seg||[]).length; i++)
|
||||
{
|
||||
if (sellvl == 0 && s.seg[i].id == s.mainseg) {
|
||||
@ -1296,15 +1335,17 @@ function readState(s,command=false)
|
||||
sellvl = 2;
|
||||
var lc = lastinfo.leds.seglc[s.seg[i].id];
|
||||
hasRGB |= !!(lc & 0x01);
|
||||
hasWhite |= !!(lc & 0x08); // & 0x02 contains W channel
|
||||
hasWhite |= !!(lc & 0x02);
|
||||
hasCCT |= !!(lc & 0x04);
|
||||
let sLen = (s.seg[i].stop - s.seg[i].start)*(s.seg[i].stopY?(s.seg[i].stopY - s.seg[i].startY):1);
|
||||
segLmax = segLmax < sLen ? sLen : segLmax;
|
||||
}
|
||||
}
|
||||
var i=s.seg[selc];
|
||||
if (sellvl == 1) {
|
||||
var lc = lastinfo.leds.seglc[i.id];
|
||||
hasRGB = !!(lc & 0x01);
|
||||
hasWhite = !!(lc & 0x08); // & 0x02 contains W channel
|
||||
hasWhite = !!(lc & 0x02);
|
||||
hasCCT = !!(lc & 0x04);
|
||||
}
|
||||
if (!i) {
|
||||
@ -1318,7 +1359,7 @@ function readState(s,command=false)
|
||||
cd[e].dataset.r = i.col[e][0];
|
||||
cd[e].dataset.g = i.col[e][1];
|
||||
cd[e].dataset.b = i.col[e][2];
|
||||
if (hasWhite) { cd[e].dataset.w = i.col[e][3]; }
|
||||
if (hasWhite || (!hasRGB && !hasWhite)) { cd[e].dataset.w = i.col[e][3]; }
|
||||
setCSL(cd[e]);
|
||||
}
|
||||
selectSlot(csel);
|
||||
@ -1470,8 +1511,8 @@ function setEffectParameters(idx)
|
||||
var palw = gId("palw"); // wrapper
|
||||
var pall = gId("pall"); // label
|
||||
// if not controlDefined or palette has a value
|
||||
if ((!controlDefined) || (paOnOff.length>0 && paOnOff[0]!="" && isNaN(paOnOff[0]))) {
|
||||
palw.style.display = hasRGB ? "inline-block" : "none";
|
||||
if (hasRGB && ((!controlDefined) || (paOnOff.length>0 && paOnOff[0]!="" && isNaN(paOnOff[0])))) {
|
||||
palw.style.display = "inline-block";
|
||||
if (paOnOff.length>0 && paOnOff[0].indexOf("=")>0) {
|
||||
// embeded default values
|
||||
var dPos = paOnOff[0].indexOf("=");
|
||||
@ -1681,22 +1722,22 @@ function makeSeg()
|
||||
});
|
||||
var cn = `<div class="seg lstI expanded">
|
||||
<div class="segin">
|
||||
<input type="text" class="noslide" id="seg${lu}t" autocomplete="off" maxlength=32 value="" placeholder="New segment ${lu}"/>
|
||||
<input type="text" id="seg${lu}t" autocomplete="off" maxlength=32 value="" placeholder="New segment ${lu}"/>
|
||||
<table class="segt">
|
||||
<tr>
|
||||
<td width="38%">${isM?'Start X':'Start LED'}</td>
|
||||
<td width="38%">${isM?(cfg.comp.seglen?"Width":"Stop X"):(cfg.comp.seglen?"LED count":"Stop LED")}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input class="noslide segn" id="seg${lu}s" type="number" min="0" max="${isM?mw-1:ledCount-1}" value="${ns}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
|
||||
<td><input class="noslide segn" id="seg${lu}e" type="number" min="0" max="${ct}" value="${ct}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
|
||||
<td><input class="segn" id="seg${lu}s" type="number" min="0" max="${isM?mw-1:ledCount-1}" value="${ns}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
|
||||
<td><input class="segn" id="seg${lu}e" type="number" min="0" max="${ct}" value="${ct}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
|
||||
<td><button class="btn btn-xs" onclick="setSeg(${lu});"><i class="icons bth-icon" id="segc${lu}"></i></button></td>
|
||||
</tr>
|
||||
${isM ? '<tr><td>Start Y</td><td>'+(cfg.comp.seglen?'Height':'Stop Y')+'</td></tr>'+
|
||||
'<tr>'+
|
||||
'<td><input class="noslide segn" id="seg'+lu+'sY" type="number" min="0" max="'+(mh-1)+'" value="'+0+'" oninput="updateLen('+lu+')" onkeydown="segEnter('+lu+')"></td>'+
|
||||
'<td><input class="noslide segn" id="seg'+lu+'eY" type="number" min="0" max="'+mh+'" value="'+mh+'" oninput="updateLen('+lu+')" onkeydown="segEnter('+lu+')"></td>'+
|
||||
'</tr>':''}
|
||||
<tr id="mkSYH" class="${isM?"":"hide"}"><td>Start Y</td><td>${cfg.comp.seglen?'Height':'Stop Y'}</td></tr>
|
||||
<tr id="mkSYD" class="${isM?"":"hide"}">
|
||||
<td><input class="segn" id="seg${lu}sY" type="number" min="0" max="${mh-1}" value="0" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
|
||||
<td><input class="segn" id="seg${lu}eY" type="number" min="0" max="${mh}" value="${isM?mh:1}" oninput="updateLen(${lu})" onkeydown="segEnter(${lu})"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="h" id="seg${lu}len">${ledCount - ns} LEDs</div>
|
||||
<div class="c"><button class="btn btn-p" onclick="resetUtil()">Cancel</button></div>
|
||||
@ -1820,7 +1861,7 @@ function makeP(i,pl)
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
<div id="pl${i}o1" style="display:${rep>0?"block":"none"}">
|
||||
<div class="c">Repeat <input class="noslide" type="number" id="pl${i}rp" oninput="plR(${i})" max=127 min=0 value=${rep>0?rep:1}> times</div>
|
||||
<div class="c">Repeat <input type="number" id="pl${i}rp" oninput="plR(${i})" max=127 min=0 value=${rep>0?rep:1}> times</div>
|
||||
<div class="sel">End preset:<br>
|
||||
<div class="sel-p"><select class="sel-ple" id="pl${i}selEnd" onchange="plR(${i})" data-val=${plJson[i].end?plJson[i].end:0}>
|
||||
<option value="0">None</option>
|
||||
@ -1852,15 +1893,15 @@ ${makePlSel(plJson[i].end?plJson[i].end:0, true)}
|
||||
<input type="checkbox" id="p${i}sbchk">
|
||||
<span class="checkmark"></span>
|
||||
</label>`;
|
||||
if (!isM && Array.isArray(lastinfo.maps) && lastinfo.maps.length>1) {
|
||||
if (Array.isArray(lastinfo.maps) && lastinfo.maps.length>1) {
|
||||
content += `<div class="lbl-l">Ledmap: <div class="sel-p"><select class="sel-p" id="p${i}lmp"><option value="">Unchanged</option>`;
|
||||
for (const k of (lastinfo.maps||[])) content += `<option value="${k}"${(i>0 && pJson[i].ledmap==k)?" selected":""}>${k==0?'Default':'ledmap'+k+'.json'}</option>`;
|
||||
for (const k of (lastinfo.maps||[])) content += `<option value="${k.id}"${(i>0 && pJson[i].ledmap==k.id)?" selected":""}>${k.id==0?'Default':(k.n?k.n:'ledmap'+k.id+'.json')}</option>`;
|
||||
content += "</select></div></div>";
|
||||
}
|
||||
}
|
||||
|
||||
return `<input type="text" class="ptxt noslide ${i==0?'show':''}" id="p${i}txt" autocomplete="off" maxlength=32 value="${(i>0)?pName(i):""}" placeholder="Enter name..."/>
|
||||
<div class="c">Quick load label: <input type="text" class="stxt noslide" maxlength=2 value="${qlName(i)}" id="p${i}ql" autocomplete="off"/></div>
|
||||
return `<input type="text" class="ptxt ${i==0?'show':''}" id="p${i}txt" autocomplete="off" maxlength=32 value="${(i>0)?pName(i):""}" placeholder="Enter name..."/>
|
||||
<div class="c">Quick load label: <input type="text" class="stxt" maxlength=2 value="${qlName(i)}" id="p${i}ql" autocomplete="off"/></div>
|
||||
<div class="h">(leave empty for no Quick load button)</div>
|
||||
<div ${pl&&i==0?"style='display:none'":""}>
|
||||
<label class="check revchkl">
|
||||
@ -1871,9 +1912,9 @@ ${makePlSel(plJson[i].end?plJson[i].end:0, true)}
|
||||
<span class="checkmark"></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="po2" id="p${i}o2">API command<br><textarea class="apitxt noslide" id="p${i}api"></textarea></div>
|
||||
<div class="po2" id="p${i}o2">API command<br><textarea class="apitxt" id="p${i}api"></textarea></div>
|
||||
<div class="po1" id="p${i}o1">${content}</div>
|
||||
<div class="c m6">Save to ID <input class="noslide" id="p${i}id" type="number" oninput="checkUsed(${i})" max=250 min=1 value=${(i>0)?i:getLowestUnusedP()}></div>
|
||||
<div class="c m6">Save to ID <input id="p${i}id" type="number" oninput="checkUsed(${i})" max=250 min=1 value=${(i>0)?i:getLowestUnusedP()}></div>
|
||||
<div class="c">
|
||||
<button class="btn btn-p" onclick="saveP(${i},${pl})"><i class="icons btn-icon"></i>Save</button>
|
||||
${(i>0)?'<button class="btn btn-p" id="p'+i+'del" onclick="delP('+i+')"><i class="icons btn-icon"></i>Delete':'<button class="btn btn-p" onclick="resetPUtil()">Cancel'}</button>
|
||||
@ -1918,8 +1959,8 @@ function makePlEntry(p,i)
|
||||
<td class="c">#${i+1}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="c" width="40%"><input class="noslide segn" type="number" placeholder="Duration" max=6553.0 min=0.2 step=0.1 oninput="pleDur(${p},${i},this)" value="${plJson[p].dur[i]/10.0}">s</td>
|
||||
<td class="c" width="40%"><input class="noslide segn" type="number" placeholder="Transition" max=65.0 min=0.0 step=0.1 oninput="pleTr(${p},${i},this)" value="${plJson[p].transition[i]/10.0}">s</td>
|
||||
<td class="c" width="40%"><input class="segn" type="number" placeholder="Duration" max=6553.0 min=0.2 step=0.1 oninput="pleDur(${p},${i},this)" value="${plJson[p].dur[i]/10.0}">s</td>
|
||||
<td class="c" width="40%"><input class="segn" type="number" placeholder="Transition" max=65.0 min=0.0 step=0.1 oninput="pleTr(${p},${i},this)" value="${plJson[p].transition[i]/10.0}">s</td>
|
||||
<td class="c"><button class="btn btn-pl-del" onclick="delPl(${p},${i})"><i class="icons btn-icon"></i></button></div></td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -2026,29 +2067,30 @@ function setSeg(s)
|
||||
let sX = gId(`seg${s}s`);
|
||||
let eX = gId(`seg${s}e`);
|
||||
var start = parseInt(sX.value);
|
||||
var stop = parseInt(eX.value);
|
||||
var stop = parseInt(eX.value) + (cfg.comp.seglen?start:0);
|
||||
if (start<sX.min || start>sX.max) {sX.value=sX.min; return;} // prevent out of bounds
|
||||
if (stop<eX.min || stop>eX.max) {eX.value=eX.max; return;} // prevent out of bounds
|
||||
if (stop<eX.min || stop-(cfg.comp.seglen?start:0)>eX.max) {eX.value=eX.max; return;} // prevent out of bounds
|
||||
if ((cfg.comp.seglen && stop == 0) || (!cfg.comp.seglen && stop <= start)) {delSeg(s); return;}
|
||||
var obj = {"seg": {"id": s, "n": name, "start": start, "stop": (cfg.comp.seglen?start:0)+stop}};
|
||||
if (isM) {
|
||||
var obj = {"seg": {"id": s, "n": name, "start": start, "stop": stop}};
|
||||
if (isM && start<mw*mh) {
|
||||
let sY = gId(`seg${s}sY`);
|
||||
let eY = gId(`seg${s}eY`);
|
||||
var startY = parseInt(sY.value);
|
||||
var stopY = parseInt(eY.value);
|
||||
var stopY = parseInt(eY.value) + (cfg.comp.seglen?startY:0);
|
||||
if (startY<sY.min || startY>sY.max) {sY.value=sY.min; return;} // prevent out of bounds
|
||||
if (stopY<eY.min || stopY>eY.max) {eY.value=eY.max; return;} // prevent out of bounds
|
||||
obj.seg.startY = startY;
|
||||
obj.seg.stopY = (cfg.comp.seglen?startY:0)+stopY;
|
||||
obj.seg.stopY = stopY;
|
||||
}
|
||||
if (gId(`seg${s}grp`)) { // advanced options, not present in new segment dialog (makeSeg())
|
||||
var grp = parseInt(gId(`seg${s}grp`).value);
|
||||
var spc = parseInt(gId(`seg${s}spc`).value);
|
||||
var ofs = parseInt(gId(`seg${s}of` ).value);
|
||||
let g = gId(`seg${s}grp`);
|
||||
if (g) { // advanced options, not present in new segment dialog (makeSeg())
|
||||
let grp = parseInt(g.value);
|
||||
let spc = parseInt(gId(`seg${s}spc`).value);
|
||||
let ofs = parseInt(gId(`seg${s}of` ).value);
|
||||
obj.seg.grp = grp;
|
||||
obj.seg.spc = spc;
|
||||
obj.seg.of = ofs;
|
||||
if (isM) obj.seg.tp = gId(`seg${s}tp`).checked;
|
||||
if (isM && gId(`seg${s}tp`)) obj.seg.tp = gId(`seg${s}tp`).checked;
|
||||
}
|
||||
resetUtil(); // close add segment dialog just in case
|
||||
requestJson(obj);
|
||||
@ -2210,7 +2252,7 @@ function setLor(i)
|
||||
function setPreset(i)
|
||||
{
|
||||
var obj = {"ps":i};
|
||||
if (pJson && pJson[i] && (!pJson[i].win || pJson[i].win.indexOf("Please") <= 0)) {
|
||||
if (!isPlaylist(i) && pJson && pJson[i] && (!pJson[i].win || pJson[i].win.indexOf("Please") <= 0)) {
|
||||
// we will send the complete preset content as to avoid delay introduced by
|
||||
// async nature of applyPreset() and having to read the preset from file system.
|
||||
obj = {"pd":i}; // use "pd" instead of "ps" to indicate that we are sending the preset content directly
|
||||
@ -2716,7 +2758,7 @@ function hasIroClass(classList)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//required by rangetouch.js
|
||||
function lock(e)
|
||||
{
|
||||
if (pcMode) return;
|
||||
@ -2730,7 +2772,7 @@ function lock(e)
|
||||
|
||||
_C.classList.toggle('smooth', !(locked = true));
|
||||
}
|
||||
|
||||
//required by rangetouch.js
|
||||
function move(e)
|
||||
{
|
||||
if(!locked || pcMode) return;
|
||||
|
@ -7,11 +7,13 @@
|
||||
<title>2D Set-up</title>
|
||||
<script>
|
||||
var d=document;
|
||||
var loc = false, locip;
|
||||
var loc = false, locip;
|
||||
var maxPanels=64;
|
||||
var ctx = null; // WLEDMM
|
||||
function H(){window.open("https://kno.wled.ge/features/2D");}
|
||||
function B(){window.open("/settings","_self");}
|
||||
function gId(n){return d.getElementById(n);}
|
||||
function fS(){d.Sf.submit();} // <button type=submit> sometimes didn't work
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
@ -33,15 +35,15 @@
|
||||
});
|
||||
}
|
||||
function S() {
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=10';
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=10';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
|
||||
@ -52,6 +54,30 @@
|
||||
return;
|
||||
}
|
||||
gId("mpdiv").style.display = "block";
|
||||
draw();
|
||||
}
|
||||
|
||||
var timeout;
|
||||
function showToast(text, error = false)
|
||||
{
|
||||
var x = gId("toast");
|
||||
x.innerHTML = text;
|
||||
x.className = error ? "error":"show";
|
||||
clearTimeout(timeout);
|
||||
x.style.animation = 'none';
|
||||
timeout = setTimeout(function(){ x.className = x.className.replace("show", ""); }, 2900);
|
||||
}
|
||||
|
||||
function uploadFile(name) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.addEventListener('load', function(){showToast(this.responseText,this.status >= 400)});
|
||||
req.addEventListener('error', function(e){showToast(e.stack,true);});
|
||||
req.open("POST", "/upload");
|
||||
var formData = new FormData();
|
||||
formData.append("data", d.Sf.data.files[0], name);
|
||||
req.send(formData);
|
||||
d.Sf.data.value = '';
|
||||
return false;
|
||||
}
|
||||
|
||||
function addPanels() {
|
||||
@ -67,31 +93,31 @@
|
||||
var pw = parseInt(d.Sf.PW.value);
|
||||
var ph = parseInt(d.Sf.PH.value);
|
||||
let b = `<div id="pnl${i}"><hr class="sml">Panel ${i}<br>
|
||||
1<sup>st</sup> LED: <select name="P${i}B">
|
||||
1<sup>st</sup> LED: <select name="P${i}B" oninput="UI()">
|
||||
<option value="0">Top</option>
|
||||
<option value="1">Bottom</option>
|
||||
</select><select name="P${i}R">
|
||||
</select><select name="P${i}R" oninput="UI()">
|
||||
<option value="0">Left</option>
|
||||
<option value="1">Right</option>
|
||||
</select><br>
|
||||
Orientation: <select name="P${i}V">
|
||||
Orientation: <select name="P${i}V" oninput="UI()">
|
||||
<option value="0">Horizontal</option>
|
||||
<option value="1">Vertical</option>
|
||||
</select><br>
|
||||
Serpentine: <input type="checkbox" name="P${i}S"><br>
|
||||
Dimensions (WxH): <input id="P${i}W" name="P${i}W" type="number" min="1" max="128" value="${pw}"> x <input id="P${i}H" name="P${i}H" type="number" min="1" max="128" value="${ph}"><br>
|
||||
Offset X:<input id="P${i}X" name="P${i}X" type="number" min="0" max="256" value="0">
|
||||
Y:<input id="P${i}Y" name="P${i}Y" type="number" min="0" max="256" value="0"><br><i>(offset from top-left corner in # LEDs)</i>
|
||||
Serpentine: <input type="checkbox" name="P${i}S" oninput="UI()"><br>
|
||||
Dimensions (WxH): <input name="P${i}W" type="number" min="1" max="255" value="${pw}" oninput="UI()"> x <input name="P${i}H" type="number" min="1" max="255" value="${ph}" oninput="UI()"><br>
|
||||
Offset X:<input name="P${i}X" type="number" min="0" max="255" value="0" oninput="UI()">
|
||||
Y:<input name="P${i}Y" type="number" min="0" max="255" value="0" oninput="UI()"><br><i>(offset from top-left corner in # LEDs)</i>
|
||||
</div>`;
|
||||
p.insertAdjacentHTML("beforeend", b);
|
||||
}
|
||||
|
||||
function remPanel() {
|
||||
function remPanel() {
|
||||
let p = gId("panels").children;
|
||||
var i = p.length;
|
||||
if (i <= 1) return;
|
||||
p[i-1].remove();
|
||||
}
|
||||
var i = p.length;
|
||||
if (i <= 1) return;
|
||||
p[i-1].remove();
|
||||
}
|
||||
|
||||
function resetPanels() {
|
||||
d.Sf.MPC.value = 1;
|
||||
@ -107,17 +133,17 @@ Y:<input id="P${i}Y" name="P${i}Y" type="number" min="0" max="256" value="0"><br
|
||||
function gen() {
|
||||
resetPanels();
|
||||
|
||||
var pansH = parseInt(d.Sf.MPH.value);
|
||||
var pansV = parseInt(d.Sf.MPV.value);
|
||||
var pansH = parseInt(Sf.MPH.value);
|
||||
var pansV = parseInt(Sf.MPV.value);
|
||||
var c = pansH*pansV;
|
||||
d.Sf.MPC.value = c; // number of panels
|
||||
Sf.MPC.value = c; // number of panels
|
||||
|
||||
var ps = d.Sf.PS.checked;
|
||||
var pv = d.Sf.PV.value==="1";
|
||||
var pb = d.Sf.PB.value==="1";
|
||||
var pr = d.Sf.PR.value==="1";
|
||||
var pw = parseInt(d.Sf.PW.value);
|
||||
var ph = parseInt(d.Sf.PH.value);
|
||||
var ps = Sf.PS.checked;
|
||||
var pv = Sf.PV.value==="1";
|
||||
var pb = Sf.PB.value==="1";
|
||||
var pr = Sf.PR.value==="1";
|
||||
var pw = parseInt(Sf.PW.value);
|
||||
var ph = parseInt(Sf.PH.value);
|
||||
|
||||
var h = pv ? pansV : pansH;
|
||||
var v = pv ? pansH : pansV;
|
||||
@ -127,13 +153,141 @@ Y:<input id="P${i}Y" name="P${i}Y" type="number" min="0" max="256" value="0"><br
|
||||
var y = (pv?pr:pb) ? v-j-1: j;
|
||||
var x = (pv?pb:pr) ? h-i-1 : i;
|
||||
x = ps && j%2 ? h-x-1 : x;
|
||||
gId("P"+p+"X").value = (pv?y:x) * pw;
|
||||
gId("P"+p+"Y").value = (pv?x:y) * ph
|
||||
gId("P"+p+"W").value = pw;
|
||||
gId("P"+p+"H").value = ph;
|
||||
Sf[`P${p}X`].value = (pv?y:x) * pw;
|
||||
Sf[`P${p}Y`].value = (pv?x:y) * ph
|
||||
Sf[`P${p}W`].value = pw;
|
||||
Sf[`P${p}H`].value = ph;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function expand(o,i)
|
||||
{
|
||||
i.style.display = i.style.display!=="none" ? "none" : "";
|
||||
o.style.rotate = i.style.display==="none" ? "none" : "90deg";
|
||||
}
|
||||
|
||||
function draw() {
|
||||
|
||||
if (!ctx) {
|
||||
//WLEDMM: add canvas, initialize and set UI
|
||||
var canvas = gId("canvas");
|
||||
canvas.width = window.innerWidth > 640?640:400; //Mobile gets 400, pc 640
|
||||
canvas.height = canvas.width;
|
||||
ctx = canvas.getContext('2d');
|
||||
|
||||
// window.requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
//calc max height and width
|
||||
var maxWidth = 0;
|
||||
var maxHeight = 0;
|
||||
for (let p=0; p<gId("panels").children.length; p++) {
|
||||
var px = parseInt(Sf[`P${p}X`].value); //first led x
|
||||
var py = parseInt(Sf[`P${p}Y`].value); //first led y
|
||||
var pw = parseInt(Sf[`P${p}W`].value); //width
|
||||
var ph = parseInt(Sf[`P${p}H`].value); //height
|
||||
maxWidth = Math.max(maxWidth, px + pw);
|
||||
maxHeight = Math.max(maxHeight, py + ph);
|
||||
}
|
||||
|
||||
ctx.canvas.height = ctx.canvas.width / maxWidth * maxHeight;
|
||||
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||
var space=0; // space between panels + margin
|
||||
var ppL = (ctx.canvas.width - space * 2) / maxWidth; //pixels per led
|
||||
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeStyle="yellow";
|
||||
ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height); // add space between panels
|
||||
|
||||
for (let p=0; p<gId("panels").children.length; p++) {
|
||||
var px = parseInt(Sf[`P${p}X`].value); //first led x
|
||||
var py = parseInt(Sf[`P${p}Y`].value); //first led y
|
||||
var pw = parseInt(Sf[`P${p}W`].value); //width
|
||||
var ph = parseInt(Sf[`P${p}H`].value); //height
|
||||
|
||||
var pb = Sf[`P${p}B`].value == "1"; //bottom
|
||||
var pr = Sf[`P${p}R`].value == "1"; //right
|
||||
var pv = Sf[`P${p}V`].value == "1"; //vertical
|
||||
var ps = Sf[`P${p}S`].checked; //serpentine
|
||||
|
||||
var topLeftX = px*ppL + space; //left margin
|
||||
var topLeftY = py*ppL + space; //top margin
|
||||
|
||||
ctx.lineWidth = 3;
|
||||
ctx.strokeStyle="white";
|
||||
ctx.strokeRect(topLeftX, topLeftY, pw*ppL, ph*ppL); // add space between panels
|
||||
|
||||
var lnX;
|
||||
var lnY;
|
||||
|
||||
//find start led
|
||||
if (pb) //bottom
|
||||
lnY = topLeftY + ph*ppL - ppL/2;
|
||||
else //top
|
||||
lnY = topLeftY + ppL/2;
|
||||
if (pr) //right
|
||||
lnX = topLeftX + pw*ppL - ppL/2;
|
||||
else //left
|
||||
lnX = topLeftX + ppL/2;
|
||||
|
||||
//first led
|
||||
ctx.fillStyle = "green";
|
||||
ctx.beginPath();
|
||||
ctx.arc(lnX, lnY, ppL*0.5, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
|
||||
//start line
|
||||
ctx.lineWidth = 1;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(lnX, lnY);
|
||||
|
||||
var longLineLength = (pv?ph:pw)*ppL - ppL;
|
||||
for (let ln=0; ln<(pv?pw:ph); ln++) { //loop over panelwidth (or height of vertical?)
|
||||
|
||||
var serpLine = ps && ln%2!=0; //serp: turn around if even line
|
||||
|
||||
if (pv) //if vertical
|
||||
lnY += (pb?-1:1) * longLineLength * (serpLine?-1:1); //if vertical change the Y
|
||||
else
|
||||
lnX += (pr?-1:1) * longLineLength * (serpLine?-1:1); //if horizontal change the X
|
||||
|
||||
ctx.lineTo(lnX, lnY); //draw the long line
|
||||
|
||||
if (ln<(pv?pw:ph)-1) { //not the last
|
||||
//find the small line end point
|
||||
if (pv) //vertical
|
||||
lnX += (pr?-1:1) * ppL;
|
||||
else //horizontal
|
||||
lnY += (pb?-1:1) * ppL;
|
||||
|
||||
//if serpentine go next else go down
|
||||
if (ps) { //serpentine
|
||||
ctx.lineTo(lnX, lnY); //draw the serpentine line
|
||||
} else {
|
||||
//find the other end of the long line
|
||||
if (pv) //vertical
|
||||
lnY += (pb?1:-1) * longLineLength * (serpLine?-1:1); //min as we go back
|
||||
else //horizontal
|
||||
lnX += (pr?1:-1) * longLineLength * (serpLine?-1:1);
|
||||
ctx.moveTo(lnX, lnY); //move to the start point of the next long line
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.stroke();
|
||||
|
||||
//last led
|
||||
ctx.fillStyle = "red";
|
||||
ctx.beginPath();
|
||||
ctx.arc(lnX, lnY, ppL*0.5, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
|
||||
ctx.font = '40px Arial';
|
||||
ctx.fillStyle = "orange";
|
||||
ctx.fillText(p, topLeftX + pw/2*ppL - 10, topLeftY + ph/2*ppL + 10);
|
||||
}
|
||||
gId("MD").innerHTML = "Matrix Dimensions (W*H=LC): " + maxWidth + " x " + maxHeight + " = " + maxWidth * maxHeight;
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
@ -141,46 +295,55 @@ Y:<input id="P${i}Y" name="P${i}Y" type="number" min="0" max="256" value="0"><br
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="toprow">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="button" onclick="fS()">Save</button><hr>
|
||||
</div>
|
||||
<h2>2D setup</h2>
|
||||
Strip or panel:
|
||||
Strip or panel:
|
||||
<select id="somp" name="SOMP" onchange="resetPanels();addPanels();UI();" >
|
||||
<option value="0">1D Strip</option>
|
||||
<option value="1">2D Matrix</option>
|
||||
</select><br>
|
||||
<div id="mpdiv" style="display:none;">
|
||||
<hr class="sml">
|
||||
<h3>Matrix Generator</h3>
|
||||
Panel dimensions (WxH): <input name="PW" type="number" min="1" max="128" value="8"> x <input name="PH" type="number" min="1" max="128" value="8"><br>
|
||||
Horizontal panels: <input name="MPH" type="number" min="1" max="8" value="1">
|
||||
Vertical panels: <input name="MPV" type="number" min="1" max="8" value="1"><br>
|
||||
1<sup>st</sup> panel: <select name="PB">
|
||||
<option value="0">Top</option>
|
||||
<option value="1">Bottom</option>
|
||||
</select><select name="PR">
|
||||
<option value="0">Left</option>
|
||||
<option value="1">Right</option>
|
||||
</select><br>
|
||||
Orientation: <select name="PV">
|
||||
<option value="0">Horizontal</option>
|
||||
<option value="1">Vertical</option>
|
||||
</select><br>
|
||||
Serpentine: <input type="checkbox" name="PS"><br>
|
||||
<i style="color:#fa0;">Can populate LED panel layout with pre-arranged matrix.<br>These values do not affect final layout.</i><br>
|
||||
<button type="button" onclick="gen()">Populate</button>
|
||||
<h3>Matrix Generator <button type="button" id="expGen" onclick="expand(this,gId('mxGen'));">></button></h3>
|
||||
<div id="mxGen" style="display:none;">
|
||||
Panel dimensions (WxH): <input name="PW" type="number" min="1" max="128" value="8"> x <input name="PH" type="number" min="1" max="128" value="8"><br>
|
||||
Horizontal panels: <input name="MPH" type="number" min="1" max="8" value="1">
|
||||
Vertical panels: <input name="MPV" type="number" min="1" max="8" value="1"><br>
|
||||
1<sup>st</sup> panel: <select name="PB">
|
||||
<option value="0">Top</option>
|
||||
<option value="1">Bottom</option>
|
||||
</select><select name="PR">
|
||||
<option value="0">Left</option>
|
||||
<option value="1">Right</option>
|
||||
</select><br>
|
||||
Orientation: <select name="PV">
|
||||
<option value="0">Horizontal</option>
|
||||
<option value="1">Vertical</option>
|
||||
</select><br>
|
||||
Serpentine: <input type="checkbox" name="PS"><br>
|
||||
<i style="color:#fa0;">Pressing Populate will create LED panel layout with pre-arranged matrix.<br>Values above <i>will not</i> affect final layout.<br>
|
||||
WARNING: You may need to update each panel parameters after they are generated.</i><br>
|
||||
<button type="button" onclick="gen();expand(gId('expGen'),gId('mxGen'));">Populate</button>
|
||||
</div>
|
||||
<hr class="sml">
|
||||
<h3>Panel set-up</h3>
|
||||
Number of panels: <input name="MPC" type="number" min="1" max="64" value="1" oninput="addPanels()"><br>
|
||||
Number of panels: <input name="MPC" type="number" min="1" max="64" value="1" oninput="addPanels();UI();"><br>
|
||||
<i>A matrix is made of 1 or more physical LED panels.<br>
|
||||
<!--Panels should be arranged from top-left to bottom-right order, starting with lower panel number on the left (or top if transposed).<br>-->
|
||||
Each panel can be of different size and/or have different LED orientation and/or starting point and/or layout.</i><br>
|
||||
<h3>LED panel layout</h3>
|
||||
<div id="panels">
|
||||
</div>
|
||||
<hr class="sml">
|
||||
<div id="MD"></div>
|
||||
<canvas id="canvas"></canvas>
|
||||
<div id="json" >Gap file: <input type="file" name="data" accept=".json"><button type="button" class="sml" onclick="uploadFile('/2d-gaps.json')">Upload</button></div>
|
||||
<i>Note: Gap file is a <b>.json</b> file containing an array with number of elements equal to the matrix size.<br>
|
||||
A value of -1 means that pixel at that position is missing, a value of 0 means never paint that pixel, and 1 means regular pixel.</i>
|
||||
</div>
|
||||
<hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
<button type="button" onclick="B()">Back</button><button type="button" onclick="fS()">Save</button>
|
||||
</form>
|
||||
<div id="toast"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,72 +1,72 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta name="viewport" content="width=500">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||
<meta charset="utf-8">
|
||||
<title>DMX Settings</title>
|
||||
<script>
|
||||
var d=document;
|
||||
var loc = false, locip;
|
||||
function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}
|
||||
function B(){window.history.back();}
|
||||
function GCH(num) {
|
||||
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(){
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GCH(15);GetV();mMap();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S(){
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=7';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
<meta name="viewport" content="width=500">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||
<meta charset="utf-8">
|
||||
<title>DMX Settings</title>
|
||||
<script>
|
||||
var d=document;
|
||||
var loc = false, locip;
|
||||
function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}
|
||||
function B(){window.history.back();}
|
||||
function GCH(num) {
|
||||
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(){
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GCH(15);GetV();mMap();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S(){
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=7';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,7 +17,7 @@
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<h2>Please enter settings PIN code</h2>
|
||||
<input type="password" name="PIN" size="4" maxlength="4" minlength="4" pattern="[0-9]*" inputmode="numeric" autofocus>
|
||||
<hr>
|
||||
<hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Submit</button>
|
||||
</form>
|
||||
</body>
|
||||
|
@ -53,7 +53,7 @@
|
||||
req.send(formData);
|
||||
fO.value = '';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function checkNum(o) {
|
||||
const specialkeys = ["Backspace", "Tab", "Enter", "Shift", "Control", "Alt", "Pause", "CapsLock", "Escape", "Space", "PageUp", "PageDown", "End", "Home", "ArrowLeft", "ArrowUp", "ArrowRight", "ArrowDown", "Insert", "Delete"];
|
||||
// true if key is a number or a special key
|
||||
|
@ -1,74 +1,74 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta name="viewport" content="width=500">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||
<meta charset="utf-8">
|
||||
<title>Sync Settings</title>
|
||||
<script>var d=document;
|
||||
var loc = false, locip;
|
||||
function gId(s){return d.getElementById(s);}
|
||||
function toggle(el){gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide");}
|
||||
function H(){window.open("https://kno.wled.ge/interfaces/udp-notifier/");}
|
||||
function B(){window.open("/settings","_self");}
|
||||
function adj(){if (d.Sf.DI.value == 6454) {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;} }
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();SetVal();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function FC()
|
||||
{
|
||||
for(j=0;j<8;j++)
|
||||
{
|
||||
gId("G"+(j+1)).checked=gId("GS").value>>j&1;
|
||||
gId("R"+(j+1)).checked=gId("GR").value>>j&1;
|
||||
}
|
||||
}
|
||||
function GC()
|
||||
{
|
||||
var a=0, b=0;
|
||||
<meta name="viewport" content="width=500">
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||
<meta charset="utf-8">
|
||||
<title>Sync Settings</title>
|
||||
<script>var d=document;
|
||||
var loc = false, locip;
|
||||
function gId(s){return d.getElementById(s);}
|
||||
function toggle(el){gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide");}
|
||||
function H(){window.open("https://kno.wled.ge/interfaces/udp-notifier/");}
|
||||
function B(){window.open("/settings","_self");}
|
||||
function adj(){if (d.Sf.DI.value == 6454) {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;} }
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();SetVal();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function FC()
|
||||
{
|
||||
for(j=0;j<8;j++)
|
||||
{
|
||||
gId("G"+(j+1)).checked=gId("GS").value>>j&1;
|
||||
gId("R"+(j+1)).checked=gId("GR").value>>j&1;
|
||||
}
|
||||
}
|
||||
function GC()
|
||||
{
|
||||
var a=0, b=0;
|
||||
|
||||
var m=1;
|
||||
for(j=0;j<8;j++)
|
||||
{
|
||||
a+=gId("G"+(j+1)).checked*m;
|
||||
b+=gId("R"+(j+1)).checked*m;
|
||||
m*=2;
|
||||
}
|
||||
gId("GS").value=a;
|
||||
gId("GR").value=b;
|
||||
}
|
||||
function SP(){var p = d.Sf.DI.value; gId("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; case 4048: d.Sf.DI.value = 4048; break; }; SP();FC();}
|
||||
function S(){
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
var m=1;
|
||||
for(j=0;j<8;j++)
|
||||
{
|
||||
a+=gId("G"+(j+1)).checked*m;
|
||||
b+=gId("R"+(j+1)).checked*m;
|
||||
m*=2;
|
||||
}
|
||||
gId("GS").value=a;
|
||||
gId("GR").value=b;
|
||||
}
|
||||
function SP(){var p = d.Sf.DI.value; gId("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; case 4048: d.Sf.DI.value = 4048; break; }; SP();FC();}
|
||||
function S(){
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=4';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=4';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post" onsubmit="GC()">
|
||||
@ -84,39 +84,39 @@ UDP Port: <input name="UP" type="number" min="1" max="65535" class="d5" required
|
||||
<input name="GS" id="GS" type="number" style="display: none;"><!-- hidden inputs for bitwise group checkboxes -->
|
||||
<input name="GR" id="GR" type="number" style="display: none;">
|
||||
<table style="margin: 0 auto;">
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
<td>4</td>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
<td>7</td>
|
||||
<td>8</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Send:</td>
|
||||
<td><input type="checkbox" id="G1" name="G1"></td>
|
||||
<td><input type="checkbox" id="G2" name="G2"></td>
|
||||
<td><input type="checkbox" id="G3" name="G3"></td>
|
||||
<td><input type="checkbox" id="G4" name="G4"></td>
|
||||
<td><input type="checkbox" id="G5" name="G5"></td>
|
||||
<td><input type="checkbox" id="G6" name="G6"></td>
|
||||
<td><input type="checkbox" id="G7" name="G7"></td>
|
||||
<td><input type="checkbox" id="G8" name="G8"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Receive:</td>
|
||||
<td><input type="checkbox" id="R1" name="R1"></td>
|
||||
<td><input type="checkbox" id="R2" name="R2"></td>
|
||||
<td><input type="checkbox" id="R3" name="R3"></td>
|
||||
<td><input type="checkbox" id="R4" name="R4"></td>
|
||||
<td><input type="checkbox" id="R5" name="R5"></td>
|
||||
<td><input type="checkbox" id="R6" name="R6"></td>
|
||||
<td><input type="checkbox" id="R7" name="R7"></td>
|
||||
<td><input type="checkbox" id="R8" name="R8"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
<td>4</td>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
<td>7</td>
|
||||
<td>8</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Send:</td>
|
||||
<td><input type="checkbox" id="G1" name="G1"></td>
|
||||
<td><input type="checkbox" id="G2" name="G2"></td>
|
||||
<td><input type="checkbox" id="G3" name="G3"></td>
|
||||
<td><input type="checkbox" id="G4" name="G4"></td>
|
||||
<td><input type="checkbox" id="G5" name="G5"></td>
|
||||
<td><input type="checkbox" id="G6" name="G6"></td>
|
||||
<td><input type="checkbox" id="G7" name="G7"></td>
|
||||
<td><input type="checkbox" id="G8" name="G8"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Receive:</td>
|
||||
<td><input type="checkbox" id="R1" name="R1"></td>
|
||||
<td><input type="checkbox" id="R2" name="R2"></td>
|
||||
<td><input type="checkbox" id="R3" name="R3"></td>
|
||||
<td><input type="checkbox" id="R4" name="R4"></td>
|
||||
<td><input type="checkbox" id="R5" name="R5"></td>
|
||||
<td><input type="checkbox" id="R6" name="R6"></td>
|
||||
<td><input type="checkbox" id="R7" name="R7"></td>
|
||||
<td><input type="checkbox" id="R8" name="R8"></td>
|
||||
</tr>
|
||||
</table><br>
|
||||
Receive: <nowrap><input type="checkbox" name="RB">Brightness,</nowrap> <nowrap><input type="checkbox" name="RC">Color,</nowrap> <nowrap>and <input type="checkbox" name="RX">Effects</nowrap><br>
|
||||
<input type="checkbox" name="SO"> Segment options, <input type="checkbox" name="SG"> bounds<br>
|
||||
@ -149,6 +149,7 @@ Start universe: <input name="EU" type="number" min="0" max="63999" required><br>
|
||||
Skip out-of-sequence packets: <input type="checkbox" name="ES"><br>
|
||||
DMX start address: <input name="DA" type="number" min="1" max="510" required><br>
|
||||
DMX segment spacing: <input name="XX" type="number" min="0" max="150" required><br>
|
||||
E1.31 port priority: <input name="PY" type="number" min="0" max="200" required><br>
|
||||
DMX mode:
|
||||
<select name=DM>
|
||||
<option value=0>Disabled</option>
|
||||
@ -171,7 +172,7 @@ Realtime LED offset: <input name="WO" type="number" min="-255" max="255" require
|
||||
<hr class="sml">
|
||||
<h3>Alexa Voice Assistant</h3>
|
||||
<div id="NoAlexa" class="hide">
|
||||
<em style="color:#fa0;">This firmware build does not include Alexa support.<br></em><br>
|
||||
<em style="color:#fa0;">This firmware build does not include Alexa support.<br></em><br>
|
||||
</div>
|
||||
<div id="Alexa">
|
||||
Emulate Alexa device: <input type="checkbox" name="AL"><br>
|
||||
@ -179,25 +180,15 @@ Alexa invocation name: <input type="text" name="AI" maxlength="32"><br>
|
||||
Also emulate devices to call the first <input name="AP" type="number" class="s" min="0" max="9" required> presets<br><br>
|
||||
</div>
|
||||
<hr class="sml">
|
||||
<div style="color: #fa0;">⚠ <b>Blynk, MQTT and Hue sync all connect to external hosts!<br>
|
||||
<div style="color: #fa0;">⚠ <b>MQTT and Hue sync all connect to external hosts!<br>
|
||||
This may impact the responsiveness of WLED.</b><br>
|
||||
</div>
|
||||
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)
|
||||
<hr class="sml">
|
||||
<h3>Blynk</h3>
|
||||
<div id="NoBlynk" class="hide">
|
||||
<em style="color:#fa0;">This firmware build does not include Blynk support.<br></em>
|
||||
</div>
|
||||
<div id="Blynk">
|
||||
Host: <input type="text" name="BH" maxlength="32">
|
||||
Port: <input name="BP" type="number" min="1" max="65535" value="80" class="d5"><br>
|
||||
Device Auth token: <input name="BK" maxlength="33"><br>
|
||||
<i>Clear the token field to disable. </i><a href="https://kno.wled.ge/interfaces/blynk/" target="_blank">Setup info</a>
|
||||
</div>
|
||||
<h3>MQTT</h3>
|
||||
<div id="NoMQTT" class="hide">
|
||||
<em style="color:#fa0;">This firmware build does not include MQTT support.<br></em>
|
||||
<em style="color:#fa0;">This firmware build does not include MQTT support.<br></em>
|
||||
</div>
|
||||
<div id="MQTT">
|
||||
Enable MQTT: <input type="checkbox" name="MQ"><br>
|
||||
@ -215,7 +206,7 @@ Publish on button press: <input type="checkbox" name="BM"><br>
|
||||
</div>
|
||||
<h3>Philips Hue</h3>
|
||||
<div id="NoHue" class="hide">
|
||||
<em style="color:#fa0;">This firmware build does not include Philips Hue support.<br></em>
|
||||
<em style="color:#fa0;">This firmware build does not include Philips Hue support.<br></em>
|
||||
</div>
|
||||
<div id="Hue">
|
||||
<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
|
||||
|
@ -6,8 +6,8 @@
|
||||
<meta charset="utf-8">
|
||||
<title>Time Settings</title>
|
||||
<script>
|
||||
var d=document;
|
||||
var loc = false, locip;
|
||||
var d=document;
|
||||
var loc = false, locip;
|
||||
var el=false;
|
||||
var ms=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
||||
function H() { window.open("https://kno.wled.ge/features/settings/#time-settings"); }
|
||||
@ -156,7 +156,7 @@
|
||||
</div>
|
||||
<h2>Time setup</h2>
|
||||
Get time from NTP server: <input type="checkbox" name="NT"><br>
|
||||
<input type="text" name="NS" maxlength="32"><br>
|
||||
<input type="text" name="NS" maxlength="32"><br>
|
||||
Use 24h format: <input type="checkbox" name="CF"><br>
|
||||
Time zone:
|
||||
<select name="TZ">
|
||||
@ -181,7 +181,7 @@
|
||||
<option value="18">HST (Hawaii)</option>
|
||||
<option value="19">NOVT (Novosibirsk)</option>
|
||||
<option value="20">AKST/AKDT (Anchorage)</option>
|
||||
<option value="21">MX-CST/CDT</option>
|
||||
<option value="21">MX-CST</option>
|
||||
<option value="22">PKT (Pakistan)</option>
|
||||
</select><br>
|
||||
UTC offset: <input name="UO" type="number" min="-65500" max="65500" required> seconds (max. 18 hours)<br>
|
||||
|
@ -6,234 +6,234 @@
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||
<title>UI Settings</title>
|
||||
<script>
|
||||
var d = document;
|
||||
var loc = false, locip;
|
||||
var initial_ds, initial_st, initial_su;
|
||||
var sett = null;
|
||||
var l = {
|
||||
"comp":{
|
||||
"labels":"Show button labels",
|
||||
"colors":{
|
||||
"LABEL":"Color selection methods",
|
||||
"picker": "Color Wheel",
|
||||
"rgb": "RGB sliders",
|
||||
"quick": "Quick color selectors",
|
||||
"hex": "HEX color input"
|
||||
},
|
||||
"pcmbot": "Show bottom tab bar in PC mode",
|
||||
"pid": "Show preset IDs",
|
||||
"seglen": "Set segment length instead of stop LED",
|
||||
"segpwr": "Hide segment power & brightness",
|
||||
"segexp" : "Always expand first segment",
|
||||
"css": "Enable custom CSS",
|
||||
"hdays": "Enable custom Holidays list"
|
||||
var d = document;
|
||||
var loc = false, locip;
|
||||
var initial_ds, initial_st, initial_su;
|
||||
var sett = null;
|
||||
var l = {
|
||||
"comp":{
|
||||
"labels":"Show button labels",
|
||||
"colors":{
|
||||
"LABEL":"Color selection methods",
|
||||
"picker": "Color Wheel",
|
||||
"rgb": "RGB sliders",
|
||||
"quick": "Quick color selectors",
|
||||
"hex": "HEX color input"
|
||||
},
|
||||
"pcmbot": "Show bottom tab bar in PC mode",
|
||||
"pid": "Show preset IDs",
|
||||
"seglen": "Set segment length instead of stop LED",
|
||||
"segpwr": "Hide segment power & brightness",
|
||||
"segexp" : "Always expand first segment",
|
||||
"css": "Enable custom CSS",
|
||||
"hdays": "Enable custom Holidays list"
|
||||
},
|
||||
"theme":{
|
||||
"alpha": {
|
||||
"bg":"Background opacity",
|
||||
"tab":"Button opacity"
|
||||
},
|
||||
"theme":{
|
||||
"alpha": {
|
||||
"bg":"Background opacity",
|
||||
"tab":"Button opacity"
|
||||
},
|
||||
"bg":{
|
||||
"url":"BG image URL",
|
||||
"random":"Random BG image"
|
||||
},
|
||||
"color":{
|
||||
"bg":"BG HEX color"
|
||||
}
|
||||
"bg":{
|
||||
"url":"BG image URL",
|
||||
"random":"Random BG image"
|
||||
},
|
||||
"color":{
|
||||
"bg":"BG HEX color"
|
||||
}
|
||||
};
|
||||
function gId(s) { return d.getElementById(s); }
|
||||
function toggle(el) { gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide"); }
|
||||
function isObject(item) {
|
||||
return (item && typeof item === 'object' && !Array.isArray(item));
|
||||
}
|
||||
function set(path, obj, val) {
|
||||
var tar = obj;
|
||||
var pList = path.split('_');
|
||||
var len = pList.length;
|
||||
for(var i = 0; i < len-1; i++) {
|
||||
var elem = pList[i];
|
||||
if( !tar[elem] ) tar[elem] = {}
|
||||
tar = tar[elem];
|
||||
}
|
||||
tar[pList[len-1]] = val;
|
||||
};
|
||||
function gId(s) { return d.getElementById(s); }
|
||||
function toggle(el) { gId(el).classList.toggle("hide"); gId('No'+el).classList.toggle("hide"); }
|
||||
function isObject(item) {
|
||||
return (item && typeof item === 'object' && !Array.isArray(item));
|
||||
}
|
||||
function set(path, obj, val) {
|
||||
var tar = obj;
|
||||
var pList = path.split('_');
|
||||
var len = pList.length;
|
||||
for(var i = 0; i < len-1; i++) {
|
||||
var elem = pList[i];
|
||||
if( !tar[elem] ) tar[elem] = {}
|
||||
tar = tar[elem];
|
||||
}
|
||||
var timeout;
|
||||
function showToast(text, error = false)
|
||||
tar[pList[len-1]] = val;
|
||||
}
|
||||
var timeout;
|
||||
function showToast(text, error = false)
|
||||
{
|
||||
var x = gId("toast");
|
||||
x.innerHTML = text;
|
||||
x.classList.add(error ? "error":"show");
|
||||
clearTimeout(timeout);
|
||||
x.style.animation = 'none';
|
||||
timeout = setTimeout(function(){ x.classList.remove("show"); }, 2900);
|
||||
}
|
||||
function addRec(s, path = "", label = null)
|
||||
{
|
||||
var str = "";
|
||||
for (i in s)
|
||||
{
|
||||
var x = gId("toast");
|
||||
x.innerHTML = text;
|
||||
x.classList.add(error ? "error":"show");
|
||||
clearTimeout(timeout);
|
||||
x.style.animation = 'none';
|
||||
timeout = setTimeout(function(){ x.classList.remove("show"); }, 2900);
|
||||
}
|
||||
function addRec(s, path = "", label = null)
|
||||
{
|
||||
var str = "";
|
||||
for (i in s)
|
||||
{
|
||||
var fk = path + (path?'_':'') + i;
|
||||
if (isObject(s[i])) {
|
||||
if (label && label[i] && label[i]["LABEL"]) str += `<h3>${label[i]["LABEL"]}</h3>`;
|
||||
str += addRec(s[i], fk, label? label[i] : null);
|
||||
} else {
|
||||
var lb = fk;
|
||||
if (label && label[i]) lb = label[i];
|
||||
else if (s[i+'LABEL']) lb = s[i+'LABEL'];
|
||||
if (i.indexOf('LABEL') > 0) continue;
|
||||
var t = typeof s[i];
|
||||
if (gId(fk)) { //already exists
|
||||
if(t === 'boolean')
|
||||
{
|
||||
gId(fk).checked = s[i];
|
||||
} else {
|
||||
gId(fk).value = s[i];
|
||||
}
|
||||
if (gId(fk).previousElementSibling.matches('.l')) {
|
||||
gId(fk).previousElementSibling.innerHTML = lb;
|
||||
}
|
||||
var fk = path + (path?'_':'') + i;
|
||||
if (isObject(s[i])) {
|
||||
if (label && label[i] && label[i]["LABEL"]) str += `<h3>${label[i]["LABEL"]}</h3>`;
|
||||
str += addRec(s[i], fk, label? label[i] : null);
|
||||
} else {
|
||||
var lb = fk;
|
||||
if (label && label[i]) lb = label[i];
|
||||
else if (s[i+'LABEL']) lb = s[i+'LABEL'];
|
||||
if (i.indexOf('LABEL') > 0) continue;
|
||||
var t = typeof s[i];
|
||||
if (gId(fk)) { //already exists
|
||||
if(t === 'boolean')
|
||||
{
|
||||
gId(fk).checked = s[i];
|
||||
} else {
|
||||
if(t === 'boolean')
|
||||
{
|
||||
str += `${lb}: <input class="agi cb" type="checkbox" id=${fk} ${s[i]?"checked":""}><br>`;
|
||||
} else if (t === 'number')
|
||||
{
|
||||
str += `${lb}: <input class="agi" type="number" id=${fk} value=${s[i]}><br>`;
|
||||
} else if (t === 'string')
|
||||
{
|
||||
str += `${lb}:<br><input class="agi" id=${fk} value=${s[i]}><br>`;
|
||||
}
|
||||
gId(fk).value = s[i];
|
||||
}
|
||||
if (gId(fk).previousElementSibling.matches('.l')) {
|
||||
gId(fk).previousElementSibling.innerHTML = lb;
|
||||
}
|
||||
} else {
|
||||
if(t === 'boolean')
|
||||
{
|
||||
str += `${lb}: <input class="agi cb" type="checkbox" id=${fk} ${s[i]?"checked":""}><br>`;
|
||||
} else if (t === 'number')
|
||||
{
|
||||
str += `${lb}: <input class="agi" type="number" id=${fk} value=${s[i]}><br>`;
|
||||
} else if (t === 'string')
|
||||
{
|
||||
str += `${lb}:<br><input class="agi" id=${fk} value=${s[i]}><br>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function genForm(s) {
|
||||
var str = "";
|
||||
str = addRec(s,"",l);
|
||||
|
||||
gId('gen').innerHTML = str;
|
||||
function genForm(s) {
|
||||
var str = "";
|
||||
str = addRec(s,"",l);
|
||||
|
||||
gId('gen').innerHTML = str;
|
||||
}
|
||||
function GetLS()
|
||||
{
|
||||
sett = localStorage.getItem('wledUiCfg');
|
||||
if (!sett) gId('lserr').style.display = "inline";
|
||||
try {
|
||||
sett = JSON.parse(sett);
|
||||
} catch (e) {
|
||||
sett = {};
|
||||
gId('lserr').style.display = "inline";
|
||||
gId('lserr').innerHTML = "⚠ Settings JSON parsing failed. (" + e + ")";
|
||||
}
|
||||
function GetLS()
|
||||
{
|
||||
sett = localStorage.getItem('wledUiCfg');
|
||||
if (!sett) gId('lserr').style.display = "inline";
|
||||
try {
|
||||
sett = JSON.parse(sett);
|
||||
} catch (e) {
|
||||
sett = {};
|
||||
gId('lserr').style.display = "inline";
|
||||
gId('lserr').innerHTML = "⚠ Settings JSON parsing failed. (" + e + ")";
|
||||
}
|
||||
genForm(sett);
|
||||
gId('dm').checked = (gId('theme_base').value === 'light');
|
||||
genForm(sett);
|
||||
gId('dm').checked = (gId('theme_base').value === 'light');
|
||||
}
|
||||
|
||||
function SetLS()
|
||||
{
|
||||
var l = d.querySelectorAll('.agi');
|
||||
for (var i = 0; i < l.length; i++) {
|
||||
var e = l[i];
|
||||
var val = e.classList.contains('cb') ? e.checked : e.value;
|
||||
set(e.id, sett, val);
|
||||
console.log(`${e.id} set to ${val}`);
|
||||
}
|
||||
try {
|
||||
localStorage.setItem('wledUiCfg', JSON.stringify(sett));
|
||||
gId('lssuc').style.display = "inline";
|
||||
} catch (e) {
|
||||
gId('lssuc').style.display = "none";
|
||||
gId('lserr').style.display = "inline";
|
||||
gId('lserr').innerHTML = "⚠ Settings JSON saving failed. (" + e + ")";
|
||||
}
|
||||
}
|
||||
|
||||
function cLS()
|
||||
{
|
||||
localStorage.removeItem('wledP');
|
||||
localStorage.removeItem('wledPmt');
|
||||
localStorage.removeItem('wledPalx');
|
||||
showToast("Cleared.");
|
||||
}
|
||||
|
||||
function SetLS()
|
||||
{
|
||||
var l = d.querySelectorAll('.agi');
|
||||
for (var i = 0; i < l.length; i++) {
|
||||
var e = l[i];
|
||||
var val = e.classList.contains('cb') ? e.checked : e.value;
|
||||
set(e.id, sett, val);
|
||||
console.log(`${e.id} set to ${val}`);
|
||||
}
|
||||
try {
|
||||
localStorage.setItem('wledUiCfg', JSON.stringify(sett));
|
||||
gId('lssuc').style.display = "inline";
|
||||
} catch (e) {
|
||||
gId('lssuc').style.display = "none";
|
||||
gId('lserr').style.display = "inline";
|
||||
gId('lserr').innerHTML = "⚠ Settings JSON saving failed. (" + e + ")";
|
||||
function Save() {
|
||||
SetLS();
|
||||
if (d.Sf.DS.value != initial_ds || d.Sf.ST.checked != initial_st || d.Sf.SU.checked != initial_su) d.Sf.submit();
|
||||
}
|
||||
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();
|
||||
initial_ds = d.Sf.DS.value;
|
||||
initial_st = d.Sf.ST.checked;
|
||||
initial_su = d.Sf.SU.checked;
|
||||
GetLS();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S()
|
||||
{
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=3';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
function H() { window.open("https://kno.wled.ge/features/settings/#user-interface-settings"); }
|
||||
function B() { window.open("/settings","_self"); }
|
||||
function UI()
|
||||
{
|
||||
gId('idonthateyou').style.display = (gId('dm').checked) ? 'inline':'none';
|
||||
var f = gId('theme_base');
|
||||
if (f) f.value = (gId('dm').checked) ? 'light':'dark';
|
||||
}
|
||||
|
||||
function cLS()
|
||||
{
|
||||
localStorage.removeItem('wledP');
|
||||
localStorage.removeItem('wledPmt');
|
||||
localStorage.removeItem('wledPalx');
|
||||
showToast("Cleared.");
|
||||
// random BG image
|
||||
function setRandomBg() {
|
||||
if (gId("theme_bg_random").checked) {
|
||||
gId("theme_bg_url").value = "https://picsum.photos/1920/1080";
|
||||
} else {
|
||||
gId("theme_bg_url").value = "";
|
||||
}
|
||||
|
||||
function Save() {
|
||||
SetLS();
|
||||
if (d.Sf.DS.value != initial_ds || d.Sf.ST.checked != initial_st || d.Sf.SU.checked != initial_su) d.Sf.submit();
|
||||
}
|
||||
|
||||
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||
function loadJS(FILE_URL, async = true) {
|
||||
let scE = d.createElement("script");
|
||||
scE.setAttribute("src", FILE_URL);
|
||||
scE.setAttribute("type", "text/javascript");
|
||||
scE.setAttribute("async", async);
|
||||
d.body.appendChild(scE);
|
||||
// success event
|
||||
scE.addEventListener("load", () => {
|
||||
//console.log("File loaded");
|
||||
GetV();
|
||||
initial_ds = d.Sf.DS.value;
|
||||
initial_st = d.Sf.ST.checked;
|
||||
initial_su = d.Sf.SU.checked;
|
||||
GetLS();
|
||||
});
|
||||
// error event
|
||||
scE.addEventListener("error", (ev) => {
|
||||
console.log("Error on loading file", ev);
|
||||
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||
});
|
||||
}
|
||||
function S()
|
||||
{
|
||||
if (window.location.protocol == "file:") {
|
||||
loc = true;
|
||||
locip = localStorage.getItem('locIp');
|
||||
if (!locip) {
|
||||
locip = prompt("File Mode. Please enter WLED IP!");
|
||||
localStorage.setItem('locIp', locip);
|
||||
}
|
||||
}
|
||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=3';
|
||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||
}
|
||||
function H() { window.open("https://kno.wled.ge/features/settings/#user-interface-settings"); }
|
||||
function B() { window.open("/settings","_self"); }
|
||||
function UI()
|
||||
{
|
||||
gId('idonthateyou').style.display = (gId('dm').checked) ? 'inline':'none';
|
||||
var f = gId('theme_base');
|
||||
if (f) f.value = (gId('dm').checked) ? 'light':'dark';
|
||||
}
|
||||
|
||||
// random BG image
|
||||
function setRandomBg() {
|
||||
if (gId("theme_bg_random").checked) {
|
||||
gId("theme_bg_url").value = "https://picsum.photos/1920/1080";
|
||||
} else {
|
||||
gId("theme_bg_url").value = "";
|
||||
}
|
||||
|
||||
}
|
||||
function checkRandomBg() {
|
||||
if (gId("theme_bg_url").value === "https://picsum.photos/1920/1080") {
|
||||
gId("theme_bg_random").checked = true;
|
||||
} else {
|
||||
gId("theme_bg_random").checked = false;
|
||||
}
|
||||
}
|
||||
function uploadFile(fO,name) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.addEventListener('load', function(){showToast(this.responseText,this.status >= 400)});
|
||||
req.addEventListener('error', function(e){showToast(e.stack,true);});
|
||||
req.open("POST", "/upload");
|
||||
var formData = new FormData();
|
||||
formData.append("data", fO.files[0], name);
|
||||
req.send(formData);
|
||||
fO.value = '';
|
||||
return false;
|
||||
}
|
||||
function checkRandomBg() {
|
||||
if (gId("theme_bg_url").value === "https://picsum.photos/1920/1080") {
|
||||
gId("theme_bg_random").checked = true;
|
||||
} else {
|
||||
gId("theme_bg_random").checked = false;
|
||||
}
|
||||
}
|
||||
function uploadFile(fO,name) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.addEventListener('load', function(){showToast(this.responseText,this.status >= 400)});
|
||||
req.addEventListener('error', function(e){showToast(e.stack,true);});
|
||||
req.open("POST", "/upload");
|
||||
var formData = new FormData();
|
||||
formData.append("data", fO.files[0], name);
|
||||
req.send(formData);
|
||||
fO.value = '';
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
<style>@import url("style.css");</style>
|
||||
</head>
|
||||
|
@ -127,19 +127,19 @@
|
||||
<p class="label h">RGB channels</p>
|
||||
<div id="rwrap" class="il">
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderR" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
|
||||
<input id="sliderR" class="noslide" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
</div><br>
|
||||
<div id="gwrap" class="il">
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderG" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
|
||||
<input id="sliderG" class="noslide" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
</div><br>
|
||||
<div id="bwrap" class="il">
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderB" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
|
||||
<input id="sliderB" class="noslide" onchange="fromRgb()" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
</div><br>
|
||||
@ -147,14 +147,14 @@
|
||||
<div id="wwrap" class="center">
|
||||
<p class="label h">White channel</p>
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderW" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
||||
<input id="sliderW" class="noslide" onchange="setColor(0)" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="wbal">
|
||||
<p class="label h">White balance</p>
|
||||
<div class="sliderwrap il">
|
||||
<input id="sliderA" onchange="setBalance(this.value)" max="255" min="0" type="range" value="128" />
|
||||
<input id="sliderA" class="noslide" onchange="setBalance(this.value)" max="255" min="0" type="range" value="128" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -551,7 +551,7 @@ function populateSegments(s)
|
||||
<div class="il">
|
||||
<i class="icons slider-icon pwr ${powered[i] ? "act":""}" id="seg${i}pwr" onclick="setSegPwr(${i})" title="${inst.n}"></i>
|
||||
<div id="sliderSeg${i}Bri" class="sliderwrap il">
|
||||
<input id="seg${i}bri" class="noslide" onchange="setSegBri(${i})" oninput="updateTrail(this)" max="255" min="1" type="range" value="${inst.bri}" />
|
||||
<input id="seg${i}bri" onchange="setSegBri(${i})" oninput="updateTrail(this)" max="255" min="1" type="range" value="${inst.bri}" />
|
||||
<div class="sliderdisplay"></div>
|
||||
</div>
|
||||
<output class="sliderbubble"></output>
|
||||
@ -1379,7 +1379,7 @@ function hasIroClass(classList)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//required by rangetouch.js
|
||||
function lock(e)
|
||||
{
|
||||
var l = e.target.classList;
|
||||
@ -1392,7 +1392,7 @@ function lock(e)
|
||||
|
||||
_C.classList.toggle('smooth', !(locked = true));
|
||||
}
|
||||
|
||||
//required by rangetouch.js
|
||||
function move(e)
|
||||
{
|
||||
if(!locked) return;
|
||||
|
@ -70,10 +70,20 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){
|
||||
seq = p->art_sequence_number;
|
||||
mde = REALTIME_MODE_ARTNET;
|
||||
} else if (protocol == P_E131) {
|
||||
// Ignore PREVIEW data (E1.31: 6.2.6)
|
||||
if ((p->options & 0x80) != 0) return;
|
||||
dmxChannels = htons(p->property_value_count) - 1;
|
||||
// DMX level data is zero start code. Ignore everything else. (E1.11: 8.5)
|
||||
if (dmxChannels == 0 || p->property_values[0] != 0) return;
|
||||
uni = htons(p->universe);
|
||||
dmxChannels = htons(p->property_value_count) -1;
|
||||
e131_data = p->property_values;
|
||||
seq = p->sequence_number;
|
||||
if (e131Priority != 0) {
|
||||
if (p->priority < e131Priority ) return;
|
||||
// track highest priority & skip all lower priorities
|
||||
if (p->priority >= highPriority.get()) highPriority.set(p->priority);
|
||||
if (p->priority < highPriority.get()) return;
|
||||
}
|
||||
} else { //DDP
|
||||
realtimeIP = clientIP;
|
||||
handleDDPPacket(p);
|
||||
|
@ -13,13 +13,6 @@ void handleAlexa();
|
||||
void onAlexaChange(EspalexaDevice* dev);
|
||||
#endif
|
||||
|
||||
//blynk.cpp
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
void initBlynk(const char* auth, const char* host, uint16_t port);
|
||||
void handleBlynk();
|
||||
void updateBlynk();
|
||||
#endif
|
||||
|
||||
//button.cpp
|
||||
void shortPressAction(uint8_t b=0);
|
||||
void longPressAction(uint8_t b=0);
|
||||
@ -131,7 +124,7 @@ void handleIR();
|
||||
#include "src/dependencies/json/AsyncJson-v6.h"
|
||||
#include "FX.h"
|
||||
|
||||
void deserializeSegment(JsonObject elem, byte it, byte presetId = 0);
|
||||
bool deserializeSegment(JsonObject elem, byte it, byte presetId = 0);
|
||||
bool deserializeState(JsonObject root, byte callMode = CALL_MODE_DIRECT_CHANGE, byte presetId = 0);
|
||||
void serializeSegment(JsonObject& root, Segment& seg, byte id, bool forPreset = false, bool segmentBounds = true);
|
||||
void serializeState(JsonObject root, bool forPreset = false, bool includeBri = true, bool segmentBounds = true, bool selectedSegmentsOnly = false);
|
||||
@ -264,19 +257,20 @@ class Usermod {
|
||||
virtual ~Usermod() { if (um_data) delete um_data; }
|
||||
virtual void setup() = 0; // pure virtual, has to be overriden
|
||||
virtual void loop() = 0; // pure virtual, has to be overriden
|
||||
virtual void handleOverlayDraw() {}
|
||||
virtual bool handleButton(uint8_t b) { return false; }
|
||||
virtual bool getUMData(um_data_t **data) { if (data) *data = nullptr; return false; };
|
||||
virtual void connected() {}
|
||||
virtual void appendConfigData() {}
|
||||
virtual void addToJsonState(JsonObject& obj) {}
|
||||
virtual void addToJsonInfo(JsonObject& obj) {}
|
||||
virtual void readFromJsonState(JsonObject& obj) {}
|
||||
virtual void addToConfig(JsonObject& obj) {}
|
||||
virtual void handleOverlayDraw() {} // called after all effects have been processed, just before strip.show()
|
||||
virtual bool handleButton(uint8_t b) { return false; } // button overrides are possible here
|
||||
virtual bool getUMData(um_data_t **data) { if (data) *data = nullptr; return false; }; // usermod data exchange [see examples for audio effects]
|
||||
virtual void connected() {} // called when WiFi is (re)connected
|
||||
virtual void appendConfigData() {} // helper function called from usermod settings page to add metadata for entry fields
|
||||
virtual void addToJsonState(JsonObject& obj) {} // add JSON objects for WLED state
|
||||
virtual void addToJsonInfo(JsonObject& obj) {} // add JSON objects for UI Info page
|
||||
virtual void readFromJsonState(JsonObject& obj) {} // process JSON messages received from web server
|
||||
virtual void addToConfig(JsonObject& obj) {} // add JSON entries that go to cfg.json
|
||||
virtual bool readFromConfig(JsonObject& obj) { return true; } // Note as of 2021-06 readFromConfig() now needs to return a bool, see usermod_v2_example.h
|
||||
virtual void onMqttConnect(bool sessionPresent) {}
|
||||
virtual bool onMqttMessage(char* topic, char* payload) { return false; }
|
||||
virtual void onUpdateBegin(bool) {}
|
||||
virtual void onMqttConnect(bool sessionPresent) {} // fired when MQTT connection is established (so usermod can subscribe)
|
||||
virtual bool onMqttMessage(char* topic, char* payload) { return false; } // fired upon MQTT message received (wled topic)
|
||||
virtual void onUpdateBegin(bool) {} // fired prior to and after unsuccessful firmware update
|
||||
virtual void onStateChange(uint8_t mode) {} // fired upon WLED state change
|
||||
virtual uint16_t getId() {return USERMOD_ID_UNSPECIFIED;}
|
||||
};
|
||||
|
||||
@ -301,6 +295,7 @@ class UsermodManager {
|
||||
void onMqttConnect(bool sessionPresent);
|
||||
bool onMqttMessage(char* topic, char* payload);
|
||||
void onUpdateBegin(bool);
|
||||
void onStateChange(uint8_t);
|
||||
bool add(Usermod* um);
|
||||
Usermod* lookup(uint16_t mod_id);
|
||||
byte getModCount() {return numMods;};
|
||||
|
@ -44,7 +44,7 @@ const char PAGE_dmxmap[] PROGMEM = R"=====()=====";
|
||||
const uint16_t PAGE_update_length = 615;
|
||||
const uint8_t PAGE_update[] PROGMEM = {
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x75, 0x53, 0x5d, 0x6f, 0xd4, 0x30,
|
||||
0x10, 0x7c, 0xcf, 0xaf, 0x70, 0xfd, 0x74, 0x27, 0x71, 0x4e, 0x8b, 0x78, 0xa1, 0x24, 0x29, 0x1c,
|
||||
0x10, 0x7c, 0xcf, 0xaf, 0x70, 0xfd, 0x74, 0x27, 0x71, 0x4e, 0xa9, 0x78, 0xa1, 0x24, 0x29, 0x1c,
|
||||
0xad, 0x50, 0x25, 0xa4, 0x56, 0x6a, 0x0b, 0xe2, 0x09, 0x39, 0xf6, 0xe6, 0x62, 0xce, 0xb1, 0x53,
|
||||
0x7b, 0x73, 0xa7, 0xa8, 0xea, 0x7f, 0x67, 0xe3, 0xdc, 0x15, 0xc4, 0xc7, 0x4b, 0x14, 0x67, 0x67,
|
||||
0xc7, 0xbb, 0x33, 0x93, 0xe2, 0xe4, 0xf2, 0xe6, 0xe3, 0xfd, 0xb7, 0xdb, 0x2b, 0xd6, 0x62, 0x67,
|
||||
@ -60,13 +60,13 @@ const uint8_t PAGE_update[] PROGMEM = {
|
||||
0x95, 0x3c, 0x8f, 0x80, 0x68, 0xdc, 0x26, 0xe6, 0x51, 0xfc, 0x88, 0x17, 0x7d, 0xf9, 0x96, 0x57,
|
||||
0xbf, 0x21, 0x27, 0xaa, 0x2a, 0x7b, 0x6f, 0xba, 0x49, 0x00, 0x36, 0x04, 0xbb, 0xe0, 0x33, 0xbd,
|
||||
0x8a, 0x91, 0x2f, 0xdf, 0x11, 0x32, 0x21, 0x8a, 0x7c, 0x96, 0xb4, 0xf6, 0x7a, 0x64, 0xde, 0x59,
|
||||
0x2f, 0x75, 0xc9, 0x3f, 0x01, 0x7e, 0x59, 0x2c, 0x89, 0xae, 0x7d, 0x5d, 0x65, 0x49, 0xb2, 0x3b,
|
||||
0xdf, 0xe0, 0x5e, 0x06, 0x78, 0xd1, 0x8e, 0x2a, 0x45, 0xe3, 0x43, 0xc7, 0xc8, 0x8b, 0xd6, 0x53,
|
||||
0xcf, 0xed, 0xcd, 0xdd, 0x3d, 0x67, 0x32, 0xc9, 0x43, 0xc3, 0x0d, 0x09, 0xc7, 0x99, 0xa1, 0x12,
|
||||
0xe9, 0xc1, 0x32, 0x20, 0xe5, 0xc6, 0x9e, 0x4c, 0xe9, 0x06, 0x8b, 0xa6, 0x97, 0x01, 0xf3, 0xa9,
|
||||
0x7f, 0x45, 0x30, 0xc9, 0xe9, 0xe6, 0x38, 0xd4, 0x9d, 0x21, 0x37, 0x1f, 0xa6, 0x8b, 0xaf, 0x5d,
|
||||
0x44, 0x69, 0x2d, 0x68, 0xb6, 0x83, 0x10, 0x89, 0xf1, 0x9c, 0x15, 0xb1, 0x97, 0x8e, 0x65, 0xca,
|
||||
0xca, 0x18, 0x4b, 0x1e, 0x4d, 0xcf, 0xab, 0x53, 0x71, 0xf6, 0x46, 0x9c, 0xae, 0xea, 0x33, 0x5a,
|
||||
0x2f, 0x75, 0xc9, 0x3f, 0x01, 0x7e, 0x59, 0x2c, 0x89, 0xae, 0x3d, 0xab, 0xb2, 0x24, 0xd9, 0x9d,
|
||||
0x6f, 0x70, 0x2f, 0x03, 0xbc, 0x68, 0x47, 0x95, 0xa2, 0xf1, 0xa1, 0x63, 0xe4, 0x45, 0xeb, 0xa9,
|
||||
0xe7, 0xf6, 0xe6, 0xee, 0x9e, 0x33, 0x99, 0xe4, 0xa1, 0xe1, 0x86, 0x84, 0xe3, 0xcc, 0x50, 0x89,
|
||||
0xf4, 0x60, 0x19, 0x90, 0x72, 0x63, 0x4f, 0xa6, 0x74, 0x83, 0x45, 0xd3, 0xcb, 0x80, 0xf9, 0xd4,
|
||||
0xbf, 0x22, 0x98, 0xe4, 0x74, 0x73, 0x1c, 0xea, 0xce, 0x90, 0x9b, 0x0f, 0xd3, 0xc5, 0xd7, 0x2e,
|
||||
0xa2, 0xb4, 0x16, 0x34, 0xdb, 0x41, 0x88, 0xc4, 0x78, 0xce, 0x8a, 0xd8, 0x4b, 0xc7, 0x32, 0x65,
|
||||
0x65, 0x8c, 0x25, 0x8f, 0xa6, 0xe7, 0xd5, 0xa9, 0x78, 0xfd, 0x46, 0x9c, 0xae, 0xea, 0x33, 0x5a,
|
||||
0x86, 0x8a, 0xb4, 0x44, 0xa8, 0x2e, 0xfd, 0x3e, 0x2d, 0xc1, 0xb0, 0x05, 0x66, 0x69, 0x84, 0x88,
|
||||
0xac, 0x36, 0x4e, 0x86, 0x91, 0x28, 0x24, 0xcb, 0xda, 0x00, 0x4d, 0xc9, 0x5b, 0xc4, 0x3e, 0x9e,
|
||||
0xe7, 0xf9, 0xc6, 0x60, 0x3b, 0xd4, 0x42, 0xf9, 0x2e, 0xff, 0x60, 0x82, 0xf2, 0xde, 0x6f, 0x0d,
|
||||
@ -80,8 +80,8 @@ const uint8_t PAGE_update[] PROGMEM = {
|
||||
0x9a, 0x92, 0xfe, 0xab, 0x29, 0x79, 0x54, 0x15, 0xda, 0xec, 0xb2, 0x64, 0xe5, 0x94, 0x53, 0xa2,
|
||||
0xa9, 0x12, 0x3b, 0x85, 0x4f, 0x08, 0x41, 0xe0, 0x44, 0x7e, 0x9b, 0x96, 0x65, 0xda, 0x33, 0xe7,
|
||||
0x91, 0x29, 0xeb, 0xe9, 0xe0, 0x03, 0xcd, 0xda, 0x04, 0x88, 0x6d, 0xf2, 0xa3, 0x97, 0x1b, 0x60,
|
||||
0xe7, 0xcb, 0x22, 0x27, 0xbe, 0x69, 0xdd, 0x29, 0x74, 0x53, 0x02, 0xa7, 0x5f, 0xfb, 0x27, 0xff,
|
||||
0x66, 0x0a, 0x46, 0xf0, 0x03, 0x00, 0x00
|
||||
0xe7, 0xcb, 0x22, 0x27, 0xbe, 0x69, 0xdd, 0x29, 0x74, 0x53, 0x02, 0xa7, 0x5f, 0xfb, 0x27, 0x3b,
|
||||
0x01, 0xc5, 0x54, 0xf0, 0x03, 0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
|
@ -7,526 +7,476 @@
|
||||
*/
|
||||
|
||||
// Autogenerated from wled00/data/pixart/pixart.htm, do not edit!!
|
||||
const uint16_t PAGE_pixart_L = 8313;
|
||||
const uint16_t PAGE_pixart_L = 7510;
|
||||
const uint8_t PAGE_pixart[] PROGMEM = {
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0xd5, 0x3c, 0x6b, 0x7b, 0xda, 0x38,
|
||||
0xb3, 0xdf, 0xf3, 0x2b, 0x54, 0xb7, 0xdb, 0xe2, 0xc5, 0x18, 0xdb, 0x5c, 0x03, 0x71, 0xfa, 0x10,
|
||||
0x72, 0x21, 0xdb, 0x5c, 0x21, 0x49, 0x93, 0xe6, 0xcd, 0xd3, 0x1a, 0x2c, 0xc0, 0x89, 0xb1, 0xa9,
|
||||
0x6d, 0x20, 0x84, 0xf2, 0xdf, 0xcf, 0x8c, 0x64, 0x83, 0xb9, 0xa4, 0x49, 0x7b, 0xba, 0xef, 0x73,
|
||||
0xce, 0x76, 0x83, 0x6d, 0x69, 0x24, 0x8d, 0xe6, 0x3e, 0x23, 0xc3, 0xd6, 0x9b, 0xdd, 0xd3, 0xea,
|
||||
0xc5, 0xcd, 0xd9, 0x1e, 0xe9, 0x06, 0x3d, 0x7b, 0x9b, 0x6c, 0x45, 0x17, 0x6a, 0x98, 0x70, 0xe9,
|
||||
0xd1, 0xc0, 0x80, 0x9e, 0xa0, 0x9f, 0xa2, 0xdf, 0x07, 0xd6, 0x50, 0x17, 0xaa, 0x46, 0xab, 0x4b,
|
||||
0x53, 0x55, 0xd7, 0x09, 0x3c, 0xd7, 0x16, 0xc8, 0x46, 0x0b, 0xee, 0xa8, 0x13, 0xe8, 0x82, 0xe3,
|
||||
0xa6, 0x5a, 0xd8, 0x27, 0x11, 0xb8, 0xf3, 0x03, 0xd7, 0x83, 0xbb, 0xde, 0xc0, 0x0f, 0x52, 0x1e,
|
||||
0x1d, 0x1a, 0xb6, 0x65, 0x1a, 0x01, 0x15, 0xd6, 0x4d, 0x78, 0xe6, 0x19, 0x9d, 0x9e, 0xb1, 0x6e,
|
||||
0xa6, 0xb5, 0xe0, 0x7b, 0x8f, 0x7d, 0xcb, 0xa3, 0xbe, 0x40, 0x66, 0xe0, 0x0a, 0xc2, 0x05, 0x56,
|
||||
0x60, 0xd3, 0xed, 0x8d, 0xcf, 0x47, 0x7b, 0xbb, 0xe4, 0xcc, 0x7a, 0xa4, 0x36, 0xa9, 0x78, 0x01,
|
||||
0x01, 0x34, 0x87, 0xd4, 0x0b, 0xa8, 0xb7, 0x95, 0xe6, 0x00, 0x64, 0xcb, 0x0f, 0xc6, 0x08, 0x28,
|
||||
0x37, 0xdd, 0xc7, 0x49, 0xd3, 0xf5, 0x4c, 0xea, 0x95, 0xb4, 0xfe, 0x23, 0xf1, 0x5d, 0x40, 0x91,
|
||||
0xbc, 0x6d, 0xb7, 0xdb, 0xd3, 0xa6, 0x6b, 0x8e, 0x27, 0x6d, 0x98, 0x3d, 0xd5, 0x36, 0x7a, 0x96,
|
||||
0x3d, 0x2e, 0x55, 0x3c, 0xcb, 0xb0, 0x25, 0xdf, 0x70, 0xfc, 0x94, 0x4f, 0x3d, 0xab, 0x5d, 0x6e,
|
||||
0x1a, 0xad, 0x87, 0x8e, 0xe7, 0x0e, 0x1c, 0x33, 0xd5, 0x72, 0x6d, 0xd7, 0x2b, 0xbd, 0x55, 0x55,
|
||||
0x75, 0x2a, 0x07, 0x6e, 0x3f, 0xd5, 0x37, 0xbc, 0x60, 0x32, 0xb2, 0xcc, 0xa0, 0x5b, 0xca, 0x2b,
|
||||
0x4a, 0xff, 0xb1, 0xdc, 0x33, 0xbc, 0x8e, 0xe5, 0x94, 0x14, 0x62, 0x0c, 0x02, 0x77, 0x2a, 0x23,
|
||||
0xd6, 0x86, 0xe5, 0x50, 0x6f, 0xd2, 0x33, 0x1e, 0x53, 0x1c, 0x50, 0x55, 0x94, 0xbf, 0x48, 0x2a,
|
||||
0x8b, 0xd0, 0x1c, 0xa3, 0x94, 0x67, 0x98, 0xd6, 0xc0, 0x2f, 0x29, 0xe5, 0xbe, 0x61, 0x9a, 0x96,
|
||||
0xd3, 0x29, 0x69, 0xd8, 0x19, 0xd0, 0xc7, 0x20, 0x05, 0xa4, 0xec, 0x38, 0xa5, 0x16, 0xec, 0x9c,
|
||||
0x7a, 0xd3, 0xae, 0xca, 0x11, 0xf5, 0xad, 0x27, 0x5a, 0xd2, 0xe4, 0x0c, 0xed, 0x95, 0x43, 0x84,
|
||||
0x4c, 0xd3, 0x8c, 0x96, 0x56, 0x61, 0x7b, 0x4a, 0xf9, 0xa7, 0x1b, 0xb2, 0x01, 0xa3, 0x54, 0x97,
|
||||
0x5a, 0x9d, 0x6e, 0x50, 0x92, 0x73, 0xd3, 0xae, 0x16, 0x9b, 0x56, 0x95, 0xd5, 0xd9, 0xb4, 0x5e,
|
||||
0xa7, 0x69, 0x24, 0x34, 0x4d, 0x95, 0xa2, 0x3f, 0x39, 0xaf, 0x8a, 0xbf, 0xbd, 0xce, 0xba, 0x0d,
|
||||
0x65, 0x62, 0x2b, 0xcb, 0x85, 0x7f, 0x65, 0x61, 0x55, 0xce, 0xae, 0xae, 0x5c, 0x66, 0x0f, 0x29,
|
||||
0x2b, 0xa0, 0x3d, 0x3f, 0x6a, 0xba, 0x07, 0xe9, 0xb5, 0xda, 0xe3, 0x54, 0x28, 0x69, 0x51, 0xb3,
|
||||
0x69, 0xf9, 0x7d, 0xdb, 0x18, 0x97, 0xda, 0x36, 0x7d, 0x9c, 0xf6, 0xe3, 0x94, 0x9a, 0x93, 0xbf,
|
||||
0x50, 0x28, 0x2c, 0xad, 0x99, 0xfb, 0x29, 0x82, 0xd3, 0xb7, 0x6d, 0x8b, 0xda, 0xe6, 0x85, 0xd1,
|
||||
0xb4, 0x69, 0x7c, 0x46, 0xf2, 0x93, 0x29, 0x5f, 0x98, 0xd0, 0x6f, 0x19, 0x36, 0xfd, 0x93, 0x13,
|
||||
0x9a, 0x1e, 0xc8, 0xf7, 0x93, 0xeb, 0xd0, 0x49, 0x44, 0x81, 0xa6, 0xed, 0xb6, 0x1e, 0xca, 0x73,
|
||||
0x21, 0x8e, 0xcb, 0x70, 0x29, 0x03, 0x5c, 0x31, 0x0d, 0xbf, 0x4b, 0x41, 0xad, 0x50, 0x1a, 0x97,
|
||||
0x45, 0x7b, 0x95, 0x05, 0x0b, 0xc2, 0x1e, 0xe9, 0x4d, 0xb9, 0x35, 0xf0, 0x7c, 0x40, 0xb7, 0xef,
|
||||
0x5a, 0x0c, 0xe8, 0xa7, 0x6c, 0x8e, 0x6d, 0x34, 0x07, 0x73, 0xcc, 0x37, 0x8a, 0xf4, 0xb5, 0x69,
|
||||
0xaa, 0x6f, 0xb5, 0x1e, 0x40, 0xf5, 0x22, 0xfc, 0x1d, 0xd8, 0xcc, 0x54, 0x36, 0x4c, 0xa3, 0x1f,
|
||||
0x58, 0x43, 0x7a, 0xb1, 0x3b, 0x89, 0xb3, 0xb6, 0x8c, 0x1f, 0x29, 0x13, 0x8c, 0x4d, 0x2b, 0xb0,
|
||||
0x5c, 0xa7, 0xe4, 0xb9, 0x23, 0xde, 0x34, 0xf2, 0x8c, 0x3e, 0x0c, 0xc5, 0xcb, 0x1a, 0xa9, 0x99,
|
||||
0xca, 0x3d, 0xd0, 0xef, 0x06, 0xb5, 0x61, 0x98, 0xeb, 0x4d, 0x56, 0x4d, 0x85, 0xa6, 0x69, 0x71,
|
||||
0x25, 0x0d, 0xa9, 0xa5, 0xce, 0x6d, 0x50, 0x26, 0x93, 0x09, 0x77, 0x9f, 0x02, 0x8b, 0x52, 0xca,
|
||||
0xce, 0x88, 0x91, 0x6a, 0xba, 0x41, 0xe0, 0xf6, 0x58, 0x4b, 0x44, 0x2b, 0x85, 0x14, 0xe1, 0x29,
|
||||
0xe4, 0xa0, 0x86, 0xf7, 0x4b, 0x34, 0x58, 0x24, 0x7b, 0xa1, 0x1f, 0xee, 0x0b, 0x70, 0x1a, 0x01,
|
||||
0xc7, 0x17, 0x36, 0xfc, 0x6a, 0x15, 0x98, 0xd3, 0xec, 0xff, 0xdb, 0x3e, 0x39, 0xc7, 0x7d, 0xda,
|
||||
0xe9, 0xc1, 0x46, 0xfc, 0x5d, 0x6b, 0x18, 0xda, 0xea, 0x4c, 0x7e, 0xbe, 0x56, 0xca, 0xa6, 0xed,
|
||||
0xa0, 0x04, 0x73, 0x4e, 0xff, 0x26, 0x96, 0xd3, 0x1f, 0x04, 0xb7, 0xc1, 0xb8, 0x4f, 0x75, 0xcf,
|
||||
0x70, 0x3a, 0xf4, 0x6e, 0x62, 0xf4, 0xfb, 0xd4, 0x80, 0xfb, 0x16, 0x65, 0x93, 0x95, 0x53, 0x3d,
|
||||
0xf7, 0x29, 0xb5, 0xd2, 0x38, 0xa2, 0xcd, 0x07, 0x2b, 0x58, 0x69, 0x8f, 0xa3, 0x34, 0xdb, 0x59,
|
||||
0x24, 0xea, 0xb0, 0x5d, 0xdc, 0x24, 0xc9, 0x32, 0x73, 0xb6, 0x42, 0xd0, 0x00, 0xe6, 0xf1, 0xc1,
|
||||
0xbd, 0x00, 0xe2, 0xcb, 0x3a, 0x31, 0x87, 0x2d, 0xa1, 0x42, 0x1b, 0x1e, 0xac, 0x01, 0x74, 0x00,
|
||||
0xc8, 0x44, 0xe0, 0x12, 0x0f, 0x69, 0x26, 0xbd, 0x6d, 0x36, 0x9b, 0x24, 0xa7, 0xfc, 0x25, 0x21,
|
||||
0xdd, 0xf1, 0x46, 0x5c, 0x25, 0xd9, 0x74, 0x65, 0xbb, 0xa5, 0xb6, 0xdb, 0x1a, 0xf8, 0x13, 0x77,
|
||||
0x10, 0xe0, 0xc4, 0x25, 0x65, 0x0d, 0x44, 0x29, 0xda, 0xac, 0x0f, 0x5c, 0xc5, 0xe9, 0x06, 0x8e,
|
||||
0x83, 0x56, 0x27, 0x05, 0x08, 0xb7, 0x1e, 0x26, 0x71, 0x96, 0x3d, 0x8f, 0xb6, 0x82, 0x3b, 0x7e,
|
||||
0x05, 0x3a, 0xcb, 0x8b, 0x05, 0xdd, 0x41, 0xaf, 0x19, 0xad, 0xa1, 0x22, 0x13, 0x43, 0x6b, 0x94,
|
||||
0x5f, 0x11, 0x09, 0xd8, 0x72, 0x7c, 0x45, 0x74, 0xf5, 0xcb, 0x08, 0x3d, 0xc7, 0xb6, 0x25, 0x29,
|
||||
0x7d, 0x1d, 0xa2, 0x28, 0x17, 0xec, 0x61, 0x0d, 0x21, 0x56, 0x98, 0xcb, 0xfc, 0x9b, 0x22, 0xb1,
|
||||
0x7f, 0xe2, 0xaf, 0x2f, 0xc0, 0xa8, 0x10, 0x6a, 0x98, 0x12, 0xea, 0x57, 0x5c, 0x5e, 0x5e, 0x45,
|
||||
0xa0, 0xc2, 0x02, 0x62, 0x8c, 0x40, 0x53, 0x99, 0x2d, 0x70, 0x02, 0xd3, 0x83, 0xd9, 0xe4, 0x23,
|
||||
0x99, 0x75, 0xc6, 0xa8, 0xca, 0x02, 0x07, 0x13, 0x1a, 0xf0, 0x9e, 0x65, 0x9a, 0x36, 0x28, 0x56,
|
||||
0x7b, 0x60, 0xdb, 0x17, 0x60, 0xd7, 0xf7, 0xd1, 0x99, 0x71, 0x74, 0xd1, 0xcc, 0xdf, 0x3d, 0x63,
|
||||
0x1e, 0xd6, 0xdb, 0x84, 0x48, 0x0d, 0x2d, 0x87, 0x79, 0x27, 0x3f, 0x80, 0x90, 0x0a, 0xd5, 0xf1,
|
||||
0x65, 0x63, 0x11, 0x91, 0x38, 0xbb, 0x26, 0x92, 0xfa, 0x0d, 0xbf, 0xb1, 0xea, 0xb5, 0xfe, 0x94,
|
||||
0xf9, 0x6c, 0xdb, 0x8f, 0x17, 0xfb, 0xb6, 0xf9, 0x67, 0xc8, 0xf2, 0xff, 0x65, 0xd7, 0x0b, 0xd6,
|
||||
0xd4, 0x1f, 0x34, 0x7b, 0xd6, 0xef, 0x09, 0x06, 0x44, 0x8e, 0x10, 0xc4, 0xcc, 0xa3, 0x8e, 0x25,
|
||||
0x6c, 0x19, 0x1d, 0x5e, 0xbb, 0xef, 0xa5, 0x90, 0x19, 0x70, 0x6c, 0x0e, 0x40, 0x9c, 0x9c, 0xff,
|
||||
0x05, 0x67, 0x18, 0x4f, 0xfe, 0x0c, 0x76, 0x8b, 0xe1, 0xfc, 0xef, 0x91, 0x7d, 0xc9, 0xc6, 0x85,
|
||||
0x71, 0x21, 0x7a, 0xbe, 0x97, 0xe6, 0x5b, 0xaf, 0xe3, 0xa8, 0xcf, 0x60, 0x54, 0x8c, 0x49, 0xc7,
|
||||
0xb3, 0xcc, 0x14, 0x13, 0x88, 0xb4, 0x16, 0xdf, 0x6f, 0x24, 0x8e, 0x2c, 0xfb, 0xf9, 0x15, 0x32,
|
||||
0xc6, 0xd8, 0x20, 0x77, 0xc1, 0xba, 0x2f, 0x85, 0x69, 0xfe, 0x10, 0x28, 0x0c, 0x7b, 0x9b, 0xac,
|
||||
0xc7, 0xeb, 0xad, 0xd5, 0x33, 0xc0, 0x14, 0xce, 0xf3, 0xab, 0x68, 0x34, 0xe2, 0x59, 0x66, 0xc8,
|
||||
0xc2, 0xe6, 0xa0, 0x25, 0xa0, 0x88, 0xb5, 0x5f, 0x52, 0xdb, 0x1e, 0x81, 0xbf, 0xe9, 0x5b, 0xce,
|
||||
0xf1, 0x35, 0x23, 0x19, 0x61, 0x22, 0xe6, 0x86, 0x66, 0x46, 0x55, 0x62, 0x81, 0x02, 0x5a, 0x22,
|
||||
0x6c, 0x98, 0xca, 0x7c, 0x8e, 0x96, 0x6d, 0xf8, 0xfe, 0x04, 0x87, 0xcd, 0xfd, 0x3b, 0x03, 0xca,
|
||||
0xf5, 0x57, 0x26, 0xc2, 0xf8, 0x42, 0xee, 0x18, 0xfd, 0x49, 0x44, 0x3a, 0x78, 0x7e, 0xcb, 0xb5,
|
||||
0x22, 0xcc, 0x5a, 0x4b, 0xa5, 0x26, 0x6d, 0x43, 0x1a, 0x3d, 0x89, 0x18, 0x2a, 0x08, 0x33, 0x19,
|
||||
0x08, 0x8d, 0x00, 0x0f, 0xc0, 0x63, 0x44, 0x66, 0x44, 0x28, 0x0d, 0x3c, 0x3b, 0xf1, 0x01, 0x12,
|
||||
0x6e, 0xa3, 0xc4, 0x9e, 0xd3, 0x40, 0xba, 0xe4, 0x63, 0xcf, 0x2e, 0x0f, 0x82, 0x76, 0x51, 0x82,
|
||||
0x14, 0x78, 0xd8, 0x21, 0x2c, 0x0d, 0xd6, 0x85, 0xd0, 0xa4, 0x2f, 0x19, 0x4f, 0x81, 0x0c, 0x2d,
|
||||
0x3a, 0xda, 0x71, 0x1f, 0x21, 0xb9, 0x26, 0x0a, 0xd1, 0xb2, 0xf0, 0xbf, 0x40, 0xb6, 0xfa, 0x46,
|
||||
0xd0, 0x25, 0x10, 0x47, 0xdb, 0xba, 0x00, 0x42, 0x85, 0x8e, 0xa5, 0x8a, 0x2c, 0x13, 0x88, 0xa9,
|
||||
0x0b, 0xc7, 0xaa, 0x26, 0xe5, 0xaf, 0x36, 0x8f, 0xd4, 0xbc, 0x94, 0x3b, 0x82, 0x7b, 0xf5, 0x2a,
|
||||
0x5b, 0x29, 0x4a, 0x45, 0x18, 0x0d, 0x1e, 0x8d, 0x64, 0x25, 0x55, 0xab, 0xc2, 0x47, 0x46, 0xce,
|
||||
0x15, 0x48, 0x56, 0xce, 0xe6, 0x25, 0x35, 0x27, 0x2b, 0x10, 0x86, 0xc8, 0x1a, 0xb4, 0xe6, 0x65,
|
||||
0x2d, 0x7f, 0x94, 0x97, 0x0b, 0x92, 0x9a, 0x95, 0x8b, 0x55, 0x78, 0xca, 0x21, 0xe4, 0x66, 0x81,
|
||||
0x00, 0x58, 0x06, 0x3f, 0xb4, 0x4a, 0x5e, 0xca, 0xb3, 0xa9, 0x54, 0x82, 0xeb, 0x1c, 0xab, 0x45,
|
||||
0xb9, 0x90, 0x97, 0x0a, 0x72, 0x21, 0x7b, 0xa4, 0x16, 0xe4, 0x8c, 0xb4, 0x29, 0x6b, 0x55, 0x15,
|
||||
0x1f, 0x25, 0x55, 0x91, 0x95, 0x2c, 0x51, 0x8b, 0x92, 0xaa, 0xb2, 0xcf, 0xa5, 0xa1, 0x6a, 0xf1,
|
||||
0x4a, 0xcd, 0x1d, 0x41, 0xfb, 0x26, 0x22, 0xa9, 0x65, 0xae, 0x34, 0x25, 0x86, 0xa6, 0xa6, 0x20,
|
||||
0x9e, 0xf8, 0xa9, 0xc8, 0xd9, 0x0c, 0x51, 0x37, 0xe5, 0x5c, 0x56, 0x2a, 0x22, 0x26, 0xf3, 0x05,
|
||||
0xbf, 0x08, 0x24, 0xbd, 0xbd, 0x85, 0x24, 0xdd, 0xfe, 0x20, 0x96, 0x63, 0xd1, 0x63, 0x48, 0x3f,
|
||||
0xbc, 0x07, 0x46, 0x82, 0xfe, 0x82, 0x8e, 0x91, 0xbf, 0x27, 0xeb, 0x38, 0x06, 0xc2, 0x0c, 0xfd,
|
||||
0x87, 0x68, 0x0d, 0x99, 0xa7, 0xf4, 0x43, 0x21, 0xc8, 0xfd, 0xaa, 0xca, 0xbc, 0xc6, 0x55, 0xa6,
|
||||
0x7e, 0xee, 0x23, 0x0a, 0xbf, 0x60, 0x8f, 0x16, 0xbd, 0xc4, 0xd4, 0xc0, 0x68, 0xf3, 0x61, 0xf2,
|
||||
0xb3, 0x0c, 0xfd, 0xa7, 0x51, 0x2c, 0xcb, 0x00, 0x4d, 0xda, 0x72, 0x3d, 0x83, 0x65, 0x58, 0x4c,
|
||||
0xcf, 0x8d, 0xd2, 0xd0, 0xf2, 0xc1, 0x0e, 0x99, 0x7f, 0x7c, 0xde, 0xae, 0x0b, 0x5a, 0x35, 0x89,
|
||||
0x7b, 0xb9, 0xdf, 0x98, 0xc4, 0x68, 0x61, 0xda, 0xf3, 0x87, 0x71, 0xdb, 0x00, 0x79, 0x62, 0x65,
|
||||
0x29, 0xb2, 0x85, 0x14, 0x25, 0x1e, 0x05, 0x15, 0xf3, 0xbb, 0xae, 0x17, 0xb4, 0x06, 0x01, 0x41,
|
||||
0xa3, 0x27, 0x90, 0x8d, 0xae, 0x47, 0xdb, 0xba, 0x10, 0xd3, 0xea, 0xbe, 0xd3, 0x81, 0xb5, 0x7c,
|
||||
0x9a, 0xcf, 0x4a, 0xd6, 0xd5, 0xce, 0x69, 0x7d, 0xa4, 0x7c, 0x3a, 0xe8, 0xb8, 0x15, 0xf8, 0xef,
|
||||
0xa4, 0x71, 0xd9, 0xdd, 0xbb, 0xec, 0xc0, 0xdd, 0x0e, 0x3e, 0x56, 0xce, 0xab, 0x95, 0x1b, 0xbc,
|
||||
0xb6, 0x8b, 0xe9, 0xcd, 0x2e, 0x6b, 0xb9, 0x3e, 0x69, 0xd4, 0x95, 0xc3, 0x8a, 0xe7, 0x67, 0x5b,
|
||||
0xf9, 0x73, 0x78, 0x7e, 0x38, 0xf9, 0xa7, 0xbe, 0xb7, 0x7f, 0x79, 0xba, 0x97, 0xb4, 0x2f, 0xfd,
|
||||
0xe0, 0x54, 0x53, 0x2b, 0x97, 0x4e, 0xed, 0xc4, 0xdf, 0x57, 0xae, 0x92, 0xca, 0xde, 0xf5, 0x95,
|
||||
0x35, 0xac, 0x5c, 0xb7, 0x2b, 0xb4, 0xf0, 0xdd, 0x3e, 0x2a, 0xec, 0x7d, 0xd9, 0x6b, 0x9d, 0xe7,
|
||||
0x5a, 0xe7, 0x45, 0xa7, 0x7a, 0x58, 0x6d, 0xee, 0xfe, 0xb3, 0x5f, 0xb8, 0xf0, 0x86, 0x5d, 0xc3,
|
||||
0xcf, 0xdf, 0x34, 0xc7, 0xbb, 0xe6, 0xce, 0x40, 0xeb, 0x36, 0x1e, 0x0a, 0x0f, 0x56, 0xd7, 0x6f,
|
||||
0x7d, 0x52, 0xdb, 0x97, 0x9b, 0x6a, 0xad, 0xfe, 0xe9, 0x93, 0xb1, 0xdf, 0x56, 0x1f, 0xbb, 0xde,
|
||||
0x59, 0x91, 0xde, 0x1f, 0x3b, 0xd5, 0x5a, 0x31, 0xa7, 0x9c, 0xa5, 0x93, 0xc3, 0x74, 0xab, 0xaa,
|
||||
0x7d, 0x6f, 0x7d, 0x1f, 0x65, 0x3b, 0xfe, 0xc1, 0x6e, 0xa6, 0xf6, 0x90, 0x3e, 0xd0, 0x32, 0xc9,
|
||||
0xe6, 0xb0, 0x61, 0x8e, 0x0a, 0xce, 0x83, 0xfa, 0xa9, 0x58, 0x2c, 0xec, 0xd0, 0xea, 0x79, 0xb6,
|
||||
0x72, 0x70, 0x5c, 0xb1, 0xf6, 0xee, 0x5b, 0x07, 0xc6, 0x4e, 0xa1, 0xe3, 0x98, 0x7b, 0xed, 0x6e,
|
||||
0xfd, 0xbb, 0x59, 0x3f, 0x6f, 0x54, 0x37, 0x9d, 0xd6, 0xb9, 0xf5, 0x50, 0xb9, 0xb2, 0xfc, 0xca,
|
||||
0xe7, 0x83, 0x9d, 0xfd, 0x4e, 0xa7, 0x9e, 0x3b, 0x1f, 0x9e, 0x17, 0x2e, 0x5b, 0x17, 0x27, 0xe6,
|
||||
0x66, 0xef, 0x68, 0xb8, 0x6b, 0x56, 0xb5, 0xbe, 0xe6, 0x75, 0x0f, 0x4f, 0xb4, 0x83, 0xec, 0x65,
|
||||
0x7a, 0x58, 0x6f, 0x3a, 0x74, 0x3c, 0x76, 0x9e, 0xba, 0x7d, 0xbf, 0xa0, 0xb8, 0x95, 0x33, 0xbb,
|
||||
0x7b, 0x72, 0x76, 0x74, 0xff, 0xc5, 0x31, 0xd4, 0x61, 0x36, 0xfd, 0x78, 0xd5, 0x0b, 0xce, 0x6b,
|
||||
0x97, 0xc5, 0xe0, 0xe9, 0xfc, 0xfa, 0x34, 0x53, 0xad, 0x3e, 0x64, 0x1d, 0xef, 0x6c, 0xb7, 0x78,
|
||||
0x7c, 0x74, 0x92, 0xcc, 0x7f, 0x37, 0x8b, 0xb4, 0x5d, 0xa4, 0xde, 0x68, 0xe7, 0xd3, 0xb0, 0x56,
|
||||
0xc8, 0x29, 0xd7, 0x9f, 0xd4, 0xeb, 0x71, 0xd6, 0xb6, 0x36, 0xd3, 0xed, 0xf3, 0x7d, 0x6f, 0xb4,
|
||||
0x79, 0x56, 0x39, 0x68, 0xec, 0x76, 0x8a, 0xc6, 0xd3, 0x60, 0xf4, 0xcf, 0xee, 0x49, 0xfe, 0xbe,
|
||||
0x39, 0xa0, 0xfd, 0x82, 0x91, 0x3c, 0xd8, 0xdf, 0xcf, 0xd0, 0xa7, 0x13, 0x85, 0x3a, 0xb9, 0xf6,
|
||||
0xee, 0xf7, 0xe2, 0x79, 0xdb, 0x49, 0x5e, 0x7e, 0xbf, 0xea, 0xdc, 0x77, 0x3f, 0xe7, 0x9a, 0xf4,
|
||||
0xac, 0x3f, 0xaa, 0x7e, 0x1a, 0x5d, 0xd6, 0xee, 0xf3, 0x86, 0x56, 0xa9, 0xde, 0x14, 0x9e, 0xbc,
|
||||
0xaa, 0x59, 0xad, 0x66, 0xb2, 0x97, 0xf7, 0xde, 0xd3, 0x20, 0xb8, 0x3f, 0xfa, 0x62, 0x9d, 0x57,
|
||||
0xd3, 0x0f, 0x5d, 0xa5, 0x66, 0x8f, 0xcf, 0xc6, 0x83, 0xcd, 0xe0, 0xd3, 0xd3, 0x71, 0xd6, 0x3a,
|
||||
0x38, 0x6b, 0x17, 0x06, 0x07, 0x39, 0x7f, 0x77, 0x6f, 0xf4, 0xb9, 0x7f, 0xf3, 0x79, 0xe8, 0x75,
|
||||
0x8b, 0xb9, 0xfa, 0x97, 0x1b, 0xe0, 0xee, 0x61, 0xbf, 0x90, 0xbc, 0x36, 0xc6, 0x27, 0xc1, 0xf7,
|
||||
0x71, 0x70, 0x4d, 0x8f, 0xbe, 0x7f, 0x6e, 0xde, 0x5f, 0x5e, 0x9e, 0xb4, 0x8e, 0xaa, 0xc9, 0xf6,
|
||||
0xe0, 0x40, 0xeb, 0xf5, 0x8f, 0x06, 0x85, 0xe0, 0xcc, 0xce, 0xf9, 0x5f, 0x76, 0x2b, 0x4e, 0xff,
|
||||
0xe8, 0x41, 0xe9, 0x3d, 0xed, 0xef, 0x5a, 0x5e, 0x72, 0x67, 0xff, 0x1f, 0xfb, 0xa1, 0xba, 0x57,
|
||||
0x35, 0x3e, 0xed, 0x0f, 0x1a, 0x3b, 0x37, 0x0d, 0xbb, 0x92, 0xed, 0x1f, 0x7d, 0x0e, 0xac, 0xfa,
|
||||
0xfd, 0xde, 0xb8, 0x73, 0x38, 0xde, 0xf3, 0xf6, 0x9f, 0xc6, 0x87, 0x9f, 0xee, 0x3d, 0x7a, 0x73,
|
||||
0x61, 0x37, 0xbf, 0x7c, 0xea, 0x18, 0x35, 0xaf, 0x6e, 0x3f, 0xb9, 0x35, 0x37, 0x18, 0xd1, 0x6b,
|
||||
0x5a, 0xe9, 0xee, 0x75, 0x0f, 0x1f, 0xcf, 0x76, 0x2e, 0x76, 0x77, 0xba, 0xe7, 0x37, 0x9d, 0xbd,
|
||||
0x9b, 0xee, 0x49, 0x73, 0xdc, 0x3c, 0x3c, 0xe9, 0x3e, 0xde, 0xa8, 0x7e, 0xb3, 0x31, 0x1a, 0x3d,
|
||||
0x34, 0x6b, 0xa7, 0x5f, 0xbc, 0x27, 0x3f, 0x73, 0x55, 0xef, 0xdd, 0xf7, 0x9c, 0xd3, 0x87, 0x7c,
|
||||
0xf3, 0xf4, 0xc1, 0xfb, 0xfe, 0x78, 0x5c, 0xbb, 0xd8, 0x1c, 0x57, 0xbf, 0x8f, 0x1f, 0x4f, 0xc6,
|
||||
0xcd, 0xca, 0xfe, 0x71, 0x47, 0xed, 0x7d, 0xae, 0xef, 0x1c, 0xdc, 0xd8, 0x1d, 0x8d, 0x36, 0xdd,
|
||||
0xd3, 0xc6, 0xfe, 0x81, 0x79, 0x91, 0x3c, 0x1c, 0x1d, 0x67, 0xf6, 0x2c, 0x3b, 0xff, 0xb4, 0x33,
|
||||
0xba, 0xfe, 0xb2, 0xaf, 0x3e, 0x3e, 0x34, 0x3e, 0x3f, 0x9c, 0x1a, 0xf9, 0xef, 0x41, 0xcd, 0xa6,
|
||||
0x2d, 0x3a, 0x38, 0x1f, 0x56, 0x93, 0x9d, 0x6c, 0xff, 0xcb, 0xb5, 0x65, 0x9c, 0x06, 0x9b, 0xf7,
|
||||
0xe3, 0xdd, 0xa6, 0x96, 0x3d, 0xd7, 0xbe, 0x7f, 0xaa, 0xe6, 0xae, 0x2f, 0x1a, 0x43, 0xcf, 0xfe,
|
||||
0x94, 0xf9, 0x52, 0x3b, 0xfe, 0xac, 0x64, 0x9d, 0x23, 0xf3, 0xf8, 0xec, 0x53, 0x70, 0x7e, 0x7a,
|
||||
0xfc, 0xe4, 0x1e, 0x5c, 0x3c, 0x9d, 0x3d, 0xe5, 0x37, 0x6f, 0x4e, 0xce, 0xb4, 0xa1, 0x55, 0xd8,
|
||||
0x55, 0xd5, 0x76, 0x30, 0x3c, 0xff, 0x7c, 0x53, 0x7d, 0x1a, 0x07, 0x85, 0xfb, 0xf6, 0xe8, 0x54,
|
||||
0x55, 0x2e, 0xce, 0x3b, 0x47, 0xb9, 0xee, 0x05, 0xd3, 0x89, 0xca, 0xce, 0x3f, 0xf5, 0xcb, 0xdc,
|
||||
0x9e, 0xf7, 0xf0, 0x4f, 0xa7, 0xd3, 0xd1, 0x75, 0x61, 0x7b, 0x03, 0x5c, 0x67, 0xcb, 0xb3, 0xfa,
|
||||
0x01, 0x61, 0x21, 0xac, 0x80, 0xba, 0x9c, 0xbe, 0x37, 0x86, 0x06, 0x6f, 0x05, 0x80, 0xf6, 0xc0,
|
||||
0x61, 0xc5, 0x22, 0xd2, 0x39, 0x34, 0x13, 0x54, 0x9c, 0x78, 0x34, 0x18, 0x78, 0x0e, 0x31, 0xe5,
|
||||
0x0e, 0x0d, 0xf6, 0x6c, 0x8a, 0x45, 0x87, 0x9d, 0x31, 0xeb, 0x9a, 0xce, 0x40, 0x5b, 0x7b, 0x0b,
|
||||
0x90, 0x2d, 0x88, 0xad, 0x02, 0x1a, 0x02, 0x23, 0xe0, 0xd0, 0xf0, 0xc0, 0xc1, 0x9a, 0x90, 0x87,
|
||||
0x63, 0x0b, 0x9a, 0x0a, 0xb6, 0x1a, 0xd8, 0x8a, 0x74, 0x58, 0xa3, 0xc7, 0x82, 0xf5, 0xfc, 0x62,
|
||||
0x82, 0xdb, 0x61, 0x81, 0x08, 0x20, 0x18, 0x16, 0xa4, 0x85, 0xb0, 0x79, 0x23, 0xf4, 0xfa, 0x0b,
|
||||
0x01, 0xce, 0xfa, 0xb0, 0x11, 0x87, 0x74, 0xd5, 0xf5, 0x23, 0x56, 0x63, 0x45, 0x84, 0xc6, 0xa8,
|
||||
0x62, 0x63, 0x21, 0xac, 0x58, 0x76, 0x8b, 0x91, 0x57, 0x62, 0x05, 0x89, 0x52, 0x7e, 0x25, 0xce,
|
||||
0xc8, 0x68, 0xf0, 0xbf, 0xb0, 0xcd, 0xe3, 0x8c, 0x0d, 0x1e, 0x68, 0xbc, 0x55, 0x94, 0x0c, 0x24,
|
||||
0xa2, 0x3c, 0xc6, 0xc8, 0x13, 0x4d, 0xeb, 0x16, 0x87, 0xd9, 0x5a, 0xfe, 0xe9, 0x58, 0x05, 0x2f,
|
||||
0x9f, 0xed, 0x66, 0x87, 0xc5, 0x6e, 0x2a, 0x0b, 0x4f, 0x45, 0xa2, 0x2a, 0xb3, 0x27, 0x4d, 0x23,
|
||||
0x79, 0x84, 0xeb, 0xa6, 0x8a, 0x4f, 0x42, 0xe4, 0xad, 0x37, 0xc8, 0x73, 0x87, 0x03, 0x48, 0x49,
|
||||
0x15, 0xe9, 0x09, 0x34, 0xc2, 0x6d, 0x6b, 0xdb, 0x1b, 0x61, 0x1f, 0x61, 0x96, 0x96, 0x04, 0x2e,
|
||||
0x1f, 0xfb, 0x4f, 0xe3, 0xf4, 0x84, 0x24, 0xfa, 0x6c, 0x06, 0x20, 0x2b, 0x01, 0xee, 0xb1, 0xf6,
|
||||
0x9e, 0x11, 0x78, 0xd6, 0xa3, 0x08, 0xd3, 0x68, 0x30, 0xbe, 0x8f, 0xc7, 0x11, 0x58, 0x01, 0x21,
|
||||
0x1b, 0x16, 0x60, 0x3d, 0x2f, 0xec, 0x0a, 0x8b, 0x51, 0x17, 0x8b, 0x96, 0x19, 0x60, 0x0a, 0x48,
|
||||
0xeb, 0x0e, 0x82, 0x52, 0x1b, 0x66, 0x36, 0x43, 0xf2, 0xae, 0xb2, 0x23, 0xf0, 0x50, 0x02, 0x03,
|
||||
0x33, 0x9a, 0x65, 0x6d, 0x1c, 0x8c, 0x80, 0xb6, 0xd1, 0x04, 0x04, 0x21, 0x74, 0xd4, 0x05, 0x9b,
|
||||
0x9a, 0x0d, 0x90, 0xac, 0x7e, 0x54, 0xa7, 0x13, 0xb6, 0x8f, 0x28, 0x4c, 0x80, 0x4d, 0x25, 0x10,
|
||||
0x25, 0x06, 0x89, 0x3b, 0x0f, 0x50, 0x8e, 0x60, 0xea, 0x50, 0x70, 0xe6, 0x25, 0x51, 0xc6, 0x59,
|
||||
0x36, 0x98, 0xe0, 0x66, 0x56, 0xe6, 0x23, 0x1b, 0xe1, 0x90, 0x78, 0xd5, 0x13, 0x07, 0xb9, 0x7d,
|
||||
0x26, 0xdd, 0x43, 0xc3, 0x1e, 0x50, 0xec, 0x45, 0x0a, 0x01, 0x01, 0x18, 0x04, 0x85, 0x99, 0xa2,
|
||||
0x3b, 0x61, 0x5b, 0xdb, 0x25, 0xc7, 0xac, 0x1b, 0x10, 0xe2, 0xa3, 0x56, 0x86, 0x7b, 0x9a, 0x2d,
|
||||
0x6c, 0x37, 0xa8, 0xd7, 0x07, 0x62, 0x40, 0xa0, 0x23, 0x41, 0x14, 0xea, 0xf9, 0x01, 0x81, 0x38,
|
||||
0x9e, 0x57, 0xb7, 0x90, 0x43, 0x58, 0xb5, 0x23, 0xef, 0xed, 0xa0, 0x9c, 0x9a, 0x4d, 0xb3, 0xb1,
|
||||
0x3c, 0x8f, 0xad, 0x79, 0xcf, 0xcd, 0xc3, 0x86, 0x47, 0xd5, 0x32, 0x92, 0x7a, 0xdf, 0x09, 0xca,
|
||||
0x73, 0x74, 0x50, 0xeb, 0x18, 0xbe, 0x33, 0x5a, 0xa5, 0x81, 0x1b, 0x8c, 0x25, 0xbf, 0xc0, 0x91,
|
||||
0x0d, 0xc6, 0x12, 0xf8, 0x00, 0x6a, 0xcc, 0x49, 0x75, 0x3a, 0x08, 0x20, 0x0e, 0x24, 0xbc, 0xb9,
|
||||
0xf4, 0x4a, 0x9e, 0x6c, 0xc4, 0x99, 0xb2, 0x34, 0x23, 0x79, 0x15, 0x47, 0x46, 0xc0, 0x4a, 0xe0,
|
||||
0xde, 0x3a, 0x86, 0xcc, 0x64, 0xfd, 0x59, 0x7e, 0x40, 0xf8, 0x0f, 0x0c, 0xa9, 0x5e, 0xd6, 0x8f,
|
||||
0xe2, 0x34, 0x5a, 0x84, 0xe9, 0x1a, 0xc2, 0x76, 0xcd, 0xed, 0x51, 0x52, 0xf1, 0x7d, 0x0b, 0x22,
|
||||
0x53, 0x27, 0x20, 0x37, 0x95, 0xe3, 0xd8, 0x80, 0x17, 0x68, 0xba, 0xf1, 0x0b, 0x62, 0xce, 0xe2,
|
||||
0xac, 0xfd, 0x25, 0xc2, 0x6e, 0xb0, 0xec, 0x84, 0xb4, 0x5c, 0x93, 0xfe, 0x22, 0x75, 0x23, 0xe2,
|
||||
0x32, 0xfd, 0x5d, 0x37, 0xf7, 0xeb, 0x48, 0xdc, 0xa5, 0x8f, 0xcf, 0x50, 0xb8, 0xb6, 0x77, 0x4d,
|
||||
0x12, 0x6f, 0xdb, 0x59, 0xfc, 0x27, 0x3e, 0x4b, 0x65, 0x08, 0x13, 0x85, 0xed, 0xdd, 0xbd, 0x2a,
|
||||
0x49, 0x68, 0xd9, 0xac, 0x14, 0xfe, 0x89, 0x1b, 0xaf, 0xa6, 0xe0, 0xaf, 0x48, 0x25, 0x24, 0x12,
|
||||
0x1e, 0x05, 0x46, 0x39, 0x9d, 0xf9, 0x7e, 0x2a, 0xb3, 0xb6, 0xdf, 0x12, 0xcb, 0x35, 0x53, 0xbe,
|
||||
0x92, 0x6e, 0xe3, 0x26, 0xa4, 0xeb, 0xcf, 0x91, 0x8e, 0x75, 0x22, 0xf5, 0x14, 0xfc, 0x07, 0xa9,
|
||||
0x9a, 0x44, 0xd4, 0x82, 0x44, 0x9e, 0xa7, 0xe6, 0x46, 0x64, 0x44, 0xb0, 0x94, 0x29, 0x6c, 0xd7,
|
||||
0xf1, 0x42, 0x12, 0x2f, 0x8f, 0x0b, 0x87, 0xe1, 0x06, 0x90, 0x5e, 0x1b, 0x0d, 0x76, 0xb3, 0x96,
|
||||
0x6f, 0x7f, 0x4e, 0x92, 0x9b, 0xcc, 0xfe, 0x38, 0x40, 0x37, 0x5e, 0x74, 0x15, 0xb6, 0x77, 0x66,
|
||||
0x2d, 0x33, 0x2e, 0x6c, 0xc4, 0xd8, 0xf0, 0xb3, 0xb9, 0xcb, 0xaf, 0x70, 0xdb, 0xac, 0x26, 0xb7,
|
||||
0x11, 0x46, 0x34, 0x9c, 0x44, 0x8c, 0x7b, 0x2b, 0x88, 0x90, 0x9e, 0xe5, 0xe8, 0x82, 0x0a, 0x57,
|
||||
0x03, 0xfc, 0xb5, 0x96, 0xcb, 0x09, 0x11, 0x85, 0x54, 0xad, 0xc8, 0x94, 0xa6, 0x6f, 0x38, 0x5c,
|
||||
0x65, 0xe6, 0x63, 0xaf, 0x10, 0x42, 0xd8, 0x06, 0x08, 0xa0, 0x11, 0xf4, 0xff, 0x29, 0x5d, 0x3f,
|
||||
0xb2, 0x7a, 0x56, 0x10, 0x51, 0x68, 0xe3, 0xd8, 0x78, 0x24, 0x8e, 0x4b, 0xdc, 0x36, 0x61, 0x9d,
|
||||
0x7e, 0x1a, 0x8d, 0xd7, 0x3a, 0x99, 0xdd, 0xf8, 0x23, 0xd4, 0x22, 0x1b, 0x2b, 0xd4, 0x5a, 0x41,
|
||||
0x6a, 0x91, 0x5a, 0x39, 0x55, 0x9b, 0x51, 0x4b, 0xcb, 0xe5, 0x17, 0xa9, 0x35, 0x1f, 0x1b, 0x52,
|
||||
0x0b, 0x20, 0x9e, 0xa1, 0x56, 0xa4, 0x3f, 0x5d, 0x23, 0x85, 0x15, 0x32, 0xe1, 0xd7, 0xa9, 0xd7,
|
||||
0x35, 0x0e, 0x41, 0x51, 0x6b, 0x15, 0xb2, 0x4b, 0x87, 0x56, 0x8b, 0x92, 0xc3, 0xdd, 0x35, 0x74,
|
||||
0xda, 0x58, 0x6f, 0x15, 0xf9, 0xe6, 0xc3, 0xae, 0x85, 0x52, 0xbf, 0x10, 0x8b, 0x88, 0x39, 0x41,
|
||||
0xd8, 0x3a, 0x33, 0xd5, 0x63, 0x21, 0xd3, 0x57, 0x08, 0x99, 0xbe, 0xb6, 0xf8, 0x8b, 0x23, 0x36,
|
||||
0xf5, 0xbe, 0x2a, 0x8a, 0x2a, 0xfc, 0x2b, 0x3b, 0xbc, 0x5c, 0xdc, 0xe2, 0xa5, 0x63, 0x7d, 0x1f,
|
||||
0x2c, 0xee, 0x74, 0xe3, 0x05, 0xfb, 0xff, 0xda, 0x9d, 0x6e, 0xf0, 0xad, 0xe2, 0x82, 0xe4, 0x85,
|
||||
0xad, 0x1a, 0xaf, 0xd9, 0xeb, 0xc6, 0x2f, 0x86, 0x77, 0x5d, 0xe3, 0xc4, 0xe8, 0xd1, 0xf8, 0x66,
|
||||
0xf1, 0xf9, 0x5f, 0xdb, 0x27, 0x5b, 0x2c, 0xda, 0xe8, 0x3c, 0x90, 0xfe, 0x64, 0x05, 0xad, 0x2e,
|
||||
0x75, 0x84, 0x3f, 0xa1, 0xdc, 0x10, 0x58, 0x5c, 0x62, 0x6c, 0x11, 0x89, 0xe7, 0x59, 0xba, 0xeb,
|
||||
0x42, 0x84, 0xe6, 0xc4, 0xb7, 0xb5, 0x41, 0xfe, 0xe4, 0xb6, 0xa2, 0x25, 0xf9, 0xbe, 0xfe, 0x80,
|
||||
0x2b, 0x0d, 0x20, 0xcb, 0xa1, 0x10, 0x2b, 0xb0, 0x33, 0x66, 0x61, 0xfb, 0x82, 0x3d, 0x92, 0xf0,
|
||||
0xcc, 0x19, 0x94, 0xe3, 0xf5, 0xce, 0x74, 0x71, 0x1f, 0xfc, 0xcc, 0x28, 0xda, 0x81, 0x13, 0xda,
|
||||
0x19, 0x8b, 0x79, 0xc7, 0x4e, 0x4c, 0x02, 0x95, 0xd0, 0xf8, 0x28, 0xa1, 0xf1, 0xc9, 0x67, 0x96,
|
||||
0x3d, 0xf3, 0x22, 0x86, 0xcb, 0x8b, 0xc7, 0x1d, 0xf3, 0xdc, 0xb1, 0xb1, 0xfc, 0x11, 0x07, 0xcf,
|
||||
0x47, 0xe2, 0xf9, 0xf9, 0x6c, 0x74, 0xec, 0x4c, 0x1d, 0x52, 0xb8, 0x30, 0x95, 0x8a, 0x93, 0x32,
|
||||
0xcd, 0x52, 0x9d, 0x79, 0x6e, 0x14, 0x8d, 0x9b, 0xbd, 0xa6, 0x52, 0xc5, 0x86, 0x70, 0x43, 0xb3,
|
||||
0x46, 0x61, 0x29, 0xa7, 0xfc, 0x8d, 0xa4, 0xe9, 0x75, 0x42, 0x88, 0xfb, 0x9b, 0x2d, 0xcd, 0x36,
|
||||
0xf1, 0x9a, 0x94, 0x76, 0x7d, 0xa5, 0x1c, 0x4f, 0x02, 0xac, 0xd6, 0x03, 0x4c, 0x36, 0x42, 0xd5,
|
||||
0x68, 0xe0, 0x94, 0x09, 0x11, 0x73, 0x25, 0x76, 0x16, 0x03, 0x46, 0x82, 0x1f, 0xc6, 0x44, 0xb9,
|
||||
0xee, 0xba, 0x9a, 0xfa, 0x06, 0x2b, 0xaa, 0x17, 0x48, 0xa1, 0x56, 0x30, 0x72, 0x24, 0x87, 0x15,
|
||||
0x6a, 0xa2, 0xa4, 0xf0, 0x6e, 0xf6, 0x84, 0x77, 0x5d, 0x55, 0x31, 0x62, 0x0d, 0xa9, 0x58, 0x77,
|
||||
0x0a, 0x9e, 0x8e, 0x0b, 0x44, 0xcd, 0x19, 0x19, 0x92, 0x61, 0x4d, 0x6a, 0x2a, 0x93, 0xc2, 0xfb,
|
||||
0xf0, 0x89, 0x2c, 0x3d, 0x91, 0xd8, 0x13, 0xf6, 0x60, 0xee, 0xbc, 0xc1, 0x93, 0x67, 0xf2, 0xde,
|
||||
0x69, 0xfa, 0xfd, 0x32, 0xdb, 0x49, 0x98, 0x14, 0x2f, 0xf2, 0xf8, 0x15, 0x3a, 0x32, 0x93, 0xa0,
|
||||
0xb0, 0x38, 0x3e, 0x4b, 0x87, 0xe3, 0xe7, 0x3c, 0x4b, 0xf6, 0x00, 0x41, 0xaf, 0x21, 0x23, 0x21,
|
||||
0x25, 0x32, 0xd3, 0x1a, 0x8e, 0x4a, 0xe4, 0x8a, 0x23, 0x31, 0x5a, 0x2c, 0xa8, 0xaf, 0xd5, 0x12,
|
||||
0x36, 0xd7, 0xcc, 0x31, 0x47, 0xc1, 0x4b, 0x1e, 0x0b, 0x3b, 0x7c, 0xce, 0xf8, 0xe7, 0x0a, 0x1a,
|
||||
0x37, 0x60, 0x66, 0xff, 0x14, 0x1a, 0x37, 0x6b, 0xd1, 0x88, 0x48, 0xba, 0xb1, 0x5e, 0x6f, 0xd2,
|
||||
0xfd, 0xb0, 0xb8, 0x10, 0x43, 0x2c, 0xf6, 0x56, 0x53, 0x5c, 0x88, 0x67, 0xaf, 0x6a, 0xe1, 0xde,
|
||||
0x76, 0xe1, 0x21, 0xe4, 0x59, 0x97, 0x7a, 0xc0, 0xb8, 0xa6, 0xb7, 0x0d, 0x79, 0x11, 0x5e, 0x48,
|
||||
0x15, 0xe5, 0x14, 0xd3, 0xde, 0xd0, 0x3a, 0x18, 0x28, 0x8b, 0x31, 0xde, 0xce, 0x0c, 0x55, 0xb8,
|
||||
0x76, 0x64, 0x93, 0xf8, 0xb6, 0x10, 0x96, 0x6f, 0x2a, 0x8e, 0xc7, 0x73, 0x6c, 0x85, 0x39, 0x16,
|
||||
0xaa, 0x50, 0x71, 0x85, 0x5e, 0x7e, 0x17, 0x8c, 0x59, 0xf1, 0x5e, 0x87, 0xcd, 0xdd, 0xf7, 0x28,
|
||||
0x2a, 0x99, 0xb0, 0x52, 0x8c, 0x8a, 0xbd, 0x9b, 0x11, 0xbe, 0x5f, 0x09, 0x6b, 0x7b, 0xad, 0xb0,
|
||||
0x48, 0xce, 0xaa, 0x73, 0xf8, 0x32, 0x6b, 0x54, 0x24, 0x9f, 0x13, 0x78, 0x2e, 0x8a, 0x9e, 0x31,
|
||||
0x4a, 0x2d, 0x1d, 0x1c, 0x3e, 0x8b, 0x7f, 0x84, 0x0f, 0x83, 0x47, 0x6c, 0x7e, 0xb2, 0x14, 0x31,
|
||||
0xec, 0x40, 0x17, 0xea, 0xc6, 0xe8, 0x90, 0xd1, 0x9d, 0x0f, 0x99, 0xaf, 0x0f, 0x94, 0x60, 0x14,
|
||||
0x9d, 0xe1, 0xf1, 0x5a, 0x1c, 0x22, 0x06, 0x73, 0x78, 0xcb, 0x69, 0xbb, 0xeb, 0xc9, 0x32, 0x37,
|
||||
0xc1, 0xd1, 0x79, 0x2d, 0x1b, 0x86, 0x71, 0x31, 0xcb, 0xfb, 0xa1, 0xc1, 0x74, 0x1d, 0x7b, 0x0c,
|
||||
0x14, 0x08, 0xef, 0x04, 0x54, 0xf5, 0x08, 0x78, 0x91, 0x52, 0x2c, 0xa4, 0x5f, 0x3a, 0x24, 0x7d,
|
||||
0x16, 0x43, 0x0e, 0x18, 0x45, 0xb6, 0xfd, 0x71, 0xb8, 0x24, 0x6f, 0x9e, 0x79, 0x8b, 0xd8, 0x79,
|
||||
0x29, 0xa2, 0xca, 0x1f, 0x63, 0xcb, 0x75, 0x8c, 0xbe, 0x3a, 0x03, 0x86, 0x07, 0x86, 0x1d, 0xc7,
|
||||
0x28, 0x5c, 0x80, 0xfb, 0x3d, 0xc7, 0xfc, 0xb5, 0xf9, 0xe7, 0xbb, 0xc2, 0x28, 0xa2, 0x9b, 0xd9,
|
||||
0x9e, 0xad, 0x08, 0x66, 0xcb, 0x87, 0x64, 0x4e, 0xd8, 0xbe, 0xe2, 0x37, 0x44, 0x95, 0x15, 0xb9,
|
||||
0xc0, 0x07, 0x70, 0x55, 0x4f, 0x45, 0x86, 0xc1, 0x88, 0x0e, 0x63, 0xf0, 0xbd, 0x64, 0xbf, 0x94,
|
||||
0x4e, 0x77, 0xac, 0xa0, 0x3b, 0x68, 0xca, 0x2d, 0xb7, 0x97, 0x1e, 0x51, 0xef, 0xc1, 0x87, 0xb0,
|
||||
0xaf, 0x97, 0xc6, 0x2a, 0x4a, 0x8a, 0x05, 0x49, 0x10, 0x23, 0xcd, 0x6a, 0x8d, 0xe9, 0xa6, 0xed,
|
||||
0x36, 0xd3, 0x98, 0xff, 0xa6, 0xeb, 0x7b, 0x95, 0xdd, 0xe3, 0x3d, 0xb9, 0x87, 0x99, 0x2e, 0xf7,
|
||||
0xc8, 0xba, 0xf0, 0xb5, 0x69, 0x1b, 0xce, 0x03, 0x58, 0x1a, 0x6a, 0xf7, 0xd3, 0x95, 0x26, 0xf8,
|
||||
0xb7, 0xad, 0xb4, 0x01, 0x1b, 0x00, 0x4c, 0xe7, 0x4a, 0xb9, 0xc4, 0x19, 0x76, 0x9e, 0xcc, 0xeb,
|
||||
0xbc, 0xeb, 0x65, 0x61, 0x46, 0x94, 0x18, 0xe4, 0x4c, 0x3e, 0x5a, 0x86, 0x33, 0x34, 0x7c, 0xae,
|
||||
0x68, 0x88, 0x6c, 0x95, 0x3d, 0x33, 0x7a, 0xf3, 0xae, 0xed, 0x97, 0xab, 0xde, 0xae, 0x97, 0xc0,
|
||||
0x2a, 0x75, 0x07, 0x22, 0x29, 0x1d, 0x2b, 0xdf, 0xb3, 0x98, 0x4a, 0x94, 0xfc, 0xa7, 0x6b, 0xde,
|
||||
0xc4, 0xad, 0x2f, 0x36, 0xdc, 0xcc, 0x1b, 0x6e, 0x58, 0x03, 0xf8, 0x82, 0x79, 0x13, 0x3a, 0x06,
|
||||
0x51, 0xea, 0x7b, 0x23, 0xde, 0x14, 0x29, 0x3f, 0xc0, 0x1d, 0xee, 0x86, 0x50, 0x2c, 0xda, 0x11,
|
||||
0xa5, 0x7f, 0x8e, 0xc2, 0x86, 0x48, 0xaa, 0x45, 0x29, 0x68, 0x74, 0x78, 0xd3, 0x62, 0x84, 0x23,
|
||||
0x4a, 0x4d, 0xaf, 0xd3, 0xe5, 0x3d, 0x2b, 0x79, 0x2d, 0xcc, 0x4c, 0x67, 0x18, 0x2c, 0x05, 0x37,
|
||||
0xa2, 0xd4, 0xba, 0x6f, 0x86, 0x5b, 0x5a, 0x91, 0x65, 0x51, 0x6a, 0x7b, 0x3d, 0xde, 0xb9, 0x54,
|
||||
0x81, 0x83, 0x61, 0x47, 0x27, 0xd1, 0xb0, 0xa5, 0xc4, 0x50, 0x94, 0x30, 0x35, 0xa2, 0xbc, 0x97,
|
||||
0x65, 0x49, 0xd8, 0x72, 0x39, 0x6b, 0xb8, 0x0c, 0x5b, 0x4e, 0x66, 0x2d, 0x2c, 0xea, 0x16, 0x25,
|
||||
0xa3, 0xc1, 0x1b, 0xd6, 0x94, 0x55, 0x60, 0xbd, 0xfd, 0x46, 0x6c, 0xbd, 0xfd, 0x65, 0x74, 0xec,
|
||||
0x46, 0xd8, 0xbd, 0x52, 0xbf, 0x15, 0x25, 0x0b, 0x3d, 0x11, 0xeb, 0x8c, 0x19, 0x15, 0x6c, 0x6e,
|
||||
0x2d, 0x34, 0xcf, 0x35, 0x1f, 0xa8, 0x19, 0x75, 0xad, 0x58, 0x05, 0x1c, 0x17, 0x1b, 0x85, 0xc4,
|
||||
0x6d, 0xcd, 0xd9, 0x1b, 0x85, 0x56, 0xa2, 0x34, 0xd2, 0x47, 0x96, 0x63, 0xba, 0x23, 0x89, 0xcb,
|
||||
0x58, 0xc8, 0xeb, 0x98, 0xfc, 0x31, 0x96, 0x5d, 0x2d, 0xb3, 0x8c, 0x27, 0xc8, 0x48, 0xde, 0xab,
|
||||
0x65, 0xf2, 0x46, 0x5d, 0xa8, 0x93, 0x15, 0xcf, 0x33, 0xc6, 0xfa, 0xed, 0x9d, 0x84, 0x6e, 0x09,
|
||||
0x99, 0xa6, 0x0b, 0x82, 0x84, 0x29, 0x16, 0x7a, 0xd2, 0xba, 0x3b, 0xf2, 0x75, 0x53, 0x86, 0x94,
|
||||
0xd0, 0x1b, 0x47, 0x64, 0xa8, 0xd8, 0x76, 0x42, 0x90, 0xa3, 0x3c, 0x0c, 0x36, 0xa1, 0x2b, 0x65,
|
||||
0x6b, 0x2b, 0x3e, 0x42, 0xb6, 0xa9, 0xd3, 0x09, 0xba, 0x65, 0x2b, 0x99, 0x14, 0xe3, 0xed, 0xb7,
|
||||
0xd6, 0x9d, 0xcc, 0xd4, 0xeb, 0xc8, 0xf2, 0x03, 0x19, 0x78, 0x03, 0x1c, 0x63, 0x73, 0x94, 0x51,
|
||||
0x23, 0x8c, 0x56, 0x2b, 0x8a, 0xe8, 0x74, 0xe1, 0x2d, 0xa5, 0x54, 0x90, 0x78, 0x13, 0x26, 0x24,
|
||||
0x51, 0x73, 0xa1, 0x50, 0x10, 0x40, 0xe0, 0x7d, 0x78, 0x86, 0xa7, 0x56, 0xab, 0x25, 0x48, 0x1d,
|
||||
0x8f, 0x52, 0x27, 0xea, 0x57, 0x72, 0xf9, 0xa6, 0x62, 0x08, 0x92, 0x47, 0xcd, 0xa8, 0x09, 0x1a,
|
||||
0x72, 0x0a, 0xc0, 0xf1, 0x38, 0xd9, 0xed, 0x74, 0x6c, 0x7a, 0xda, 0x6e, 0xf3, 0x88, 0x51, 0x82,
|
||||
0x88, 0xb1, 0x92, 0x93, 0x72, 0xd1, 0x3b, 0x0d, 0xf8, 0x0e, 0xc4, 0xfc, 0xb1, 0x20, 0xa9, 0x85,
|
||||
0x9a, 0xba, 0x00, 0xb0, 0x04, 0x81, 0x33, 0x1c, 0x03, 0x58, 0xae, 0x92, 0x91, 0x32, 0xe1, 0x9b,
|
||||
0x13, 0xf8, 0xfe, 0x46, 0xec, 0xb1, 0x20, 0x6d, 0xc6, 0x9e, 0x54, 0x65, 0xb9, 0x57, 0xcd, 0x7d,
|
||||
0x59, 0xc4, 0xcd, 0xf9, 0x83, 0xa8, 0xa9, 0x4b, 0xb8, 0xa9, 0x4b, 0xc8, 0xa9, 0x8b, 0xd8, 0x69,
|
||||
0xca, 0x4a, 0x37, 0x47, 0x2f, 0x32, 0x15, 0x31, 0x95, 0x6f, 0x5c, 0x1d, 0x60, 0x3c, 0x2e, 0x88,
|
||||
0xf1, 0x53, 0xb6, 0x57, 0x1f, 0xf9, 0xd1, 0x80, 0x59, 0xfb, 0xfa, 0xc1, 0x0e, 0x93, 0x45, 0x1f,
|
||||
0x8f, 0xf5, 0xd6, 0x4b, 0xe3, 0xb7, 0x89, 0x00, 0xf6, 0xa3, 0x14, 0x78, 0x03, 0x2a, 0xa1, 0x74,
|
||||
0x0b, 0xa5, 0x77, 0x13, 0xb4, 0x50, 0x32, 0x0b, 0x06, 0xa7, 0x12, 0x9a, 0x38, 0xa1, 0x34, 0x11,
|
||||
0x2c, 0x13, 0x7b, 0xc0, 0xa8, 0xcd, 0x3a, 0x00, 0xf4, 0xf6, 0x5b, 0xd9, 0x86, 0x7c, 0x32, 0x00,
|
||||
0x11, 0x0d, 0x30, 0x2b, 0xa4, 0x8f, 0x82, 0xae, 0x23, 0x0c, 0x33, 0xfd, 0x72, 0x68, 0xf9, 0x3f,
|
||||
0xce, 0x46, 0x95, 0xc0, 0x70, 0xf2, 0xbb, 0x32, 0xe8, 0x29, 0xe4, 0xd2, 0xb6, 0x0e, 0x1e, 0xc0,
|
||||
0x87, 0x30, 0x35, 0x48, 0x80, 0x99, 0xe2, 0x5d, 0x22, 0x9b, 0xd3, 0xd1, 0xdf, 0xa8, 0x92, 0xa1,
|
||||
0xa7, 0xd4, 0xb2, 0xa1, 0x83, 0x6d, 0x93, 0xa3, 0xaa, 0xeb, 0xa1, 0x63, 0xd2, 0xc7, 0x70, 0xb4,
|
||||
0xc5, 0x7a, 0x78, 0xe5, 0xd3, 0xbf, 0x35, 0xee, 0xc2, 0xa9, 0x0d, 0x1d, 0x6c, 0xcc, 0xda, 0x01,
|
||||
0x2e, 0xeb, 0x59, 0x33, 0x00, 0x6c, 0xd6, 0xd2, 0x00, 0xc4, 0xc1, 0xd7, 0xdf, 0x28, 0x65, 0x56,
|
||||
0xfa, 0xd6, 0x19, 0xc4, 0xf2, 0xc0, 0xf7, 0xef, 0x13, 0x00, 0xa2, 0x82, 0x3d, 0xd4, 0x8d, 0x75,
|
||||
0xe3, 0x3d, 0x36, 0x3e, 0x2c, 0xda, 0xea, 0x08, 0xb3, 0x3c, 0xc3, 0x47, 0x00, 0x51, 0x4b, 0x51,
|
||||
0x95, 0x79, 0x2d, 0x08, 0x2c, 0x02, 0xb4, 0x50, 0x38, 0x55, 0x06, 0x68, 0x3d, 0x4c, 0xfc, 0x68,
|
||||
0xe9, 0x1f, 0x84, 0x0f, 0x52, 0x17, 0x3f, 0xcb, 0xfe, 0x8f, 0x1f, 0x09, 0x88, 0xff, 0x6e, 0xc1,
|
||||
0xb0, 0xe8, 0xc2, 0x9d, 0xc0, 0x41, 0xfb, 0x48, 0x40, 0x08, 0x0c, 0x04, 0xa6, 0xfd, 0x1d, 0xbd,
|
||||
0xb5, 0x07, 0x26, 0x2a, 0x32, 0x68, 0x60, 0x18, 0xf1, 0x1c, 0x18, 0xbf, 0x3a, 0x05, 0x52, 0x94,
|
||||
0x10, 0x34, 0x53, 0x90, 0x26, 0x23, 0x48, 0xfd, 0xea, 0x10, 0x82, 0xed, 0x7b, 0x14, 0x2c, 0x92,
|
||||
0x13, 0xd8, 0xe3, 0xd2, 0x1b, 0x65, 0x2a, 0x4a, 0x43, 0xdd, 0xa1, 0x23, 0xc2, 0xa2, 0xc7, 0xf2,
|
||||
0x50, 0xc6, 0x50, 0x93, 0x4a, 0x43, 0x19, 0x02, 0x35, 0xd7, 0x30, 0xf5, 0x48, 0xe6, 0x12, 0xe2,
|
||||
0x04, 0x57, 0xa5, 0x3a, 0x33, 0xb2, 0x72, 0xab, 0x6b, 0xd9, 0xe0, 0x1b, 0x9c, 0x5b, 0xe5, 0x6e,
|
||||
0xe1, 0x1e, 0x16, 0xad, 0x04, 0x81, 0x67, 0x81, 0xb5, 0xa6, 0x09, 0x0c, 0xd5, 0xd1, 0x31, 0x1b,
|
||||
0x3a, 0xb8, 0x66, 0xbe, 0x5b, 0x69, 0x0c, 0xf7, 0x37, 0x21, 0x5f, 0x12, 0xf4, 0x8d, 0x1e, 0x33,
|
||||
0x5b, 0x3f, 0x7e, 0x18, 0x5b, 0xea, 0x8f, 0x1f, 0xe3, 0x2d, 0x55, 0x04, 0xa2, 0x18, 0xfa, 0x50,
|
||||
0x66, 0x61, 0x3b, 0x0c, 0x19, 0xca, 0x3c, 0x0f, 0x96, 0x12, 0x61, 0xdb, 0x76, 0x4e, 0xd5, 0x7e,
|
||||
0xfc, 0x88, 0x9a, 0xf1, 0x89, 0x0f, 0x51, 0xf3, 0x00, 0xad, 0xe6, 0x45, 0x51, 0xea, 0x70, 0x40,
|
||||
0xdd, 0x80, 0x3b, 0x0e, 0xa5, 0x8f, 0x91, 0x5c, 0x10, 0x0f, 0x7f, 0x66, 0xc9, 0x00, 0x11, 0x92,
|
||||
0x46, 0x52, 0x90, 0x48, 0x8d, 0x67, 0xd8, 0xf0, 0x38, 0x4e, 0x0a, 0x24, 0xd1, 0x33, 0x1e, 0x28,
|
||||
0xf1, 0x07, 0x90, 0xbb, 0x04, 0x5d, 0xcb, 0xc7, 0xe3, 0xd6, 0x56, 0x97, 0xfa, 0x04, 0xd2, 0x7f,
|
||||
0x8f, 0x80, 0x47, 0x0b, 0xcf, 0x5f, 0xf9, 0xb1, 0xa6, 0x88, 0x91, 0xb5, 0x20, 0xf5, 0x64, 0xd3,
|
||||
0x0b, 0xa3, 0xef, 0xc4, 0x90, 0xbd, 0x57, 0x6d, 0x48, 0x63, 0x6e, 0x94, 0x1b, 0x7a, 0x0f, 0x49,
|
||||
0xc2, 0xfa, 0x76, 0x21, 0x7c, 0x4f, 0x44, 0xbd, 0x32, 0x06, 0xf3, 0xd2, 0x3b, 0x50, 0x55, 0xc6,
|
||||
0xcc, 0x91, 0xae, 0x96, 0xd9, 0x89, 0xa1, 0xae, 0xbb, 0xb0, 0x91, 0x91, 0x0e, 0xf2, 0x10, 0x85,
|
||||
0x3a, 0x87, 0xa0, 0x7d, 0x87, 0x5b, 0x8d, 0xc8, 0x2b, 0x1c, 0x26, 0xf5, 0xac, 0x38, 0xc1, 0x8e,
|
||||
0xa6, 0xde, 0xb8, 0x3d, 0xbc, 0x93, 0x1e, 0xf1, 0x92, 0x54, 0xef, 0xa4, 0x0b, 0x76, 0xa3, 0xdd,
|
||||
0x49, 0x27, 0xec, 0x26, 0xc3, 0xa7, 0xa6, 0xfa, 0x61, 0x3a, 0x2b, 0x05, 0xfa, 0x31, 0x58, 0x1b,
|
||||
0xb9, 0x6d, 0xbb, 0x30, 0x2b, 0x4d, 0x1b, 0xe0, 0xa7, 0x75, 0x5a, 0xb6, 0xda, 0x89, 0xe8, 0xb8,
|
||||
0x14, 0x16, 0x16, 0xcb, 0xd4, 0xf6, 0x21, 0x81, 0x68, 0x27, 0x12, 0x41, 0x72, 0x24, 0xfe, 0xa5,
|
||||
0xe9, 0x88, 0x06, 0xb6, 0x4d, 0x6c, 0x3d, 0xf8, 0xdb, 0x48, 0x26, 0x8c, 0x94, 0x9a, 0x4a, 0xd8,
|
||||
0x29, 0xb8, 0x17, 0xc5, 0xe9, 0x3b, 0xb9, 0x3f, 0xf0, 0xbb, 0x89, 0xdb, 0xa6, 0xf4, 0x28, 0x5d,
|
||||
0x48, 0x27, 0x92, 0x2d, 0x51, 0x29, 0xb8, 0xc3, 0x76, 0xdf, 0xf5, 0x82, 0x44, 0x02, 0x9e, 0x44,
|
||||
0x7d, 0x9b, 0xde, 0xe6, 0xee, 0x52, 0x01, 0x7c, 0x70, 0xa9, 0x3d, 0xd5, 0x6f, 0x65, 0x59, 0x7e,
|
||||
0x77, 0x57, 0x3e, 0x5d, 0x82, 0xca, 0x22, 0x54, 0x36, 0x84, 0xaa, 0xa3, 0x06, 0xdc, 0x83, 0x71,
|
||||
0x90, 0x76, 0xf5, 0xd3, 0x70, 0xe3, 0xd2, 0x57, 0x5d, 0x91, 0x2a, 0x48, 0x30, 0x24, 0x0c, 0xdf,
|
||||
0x99, 0x52, 0xa6, 0x5b, 0xbb, 0x65, 0x0a, 0x7e, 0x72, 0xc2, 0xed, 0xd4, 0xe9, 0x2d, 0xbd, 0x03,
|
||||
0x71, 0x0b, 0x40, 0x14, 0xc1, 0xb1, 0x06, 0xb7, 0x40, 0x15, 0x17, 0x2e, 0x40, 0x93, 0x01, 0x5c,
|
||||
0x32, 0x77, 0x5c, 0xb7, 0xda, 0x68, 0x76, 0x60, 0x9b, 0x9e, 0x08, 0x1f, 0xf7, 0x5b, 0x0a, 0x50,
|
||||
0xfc, 0x5e, 0xa7, 0xa2, 0x04, 0x93, 0xa5, 0xd4, 0xd8, 0x54, 0x40, 0xd4, 0x32, 0x4e, 0x05, 0x7a,
|
||||
0xfb, 0xfe, 0x3d, 0x4e, 0xa6, 0xeb, 0x16, 0xde, 0x68, 0x70, 0xe3, 0x82, 0x4e, 0xb6, 0x75, 0x00,
|
||||
0x81, 0x29, 0xef, 0x75, 0x1d, 0xd4, 0xd8, 0xf9, 0x28, 0x00, 0x15, 0xeb, 0x1f, 0x29, 0x48, 0x95,
|
||||
0x50, 0x12, 0x84, 0xd2, 0x3d, 0xde, 0x24, 0xdb, 0xf8, 0x29, 0x4e, 0x19, 0x69, 0x67, 0x03, 0x92,
|
||||
0xaa, 0xae, 0xb7, 0x7f, 0x3e, 0x84, 0x11, 0x9e, 0x75, 0x03, 0x7a, 0x75, 0x44, 0x0f, 0x70, 0x04,
|
||||
0xd4, 0x19, 0xd7, 0x06, 0x5b, 0x5a, 0x2e, 0x07, 0xed, 0x7d, 0xb4, 0x1c, 0x52, 0x7b, 0x7b, 0x8e,
|
||||
0xb6, 0xc1, 0x66, 0xb0, 0xd8, 0xa7, 0x8b, 0xa0, 0xbe, 0x38, 0x61, 0xc6, 0xf1, 0x96, 0x02, 0x87,
|
||||
0x9c, 0x3b, 0xfd, 0xd6, 0x90, 0x2c, 0xc9, 0xbd, 0x43, 0x83, 0x2e, 0x24, 0xc3, 0x46, 0xb9, 0x67,
|
||||
0xf4, 0x13, 0x14, 0xd8, 0x20, 0x07, 0x6e, 0x03, 0xc4, 0xc1, 0xe9, 0x24, 0x40, 0x89, 0xe4, 0xbe,
|
||||
0x61, 0x36, 0xf0, 0x35, 0xbf, 0x84, 0x26, 0x09, 0x8a, 0x20, 0x8a, 0xf2, 0xbd, 0x6b, 0x39, 0x09,
|
||||
0x01, 0x76, 0x53, 0x4f, 0xea, 0x66, 0xb2, 0x95, 0x0c, 0x92, 0xdd, 0xb9, 0xa7, 0xa9, 0x27, 0xa3,
|
||||
0xa6, 0xaf, 0x49, 0x5d, 0x95, 0xbe, 0xfe, 0x65, 0x83, 0xfc, 0xfc, 0xf8, 0x41, 0x75, 0x1d, 0xa8,
|
||||
0xfa, 0x31, 0x51, 0xe1, 0xe2, 0x52, 0x17, 0x25, 0xe4, 0xae, 0x58, 0x82, 0x29, 0x00, 0x47, 0xc6,
|
||||
0xe5, 0xe9, 0x14, 0x9b, 0x96, 0xf8, 0x5a, 0x89, 0x04, 0x7e, 0xc6, 0x5e, 0xfb, 0x57, 0x9d, 0x59,
|
||||
0xe8, 0xc4, 0xde, 0x4d, 0x2a, 0x20, 0x16, 0xd3, 0xbb, 0xe9, 0xf4, 0x5b, 0x79, 0xe6, 0x24, 0x39,
|
||||
0x36, 0x76, 0xe4, 0x8c, 0xbe, 0x61, 0x1a, 0x41, 0x52, 0xd7, 0xe4, 0xec, 0xb4, 0x71, 0x41, 0x58,
|
||||
0xb6, 0x05, 0xc9, 0xd6, 0xbb, 0x09, 0xe6, 0x19, 0xe1, 0xec, 0xe9, 0x7b, 0xdf, 0x75, 0xd2, 0x7e,
|
||||
0x80, 0x5f, 0x2e, 0x25, 0x29, 0x93, 0x7c, 0x78, 0x37, 0xb1, 0xa7, 0x1f, 0x48, 0xaa, 0x46, 0x84,
|
||||
0x2a, 0xaf, 0x05, 0xa6, 0x2e, 0xc0, 0x71, 0x97, 0x88, 0xd1, 0xef, 0xdb, 0x56, 0x8b, 0xbd, 0x73,
|
||||
0xc7, 0xc6, 0x08, 0xdf, 0xca, 0x74, 0x1b, 0x85, 0x0c, 0xb7, 0xfc, 0x1f, 0x47, 0x90, 0x06, 0x70,
|
||||
0x25, 0xef, 0xdf, 0x13, 0x30, 0x8d, 0xd0, 0x64, 0xe3, 0xb3, 0x33, 0x35, 0xf5, 0x6f, 0x6f, 0x2f,
|
||||
0x1d, 0xc8, 0xeb, 0x78, 0xe9, 0xb6, 0x8d, 0x26, 0x87, 0x40, 0xba, 0xfc, 0x21, 0x80, 0x04, 0xdf,
|
||||
0xc6, 0xd4, 0x79, 0x4c, 0xba, 0xc6, 0x10, 0xed, 0x12, 0x05, 0x51, 0x32, 0x69, 0x1b, 0xa2, 0x60,
|
||||
0x93, 0x58, 0x0e, 0xb7, 0x4d, 0xbc, 0xfc, 0x07, 0x76, 0x89, 0x47, 0x08, 0x6e, 0x9b, 0x37, 0x03,
|
||||
0xeb, 0xdb, 0x16, 0x6c, 0x82, 0x61, 0x23, 0x8f, 0x8d, 0x9e, 0xfd, 0x1f, 0xe7, 0x6d, 0x8a, 0xe0,
|
||||
0xbb, 0xc9, 0x98, 0x48, 0x94, 0x08, 0x2e, 0x68, 0x38, 0xe6, 0x57, 0x7c, 0xa9, 0xf3, 0x3f, 0x0e,
|
||||
0x21, 0x6f, 0xf9, 0x44, 0xd4, 0x2f, 0xe1, 0x13, 0x21, 0xef, 0x26, 0x2c, 0x87, 0x08, 0x69, 0xc0,
|
||||
0xdb, 0x08, 0x69, 0x7b, 0x16, 0xe4, 0xc3, 0xf6, 0xf8, 0x2b, 0x2b, 0x96, 0x33, 0xa0, 0x93, 0x65,
|
||||
0x98, 0x01, 0x3b, 0x0b, 0xf9, 0x6a, 0x99, 0xbc, 0xff, 0x72, 0xb9, 0x3f, 0x5a, 0xd9, 0x75, 0x4a,
|
||||
0x64, 0x3b, 0x6a, 0xc4, 0x05, 0x07, 0xab, 0x20, 0xed, 0xf6, 0x02, 0xcc, 0x6f, 0x30, 0x8b, 0x4b,
|
||||
0x4e, 0xdb, 0x00, 0xa5, 0x7a, 0x25, 0xd3, 0x30, 0xe9, 0x93, 0xe3, 0x6f, 0x30, 0x80, 0xf6, 0x7f,
|
||||
0xac, 0x97, 0xf8, 0x0b, 0x09, 0x78, 0x3f, 0x28, 0xe1, 0x8b, 0x07, 0x78, 0x67, 0x96, 0x84, 0xbd,
|
||||
0x7a, 0xfd, 0xb4, 0xfe, 0x26, 0xed, 0x30, 0xdd, 0x23, 0xe0, 0x39, 0x0c, 0x07, 0x28, 0xf0, 0xe0,
|
||||
0xb8, 0x23, 0x27, 0x7c, 0x23, 0x40, 0x16, 0x66, 0xba, 0x02, 0xfc, 0x07, 0x69, 0x14, 0x98, 0xec,
|
||||
0x55, 0x75, 0xcc, 0x8a, 0xa4, 0x1a, 0xbb, 0x94, 0xfb, 0x20, 0x26, 0xed, 0x24, 0x73, 0x53, 0x5b,
|
||||
0xcd, 0xed, 0xcf, 0x95, 0xfa, 0xc9, 0xe1, 0xc9, 0xc1, 0x9b, 0xad, 0x74, 0x73, 0x9b, 0x5c, 0xcc,
|
||||
0x5e, 0xed, 0x6c, 0x8d, 0x09, 0x66, 0x4e, 0x20, 0x03, 0x01, 0x8b, 0x48, 0x50, 0x08, 0x58, 0x0e,
|
||||
0x24, 0x2f, 0x02, 0x25, 0x0c, 0xbb, 0xdf, 0x35, 0x44, 0x10, 0x1b, 0x9f, 0x34, 0x21, 0xca, 0x27,
|
||||
0x56, 0xc7, 0x71, 0x21, 0xb4, 0x07, 0x30, 0x97, 0x50, 0x87, 0x79, 0x39, 0x94, 0x32, 0x3c, 0x33,
|
||||
0x00, 0xa9, 0x22, 0x90, 0xeb, 0x0d, 0xec, 0x80, 0x0b, 0x1e, 0xf5, 0x2d, 0xfc, 0x56, 0xf5, 0x00,
|
||||
0x44, 0x0d, 0x4b, 0x36, 0xe1, 0x9b, 0xc0, 0xfc, 0xcc, 0x73, 0x26, 0x74, 0x7c, 0x51, 0xe6, 0x05,
|
||||
0x45, 0xa9, 0x2a, 0x5b, 0x0e, 0xe4, 0x65, 0xb5, 0x8b, 0xe3, 0x23, 0xbd, 0x2d, 0xd5, 0x16, 0x63,
|
||||
0x44, 0x5d, 0x60, 0x6f, 0x23, 0x43, 0x70, 0x03, 0xae, 0x72, 0xc7, 0x7d, 0x84, 0x90, 0xf5, 0x1d,
|
||||
0x73, 0x84, 0xd3, 0xe9, 0xef, 0x04, 0xc0, 0xf3, 0x59, 0x02, 0xf0, 0x3a, 0x06, 0xf7, 0x87, 0x56,
|
||||
0x94, 0xe8, 0x39, 0x3a, 0x0f, 0x84, 0x5e, 0x1d, 0x02, 0x95, 0xad, 0x10, 0x77, 0x16, 0x0b, 0x6c,
|
||||
0x85, 0x4f, 0x2c, 0x4e, 0xf8, 0x18, 0x4e, 0xc5, 0xa3, 0x89, 0x98, 0x13, 0x95, 0x37, 0x8b, 0x7f,
|
||||
0x2f, 0x0c, 0x13, 0x4b, 0xaf, 0x00, 0x65, 0x73, 0x72, 0xa3, 0x63, 0xc7, 0x41, 0xe2, 0x43, 0xd3,
|
||||
0x60, 0xeb, 0xbb, 0x7a, 0x22, 0x3e, 0x22, 0x45, 0xff, 0xb6, 0xc5, 0xb4, 0x56, 0x0e, 0xc1, 0xc2,
|
||||
0x80, 0xc6, 0x06, 0x9f, 0xac, 0x2a, 0x33, 0xbb, 0xc9, 0x33, 0x49, 0x83, 0xe5, 0x8d, 0x51, 0x9b,
|
||||
0x01, 0x6d, 0xc6, 0x16, 0x84, 0xc0, 0x91, 0x11, 0xed, 0x82, 0x1f, 0xb4, 0xfe, 0xa6, 0x49, 0xe3,
|
||||
0x4e, 0x82, 0xec, 0xce, 0xeb, 0x34, 0x13, 0x42, 0xb2, 0x0b, 0x3e, 0x0e, 0x43, 0x21, 0xbc, 0x53,
|
||||
0x67, 0x77, 0x1a, 0xdc, 0x89, 0x2c, 0x1a, 0x45, 0x28, 0x55, 0xc3, 0x37, 0xdc, 0xd9, 0x9f, 0x28,
|
||||
0x94, 0x1d, 0x19, 0x43, 0xbb, 0x06, 0x2b, 0x00, 0x79, 0x12, 0x7f, 0xaa, 0x83, 0x2c, 0x26, 0x8c,
|
||||
0xbf, 0x6d, 0xc9, 0x82, 0x3f, 0xf8, 0x27, 0x42, 0x3b, 0x96, 0xa7, 0x1e, 0x28, 0x87, 0x13, 0xde,
|
||||
0x16, 0xd9, 0x7f, 0x02, 0xb4, 0xa3, 0xb5, 0x61, 0x1b, 0x03, 0x47, 0x11, 0x41, 0xad, 0x1b, 0x8f,
|
||||
0x2f, 0x84, 0xeb, 0x02, 0x7e, 0x61, 0x81, 0xb0, 0x97, 0xc5, 0x05, 0x29, 0xbe, 0xb2, 0x09, 0x4f,
|
||||
0xc8, 0xdc, 0x0a, 0x56, 0x73, 0x75, 0x21, 0x2c, 0xe7, 0x86, 0x8d, 0x3b, 0x06, 0x04, 0xec, 0xb0,
|
||||
0x8c, 0x2e, 0x84, 0xc7, 0x02, 0xe1, 0x50, 0x4c, 0x87, 0x13, 0x5d, 0x08, 0x35, 0xc0, 0x13, 0xc3,
|
||||
0x6a, 0x49, 0x3b, 0xad, 0xe1, 0x8a, 0x78, 0xe5, 0x2f, 0x40, 0x7a, 0xba, 0xb3, 0x1a, 0xb3, 0xc5,
|
||||
0xf9, 0x23, 0x2d, 0x70, 0x41, 0x04, 0x62, 0xb4, 0x6c, 0x6a, 0x78, 0x0c, 0xff, 0x17, 0x60, 0x17,
|
||||
0xfa, 0xf4, 0x38, 0x87, 0x01, 0xbb, 0xfe, 0x20, 0xb6, 0xa8, 0x27, 0x75, 0x25, 0x45, 0xfc, 0x15,
|
||||
0xe5, 0x40, 0xee, 0x9a, 0x74, 0x78, 0xec, 0x9a, 0x14, 0x52, 0x83, 0xf2, 0xdc, 0x18, 0xea, 0xa0,
|
||||
0x79, 0xdc, 0xfe, 0xe3, 0xf9, 0x66, 0x98, 0x2a, 0x41, 0xef, 0x99, 0xe1, 0x19, 0x3d, 0x9f, 0x05,
|
||||
0xff, 0x97, 0xf5, 0xa3, 0x06, 0x6c, 0xa1, 0xd5, 0xe5, 0x6d, 0x09, 0xae, 0x48, 0xf2, 0x6c, 0xa0,
|
||||
0xcf, 0x3a, 0x21, 0x26, 0x9d, 0x67, 0xa0, 0x98, 0x11, 0x60, 0xa8, 0x38, 0x0b, 0xed, 0xd1, 0xc5,
|
||||
0xcd, 0x62, 0xfb, 0x6d, 0xf0, 0xfc, 0x02, 0xab, 0x08, 0xea, 0x3a, 0xab, 0xba, 0x2d, 0x9a, 0x03,
|
||||
0x88, 0xd6, 0xe7, 0xf8, 0x85, 0x8e, 0x1e, 0xc7, 0xf3, 0x21, 0x6f, 0xf4, 0xbe, 0x37, 0x5a, 0x1a,
|
||||
0x10, 0x66, 0x1f, 0xac, 0xc3, 0x6b, 0x61, 0x60, 0x63, 0x61, 0x89, 0xc6, 0x32, 0x77, 0x58, 0x19,
|
||||
0xfc, 0x00, 0x1a, 0xa8, 0x28, 0x5a, 0xbd, 0x30, 0x7f, 0x59, 0x97, 0x21, 0xb3, 0x3a, 0xd3, 0x33,
|
||||
0x66, 0xa9, 0xb9, 0xda, 0x23, 0x84, 0xa1, 0x2f, 0x0b, 0xab, 0xd6, 0x19, 0xe4, 0x7d, 0x3c, 0xbe,
|
||||
0x30, 0x5d, 0xc8, 0x0e, 0x1c, 0x37, 0x20, 0xfc, 0x8b, 0x9c, 0x78, 0xbe, 0xd1, 0xa4, 0xc4, 0x20,
|
||||
0xec, 0x77, 0x28, 0xb8, 0x81, 0x64, 0xf6, 0xb1, 0x8c, 0xe6, 0x3d, 0x66, 0x21, 0x03, 0x56, 0x0c,
|
||||
0x7b, 0x06, 0x9b, 0x75, 0x88, 0x32, 0xca, 0xc4, 0x7d, 0x12, 0xa8, 0x26, 0xe7, 0xf6, 0xfb, 0xf7,
|
||||
0xc8, 0x52, 0x17, 0x80, 0x6d, 0xb7, 0x93, 0x10, 0x2e, 0xc0, 0x92, 0xfb, 0x2c, 0x88, 0x23, 0x1f,
|
||||
0x84, 0x24, 0x84, 0x96, 0x1f, 0xd0, 0x1d, 0x31, 0x14, 0x43, 0xac, 0xf8, 0xc9, 0x41, 0x68, 0xbd,
|
||||
0x21, 0x9a, 0x9b, 0x02, 0xf1, 0xd6, 0xb0, 0x43, 0xe4, 0x95, 0xb4, 0x46, 0x47, 0x10, 0x41, 0x00,
|
||||
0x56, 0xf2, 0x3a, 0x29, 0x96, 0xba, 0x85, 0x69, 0xc2, 0xab, 0x06, 0xcc, 0xea, 0x51, 0x62, 0x98,
|
||||
0x9f, 0x04, 0x8d, 0x4e, 0x99, 0xae, 0xdf, 0x2e, 0x8d, 0x51, 0x0c, 0x36, 0x8c, 0xe5, 0x85, 0x25,
|
||||
0x38, 0x56, 0x94, 0x98, 0x4e, 0x0d, 0x7f, 0xec, 0xb4, 0xc8, 0x4c, 0x3c, 0xfb, 0x20, 0xe8, 0x8c,
|
||||
0xff, 0xfe, 0x2c, 0x6f, 0x0d, 0xeb, 0xb9, 0x8e, 0xd9, 0x18, 0x76, 0xce, 0x20, 0x87, 0xa6, 0x6b,
|
||||
0x51, 0xe4, 0xb5, 0x31, 0x31, 0x2c, 0x7b, 0xbc, 0x51, 0xe7, 0x41, 0x29, 0x86, 0x54, 0xb3, 0xe8,
|
||||
0x51, 0x0c, 0xbc, 0xf1, 0x64, 0x2d, 0xf9, 0x41, 0xcc, 0xd6, 0xb7, 0x87, 0x64, 0x15, 0x43, 0xfd,
|
||||
0x83, 0x48, 0x7d, 0x64, 0x58, 0x01, 0x69, 0x53, 0x88, 0xb6, 0x12, 0x51, 0x0c, 0x23, 0x24, 0x17,
|
||||
0x6b, 0xda, 0x9c, 0x23, 0x49, 0x21, 0x1e, 0xce, 0x48, 0x93, 0x1e, 0x0d, 0xba, 0x2e, 0xc4, 0x1c,
|
||||
0x18, 0xfe, 0x08, 0x12, 0xbe, 0x99, 0x4d, 0x3d, 0x1f, 0xc2, 0xde, 0x78, 0x44, 0x03, 0xe9, 0xc4,
|
||||
0x4a, 0x48, 0x33, 0x95, 0xf0, 0xbd, 0xed, 0x12, 0x85, 0x9c, 0xdf, 0x09, 0x97, 0x0f, 0x64, 0xec,
|
||||
0x49, 0x88, 0xe5, 0xb5, 0x48, 0x3b, 0xe2, 0xb4, 0x85, 0x09, 0x30, 0x96, 0x97, 0xa2, 0x76, 0xea,
|
||||
0x79, 0x98, 0x42, 0x8a, 0x90, 0x52, 0x82, 0xeb, 0x0c, 0x3e, 0x26, 0xd6, 0x13, 0x32, 0xaa, 0x20,
|
||||
0x62, 0xc9, 0x3b, 0xb8, 0xb0, 0x7a, 0xd4, 0x1d, 0x40, 0xb6, 0x17, 0xab, 0x26, 0xd0, 0x57, 0x89,
|
||||
0x08, 0xa0, 0xaa, 0xd2, 0x8c, 0x28, 0x96, 0x9e, 0x59, 0x66, 0x5e, 0xbd, 0xfc, 0xad, 0x85, 0x16,
|
||||
0x17, 0x99, 0xae, 0x28, 0xc1, 0x96, 0x0a, 0xf1, 0x58, 0xcc, 0x92, 0x0a, 0xc7, 0x16, 0x2b, 0x87,
|
||||
0x7f, 0xad, 0x81, 0x80, 0xf1, 0x92, 0x3d, 0x16, 0x62, 0xf7, 0x86, 0x30, 0x17, 0x56, 0x65, 0x29,
|
||||
0x08, 0x2b, 0xb0, 0x0f, 0x4f, 0x3a, 0x61, 0x09, 0x94, 0xc9, 0x04, 0x64, 0xb7, 0xa1, 0x04, 0x82,
|
||||
0xee, 0x32, 0xa9, 0xc3, 0x32, 0x12, 0x50, 0x1c, 0x45, 0x88, 0x33, 0xc1, 0x31, 0x86, 0x56, 0xc7,
|
||||
0x08, 0x5c, 0x0f, 0x1c, 0x89, 0xd5, 0x6f, 0xba, 0x86, 0x67, 0xca, 0x23, 0xcf, 0x0a, 0x28, 0xf3,
|
||||
0x55, 0x61, 0xdc, 0x1c, 0x63, 0xc5, 0x7c, 0xa4, 0x29, 0xd3, 0x47, 0xda, 0xaa, 0xf2, 0x30, 0x99,
|
||||
0x1f, 0x1c, 0x08, 0xcf, 0xf2, 0x4c, 0xd8, 0x37, 0x2c, 0x2c, 0x61, 0x80, 0x89, 0x42, 0x40, 0x82,
|
||||
0x2e, 0xa4, 0x44, 0x40, 0xc9, 0xc0, 0x02, 0x4c, 0x59, 0xe1, 0x7e, 0xdd, 0x5e, 0xba, 0xec, 0xcd,
|
||||
0x33, 0x30, 0xa8, 0x0e, 0x3b, 0x50, 0x79, 0x19, 0xe4, 0xfa, 0x25, 0x10, 0x2c, 0xb5, 0xbd, 0x00,
|
||||
0x62, 0xbc, 0x08, 0xc1, 0xd2, 0xbe, 0x97, 0x16, 0x3a, 0x3a, 0x79, 0x09, 0x84, 0x27, 0x37, 0x2f,
|
||||
0x02, 0x5d, 0xbe, 0x02, 0xe6, 0xe4, 0x45, 0x18, 0x26, 0x48, 0x2f, 0xd1, 0x0f, 0x4c, 0xdc, 0x0b,
|
||||
0x20, 0xe8, 0x03, 0x57, 0x41, 0xb0, 0x5a, 0x17, 0x02, 0x60, 0x3d, 0xf6, 0xf9, 0x39, 0x98, 0x44,
|
||||
0xfa, 0x6e, 0x9f, 0x15, 0x72, 0xa3, 0x6a, 0x24, 0x2b, 0xea, 0xc6, 0x0b, 0x9c, 0x77, 0xd2, 0xcc,
|
||||
0xb1, 0xeb, 0x00, 0xcc, 0xea, 0x55, 0xa0, 0x47, 0xf2, 0xa3, 0x34, 0xf3, 0xf1, 0x0b, 0xed, 0x63,
|
||||
0x89, 0x85, 0x04, 0x20, 0x47, 0x33, 0x43, 0xbb, 0x74, 0x84, 0xf5, 0x1a, 0x45, 0x09, 0x8f, 0x39,
|
||||
0x21, 0x68, 0xd0, 0x97, 0x43, 0x90, 0xbe, 0xe7, 0x06, 0x2e, 0xe4, 0x1f, 0x1f, 0x0d, 0x9b, 0x7a,
|
||||
0x10, 0xcf, 0x7f, 0x06, 0x35, 0xe6, 0xa9, 0x09, 0xfa, 0xdb, 0x21, 0x88, 0x36, 0x7b, 0xd7, 0x67,
|
||||
0xd4, 0x85, 0x3c, 0xc7, 0xa7, 0xde, 0x10, 0x04, 0x1d, 0xbf, 0x84, 0xc7, 0x6c, 0x36, 0x49, 0xb8,
|
||||
0x1e, 0xff, 0xfa, 0x04, 0x78, 0x42, 0x6f, 0xe0, 0xcc, 0x7b, 0x7c, 0x51, 0x10, 0x4b, 0x71, 0x6f,
|
||||
0x31, 0x0d, 0x45, 0xcb, 0x75, 0xd8, 0xdb, 0x07, 0x3a, 0x43, 0x0b, 0xcf, 0x87, 0x58, 0x50, 0x19,
|
||||
0x5a, 0x58, 0x7d, 0x5e, 0x74, 0x08, 0x7d, 0x98, 0xaa, 0x28, 0x7f, 0xcf, 0x4a, 0xdd, 0xf3, 0x5e,
|
||||
0x88, 0xd9, 0x73, 0x39, 0x56, 0x09, 0x0c, 0xf4, 0x6f, 0xcb, 0xbf, 0x97, 0xb1, 0xa9, 0x98, 0xb4,
|
||||
0x23, 0x11, 0xf6, 0x6b, 0x19, 0xef, 0x26, 0x74, 0xfa, 0x97, 0xc4, 0xbe, 0x69, 0xc9, 0xef, 0xc5,
|
||||
0x6f, 0x65, 0x36, 0x0d, 0x77, 0x77, 0xf3, 0xef, 0xf9, 0xb1, 0x08, 0x51, 0x0f, 0xa6, 0x4c, 0xb8,
|
||||
0x17, 0x90, 0xe4, 0x88, 0x40, 0x73, 0xb9, 0x75, 0xb4, 0x88, 0x2d, 0x8d, 0xa1, 0x1a, 0x2c, 0xa2,
|
||||
0x1a, 0x19, 0x97, 0x74, 0x4e, 0xd5, 0x18, 0x9e, 0xce, 0x4b, 0x78, 0x06, 0x31, 0x3c, 0x03, 0x86,
|
||||
0x27, 0x7d, 0x06, 0x49, 0x67, 0x8a, 0xa7, 0x96, 0x2f, 0x49, 0x62, 0x54, 0xe6, 0xe4, 0x55, 0x9f,
|
||||
0x75, 0xe7, 0x60, 0x74, 0xf9, 0x1c, 0x8c, 0xc6, 0xcf, 0xc1, 0x02, 0x76, 0xec, 0x13, 0x1e, 0x85,
|
||||
0x49, 0x98, 0x91, 0xbf, 0xd1, 0xd9, 0xb9, 0x41, 0x68, 0x35, 0x23, 0x87, 0x8b, 0xef, 0xa9, 0x7c,
|
||||
0x81, 0xa0, 0x82, 0x07, 0x02, 0xf3, 0xb7, 0x56, 0x44, 0x96, 0x95, 0x9f, 0xb1, 0xf7, 0x49, 0xc2,
|
||||
0x13, 0xd6, 0xd8, 0x0b, 0x26, 0xa8, 0x6d, 0xec, 0x54, 0x18, 0x23, 0xcf, 0x79, 0xf8, 0x8b, 0x23,
|
||||
0xd9, 0xfb, 0x2c, 0x94, 0x7d, 0xf7, 0x8a, 0xca, 0x08, 0x05, 0x7b, 0xdc, 0xa5, 0x6d, 0x03, 0x52,
|
||||
0xe8, 0x44, 0x7c, 0x52, 0x99, 0x49, 0x79, 0x22, 0xf6, 0x35, 0x2c, 0xc8, 0x5e, 0x3b, 0x7b, 0x98,
|
||||
0xab, 0x3c, 0x33, 0x16, 0x2b, 0xcf, 0xcb, 0x27, 0x7d, 0x38, 0x26, 0x85, 0x62, 0x2b, 0x2c, 0x4d,
|
||||
0x74, 0x3a, 0x7c, 0x6e, 0x9e, 0x38, 0x9c, 0x0b, 0xd1, 0xa9, 0xf9, 0xba, 0xe5, 0x3c, 0xda, 0x83,
|
||||
0x75, 0x16, 0x56, 0x2c, 0x0f, 0xfa, 0xf8, 0x9b, 0x6a, 0x67, 0x9c, 0x14, 0x20, 0x34, 0xa8, 0xf5,
|
||||
0xac, 0xd4, 0xd0, 0x86, 0xfd, 0xe1, 0x56, 0x7d, 0x48, 0x21, 0x63, 0x0b, 0xce, 0x76, 0xcf, 0xd6,
|
||||
0x5c, 0x1e, 0xcd, 0x4f, 0xcc, 0xd7, 0x8d, 0x5b, 0x82, 0x0c, 0x4b, 0x97, 0x20, 0xb4, 0x98, 0xa4,
|
||||
0x60, 0xbc, 0x5d, 0x67, 0xc1, 0x4e, 0x39, 0x88, 0x8e, 0x27, 0x98, 0x08, 0x85, 0x2c, 0x62, 0xa1,
|
||||
0x3f, 0xe2, 0x8f, 0x55, 0x0c, 0x69, 0x25, 0x85, 0x80, 0x00, 0x72, 0x2a, 0x61, 0xb7, 0x61, 0x56,
|
||||
0x7c, 0xcc, 0xb1, 0x20, 0xe9, 0x59, 0xf8, 0x76, 0xdc, 0x9a, 0x84, 0x22, 0xfc, 0xae, 0x1c, 0x04,
|
||||
0x3a, 0x91, 0xf8, 0xac, 0x11, 0x67, 0x24, 0x54, 0x98, 0x7a, 0xce, 0x38, 0x0b, 0x51, 0xe0, 0xcf,
|
||||
0x07, 0x30, 0xc2, 0x4a, 0x11, 0x03, 0x5f, 0x00, 0x77, 0xfb, 0x82, 0x14, 0xf2, 0xf0, 0xa7, 0x90,
|
||||
0xa1, 0x3d, 0x8d, 0x49, 0xe7, 0x82, 0x20, 0x3e, 0xaf, 0x89, 0x73, 0x7e, 0xcd, 0xcf, 0x1d, 0xfe,
|
||||
0xdb, 0x87, 0xd8, 0x33, 0x3e, 0x2c, 0xbc, 0xc9, 0xf8, 0x9a, 0x53, 0x27, 0x09, 0x4d, 0xdc, 0xda,
|
||||
0x93, 0x27, 0x07, 0xd3, 0xb8, 0x00, 0xbc, 0x49, 0x2c, 0xdc, 0xfb, 0x98, 0x08, 0xf4, 0xa5, 0x30,
|
||||
0x13, 0xe0, 0x96, 0x8e, 0xb7, 0xa5, 0x35, 0x49, 0x6b, 0x98, 0x94, 0x40, 0x2c, 0x1a, 0xc4, 0xe7,
|
||||
0x5b, 0x1a, 0xec, 0x3c, 0x33, 0x16, 0xb0, 0x59, 0x1f, 0x89, 0x06, 0xab, 0x1d, 0xe0, 0xc8, 0x31,
|
||||
0x5c, 0x60, 0x0e, 0x35, 0x9e, 0x72, 0x53, 0x0f, 0xb4, 0x23, 0x3c, 0x41, 0x3e, 0xe5, 0x9e, 0x9b,
|
||||
0xc5, 0x83, 0xe0, 0xbc, 0xe3, 0x79, 0xd2, 0x8c, 0x85, 0xec, 0xe0, 0x76, 0x2b, 0x0a, 0x66, 0xcb,
|
||||
0x01, 0x16, 0x81, 0xb8, 0x91, 0xc7, 0xd3, 0x42, 0xee, 0xfb, 0x05, 0x2c, 0x60, 0x70, 0x7f, 0x4e,
|
||||
0x6f, 0x83, 0xf0, 0x50, 0x32, 0xac, 0xa1, 0xf0, 0x16, 0xbc, 0x83, 0x86, 0x59, 0x04, 0xc0, 0x5b,
|
||||
0x1f, 0x63, 0x4d, 0x63, 0xde, 0x34, 0xe6, 0x91, 0x07, 0x88, 0xa9, 0x63, 0x56, 0x91, 0x3d, 0x90,
|
||||
0x40, 0x48, 0x0a, 0x50, 0x3f, 0xc0, 0x43, 0xce, 0x59, 0x7c, 0x01, 0x79, 0x43, 0x2c, 0xb8, 0x70,
|
||||
0xd6, 0x86, 0x16, 0xb1, 0xb9, 0xc5, 0x95, 0xec, 0x2e, 0x76, 0x8c, 0xce, 0x8b, 0x10, 0xad, 0xa1,
|
||||
0x3e, 0x0f, 0xd2, 0xa5, 0xd6, 0x70, 0x9e, 0xc2, 0x62, 0xa8, 0xcc, 0xbd, 0xcb, 0xed, 0x5d, 0xe8,
|
||||
0x08, 0x9c, 0x67, 0x32, 0xaf, 0xd6, 0x70, 0x31, 0xcf, 0x8a, 0xaa, 0x74, 0x89, 0x30, 0x48, 0x0f,
|
||||
0x33, 0x25, 0x4c, 0x6d, 0x3b, 0xd1, 0x81, 0x49, 0x62, 0x62, 0x99, 0x25, 0x48, 0x52, 0x4d, 0xc9,
|
||||
0x81, 0x8b, 0x23, 0x3d, 0xfa, 0x25, 0xf4, 0x86, 0x86, 0x17, 0x48, 0x8f, 0x94, 0xdd, 0xba, 0x7d,
|
||||
0x69, 0x3c, 0x6b, 0xbc, 0x91, 0xc6, 0x51, 0xeb, 0xcd, 0x54, 0x14, 0x97, 0xf8, 0x64, 0xc7, 0xf9,
|
||||
0x44, 0xf9, 0x01, 0xc5, 0x84, 0x9f, 0xab, 0xdb, 0x48, 0x5e, 0x58, 0x85, 0x85, 0xec, 0xec, 0xc1,
|
||||
0xc1, 0xc3, 0x4a, 0x0b, 0x23, 0x35, 0x3c, 0xba, 0x0c, 0xfb, 0x59, 0xc1, 0xee, 0x91, 0x03, 0x3c,
|
||||
0xd2, 0x14, 0xbf, 0xfa, 0xd2, 0x98, 0xb7, 0x8c, 0xc3, 0x96, 0xb1, 0x0f, 0x4e, 0xf1, 0x59, 0x69,
|
||||
0x92, 0x56, 0xce, 0xf7, 0xc3, 0x24, 0x7b, 0x5d, 0xf6, 0xcd, 0xb3, 0xf4, 0x17, 0xd2, 0xfe, 0x57,
|
||||
0xe4, 0x68, 0xbf, 0x50, 0x69, 0x08, 0x93, 0xb5, 0x9f, 0x24, 0xa6, 0x2f, 0x4c, 0xf6, 0x62, 0x66,
|
||||
0xfa, 0xeb, 0xc8, 0xac, 0xa3, 0x19, 0x27, 0xcd, 0xb3, 0x15, 0x0b, 0x76, 0x1e, 0xf8, 0x5f, 0xc1,
|
||||
0x74, 0x25, 0x99, 0xfe, 0x0d, 0x6c, 0x9f, 0x33, 0x42, 0xac, 0x18, 0x82, 0x4c, 0x98, 0x4b, 0xf2,
|
||||
0xed, 0x1d, 0x18, 0x44, 0xa5, 0xec, 0x6c, 0xd1, 0xb2, 0x03, 0x72, 0x1c, 0x2c, 0xc8, 0xb1, 0xc3,
|
||||
0x25, 0x58, 0x68, 0x44, 0xdf, 0x50, 0x40, 0x01, 0x06, 0xf9, 0x75, 0x40, 0x22, 0xc3, 0xaf, 0xa5,
|
||||
0x07, 0xd3, 0xff, 0x13, 0x41, 0x23, 0xce, 0x1e, 0x7e, 0xcf, 0x00, 0x63, 0x05, 0x7d, 0xed, 0xc6,
|
||||
0x55, 0xe5, 0x59, 0x45, 0x8a, 0x8d, 0x0d, 0xdf, 0xfa, 0x8b, 0x99, 0xe8, 0x0f, 0xec, 0x75, 0x7f,
|
||||
0xcb, 0xd4, 0x17, 0x5f, 0x08, 0x22, 0x3f, 0xff, 0x4a, 0xfb, 0xe2, 0xaf, 0x2b, 0xbd, 0xf0, 0x75,
|
||||
0x80, 0x05, 0x1b, 0x19, 0xbd, 0xfc, 0x0f, 0x2b, 0x82, 0xb4, 0x3c, 0xfb, 0xbb, 0x3a, 0x79, 0x39,
|
||||
0x47, 0x34, 0xe5, 0x3c, 0x2b, 0x6b, 0x1a, 0x5c, 0x89, 0x26, 0xe7, 0xf1, 0x87, 0x6d, 0xd8, 0xcf,
|
||||
0xd3, 0x10, 0x35, 0x2f, 0x17, 0x73, 0x78, 0xcd, 0xca, 0xb9, 0x22, 0x5e, 0xa1, 0x37, 0x03, 0x20,
|
||||
0x6a, 0x81, 0xa8, 0xaa, 0xac, 0x92, 0x8c, 0x9c, 0xc9, 0x91, 0x4d, 0xfc, 0xcd, 0x9d, 0x9c, 0xac,
|
||||
0xe1, 0x9d, 0x9a, 0x83, 0xbb, 0x7c, 0x91, 0x14, 0xb0, 0x03, 0x3e, 0x8a, 0xf0, 0x58, 0xc8, 0x40,
|
||||
0x87, 0x82, 0x3f, 0xcb, 0x03, 0x13, 0xa8, 0xe1, 0x45, 0x2e, 0x66, 0xf8, 0x9d, 0x26, 0x67, 0xb1,
|
||||
0x2d, 0xbf, 0x49, 0x54, 0xf6, 0x73, 0x3d, 0x45, 0xbc, 0xe6, 0x65, 0xf5, 0x0a, 0x7a, 0xd4, 0xdc,
|
||||
0x11, 0xac, 0x9c, 0x27, 0xaa, 0x22, 0xe7, 0x8f, 0x54, 0xb8, 0x6a, 0x47, 0xaa, 0x06, 0x48, 0x1d,
|
||||
0x15, 0xf1, 0x76, 0x53, 0xce, 0x86, 0x3d, 0x6c, 0x1a, 0x35, 0x77, 0x05, 0xc3, 0xce, 0x01, 0x07,
|
||||
0x18, 0x9e, 0xcd, 0x91, 0xa2, 0xac, 0x20, 0x0a, 0x9b, 0x59, 0x52, 0x80, 0xf5, 0x61, 0x3b, 0x88,
|
||||
0x73, 0x0d, 0x76, 0x7b, 0x9e, 0xc3, 0x1e, 0x86, 0x89, 0x92, 0xc1, 0x91, 0x0a, 0x7e, 0x29, 0x41,
|
||||
0xcd, 0x60, 0x6b, 0x86, 0x6d, 0x15, 0x2f, 0x39, 0x79, 0x33, 0x17, 0x42, 0xe0, 0xee, 0x70, 0x44,
|
||||
0x91, 0x20, 0xad, 0xd4, 0x62, 0x0d, 0xc8, 0x93, 0x3b, 0xc7, 0x1f, 0xef, 0x61, 0x8d, 0x9a, 0x22,
|
||||
0x6b, 0x30, 0x77, 0x01, 0x3f, 0x35, 0x46, 0x33, 0x68, 0xc7, 0x9b, 0x9c, 0xcc, 0xaf, 0x59, 0x44,
|
||||
0x27, 0x84, 0xca, 0x20, 0x39, 0xc2, 0xa1, 0x19, 0xa4, 0x33, 0x5e, 0x6b, 0x6a, 0xe1, 0x4a, 0x55,
|
||||
0xcf, 0x55, 0x44, 0xb4, 0x88, 0x13, 0x30, 0xf4, 0x0b, 0x79, 0x86, 0x05, 0xec, 0x01, 0x87, 0xc0,
|
||||
0x5e, 0xae, 0x80, 0x16, 0xc5, 0x73, 0xce, 0x93, 0x1c, 0x9b, 0x01, 0xb6, 0x07, 0xfb, 0x92, 0x35,
|
||||
0x80, 0xdc, 0x24, 0x9b, 0xf8, 0xa1, 0xe2, 0x0b, 0x69, 0x6c, 0x80, 0x2a, 0x03, 0x3f, 0x81, 0xce,
|
||||
0x48, 0x36, 0x44, 0x84, 0x6d, 0xb1, 0x50, 0x64, 0x37, 0xb9, 0xb0, 0x81, 0x71, 0x08, 0x80, 0x90,
|
||||
0xfa, 0x45, 0xfc, 0x84, 0xb1, 0xd8, 0xa2, 0x70, 0xcc, 0x34, 0xe5, 0x18, 0xe9, 0xad, 0xc2, 0xee,
|
||||
0xe3, 0xbf, 0x4a, 0xc4, 0x0a, 0x60, 0xcb, 0x72, 0x1d, 0x7d, 0x3f, 0x21, 0xfc, 0x11, 0x2d, 0x81,
|
||||
0xfc, 0xfa, 0xd7, 0x5a, 0xb6, 0x5f, 0xfa, 0x05, 0xa8, 0x4d, 0x49, 0x53, 0x6b, 0xc5, 0xab, 0x42,
|
||||
0x4d, 0xdd, 0xc4, 0x87, 0x5c, 0xad, 0x58, 0xd1, 0x24, 0x2d, 0x7c, 0x77, 0x2f, 0x2f, 0x15, 0xae,
|
||||
0x34, 0x35, 0xd6, 0x50, 0x94, 0x34, 0xa0, 0xec, 0x66, 0xac, 0x05, 0x7f, 0x44, 0x47, 0xbd, 0x2a,
|
||||
0xc4, 0x5a, 0x70, 0x96, 0x63, 0x35, 0x2f, 0xa9, 0xb5, 0x6c, 0x1c, 0x4e, 0xca, 0x5c, 0xa9, 0x85,
|
||||
0x5a, 0xf6, 0x0a, 0xc6, 0xe7, 0xaf, 0x54, 0xb6, 0x77, 0xc2, 0x37, 0x1f, 0xbe, 0xa2, 0x5d, 0x65,
|
||||
0xa5, 0x34, 0x97, 0xcc, 0x4a, 0x77, 0x1f, 0x9e, 0xaf, 0x80, 0xfc, 0x8b, 0x94, 0x42, 0xd5, 0x0e,
|
||||
0x8b, 0xdb, 0xff, 0x45, 0xfd, 0x2e, 0xa2, 0x22, 0x14, 0x51, 0xb9, 0x0a, 0xf8, 0x98, 0x45, 0xfd,
|
||||
0x86, 0x61, 0xa0, 0x8d, 0x1a, 0x7e, 0x64, 0x51, 0x28, 0xb3, 0x38, 0xf7, 0x66, 0x1e, 0x00, 0xf1,
|
||||
0xd7, 0xb2, 0x36, 0x51, 0x1b, 0x0b, 0xff, 0x82, 0x7c, 0xd6, 0xd4, 0xcc, 0x39, 0xea, 0x3e, 0x6f,
|
||||
0x53, 0xe5, 0x1c, 0x2a, 0x01, 0x5a, 0x14, 0xf6, 0xeb, 0x5c, 0x68, 0x64, 0xd8, 0x0d, 0x1a, 0x93,
|
||||
0x62, 0x8e, 0x5b, 0x0c, 0xd0, 0x46, 0xb4, 0x1f, 0x19, 0x34, 0x25, 0x9b, 0xcc, 0xaa, 0x64, 0x42,
|
||||
0x2b, 0x83, 0x3d, 0x2a, 0xb3, 0x08, 0xc5, 0xdc, 0xd5, 0xbf, 0xaa, 0xe6, 0x45, 0x24, 0x11, 0x0e,
|
||||
0x04, 0xe3, 0x24, 0x67, 0xd9, 0xd2, 0x0a, 0x10, 0x15, 0x09, 0x98, 0x07, 0x62, 0x42, 0x67, 0x1e,
|
||||
0x60, 0xa0, 0x83, 0xf5, 0x86, 0xf0, 0x7f, 0xce, 0x7e, 0x6d, 0x5e, 0x85, 0x9a, 0x9d, 0x59, 0x23,
|
||||
0xda, 0x0d, 0x10, 0x28, 0x14, 0x6d, 0x93, 0x7d, 0x41, 0xf2, 0x83, 0xb4, 0xf6, 0xc8, 0xee, 0x17,
|
||||
0xa2, 0xa5, 0x85, 0x1f, 0x94, 0x09, 0x7f, 0x42, 0x86, 0x5f, 0xb7, 0xd8, 0x57, 0x5a, 0xb6, 0xff,
|
||||
0x07, 0x16, 0x4c, 0xe9, 0xef, 0x21, 0x5e, 0x00, 0x00
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a, 0xd5, 0x3c, 0x6d, 0x7b, 0xda, 0xb8,
|
||||
0xb2, 0xdf, 0xf9, 0x15, 0xaa, 0xdb, 0x6d, 0x71, 0x23, 0x1c, 0xdb, 0xbc, 0x06, 0xe2, 0xf4, 0xc9,
|
||||
0xa6, 0xed, 0xa6, 0xe7, 0xa6, 0x2f, 0x9b, 0xb4, 0xd9, 0xed, 0xc9, 0xc9, 0xd3, 0x0a, 0x2c, 0xc0,
|
||||
0xad, 0xb1, 0x39, 0xb6, 0x21, 0x61, 0x29, 0xff, 0xfd, 0xce, 0x48, 0xb2, 0x31, 0x60, 0x1a, 0xd2,
|
||||
0xdb, 0x3d, 0xcf, 0x3d, 0xdb, 0x0d, 0xb6, 0xa5, 0x91, 0x34, 0x9a, 0xf7, 0x19, 0x19, 0x0e, 0x1f,
|
||||
0x3c, 0x7f, 0x7b, 0xf2, 0xfe, 0xe3, 0xbb, 0x17, 0x64, 0x98, 0x8c, 0xfc, 0x23, 0x72, 0x98, 0x5e,
|
||||
0x38, 0x73, 0xe1, 0x32, 0xe2, 0x09, 0x83, 0x9e, 0x64, 0x5c, 0xe1, 0xff, 0x9e, 0x78, 0x53, 0x47,
|
||||
0x3b, 0x61, 0xbd, 0x21, 0xaf, 0x9c, 0x84, 0x41, 0x12, 0x85, 0xbe, 0x46, 0x4a, 0x3d, 0xb8, 0xe3,
|
||||
0x41, 0xe2, 0x68, 0x41, 0x58, 0xe9, 0x61, 0x1f, 0x25, 0x70, 0x17, 0x27, 0x61, 0x04, 0x77, 0xa3,
|
||||
0x49, 0x9c, 0x54, 0x22, 0x3e, 0x65, 0xbe, 0xe7, 0xb2, 0x84, 0x6b, 0x45, 0x13, 0xbe, 0x8b, 0xd8,
|
||||
0x60, 0xc4, 0x8a, 0x66, 0x2a, 0x04, 0x7f, 0x71, 0x3b, 0xf6, 0x22, 0x1e, 0x6b, 0x24, 0x03, 0x37,
|
||||
0x11, 0x2e, 0xf1, 0x12, 0x9f, 0x1f, 0x95, 0xfe, 0x38, 0x7b, 0xf1, 0x9c, 0xbc, 0xf3, 0x6e, 0xb9,
|
||||
0x4f, 0x8e, 0xa3, 0x84, 0x00, 0x9a, 0x53, 0x1e, 0x25, 0x3c, 0x3a, 0xdc, 0x97, 0x00, 0xe4, 0x30,
|
||||
0x4e, 0x66, 0x08, 0x68, 0x74, 0xc3, 0xdb, 0x79, 0x37, 0x8c, 0x5c, 0x1e, 0xb5, 0xed, 0xf1, 0x2d,
|
||||
0x89, 0x43, 0x40, 0x91, 0x3c, 0xec, 0xf7, 0xfb, 0x8b, 0x6e, 0xe8, 0xce, 0xe6, 0x7d, 0x98, 0xbd,
|
||||
0xd2, 0x67, 0x23, 0xcf, 0x9f, 0xb5, 0x8f, 0x23, 0x8f, 0xf9, 0x34, 0x66, 0x41, 0x5c, 0x89, 0x79,
|
||||
0xe4, 0xf5, 0x3b, 0x5d, 0xd6, 0xfb, 0x3a, 0x88, 0xc2, 0x49, 0xe0, 0x56, 0x7a, 0xa1, 0x1f, 0x46,
|
||||
0xed, 0x87, 0x96, 0x65, 0x2d, 0x8c, 0x24, 0x1c, 0x57, 0xc6, 0x2c, 0x4a, 0xe6, 0x37, 0x9e, 0x9b,
|
||||
0x0c, 0xdb, 0x0d, 0xd3, 0x1c, 0xdf, 0x76, 0x46, 0x2c, 0x1a, 0x78, 0x41, 0xdb, 0x24, 0x6c, 0x92,
|
||||
0x84, 0x0b, 0x03, 0xb1, 0x66, 0x5e, 0xc0, 0xa3, 0xf9, 0x88, 0xdd, 0x56, 0x24, 0xa0, 0x65, 0x9a,
|
||||
0xbf, 0x90, 0x4a, 0x0d, 0xa1, 0x25, 0x46, 0x95, 0x88, 0xb9, 0xde, 0x24, 0x6e, 0x9b, 0x9d, 0x31,
|
||||
0x73, 0x5d, 0x2f, 0x18, 0xb4, 0x6d, 0xec, 0x4c, 0xf8, 0x6d, 0x52, 0x01, 0x52, 0x0e, 0x82, 0x76,
|
||||
0x0f, 0x76, 0xce, 0xa3, 0xc5, 0xd0, 0x92, 0x88, 0xc6, 0xde, 0x5f, 0xbc, 0x6d, 0x1b, 0x55, 0x3e,
|
||||
0xea, 0x28, 0x84, 0x5c, 0xd7, 0x4d, 0x97, 0xb6, 0x60, 0x7b, 0x66, 0xe7, 0xbb, 0x1b, 0xf2, 0x01,
|
||||
0xa3, 0xca, 0x90, 0x7b, 0x83, 0x61, 0xd2, 0x36, 0xea, 0x8b, 0xa1, 0x9d, 0x9b, 0xd6, 0x32, 0xac,
|
||||
0x6c, 0xda, 0x68, 0xd0, 0x65, 0x65, 0xdb, 0xb6, 0x68, 0xfa, 0x67, 0x34, 0x2c, 0xfd, 0x87, 0xd7,
|
||||
0x29, 0xda, 0x50, 0x35, 0xb7, 0xb2, 0xd1, 0xfc, 0x5b, 0x16, 0xb6, 0x8c, 0xda, 0xe6, 0xca, 0x1d,
|
||||
0xf1, 0x50, 0xf1, 0x12, 0x3e, 0x8a, 0xd3, 0xa6, 0x2f, 0x20, 0xbd, 0x5e, 0x7f, 0x56, 0x51, 0x92,
|
||||
0x96, 0x36, 0xbb, 0x5e, 0x3c, 0xf6, 0xd9, 0xac, 0xdd, 0xf7, 0xf9, 0xed, 0x62, 0x9c, 0xa7, 0xd4,
|
||||
0x92, 0xfc, 0xcd, 0x66, 0x73, 0x6d, 0xcd, 0xfa, 0x77, 0x11, 0x5c, 0x3c, 0xec, 0x7b, 0xdc, 0x77,
|
||||
0xdf, 0xb3, 0xae, 0xcf, 0xf3, 0x33, 0x92, 0xef, 0x4c, 0x79, 0xc7, 0x84, 0x71, 0x8f, 0xf9, 0xfc,
|
||||
0x67, 0x4e, 0xe8, 0x46, 0x20, 0xdf, 0x7f, 0x85, 0x01, 0x9f, 0xa7, 0x14, 0xe8, 0xfa, 0x61, 0xef,
|
||||
0x6b, 0x67, 0x29, 0xc4, 0x79, 0x19, 0x6e, 0x57, 0x81, 0x2b, 0x2e, 0x8b, 0x87, 0x1c, 0xd4, 0x0a,
|
||||
0xa5, 0x71, 0x5d, 0xb4, 0x37, 0x59, 0xb0, 0x22, 0xec, 0xa9, 0xde, 0x74, 0x7a, 0x93, 0x28, 0x06,
|
||||
0x74, 0xc7, 0xa1, 0x27, 0x80, 0xbe, 0xcb, 0xe6, 0xdc, 0x46, 0xeb, 0x30, 0xc7, 0x72, 0xa3, 0x48,
|
||||
0x5f, 0x9f, 0x57, 0xc6, 0x5e, 0xef, 0x2b, 0xa8, 0x5e, 0x8a, 0x7f, 0x00, 0x9b, 0x59, 0x18, 0xcc,
|
||||
0x65, 0xe3, 0xc4, 0x9b, 0xf2, 0xf7, 0xcf, 0xe7, 0x79, 0xd6, 0x76, 0xf0, 0xa3, 0xe2, 0x82, 0xb1,
|
||||
0xe9, 0x25, 0x5e, 0x18, 0xb4, 0xa3, 0xf0, 0x46, 0x36, 0xdd, 0x44, 0x6c, 0x0c, 0x43, 0xf1, 0x52,
|
||||
0x20, 0x35, 0x0b, 0x63, 0x04, 0xfa, 0x7d, 0xc1, 0x7d, 0x18, 0x16, 0x46, 0xf3, 0x4d, 0x53, 0x61,
|
||||
0xdb, 0x76, 0x5e, 0x49, 0x15, 0xb5, 0xac, 0xa5, 0x0d, 0xaa, 0x56, 0xab, 0x6a, 0xf7, 0x15, 0xb0,
|
||||
0x28, 0xed, 0x5a, 0x46, 0x8c, 0x4a, 0x37, 0x4c, 0x92, 0x70, 0x24, 0x5a, 0x52, 0x5a, 0x99, 0xa4,
|
||||
0x05, 0x4f, 0x8a, 0x83, 0x36, 0xde, 0xaf, 0xd1, 0x60, 0x95, 0xec, 0xcd, 0xb1, 0xda, 0x17, 0xe0,
|
||||
0x74, 0x03, 0x1c, 0x5f, 0xd9, 0xf0, 0xce, 0x2a, 0xb0, 0xa4, 0xd9, 0x7f, 0xdb, 0x3e, 0x25, 0xc7,
|
||||
0x63, 0x3e, 0x18, 0xc1, 0x46, 0xe2, 0xe7, 0xde, 0x54, 0xd9, 0xea, 0x6a, 0x63, 0xb9, 0x56, 0xc5,
|
||||
0xe7, 0xfd, 0xa4, 0x0d, 0x73, 0x2e, 0x9e, 0x12, 0x2f, 0x18, 0x4f, 0x92, 0xab, 0x64, 0x36, 0xe6,
|
||||
0x4e, 0xc4, 0x82, 0x01, 0xbf, 0x9e, 0xb3, 0xf1, 0x98, 0x33, 0xb8, 0xef, 0x71, 0x31, 0x59, 0xa7,
|
||||
0x32, 0x0a, 0xff, 0xaa, 0x6c, 0x34, 0xde, 0xf0, 0xee, 0x57, 0x2f, 0xd9, 0x68, 0xcf, 0xa3, 0x94,
|
||||
0xed, 0x2c, 0x15, 0x75, 0xd8, 0x2e, 0x6e, 0x92, 0xd4, 0x84, 0x39, 0xdb, 0x20, 0x68, 0x02, 0xf3,
|
||||
0xc4, 0xe0, 0x5e, 0x00, 0xf1, 0x75, 0x9d, 0x58, 0xc2, 0xb6, 0x51, 0xa1, 0x59, 0x04, 0x6b, 0x00,
|
||||
0x1d, 0x00, 0xb2, 0x9c, 0x84, 0x24, 0x42, 0x9a, 0xd1, 0x87, 0xdd, 0x6e, 0x97, 0xd4, 0xcd, 0x5f,
|
||||
0x28, 0xd2, 0x1d, 0x6f, 0xf4, 0x4d, 0x92, 0x2d, 0x36, 0xb6, 0xdb, 0xee, 0x87, 0xbd, 0x49, 0x3c,
|
||||
0x0f, 0x27, 0x09, 0x4e, 0xdc, 0x36, 0x0b, 0x20, 0xda, 0xe9, 0x66, 0x63, 0xe0, 0x2a, 0x4e, 0x37,
|
||||
0x09, 0x02, 0xb4, 0x3a, 0x15, 0x40, 0xb8, 0xf7, 0x75, 0x9e, 0x67, 0xd9, 0x76, 0xb4, 0x4d, 0xdc,
|
||||
0xf1, 0x0e, 0xe8, 0xac, 0x2f, 0x96, 0x0c, 0x27, 0xa3, 0x6e, 0xba, 0x86, 0x85, 0x4c, 0x54, 0xd6,
|
||||
0xa8, 0xb1, 0x21, 0x12, 0xb0, 0xe5, 0xfc, 0x8a, 0xe8, 0xea, 0xd7, 0x11, 0xda, 0xc6, 0xb6, 0x35,
|
||||
0x29, 0xdd, 0x0d, 0x51, 0x94, 0x0b, 0xf1, 0x50, 0x40, 0x88, 0x0d, 0xe6, 0x0a, 0xff, 0x66, 0x52,
|
||||
0xf1, 0x4f, 0xbf, 0xff, 0x02, 0x82, 0x0a, 0x4a, 0xc3, 0x4c, 0xa5, 0x5f, 0x79, 0x79, 0xd9, 0x89,
|
||||
0x40, 0xcd, 0x15, 0xc4, 0x04, 0x81, 0x16, 0x86, 0x58, 0xe0, 0x0d, 0x4c, 0x0f, 0x66, 0x53, 0x8e,
|
||||
0x14, 0xd6, 0x19, 0xa3, 0x2a, 0x0f, 0x1c, 0x8c, 0x32, 0xe0, 0x23, 0xcf, 0x75, 0x7d, 0x50, 0xac,
|
||||
0xfe, 0xc4, 0xf7, 0xdf, 0x83, 0x5d, 0x7f, 0x89, 0xce, 0x4c, 0xa2, 0x8b, 0x66, 0xfe, 0x7a, 0x8b,
|
||||
0x79, 0x28, 0xb6, 0x09, 0xa9, 0x1a, 0x7a, 0x81, 0xf0, 0x4e, 0x71, 0x02, 0x21, 0x15, 0xaa, 0xe3,
|
||||
0xdd, 0xc6, 0x22, 0x25, 0x71, 0xad, 0x20, 0x92, 0xfa, 0x01, 0xbf, 0xb1, 0xe9, 0xb5, 0x7e, 0x96,
|
||||
0xf9, 0xec, 0xfb, 0xb7, 0xef, 0x5f, 0xfa, 0xee, 0xcf, 0x21, 0xcb, 0x7f, 0xcb, 0xae, 0x57, 0xac,
|
||||
0x69, 0x3c, 0xe9, 0x8e, 0xbc, 0x1f, 0x13, 0x0c, 0x88, 0x1c, 0x21, 0x88, 0x59, 0x46, 0x1d, 0x6b,
|
||||
0xd8, 0x0a, 0x3a, 0xec, 0xba, 0xef, 0xb5, 0x90, 0x19, 0x70, 0xec, 0x4e, 0x40, 0x9c, 0x82, 0xff,
|
||||
0x03, 0x67, 0x04, 0x4f, 0x7e, 0x0e, 0x76, 0xab, 0xe1, 0xfc, 0x8f, 0x91, 0x7d, 0xcd, 0xc6, 0xa9,
|
||||
0xb8, 0x10, 0x3d, 0xdf, 0x5d, 0xf3, 0x15, 0xeb, 0x38, 0xea, 0x33, 0x18, 0x15, 0x36, 0x1f, 0x44,
|
||||
0x9e, 0x5b, 0x11, 0x02, 0xb1, 0x6f, 0xe7, 0xf7, 0x9b, 0x8a, 0xa3, 0xc8, 0x7e, 0xee, 0x43, 0xc6,
|
||||
0x1c, 0x1b, 0x8c, 0x21, 0x58, 0xf7, 0xb5, 0x30, 0x2d, 0x9e, 0x02, 0x85, 0x61, 0x6f, 0xf3, 0x62,
|
||||
0xbc, 0x1e, 0x7a, 0x23, 0x06, 0xa6, 0x70, 0x99, 0x5f, 0xa5, 0xa3, 0x11, 0xcf, 0x8e, 0x40, 0x16,
|
||||
0x36, 0x07, 0x2d, 0x09, 0x47, 0xac, 0xe3, 0xb6, 0xd5, 0x8f, 0x08, 0xfc, 0x2d, 0x1e, 0x4a, 0x8e,
|
||||
0x17, 0x8c, 0x14, 0x84, 0x49, 0x99, 0xab, 0xcc, 0x8c, 0x65, 0xe6, 0x02, 0x05, 0xb4, 0x44, 0xd8,
|
||||
0xb0, 0x30, 0xe4, 0x1c, 0x3d, 0x9f, 0xc5, 0xf1, 0x1c, 0x87, 0x2d, 0xfd, 0xbb, 0x00, 0xaa, 0x8f,
|
||||
0x37, 0x26, 0xc2, 0xf8, 0xc2, 0x18, 0xb0, 0xf1, 0x3c, 0x25, 0x1d, 0x3c, 0x3f, 0x94, 0x5a, 0xa1,
|
||||
0xb2, 0xd6, 0x76, 0xbb, 0xcb, 0xfb, 0x90, 0x46, 0xcf, 0x53, 0x86, 0x6a, 0x5a, 0x26, 0x03, 0xca,
|
||||
0x08, 0xc8, 0x00, 0x3c, 0x47, 0x64, 0x41, 0x84, 0xf6, 0x24, 0xf2, 0xcb, 0x4f, 0x20, 0xe1, 0x66,
|
||||
0x6d, 0xf1, 0xbc, 0x0f, 0xa4, 0xdb, 0xbb, 0x1d, 0xf9, 0x9d, 0x49, 0xd2, 0x6f, 0x51, 0x48, 0x81,
|
||||
0xa7, 0x03, 0x22, 0xd2, 0x60, 0x47, 0x53, 0x26, 0x7d, 0xcd, 0x78, 0x6a, 0x64, 0xea, 0xf1, 0x9b,
|
||||
0x5f, 0xc3, 0x5b, 0x48, 0xae, 0x89, 0x49, 0xec, 0x1a, 0xfc, 0xaf, 0x91, 0xc3, 0x31, 0x4b, 0x86,
|
||||
0x04, 0xe2, 0x68, 0xdf, 0xd1, 0x40, 0xa8, 0xd0, 0xb1, 0x9c, 0x20, 0xcb, 0x34, 0xe2, 0x3a, 0xda,
|
||||
0x6b, 0xcb, 0xa6, 0x8d, 0xcb, 0x83, 0x33, 0xab, 0x41, 0xeb, 0x67, 0x70, 0x6f, 0x5d, 0xd6, 0x8e,
|
||||
0x5b, 0xb4, 0x05, 0xa3, 0xc1, 0xa3, 0x91, 0x1a, 0xb5, 0xec, 0x13, 0xf8, 0xa8, 0x1a, 0xf5, 0x26,
|
||||
0xa9, 0x19, 0xb5, 0x06, 0xb5, 0xea, 0x86, 0x09, 0x61, 0x88, 0x61, 0x43, 0x6b, 0xc3, 0xb0, 0x1b,
|
||||
0x67, 0x0d, 0xa3, 0x49, 0xad, 0x9a, 0xd1, 0x3a, 0x81, 0xa7, 0x3a, 0x42, 0x1e, 0x34, 0x09, 0x80,
|
||||
0x55, 0xf1, 0xc3, 0x3e, 0x6e, 0xd0, 0x86, 0x98, 0xca, 0x22, 0xb8, 0xce, 0x6b, 0xab, 0x65, 0x34,
|
||||
0x1b, 0xb4, 0x69, 0x34, 0x6b, 0x67, 0x56, 0xd3, 0xa8, 0xd2, 0x03, 0xc3, 0x3e, 0xb1, 0xf0, 0x91,
|
||||
0x5a, 0xa6, 0x61, 0xd6, 0x88, 0xd5, 0xa2, 0x96, 0x25, 0x3e, 0xd7, 0x86, 0x5a, 0xad, 0x4b, 0xab,
|
||||
0x7e, 0x06, 0xed, 0x07, 0x88, 0xa4, 0x5d, 0xbd, 0xb4, 0xcd, 0x1c, 0x9a, 0xb6, 0x89, 0x78, 0xe2,
|
||||
0xa7, 0x69, 0xd4, 0xaa, 0xc4, 0x3a, 0x30, 0xea, 0x35, 0xda, 0x42, 0x4c, 0x96, 0x0b, 0xfe, 0x53,
|
||||
0x23, 0xfb, 0x47, 0x87, 0x48, 0xd2, 0xa3, 0x27, 0x7a, 0x27, 0x17, 0x3d, 0x2a, 0xfa, 0xe1, 0x3d,
|
||||
0x30, 0x12, 0xf4, 0x17, 0x74, 0x8c, 0x3c, 0x9d, 0x17, 0x71, 0x0c, 0x84, 0x19, 0xfa, 0x5f, 0xa1,
|
||||
0x35, 0x14, 0x9e, 0x32, 0x56, 0x42, 0x50, 0xbf, 0xaf, 0xca, 0xec, 0xe2, 0x2a, 0x2b, 0xdf, 0xf7,
|
||||
0x11, 0xcd, 0x7b, 0xd8, 0xa3, 0x55, 0x2f, 0xb1, 0x60, 0x18, 0x6d, 0x7e, 0x9d, 0x7f, 0x2f, 0x43,
|
||||
0xff, 0x6e, 0x14, 0x2b, 0x32, 0x40, 0x97, 0xf7, 0xc2, 0x88, 0x89, 0x0c, 0x4b, 0xe8, 0x39, 0x6b,
|
||||
0x4f, 0xbd, 0x18, 0xec, 0x90, 0xfb, 0xd3, 0xe7, 0x1d, 0x86, 0xa0, 0x55, 0xf3, 0xbc, 0x97, 0xfb,
|
||||
0x81, 0x49, 0x58, 0x0f, 0xd3, 0x9e, 0x9f, 0x8c, 0x5b, 0x09, 0xe4, 0x49, 0x94, 0xa5, 0xc8, 0x21,
|
||||
0x52, 0x94, 0x44, 0x1c, 0x54, 0x2c, 0x1e, 0x86, 0x51, 0xd2, 0x9b, 0x24, 0x04, 0x8d, 0x9e, 0x46,
|
||||
0x86, 0x11, 0xef, 0x3b, 0x9a, 0x50, 0x6a, 0x08, 0x4f, 0x7d, 0x30, 0x80, 0x38, 0x7e, 0x3f, 0xec,
|
||||
0x25, 0x1c, 0xd8, 0x93, 0x80, 0x45, 0x1e, 0xc1, 0xca, 0x31, 0x6f, 0xd4, 0xa8, 0x76, 0x54, 0x02,
|
||||
0x25, 0xef, 0x45, 0xde, 0x38, 0x21, 0xc2, 0xd9, 0x6a, 0xb8, 0xea, 0xfe, 0x17, 0x36, 0x65, 0xb2,
|
||||
0x15, 0x00, 0xfa, 0x93, 0x40, 0xa4, 0xb5, 0x64, 0xf0, 0xca, 0x2d, 0x73, 0x7d, 0x1e, 0xf1, 0x64,
|
||||
0x12, 0x05, 0xc4, 0x35, 0x06, 0x3c, 0x79, 0xe1, 0x73, 0x4c, 0x8f, 0x7e, 0x9d, 0x89, 0xae, 0x45,
|
||||
0x06, 0xda, 0x7b, 0xb1, 0x02, 0xd9, 0x83, 0x35, 0x13, 0xae, 0x80, 0x11, 0x70, 0xca, 0x22, 0x30,
|
||||
0x05, 0x2e, 0x64, 0x0c, 0xd8, 0x82, 0x9b, 0x12, 0xab, 0xc1, 0xae, 0xf6, 0x55, 0x35, 0x11, 0x4b,
|
||||
0x6b, 0xcb, 0x8b, 0x0b, 0x0a, 0x22, 0x4c, 0x26, 0x20, 0xa8, 0x4a, 0x67, 0x9a, 0x6a, 0x2e, 0x29,
|
||||
0xfb, 0xb4, 0x62, 0x8a, 0x8b, 0x1d, 0x1c, 0x0e, 0x19, 0x5a, 0xc5, 0x23, 0x36, 0xbd, 0x1a, 0x42,
|
||||
0xa3, 0xfd, 0x2b, 0xad, 0x18, 0xc0, 0x75, 0x05, 0x4e, 0xf5, 0x47, 0xa4, 0x4e, 0xed, 0xc6, 0x86,
|
||||
0x45, 0xac, 0xda, 0xf0, 0xbf, 0x76, 0x24, 0x2d, 0x62, 0x49, 0x9a, 0xc4, 0x87, 0xa6, 0x59, 0x85,
|
||||
0x90, 0x59, 0x5a, 0xc3, 0x06, 0xb1, 0xed, 0x61, 0x6b, 0x5a, 0x3b, 0x6d, 0xfc, 0xf5, 0xda, 0x02,
|
||||
0x7b, 0x54, 0x1b, 0xd6, 0xa6, 0xad, 0x61, 0xa5, 0x06, 0x4f, 0x2d, 0x62, 0x99, 0xd9, 0x93, 0x6d,
|
||||
0x93, 0x06, 0xc2, 0x0d, 0x2b, 0xad, 0xbf, 0xb4, 0xd4, 0xae, 0x94, 0xc8, 0xb6, 0x32, 0x26, 0x52,
|
||||
0xd2, 0x42, 0x7a, 0x02, 0x8d, 0x70, 0xdb, 0xf6, 0x51, 0x49, 0xf5, 0x11, 0x61, 0xe9, 0x09, 0xa4,
|
||||
0x7b, 0x62, 0xec, 0x3f, 0x2e, 0xde, 0xbe, 0x21, 0xe5, 0xb1, 0x98, 0x01, 0xc8, 0x4a, 0x80, 0x7b,
|
||||
0xa2, 0x7d, 0xc4, 0x92, 0xc8, 0xbb, 0xd5, 0x61, 0x1a, 0x1b, 0xc6, 0x8f, 0xb1, 0x70, 0x8a, 0xb9,
|
||||
0x1a, 0x29, 0x79, 0x80, 0xf5, 0xb2, 0x04, 0xa5, 0xad, 0xfa, 0x07, 0xe1, 0xd7, 0x05, 0x60, 0x05,
|
||||
0x48, 0x0b, 0xc9, 0x60, 0xbb, 0x0f, 0x33, 0xbb, 0x8a, 0xbc, 0x9b, 0xec, 0x48, 0x22, 0x94, 0xc0,
|
||||
0xc4, 0x4d, 0x67, 0x29, 0xf4, 0xd8, 0x08, 0xe8, 0xb3, 0x2e, 0x20, 0x08, 0x4e, 0xce, 0xd1, 0x7c,
|
||||
0xee, 0x5e, 0x80, 0x64, 0x8d, 0xd3, 0x8a, 0x82, 0x76, 0x74, 0xc6, 0x61, 0x02, 0x6c, 0x6a, 0x83,
|
||||
0x28, 0x09, 0x48, 0xdc, 0x79, 0x82, 0x72, 0x04, 0x53, 0x2b, 0xc1, 0x59, 0x16, 0x6f, 0x04, 0x67,
|
||||
0xc5, 0x60, 0x82, 0x9b, 0xd9, 0x98, 0x8f, 0x94, 0xd4, 0x90, 0x7c, 0x7d, 0x06, 0x07, 0x85, 0x63,
|
||||
0x21, 0xdd, 0x53, 0xe6, 0x4f, 0x38, 0xf6, 0x22, 0x85, 0x80, 0x00, 0x02, 0x82, 0xc3, 0x4c, 0xe9,
|
||||
0x9d, 0x76, 0x64, 0x3f, 0x27, 0xaf, 0x45, 0x37, 0x20, 0x24, 0x47, 0x6d, 0x0c, 0x8f, 0x6c, 0x5f,
|
||||
0x3b, 0xba, 0xe0, 0xd1, 0x18, 0x88, 0x01, 0x26, 0x99, 0x82, 0xbf, 0x8c, 0xe2, 0x84, 0x40, 0xc4,
|
||||
0x21, 0xf3, 0x70, 0xe4, 0x10, 0xd6, 0x17, 0xc8, 0x63, 0x3f, 0xe9, 0x54, 0xb2, 0x69, 0x4a, 0xeb,
|
||||
0xf3, 0xf8, 0x76, 0xb4, 0x6d, 0x1e, 0x31, 0x3c, 0xcd, 0xeb, 0x49, 0xe5, 0xf1, 0x20, 0xe9, 0x2c,
|
||||
0xd1, 0x41, 0xad, 0x13, 0xf8, 0x66, 0xb4, 0xda, 0x07, 0x6e, 0x08, 0x96, 0xdc, 0x83, 0x23, 0x25,
|
||||
0xc1, 0x12, 0xf8, 0x00, 0x6a, 0x2c, 0x49, 0xf5, 0x76, 0x92, 0x80, 0xc7, 0x22, 0xb2, 0xb9, 0xbd,
|
||||
0x23, 0x4f, 0x4a, 0x79, 0xa6, 0xac, 0xcd, 0x48, 0x76, 0xe2, 0xc8, 0x0d, 0xb0, 0x12, 0xb8, 0x57,
|
||||
0xc4, 0x90, 0x4c, 0xd6, 0xb7, 0xf2, 0x03, 0x02, 0x15, 0x60, 0xc8, 0xc9, 0x87, 0xf3, 0xb3, 0x3c,
|
||||
0x8d, 0x56, 0x61, 0x86, 0x4c, 0x3b, 0x3a, 0x0d, 0x47, 0x9c, 0x1c, 0xc7, 0xb1, 0x07, 0x3e, 0x34,
|
||||
0x48, 0xc8, 0xc7, 0xe3, 0xd7, 0xb9, 0x01, 0x77, 0xd0, 0xb4, 0x74, 0x0f, 0x31, 0x17, 0x1e, 0xe1,
|
||||
0xe5, 0x1a, 0x61, 0x4b, 0x22, 0x8e, 0x22, 0xbd, 0xd0, 0xe5, 0xf7, 0xa4, 0x6e, 0x4a, 0x5c, 0xa1,
|
||||
0xbf, 0x45, 0x73, 0xef, 0x46, 0xe2, 0x21, 0xbf, 0xdd, 0x42, 0xe1, 0xd3, 0x17, 0x7f, 0x92, 0xf2,
|
||||
0xc3, 0x7e, 0x0d, 0xff, 0xe9, 0x5b, 0xa9, 0x0c, 0x0e, 0x4d, 0x3b, 0x7a, 0xfe, 0xe2, 0x84, 0x94,
|
||||
0xed, 0x5a, 0x8d, 0xaa, 0x3f, 0xbd, 0xb4, 0x33, 0x05, 0xef, 0x23, 0x95, 0x10, 0xf2, 0x44, 0x1c,
|
||||
0x18, 0x15, 0x0c, 0x96, 0xfb, 0x39, 0xce, 0xda, 0x7e, 0x48, 0x2c, 0x0b, 0xa6, 0xdc, 0x91, 0x6e,
|
||||
0xb3, 0x2e, 0x24, 0x16, 0xdb, 0x48, 0x27, 0x3a, 0x91, 0x7a, 0x26, 0xfe, 0x83, 0xa0, 0x92, 0x12,
|
||||
0xab, 0x49, 0xc9, 0x76, 0x6a, 0x96, 0x52, 0x23, 0x82, 0x45, 0x17, 0xed, 0xe8, 0x1c, 0x2f, 0xa4,
|
||||
0x7c, 0xf7, 0x38, 0x35, 0x0c, 0x37, 0x80, 0xf4, 0x2a, 0x5d, 0x88, 0x9b, 0x42, 0xbe, 0xfd, 0x3c,
|
||||
0x49, 0xee, 0x0a, 0xfb, 0x13, 0x00, 0xdd, 0x64, 0x79, 0x48, 0x3b, 0xfa, 0x35, 0x6b, 0xc9, 0xb8,
|
||||
0x50, 0xca, 0xb1, 0xe1, 0x7b, 0x73, 0x77, 0x76, 0x70, 0xdb, 0xa2, 0x7a, 0x50, 0x52, 0x11, 0x8d,
|
||||
0x24, 0x91, 0xe0, 0xde, 0x06, 0x22, 0x64, 0xe4, 0x05, 0x8e, 0x66, 0xc1, 0x95, 0x81, 0xbf, 0xb6,
|
||||
0xeb, 0x75, 0x2d, 0xa5, 0x90, 0x65, 0xb7, 0x84, 0xd2, 0x8c, 0x59, 0x20, 0x55, 0x66, 0x39, 0xf6,
|
||||
0x12, 0x21, 0xb4, 0x23, 0x80, 0x00, 0x1a, 0x41, 0xff, 0xcf, 0xd2, 0xf5, 0x33, 0x0f, 0x32, 0xba,
|
||||
0x94, 0x42, 0xa5, 0xd7, 0xec, 0x96, 0x04, 0x21, 0x09, 0xfb, 0x44, 0x74, 0xc6, 0xfb, 0x68, 0xbc,
|
||||
0x8a, 0x64, 0xb6, 0xf4, 0x53, 0xa8, 0x45, 0x4a, 0x1b, 0xd4, 0xda, 0x40, 0x6a, 0x95, 0x5a, 0x75,
|
||||
0xcb, 0xce, 0xa8, 0x65, 0xd7, 0x1b, 0xab, 0xd4, 0x5a, 0x8e, 0x55, 0xd4, 0x02, 0x88, 0x2d, 0xd4,
|
||||
0x4a, 0xf5, 0x67, 0xc8, 0x2a, 0x98, 0xcb, 0x6b, 0xf7, 0xa7, 0xde, 0x90, 0xbd, 0x02, 0x45, 0x3d,
|
||||
0x3d, 0x26, 0xcf, 0xf9, 0xd4, 0xeb, 0x71, 0xf2, 0xea, 0x79, 0x01, 0x9d, 0x4a, 0xc5, 0x56, 0x51,
|
||||
0x6e, 0x5e, 0x75, 0xad, 0x14, 0x25, 0xb5, 0x5c, 0x44, 0x2c, 0x09, 0x22, 0xd6, 0xc9, 0x54, 0x4f,
|
||||
0x84, 0x4c, 0x9f, 0x20, 0x64, 0xfa, 0xd4, 0x93, 0x47, 0xdc, 0x3e, 0x8f, 0x3e, 0x99, 0xa6, 0xa5,
|
||||
0xfd, 0x2d, 0x3b, 0xfc, 0xb0, 0xba, 0xc5, 0x0f, 0x81, 0xf7, 0xef, 0xc9, 0xea, 0x4e, 0x4b, 0x77,
|
||||
0xd8, 0xff, 0x5d, 0x77, 0x5a, 0x92, 0x5b, 0xc5, 0x05, 0xc9, 0x1d, 0x5b, 0x65, 0xbb, 0xec, 0xb5,
|
||||
0x74, 0xcf, 0xf0, 0x6e, 0xc8, 0xde, 0xb0, 0x11, 0xcf, 0x6f, 0x16, 0x9f, 0xff, 0xb6, 0x7d, 0x8a,
|
||||
0xc5, 0xd2, 0x8d, 0x2e, 0x03, 0xe9, 0xff, 0xf1, 0x92, 0xde, 0x90, 0x07, 0xda, 0xcf, 0x50, 0x6e,
|
||||
0x08, 0x2c, 0x3e, 0x60, 0x6c, 0x91, 0x8a, 0xe7, 0xbb, 0xfd, 0x61, 0x08, 0x11, 0x5a, 0x90, 0xdf,
|
||||
0x56, 0x89, 0xfc, 0xcc, 0x6d, 0xa5, 0x4b, 0xca, 0x7d, 0xfd, 0x04, 0x57, 0x9a, 0x40, 0x96, 0xc3,
|
||||
0x21, 0x56, 0x10, 0xa7, 0x61, 0xda, 0xd1, 0x7b, 0xf1, 0x48, 0xd4, 0xe9, 0x18, 0x28, 0xc7, 0xee,
|
||||
0xce, 0x74, 0x75, 0x1f, 0xb2, 0xba, 0x9d, 0xee, 0x20, 0x50, 0x76, 0xc6, 0x13, 0xde, 0x71, 0x90,
|
||||
0x93, 0x40, 0x53, 0x19, 0x1f, 0x53, 0x19, 0x9f, 0x46, 0x75, 0xdd, 0x33, 0xaf, 0x62, 0xb8, 0xbe,
|
||||
0x78, 0xde, 0x31, 0x2f, 0x1d, 0x9b, 0xc8, 0x1f, 0x71, 0xf0, 0x72, 0x24, 0x9e, 0xf4, 0x65, 0xa3,
|
||||
0x73, 0xa7, 0x7f, 0x90, 0xc2, 0xa9, 0x54, 0x2a, 0x4f, 0xca, 0x7d, 0x91, 0xea, 0x2c, 0x73, 0xa3,
|
||||
0x74, 0x5c, 0x76, 0xa0, 0x7e, 0x82, 0x0d, 0x6a, 0x43, 0x59, 0xa3, 0xb6, 0x96, 0x53, 0xfe, 0x40,
|
||||
0xd2, 0xb4, 0x9b, 0x10, 0xe2, 0xfe, 0xb2, 0xa5, 0xc5, 0x26, 0x76, 0x49, 0x69, 0x8b, 0x6b, 0x7a,
|
||||
0x58, 0xb3, 0xf4, 0x7a, 0x5f, 0x61, 0xb2, 0x1b, 0x54, 0x8d, 0x0b, 0x9c, 0xb2, 0xac, 0x63, 0xae,
|
||||
0x24, 0xaa, 0xc6, 0x60, 0x24, 0x64, 0xd9, 0x38, 0xcd, 0x75, 0x8b, 0xaa, 0x7f, 0x25, 0x51, 0xfe,
|
||||
0x6b, 0x92, 0xe6, 0x69, 0x93, 0xd5, 0x49, 0x1d, 0x6b, 0x69, 0xc4, 0xac, 0xe0, 0x5d, 0xf6, 0x84,
|
||||
0x77, 0x43, 0xcb, 0x64, 0xb9, 0x86, 0x4a, 0xae, 0xbb, 0x02, 0x4f, 0xaf, 0x9b, 0xc4, 0xaa, 0xb3,
|
||||
0x2a, 0xa9, 0x8a, 0x26, 0xab, 0x52, 0xad, 0xe0, 0xbd, 0x7a, 0x22, 0x6b, 0x4f, 0x24, 0xf7, 0x84,
|
||||
0x3d, 0x98, 0x3b, 0x97, 0x64, 0xf2, 0x4c, 0x1e, 0x07, 0xdd, 0x78, 0xdc, 0x11, 0x3b, 0x51, 0x49,
|
||||
0xf1, 0x2a, 0x8f, 0x77, 0xd0, 0x91, 0x4c, 0x82, 0x54, 0x19, 0x2f, 0x4b, 0x87, 0xf3, 0x15, 0xe9,
|
||||
0x35, 0x7b, 0x80, 0xa0, 0x7f, 0x42, 0x46, 0x42, 0xda, 0x24, 0xd3, 0x1a, 0x89, 0x4a, 0xea, 0x8a,
|
||||
0x53, 0x31, 0x5a, 0x2d, 0xfd, 0x15, 0x6a, 0x89, 0x98, 0x2b, 0x73, 0xcc, 0x69, 0xf0, 0xd2, 0xc0,
|
||||
0xc2, 0x8e, 0x9c, 0x33, 0xff, 0xb9, 0x81, 0xc6, 0x47, 0x30, 0xb3, 0x3f, 0x0b, 0x8d, 0x8f, 0x85,
|
||||
0x68, 0xa4, 0x24, 0x2d, 0x15, 0xeb, 0xcd, 0xfe, 0x58, 0x15, 0x17, 0x72, 0x88, 0xe5, 0xde, 0xbf,
|
||||
0xc8, 0x0b, 0x71, 0xf6, 0x52, 0x09, 0xee, 0xed, 0x39, 0x3c, 0x28, 0x9e, 0x0d, 0x79, 0x04, 0x8c,
|
||||
0xeb, 0x46, 0x47, 0x90, 0x17, 0xe1, 0x85, 0x9c, 0xa0, 0x9c, 0x62, 0xda, 0xab, 0xac, 0x03, 0x43,
|
||||
0x59, 0xcc, 0xf1, 0x36, 0x33, 0x54, 0x6a, 0xed, 0xd4, 0x26, 0xc9, 0x6d, 0x21, 0xac, 0xdc, 0x54,
|
||||
0x1e, 0x8f, 0x6d, 0x6c, 0x85, 0x39, 0x56, 0xaa, 0x50, 0x79, 0x85, 0x5e, 0x7f, 0x6b, 0x45, 0x58,
|
||||
0xf1, 0xd1, 0x40, 0xcc, 0x3d, 0x8e, 0x38, 0x2a, 0x99, 0xb6, 0x51, 0x8c, 0xca, 0x9d, 0x22, 0xab,
|
||||
0x37, 0xc1, 0x60, 0xed, 0xa8, 0xb7, 0x73, 0x3d, 0x0f, 0x09, 0x2d, 0xf7, 0x99, 0xd2, 0x2d, 0x62,
|
||||
0x37, 0x95, 0xb5, 0x13, 0x8f, 0xad, 0xdb, 0x49, 0xd1, 0x13, 0xf0, 0x88, 0xdc, 0xee, 0x2b, 0x13,
|
||||
0xe6, 0x27, 0x8e, 0x76, 0xce, 0x6e, 0x5e, 0x09, 0xae, 0xc8, 0x19, 0x96, 0x05, 0x28, 0xa0, 0x13,
|
||||
0xd0, 0xaa, 0xb4, 0x44, 0x6b, 0x57, 0x94, 0x56, 0xe1, 0xbd, 0xa0, 0x1f, 0x16, 0x13, 0x6d, 0x69,
|
||||
0xa0, 0xd3, 0x73, 0x27, 0x31, 0x0c, 0xa3, 0x66, 0x51, 0x15, 0x80, 0x06, 0x37, 0x0c, 0xfc, 0x19,
|
||||
0x10, 0x44, 0xdd, 0x69, 0x68, 0x08, 0x52, 0xe0, 0x25, 0xa6, 0xe9, 0x82, 0xeb, 0x87, 0x3d, 0x5b,
|
||||
0x31, 0x94, 0x80, 0x69, 0xdc, 0x3b, 0x9e, 0xa9, 0x25, 0x65, 0x73, 0xe6, 0x4b, 0x72, 0xe7, 0x3e,
|
||||
0x88, 0xaa, 0x7c, 0xcc, 0x2d, 0x37, 0x60, 0x63, 0x2b, 0x03, 0x86, 0x07, 0x81, 0x9d, 0xc4, 0x48,
|
||||
0x2d, 0x20, 0xbd, 0x62, 0xe0, 0xde, 0x6f, 0xfe, 0xe5, 0xae, 0x90, 0xfa, 0xc3, 0xea, 0x51, 0xb6,
|
||||
0x22, 0x18, 0xb5, 0x18, 0xd8, 0xa9, 0x1d, 0x5d, 0xca, 0x1b, 0x62, 0x19, 0xa6, 0xd1, 0x94, 0x03,
|
||||
0xa4, 0x21, 0xa8, 0xa4, 0x66, 0x83, 0x91, 0x92, 0xac, 0x2a, 0xe3, 0xfb, 0x95, 0x71, 0x7b, 0x7f,
|
||||
0x7f, 0xe0, 0x25, 0xc3, 0x49, 0xd7, 0xe8, 0x85, 0xa3, 0xfd, 0x1b, 0x1e, 0x7d, 0x05, 0x59, 0x80,
|
||||
0x3b, 0xac, 0xb1, 0x54, 0x44, 0x08, 0x05, 0x11, 0x54, 0x56, 0x89, 0xdc, 0xef, 0xfa, 0x61, 0x77,
|
||||
0x1f, 0xb3, 0xe3, 0xfd, 0xf3, 0x17, 0xc7, 0xcf, 0x5f, 0xbf, 0x30, 0x46, 0x98, 0x07, 0x4b, 0x7f,
|
||||
0xed, 0x68, 0x9f, 0xba, 0x3e, 0x0b, 0xbe, 0x82, 0x1d, 0xe2, 0xfe, 0x78, 0xff, 0xb8, 0x0b, 0xde,
|
||||
0xef, 0x70, 0x9f, 0xc1, 0x06, 0x00, 0xd3, 0xa5, 0xca, 0xae, 0x71, 0x46, 0x9c, 0x8b, 0xc9, 0x2a,
|
||||
0x70, 0xb1, 0x2c, 0x64, 0x44, 0xc9, 0x41, 0x66, 0xf2, 0xd1, 0x63, 0xc1, 0x94, 0xc5, 0x52, 0x0d,
|
||||
0x11, 0xd9, 0x13, 0xf1, 0x2c, 0xe8, 0x2d, 0xbb, 0x8e, 0xee, 0xae, 0x89, 0x87, 0x51, 0x19, 0x6b,
|
||||
0xd8, 0x03, 0x88, 0xb3, 0x1c, 0xac, 0x8b, 0x67, 0x11, 0x97, 0x4e, 0xe3, 0xbf, 0xfe, 0x94, 0x4d,
|
||||
0xd2, 0x36, 0x63, 0xc3, 0xc7, 0x65, 0xc3, 0x47, 0xd1, 0x00, 0x9e, 0x62, 0xd9, 0x84, 0x6e, 0x43,
|
||||
0xa7, 0xe3, 0xe8, 0x46, 0x36, 0xa5, 0xa6, 0x01, 0xe0, 0x5e, 0x3d, 0x57, 0x50, 0x22, 0x16, 0xd2,
|
||||
0xe9, 0x3f, 0xce, 0x54, 0x43, 0x2a, 0xd5, 0x3a, 0x4d, 0x2e, 0x06, 0xb2, 0x69, 0x35, 0xfe, 0xd1,
|
||||
0x69, 0x37, 0x1a, 0x0c, 0x65, 0xcf, 0x46, 0xd6, 0x0b, 0x33, 0xf3, 0x0c, 0x83, 0xb5, 0xd0, 0x47,
|
||||
0xa7, 0xbd, 0x2f, 0x5d, 0xb5, 0xa5, 0x0d, 0x59, 0xd6, 0x69, 0x3f, 0x1a, 0xc9, 0xce, 0xb5, 0xfa,
|
||||
0x1c, 0x0c, 0x3b, 0x7b, 0x93, 0x0e, 0x5b, 0x4b, 0x1b, 0x75, 0x8a, 0x89, 0x13, 0x97, 0xbd, 0x22,
|
||||
0x87, 0xc2, 0x96, 0x0f, 0x59, 0xc3, 0x07, 0xd5, 0xf2, 0x26, 0x6b, 0x11, 0x31, 0xb9, 0x4e, 0xd9,
|
||||
0x85, 0x6c, 0x28, 0x28, 0xba, 0xc0, 0x7a, 0x2f, 0x2f, 0x72, 0xeb, 0xbd, 0x5c, 0x47, 0xc7, 0xbf,
|
||||
0x50, 0xdd, 0x1b, 0xd5, 0x5d, 0x9d, 0x7a, 0xe8, 0xa7, 0x44, 0x67, 0xce, 0xa8, 0x60, 0x73, 0x6f,
|
||||
0xa5, 0x79, 0xa9, 0xf9, 0x40, 0xcd, 0xb4, 0x6b, 0xc3, 0x2a, 0xe0, 0xb8, 0xdc, 0x28, 0x24, 0x6e,
|
||||
0x6f, 0xc9, 0xde, 0x34, 0xf0, 0xd2, 0xe9, 0x8d, 0x73, 0xe3, 0x05, 0x6e, 0x78, 0x43, 0xa5, 0x8c,
|
||||
0x29, 0x5e, 0xe7, 0xe4, 0x4f, 0xb0, 0xec, 0x72, 0x9d, 0x65, 0x32, 0x7d, 0x46, 0xf2, 0x5e, 0xae,
|
||||
0x93, 0x37, 0xed, 0x42, 0x9d, 0x3c, 0x8e, 0x22, 0x36, 0x73, 0xae, 0xae, 0x29, 0x3a, 0x2d, 0x64,
|
||||
0x9a, 0xa3, 0x69, 0x14, 0x13, 0x30, 0xf4, 0xb3, 0xe7, 0xe1, 0x4d, 0xec, 0xb8, 0x06, 0x24, 0x8c,
|
||||
0xd1, 0x2c, 0x25, 0xc3, 0xb1, 0xef, 0x97, 0x35, 0x23, 0xcd, 0xd2, 0x60, 0x13, 0x8e, 0xd9, 0xf1,
|
||||
0x0e, 0xf3, 0x23, 0x0c, 0x9f, 0x07, 0x83, 0x64, 0xd8, 0xf1, 0xf6, 0xf6, 0xf4, 0x7c, 0xfb, 0x95,
|
||||
0x77, 0x6d, 0x08, 0xf5, 0x3a, 0xf3, 0xe2, 0xc4, 0x00, 0xde, 0x00, 0xc7, 0xc4, 0x1c, 0x1d, 0xd4,
|
||||
0x08, 0xd6, 0xeb, 0xa5, 0xf1, 0x9e, 0xa3, 0x3d, 0xe4, 0x9c, 0x6b, 0x54, 0x36, 0x61, 0xba, 0x92,
|
||||
0x36, 0x37, 0x9b, 0x4d, 0x0d, 0x04, 0x3e, 0x86, 0x67, 0x78, 0xea, 0xf5, 0x7a, 0x1a, 0x1d, 0x44,
|
||||
0x9c, 0x07, 0x69, 0xbf, 0x59, 0x6f, 0x74, 0x4d, 0xa6, 0xd1, 0x88, 0xbb, 0x69, 0x13, 0x34, 0xd4,
|
||||
0x4d, 0x80, 0x93, 0x51, 0x74, 0x38, 0x18, 0xf8, 0xfc, 0x6d, 0xbf, 0x2f, 0xe3, 0x49, 0x0a, 0xf1,
|
||||
0xe4, 0x71, 0x9d, 0xd6, 0xd3, 0xb3, 0x59, 0x3c, 0xcb, 0x5d, 0x3e, 0x36, 0xa9, 0xd5, 0x3c, 0xb5,
|
||||
0x56, 0x00, 0xd6, 0x20, 0x70, 0x86, 0xd7, 0x00, 0x56, 0x3f, 0xae, 0xd2, 0xaa, 0x3a, 0x01, 0xc6,
|
||||
0x73, 0xe8, 0xdc, 0x63, 0x93, 0x1e, 0xe4, 0x9e, 0x2c, 0x73, 0xbd, 0xd7, 0xaa, 0xff, 0x73, 0x15,
|
||||
0xb7, 0xe0, 0x27, 0xa2, 0x66, 0xad, 0xe1, 0x66, 0xad, 0x21, 0x67, 0xad, 0x62, 0x67, 0x9b, 0x1b,
|
||||
0xdd, 0x12, 0xbd, 0xd4, 0x54, 0xe4, 0x54, 0xfe, 0xe2, 0xf2, 0x37, 0x8c, 0xd6, 0x35, 0x3d, 0x7f,
|
||||
0x06, 0xb7, 0xf3, 0x81, 0x20, 0x4f, 0x84, 0xb5, 0x3f, 0xff, 0xed, 0x57, 0x21, 0x8b, 0x31, 0x1e,
|
||||
0xfa, 0x15, 0x4b, 0xe3, 0xe7, 0xb9, 0x06, 0xf6, 0xa3, 0x9d, 0x44, 0x13, 0x4e, 0x51, 0xba, 0xb5,
|
||||
0xf6, 0xa3, 0x39, 0x5a, 0x28, 0x43, 0x84, 0x8a, 0x0b, 0x8a, 0x26, 0x4e, 0x6b, 0xcf, 0x35, 0xcf,
|
||||
0xc5, 0x1e, 0x30, 0x6a, 0x59, 0x07, 0x80, 0x5e, 0x7d, 0xee, 0xf8, 0x90, 0x6d, 0x26, 0x20, 0xa2,
|
||||
0x09, 0xe6, 0x8c, 0xfc, 0x56, 0x73, 0x1c, 0x84, 0x11, 0xa6, 0xdf, 0x50, 0x96, 0xff, 0x59, 0x36,
|
||||
0xaa, 0x0d, 0x86, 0x53, 0xde, 0x75, 0x40, 0x4f, 0x21, 0xd3, 0xf6, 0x1d, 0xf0, 0x00, 0x31, 0x04,
|
||||
0xb1, 0x49, 0x19, 0xcc, 0x94, 0xec, 0xd2, 0xc5, 0x9c, 0x81, 0xf3, 0xc0, 0xa2, 0xcc, 0xa9, 0x58,
|
||||
0x1d, 0xe6, 0x80, 0x6d, 0x33, 0xd2, 0x9a, 0xec, 0xab, 0xc0, 0xe5, 0xb7, 0x6a, 0xb4, 0x27, 0x7a,
|
||||
0x64, 0x5d, 0x34, 0xbe, 0x62, 0xd7, 0x6a, 0x6a, 0xe6, 0x80, 0x8d, 0x29, 0x1c, 0x10, 0x8a, 0x9e,
|
||||
0x82, 0x01, 0x60, 0xb3, 0xd6, 0x06, 0x20, 0x0e, 0xb1, 0xf3, 0xc0, 0xec, 0x88, 0xc2, 0xb8, 0x23,
|
||||
0x20, 0xd6, 0x07, 0x3e, 0x7e, 0x5c, 0x06, 0x10, 0x0b, 0xec, 0xa1, 0xc3, 0x8a, 0xc6, 0x47, 0x62,
|
||||
0xbc, 0x2a, 0xe9, 0x3a, 0x08, 0xb3, 0x3e, 0xc3, 0x33, 0x00, 0xb1, 0xda, 0x69, 0x0d, 0xba, 0x10,
|
||||
0x04, 0x16, 0x01, 0x5a, 0x98, 0x92, 0x2a, 0x13, 0xb4, 0x1e, 0x2e, 0x7e, 0xf4, 0x9c, 0x27, 0xda,
|
||||
0x13, 0x3a, 0xc4, 0xcf, 0x4e, 0xfc, 0xed, 0x5b, 0x19, 0xc2, 0xc1, 0x2b, 0x30, 0x2c, 0x8e, 0x76,
|
||||
0xad, 0x49, 0xd0, 0x31, 0x12, 0x10, 0x02, 0x03, 0x4d, 0x68, 0xff, 0xc0, 0xe9, 0xbd, 0x00, 0x13,
|
||||
0x95, 0x1a, 0x34, 0x30, 0x8c, 0x78, 0x4a, 0x8c, 0x5f, 0x01, 0x01, 0x29, 0x2a, 0x6b, 0xb6, 0xab,
|
||||
0xd1, 0xf9, 0x0d, 0x24, 0x86, 0xe7, 0x10, 0x82, 0xbd, 0x8c, 0x38, 0x58, 0xa4, 0x20, 0xf1, 0x67,
|
||||
0xed, 0x07, 0xe6, 0x42, 0xa7, 0x53, 0x27, 0xe0, 0x37, 0x44, 0x44, 0x8f, 0x9d, 0xa9, 0x81, 0x91,
|
||||
0x27, 0xa7, 0x53, 0x03, 0x02, 0xb5, 0x90, 0xb9, 0x4e, 0x2a, 0x73, 0x65, 0x7d, 0x8e, 0xab, 0x72,
|
||||
0x47, 0x18, 0x59, 0xa3, 0x37, 0xf4, 0x7c, 0xf0, 0x0d, 0xc1, 0x95, 0x79, 0xbd, 0x72, 0x0f, 0x8b,
|
||||
0x1e, 0x27, 0x49, 0xe4, 0x81, 0xb5, 0xe6, 0x65, 0x0c, 0xe4, 0xd1, 0x31, 0x33, 0x07, 0x5c, 0xb3,
|
||||
0xdc, 0x2d, 0x9d, 0xc1, 0xfd, 0x47, 0xc5, 0x97, 0x32, 0x7f, 0xe0, 0xe4, 0xcc, 0xd6, 0xb7, 0x6f,
|
||||
0xec, 0xd0, 0xfa, 0xf6, 0x6d, 0x76, 0x68, 0xe9, 0x40, 0x14, 0xe6, 0x4c, 0x0d, 0x11, 0xd4, 0xc3,
|
||||
0x90, 0xa9, 0x21, 0xb3, 0x64, 0x5a, 0x56, 0x6d, 0x47, 0x75, 0xcb, 0xfe, 0xf6, 0x2d, 0x6d, 0xc6,
|
||||
0x27, 0x39, 0xc4, 0x6a, 0x00, 0xb4, 0xd5, 0xd0, 0x75, 0x3a, 0x90, 0x80, 0x0e, 0x83, 0x3b, 0x09,
|
||||
0xe5, 0xcc, 0x90, 0x5c, 0x10, 0x0f, 0xff, 0x21, 0x52, 0x05, 0xa2, 0xed, 0xb1, 0x3d, 0x8d, 0x92,
|
||||
0x53, 0x99, 0x7f, 0xc3, 0xe3, 0x6c, 0x4f, 0x23, 0xe5, 0x11, 0xfb, 0xca, 0x49, 0x3c, 0x81, 0xcc,
|
||||
0x26, 0x19, 0x7a, 0x31, 0x1e, 0xc6, 0xf6, 0x86, 0x3c, 0x26, 0xb3, 0x70, 0x12, 0x11, 0xf0, 0x68,
|
||||
0xea, 0x74, 0x56, 0x1e, 0x7a, 0xea, 0x18, 0x59, 0x6b, 0x74, 0x64, 0xb8, 0x91, 0x8a, 0xbe, 0xcb,
|
||||
0x53, 0xf1, 0x7e, 0x28, 0xa3, 0x33, 0x69, 0x94, 0x2f, 0x9c, 0x11, 0x92, 0x44, 0xf4, 0x3d, 0x87,
|
||||
0x68, 0xbe, 0x9c, 0xf6, 0x1a, 0x18, 0xdb, 0xd3, 0x47, 0xa0, 0xaa, 0x82, 0x99, 0x37, 0x8e, 0xd5,
|
||||
0x11, 0xe7, 0x89, 0x8e, 0x13, 0xc2, 0x46, 0x6e, 0x1c, 0x90, 0x87, 0x34, 0xd4, 0x79, 0x05, 0xda,
|
||||
0xf7, 0xea, 0xf0, 0x22, 0xf5, 0x0a, 0xaf, 0xf6, 0x9c, 0x9a, 0x3e, 0xc7, 0x8e, 0xae, 0x73, 0x71,
|
||||
0xf5, 0xea, 0x9a, 0xde, 0xe2, 0x65, 0xcf, 0xba, 0xa6, 0xef, 0xc5, 0x8d, 0x7d, 0x4d, 0xdf, 0x88,
|
||||
0x9b, 0xaa, 0x9c, 0x9a, 0x3b, 0xaf, 0xf6, 0x6b, 0x34, 0x71, 0x5e, 0x83, 0xb5, 0x31, 0xfa, 0x7e,
|
||||
0x08, 0xb3, 0xf2, 0x7d, 0x06, 0x7e, 0xda, 0xe1, 0x1d, 0xaf, 0x5f, 0x4e, 0x0f, 0x53, 0x61, 0x61,
|
||||
0xbd, 0xc3, 0xfd, 0x18, 0x12, 0x88, 0x7e, 0xb9, 0x9c, 0xec, 0xdd, 0xe8, 0xbf, 0xd8, 0x0e, 0xa2,
|
||||
0x81, 0x6d, 0x73, 0xdf, 0x49, 0x9e, 0xb2, 0xbd, 0x32, 0xab, 0x58, 0x95, 0xb2, 0x5f, 0x81, 0x7b,
|
||||
0x5d, 0x5f, 0x3c, 0x32, 0xc6, 0x93, 0x78, 0x58, 0xbe, 0xea, 0xd2, 0x5b, 0xfa, 0x9e, 0xbe, 0xa1,
|
||||
0x3e, 0xe5, 0x34, 0xb9, 0xc6, 0xf6, 0x38, 0x8c, 0x92, 0x72, 0x19, 0x9e, 0x74, 0xe7, 0x88, 0x5f,
|
||||
0xd5, 0xaf, 0x2b, 0x09, 0x7c, 0x48, 0xa9, 0x7d, 0xeb, 0x5c, 0x19, 0x86, 0xf1, 0xe8, 0xba, 0xf3,
|
||||
0x76, 0x0d, 0xaa, 0x86, 0x50, 0x35, 0x05, 0x75, 0x8e, 0x1a, 0xf0, 0x05, 0x8c, 0x03, 0x7d, 0xee,
|
||||
0xbc, 0x55, 0x1b, 0xa7, 0x9f, 0x1c, 0x93, 0x1e, 0x23, 0xc1, 0x90, 0x30, 0x72, 0x67, 0x66, 0x87,
|
||||
0x1f, 0x3e, 0xef, 0x70, 0xf0, 0x93, 0x73, 0x69, 0xa7, 0xde, 0x5e, 0xf1, 0x6b, 0x10, 0xb7, 0x04,
|
||||
0x44, 0x11, 0x1c, 0x6b, 0x72, 0x05, 0x54, 0x09, 0xe1, 0x02, 0x34, 0x99, 0xc0, 0xa5, 0x7a, 0x2d,
|
||||
0x75, 0xab, 0x8f, 0x66, 0x07, 0xb6, 0x19, 0xe9, 0xf0, 0xf1, 0xe5, 0xd0, 0x04, 0x8a, 0x7f, 0x71,
|
||||
0xb8, 0x4e, 0x61, 0xb2, 0x8a, 0x95, 0x9b, 0x0a, 0x88, 0xda, 0xc1, 0xa9, 0x40, 0x6f, 0x1f, 0x3f,
|
||||
0xc6, 0xc9, 0x1c, 0xc7, 0xc3, 0x1b, 0x1b, 0x6e, 0x42, 0xd0, 0xc9, 0xbe, 0x03, 0x20, 0x30, 0xe5,
|
||||
0x17, 0xc7, 0x01, 0x35, 0x0e, 0x9e, 0x69, 0x40, 0xc5, 0xf3, 0x67, 0x1c, 0xa4, 0x4a, 0x6b, 0x6b,
|
||||
0x5a, 0xfb, 0x0b, 0xde, 0xec, 0xf5, 0xf1, 0x53, 0x5f, 0x08, 0xd2, 0x66, 0x03, 0xf6, 0x2c, 0xc7,
|
||||
0xe9, 0x7f, 0x7f, 0x88, 0x20, 0xbc, 0xe8, 0x06, 0xf4, 0xce, 0x11, 0x3d, 0xc0, 0x11, 0x50, 0x17,
|
||||
0x5c, 0x9b, 0x1c, 0xda, 0xf5, 0x3a, 0xb4, 0x8f, 0xd1, 0x72, 0xd0, 0xfe, 0xd1, 0x12, 0x6d, 0x26,
|
||||
0x66, 0xf0, 0xc4, 0x67, 0x88, 0xa0, 0xb1, 0x3e, 0x17, 0xc6, 0xf1, 0x8a, 0x03, 0x87, 0x82, 0x6b,
|
||||
0xe7, 0x8a, 0x51, 0x8f, 0x86, 0xd7, 0x68, 0xd0, 0xb5, 0x3d, 0xd5, 0x68, 0x8c, 0xd8, 0xb8, 0xcc,
|
||||
0x81, 0x0d, 0x46, 0x12, 0x5e, 0x80, 0x38, 0x04, 0x83, 0x32, 0x28, 0x91, 0x31, 0x66, 0xee, 0x05,
|
||||
0xbe, 0xae, 0x54, 0xb6, 0xa9, 0x66, 0x6a, 0xba, 0x6e, 0x7c, 0x09, 0xbd, 0xa0, 0xac, 0xc1, 0x6e,
|
||||
0xce, 0xf7, 0x1c, 0x77, 0xaf, 0xb7, 0x97, 0xec, 0x0d, 0x97, 0x9e, 0xe6, 0x7c, 0x2f, 0x6d, 0xfa,
|
||||
0xb4, 0xe7, 0x58, 0xf4, 0xd3, 0x2f, 0x3e, 0xc8, 0xcf, 0xb7, 0x6f, 0xdc, 0x71, 0x80, 0xaa, 0xcf,
|
||||
0xca, 0xc7, 0x52, 0x5c, 0xce, 0x75, 0x8a, 0xdc, 0xd5, 0xdb, 0x30, 0x05, 0xe0, 0x28, 0xb8, 0xbc,
|
||||
0x58, 0x60, 0xd3, 0x1a, 0x5f, 0x8f, 0x53, 0x81, 0xcf, 0xd8, 0xeb, 0xdf, 0xd7, 0x99, 0x29, 0x27,
|
||||
0xf6, 0x68, 0x7e, 0x0c, 0x62, 0xb1, 0xb8, 0x5e, 0x2c, 0x3e, 0x77, 0x32, 0x27, 0x29, 0xb1, 0xf1,
|
||||
0x53, 0x67, 0xf4, 0x19, 0xd3, 0x08, 0x52, 0xf9, 0x93, 0xbc, 0x7b, 0x7b, 0xf1, 0x9e, 0x88, 0x6c,
|
||||
0x0b, 0x92, 0xad, 0x47, 0x73, 0xcc, 0x33, 0xd4, 0xec, 0xfb, 0x5f, 0x62, 0x48, 0xc1, 0xe3, 0x04,
|
||||
0xbf, 0x24, 0x47, 0x2a, 0x2e, 0x79, 0xf2, 0x68, 0xee, 0x2f, 0x9e, 0x90, 0xca, 0x29, 0xd1, 0x4e,
|
||||
0x64, 0xa5, 0xb0, 0xf2, 0x1e, 0x1c, 0x77, 0x9b, 0xe4, 0x33, 0x76, 0x1c, 0xa3, 0x7d, 0xee, 0xf0,
|
||||
0x23, 0x14, 0x32, 0xdc, 0xf2, 0xbf, 0x02, 0x8d, 0x4e, 0xe0, 0x4a, 0x1e, 0x3f, 0x26, 0x60, 0x1a,
|
||||
0xa1, 0xc9, 0xc7, 0xe7, 0x60, 0xe1, 0x3a, 0x9f, 0x1f, 0x7e, 0x08, 0x20, 0xaf, 0x93, 0x85, 0xdd,
|
||||
0x3e, 0x9a, 0x1c, 0x02, 0xe9, 0xf2, 0x93, 0x04, 0x12, 0x7c, 0x1f, 0x53, 0xe7, 0x19, 0x19, 0xb2,
|
||||
0x29, 0xda, 0x25, 0x0e, 0xa2, 0xe4, 0xf2, 0x3e, 0x44, 0xc1, 0x2e, 0xf1, 0x02, 0x69, 0x9b, 0x64,
|
||||
0x71, 0x10, 0xec, 0x92, 0x8c, 0x10, 0xc2, 0xbe, 0x6c, 0x06, 0xd6, 0xf7, 0x3d, 0xd8, 0x84, 0xc0,
|
||||
0xc6, 0x98, 0xb1, 0x91, 0x4f, 0xfe, 0x15, 0x3c, 0xac, 0x10, 0x7c, 0xc9, 0x12, 0x33, 0x89, 0x36,
|
||||
0xc1, 0x15, 0x59, 0xe0, 0x7e, 0xc2, 0xb7, 0xd3, 0xa0, 0x8f, 0x90, 0x87, 0x72, 0x2a, 0x1e, 0xb7,
|
||||
0xc5, 0x23, 0x21, 0x8f, 0xe6, 0x22, 0x8d, 0x50, 0x64, 0x50, 0x8d, 0x84, 0xf4, 0x23, 0x0f, 0x72,
|
||||
0x62, 0x7f, 0xf6, 0x49, 0x94, 0xd3, 0x05, 0xd4, 0x9b, 0x0d, 0xa0, 0x89, 0x38, 0x2e, 0xf9, 0xe4,
|
||||
0xb9, 0x12, 0xe0, 0xc3, 0x06, 0x40, 0xba, 0x7c, 0x18, 0xb4, 0xc9, 0x51, 0xd6, 0x8a, 0x8b, 0x4e,
|
||||
0x0a, 0x80, 0xfa, 0xfd, 0x55, 0xa8, 0x1f, 0xe0, 0x9a, 0x14, 0xa1, 0x3e, 0x03, 0xed, 0xda, 0x91,
|
||||
0x7b, 0x98, 0xfd, 0x19, 0xf9, 0x17, 0x1d, 0xc0, 0x0c, 0x3c, 0x3b, 0x6f, 0xcb, 0xf7, 0x16, 0xf0,
|
||||
0x7e, 0xd2, 0xc6, 0xf7, 0x13, 0xf0, 0xce, 0x6d, 0x6b, 0x2f, 0xce, 0xcf, 0xdf, 0x9e, 0x3f, 0xd8,
|
||||
0x0f, 0x84, 0x12, 0x12, 0x70, 0x21, 0x2c, 0x00, 0x2a, 0x7c, 0x0d, 0xc2, 0x9b, 0x40, 0xbd, 0x38,
|
||||
0x60, 0x68, 0x99, 0xd2, 0x80, 0x20, 0x80, 0x58, 0x6a, 0x42, 0x08, 0x4f, 0x1c, 0x4c, 0x8f, 0xe8,
|
||||
0xa9, 0xb8, 0x74, 0xc6, 0x20, 0x2f, 0xfd, 0x3d, 0xe1, 0xaf, 0x0e, 0xbb, 0x47, 0x7f, 0x1c, 0x9f,
|
||||
0xbf, 0x79, 0xf5, 0xe6, 0xb7, 0x07, 0x87, 0xfb, 0xdd, 0x23, 0xf2, 0x3e, 0x7b, 0x57, 0xad, 0x37,
|
||||
0x23, 0x98, 0x42, 0x81, 0x30, 0x24, 0x22, 0x34, 0x41, 0x69, 0x10, 0xc9, 0x90, 0xb1, 0x0a, 0x54,
|
||||
0x66, 0xfe, 0x78, 0xc8, 0x74, 0x90, 0x9f, 0x98, 0x74, 0x21, 0xdc, 0x27, 0xde, 0x20, 0x08, 0x21,
|
||||
0xc6, 0x07, 0xb0, 0x90, 0xf0, 0x40, 0xb8, 0x3b, 0x14, 0x37, 0x3c, 0x5a, 0x00, 0xf1, 0x22, 0x90,
|
||||
0xf4, 0x4d, 0xfc, 0x44, 0x4a, 0x20, 0x8f, 0x3d, 0xfc, 0x9a, 0xe8, 0x04, 0x64, 0x0e, 0x6b, 0x37,
|
||||
0xea, 0xd5, 0x46, 0x79, 0x34, 0x9a, 0x49, 0x9f, 0x5c, 0x54, 0xb8, 0x43, 0x9d, 0x9e, 0x18, 0x5e,
|
||||
0x00, 0x09, 0xda, 0xe9, 0xfb, 0xd7, 0x67, 0x4e, 0x9f, 0x9e, 0xae, 0x06, 0x8b, 0x8e, 0x26, 0x5e,
|
||||
0xaf, 0x84, 0x28, 0x07, 0x7c, 0xe6, 0xaf, 0xe1, 0x2d, 0xc4, 0xae, 0x8f, 0x84, 0x47, 0x5c, 0x2c,
|
||||
0x7e, 0x24, 0x12, 0x5e, 0xce, 0x92, 0x80, 0xfb, 0x61, 0xd2, 0x31, 0x7a, 0x69, 0xc6, 0x17, 0x38,
|
||||
0x32, 0x22, 0xda, 0x39, 0x16, 0xea, 0x78, 0x0a, 0x77, 0x11, 0x14, 0x1c, 0xaa, 0x27, 0x11, 0x30,
|
||||
0x3c, 0x53, 0x53, 0xc9, 0xb0, 0x22, 0xe7, 0x4d, 0x8d, 0x83, 0xd6, 0xd3, 0x95, 0x61, 0x7a, 0x7b,
|
||||
0x07, 0x50, 0x31, 0xa7, 0xb4, 0x3e, 0x7e, 0x1e, 0x24, 0x3f, 0x74, 0x1f, 0x8c, 0xfe, 0xd0, 0x29,
|
||||
0xe7, 0x47, 0x54, 0xf8, 0x53, 0x5f, 0xdf, 0xb7, 0x3b, 0x0a, 0x4c, 0x45, 0x36, 0x3e, 0x38, 0x67,
|
||||
0xcb, 0xcc, 0x0c, 0xa8, 0x4c, 0x29, 0x99, 0x48, 0x20, 0xd3, 0x36, 0x06, 0x6d, 0xec, 0x10, 0x62,
|
||||
0xe1, 0xd4, 0x9a, 0x0e, 0xc1, 0x21, 0x7a, 0x4f, 0xf9, 0x1e, 0xbb, 0xa6, 0x90, 0xe6, 0x45, 0x83,
|
||||
0x6e, 0x59, 0xdb, 0x1b, 0x82, 0xb3, 0xc3, 0x98, 0x08, 0xef, 0xac, 0xec, 0xce, 0x86, 0x3b, 0x5d,
|
||||
0x84, 0xa5, 0x08, 0x65, 0xd9, 0xf8, 0xca, 0xae, 0xf8, 0xd3, 0xb5, 0x4e, 0x60, 0x60, 0x8c, 0x77,
|
||||
0x21, 0x2a, 0x41, 0x11, 0x95, 0x4f, 0xe7, 0x20, 0x8b, 0x65, 0xf6, 0xd4, 0xa7, 0x1e, 0xfc, 0xc1,
|
||||
0x3f, 0x1d, 0xda, 0xb1, 0x4e, 0xf5, 0x95, 0x4b, 0x38, 0xed, 0x61, 0x4b, 0xfc, 0xa7, 0x41, 0x3b,
|
||||
0x5a, 0x1d, 0xb1, 0x31, 0xf0, 0x18, 0x29, 0x54, 0xd1, 0x78, 0x7c, 0xc3, 0xd5, 0xd1, 0xf0, 0x0d,
|
||||
0x6c, 0x22, 0xde, 0x7e, 0xd5, 0x68, 0x7e, 0x65, 0x17, 0x9e, 0x90, 0xb9, 0xc7, 0x58, 0xf4, 0x75,
|
||||
0x34, 0x55, 0xf5, 0x55, 0x8d, 0xbf, 0x32, 0x88, 0xdc, 0x61, 0x19, 0x47, 0x53, 0xa7, 0x07, 0x6a,
|
||||
0x28, 0xe6, 0xc5, 0xe5, 0x21, 0xc4, 0x1c, 0xe0, 0x92, 0x61, 0xb5, 0x3d, 0x7f, 0xdf, 0xc6, 0x15,
|
||||
0xf1, 0x2a, 0xdf, 0x93, 0x8c, 0x9c, 0x60, 0x33, 0x78, 0xcb, 0xf3, 0x87, 0xae, 0x70, 0x41, 0x07,
|
||||
0x62, 0xf4, 0x7c, 0xce, 0x22, 0x81, 0xff, 0x1d, 0xb0, 0x2b, 0x7d, 0x4e, 0x9e, 0xc3, 0x80, 0xdd,
|
||||
0x78, 0x92, 0x5b, 0x34, 0xa2, 0x43, 0x6a, 0xea, 0xf7, 0x51, 0x0e, 0xe4, 0xae, 0xcb, 0xa7, 0xaf,
|
||||
0x43, 0x97, 0x43, 0x8e, 0xd0, 0x59, 0x1a, 0x43, 0x07, 0x34, 0x4f, 0x3a, 0x02, 0x3c, 0x06, 0x55,
|
||||
0x39, 0x13, 0xf4, 0xbe, 0x63, 0x11, 0x1b, 0xc5, 0x22, 0x0b, 0xf8, 0x70, 0x7e, 0x76, 0x01, 0x5b,
|
||||
0xe8, 0x0d, 0x65, 0x5b, 0x59, 0x2a, 0x92, 0x91, 0x0d, 0x8c, 0x45, 0x27, 0x04, 0xa7, 0xcb, 0x54,
|
||||
0x14, 0x53, 0x03, 0x8c, 0x19, 0xb3, 0x18, 0x1f, 0x7d, 0x5d, 0x16, 0xe4, 0x1f, 0x41, 0x08, 0xa0,
|
||||
0x89, 0xd2, 0xa0, 0xe3, 0x88, 0xf2, 0xdb, 0xaa, 0x39, 0x80, 0xb0, 0x7d, 0x89, 0x9f, 0xf2, 0xf8,
|
||||
0x38, 0x5e, 0x0e, 0x79, 0xe0, 0x8c, 0xa3, 0x9b, 0xb5, 0x01, 0x2a, 0x0d, 0x11, 0x1d, 0x51, 0x0f,
|
||||
0x23, 0x1c, 0x0f, 0x6b, 0x35, 0x9e, 0xfb, 0xab, 0xa8, 0x87, 0xff, 0x06, 0x0d, 0x5c, 0xd7, 0xbd,
|
||||
0x91, 0x4a, 0x64, 0x8a, 0x52, 0x65, 0x51, 0x70, 0xda, 0x62, 0x96, 0xba, 0x9b, 0x3d, 0x9a, 0x8a,
|
||||
0x81, 0x45, 0x7c, 0x55, 0x64, 0x90, 0x5f, 0xe2, 0x29, 0x87, 0x1b, 0x42, 0x9a, 0x10, 0x84, 0x09,
|
||||
0x91, 0xdf, 0x4c, 0xc3, 0x63, 0x90, 0x2e, 0x27, 0x8c, 0x88, 0x2f, 0xd6, 0x4b, 0x03, 0x29, 0xec,
|
||||
0x63, 0x07, 0xcd, 0x7b, 0xce, 0x42, 0x26, 0xa2, 0x2a, 0xb6, 0x05, 0x9b, 0x22, 0x44, 0x05, 0x65,
|
||||
0xf2, 0x3e, 0x09, 0x54, 0x53, 0x72, 0xfb, 0xf1, 0x63, 0x64, 0x69, 0x08, 0xc0, 0x7e, 0x38, 0x28,
|
||||
0x6b, 0xef, 0xc1, 0x92, 0xc7, 0x22, 0x9a, 0x23, 0x4f, 0xb4, 0x3d, 0x88, 0x31, 0x9f, 0xa0, 0x3b,
|
||||
0x12, 0x28, 0x2a, 0xac, 0xe4, 0x11, 0x82, 0xb2, 0xde, 0x10, 0xd6, 0x2d, 0x80, 0x78, 0x05, 0xec,
|
||||
0xd0, 0x65, 0x49, 0xed, 0x62, 0xa0, 0xe9, 0x20, 0x00, 0x1b, 0x09, 0x1e, 0xcd, 0xe5, 0x70, 0x2a,
|
||||
0x5f, 0xd8, 0x69, 0x40, 0x56, 0x98, 0xd2, 0x55, 0xa2, 0x92, 0x5c, 0x0c, 0x3a, 0xbc, 0x78, 0xbb,
|
||||
0x3c, 0x47, 0x31, 0xd8, 0x30, 0xd6, 0x19, 0xd6, 0xe0, 0x44, 0x75, 0x62, 0xb1, 0x60, 0xf1, 0x2c,
|
||||
0xe8, 0x91, 0x4c, 0x3c, 0xc7, 0x20, 0xe8, 0x82, 0xff, 0x71, 0x96, 0xc0, 0xaa, 0xc2, 0x6e, 0xe0,
|
||||
0x5e, 0x4c, 0x07, 0xef, 0x20, 0x99, 0xe6, 0x85, 0x28, 0xca, 0x22, 0x99, 0xae, 0xea, 0x1f, 0x0f,
|
||||
0xac, 0x65, 0x74, 0x8a, 0xb1, 0x55, 0x16, 0x46, 0xea, 0x49, 0x34, 0x9b, 0x17, 0x92, 0x1f, 0xc4,
|
||||
0xac, 0xb8, 0x5d, 0x91, 0x55, 0x57, 0xfa, 0x07, 0x21, 0xfb, 0x0d, 0xf3, 0x12, 0xd2, 0xe7, 0x10,
|
||||
0x74, 0x95, 0xd3, 0x18, 0x46, 0xdb, 0x5b, 0x2d, 0x6e, 0x4b, 0x8e, 0xec, 0x69, 0xf9, 0x70, 0x86,
|
||||
0xce, 0x47, 0x3c, 0x19, 0x86, 0x10, 0x73, 0x60, 0xf8, 0xa3, 0x51, 0x7c, 0x81, 0x9b, 0x47, 0x31,
|
||||
0xc4, 0xbf, 0xf9, 0x88, 0x06, 0xf2, 0x8a, 0x8d, 0x90, 0x66, 0x41, 0xf1, 0xf5, 0xee, 0x36, 0x87,
|
||||
0xe4, 0x3f, 0x50, 0xcb, 0x27, 0x06, 0xf6, 0x94, 0xf5, 0x4e, 0x21, 0xd2, 0x81, 0xbe, 0xe8, 0x61,
|
||||
0x26, 0x8c, 0x75, 0xa6, 0xb4, 0x9d, 0x47, 0x11, 0xe6, 0x92, 0x3a, 0xe4, 0x96, 0xe0, 0x3a, 0x93,
|
||||
0x67, 0xe5, 0x62, 0x42, 0xa6, 0xa5, 0x44, 0xac, 0x7d, 0x27, 0xef, 0xbd, 0x11, 0x0f, 0x27, 0x90,
|
||||
0xf6, 0xe5, 0xca, 0x0a, 0x7c, 0x27, 0x11, 0x01, 0x54, 0x2d, 0x5e, 0xd5, 0xf5, 0xf6, 0x96, 0x65,
|
||||
0x96, 0x65, 0xcc, 0x1f, 0x5a, 0x68, 0x75, 0x91, 0xc5, 0x86, 0x12, 0x1c, 0x5a, 0x10, 0x8f, 0xe5,
|
||||
0x2c, 0xa9, 0xf6, 0xda, 0x13, 0x75, 0xf1, 0x4f, 0xa7, 0x20, 0x60, 0xb2, 0x76, 0x8f, 0x15, 0xd9,
|
||||
0x17, 0x53, 0x98, 0x0b, 0xcb, 0xb3, 0x1c, 0x84, 0x15, 0xd8, 0x87, 0x07, 0xa2, 0xb0, 0x04, 0xca,
|
||||
0x64, 0x19, 0xd2, 0x5c, 0x25, 0x81, 0xa0, 0xbb, 0x42, 0xea, 0xb0, 0x9e, 0x04, 0x14, 0x47, 0x11,
|
||||
0x92, 0x4c, 0x08, 0xd8, 0xd4, 0x1b, 0xb0, 0x24, 0x8c, 0xc0, 0x91, 0x78, 0xe3, 0x6e, 0xc8, 0x22,
|
||||
0xd7, 0xb8, 0x89, 0xbc, 0x84, 0x0b, 0x5f, 0xa5, 0x62, 0xe7, 0x1c, 0x2b, 0x96, 0x23, 0x5d, 0x83,
|
||||
0xdf, 0xf2, 0xde, 0x89, 0x8c, 0x93, 0xe5, 0x09, 0x82, 0xb6, 0x95, 0x67, 0xda, 0x4b, 0xe6, 0x61,
|
||||
0x2d, 0x03, 0x4c, 0x14, 0x02, 0x12, 0x74, 0x21, 0x6d, 0x02, 0x4a, 0x06, 0x16, 0x60, 0x21, 0x2a,
|
||||
0xf8, 0x45, 0x7b, 0x19, 0x8a, 0x17, 0xd4, 0xc0, 0xa0, 0x06, 0xe2, 0x64, 0xe5, 0x6e, 0x90, 0x3f,
|
||||
0xef, 0x02, 0xc1, 0x9a, 0xdb, 0x1d, 0x20, 0xec, 0x4e, 0x08, 0x91, 0xff, 0xdd, 0xb5, 0xd0, 0xd9,
|
||||
0x9b, 0xbb, 0x40, 0x64, 0x8a, 0x73, 0x27, 0xd0, 0x87, 0x1d, 0x60, 0xde, 0xdc, 0x09, 0x23, 0x04,
|
||||
0xe9, 0x2e, 0xfa, 0x81, 0x89, 0xbb, 0x03, 0x04, 0x7d, 0xe0, 0x26, 0x08, 0x96, 0xed, 0x14, 0x00,
|
||||
0x16, 0x66, 0xb7, 0xcf, 0x21, 0x24, 0x32, 0x0e, 0xc7, 0xa2, 0xa2, 0x9b, 0x96, 0x25, 0x45, 0x75,
|
||||
0x37, 0x5f, 0xe9, 0xbc, 0xa6, 0x99, 0x63, 0x77, 0x00, 0x58, 0x14, 0xae, 0x40, 0x8f, 0x8c, 0x5b,
|
||||
0x9a, 0xf9, 0xf8, 0x95, 0xf6, 0x19, 0x15, 0x21, 0x01, 0xc8, 0x51, 0x66, 0x68, 0xd7, 0xce, 0xb2,
|
||||
0x76, 0x51, 0x14, 0x75, 0xde, 0x09, 0x41, 0x83, 0xb3, 0x1e, 0x82, 0x8c, 0xa3, 0x30, 0x09, 0x21,
|
||||
0xff, 0x78, 0xc6, 0x7c, 0x1e, 0x41, 0x3c, 0xff, 0x07, 0xa8, 0xb1, 0x4c, 0x4d, 0xd0, 0xdf, 0x4e,
|
||||
0x41, 0xb4, 0xc5, 0x2b, 0x41, 0x37, 0x43, 0xc8, 0x73, 0x62, 0x1e, 0x4d, 0x41, 0xd0, 0xf1, 0x5b,
|
||||
0x45, 0xc2, 0x66, 0x93, 0x72, 0x18, 0xc9, 0x6f, 0x59, 0x80, 0x27, 0x8c, 0x26, 0xc1, 0xb2, 0x27,
|
||||
0xd6, 0x35, 0xbd, 0x9d, 0xf7, 0x16, 0x0b, 0x25, 0x5a, 0x61, 0x20, 0x5e, 0x52, 0x70, 0x04, 0x5a,
|
||||
0x78, 0x50, 0x24, 0x82, 0x4a, 0x65, 0x61, 0x9d, 0x65, 0xf5, 0x41, 0xf9, 0x30, 0xcb, 0x34, 0x9f,
|
||||
0x66, 0x35, 0xef, 0x65, 0x2f, 0xc4, 0xec, 0xf5, 0xba, 0x28, 0x09, 0x26, 0xce, 0xe7, 0xf5, 0x1f,
|
||||
0x00, 0x38, 0x30, 0x5d, 0x3e, 0xa0, 0x44, 0x7c, 0xfd, 0xff, 0xd1, 0x9c, 0x2f, 0x7e, 0xa1, 0xe2,
|
||||
0xab, 0x63, 0xf2, 0x5e, 0xff, 0xdc, 0x11, 0xd3, 0x48, 0x77, 0xb7, 0xfc, 0xe2, 0x92, 0x88, 0x10,
|
||||
0x9d, 0x64, 0x21, 0x84, 0x7b, 0x05, 0x49, 0x89, 0x08, 0x34, 0x77, 0x7a, 0x67, 0xab, 0xd8, 0xf2,
|
||||
0x1c, 0xaa, 0xc9, 0x2a, 0xaa, 0xa9, 0x71, 0xd9, 0xaf, 0x5b, 0xb6, 0xc0, 0x33, 0xb8, 0x0b, 0xcf,
|
||||
0x24, 0x87, 0x67, 0x22, 0xf0, 0xe4, 0x5b, 0x90, 0x0c, 0x16, 0x78, 0x7c, 0x79, 0x97, 0x24, 0xa6,
|
||||
0xf5, 0x4e, 0x59, 0xfe, 0x29, 0x3a, 0x10, 0xe3, 0xeb, 0x07, 0x62, 0x3c, 0x7f, 0x20, 0x96, 0x88,
|
||||
0xf3, 0x1f, 0x75, 0x26, 0x46, 0x31, 0x23, 0x7f, 0xe0, 0x88, 0x03, 0x04, 0x65, 0x35, 0x53, 0x87,
|
||||
0x8b, 0xaf, 0xb3, 0xfc, 0x13, 0x82, 0x0a, 0x19, 0x08, 0x2c, 0x5f, 0x6e, 0xd1, 0x45, 0x56, 0xfe,
|
||||
0x4e, 0xbc, 0x76, 0xa2, 0x8e, 0x5a, 0x73, 0xef, 0xa1, 0xa0, 0xb6, 0x89, 0xe3, 0x61, 0x8c, 0x3c,
|
||||
0x97, 0xe1, 0x2f, 0x8e, 0x14, 0xaf, 0xbd, 0x70, 0xf1, 0x15, 0x2d, 0x6e, 0x20, 0x14, 0xec, 0xf1,
|
||||
0x39, 0xef, 0x33, 0x48, 0xa1, 0xcb, 0xf9, 0x49, 0x0d, 0x21, 0xe5, 0xe5, 0xdc, 0xb7, 0xb5, 0x20,
|
||||
0x7b, 0x1d, 0xbc, 0xc0, 0x5c, 0x65, 0xcb, 0x58, 0x2c, 0x41, 0xaf, 0x1f, 0xf9, 0xe1, 0x98, 0x0a,
|
||||
0x8a, 0xad, 0xb6, 0x36, 0xd1, 0xdb, 0xe9, 0xb6, 0x79, 0xf2, 0x70, 0x21, 0x44, 0xa7, 0xee, 0x6e,
|
||||
0xcb, 0x45, 0x7c, 0x04, 0xeb, 0xac, 0xac, 0xd8, 0x99, 0x8c, 0xf1, 0x47, 0xa2, 0xde, 0x49, 0x52,
|
||||
0x80, 0xd0, 0xa0, 0xd6, 0x8b, 0x52, 0x43, 0x1f, 0xf6, 0x87, 0x5b, 0x8d, 0x21, 0x85, 0xcc, 0x2d,
|
||||
0x98, 0xed, 0x5e, 0xac, 0xb9, 0x3e, 0x5a, 0x1e, 0x9d, 0x17, 0x8d, 0x5b, 0x83, 0x54, 0x35, 0x4c,
|
||||
0x10, 0x5a, 0x4c, 0x52, 0x30, 0xde, 0x3e, 0x17, 0xc1, 0x4e, 0x27, 0x49, 0xcf, 0x29, 0x84, 0x08,
|
||||
0x29, 0x16, 0x89, 0xd0, 0x1f, 0xf1, 0xc7, 0x2a, 0x06, 0xdd, 0x48, 0x21, 0x20, 0x80, 0x5c, 0x50,
|
||||
0xec, 0x66, 0xee, 0x71, 0x8c, 0x39, 0x16, 0x24, 0x3d, 0x2b, 0x5f, 0xa2, 0x2b, 0x48, 0x28, 0xd4,
|
||||
0x57, 0xea, 0x20, 0xd0, 0x49, 0xc5, 0xa7, 0x40, 0x9c, 0x91, 0x50, 0x2a, 0xf5, 0xcc, 0x38, 0x0b,
|
||||
0x51, 0xe0, 0xf7, 0x07, 0x08, 0xc2, 0xd2, 0x94, 0x81, 0x77, 0x80, 0x87, 0x63, 0x8d, 0x2a, 0x1e,
|
||||
0x7e, 0x17, 0x52, 0xd9, 0xd3, 0x9c, 0x74, 0xae, 0x08, 0xe2, 0x76, 0x4d, 0x5c, 0xf2, 0x6b, 0x79,
|
||||
0x00, 0xf1, 0x9f, 0x3e, 0xcd, 0xce, 0xf8, 0xb0, 0xf2, 0xc2, 0xe3, 0x2e, 0xc7, 0x4f, 0x14, 0x4d,
|
||||
0x5c, 0xe1, 0x11, 0x54, 0x80, 0x69, 0x5c, 0x02, 0xde, 0x24, 0x17, 0xee, 0x3d, 0x2b, 0x27, 0xce,
|
||||
0x5a, 0x98, 0x09, 0x70, 0x6b, 0xe7, 0xdc, 0xb4, 0x20, 0x69, 0x55, 0x49, 0x09, 0xc4, 0xa2, 0x49,
|
||||
0x7e, 0xbe, 0xb5, 0xc1, 0xc1, 0x96, 0xb1, 0x80, 0x4d, 0x71, 0x24, 0x9a, 0x6c, 0x76, 0x80, 0x23,
|
||||
0xc7, 0x70, 0x41, 0x38, 0xd4, 0x7c, 0xca, 0xcd, 0x23, 0xd0, 0x0e, 0x75, 0x94, 0xfc, 0x56, 0x7a,
|
||||
0x6e, 0x11, 0x0f, 0x82, 0xf3, 0xce, 0xe7, 0x49, 0x19, 0x0b, 0xc5, 0x09, 0xee, 0x61, 0x1a, 0xcc,
|
||||
0x76, 0x12, 0x2c, 0x02, 0x49, 0x23, 0x8f, 0xc7, 0x86, 0xd2, 0xf7, 0x6b, 0x58, 0xc0, 0x90, 0xfe,
|
||||
0x9c, 0x5f, 0x25, 0xea, 0x74, 0x52, 0xd5, 0x50, 0x64, 0x0b, 0xde, 0x41, 0x43, 0x16, 0x01, 0xc8,
|
||||
0xd6, 0xdb, 0x5c, 0xd3, 0x4c, 0x36, 0xcd, 0x64, 0xe4, 0x01, 0x62, 0x1a, 0xb8, 0x27, 0xc8, 0x1e,
|
||||
0x48, 0x20, 0xa8, 0x09, 0xd4, 0x4f, 0xf0, 0xb4, 0x33, 0x8b, 0x2f, 0x20, 0x6f, 0xc8, 0x05, 0x17,
|
||||
0x41, 0x61, 0x68, 0x91, 0x9b, 0x5b, 0xdf, 0xc8, 0xee, 0x72, 0xe7, 0xe9, 0xb2, 0x08, 0xd1, 0x9b,
|
||||
0x3a, 0xcb, 0x20, 0x9d, 0xf6, 0xa6, 0xcb, 0x14, 0x16, 0x43, 0x65, 0xe9, 0x5d, 0xae, 0xae, 0x95,
|
||||
0x23, 0x08, 0xb6, 0x64, 0x5e, 0xbd, 0xe9, 0x6a, 0x9e, 0x95, 0x56, 0xe9, 0xca, 0x2a, 0x48, 0x57,
|
||||
0x99, 0x12, 0xa6, 0xb6, 0x83, 0xf4, 0xe4, 0xa4, 0x3c, 0xf7, 0xdc, 0x36, 0x24, 0xa9, 0x2e, 0x0d,
|
||||
0xe0, 0x12, 0xd0, 0xdb, 0xb8, 0x8d, 0xde, 0x90, 0x45, 0x09, 0xbd, 0xe5, 0xe2, 0x36, 0x1c, 0xd3,
|
||||
0x59, 0xd6, 0xf8, 0x91, 0xce, 0xd2, 0xd6, 0x8f, 0x0b, 0x5d, 0x5f, 0xe3, 0x93, 0x9f, 0xe7, 0x13,
|
||||
0x97, 0x27, 0x15, 0x73, 0x79, 0xc0, 0xee, 0x23, 0x79, 0x61, 0x15, 0x11, 0xb2, 0x8b, 0x87, 0x00,
|
||||
0x4f, 0x2d, 0x3d, 0x8c, 0xd4, 0xf0, 0x0c, 0x53, 0xf5, 0x8b, 0x82, 0xdd, 0xad, 0x04, 0xb8, 0xe5,
|
||||
0x15, 0x79, 0x8d, 0xe9, 0x4c, 0xb6, 0xcc, 0x54, 0xcb, 0x2c, 0x06, 0xa7, 0xb8, 0x55, 0x9a, 0xe8,
|
||||
0xc6, 0x41, 0xbf, 0x4a, 0xb2, 0x8b, 0xb2, 0x6f, 0x99, 0xa5, 0xdf, 0x91, 0xf6, 0xef, 0x90, 0xa3,
|
||||
0xdd, 0xa3, 0xd2, 0xa0, 0x92, 0xb5, 0xef, 0x24, 0xa6, 0x77, 0x4c, 0x76, 0x67, 0x66, 0x7a, 0x7f,
|
||||
0x64, 0x8a, 0x68, 0x26, 0x49, 0xb3, 0xb5, 0x62, 0x21, 0x0e, 0x06, 0xff, 0x23, 0x98, 0x6e, 0x24,
|
||||
0xd3, 0x3f, 0x80, 0xed, 0x36, 0x23, 0x24, 0x8a, 0x21, 0xc8, 0x84, 0xa5, 0x24, 0x5f, 0x5d, 0x83,
|
||||
0x41, 0x34, 0x3b, 0xc1, 0x21, 0xef, 0x04, 0x20, 0xc7, 0xc9, 0x8a, 0x1c, 0x07, 0x52, 0x82, 0xb5,
|
||||
0x8b, 0xf4, 0x8b, 0x0c, 0x28, 0xc0, 0x20, 0xbf, 0x01, 0x48, 0xa4, 0xfa, 0xf6, 0x7a, 0xb2, 0xf8,
|
||||
0x7f, 0x11, 0x34, 0xe2, 0xec, 0xea, 0xeb, 0x08, 0x18, 0x2b, 0x38, 0x85, 0x1b, 0xb7, 0xcc, 0xad,
|
||||
0x8a, 0x94, 0x1b, 0xab, 0x5e, 0xff, 0xcb, 0x99, 0xe8, 0x27, 0xe2, 0x5b, 0x01, 0x9e, 0xeb, 0xac,
|
||||
0xbe, 0x19, 0x44, 0xbe, 0xff, 0xcd, 0xf7, 0xd5, 0x9f, 0x8b, 0xb9, 0xe3, 0x5b, 0x03, 0x2b, 0x36,
|
||||
0x32, 0xfd, 0x8e, 0x00, 0xac, 0x08, 0xd2, 0xb2, 0xf5, 0x87, 0x42, 0x1a, 0x46, 0x9d, 0xd8, 0xe6,
|
||||
0xef, 0x35, 0xc3, 0xb6, 0xe1, 0x4a, 0x6c, 0xa3, 0x81, 0xbf, 0xd4, 0x21, 0x7e, 0x6f, 0x83, 0x58,
|
||||
0x0d, 0xa3, 0x55, 0xc7, 0x6b, 0xcd, 0xa8, 0xb7, 0xf0, 0x0a, 0xbd, 0x55, 0x00, 0xb1, 0x9a, 0xc4,
|
||||
0xb2, 0x0c, 0x8b, 0x54, 0x8d, 0x6a, 0x9d, 0x1c, 0xe0, 0x8f, 0x88, 0xd4, 0x0d, 0x1b, 0xef, 0xac,
|
||||
0x3a, 0xdc, 0x35, 0x5a, 0xa4, 0x89, 0x1d, 0xf0, 0xd1, 0x82, 0xc7, 0x66, 0x15, 0x3a, 0x4c, 0xfc,
|
||||
0x9d, 0x11, 0x98, 0xc0, 0x52, 0x17, 0xa3, 0x55, 0x95, 0x77, 0xb6, 0x51, 0xc3, 0xb6, 0xc6, 0x01,
|
||||
0xb1, 0xc4, 0xef, 0x8f, 0xb4, 0xf0, 0xda, 0x30, 0xac, 0x4b, 0xe8, 0xb1, 0xea, 0x67, 0xb0, 0x72,
|
||||
0x83, 0x58, 0xa6, 0xd1, 0x38, 0xb3, 0xe0, 0x6a, 0x9f, 0x59, 0x36, 0x20, 0x75, 0xd6, 0xc2, 0xdb,
|
||||
0x03, 0xa3, 0xa6, 0x7a, 0xc4, 0x34, 0x56, 0xfd, 0x12, 0x86, 0xfd, 0x0e, 0x38, 0xc0, 0xf0, 0x5a,
|
||||
0x9d, 0xb4, 0x0c, 0x13, 0x51, 0x38, 0xa8, 0x91, 0x26, 0xac, 0x0f, 0xdb, 0x41, 0x9c, 0x4f, 0x61,
|
||||
0xb7, 0xbf, 0xd7, 0xb1, 0x47, 0x60, 0x62, 0x56, 0x71, 0xa4, 0x89, 0xdf, 0x5d, 0xb0, 0xaa, 0xd8,
|
||||
0x5a, 0x15, 0x5b, 0xc5, 0x4b, 0xdd, 0x38, 0xa8, 0x2b, 0x08, 0xdc, 0x1d, 0x8e, 0x68, 0x11, 0xa4,
|
||||
0x95, 0xd5, 0x3a, 0x05, 0xf2, 0xd4, 0x7f, 0xc7, 0x5f, 0x23, 0x11, 0x8d, 0xb6, 0x69, 0xd8, 0x30,
|
||||
0x77, 0x13, 0x3f, 0x6d, 0x41, 0x33, 0x68, 0xc7, 0x9b, 0xba, 0x21, 0xaf, 0x35, 0x44, 0x47, 0x41,
|
||||
0x55, 0x91, 0x1c, 0x6a, 0x68, 0x15, 0xe9, 0x8c, 0xd7, 0x53, 0xab, 0x79, 0x69, 0x59, 0xbf, 0x5b,
|
||||
0x88, 0x68, 0x0b, 0x27, 0x10, 0xe8, 0x37, 0x1b, 0x02, 0x0b, 0xd8, 0x03, 0x0e, 0x81, 0xbd, 0x5c,
|
||||
0x02, 0x2d, 0x5a, 0xbf, 0x4b, 0x9e, 0xd4, 0xc5, 0x0c, 0xb0, 0x3d, 0xd8, 0x97, 0x61, 0x03, 0xe4,
|
||||
0x01, 0x39, 0xc0, 0x0f, 0x0b, 0xdf, 0x4c, 0x13, 0x03, 0x2c, 0x03, 0xf8, 0x09, 0x74, 0x46, 0xb2,
|
||||
0x21, 0x22, 0x62, 0x8b, 0xcd, 0x96, 0xb8, 0xa9, 0xab, 0x06, 0xc1, 0x21, 0x00, 0x42, 0xea, 0xb7,
|
||||
0xf0, 0x13, 0xc6, 0x62, 0x8b, 0x29, 0x31, 0xb3, 0xcd, 0xd7, 0x48, 0x6f, 0x0b, 0x76, 0x9f, 0xff,
|
||||
0x99, 0x15, 0x51, 0x00, 0x5b, 0x97, 0xeb, 0xf4, 0x6b, 0x0c, 0xea, 0x57, 0x81, 0x34, 0x72, 0xff,
|
||||
0x6f, 0xbf, 0x1c, 0xdd, 0xf5, 0x93, 0x36, 0x07, 0xd4, 0xb6, 0x4e, 0x5b, 0x97, 0xcd, 0x53, 0xeb,
|
||||
0x00, 0x1f, 0xea, 0xa7, 0xad, 0x63, 0x9b, 0xda, 0xea, 0x25, 0xbe, 0x06, 0x6d, 0x5e, 0xda, 0x56,
|
||||
0xae, 0xa1, 0x45, 0x6d, 0xa0, 0xec, 0x41, 0xae, 0x05, 0x7f, 0x15, 0xc4, 0xba, 0x6c, 0xe6, 0x5a,
|
||||
0x70, 0x96, 0xd7, 0x56, 0x83, 0x5a, 0xa7, 0xb5, 0x3c, 0x1c, 0xad, 0x5e, 0x5a, 0xcd, 0xd3, 0xda,
|
||||
0x25, 0x8c, 0x6f, 0x5c, 0x5a, 0x62, 0xef, 0x44, 0x6e, 0x5e, 0xbd, 0xab, 0x7d, 0x22, 0x4a, 0x69,
|
||||
0x21, 0xc9, 0x4a, 0x77, 0x4f, 0xb6, 0x57, 0x40, 0xfe, 0x46, 0x4a, 0xa1, 0x6a, 0xab, 0xe2, 0xf6,
|
||||
0x7f, 0x50, 0xbf, 0x5b, 0xa8, 0x08, 0x2d, 0x54, 0xae, 0x26, 0x3e, 0xd6, 0x50, 0xbf, 0x61, 0x18,
|
||||
0x68, 0xa3, 0x8d, 0x1f, 0x35, 0x14, 0xca, 0x1a, 0xce, 0x7d, 0xd0, 0x00, 0x40, 0xfc, 0xf9, 0x9f,
|
||||
0x03, 0xd4, 0xc6, 0xe6, 0xdf, 0x20, 0x9f, 0xa7, 0x56, 0xf5, 0x77, 0xd4, 0x7d, 0xd9, 0x66, 0x19,
|
||||
0x75, 0x54, 0x02, 0xb4, 0x28, 0xe2, 0xe7, 0x86, 0xd0, 0xc8, 0x88, 0x1b, 0x34, 0x26, 0xad, 0xba,
|
||||
0xb4, 0x18, 0xa0, 0x8d, 0x68, 0x3f, 0xaa, 0x68, 0x4a, 0x0e, 0x84, 0x55, 0xa9, 0x2a, 0x2b, 0x83,
|
||||
0x3d, 0x96, 0xb0, 0x08, 0xad, 0xfa, 0xe5, 0xdf, 0xaa, 0xe6, 0x2d, 0x24, 0x11, 0x0e, 0x04, 0xe3,
|
||||
0x64, 0xd4, 0xc4, 0xd2, 0x26, 0x10, 0x15, 0x09, 0xd8, 0x00, 0x62, 0x42, 0x67, 0x03, 0x60, 0xa0,
|
||||
0x43, 0xf4, 0x2a, 0xf8, 0x9f, 0x67, 0xbf, 0x0e, 0x2e, 0x95, 0x66, 0x57, 0x0b, 0x44, 0xfb, 0x02,
|
||||
0x04, 0x0a, 0x45, 0xdb, 0x15, 0xdf, 0xa3, 0x7c, 0x42, 0x0b, 0x8f, 0xec, 0xee, 0x11, 0x2d, 0xad,
|
||||
0xfc, 0xee, 0x8c, 0xfa, 0xa5, 0x19, 0x79, 0x3d, 0xdc, 0x17, 0xbf, 0x6d, 0xfd, 0xbf, 0xe8, 0xc4,
|
||||
0x80, 0x4e, 0xf2, 0x5a, 0x00, 0x00
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
1219
wled00/html_simple.h
1219
wled00/html_simple.h
File diff suppressed because it is too large
Load Diff
3849
wled00/html_ui.h
3849
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -189,7 +189,7 @@ void sendImprovInfoResponse() {
|
||||
out[11] = 4; //Firmware len ("WLED")
|
||||
out[12] = 'W'; out[13] = 'L'; out[14] = 'E'; out[15] = 'D';
|
||||
uint8_t lengthSum = 17;
|
||||
uint8_t vlen = sprintf_P(out+lengthSum,PSTR("0.14.0-b1/%i"),VERSION);
|
||||
uint8_t vlen = sprintf_P(out+lengthSum,PSTR("0.14.0-b2/%i"),VERSION);
|
||||
out[16] = vlen; lengthSum += vlen;
|
||||
uint8_t hlen = 7;
|
||||
#ifdef ESP8266
|
||||
|
@ -14,16 +14,16 @@
|
||||
* JSON API (De)serialization
|
||||
*/
|
||||
|
||||
void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
bool deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
{
|
||||
byte id = elem["id"] | it;
|
||||
if (id >= strip.getMaxSegments()) return;
|
||||
if (id >= strip.getMaxSegments()) return false;
|
||||
|
||||
int stop = elem["stop"] | -1;
|
||||
|
||||
// if using vectors use this code to append segment
|
||||
if (id >= strip.getSegmentsNum()) {
|
||||
if (stop <= 0) return; // ignore empty/inactive segments
|
||||
if (stop <= 0) return false; // ignore empty/inactive segments
|
||||
strip.appendSegment(Segment(0, strip.getLengthTotal()));
|
||||
id = strip.getSegmentsNum()-1; // segments are added at the end of list
|
||||
}
|
||||
@ -56,7 +56,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
elem["rev"] = !elem["rev"]; // alternate reverse on even/odd segments
|
||||
deserializeSegment(elem, i, presetId); // recursive call with new id
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (elem["n"]) {
|
||||
@ -107,6 +107,8 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
if (stop > start && of > len -1) of = len -1;
|
||||
seg.set(start, stop, grp, spc, of, startY, stopY);
|
||||
|
||||
if (seg.reset && seg.stop == 0) return true; // segment was deleted & is marked for reset, no need to change anything else
|
||||
|
||||
byte segbri = seg.opacity;
|
||||
if (getVal(elem["bri"], &segbri)) {
|
||||
if (segbri > 0) seg.setOpacity(segbri);
|
||||
@ -211,6 +213,9 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
|
||||
JsonArray iarr = elem[F("i")]; //set individual LEDs
|
||||
if (!iarr.isNull()) {
|
||||
uint8_t oldMap1D2D = seg.map1D2D;
|
||||
seg.map1D2D = M12_Pixels; // no mapping
|
||||
|
||||
// set brightness immediately and disable transition
|
||||
transitionDelayTemp = 0;
|
||||
jsonTransitionOnce = true;
|
||||
@ -254,10 +259,13 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
||||
set = 0;
|
||||
}
|
||||
}
|
||||
seg.map1D2D = oldMap1D2D; // restore mapping
|
||||
strip.trigger(); // force segment update
|
||||
}
|
||||
// send UDP/WS if segment options changed (except selection; will also deselect current preset)
|
||||
if (seg.differs(prev) & 0x7F) stateChanged = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// deserializes WLED state (fileDoc points to doc object if called from web server)
|
||||
@ -373,11 +381,12 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
||||
deserializeSegment(segVar, id, presetId); //apply only the segment with the specified ID
|
||||
}
|
||||
} else {
|
||||
size_t deleted = 0;
|
||||
JsonArray segs = segVar.as<JsonArray>();
|
||||
for (JsonObject elem : segs) {
|
||||
deserializeSegment(elem, it, presetId);
|
||||
it++;
|
||||
if (deserializeSegment(elem, it++, presetId) && !elem["stop"].isNull() && elem["stop"]==0) deleted++;
|
||||
}
|
||||
if (strip.getSegmentsNum() > 3 && deleted >= strip.getSegmentsNum()/2U) strip.purgeSegments(); // batch deleting more than half segments
|
||||
}
|
||||
|
||||
usermods.readFromJsonState(root);
|
||||
@ -639,8 +648,14 @@ void serializeInfo(JsonObject root)
|
||||
root[F("cpalcount")] = strip.customPalettes.size(); //number of custom palettes
|
||||
|
||||
JsonArray ledmaps = root.createNestedArray(F("maps"));
|
||||
for (size_t i=0; i<10; i++) {
|
||||
if ((ledMaps>>i) & 0x0001) ledmaps.add(i);
|
||||
for (size_t i=0; i<WLED_MAX_LEDMAPS; i++) {
|
||||
if ((ledMaps>>i) & 0x00000001U) {
|
||||
JsonObject ledmaps0 = ledmaps.createNestedObject();
|
||||
ledmaps0["id"] = i;
|
||||
#ifndef ESP8266
|
||||
if (i && ledmapNames[i-1]) ledmaps0["n"] = ledmapNames[i-1];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
JsonObject wifi_info = root.createNestedObject("wifi");
|
||||
@ -703,9 +718,9 @@ void serializeInfo(JsonObject root)
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
os += 0x40;
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
os += 0x20;
|
||||
#endif
|
||||
|
||||
//os += 0x20; // indicated now removed Blynk support, may be reused to indicate another build-time option
|
||||
|
||||
#ifdef USERMOD_CRONIXIE
|
||||
os += 0x10;
|
||||
#endif
|
||||
|
@ -105,7 +105,7 @@ void stateUpdated(byte callMode) {
|
||||
|
||||
if (callMode != CALL_MODE_NOTIFICATION && callMode != CALL_MODE_NO_NOTIFY) notify(callMode);
|
||||
|
||||
//set flag to update blynk, ws and mqtt
|
||||
//set flag to update ws and mqtt
|
||||
interfaceUpdateCallMode = callMode;
|
||||
stateChanged = false;
|
||||
} else {
|
||||
@ -129,6 +129,9 @@ void stateUpdated(byte callMode) {
|
||||
//deactivate nightlight if target brightness is reached
|
||||
if (bri == nightlightTargetBri && callMode != CALL_MODE_NO_NOTIFY && nightlightMode != NL_MODE_SUN) nightlightActive = false;
|
||||
|
||||
// notify usermods of state change
|
||||
usermods.onStateChange(callMode);
|
||||
|
||||
if (fadeTransition) {
|
||||
//set correct delay if not using notification delay
|
||||
if (callMode != CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay; // load actual transition duration
|
||||
@ -167,10 +170,6 @@ void updateInterfaces(uint8_t callMode)
|
||||
espalexaDevice->setColor(col[0], col[1], col[2]);
|
||||
}
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
if (callMode != CALL_MODE_BLYNK &&
|
||||
callMode != CALL_MODE_NO_NOTIFY) updateBlynk();
|
||||
#endif
|
||||
doPublishMqtt = true;
|
||||
interfaceUpdateCallMode = 0; //disable
|
||||
}
|
||||
@ -275,9 +274,7 @@ void handleNightlight()
|
||||
applyFinalBri();
|
||||
}
|
||||
}
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
updateBlynk();
|
||||
#endif
|
||||
|
||||
if (macroNl > 0)
|
||||
applyPreset(macroNl);
|
||||
nightlightActiveOld = false;
|
||||
|
@ -3,7 +3,7 @@
|
||||
#ifdef WLED_DEBUG_HOST
|
||||
|
||||
size_t NetworkDebugPrinter::write(uint8_t c) {
|
||||
if (!WLED_CONNECTED) return 0;
|
||||
if (!WLED_CONNECTED || !netDebugEnabled) return 0;
|
||||
|
||||
if (!debugPrintHostIP && !debugPrintHostIP.fromString(netDebugPrintHost)) {
|
||||
#ifdef ESP8266
|
||||
@ -24,7 +24,7 @@ size_t NetworkDebugPrinter::write(uint8_t c) {
|
||||
}
|
||||
|
||||
size_t NetworkDebugPrinter::write(const uint8_t *buf, size_t size) {
|
||||
if (!WLED_CONNECTED || buf == nullptr) return 0;
|
||||
if (!WLED_CONNECTED || buf == nullptr || !netDebugEnabled) return 0;
|
||||
|
||||
if (!debugPrintHostIP && !debugPrintHostIP.fromString(netDebugPrintHost)) {
|
||||
#ifdef ESP8266
|
||||
|
@ -13,6 +13,7 @@ class NetworkDebugPrinter : public Print {
|
||||
virtual size_t write(const uint8_t *buf, size_t s);
|
||||
};
|
||||
|
||||
// use it on your linux/macOS with: nc -p 7868 -u -l -s <network ip>
|
||||
extern NetworkDebugPrinter NetDebug;
|
||||
|
||||
#endif
|
@ -144,8 +144,8 @@ void updateTimezone() {
|
||||
break;
|
||||
}
|
||||
case TZ_MX_CENTRAL : {
|
||||
tcrDaylight = {First, Sun, Apr, 2, -300}; //CDT = UTC - 5 hours
|
||||
tcrStandard = {Last, Sun, Oct, 2, -360}; //CST = UTC - 6 hours
|
||||
tcrDaylight = {First, Sun, Apr, 2, -360}; //CST = UTC - 6 hours
|
||||
tcrStandard = tcrDaylight;
|
||||
break;
|
||||
}
|
||||
case TZ_PAKISTAN : {
|
||||
|
@ -11,15 +11,15 @@ void _overlayAnalogClock()
|
||||
{
|
||||
_overlayAnalogCountdown(); return;
|
||||
}
|
||||
double hourP = ((double)(hour(localTime)%12))/12;
|
||||
double minuteP = ((double)minute(localTime))/60;
|
||||
hourP = hourP + minuteP/12;
|
||||
double secondP = ((double)second(localTime))/60;
|
||||
int hourPixel = floor(analogClock12pixel + overlaySize*hourP);
|
||||
float hourP = ((float)(hour(localTime)%12))/12.0f;
|
||||
float minuteP = ((float)minute(localTime))/60.0f;
|
||||
hourP = hourP + minuteP/12.0f;
|
||||
float secondP = ((float)second(localTime))/60.0f;
|
||||
int hourPixel = floorf(analogClock12pixel + overlaySize*hourP);
|
||||
if (hourPixel > overlayMax) hourPixel = overlayMin -1 + hourPixel - overlayMax;
|
||||
int minutePixel = floor(analogClock12pixel + overlaySize*minuteP);
|
||||
int minutePixel = floorf(analogClock12pixel + overlaySize*minuteP);
|
||||
if (minutePixel > overlayMax) minutePixel = overlayMin -1 + minutePixel - overlayMax;
|
||||
int secondPixel = floor(analogClock12pixel + overlaySize*secondP);
|
||||
int secondPixel = floorf(analogClock12pixel + overlaySize*secondP);
|
||||
if (secondPixel > overlayMax) secondPixel = overlayMin -1 + secondPixel - overlayMax;
|
||||
if (analogClockSecondsTrail)
|
||||
{
|
||||
@ -36,7 +36,7 @@ void _overlayAnalogClock()
|
||||
{
|
||||
for (byte i = 0; i <= 12; i++)
|
||||
{
|
||||
int pix = analogClock12pixel + round((overlaySize / 12.0) *i);
|
||||
int pix = analogClock12pixel + roundf((overlaySize / 12.0f) *i);
|
||||
if (pix > overlayMax) pix -= overlaySize;
|
||||
strip.setPixelColor(pix, 0x00FFAA);
|
||||
}
|
||||
@ -52,29 +52,29 @@ void _overlayAnalogCountdown()
|
||||
if ((unsigned long)toki.second() < countdownTime)
|
||||
{
|
||||
long diff = countdownTime - toki.second();
|
||||
double pval = 60;
|
||||
float pval = 60.0f;
|
||||
if (diff > 31557600L) //display in years if more than 365 days
|
||||
{
|
||||
pval = 315576000L; //10 years
|
||||
pval = 315576000.0f; //10 years
|
||||
} else if (diff > 2592000L) //display in months if more than a month
|
||||
{
|
||||
pval = 31557600L; //1 year
|
||||
pval = 31557600.0f; //1 year
|
||||
} else if (diff > 604800) //display in weeks if more than a week
|
||||
{
|
||||
pval = 2592000L; //1 month
|
||||
pval = 2592000.0f; //1 month
|
||||
} else if (diff > 86400) //display in days if more than 24 hours
|
||||
{
|
||||
pval = 604800; //1 week
|
||||
pval = 604800.0f; //1 week
|
||||
} else if (diff > 3600) //display in hours if more than 60 minutes
|
||||
{
|
||||
pval = 86400; //1 day
|
||||
pval = 86400.0f; //1 day
|
||||
} else if (diff > 60) //display in minutes if more than 60 seconds
|
||||
{
|
||||
pval = 3600; //1 hour
|
||||
pval = 3600.0f; //1 hour
|
||||
}
|
||||
int overlaySize = overlayMax - overlayMin +1;
|
||||
double perc = (pval-(double)diff)/pval;
|
||||
if (perc > 1.0) perc = 1.0;
|
||||
float perc = (pval-(float)diff)/pval;
|
||||
if (perc > 1.0f) perc = 1.0f;
|
||||
byte pixelCnt = perc*overlaySize;
|
||||
if (analogClock12pixel + pixelCnt > overlayMax)
|
||||
{
|
||||
|
@ -156,7 +156,7 @@ void serializePlaylist(JsonObject sObj) {
|
||||
JsonArray ps = playlist.createNestedArray("ps");
|
||||
JsonArray dur = playlist.createNestedArray("dur");
|
||||
JsonArray transition = playlist.createNestedArray(F("transition"));
|
||||
playlist[F("repeat")] = playlistRepeat;
|
||||
playlist[F("repeat")] = (playlistIndex < 0) ? playlistRepeat - 1 : playlistRepeat; // remove added repetition count (if not yet running)
|
||||
playlist["end"] = playlistEndPreset;
|
||||
playlist["r"] = playlistOptions & PL_OPTION_SHUFFLE;
|
||||
for (int i=0; i<playlistLen; i++) {
|
||||
|
@ -210,7 +210,7 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
|
||||
} else {
|
||||
// this is a playlist or API call
|
||||
if (sObj[F("playlist")].isNull()) {
|
||||
// we will save API call immediately
|
||||
// we will save API call immediately (often causes presets.json corruption)
|
||||
presetToSave = 0;
|
||||
if (index > 250 || !fileDoc) return; // cannot save API calls to temporary preset (255)
|
||||
sObj.remove("o");
|
||||
@ -220,11 +220,12 @@ void savePreset(byte index, const char* pname, JsonObject sObj)
|
||||
sObj.remove(F("psave"));
|
||||
if (sObj["n"].isNull()) sObj["n"] = saveName;
|
||||
initPresetsFile(); // just in case if someone deleted presets.json using /edit
|
||||
writeObjectToFileUsingId(getFileName(index), index, fileDoc);
|
||||
writeObjectToFileUsingId(getFileName(index<255), index, fileDoc);
|
||||
presetsModifiedTime = toki.second(); //unix time
|
||||
updateFSInfo();
|
||||
} else {
|
||||
// store playlist
|
||||
// WARNING: playlist will be loaded in json.cpp after this call and will have repeat counter increased by 1
|
||||
includeBri = true; // !sObj["on"].isNull();
|
||||
playlistSave = true;
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
cctFromRgb = request->hasArg(F("CR"));
|
||||
strip.cctBlending = request->arg(F("CB")).toInt();
|
||||
Bus::setCCTBlend(strip.cctBlending);
|
||||
Bus::setAutoWhiteMode(request->arg(F("AW")).toInt());
|
||||
Bus::setGlobalAWMode(request->arg(F("AW")).toInt());
|
||||
strip.setTargetFps(request->arg(F("FR")).toInt());
|
||||
strip.useLedsArray = request->hasArg(F("LD"));
|
||||
|
||||
@ -208,11 +208,21 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (t <= 250) bootPreset = t;
|
||||
gammaCorrectBri = request->hasArg(F("GB"));
|
||||
gammaCorrectCol = request->hasArg(F("GC"));
|
||||
gammaCorrectVal = request->arg(F("GV")).toFloat();
|
||||
if (gammaCorrectVal > 1.0f && gammaCorrectVal <= 3)
|
||||
calcGammaTable(gammaCorrectVal);
|
||||
else {
|
||||
gammaCorrectVal = 1.0f; // no gamma correction
|
||||
gammaCorrectBri = false;
|
||||
gammaCorrectCol = false;
|
||||
}
|
||||
|
||||
fadeTransition = request->hasArg(F("TF"));
|
||||
t = request->arg(F("TD")).toInt();
|
||||
if (t >= 0) transitionDelayDefault = t;
|
||||
strip.paletteFade = request->hasArg(F("PF"));
|
||||
t = request->arg(F("TP")).toInt();
|
||||
randomPaletteChangeTime = MIN(255,MAX(1,t));
|
||||
|
||||
nightlightTargetBri = request->arg(F("TB")).toInt();
|
||||
t = request->arg(F("TL")).toInt();
|
||||
@ -240,6 +250,10 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
}
|
||||
simplifiedUI = request->hasArg(F("SU"));
|
||||
#endif
|
||||
DEBUG_PRINTLN(F("Enumerating ledmaps"));
|
||||
enumerateLedmaps();
|
||||
DEBUG_PRINTLN(F("Loading custom palettes"));
|
||||
strip.loadCustomPalettes(); // (re)load all custom palettes
|
||||
}
|
||||
|
||||
//SYNC
|
||||
@ -286,6 +300,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (t >= 0 && t <= 510) DMXAddress = t;
|
||||
t = request->arg(F("XX")).toInt();
|
||||
if (t >= 0 && t <= 150) DMXSegmentSpacing = t;
|
||||
t = request->arg(F("PY")).toInt();
|
||||
if (t >= 0 && t <= 200) e131Priority = t;
|
||||
t = request->arg(F("DM")).toInt();
|
||||
if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_PRESET) DMXMode = t;
|
||||
t = request->arg(F("ET")).toInt();
|
||||
@ -300,16 +316,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
t = request->arg(F("AP")).toInt();
|
||||
if (t >= 0 && t <= 9) alexaNumPresets = t;
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
strlcpy(blynkHost, request->arg("BH").c_str(), 33);
|
||||
t = request->arg(F("BP")).toInt();
|
||||
if (t > 0) blynkPort = t;
|
||||
|
||||
if (request->hasArg("BK") && !request->arg("BK").equals(F("Hidden"))) {
|
||||
strlcpy(blynkApiKey, request->arg("BK").c_str(), 36); initBlynk(blynkApiKey, blynkHost, blynkPort);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
mqttEnabled = request->hasArg(F("MQ"));
|
||||
strlcpy(mqttServer, request->arg(F("MS")).c_str(), 33);
|
||||
@ -409,15 +415,15 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
k[0] = 'W'; //weekdays
|
||||
timerWeekday[i] = request->arg(k).toInt();
|
||||
if (i<8) {
|
||||
k[0] = 'M'; //start month
|
||||
timerMonth[i] = request->arg(k).toInt() & 0x0F;
|
||||
timerMonth[i] <<= 4;
|
||||
k[0] = 'P'; //end month
|
||||
timerMonth[i] += (request->arg(k).toInt() & 0x0F);
|
||||
k[0] = 'D'; //start day
|
||||
timerDay[i] = request->arg(k).toInt();
|
||||
k[0] = 'E'; //end day
|
||||
timerDayEnd[i] = request->arg(k).toInt();
|
||||
k[0] = 'M'; //start month
|
||||
timerMonth[i] = request->arg(k).toInt() & 0x0F;
|
||||
timerMonth[i] <<= 4;
|
||||
k[0] = 'P'; //end month
|
||||
timerMonth[i] += (request->arg(k).toInt() & 0x0F);
|
||||
k[0] = 'D'; //start day
|
||||
timerDay[i] = request->arg(k).toInt();
|
||||
k[0] = 'E'; //end day
|
||||
timerDayEnd[i] = request->arg(k).toInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -645,15 +651,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (subPage == 10)
|
||||
{
|
||||
strip.isMatrix = request->arg(F("SOMP")).toInt();
|
||||
// strip.panelH = MAX(1,MIN(128,request->arg(F("PH")).toInt()));
|
||||
// strip.panelW = MAX(1,MIN(128,request->arg(F("PW")).toInt()));
|
||||
strip.panel.clear(); // release memory if allocated
|
||||
if (strip.isMatrix) {
|
||||
strip.panels = MAX(1,MIN(WLED_MAX_PANELS,request->arg(F("MPC")).toInt()));
|
||||
strip.matrix.bottomStart = request->arg(F("PB")).toInt();
|
||||
strip.matrix.rightStart = request->arg(F("PR")).toInt();
|
||||
strip.matrix.vertical = request->arg(F("PV")).toInt();
|
||||
strip.matrix.serpentine = request->hasArg(F("PS"));
|
||||
strip.panel.reserve(strip.panels); // pre-allocate memory
|
||||
for (uint8_t i=0; i<strip.panels; i++) {
|
||||
WS2812FX::Panel p;
|
||||
@ -673,11 +673,13 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
pO[l] = 'H'; p.height = request->arg(pO).toInt();
|
||||
strip.panel.push_back(p);
|
||||
}
|
||||
strip.setUpMatrix(); // will check limits
|
||||
strip.makeAutoSegments(true);
|
||||
strip.deserializeMap();
|
||||
} else {
|
||||
Segment::maxWidth = strip.getLengthTotal();
|
||||
Segment::maxHeight = 1;
|
||||
}
|
||||
strip.setUpMatrix(); // will check limits
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -800,7 +802,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
||||
|
||||
//apply preset
|
||||
if (updateVal(req.c_str(), "PL=", &presetCycCurr, presetCycMin, presetCycMax)) {
|
||||
unloadPlaylist();
|
||||
unloadPlaylist();
|
||||
applyPreset(presetCycCurr);
|
||||
}
|
||||
|
||||
|
@ -1,321 +0,0 @@
|
||||
/**
|
||||
* @file BlynkApi.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Jan 2015
|
||||
* @brief High-level functions
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkApi_h
|
||||
#define BlynkApi_h
|
||||
|
||||
#include "BlynkConfig.h"
|
||||
#include "BlynkDebug.h"
|
||||
#include "BlynkParam.h"
|
||||
#include "BlynkTimer.h"
|
||||
#include "BlynkHandlers.h"
|
||||
#include "BlynkProtocolDefs.h"
|
||||
|
||||
#if defined(BLYNK_EXPERIMENTAL)
|
||||
#include <Blynk/BlynkEveryN.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Represents high-level functions of Blynk
|
||||
*/
|
||||
template <class Proto>
|
||||
class BlynkApi
|
||||
{
|
||||
public:
|
||||
BlynkApi() {
|
||||
}
|
||||
|
||||
#ifdef DOXYGEN // These API here are only for the documentation
|
||||
|
||||
/**
|
||||
* Connects to the server.
|
||||
* Blocks until connected or timeout happens.
|
||||
* May take less or more then timeout value.
|
||||
*
|
||||
* @param timeout Connection timeout
|
||||
* @returns True if connected to the server
|
||||
*/
|
||||
bool connect(unsigned long timeout = BLYNK_TIMEOUT_MS*3);
|
||||
|
||||
/**
|
||||
* Disconnects from the server.
|
||||
* It will not try to reconnect, until connect() is called
|
||||
*/
|
||||
void disconnect();
|
||||
|
||||
/**
|
||||
* @returns True if connected to the server
|
||||
*/
|
||||
bool connected();
|
||||
|
||||
/**
|
||||
* Performs Blynk-related housekeeping
|
||||
* and processes incoming commands
|
||||
*
|
||||
* @param available True if there is incoming data to process
|
||||
* Only used when user manages connection manually.
|
||||
*/
|
||||
bool run(bool available = false);
|
||||
|
||||
#endif // DOXYGEN
|
||||
|
||||
/**
|
||||
* Sends value to a Virtual Pin
|
||||
*
|
||||
* @param pin Virtual Pin number
|
||||
* @param data Value to be sent
|
||||
*/
|
||||
template <typename... Args>
|
||||
void virtualWrite(int pin, Args... values) {
|
||||
char mem[BLYNK_MAX_SENDBYTES];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add("vw");
|
||||
cmd.add(pin);
|
||||
cmd.add_multi(values...);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_HARDWARE, 0, cmd.getBuffer(), cmd.getLength()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends buffer to a Virtual Pin
|
||||
*
|
||||
* @param pin Virtual Pin number
|
||||
* @param buff Data buffer
|
||||
* @param len Length of data
|
||||
*/
|
||||
void virtualWriteBinary(int pin, const void* buff, size_t len) {
|
||||
char mem[8];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add("vw");
|
||||
cmd.add(pin);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_HARDWARE, 0, cmd.getBuffer(), cmd.getLength(), buff, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends BlynkParam to a Virtual Pin
|
||||
*
|
||||
* @param pin Virtual Pin number
|
||||
* @param param
|
||||
*/
|
||||
void virtualWrite(int pin, const BlynkParam& param) {
|
||||
virtualWriteBinary(pin, param.getBuffer(), param.getLength());
|
||||
}
|
||||
|
||||
void virtualWrite(int pin, const BlynkParamAllocated& param) {
|
||||
virtualWriteBinary(pin, param.getBuffer(), param.getLength());
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests Server to re-send current values for all widgets.
|
||||
*/
|
||||
void syncAll() {
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_HARDWARE_SYNC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends internal command
|
||||
*/
|
||||
template <typename... Args>
|
||||
void sendInternal(Args... params) {
|
||||
char mem[BLYNK_MAX_SENDBYTES];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add_multi(params...);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_INTERNAL, 0, cmd.getBuffer(), cmd.getLength()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests App or Server to re-send current value of a Virtual Pin.
|
||||
* This will probably cause user-defined BLYNK_WRITE handler to be called.
|
||||
*
|
||||
* @param pin Virtual Pin number
|
||||
*/
|
||||
template <typename... Args>
|
||||
void syncVirtual(Args... pins) {
|
||||
char mem[BLYNK_MAX_SENDBYTES];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add("vr");
|
||||
cmd.add_multi(pins...);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_HARDWARE_SYNC, 0, cmd.getBuffer(), cmd.getLength()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tweets a message
|
||||
*
|
||||
* @param msg Text of the message
|
||||
*/
|
||||
template<typename T>
|
||||
void tweet(const T& msg) {
|
||||
char mem[BLYNK_MAX_SENDBYTES];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add(msg);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_TWEET, 0, cmd.getBuffer(), cmd.getLength()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a push notification to the App
|
||||
*
|
||||
* @param msg Text of the message
|
||||
*/
|
||||
template<typename T>
|
||||
void notify(const T& msg) {
|
||||
char mem[BLYNK_MAX_SENDBYTES];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add(msg);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_NOTIFY, 0, cmd.getBuffer(), cmd.getLength()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an SMS
|
||||
*
|
||||
* @param msg Text of the message
|
||||
*/
|
||||
template<typename T>
|
||||
void sms(const T& msg) {
|
||||
char mem[BLYNK_MAX_SENDBYTES];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add(msg);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_SMS, 0, cmd.getBuffer(), cmd.getLength()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an email message
|
||||
*
|
||||
* @param email Email to send to
|
||||
* @param subject Subject of message
|
||||
* @param msg Text of the message
|
||||
*/
|
||||
template <typename T1, typename T2>
|
||||
void email(const char* email, const T1& subject, const T2& msg) {
|
||||
char mem[BLYNK_MAX_SENDBYTES];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add(email);
|
||||
cmd.add(subject);
|
||||
cmd.add(msg);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_EMAIL, 0, cmd.getBuffer(), cmd.getLength()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an email message
|
||||
*
|
||||
* @param subject Subject of message
|
||||
* @param msg Text of the message
|
||||
*/
|
||||
template <typename T1, typename T2>
|
||||
void email(const T1& subject, const T2& msg) {
|
||||
char mem[BLYNK_MAX_SENDBYTES];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add(subject);
|
||||
cmd.add(msg);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_EMAIL, 0, cmd.getBuffer(), cmd.getLength()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets property of a Widget
|
||||
*
|
||||
* @experimental
|
||||
*
|
||||
* @param pin Virtual Pin number
|
||||
* @param property Property name ("label", "labels", "color", ...)
|
||||
* @param value Property value
|
||||
*/
|
||||
template <typename T, typename... Args>
|
||||
void setProperty(int pin, const T& property, Args... values) {
|
||||
char mem[BLYNK_MAX_SENDBYTES];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add(pin);
|
||||
cmd.add(property);
|
||||
cmd.add_multi(values...);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_PROPERTY, 0, cmd.getBuffer(), cmd.getLength()-1);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void setProperty(int pin, const T& property, const BlynkParam& param) {
|
||||
char mem[32];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add(pin);
|
||||
cmd.add(property);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_PROPERTY, 0, cmd.getBuffer(), cmd.getLength(), param.getBuffer(), param.getLength());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void setProperty(int pin, const T& property, const BlynkParamAllocated& param) {
|
||||
char mem[32];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add(pin);
|
||||
cmd.add(property);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_PROPERTY, 0, cmd.getBuffer(), cmd.getLength(), param.getBuffer(), param.getLength());
|
||||
}
|
||||
|
||||
template <typename NAME>
|
||||
void logEvent(const NAME& event_name) {
|
||||
char mem[BLYNK_MAX_SENDBYTES];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add(event_name);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_EVENT_LOG, 0, cmd.getBuffer(), cmd.getLength());
|
||||
}
|
||||
|
||||
template <typename NAME, typename DESCR>
|
||||
void logEvent(const NAME& event_name, const DESCR& description) {
|
||||
char mem[BLYNK_MAX_SENDBYTES];
|
||||
BlynkParam cmd(mem, 0, sizeof(mem));
|
||||
cmd.add(event_name);
|
||||
cmd.add(description);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_EVENT_LOG, 0, cmd.getBuffer(), cmd.getLength());
|
||||
}
|
||||
|
||||
#if defined(BLYNK_EXPERIMENTAL)
|
||||
// Attention!
|
||||
// Every function in this section may be changed, removed or renamed.
|
||||
|
||||
/**
|
||||
* Refreshes value of a widget by running
|
||||
* user-defined BLYNK_READ handler of a pin.
|
||||
*
|
||||
* @experimental
|
||||
*
|
||||
* @param pin Virtual Pin number
|
||||
*/
|
||||
void refresh(int pin) {
|
||||
if (WidgetReadHandler handler = GetReadHandler(pin)) {
|
||||
BlynkReq req = { 0, BLYNK_SUCCESS, (uint8_t)pin };
|
||||
handler(req);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delays for N milliseconds, handling server communication in background.
|
||||
*
|
||||
* @experimental
|
||||
* @warning Should be used very carefully, especially on platforms with small RAM.
|
||||
*
|
||||
* @param ms Milliseconds to wait
|
||||
*/
|
||||
void delay(unsigned long ms) {
|
||||
uint16_t start = (uint16_t)micros();
|
||||
while (ms > 0) {
|
||||
static_cast<Proto*>(this)->run();
|
||||
#if !defined(BLYNK_NO_YIELD)
|
||||
yield();
|
||||
#endif
|
||||
if (((uint16_t)micros() - start) >= 1000) {
|
||||
ms--;
|
||||
start += 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void processCmd(const void* buff, size_t len);
|
||||
void sendInfo();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -1,199 +0,0 @@
|
||||
/**
|
||||
* @file BlynkApiArduino.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Mar 2015
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkApiArduino_h
|
||||
#define BlynkApiArduino_h
|
||||
|
||||
#include "BlynkApi.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
#ifdef BLYNK_NO_INFO
|
||||
|
||||
template<class Proto>
|
||||
BLYNK_FORCE_INLINE
|
||||
void BlynkApi<Proto>::sendInfo() {}
|
||||
|
||||
#else
|
||||
|
||||
template<class Proto>
|
||||
BLYNK_FORCE_INLINE
|
||||
void BlynkApi<Proto>::sendInfo()
|
||||
{
|
||||
static const char profile[] BLYNK_PROGMEM = "blnkinf\0"
|
||||
#ifdef BOARD_FIRMWARE_VERSION
|
||||
BLYNK_PARAM_KV("ver" , BOARD_FIRMWARE_VERSION)
|
||||
BLYNK_PARAM_KV("blynk" , BLYNK_VERSION)
|
||||
#else
|
||||
BLYNK_PARAM_KV("ver" , BLYNK_VERSION)
|
||||
#endif
|
||||
#ifdef BOARD_TEMPLATE_ID
|
||||
BLYNK_PARAM_KV("tmpl" , BOARD_TEMPLATE_ID)
|
||||
#endif
|
||||
BLYNK_PARAM_KV("h-beat" , BLYNK_TOSTRING(BLYNK_HEARTBEAT))
|
||||
BLYNK_PARAM_KV("buff-in", BLYNK_TOSTRING(BLYNK_MAX_READBYTES))
|
||||
#ifdef BLYNK_INFO_DEVICE
|
||||
BLYNK_PARAM_KV("dev" , BLYNK_INFO_DEVICE)
|
||||
#endif
|
||||
#ifdef BLYNK_INFO_CPU
|
||||
BLYNK_PARAM_KV("cpu" , BLYNK_INFO_CPU)
|
||||
#endif
|
||||
#ifdef BLYNK_INFO_CONNECTION
|
||||
BLYNK_PARAM_KV("con" , BLYNK_INFO_CONNECTION)
|
||||
#endif
|
||||
BLYNK_PARAM_KV("build" , __DATE__ " " __TIME__)
|
||||
"\0"
|
||||
;
|
||||
const size_t profile_len = sizeof(profile)-8-2;
|
||||
|
||||
#ifdef BLYNK_HAS_PROGMEM
|
||||
char mem[profile_len];
|
||||
memcpy_P(mem, profile+8, profile_len);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_INTERNAL, 0, mem, profile_len);
|
||||
#else
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_INTERNAL, 0, profile+8, profile_len);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Check if analog pins can be referenced by name on this device
|
||||
#if defined(analogInputToDigitalPin)
|
||||
#define BLYNK_DECODE_PIN(it) (((it).asStr()[0] == 'A') ? analogInputToDigitalPin(atoi((it).asStr()+1)) : (it).asInt())
|
||||
#else
|
||||
#define BLYNK_DECODE_PIN(it) ((it).asInt())
|
||||
|
||||
#if defined(BLYNK_DEBUG_ALL)
|
||||
#pragma message "analogInputToDigitalPin not defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template<class Proto>
|
||||
BLYNK_FORCE_INLINE
|
||||
void BlynkApi<Proto>::processCmd(const void* buff, size_t len)
|
||||
{
|
||||
BlynkParam param((void*)buff, len);
|
||||
BlynkParam::iterator it = param.begin();
|
||||
if (it >= param.end())
|
||||
return;
|
||||
const char* cmd = it.asStr();
|
||||
uint16_t cmd16;
|
||||
memcpy(&cmd16, cmd, sizeof(cmd16));
|
||||
if (++it >= param.end())
|
||||
return;
|
||||
|
||||
uint8_t pin = BLYNK_DECODE_PIN(it);
|
||||
|
||||
switch(cmd16) {
|
||||
|
||||
#ifndef BLYNK_NO_BUILTIN
|
||||
|
||||
case BLYNK_HW_PM: {
|
||||
while (it < param.end()) {
|
||||
pin = BLYNK_DECODE_PIN(it);
|
||||
++it;
|
||||
if (!strcmp(it.asStr(), "in")) {
|
||||
pinMode(pin, INPUT);
|
||||
} else if (!strcmp(it.asStr(), "out") || !strcmp(it.asStr(), "pwm")) {
|
||||
pinMode(pin, OUTPUT);
|
||||
#ifdef INPUT_PULLUP
|
||||
} else if (!strcmp(it.asStr(), "pu")) {
|
||||
pinMode(pin, INPUT_PULLUP);
|
||||
#endif
|
||||
#ifdef INPUT_PULLDOWN
|
||||
} else if (!strcmp(it.asStr(), "pd")) {
|
||||
pinMode(pin, INPUT_PULLDOWN);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef BLYNK_DEBUG
|
||||
BLYNK_LOG4(BLYNK_F("Invalid pin "), pin, BLYNK_F(" mode "), it.asStr());
|
||||
#endif
|
||||
}
|
||||
++it;
|
||||
}
|
||||
} break;
|
||||
case BLYNK_HW_DR: {
|
||||
char mem[16];
|
||||
BlynkParam rsp(mem, 0, sizeof(mem));
|
||||
rsp.add("dw");
|
||||
rsp.add(pin);
|
||||
rsp.add(digitalRead(pin));
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_HARDWARE, 0, rsp.getBuffer(), rsp.getLength()-1);
|
||||
} break;
|
||||
case BLYNK_HW_DW: {
|
||||
// Should be 1 parameter (value)
|
||||
if (++it >= param.end())
|
||||
return;
|
||||
|
||||
#ifdef ESP8266
|
||||
// Disable PWM...
|
||||
analogWrite(pin, 0);
|
||||
#endif
|
||||
#ifndef BLYNK_MINIMIZE_PINMODE_USAGE
|
||||
pinMode(pin, OUTPUT);
|
||||
#endif
|
||||
digitalWrite(pin, it.asInt() ? HIGH : LOW);
|
||||
} break;
|
||||
case BLYNK_HW_AR: {
|
||||
char mem[16];
|
||||
BlynkParam rsp(mem, 0, sizeof(mem));
|
||||
rsp.add("aw");
|
||||
rsp.add(pin);
|
||||
rsp.add(analogRead(pin));
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_HARDWARE, 0, rsp.getBuffer(), rsp.getLength()-1);
|
||||
} break;
|
||||
|
||||
// TODO: Remove workaround for ESP32
|
||||
#if !defined(ESP32)
|
||||
|
||||
case BLYNK_HW_AW: {
|
||||
// Should be 1 parameter (value)
|
||||
if (++it >= param.end())
|
||||
return;
|
||||
|
||||
#ifndef BLYNK_MINIMIZE_PINMODE_USAGE
|
||||
pinMode(pin, OUTPUT);
|
||||
#endif
|
||||
analogWrite(pin, it.asInt());
|
||||
} break;
|
||||
|
||||
#endif // TODO: Remove workaround for ESP32
|
||||
|
||||
#endif
|
||||
|
||||
case BLYNK_HW_VR: {
|
||||
BlynkReq req = { pin };
|
||||
WidgetReadHandler handler = GetReadHandler(pin);
|
||||
if (handler && (handler != BlynkWidgetRead)) {
|
||||
handler(req);
|
||||
} else {
|
||||
BlynkWidgetReadDefault(req);
|
||||
}
|
||||
} break;
|
||||
case BLYNK_HW_VW: {
|
||||
++it;
|
||||
char* start = (char*)it.asStr();
|
||||
BlynkParam param2(start, len - (start - (char*)buff));
|
||||
BlynkReq req = { pin };
|
||||
WidgetWriteHandler handler = GetWriteHandler(pin);
|
||||
if (handler && (handler != BlynkWidgetWrite)) {
|
||||
handler(req, param2);
|
||||
} else {
|
||||
BlynkWidgetWriteDefault(req, param2);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
BLYNK_LOG2(BLYNK_F("Invalid HW cmd: "), cmd);
|
||||
static_cast<Proto*>(this)->sendCmd(BLYNK_CMD_RESPONSE, static_cast<Proto*>(this)->msgIdOutOverride, NULL, BLYNK_ILLEGAL_COMMAND);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,128 +0,0 @@
|
||||
/**
|
||||
* @file BlynkParam.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Jan 2015
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkArduinoClient_h
|
||||
#define BlynkArduinoClient_h
|
||||
|
||||
#include "BlynkApiArduino.h"
|
||||
#include "BlynkDebug.h"
|
||||
#include <Client.h>
|
||||
|
||||
#if defined(ESP8266) && !defined(BLYNK_NO_YIELD)
|
||||
#define YIELD_FIX() BLYNK_RUN_YIELD();
|
||||
#else
|
||||
#define YIELD_FIX()
|
||||
#endif
|
||||
|
||||
template <typename Client>
|
||||
class BlynkArduinoClientGen
|
||||
{
|
||||
public:
|
||||
BlynkArduinoClientGen(Client& c)
|
||||
: client(NULL), domain(NULL), port(0), isConn(false)
|
||||
{
|
||||
setClient(&c);
|
||||
}
|
||||
|
||||
BlynkArduinoClientGen()
|
||||
: client(NULL), domain(NULL), port(0), isConn(false)
|
||||
{}
|
||||
|
||||
void setClient(Client* c) {
|
||||
client = c;
|
||||
client->setTimeout(BLYNK_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
void begin(IPAddress a, uint16_t p) {
|
||||
domain = NULL;
|
||||
port = p;
|
||||
addr = a;
|
||||
}
|
||||
|
||||
void begin(const char* d, uint16_t p) {
|
||||
domain = d;
|
||||
port = p;
|
||||
}
|
||||
|
||||
bool connect() {
|
||||
if (domain) {
|
||||
BLYNK_LOG4(BLYNK_F("Connecting to "), domain, ':', port);
|
||||
|
||||
isConn = (1 == client->connect(domain, port));
|
||||
return isConn;
|
||||
} else { //if (uint32_t(addr) != 0) {
|
||||
BLYNK_LOG_IP("Connecting to ", addr);
|
||||
isConn = (1 == client->connect(addr, port));
|
||||
return isConn;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void disconnect() { isConn = false; client->stop(); }
|
||||
|
||||
#ifdef BLYNK_ENC28J60_FIX
|
||||
size_t read(void* buf, size_t len) {
|
||||
while (client->available() < len) { BLYNK_RUN_YIELD(); }
|
||||
return client->read((uint8_t*)buf, len);
|
||||
}
|
||||
#else
|
||||
size_t read(void* buf, size_t len) {
|
||||
size_t res = client->readBytes((char*)buf, len);
|
||||
YIELD_FIX();
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BLYNK_RETRY_SEND
|
||||
size_t write(const void* buf, size_t len) {
|
||||
size_t sent = 0;
|
||||
int retry = 0;
|
||||
while (sent < len && ++retry < 10) {
|
||||
size_t w = client->write((const uint8_t*)buf+sent, len-sent);
|
||||
if (w != 0 && w != -1) {
|
||||
sent += w;
|
||||
} else {
|
||||
BlynkDelay(50);
|
||||
#if defined(BLYNK_DEBUG) && defined(BLYNK_PRINT)
|
||||
BLYNK_PRINT_TIME();
|
||||
BLYNK_PRINT.print(BLYNK_F("Retry "));
|
||||
BLYNK_PRINT.print(retry);
|
||||
BLYNK_PRINT.print(BLYNK_F(" send: "));
|
||||
BLYNK_PRINT.print(sent);
|
||||
BLYNK_PRINT.print('/');
|
||||
BLYNK_PRINT.println(len);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
#else
|
||||
size_t write(const void* buf, size_t len) {
|
||||
YIELD_FIX();
|
||||
size_t res = client->write((const uint8_t*)buf, len);
|
||||
YIELD_FIX();
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool connected() { YIELD_FIX(); return isConn && client->connected(); }
|
||||
int available() { YIELD_FIX(); return client->available(); }
|
||||
|
||||
protected:
|
||||
Client* client;
|
||||
IPAddress addr;
|
||||
const char* domain;
|
||||
uint16_t port;
|
||||
bool isConn;
|
||||
};
|
||||
|
||||
typedef BlynkArduinoClientGen<Client> BlynkArduinoClient;
|
||||
|
||||
#endif
|
@ -1,95 +0,0 @@
|
||||
/**
|
||||
* @file BlynkConfig.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Jan 2015
|
||||
* @brief Configuration of different aspects of library
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkConfig_h
|
||||
#define BlynkConfig_h
|
||||
|
||||
#include "BlynkDetectDevice.h"
|
||||
|
||||
/***************************************************
|
||||
* Change these settings to match your need
|
||||
***************************************************/
|
||||
|
||||
#define BLYNK_DEFAULT_DOMAIN "blynk-cloud.com"
|
||||
#define BLYNK_DEFAULT_PORT 80
|
||||
#define BLYNK_DEFAULT_PORT_SSL 8441
|
||||
|
||||
/***************************************************
|
||||
* Professional settings
|
||||
***************************************************/
|
||||
// Library version.
|
||||
#define BLYNK_VERSION "0.5.3"
|
||||
|
||||
// Heartbeat period in seconds.
|
||||
#ifndef BLYNK_HEARTBEAT
|
||||
#define BLYNK_HEARTBEAT 10
|
||||
#endif
|
||||
|
||||
// Network timeout in milliseconds.
|
||||
#ifndef BLYNK_TIMEOUT_MS
|
||||
#define BLYNK_TIMEOUT_MS 2000UL
|
||||
#endif
|
||||
|
||||
// Limit the amount of outgoing commands per second.
|
||||
#ifndef BLYNK_MSG_LIMIT
|
||||
#define BLYNK_MSG_LIMIT 15
|
||||
#endif
|
||||
|
||||
// Limit the incoming command length.
|
||||
#ifndef BLYNK_MAX_READBYTES
|
||||
#define BLYNK_MAX_READBYTES 256
|
||||
#endif
|
||||
|
||||
// Limit the outgoing command length.
|
||||
#ifndef BLYNK_MAX_SENDBYTES
|
||||
#define BLYNK_MAX_SENDBYTES 128
|
||||
#endif
|
||||
|
||||
// Uncomment to use Let's Encrypt Root CA
|
||||
//#define BLYNK_SSL_USE_LETSENCRYPT
|
||||
|
||||
// Uncomment to disable built-in analog and digital operations.
|
||||
//#define BLYNK_NO_BUILTIN
|
||||
|
||||
// Uncomment to disable providing info about device to the server.
|
||||
//#define BLYNK_NO_INFO
|
||||
|
||||
// Uncomment to enable debug prints.
|
||||
//#define BLYNK_DEBUG
|
||||
|
||||
// Uncomment to force-enable 128 virtual pins
|
||||
//#define BLYNK_USE_128_VPINS
|
||||
|
||||
// Uncomment to disable fancy logo
|
||||
//#define BLYNK_NO_FANCY_LOGO
|
||||
|
||||
// Uncomment to enable 3D fancy logo
|
||||
//#define BLYNK_FANCY_LOGO_3D
|
||||
|
||||
// Uncomment to enable experimental functions.
|
||||
//#define BLYNK_EXPERIMENTAL
|
||||
|
||||
// Uncomment to disable all float/double usage
|
||||
//#define BLYNK_NO_FLOAT
|
||||
|
||||
// Uncomment to switch to direct-connect mode
|
||||
//#define BLYNK_USE_DIRECT_CONNECT
|
||||
|
||||
|
||||
// Uncomment to append command body to header (uses more RAM)
|
||||
//#define BLYNK_SEND_ATOMIC
|
||||
|
||||
// Split whole command into chunks (in bytes)
|
||||
//#define BLYNK_SEND_CHUNK 64
|
||||
|
||||
// Wait after sending each chunk (in milliseconds)
|
||||
//#define BLYNK_SEND_THROTTLE 10
|
||||
|
||||
#endif
|
@ -1,173 +0,0 @@
|
||||
/**
|
||||
* @file BlynkDateTime.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
|
||||
* @date Aug 2016
|
||||
* @brief DateTime implementation
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkDateTime_h
|
||||
#define BlynkDateTime_h
|
||||
|
||||
typedef long blynk_time_t;
|
||||
|
||||
struct blynk_tm *blynk_gmtime_r(const blynk_time_t *time, struct blynk_tm *tm);
|
||||
blynk_time_t blynk_mk_gmtime(struct blynk_tm *tm);
|
||||
|
||||
struct blynk_tm {
|
||||
int8_t tm_sec;
|
||||
int8_t tm_min;
|
||||
int8_t tm_hour;
|
||||
int8_t tm_mday;
|
||||
int8_t tm_wday;
|
||||
int8_t tm_mon;
|
||||
int16_t tm_year;
|
||||
int16_t tm_yday;
|
||||
int16_t tm_isdst;
|
||||
};
|
||||
|
||||
class BlynkTime {
|
||||
|
||||
public:
|
||||
static const uint32_t MAX_TIME = 86400L;
|
||||
|
||||
BlynkTime() : mTime(-1) {}
|
||||
|
||||
BlynkTime(const BlynkTime& t) : mTime(t.mTime) {}
|
||||
|
||||
BlynkTime(long seconds) : mTime(seconds % MAX_TIME) {}
|
||||
|
||||
BlynkTime(int hour, int minute, int second)
|
||||
{
|
||||
mTime = (hour * 3600 + minute * 60 + second) % MAX_TIME;
|
||||
}
|
||||
|
||||
int second() const { return mTime % 60; }
|
||||
int minute() const { return (mTime / 60) % 60; }
|
||||
int hour() const { return mTime / 3600; }
|
||||
|
||||
int hour12() const {
|
||||
int h = hour();
|
||||
if (h == 0)
|
||||
return 12; // 12 midnight
|
||||
else if (h > 12)
|
||||
return h - 12;
|
||||
return h;
|
||||
}
|
||||
|
||||
bool isAM() const { return !isPM(); }
|
||||
bool isPM() const { return (hour() >= 12); }
|
||||
|
||||
void adjustSeconds(int sec) {
|
||||
if (isValid()) {
|
||||
mTime = (mTime + sec) % MAX_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
blynk_time_t getUnixOffset() const { return mTime; }
|
||||
|
||||
bool isValid() const { return mTime < MAX_TIME; }
|
||||
operator bool() const { return isValid(); }
|
||||
|
||||
bool operator == (const BlynkTime& t) const { return mTime == t.mTime; }
|
||||
bool operator >= (const BlynkTime& t) const { return mTime >= t.mTime; }
|
||||
bool operator <= (const BlynkTime& t) const { return mTime <= t.mTime; }
|
||||
bool operator > (const BlynkTime& t) const { return mTime > t.mTime; }
|
||||
bool operator < (const BlynkTime& t) const { return mTime < t.mTime; }
|
||||
|
||||
private:
|
||||
uint32_t mTime;
|
||||
};
|
||||
|
||||
class BlynkDateTime {
|
||||
|
||||
public:
|
||||
BlynkDateTime() : mTime(0) {}
|
||||
|
||||
BlynkDateTime(const BlynkDateTime& t)
|
||||
{
|
||||
mTime = t.mTime;
|
||||
blynk_gmtime_r(&mTime, &mTm);
|
||||
}
|
||||
|
||||
BlynkDateTime(blynk_time_t t)
|
||||
{
|
||||
mTime = t;
|
||||
blynk_gmtime_r(&mTime, &mTm);
|
||||
}
|
||||
|
||||
BlynkDateTime(int hour, int minute, int second, int day, int month, int year)
|
||||
{
|
||||
mTm.tm_hour = hour;
|
||||
mTm.tm_min = minute;
|
||||
mTm.tm_sec = second;
|
||||
|
||||
mTm.tm_mday = day;
|
||||
mTm.tm_mon = month - 1;
|
||||
mTm.tm_year = year - 1900;
|
||||
|
||||
mTm.tm_isdst = 0;
|
||||
|
||||
mTime = blynk_mk_gmtime(&mTm);
|
||||
}
|
||||
|
||||
int second() const { return mTm.tm_sec; }
|
||||
int minute() const { return mTm.tm_min; }
|
||||
int hour() const { return mTm.tm_hour; }
|
||||
int day() const { return mTm.tm_mday; }
|
||||
int month() const { return 1 + mTm.tm_mon; }
|
||||
int year() const { return 1900 + mTm.tm_year; }
|
||||
|
||||
int day_of_year() const { return 1 + mTm.tm_yday; }
|
||||
int day_of_week() const { return mTm.tm_wday == 0 ? 7 : mTm.tm_wday; }
|
||||
|
||||
/*int weak_of_year() const {
|
||||
int julian = day_of_year();
|
||||
int dow = day_of_week();
|
||||
int dowJan1 = BlynkDateTime(0,0,0, 1,1,year()).day_of_week();
|
||||
int weekNum = ((julian + 6) / 7);
|
||||
if (dow < dowJan1)
|
||||
++weekNum;
|
||||
return (weekNum);
|
||||
}*/
|
||||
|
||||
int hour12() const {
|
||||
int h = hour();
|
||||
if (h == 0)
|
||||
return 12; // 12 midnight
|
||||
else if (h > 12)
|
||||
return h - 12;
|
||||
return h;
|
||||
}
|
||||
|
||||
bool isAM() const { return !isPM(); }
|
||||
bool isPM() const { return (hour() >= 12); }
|
||||
|
||||
void adjustSeconds(int sec) {
|
||||
if (isValid()) {
|
||||
mTime += sec;
|
||||
blynk_gmtime_r(&mTime, &mTm);
|
||||
}
|
||||
}
|
||||
|
||||
//tm& getTm() { return mTm; }
|
||||
blynk_time_t getUnix() const { return mTime; }
|
||||
|
||||
bool isValid() const { return mTime != 0; }
|
||||
operator bool() const { return isValid(); }
|
||||
|
||||
bool operator == (const BlynkDateTime& t) const { return mTime == t.mTime; }
|
||||
bool operator >= (const BlynkDateTime& t) const { return mTime >= t.mTime; }
|
||||
bool operator <= (const BlynkDateTime& t) const { return mTime <= t.mTime; }
|
||||
bool operator > (const BlynkDateTime& t) const { return mTime > t.mTime; }
|
||||
bool operator < (const BlynkDateTime& t) const { return mTime < t.mTime; }
|
||||
|
||||
private:
|
||||
blynk_tm mTm;
|
||||
blynk_time_t mTime;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -1,278 +0,0 @@
|
||||
/**
|
||||
* @file BlynkDebug.cpp
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Jan 2015
|
||||
* @brief Debug utilities for Arduino
|
||||
*/
|
||||
#include "BlynkDebug.h"
|
||||
|
||||
#if defined(ARDUINO) && defined(__AVR__) && defined(BLYNK_USE_AVR_WDT)
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <avr/wdt.h>
|
||||
|
||||
BLYNK_CONSTRUCTOR
|
||||
static void BlynkSystemInit()
|
||||
{
|
||||
MCUSR = 0;
|
||||
wdt_disable();
|
||||
}
|
||||
|
||||
void BlynkReset()
|
||||
{
|
||||
wdt_enable(WDTO_15MS);
|
||||
delay(50);
|
||||
void(*resetFunc)(void) = 0;
|
||||
resetFunc();
|
||||
for(;;) {} // To make compiler happy
|
||||
}
|
||||
|
||||
size_t BlynkFreeRam()
|
||||
{
|
||||
extern int __heap_start, *__brkval;
|
||||
int v;
|
||||
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
|
||||
}
|
||||
|
||||
#define _BLYNK_USE_DEFAULT_MILLIS
|
||||
#define _BLYNK_USE_DEFAULT_DELAY
|
||||
|
||||
#elif defined(ARDUINO) && defined(__AVR__)
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
void BlynkReset()
|
||||
{
|
||||
void(*resetFunc)(void) = 0;
|
||||
resetFunc();
|
||||
for(;;) {}
|
||||
}
|
||||
|
||||
size_t BlynkFreeRam()
|
||||
{
|
||||
extern int __heap_start, *__brkval;
|
||||
int v;
|
||||
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
|
||||
}
|
||||
|
||||
#define _BLYNK_USE_DEFAULT_MILLIS
|
||||
#define _BLYNK_USE_DEFAULT_DELAY
|
||||
|
||||
#elif defined(ARDUINO) && defined(ESP8266)
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
size_t BlynkFreeRam()
|
||||
{
|
||||
return ESP.getFreeHeap();
|
||||
}
|
||||
|
||||
void BlynkReset()
|
||||
{
|
||||
ESP.restart();
|
||||
for(;;) {}
|
||||
}
|
||||
|
||||
#define _BLYNK_USE_DEFAULT_MILLIS
|
||||
#define _BLYNK_USE_DEFAULT_DELAY
|
||||
|
||||
#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM)
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
size_t BlynkFreeRam()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BlynkReset()
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
for(;;) {}
|
||||
}
|
||||
|
||||
#define _BLYNK_USE_DEFAULT_MILLIS
|
||||
#define _BLYNK_USE_DEFAULT_DELAY
|
||||
|
||||
#elif defined (ARDUINO_ARCH_ARC32)
|
||||
|
||||
millis_time_t BlynkMillis()
|
||||
{
|
||||
// TODO: Remove workaround for Intel Curie
|
||||
// https://forum.arduino.cc/index.php?topic=391836.0
|
||||
noInterrupts();
|
||||
uint64_t t = millis();
|
||||
interrupts();
|
||||
return t;
|
||||
}
|
||||
|
||||
#define _BLYNK_USE_DEFAULT_FREE_RAM
|
||||
#define _BLYNK_USE_DEFAULT_RESET
|
||||
#define _BLYNK_USE_DEFAULT_DELAY
|
||||
|
||||
#elif defined(ARDUINO) && (defined(__STM32F1__) || defined(__STM32F3__))
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <libmaple/nvic.h>
|
||||
|
||||
void BlynkReset()
|
||||
{
|
||||
nvic_sys_reset();
|
||||
for(;;) {}
|
||||
}
|
||||
|
||||
#define _BLYNK_USE_DEFAULT_FREE_RAM
|
||||
#define _BLYNK_USE_DEFAULT_MILLIS
|
||||
#define _BLYNK_USE_DEFAULT_DELAY
|
||||
|
||||
#elif defined (PARTICLE) || defined(SPARK)
|
||||
|
||||
#include "application.h"
|
||||
|
||||
void BlynkReset()
|
||||
{
|
||||
System.reset();
|
||||
for(;;) {} // To make compiler happy
|
||||
}
|
||||
|
||||
#define _BLYNK_USE_DEFAULT_FREE_RAM
|
||||
#define _BLYNK_USE_DEFAULT_MILLIS
|
||||
#define _BLYNK_USE_DEFAULT_DELAY
|
||||
|
||||
#elif defined(__MBED__)
|
||||
|
||||
#include "mbed.h"
|
||||
|
||||
static Timer blynk_millis_timer;
|
||||
static Ticker blynk_waker;
|
||||
|
||||
static
|
||||
void blynk_wake() {
|
||||
//pc.puts("(...)");
|
||||
}
|
||||
|
||||
BLYNK_CONSTRUCTOR
|
||||
static void BlynkSystemInit()
|
||||
{
|
||||
blynk_waker.attach(&blynk_wake, 2.0);
|
||||
blynk_millis_timer.start();
|
||||
}
|
||||
|
||||
void BlynkDelay(millis_time_t ms)
|
||||
{
|
||||
wait_ms(ms);
|
||||
}
|
||||
|
||||
millis_time_t BlynkMillis()
|
||||
{
|
||||
return blynk_millis_timer.read_ms();
|
||||
}
|
||||
|
||||
#define _BLYNK_USE_DEFAULT_FREE_RAM
|
||||
#define _BLYNK_USE_DEFAULT_RESET
|
||||
|
||||
#elif defined(LINUX) && defined(RASPBERRY)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <wiringPi.h>
|
||||
|
||||
BLYNK_CONSTRUCTOR
|
||||
static void BlynkSystemInit()
|
||||
{
|
||||
wiringPiSetupGpio();
|
||||
}
|
||||
|
||||
void BlynkReset()
|
||||
{
|
||||
exit(1);
|
||||
for(;;) {} // To make compiler happy
|
||||
}
|
||||
|
||||
#define _BLYNK_USE_DEFAULT_FREE_RAM
|
||||
#define _BLYNK_USE_DEFAULT_MILLIS
|
||||
#define _BLYNK_USE_DEFAULT_DELAY
|
||||
|
||||
#elif defined(LINUX)
|
||||
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static millis_time_t blynk_startup_time = 0;
|
||||
|
||||
BLYNK_CONSTRUCTOR
|
||||
static void BlynkSystemInit()
|
||||
{
|
||||
blynk_startup_time = BlynkMillis();
|
||||
}
|
||||
|
||||
void BlynkReset()
|
||||
{
|
||||
exit(1);
|
||||
for(;;) {} // To make compiler happy
|
||||
}
|
||||
|
||||
void BlynkDelay(millis_time_t ms)
|
||||
{
|
||||
usleep(ms * 1000);
|
||||
}
|
||||
|
||||
millis_time_t BlynkMillis()
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts );
|
||||
return ( ts.tv_sec * 1000 + ts.tv_nsec / 1000000L ) - blynk_startup_time;
|
||||
}
|
||||
|
||||
#define _BLYNK_USE_DEFAULT_FREE_RAM
|
||||
|
||||
#else
|
||||
|
||||
#if defined(BLYNK_DEBUG_ALL)
|
||||
#warning "Need to implement board-specific utilities"
|
||||
#endif
|
||||
|
||||
#define _BLYNK_USE_DEFAULT_FREE_RAM
|
||||
#define _BLYNK_USE_DEFAULT_RESET
|
||||
#define _BLYNK_USE_DEFAULT_MILLIS
|
||||
#define _BLYNK_USE_DEFAULT_DELAY
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _BLYNK_USE_DEFAULT_DELAY
|
||||
void BlynkDelay(millis_time_t ms)
|
||||
{
|
||||
return delay(ms);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _BLYNK_USE_DEFAULT_MILLIS
|
||||
millis_time_t BlynkMillis()
|
||||
{
|
||||
return millis();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _BLYNK_USE_DEFAULT_FREE_RAM
|
||||
size_t BlynkFreeRam()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _BLYNK_USE_DEFAULT_RESET
|
||||
void BlynkReset()
|
||||
{
|
||||
for(;;) {} // To make compiler happy
|
||||
}
|
||||
#endif
|
||||
|
||||
void BlynkFatal()
|
||||
{
|
||||
BlynkDelay(10000L);
|
||||
BlynkReset();
|
||||
}
|
||||
|
@ -1,305 +0,0 @@
|
||||
/**
|
||||
* @file BlynkDebug.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Jan 2015
|
||||
* @brief Debug utilities
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkDebug_h
|
||||
#define BlynkDebug_h
|
||||
|
||||
#include "BlynkConfig.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#ifdef ESP8266
|
||||
extern "C" {
|
||||
#include "ets_sys.h"
|
||||
#include "os_type.h"
|
||||
#include "mem.h"
|
||||
}
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_ARC32)
|
||||
typedef uint64_t millis_time_t;
|
||||
#else
|
||||
typedef uint32_t millis_time_t;
|
||||
#endif
|
||||
|
||||
void BlynkDelay(millis_time_t ms);
|
||||
millis_time_t BlynkMillis();
|
||||
size_t BlynkFreeRam();
|
||||
void BlynkReset() BLYNK_NORETURN;
|
||||
void BlynkFatal() BLYNK_NORETURN;
|
||||
|
||||
|
||||
#if defined(SPARK) || defined(PARTICLE)
|
||||
#include "application.h"
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO)
|
||||
#if ARDUINO >= 100
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(LINUX)
|
||||
#if defined(RASPBERRY)
|
||||
#include <wiringPi.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(BLYNK_RUN_YIELD)
|
||||
#if defined(BLYNK_NO_YIELD)
|
||||
#define BLYNK_RUN_YIELD() {}
|
||||
#elif defined(SPARK) || defined(PARTICLE)
|
||||
#define BLYNK_RUN_YIELD() { Particle.process(); }
|
||||
#elif !defined(ARDUINO) || (ARDUINO < 151)
|
||||
#define BLYNK_RUN_YIELD() {}
|
||||
#else
|
||||
#define BLYNK_RUN_YIELD() { BlynkDelay(0); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__AVR__)
|
||||
#include <avr/pgmspace.h>
|
||||
#define BLYNK_HAS_PROGMEM
|
||||
#define BLYNK_PROGMEM PROGMEM
|
||||
#define BLYNK_F(s) F(s)
|
||||
#define BLYNK_PSTR(s) PSTR(s)
|
||||
#else
|
||||
#define BLYNK_PROGMEM
|
||||
#define BLYNK_F(s) s
|
||||
#define BLYNK_PSTR(s) s
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO_AVR_DIGISPARK
|
||||
typedef fstr_t __FlashStringHelper;
|
||||
#endif
|
||||
|
||||
#if defined(BLYNK_DEBUG_ALL) && !(__cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||
#warning "Compiler features not enabled -> please contact yor board vendor to enable c++0x"
|
||||
#endif
|
||||
|
||||
// Diagnostic defines
|
||||
|
||||
#define BLYNK_FATAL(msg) { BLYNK_LOG1(msg); BlynkFatal(); }
|
||||
#define BLYNK_LOG_RAM() { BLYNK_LOG2(BLYNK_F("Free RAM: "), BlynkFreeRam()); }
|
||||
#define BLYNK_LOG_FN() BLYNK_LOG3(BLYNK_F(__FUNCTION__), '@', __LINE__);
|
||||
#define BLYNK_LOG_TROUBLE(t) BLYNK_LOG2(BLYNK_F("Trouble detected: http://docs.blynk.cc/#troubleshooting-"), t)
|
||||
|
||||
#ifndef BLYNK_PRINT
|
||||
#undef BLYNK_DEBUG
|
||||
#endif
|
||||
|
||||
#ifdef BLYNK_DEBUG_ALL
|
||||
#define BLYNK_DEBUG
|
||||
#endif
|
||||
|
||||
#ifdef BLYNK_PRINT
|
||||
|
||||
#if defined(ARDUINO) || defined(SPARK) || defined(PARTICLE)
|
||||
|
||||
#if defined(ARDUINO_ARCH_ARC32)
|
||||
// This will cause error - on purpose
|
||||
#define BLYNK_LOG(msg, ...) BLYNK_LOG_UNAVAILABLE(msg, ##__VA_ARGS__)
|
||||
#else
|
||||
#define BLYNK_LOG(msg, ...) blynk_dbg_print(BLYNK_PSTR(msg), ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define BLYNK_LOG1(p1) { BLYNK_LOG_TIME(); BLYNK_PRINT.println(p1); }
|
||||
#define BLYNK_LOG2(p1,p2) { BLYNK_LOG_TIME(); BLYNK_PRINT.print(p1); BLYNK_PRINT.println(p2); }
|
||||
#define BLYNK_LOG3(p1,p2,p3) { BLYNK_LOG_TIME(); BLYNK_PRINT.print(p1); BLYNK_PRINT.print(p2); BLYNK_PRINT.println(p3); }
|
||||
#define BLYNK_LOG4(p1,p2,p3,p4) { BLYNK_LOG_TIME(); BLYNK_PRINT.print(p1); BLYNK_PRINT.print(p2); BLYNK_PRINT.print(p3); BLYNK_PRINT.println(p4); }
|
||||
#define BLYNK_LOG6(p1,p2,p3,p4,p5,p6) { BLYNK_LOG_TIME(); BLYNK_PRINT.print(p1); BLYNK_PRINT.print(p2); BLYNK_PRINT.print(p3); BLYNK_PRINT.print(p4); BLYNK_PRINT.print(p5); BLYNK_PRINT.println(p6); }
|
||||
#define BLYNK_LOG_IP(msg, ip) { BLYNK_LOG_TIME(); BLYNK_PRINT.print(BLYNK_F(msg)); \
|
||||
BLYNK_PRINT.print(ip[0]); BLYNK_PRINT.print('.'); \
|
||||
BLYNK_PRINT.print(ip[1]); BLYNK_PRINT.print('.'); \
|
||||
BLYNK_PRINT.print(ip[2]); BLYNK_PRINT.print('.'); \
|
||||
BLYNK_PRINT.println(ip[3]); }
|
||||
#define BLYNK_LOG_IP_REV(msg, ip) { BLYNK_LOG_TIME(); BLYNK_PRINT.print(BLYNK_F(msg)); \
|
||||
BLYNK_PRINT.print(ip[3]); BLYNK_PRINT.print('.'); \
|
||||
BLYNK_PRINT.print(ip[2]); BLYNK_PRINT.print('.'); \
|
||||
BLYNK_PRINT.print(ip[1]); BLYNK_PRINT.print('.'); \
|
||||
BLYNK_PRINT.println(ip[0]); }
|
||||
|
||||
static
|
||||
void BLYNK_LOG_TIME() {
|
||||
BLYNK_PRINT.print('[');
|
||||
BLYNK_PRINT.print(BlynkMillis());
|
||||
BLYNK_PRINT.print(BLYNK_F("] "));
|
||||
}
|
||||
|
||||
#ifdef BLYNK_DEBUG
|
||||
#include <ctype.h>
|
||||
#define BLYNK_DBG_BREAK() { for(;;); }
|
||||
#define BLYNK_ASSERT(expr) { if(!(expr)) { BLYNK_LOG2(BLYNK_F("Assertion failed: "), BLYNK_F(#expr)); BLYNK_DBG_BREAK() } }
|
||||
|
||||
static
|
||||
void BLYNK_DBG_DUMP(const char* msg, const void* addr, size_t len) {
|
||||
if (len) {
|
||||
BLYNK_LOG_TIME();
|
||||
BLYNK_PRINT.print(msg);
|
||||
int l2 = len;
|
||||
const uint8_t* octets = (const uint8_t*)addr;
|
||||
bool prev_print = true;
|
||||
while (l2--) {
|
||||
const uint8_t c = *octets++ & 0xFF;
|
||||
if (c >= 32 && c < 127) {
|
||||
if (!prev_print) { BLYNK_PRINT.print(']'); }
|
||||
BLYNK_PRINT.print((char)c);
|
||||
prev_print = true;
|
||||
} else {
|
||||
BLYNK_PRINT.print(prev_print?'[':'|');
|
||||
if (c < 0x10) { BLYNK_PRINT.print('0'); }
|
||||
BLYNK_PRINT.print(c, HEX);
|
||||
prev_print = false;
|
||||
}
|
||||
}
|
||||
if (!prev_print) {
|
||||
BLYNK_PRINT.print(']');
|
||||
}
|
||||
BLYNK_PRINT.println();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(ARDUINO_ARCH_ARC32)
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
BLYNK_UNUSED
|
||||
void blynk_dbg_print(const char* BLYNK_PROGMEM fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
char buff[128];
|
||||
BLYNK_PRINT.print('[');
|
||||
BLYNK_PRINT.print(BlynkMillis());
|
||||
BLYNK_PRINT.print(BLYNK_F("] "));
|
||||
#if defined(__AVR__)
|
||||
vsnprintf_P(buff, sizeof(buff), fmt, ap);
|
||||
#else
|
||||
vsnprintf(buff, sizeof(buff), fmt, ap);
|
||||
#endif
|
||||
BLYNK_PRINT.println(buff);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif // ARDUINO_ARCH_ARC32
|
||||
|
||||
#elif defined(__MBED__)
|
||||
|
||||
#define BLYNK_LOG(msg, ...) { BLYNK_PRINT.printf("[%ld] " msg "\n", BlynkMillis(), ##__VA_ARGS__); }
|
||||
#define BLYNK_LOG1(p1) { BLYNK_LOG(p1);}
|
||||
#define BLYNK_LOG2(p1,p2) { BLYNK_LOG(p1,p2);}
|
||||
#define BLYNK_LOG3(p1,p2,p3) { BLYNK_LOG(p1,p2,p3);}
|
||||
#define BLYNK_LOG4(p1,p2,p3,p4) { BLYNK_LOG(p1,p2,p3,p4);}
|
||||
#define BLYNK_LOG6(p1,p2,p3,p4,p5,p6) { BLYNK_LOG(p1,p2,p3,p4,p5,p6);}
|
||||
|
||||
#define BLYNK_LOG_TIME() BLYNK_PRINT.printf("[%ld]", BlynkMillis());
|
||||
|
||||
#ifdef BLYNK_DEBUG
|
||||
#define BLYNK_DBG_BREAK() raise(SIGTRAP);
|
||||
#define BLYNK_ASSERT(expr) assert(expr)
|
||||
|
||||
static
|
||||
void BLYNK_DBG_DUMP(const char* msg, const void* addr, size_t len) {
|
||||
BLYNK_LOG_TIME();
|
||||
BLYNK_PRINT.printf(msg);
|
||||
int l2 = len;
|
||||
const uint8_t* octets = (const uint8_t*)addr;
|
||||
bool prev_print = true;
|
||||
while (l2--) {
|
||||
const uint8_t c = *octets++ & 0xFF;
|
||||
if (c >= 32 && c < 127) {
|
||||
if (!prev_print) { BLYNK_PRINT.putc(']'); }
|
||||
BLYNK_PRINT.putc((char)c);
|
||||
prev_print = true;
|
||||
} else {
|
||||
BLYNK_PRINT.putc(prev_print?'[':'|');
|
||||
BLYNK_PRINT.printf("%02x", c);
|
||||
prev_print = false;
|
||||
}
|
||||
}
|
||||
BLYNK_PRINT.printf("%s\n", prev_print?"":"]");
|
||||
}
|
||||
#endif
|
||||
|
||||
#elif defined(LINUX)
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
#define BLYNK_LOG(msg, ...) { fprintf(BLYNK_PRINT, "[%ld] " msg "\n", BlynkMillis(), ##__VA_ARGS__); }
|
||||
#define BLYNK_LOG1(p1) { BLYNK_LOG_TIME(); cout << p1 << endl; }
|
||||
#define BLYNK_LOG2(p1,p2) { BLYNK_LOG_TIME(); cout << p1 << p2 << endl; }
|
||||
#define BLYNK_LOG3(p1,p2,p3) { BLYNK_LOG_TIME(); cout << p1 << p2 << p3 << endl; }
|
||||
#define BLYNK_LOG4(p1,p2,p3,p4) { BLYNK_LOG_TIME(); cout << p1 << p2 << p3 << p4 << endl; }
|
||||
#define BLYNK_LOG6(p1,p2,p3,p4,p5,p6) { BLYNK_LOG_TIME(); cout << p1 << p2 << p3 << p4 << p5 << p6 << endl; }
|
||||
|
||||
#define BLYNK_LOG_TIME() cout << '[' << BlynkMillis() << "] ";
|
||||
|
||||
#ifdef BLYNK_DEBUG
|
||||
#define BLYNK_DBG_BREAK() raise(SIGTRAP);
|
||||
#define BLYNK_ASSERT(expr) assert(expr)
|
||||
|
||||
static
|
||||
void BLYNK_DBG_DUMP(const char* msg, const void* addr, size_t len) {
|
||||
BLYNK_LOG_TIME();
|
||||
fprintf(BLYNK_PRINT, "%s", msg);
|
||||
int l2 = len;
|
||||
const uint8_t* octets = (const uint8_t*)addr;
|
||||
bool prev_print = true;
|
||||
while (l2--) {
|
||||
const uint8_t c = *octets++ & 0xFF;
|
||||
if (c >= 32 && c < 127) {
|
||||
if (!prev_print) { fputc(']', BLYNK_PRINT); }
|
||||
fputc((char)c, BLYNK_PRINT);
|
||||
prev_print = true;
|
||||
} else {
|
||||
fputc(prev_print?'[':'|', BLYNK_PRINT);
|
||||
fprintf(BLYNK_PRINT, "%02x", c);
|
||||
prev_print = false;
|
||||
}
|
||||
}
|
||||
fprintf(BLYNK_PRINT, "%s\n", prev_print?"":"]");
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#warning "Cannot detect platform"
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef BLYNK_LOG
|
||||
#define BLYNK_LOG(...)
|
||||
#define BLYNK_LOG1(p1)
|
||||
#define BLYNK_LOG2(p1,p2)
|
||||
#define BLYNK_LOG3(p1,p2,p3)
|
||||
#define BLYNK_LOG4(p1,p2,p3,p4)
|
||||
#define BLYNK_LOG6(p1,p2,p3,p4,p5,p6)
|
||||
#define BLYNK_LOG_IP(msg, ip)
|
||||
#define BLYNK_LOG_IP_REV(msg, ip)
|
||||
#endif
|
||||
|
||||
#ifndef BLYNK_DBG_BREAK
|
||||
#define BLYNK_DBG_BREAK()
|
||||
#define BLYNK_ASSERT(expr)
|
||||
#define BLYNK_DBG_DUMP(msg, addr, len)
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,268 +0,0 @@
|
||||
/**
|
||||
* @file BlynkDetectDevice.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
|
||||
* @date May 2016
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkDetectDevice_h
|
||||
#define BlynkDetectDevice_h
|
||||
|
||||
// General defines
|
||||
|
||||
#define BLYNK_NEWLINE "\r\n"
|
||||
|
||||
#define BLYNK_CONCAT(a, b) a ## b
|
||||
#define BLYNK_CONCAT2(a, b) BLYNK_CONCAT(a, b)
|
||||
|
||||
#define BLYNK_STRINGIFY(x) #x
|
||||
#define BLYNK_TOSTRING(x) BLYNK_STRINGIFY(x)
|
||||
|
||||
#define BLYNK_COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
|
||||
|
||||
#define BLYNK_ATTR_PACKED __attribute__ ((__packed__))
|
||||
#define BLYNK_NORETURN __attribute__ ((noreturn))
|
||||
#define BLYNK_UNUSED __attribute__((__unused__))
|
||||
#define BLYNK_DEPRECATED __attribute__ ((deprecated))
|
||||
#define BLYNK_CONSTRUCTOR __attribute__((constructor))
|
||||
|
||||
// Causes problems on some platforms
|
||||
#define BLYNK_FORCE_INLINE inline //__attribute__((always_inline))
|
||||
|
||||
#ifndef BLYNK_INFO_CPU
|
||||
#if defined(__AVR_ATmega168__)
|
||||
#define BLYNK_INFO_CPU "ATmega168"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BLYNK_INFO_DEVICE
|
||||
|
||||
#if defined(ENERGIA)
|
||||
|
||||
#define BLYNK_NO_YIELD
|
||||
#define BLYNK_USE_128_VPINS
|
||||
|
||||
#if defined(ENERGIA_ARCH_MSP430)
|
||||
#define BLYNK_INFO_DEVICE "LaunchPad MSP430"
|
||||
#define BLYNK_INFO_CPU "MSP430"
|
||||
#define BLYNK_NO_FLOAT
|
||||
#elif defined(ENERGIA_ARCH_MSP432)
|
||||
#define BLYNK_INFO_DEVICE "LaunchPad MSP432"
|
||||
#define BLYNK_INFO_CPU "MSP432"
|
||||
#elif defined(ENERGIA_ARCH_TIVAC)
|
||||
#define BLYNK_INFO_DEVICE "LaunchPad"
|
||||
|
||||
#elif defined(ENERGIA_ARCH_CC3200EMT) || defined(ENERGIA_ARCH_CC3200)
|
||||
#define BLYNK_INFO_CONNECTION "CC3200"
|
||||
#define BLYNK_SEND_CHUNK 64
|
||||
#define BLYNK_BUFFERS_SIZE 1024
|
||||
|
||||
#if defined(ENERGIA_CC3200_LAUNCHXL) //TODO: This is a bug in Energia IDE
|
||||
#define BLYNK_INFO_DEVICE "CC3200 LaunchXL"
|
||||
#elif defined(ENERGIA_RedBearLab_CC3200)
|
||||
#define BLYNK_INFO_DEVICE "RBL CC3200"
|
||||
#elif defined(ENERGIA_RedBearLab_WiFiMini)
|
||||
#define BLYNK_INFO_DEVICE "RBL WiFi Mini"
|
||||
#elif defined(ENERGIA_RedBearLab_WiFiMicro)
|
||||
#define BLYNK_INFO_DEVICE "RBL WiFi Micro"
|
||||
#endif
|
||||
#elif defined(ENERGIA_ARCH_CC3220EMT) || defined(ENERGIA_ARCH_CC3220)
|
||||
#define BLYNK_INFO_CONNECTION "CC3220"
|
||||
#define BLYNK_SEND_CHUNK 64
|
||||
#define BLYNK_BUFFERS_SIZE 1024
|
||||
|
||||
#define BLYNK_USE_INTERNAL_DTOSTRF
|
||||
|
||||
#define BLYNK_INFO_DEVICE "CC3220"
|
||||
#define BLYNK_INFO_CPU "CC3220"
|
||||
#endif
|
||||
|
||||
#if !defined(BLYNK_INFO_DEVICE)
|
||||
#define BLYNK_INFO_DEVICE "Energia"
|
||||
#endif
|
||||
|
||||
#elif defined(LINUX)
|
||||
|
||||
#define BLYNK_INFO_DEVICE "Linux"
|
||||
#define BLYNK_USE_128_VPINS
|
||||
#define BLYNK_BUFFERS_SIZE 4096
|
||||
|
||||
#elif defined(SPARK) || defined(PARTICLE)
|
||||
|
||||
#define BLYNK_USE_128_VPINS
|
||||
#define BLYNK_BUFFERS_SIZE 1024
|
||||
|
||||
#if PLATFORM_ID==0
|
||||
#define BLYNK_INFO_DEVICE "Particle Core"
|
||||
#undef BLYNK_BUFFERS_SIZE // Use default on Core
|
||||
#elif PLATFORM_ID==6
|
||||
#define BLYNK_INFO_DEVICE "Particle Photon"
|
||||
#elif PLATFORM_ID==8
|
||||
#define BLYNK_INFO_DEVICE "Particle P1"
|
||||
#elif PLATFORM_ID==9
|
||||
#define BLYNK_INFO_DEVICE "Particle Ethernet"
|
||||
#elif PLATFORM_ID==10
|
||||
#define BLYNK_INFO_DEVICE "Particle Electron"
|
||||
#elif PLATFORM_ID==31
|
||||
#define BLYNK_INFO_DEVICE "Particle RPi"
|
||||
#elif PLATFORM_ID==82
|
||||
#define BLYNK_INFO_DEVICE "Digistump Oak"
|
||||
#elif PLATFORM_ID==88
|
||||
#define BLYNK_INFO_DEVICE "RedBear Duo"
|
||||
#elif PLATFORM_ID==103
|
||||
#define BLYNK_INFO_DEVICE "Bluz"
|
||||
#else
|
||||
#if defined(BLYNK_DEBUG_ALL)
|
||||
#warning "Cannot detect board type"
|
||||
#endif
|
||||
#define BLYNK_INFO_DEVICE "Particle"
|
||||
#endif
|
||||
|
||||
#elif defined(__MBED__)
|
||||
|
||||
#define BLYNK_INFO_DEVICE "MBED"
|
||||
#define BLYNK_USE_128_VPINS
|
||||
#define BLYNK_BUFFERS_SIZE 512
|
||||
#define noInterrupts() __disable_irq()
|
||||
#define interrupts() __enable_irq()
|
||||
|
||||
#elif defined(ARDUINO) && defined(MPIDE)
|
||||
#define BLYNK_NO_YIELD
|
||||
|
||||
#if defined(_BOARD_UNO_)
|
||||
#define BLYNK_INFO_DEVICE "chipKIT Uno32"
|
||||
#else
|
||||
#define BLYNK_INFO_DEVICE "chipKIT"
|
||||
#endif
|
||||
|
||||
#elif defined(ARDUINO) && defined(ARDUINO_AMEBA)
|
||||
#if defined(BOARD_RTL8710)
|
||||
#define BLYNK_INFO_DEVICE "RTL8710"
|
||||
#define BLYNK_USE_128_VPINS
|
||||
#define BLYNK_BUFFERS_SIZE 1024
|
||||
#elif defined(BOARD_RTL8711AM)
|
||||
#define BLYNK_INFO_DEVICE "RTL8711AM"
|
||||
#define BLYNK_USE_128_VPINS
|
||||
#define BLYNK_BUFFERS_SIZE 1024
|
||||
#elif defined(BOARD_RTL8195A)
|
||||
#define BLYNK_INFO_DEVICE "RTL8195A"
|
||||
#define BLYNK_USE_128_VPINS
|
||||
#define BLYNK_BUFFERS_SIZE 1024
|
||||
#else
|
||||
#define BLYNK_INFO_DEVICE "Ameba"
|
||||
#endif
|
||||
|
||||
#elif defined(ARDUINO) && defined(TEENSYDUINO)
|
||||
|
||||
#if defined(__MK66FX1M0__)
|
||||
#define BLYNK_INFO_DEVICE "Teensy 3.6"
|
||||
#define BLYNK_USE_128_VPINS
|
||||
#define BLYNK_BUFFERS_SIZE 1024
|
||||
#elif defined(__MK64FX512__)
|
||||
#define BLYNK_INFO_DEVICE "Teensy 3.5"
|
||||
#define BLYNK_USE_128_VPINS
|
||||
#define BLYNK_BUFFERS_SIZE 1024
|
||||
#elif defined(__MK20DX256__)
|
||||
#define BLYNK_INFO_DEVICE "Teensy 3.2/3.1"
|
||||
#define BLYNK_USE_128_VPINS
|
||||
#define BLYNK_BUFFERS_SIZE 1024
|
||||
#elif defined(__MK20DX128__)
|
||||
#define BLYNK_INFO_DEVICE "Teensy 3.0"
|
||||
#define BLYNK_USE_128_VPINS
|
||||
#define BLYNK_BUFFERS_SIZE 1024
|
||||
#elif defined(__MKL26Z64__)
|
||||
#define BLYNK_INFO_DEVICE "Teensy LC"
|
||||
#define BLYNK_BUFFERS_SIZE 512
|
||||
#elif defined(ARDUINO_ARCH_AVR)
|
||||
#define BLYNK_INFO_DEVICE "Teensy 2.0"
|
||||
#else
|
||||
#define BLYNK_INFO_DEVICE "Teensy"
|
||||
#endif
|
||||
|
||||
#elif defined(ARDUINO)
|
||||
|
||||
#if defined(ARDUINO_ARCH_SAMD) || defined(ESP32) || defined(ESP8266)
|
||||
#define BLYNK_USE_128_VPINS
|
||||
#define BLYNK_BUFFERS_SIZE 1024
|
||||
#endif
|
||||
|
||||
/* Arduino AVR */
|
||||
#if defined(ARDUINO_AVR_NANO)
|
||||
#define BLYNK_INFO_DEVICE "Arduino Nano"
|
||||
|
||||
/* ESP8266 */
|
||||
#elif defined(ARDUINO_ESP8266_ESP01)
|
||||
#define BLYNK_INFO_DEVICE "ESP8266"
|
||||
#elif defined(ARDUINO_ESP8266_ESP12)
|
||||
#define BLYNK_INFO_DEVICE "ESP-12"
|
||||
#elif defined(ARDUINO_ESP8266_NODEMCU)
|
||||
#define BLYNK_INFO_DEVICE "NodeMCU"
|
||||
#elif defined(ARDUINO_ESP8266_THING)
|
||||
#define BLYNK_INFO_DEVICE "Esp Thing"
|
||||
#elif defined(ARDUINO_ESP8266_THING_DEV)
|
||||
#define BLYNK_INFO_DEVICE "Esp Thing Dev"
|
||||
|
||||
/* ESP32 */
|
||||
#elif defined(ARDUINO_ESP32_DEV)
|
||||
#define BLYNK_INFO_DEVICE "ESP32"
|
||||
#elif defined(ARDUINO_ESP320)
|
||||
#define BLYNK_INFO_DEVICE "SweetPeas ESP320"
|
||||
#elif defined(ARDUINO_NANO32)
|
||||
#define BLYNK_INFO_DEVICE "ESP32 Nano32"
|
||||
#elif defined(ARDUINO_LoLin32)
|
||||
#define BLYNK_INFO_DEVICE "LoLin32"
|
||||
#elif defined(ARDUINO_ESPea32)
|
||||
#define BLYNK_INFO_DEVICE "ESPea32"
|
||||
#elif defined(ARDUINO_QUANTUM)
|
||||
#define BLYNK_INFO_DEVICE "Noduino Quantum"
|
||||
|
||||
#else
|
||||
#if defined(BLYNK_DEBUG_ALL)
|
||||
#warning "Cannot detect board type"
|
||||
#endif
|
||||
#define BLYNK_INFO_DEVICE "Arduino"
|
||||
#endif
|
||||
|
||||
#elif defined(TI_CC3220)
|
||||
#define BLYNK_INFO_DEVICE "TI CC3220"
|
||||
#define BLYNK_USE_128_VPINS
|
||||
#define BLYNK_BUFFERS_SIZE 1024
|
||||
|
||||
#define BLYNK_USE_INTERNAL_DTOSTRF
|
||||
|
||||
#else
|
||||
|
||||
#define BLYNK_INFO_DEVICE "Custom platform"
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(BLYNK_MAX_READBYTES) && defined(BLYNK_BUFFERS_SIZE)
|
||||
#define BLYNK_MAX_READBYTES BLYNK_BUFFERS_SIZE
|
||||
#endif
|
||||
|
||||
#if !defined(BLYNK_MAX_SENDBYTES) && defined(BLYNK_BUFFERS_SIZE)
|
||||
#define BLYNK_MAX_SENDBYTES BLYNK_BUFFERS_SIZE
|
||||
#endif
|
||||
|
||||
// Print diagnostics
|
||||
|
||||
#if defined(BLYNK_DEBUG_ALL)
|
||||
#if defined(BLYNK_INFO_DEVICE)
|
||||
#pragma message ("BLYNK_INFO_DEVICE=" BLYNK_TOSTRING(BLYNK_INFO_DEVICE))
|
||||
#endif
|
||||
|
||||
#if defined(BLYNK_INFO_CPU)
|
||||
#pragma message ("BLYNK_INFO_CPU=" BLYNK_TOSTRING(BLYNK_INFO_CPU))
|
||||
#endif
|
||||
|
||||
#if defined(BLYNK_BUFFERS_SIZE)
|
||||
#pragma message ("BLYNK_BUFFERS_SIZE=" BLYNK_TOSTRING(BLYNK_BUFFERS_SIZE))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,69 +0,0 @@
|
||||
|
||||
#ifndef BLYNKEVERYN_H
|
||||
#define BLYNKEVERYN_H
|
||||
|
||||
#include "BlynkDebug.h"
|
||||
|
||||
millis_time_t blynk_count_millis() {
|
||||
const millis_time_t ms = BlynkMillis();
|
||||
return ms;
|
||||
}
|
||||
|
||||
uint16_t blynk_count_seconds16() {
|
||||
const millis_time_t ms = BlynkMillis();
|
||||
return (ms / 1000);
|
||||
}
|
||||
|
||||
uint16_t blynk_count_minutes16()
|
||||
{
|
||||
const millis_time_t ms = BlynkMillis();
|
||||
return (ms / (60000L)) & 0xFFFF;
|
||||
}
|
||||
|
||||
uint8_t blynk_count_hours8()
|
||||
{
|
||||
const millis_time_t ms = BlynkMillis();
|
||||
return (ms / (3600000L)) & 0xFF;
|
||||
}
|
||||
|
||||
template<typename T, T (*timeGetter)()>
|
||||
class BlynkPeriodic {
|
||||
public:
|
||||
T mPrev;
|
||||
T mPeriod;
|
||||
|
||||
BlynkPeriodic() { reset(); mPeriod = 1; };
|
||||
BlynkPeriodic(T period) { reset(); setPeriod(period); };
|
||||
void setPeriod( T period) { mPeriod = period; };
|
||||
T getTime() { return (T)(timeGetter()); };
|
||||
T getPeriod() { return mPeriod; };
|
||||
T getElapsed() { return getTime() - mPrev; }
|
||||
T getRemaining() { return mPeriod - getElapsed(); }
|
||||
T getLastTriggerTime() { return mPrev; }
|
||||
bool ready() {
|
||||
bool isReady = (getElapsed() >= mPeriod);
|
||||
if( isReady ) { reset(); }
|
||||
return isReady;
|
||||
}
|
||||
void reset() { mPrev = getTime(); };
|
||||
void trigger() { mPrev = getTime() - mPeriod; };
|
||||
|
||||
operator bool() { return ready(); }
|
||||
};
|
||||
|
||||
typedef BlynkPeriodic<millis_time_t,blynk_count_millis> BlynkEveryNMillis;
|
||||
typedef BlynkPeriodic<uint16_t,blynk_count_seconds16> BlynkEveryNSeconds;
|
||||
typedef BlynkPeriodic<uint16_t,blynk_count_minutes16> BlynkEveryNMinutes;
|
||||
typedef BlynkPeriodic<uint8_t,blynk_count_hours8> BlynkEveryNHours;
|
||||
|
||||
#define BLYNK_EVERY_N_MILLIS_I(NAME,N) static BlynkEveryNMillis NAME(N); if(NAME)
|
||||
#define BLYNK_EVERY_N_SECONDS_I(NAME,N) static BlynkEveryNSeconds NAME(N); if(NAME)
|
||||
#define BLYNK_EVERY_N_MINUTES_I(NAME,N) static BlynkEveryNMinutes NAME(N); if(NAME)
|
||||
#define BLYNK_EVERY_N_HOURS_I(NAME,N) static BlynkEveryNHours NAME(N); if(NAME)
|
||||
|
||||
#define BLYNK_EVERY_N_MILLIS(N) BLYNK_EVERY_N_MILLIS_I(BLYNK_CONCAT2(PER, __COUNTER__),N)
|
||||
#define BLYNK_EVERY_N_SECONDS(N) BLYNK_EVERY_N_SECONDS_I(BLYNK_CONCAT2(PER, __COUNTER__),N)
|
||||
#define BLYNK_EVERY_N_MINUTES(N) BLYNK_EVERY_N_MINUTES_I(BLYNK_CONCAT2(PER, __COUNTER__),N)
|
||||
#define BLYNK_EVERY_N_HOURS(N) BLYNK_EVERY_N_HOURS_I(BLYNK_CONCAT2(PER, __COUNTER__),N)
|
||||
|
||||
#endif
|
@ -1,158 +0,0 @@
|
||||
/**
|
||||
* @file BlynkFifo.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Feb 2015
|
||||
* @brief FIFO implementation
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkFifo_h
|
||||
#define BlynkFifo_h
|
||||
|
||||
#include "BlynkUtility.h"
|
||||
|
||||
template <class T, unsigned N>
|
||||
class BlynkFifo
|
||||
{
|
||||
public:
|
||||
BlynkFifo()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
_r = 0;
|
||||
_w = 0;
|
||||
}
|
||||
|
||||
~BlynkFifo(void)
|
||||
{}
|
||||
|
||||
// writing thread/context API
|
||||
//-------------------------------------------------------------
|
||||
|
||||
bool writeable(void)
|
||||
{
|
||||
return free() > 0;
|
||||
}
|
||||
|
||||
int free(void)
|
||||
{
|
||||
int s = _r - _w;
|
||||
if (s <= 0)
|
||||
s += N;
|
||||
return s - 1;
|
||||
}
|
||||
|
||||
T put(const T& c)
|
||||
{
|
||||
int i = _w;
|
||||
int j = i;
|
||||
i = _inc(i);
|
||||
while (i == _r) // = !writeable()
|
||||
/* nothing / just wait */;
|
||||
_b[j] = c;
|
||||
_w = i;
|
||||
return c;
|
||||
}
|
||||
|
||||
int put(const T* p, int n, bool blocking = false)
|
||||
{
|
||||
int c = n;
|
||||
while (c)
|
||||
{
|
||||
int f;
|
||||
while ((f = free()) == 0) // wait for space
|
||||
{
|
||||
if (!blocking) return n - c; // no more space and not blocking
|
||||
/* nothing / just wait */;
|
||||
}
|
||||
// check free space
|
||||
if (c < f) f = c;
|
||||
int w = _w;
|
||||
int m = N - w;
|
||||
// check wrap
|
||||
if (f > m) f = m;
|
||||
memcpy(&_b[w], p, f);
|
||||
_w = _inc(w, f);
|
||||
c -= f;
|
||||
p += f;
|
||||
}
|
||||
return n - c;
|
||||
}
|
||||
|
||||
// reading thread/context API
|
||||
// --------------------------------------------------------
|
||||
|
||||
bool readable(void)
|
||||
{
|
||||
return (_r != _w);
|
||||
}
|
||||
|
||||
size_t size(void)
|
||||
{
|
||||
int s = _w - _r;
|
||||
if (s < 0)
|
||||
s += N;
|
||||
return s;
|
||||
}
|
||||
|
||||
T get(void)
|
||||
{
|
||||
int r = _r;
|
||||
while (r == _w) // = !readable()
|
||||
/* nothing / just wait */;
|
||||
T t = _b[r];
|
||||
_r = _inc(r);
|
||||
return t;
|
||||
}
|
||||
|
||||
T peek(void)
|
||||
{
|
||||
int r = _r;
|
||||
while (r == _w);
|
||||
return _b[r];
|
||||
}
|
||||
|
||||
int get(T* p, int n, bool blocking = false)
|
||||
{
|
||||
int c = n;
|
||||
while (c)
|
||||
{
|
||||
int f;
|
||||
for (;;) // wait for data
|
||||
{
|
||||
f = size();
|
||||
if (f) break; // free space
|
||||
if (!blocking) return n - c; // no space and not blocking
|
||||
/* nothing / just wait */;
|
||||
}
|
||||
// check available data
|
||||
if (c < f) f = c;
|
||||
int r = _r;
|
||||
int m = N - r;
|
||||
// check wrap
|
||||
if (f > m) f = m;
|
||||
memcpy(p, &_b[r], f);
|
||||
_r = _inc(r, f);
|
||||
c -= f;
|
||||
p += f;
|
||||
}
|
||||
return n - c;
|
||||
}
|
||||
|
||||
private:
|
||||
int _inc(int i, int n = 1)
|
||||
{
|
||||
return (i + n) % N;
|
||||
}
|
||||
|
||||
T _b[N];
|
||||
volatile int _w;
|
||||
volatile int _r;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,402 +0,0 @@
|
||||
/**
|
||||
* @file BlynkHandlers.cpp
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Jan 2015
|
||||
* @brief Virtual pin utilities
|
||||
*/
|
||||
|
||||
#include "BlynkConfig.h"
|
||||
#include "BlynkHandlers.h"
|
||||
#include "BlynkDebug.h"
|
||||
|
||||
void BlynkNoOpCbk()
|
||||
{}
|
||||
|
||||
void BlynkWidgetRead(BlynkReq BLYNK_UNUSED &request)
|
||||
{
|
||||
BLYNK_LOG2(BLYNK_F("No handler for reading from pin "), request.pin);
|
||||
}
|
||||
|
||||
void BlynkWidgetWrite(BlynkReq BLYNK_UNUSED &request, const BlynkParam BLYNK_UNUSED ¶m)
|
||||
{
|
||||
BLYNK_LOG2(BLYNK_F("No handler for writing to pin "), request.pin);
|
||||
}
|
||||
|
||||
#define BLYNK_ON_READ_IMPL(pin) void BlynkWidgetRead ## pin (BlynkReq BLYNK_UNUSED &req) \
|
||||
__attribute__((weak, alias("BlynkWidgetRead")))
|
||||
|
||||
#define BLYNK_ON_WRITE_IMPL(pin) void BlynkWidgetWrite ## pin (BlynkReq BLYNK_UNUSED &req, const BlynkParam BLYNK_UNUSED ¶m) \
|
||||
__attribute__((weak, alias("BlynkWidgetWrite")))
|
||||
|
||||
BLYNK_CONNECTED() __attribute__((weak, alias("BlynkNoOpCbk")));
|
||||
BLYNK_DISCONNECTED() __attribute__((weak, alias("BlynkNoOpCbk")));
|
||||
|
||||
// Internal Virtual Pins
|
||||
BLYNK_ON_WRITE_IMPL(InternalPinACON);
|
||||
BLYNK_ON_WRITE_IMPL(InternalPinADIS);
|
||||
BLYNK_ON_WRITE_IMPL(InternalPinRTC);
|
||||
BLYNK_ON_WRITE_IMPL(InternalPinOTA);
|
||||
|
||||
// Regular Virtual Pins
|
||||
BLYNK_ON_READ_IMPL(Default);
|
||||
BLYNK_ON_WRITE_IMPL(Default);
|
||||
|
||||
BLYNK_ON_READ_IMPL(0 );
|
||||
BLYNK_ON_READ_IMPL(1 );
|
||||
BLYNK_ON_READ_IMPL(2 );
|
||||
BLYNK_ON_READ_IMPL(3 );
|
||||
BLYNK_ON_READ_IMPL(4 );
|
||||
BLYNK_ON_READ_IMPL(5 );
|
||||
BLYNK_ON_READ_IMPL(6 );
|
||||
BLYNK_ON_READ_IMPL(7 );
|
||||
BLYNK_ON_READ_IMPL(8 );
|
||||
BLYNK_ON_READ_IMPL(9 );
|
||||
BLYNK_ON_READ_IMPL(10);
|
||||
BLYNK_ON_READ_IMPL(11);
|
||||
BLYNK_ON_READ_IMPL(12);
|
||||
BLYNK_ON_READ_IMPL(13);
|
||||
BLYNK_ON_READ_IMPL(14);
|
||||
BLYNK_ON_READ_IMPL(15);
|
||||
BLYNK_ON_READ_IMPL(16);
|
||||
BLYNK_ON_READ_IMPL(17);
|
||||
BLYNK_ON_READ_IMPL(18);
|
||||
BLYNK_ON_READ_IMPL(19);
|
||||
BLYNK_ON_READ_IMPL(20);
|
||||
BLYNK_ON_READ_IMPL(21);
|
||||
BLYNK_ON_READ_IMPL(22);
|
||||
BLYNK_ON_READ_IMPL(23);
|
||||
BLYNK_ON_READ_IMPL(24);
|
||||
BLYNK_ON_READ_IMPL(25);
|
||||
BLYNK_ON_READ_IMPL(26);
|
||||
BLYNK_ON_READ_IMPL(27);
|
||||
BLYNK_ON_READ_IMPL(28);
|
||||
BLYNK_ON_READ_IMPL(29);
|
||||
BLYNK_ON_READ_IMPL(30);
|
||||
BLYNK_ON_READ_IMPL(31);
|
||||
#ifdef BLYNK_USE_128_VPINS
|
||||
BLYNK_ON_READ_IMPL(32);
|
||||
BLYNK_ON_READ_IMPL(33);
|
||||
BLYNK_ON_READ_IMPL(34);
|
||||
BLYNK_ON_READ_IMPL(35);
|
||||
BLYNK_ON_READ_IMPL(36);
|
||||
BLYNK_ON_READ_IMPL(37);
|
||||
BLYNK_ON_READ_IMPL(38);
|
||||
BLYNK_ON_READ_IMPL(39);
|
||||
BLYNK_ON_READ_IMPL(40);
|
||||
BLYNK_ON_READ_IMPL(41);
|
||||
BLYNK_ON_READ_IMPL(42);
|
||||
BLYNK_ON_READ_IMPL(43);
|
||||
BLYNK_ON_READ_IMPL(44);
|
||||
BLYNK_ON_READ_IMPL(45);
|
||||
BLYNK_ON_READ_IMPL(46);
|
||||
BLYNK_ON_READ_IMPL(47);
|
||||
BLYNK_ON_READ_IMPL(48);
|
||||
BLYNK_ON_READ_IMPL(49);
|
||||
BLYNK_ON_READ_IMPL(50);
|
||||
BLYNK_ON_READ_IMPL(51);
|
||||
BLYNK_ON_READ_IMPL(52);
|
||||
BLYNK_ON_READ_IMPL(53);
|
||||
BLYNK_ON_READ_IMPL(54);
|
||||
BLYNK_ON_READ_IMPL(55);
|
||||
BLYNK_ON_READ_IMPL(56);
|
||||
BLYNK_ON_READ_IMPL(57);
|
||||
BLYNK_ON_READ_IMPL(58);
|
||||
BLYNK_ON_READ_IMPL(59);
|
||||
BLYNK_ON_READ_IMPL(60);
|
||||
BLYNK_ON_READ_IMPL(61);
|
||||
BLYNK_ON_READ_IMPL(62);
|
||||
BLYNK_ON_READ_IMPL(63);
|
||||
BLYNK_ON_READ_IMPL(64);
|
||||
BLYNK_ON_READ_IMPL(65);
|
||||
BLYNK_ON_READ_IMPL(66);
|
||||
BLYNK_ON_READ_IMPL(67);
|
||||
BLYNK_ON_READ_IMPL(68);
|
||||
BLYNK_ON_READ_IMPL(69);
|
||||
BLYNK_ON_READ_IMPL(70);
|
||||
BLYNK_ON_READ_IMPL(71);
|
||||
BLYNK_ON_READ_IMPL(72);
|
||||
BLYNK_ON_READ_IMPL(73);
|
||||
BLYNK_ON_READ_IMPL(74);
|
||||
BLYNK_ON_READ_IMPL(75);
|
||||
BLYNK_ON_READ_IMPL(76);
|
||||
BLYNK_ON_READ_IMPL(77);
|
||||
BLYNK_ON_READ_IMPL(78);
|
||||
BLYNK_ON_READ_IMPL(79);
|
||||
BLYNK_ON_READ_IMPL(80);
|
||||
BLYNK_ON_READ_IMPL(81);
|
||||
BLYNK_ON_READ_IMPL(82);
|
||||
BLYNK_ON_READ_IMPL(83);
|
||||
BLYNK_ON_READ_IMPL(84);
|
||||
BLYNK_ON_READ_IMPL(85);
|
||||
BLYNK_ON_READ_IMPL(86);
|
||||
BLYNK_ON_READ_IMPL(87);
|
||||
BLYNK_ON_READ_IMPL(88);
|
||||
BLYNK_ON_READ_IMPL(89);
|
||||
BLYNK_ON_READ_IMPL(90);
|
||||
BLYNK_ON_READ_IMPL(91);
|
||||
BLYNK_ON_READ_IMPL(92);
|
||||
BLYNK_ON_READ_IMPL(93);
|
||||
BLYNK_ON_READ_IMPL(94);
|
||||
BLYNK_ON_READ_IMPL(95);
|
||||
BLYNK_ON_READ_IMPL(96);
|
||||
BLYNK_ON_READ_IMPL(97);
|
||||
BLYNK_ON_READ_IMPL(98);
|
||||
BLYNK_ON_READ_IMPL(99);
|
||||
BLYNK_ON_READ_IMPL(100);
|
||||
BLYNK_ON_READ_IMPL(101);
|
||||
BLYNK_ON_READ_IMPL(102);
|
||||
BLYNK_ON_READ_IMPL(103);
|
||||
BLYNK_ON_READ_IMPL(104);
|
||||
BLYNK_ON_READ_IMPL(105);
|
||||
BLYNK_ON_READ_IMPL(106);
|
||||
BLYNK_ON_READ_IMPL(107);
|
||||
BLYNK_ON_READ_IMPL(108);
|
||||
BLYNK_ON_READ_IMPL(109);
|
||||
BLYNK_ON_READ_IMPL(110);
|
||||
BLYNK_ON_READ_IMPL(111);
|
||||
BLYNK_ON_READ_IMPL(112);
|
||||
BLYNK_ON_READ_IMPL(113);
|
||||
BLYNK_ON_READ_IMPL(114);
|
||||
BLYNK_ON_READ_IMPL(115);
|
||||
BLYNK_ON_READ_IMPL(116);
|
||||
BLYNK_ON_READ_IMPL(117);
|
||||
BLYNK_ON_READ_IMPL(118);
|
||||
BLYNK_ON_READ_IMPL(119);
|
||||
BLYNK_ON_READ_IMPL(120);
|
||||
BLYNK_ON_READ_IMPL(121);
|
||||
BLYNK_ON_READ_IMPL(122);
|
||||
BLYNK_ON_READ_IMPL(123);
|
||||
BLYNK_ON_READ_IMPL(124);
|
||||
BLYNK_ON_READ_IMPL(125);
|
||||
BLYNK_ON_READ_IMPL(126);
|
||||
BLYNK_ON_READ_IMPL(127);
|
||||
#endif
|
||||
|
||||
BLYNK_ON_WRITE_IMPL(0 );
|
||||
BLYNK_ON_WRITE_IMPL(1 );
|
||||
BLYNK_ON_WRITE_IMPL(2 );
|
||||
BLYNK_ON_WRITE_IMPL(3 );
|
||||
BLYNK_ON_WRITE_IMPL(4 );
|
||||
BLYNK_ON_WRITE_IMPL(5 );
|
||||
BLYNK_ON_WRITE_IMPL(6 );
|
||||
BLYNK_ON_WRITE_IMPL(7 );
|
||||
BLYNK_ON_WRITE_IMPL(8 );
|
||||
BLYNK_ON_WRITE_IMPL(9 );
|
||||
BLYNK_ON_WRITE_IMPL(10);
|
||||
BLYNK_ON_WRITE_IMPL(11);
|
||||
BLYNK_ON_WRITE_IMPL(12);
|
||||
BLYNK_ON_WRITE_IMPL(13);
|
||||
BLYNK_ON_WRITE_IMPL(14);
|
||||
BLYNK_ON_WRITE_IMPL(15);
|
||||
BLYNK_ON_WRITE_IMPL(16);
|
||||
BLYNK_ON_WRITE_IMPL(17);
|
||||
BLYNK_ON_WRITE_IMPL(18);
|
||||
BLYNK_ON_WRITE_IMPL(19);
|
||||
BLYNK_ON_WRITE_IMPL(20);
|
||||
BLYNK_ON_WRITE_IMPL(21);
|
||||
BLYNK_ON_WRITE_IMPL(22);
|
||||
BLYNK_ON_WRITE_IMPL(23);
|
||||
BLYNK_ON_WRITE_IMPL(24);
|
||||
BLYNK_ON_WRITE_IMPL(25);
|
||||
BLYNK_ON_WRITE_IMPL(26);
|
||||
BLYNK_ON_WRITE_IMPL(27);
|
||||
BLYNK_ON_WRITE_IMPL(28);
|
||||
BLYNK_ON_WRITE_IMPL(29);
|
||||
BLYNK_ON_WRITE_IMPL(30);
|
||||
BLYNK_ON_WRITE_IMPL(31);
|
||||
#ifdef BLYNK_USE_128_VPINS
|
||||
BLYNK_ON_WRITE_IMPL(32);
|
||||
BLYNK_ON_WRITE_IMPL(33);
|
||||
BLYNK_ON_WRITE_IMPL(34);
|
||||
BLYNK_ON_WRITE_IMPL(35);
|
||||
BLYNK_ON_WRITE_IMPL(36);
|
||||
BLYNK_ON_WRITE_IMPL(37);
|
||||
BLYNK_ON_WRITE_IMPL(38);
|
||||
BLYNK_ON_WRITE_IMPL(39);
|
||||
BLYNK_ON_WRITE_IMPL(40);
|
||||
BLYNK_ON_WRITE_IMPL(41);
|
||||
BLYNK_ON_WRITE_IMPL(42);
|
||||
BLYNK_ON_WRITE_IMPL(43);
|
||||
BLYNK_ON_WRITE_IMPL(44);
|
||||
BLYNK_ON_WRITE_IMPL(45);
|
||||
BLYNK_ON_WRITE_IMPL(46);
|
||||
BLYNK_ON_WRITE_IMPL(47);
|
||||
BLYNK_ON_WRITE_IMPL(48);
|
||||
BLYNK_ON_WRITE_IMPL(49);
|
||||
BLYNK_ON_WRITE_IMPL(50);
|
||||
BLYNK_ON_WRITE_IMPL(51);
|
||||
BLYNK_ON_WRITE_IMPL(52);
|
||||
BLYNK_ON_WRITE_IMPL(53);
|
||||
BLYNK_ON_WRITE_IMPL(54);
|
||||
BLYNK_ON_WRITE_IMPL(55);
|
||||
BLYNK_ON_WRITE_IMPL(56);
|
||||
BLYNK_ON_WRITE_IMPL(57);
|
||||
BLYNK_ON_WRITE_IMPL(58);
|
||||
BLYNK_ON_WRITE_IMPL(59);
|
||||
BLYNK_ON_WRITE_IMPL(60);
|
||||
BLYNK_ON_WRITE_IMPL(61);
|
||||
BLYNK_ON_WRITE_IMPL(62);
|
||||
BLYNK_ON_WRITE_IMPL(63);
|
||||
BLYNK_ON_WRITE_IMPL(64);
|
||||
BLYNK_ON_WRITE_IMPL(65);
|
||||
BLYNK_ON_WRITE_IMPL(66);
|
||||
BLYNK_ON_WRITE_IMPL(67);
|
||||
BLYNK_ON_WRITE_IMPL(68);
|
||||
BLYNK_ON_WRITE_IMPL(69);
|
||||
BLYNK_ON_WRITE_IMPL(70);
|
||||
BLYNK_ON_WRITE_IMPL(71);
|
||||
BLYNK_ON_WRITE_IMPL(72);
|
||||
BLYNK_ON_WRITE_IMPL(73);
|
||||
BLYNK_ON_WRITE_IMPL(74);
|
||||
BLYNK_ON_WRITE_IMPL(75);
|
||||
BLYNK_ON_WRITE_IMPL(76);
|
||||
BLYNK_ON_WRITE_IMPL(77);
|
||||
BLYNK_ON_WRITE_IMPL(78);
|
||||
BLYNK_ON_WRITE_IMPL(79);
|
||||
BLYNK_ON_WRITE_IMPL(80);
|
||||
BLYNK_ON_WRITE_IMPL(81);
|
||||
BLYNK_ON_WRITE_IMPL(82);
|
||||
BLYNK_ON_WRITE_IMPL(83);
|
||||
BLYNK_ON_WRITE_IMPL(84);
|
||||
BLYNK_ON_WRITE_IMPL(85);
|
||||
BLYNK_ON_WRITE_IMPL(86);
|
||||
BLYNK_ON_WRITE_IMPL(87);
|
||||
BLYNK_ON_WRITE_IMPL(88);
|
||||
BLYNK_ON_WRITE_IMPL(89);
|
||||
BLYNK_ON_WRITE_IMPL(90);
|
||||
BLYNK_ON_WRITE_IMPL(91);
|
||||
BLYNK_ON_WRITE_IMPL(92);
|
||||
BLYNK_ON_WRITE_IMPL(93);
|
||||
BLYNK_ON_WRITE_IMPL(94);
|
||||
BLYNK_ON_WRITE_IMPL(95);
|
||||
BLYNK_ON_WRITE_IMPL(96);
|
||||
BLYNK_ON_WRITE_IMPL(97);
|
||||
BLYNK_ON_WRITE_IMPL(98);
|
||||
BLYNK_ON_WRITE_IMPL(99);
|
||||
BLYNK_ON_WRITE_IMPL(100);
|
||||
BLYNK_ON_WRITE_IMPL(101);
|
||||
BLYNK_ON_WRITE_IMPL(102);
|
||||
BLYNK_ON_WRITE_IMPL(103);
|
||||
BLYNK_ON_WRITE_IMPL(104);
|
||||
BLYNK_ON_WRITE_IMPL(105);
|
||||
BLYNK_ON_WRITE_IMPL(106);
|
||||
BLYNK_ON_WRITE_IMPL(107);
|
||||
BLYNK_ON_WRITE_IMPL(108);
|
||||
BLYNK_ON_WRITE_IMPL(109);
|
||||
BLYNK_ON_WRITE_IMPL(110);
|
||||
BLYNK_ON_WRITE_IMPL(111);
|
||||
BLYNK_ON_WRITE_IMPL(112);
|
||||
BLYNK_ON_WRITE_IMPL(113);
|
||||
BLYNK_ON_WRITE_IMPL(114);
|
||||
BLYNK_ON_WRITE_IMPL(115);
|
||||
BLYNK_ON_WRITE_IMPL(116);
|
||||
BLYNK_ON_WRITE_IMPL(117);
|
||||
BLYNK_ON_WRITE_IMPL(118);
|
||||
BLYNK_ON_WRITE_IMPL(119);
|
||||
BLYNK_ON_WRITE_IMPL(120);
|
||||
BLYNK_ON_WRITE_IMPL(121);
|
||||
BLYNK_ON_WRITE_IMPL(122);
|
||||
BLYNK_ON_WRITE_IMPL(123);
|
||||
BLYNK_ON_WRITE_IMPL(124);
|
||||
BLYNK_ON_WRITE_IMPL(125);
|
||||
BLYNK_ON_WRITE_IMPL(126);
|
||||
BLYNK_ON_WRITE_IMPL(127);
|
||||
#endif
|
||||
|
||||
static const WidgetReadHandler BlynkReadHandlerVector[] BLYNK_PROGMEM = {
|
||||
BlynkWidgetRead0, BlynkWidgetRead1, BlynkWidgetRead2, BlynkWidgetRead3,
|
||||
BlynkWidgetRead4, BlynkWidgetRead5, BlynkWidgetRead6, BlynkWidgetRead7,
|
||||
BlynkWidgetRead8, BlynkWidgetRead9, BlynkWidgetRead10, BlynkWidgetRead11,
|
||||
BlynkWidgetRead12, BlynkWidgetRead13, BlynkWidgetRead14, BlynkWidgetRead15,
|
||||
BlynkWidgetRead16, BlynkWidgetRead17, BlynkWidgetRead18, BlynkWidgetRead19,
|
||||
BlynkWidgetRead20, BlynkWidgetRead21, BlynkWidgetRead22, BlynkWidgetRead23,
|
||||
BlynkWidgetRead24, BlynkWidgetRead25, BlynkWidgetRead26, BlynkWidgetRead27,
|
||||
BlynkWidgetRead28, BlynkWidgetRead29, BlynkWidgetRead30, BlynkWidgetRead31,
|
||||
#ifdef BLYNK_USE_128_VPINS
|
||||
BlynkWidgetRead32, BlynkWidgetRead33, BlynkWidgetRead34, BlynkWidgetRead35,
|
||||
BlynkWidgetRead36, BlynkWidgetRead37, BlynkWidgetRead38, BlynkWidgetRead39,
|
||||
BlynkWidgetRead40, BlynkWidgetRead41, BlynkWidgetRead42, BlynkWidgetRead43,
|
||||
BlynkWidgetRead44, BlynkWidgetRead45, BlynkWidgetRead46, BlynkWidgetRead47,
|
||||
BlynkWidgetRead48, BlynkWidgetRead49, BlynkWidgetRead50, BlynkWidgetRead51,
|
||||
BlynkWidgetRead52, BlynkWidgetRead53, BlynkWidgetRead54, BlynkWidgetRead55,
|
||||
BlynkWidgetRead56, BlynkWidgetRead57, BlynkWidgetRead58, BlynkWidgetRead59,
|
||||
BlynkWidgetRead60, BlynkWidgetRead61, BlynkWidgetRead62, BlynkWidgetRead63,
|
||||
BlynkWidgetRead64, BlynkWidgetRead65, BlynkWidgetRead66, BlynkWidgetRead67,
|
||||
BlynkWidgetRead68, BlynkWidgetRead69, BlynkWidgetRead70, BlynkWidgetRead71,
|
||||
BlynkWidgetRead72, BlynkWidgetRead73, BlynkWidgetRead74, BlynkWidgetRead75,
|
||||
BlynkWidgetRead76, BlynkWidgetRead77, BlynkWidgetRead78, BlynkWidgetRead79,
|
||||
BlynkWidgetRead80, BlynkWidgetRead81, BlynkWidgetRead82, BlynkWidgetRead83,
|
||||
BlynkWidgetRead84, BlynkWidgetRead85, BlynkWidgetRead86, BlynkWidgetRead87,
|
||||
BlynkWidgetRead88, BlynkWidgetRead89, BlynkWidgetRead90, BlynkWidgetRead91,
|
||||
BlynkWidgetRead92, BlynkWidgetRead93, BlynkWidgetRead94, BlynkWidgetRead95,
|
||||
BlynkWidgetRead96, BlynkWidgetRead97, BlynkWidgetRead98, BlynkWidgetRead99,
|
||||
BlynkWidgetRead100, BlynkWidgetRead101, BlynkWidgetRead102, BlynkWidgetRead103,
|
||||
BlynkWidgetRead104, BlynkWidgetRead105, BlynkWidgetRead106, BlynkWidgetRead107,
|
||||
BlynkWidgetRead108, BlynkWidgetRead109, BlynkWidgetRead110, BlynkWidgetRead111,
|
||||
BlynkWidgetRead112, BlynkWidgetRead113, BlynkWidgetRead114, BlynkWidgetRead115,
|
||||
BlynkWidgetRead116, BlynkWidgetRead117, BlynkWidgetRead118, BlynkWidgetRead119,
|
||||
BlynkWidgetRead120, BlynkWidgetRead121, BlynkWidgetRead122, BlynkWidgetRead123,
|
||||
BlynkWidgetRead124, BlynkWidgetRead125, BlynkWidgetRead126, BlynkWidgetRead127,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const WidgetWriteHandler BlynkWriteHandlerVector[] BLYNK_PROGMEM = {
|
||||
BlynkWidgetWrite0, BlynkWidgetWrite1, BlynkWidgetWrite2, BlynkWidgetWrite3,
|
||||
BlynkWidgetWrite4, BlynkWidgetWrite5, BlynkWidgetWrite6, BlynkWidgetWrite7,
|
||||
BlynkWidgetWrite8, BlynkWidgetWrite9, BlynkWidgetWrite10, BlynkWidgetWrite11,
|
||||
BlynkWidgetWrite12, BlynkWidgetWrite13, BlynkWidgetWrite14, BlynkWidgetWrite15,
|
||||
BlynkWidgetWrite16, BlynkWidgetWrite17, BlynkWidgetWrite18, BlynkWidgetWrite19,
|
||||
BlynkWidgetWrite20, BlynkWidgetWrite21, BlynkWidgetWrite22, BlynkWidgetWrite23,
|
||||
BlynkWidgetWrite24, BlynkWidgetWrite25, BlynkWidgetWrite26, BlynkWidgetWrite27,
|
||||
BlynkWidgetWrite28, BlynkWidgetWrite29, BlynkWidgetWrite30, BlynkWidgetWrite31,
|
||||
#ifdef BLYNK_USE_128_VPINS
|
||||
BlynkWidgetWrite32, BlynkWidgetWrite33, BlynkWidgetWrite34, BlynkWidgetWrite35,
|
||||
BlynkWidgetWrite36, BlynkWidgetWrite37, BlynkWidgetWrite38, BlynkWidgetWrite39,
|
||||
BlynkWidgetWrite40, BlynkWidgetWrite41, BlynkWidgetWrite42, BlynkWidgetWrite43,
|
||||
BlynkWidgetWrite44, BlynkWidgetWrite45, BlynkWidgetWrite46, BlynkWidgetWrite47,
|
||||
BlynkWidgetWrite48, BlynkWidgetWrite49, BlynkWidgetWrite50, BlynkWidgetWrite51,
|
||||
BlynkWidgetWrite52, BlynkWidgetWrite53, BlynkWidgetWrite54, BlynkWidgetWrite55,
|
||||
BlynkWidgetWrite56, BlynkWidgetWrite57, BlynkWidgetWrite58, BlynkWidgetWrite59,
|
||||
BlynkWidgetWrite60, BlynkWidgetWrite61, BlynkWidgetWrite62, BlynkWidgetWrite63,
|
||||
BlynkWidgetWrite64, BlynkWidgetWrite65, BlynkWidgetWrite66, BlynkWidgetWrite67,
|
||||
BlynkWidgetWrite68, BlynkWidgetWrite69, BlynkWidgetWrite70, BlynkWidgetWrite71,
|
||||
BlynkWidgetWrite72, BlynkWidgetWrite73, BlynkWidgetWrite74, BlynkWidgetWrite75,
|
||||
BlynkWidgetWrite76, BlynkWidgetWrite77, BlynkWidgetWrite78, BlynkWidgetWrite79,
|
||||
BlynkWidgetWrite80, BlynkWidgetWrite81, BlynkWidgetWrite82, BlynkWidgetWrite83,
|
||||
BlynkWidgetWrite84, BlynkWidgetWrite85, BlynkWidgetWrite86, BlynkWidgetWrite87,
|
||||
BlynkWidgetWrite88, BlynkWidgetWrite89, BlynkWidgetWrite90, BlynkWidgetWrite91,
|
||||
BlynkWidgetWrite92, BlynkWidgetWrite93, BlynkWidgetWrite94, BlynkWidgetWrite95,
|
||||
BlynkWidgetWrite96, BlynkWidgetWrite97, BlynkWidgetWrite98, BlynkWidgetWrite99,
|
||||
BlynkWidgetWrite100, BlynkWidgetWrite101, BlynkWidgetWrite102, BlynkWidgetWrite103,
|
||||
BlynkWidgetWrite104, BlynkWidgetWrite105, BlynkWidgetWrite106, BlynkWidgetWrite107,
|
||||
BlynkWidgetWrite108, BlynkWidgetWrite109, BlynkWidgetWrite110, BlynkWidgetWrite111,
|
||||
BlynkWidgetWrite112, BlynkWidgetWrite113, BlynkWidgetWrite114, BlynkWidgetWrite115,
|
||||
BlynkWidgetWrite116, BlynkWidgetWrite117, BlynkWidgetWrite118, BlynkWidgetWrite119,
|
||||
BlynkWidgetWrite120, BlynkWidgetWrite121, BlynkWidgetWrite122, BlynkWidgetWrite123,
|
||||
BlynkWidgetWrite124, BlynkWidgetWrite125, BlynkWidgetWrite126, BlynkWidgetWrite127,
|
||||
#endif
|
||||
};
|
||||
|
||||
WidgetReadHandler GetReadHandler(uint8_t pin)
|
||||
{
|
||||
if (pin >= BLYNK_COUNT_OF(BlynkReadHandlerVector))
|
||||
return NULL;
|
||||
#ifdef BLYNK_HAS_PROGMEM
|
||||
return (WidgetReadHandler)pgm_read_word(&BlynkReadHandlerVector[pin]);
|
||||
#else
|
||||
return BlynkReadHandlerVector[pin];
|
||||
#endif
|
||||
}
|
||||
|
||||
WidgetWriteHandler GetWriteHandler(uint8_t pin)
|
||||
{
|
||||
if (pin >= BLYNK_COUNT_OF(BlynkWriteHandlerVector))
|
||||
return NULL;
|
||||
#ifdef BLYNK_HAS_PROGMEM
|
||||
return (WidgetWriteHandler)pgm_read_word(&BlynkWriteHandlerVector[pin]);
|
||||
#else
|
||||
return BlynkWriteHandlerVector[pin];
|
||||
#endif
|
||||
}
|
@ -1,511 +0,0 @@
|
||||
/**
|
||||
* @file BlynkHandlers.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Jan 2015
|
||||
* @brief Handlers for virtual pin operations
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkHandlers_h
|
||||
#define BlynkHandlers_h
|
||||
|
||||
#include "BlynkConfig.h"
|
||||
#include "BlynkParam.h"
|
||||
|
||||
// Helper macro
|
||||
|
||||
#define V0 0
|
||||
#define V1 1
|
||||
#define V2 2
|
||||
#define V3 3
|
||||
#define V4 4
|
||||
#define V5 5
|
||||
#define V6 6
|
||||
#define V7 7
|
||||
#define V8 8
|
||||
#define V9 9
|
||||
#define V10 10
|
||||
#define V11 11
|
||||
#define V12 12
|
||||
#define V13 13
|
||||
#define V14 14
|
||||
#define V15 15
|
||||
#define V16 16
|
||||
#define V17 17
|
||||
#define V18 18
|
||||
#define V19 19
|
||||
#define V20 20
|
||||
#define V21 21
|
||||
#define V22 22
|
||||
#define V23 23
|
||||
#define V24 24
|
||||
#define V25 25
|
||||
#define V26 26
|
||||
#define V27 27
|
||||
#define V28 28
|
||||
#define V29 29
|
||||
#define V30 30
|
||||
#define V31 31
|
||||
#ifdef BLYNK_USE_128_VPINS
|
||||
#define V32 32
|
||||
#define V33 33
|
||||
#define V34 34
|
||||
#define V35 35
|
||||
#define V36 36
|
||||
#define V37 37
|
||||
#define V38 38
|
||||
#define V39 39
|
||||
#define V40 40
|
||||
#define V41 41
|
||||
#define V42 42
|
||||
#define V43 43
|
||||
#define V44 44
|
||||
#define V45 45
|
||||
#define V46 46
|
||||
#define V47 47
|
||||
#define V48 48
|
||||
#define V49 49
|
||||
#define V50 50
|
||||
#define V51 51
|
||||
#define V52 52
|
||||
#define V53 53
|
||||
#define V54 54
|
||||
#define V55 55
|
||||
#define V56 56
|
||||
#define V57 57
|
||||
#define V58 58
|
||||
#define V59 59
|
||||
#define V60 60
|
||||
#define V61 61
|
||||
#define V62 62
|
||||
#define V63 63
|
||||
#define V64 64
|
||||
#define V65 65
|
||||
#define V66 66
|
||||
#define V67 67
|
||||
#define V68 68
|
||||
#define V69 69
|
||||
#define V70 70
|
||||
#define V71 71
|
||||
#define V72 72
|
||||
#define V73 73
|
||||
#define V74 74
|
||||
#define V75 75
|
||||
#define V76 76
|
||||
#define V77 77
|
||||
#define V78 78
|
||||
#define V79 79
|
||||
#define V80 80
|
||||
#define V81 81
|
||||
#define V82 82
|
||||
#define V83 83
|
||||
#define V84 84
|
||||
#define V85 85
|
||||
#define V86 86
|
||||
#define V87 87
|
||||
#define V88 88
|
||||
#define V89 89
|
||||
#define V90 90
|
||||
#define V91 91
|
||||
#define V92 92
|
||||
#define V93 93
|
||||
#define V94 94
|
||||
#define V95 95
|
||||
#define V96 96
|
||||
#define V97 97
|
||||
#define V98 98
|
||||
#define V99 99
|
||||
#define V100 100
|
||||
#define V101 101
|
||||
#define V102 102
|
||||
#define V103 103
|
||||
#define V104 104
|
||||
#define V105 105
|
||||
#define V106 106
|
||||
#define V107 107
|
||||
#define V108 108
|
||||
#define V109 109
|
||||
#define V110 110
|
||||
#define V111 111
|
||||
#define V112 112
|
||||
#define V113 113
|
||||
#define V114 114
|
||||
#define V115 115
|
||||
#define V116 116
|
||||
#define V117 117
|
||||
#define V118 118
|
||||
#define V119 119
|
||||
#define V120 120
|
||||
#define V121 121
|
||||
#define V122 122
|
||||
#define V123 123
|
||||
#define V124 124
|
||||
#define V125 125
|
||||
#define V126 126
|
||||
#define V127 127
|
||||
#endif
|
||||
|
||||
// Initial syntax:
|
||||
#define BLYNK_WRITE_2(pin) \
|
||||
void BlynkWidgetWrite ## pin (BlynkReq BLYNK_UNUSED &request, const BlynkParam BLYNK_UNUSED ¶m)
|
||||
|
||||
#define BLYNK_READ_2(pin) \
|
||||
void BlynkWidgetRead ## pin (BlynkReq BLYNK_UNUSED &request)
|
||||
|
||||
#define BLYNK_WRITE_DEFAULT() BLYNK_WRITE_2(Default)
|
||||
#define BLYNK_READ_DEFAULT() BLYNK_READ_2(Default)
|
||||
|
||||
#define BLYNK_WRITE(pin) BLYNK_WRITE_2(pin)
|
||||
#define BLYNK_READ(pin) BLYNK_READ_2(pin)
|
||||
|
||||
// New, more readable syntax:
|
||||
#define BLYNK_IN_2(pin) \
|
||||
void BlynkWidgetWrite ## pin (BlynkReq BLYNK_UNUSED &request, const BlynkParam BLYNK_UNUSED &getValue)
|
||||
|
||||
#define BLYNK_OUT_2(pin) \
|
||||
void BlynkWidgetRead ## pin (BlynkReq BLYNK_UNUSED &request)
|
||||
|
||||
#define BLYNK_INPUT_DEFAULT() BLYNK_IN_2(Default)
|
||||
#define BLYNK_OUTPUT_DEFAULT() BLYNK_OUT_2(Default)
|
||||
|
||||
#define BLYNK_INPUT(pin) BLYNK_IN_2(pin)
|
||||
#define BLYNK_OUTPUT(pin) BLYNK_OUT_2(pin)
|
||||
|
||||
// Additional handlers
|
||||
#define BLYNK_CONNECTED() void BlynkOnConnected()
|
||||
#define BLYNK_DISCONNECTED() void BlynkOnDisconnected()
|
||||
|
||||
// Advanced functions
|
||||
|
||||
#define BLYNK_VAR_INT(name, pin) \
|
||||
int name; \
|
||||
BLYNK_WRITE(pin) { name = param.asInt(); } \
|
||||
BLYNK_READ(pin) { Blynk.virtualWrite(pin, name); }
|
||||
|
||||
#define BLYNK_VAR_LONG(name, pin) \
|
||||
long name; \
|
||||
BLYNK_WRITE(pin) { name = param.asLong(); } \
|
||||
BLYNK_READ(pin) { Blynk.virtualWrite(pin, name); }
|
||||
|
||||
#ifndef BLYNK_NO_FLOAT
|
||||
#define BLYNK_VAR_DOUBLE(name, pin) \
|
||||
double name; \
|
||||
BLYNK_WRITE(pin) { name = param.asDouble(); } \
|
||||
BLYNK_READ(pin) { Blynk.virtualWrite(pin, name); }
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO
|
||||
#define BLYNK_VAR_STRING(name, pin) \
|
||||
String name; \
|
||||
BLYNK_WRITE(pin) { name = param.asStr(); } \
|
||||
BLYNK_READ(pin) { Blynk.virtualWrite(pin, name); }
|
||||
#endif
|
||||
|
||||
// Default read/write handlers (you can redefine them in your code)
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct BlynkReq
|
||||
{
|
||||
uint8_t pin;
|
||||
};
|
||||
|
||||
typedef void (*WidgetReadHandler)(BlynkReq BLYNK_UNUSED &request);
|
||||
typedef void (*WidgetWriteHandler)(BlynkReq BLYNK_UNUSED &request, const BlynkParam BLYNK_UNUSED ¶m);
|
||||
|
||||
WidgetReadHandler GetReadHandler(uint8_t pin);
|
||||
WidgetWriteHandler GetWriteHandler(uint8_t pin);
|
||||
|
||||
// Declare placeholders
|
||||
BLYNK_READ();
|
||||
BLYNK_WRITE();
|
||||
void BlynkNoOpCbk();
|
||||
|
||||
// Declare all pin handlers (you can redefine them in your code)
|
||||
BLYNK_CONNECTED();
|
||||
BLYNK_DISCONNECTED();
|
||||
|
||||
// Internal Virtual Pins
|
||||
BLYNK_WRITE(InternalPinACON);
|
||||
BLYNK_WRITE(InternalPinADIS);
|
||||
BLYNK_WRITE(InternalPinRTC);
|
||||
BLYNK_WRITE(InternalPinOTA);
|
||||
|
||||
// Aliases
|
||||
#define BLYNK_APP_CONNECTED() BLYNK_WRITE(InternalPinACON)
|
||||
#define BLYNK_APP_DISCONNECTED() BLYNK_WRITE(InternalPinADIS)
|
||||
|
||||
// Regular Virtual Pins
|
||||
BLYNK_READ_DEFAULT();
|
||||
BLYNK_WRITE_DEFAULT();
|
||||
|
||||
BLYNK_READ(0 );
|
||||
BLYNK_READ(1 );
|
||||
BLYNK_READ(2 );
|
||||
BLYNK_READ(3 );
|
||||
BLYNK_READ(4 );
|
||||
BLYNK_READ(5 );
|
||||
BLYNK_READ(6 );
|
||||
BLYNK_READ(7 );
|
||||
BLYNK_READ(8 );
|
||||
BLYNK_READ(9 );
|
||||
BLYNK_READ(10);
|
||||
BLYNK_READ(11);
|
||||
BLYNK_READ(12);
|
||||
BLYNK_READ(13);
|
||||
BLYNK_READ(14);
|
||||
BLYNK_READ(15);
|
||||
BLYNK_READ(16);
|
||||
BLYNK_READ(17);
|
||||
BLYNK_READ(18);
|
||||
BLYNK_READ(19);
|
||||
BLYNK_READ(20);
|
||||
BLYNK_READ(21);
|
||||
BLYNK_READ(22);
|
||||
BLYNK_READ(23);
|
||||
BLYNK_READ(24);
|
||||
BLYNK_READ(25);
|
||||
BLYNK_READ(26);
|
||||
BLYNK_READ(27);
|
||||
BLYNK_READ(28);
|
||||
BLYNK_READ(29);
|
||||
BLYNK_READ(30);
|
||||
BLYNK_READ(31);
|
||||
#ifdef BLYNK_USE_128_VPINS
|
||||
BLYNK_READ(32);
|
||||
BLYNK_READ(33);
|
||||
BLYNK_READ(34);
|
||||
BLYNK_READ(35);
|
||||
BLYNK_READ(36);
|
||||
BLYNK_READ(37);
|
||||
BLYNK_READ(38);
|
||||
BLYNK_READ(39);
|
||||
BLYNK_READ(40);
|
||||
BLYNK_READ(41);
|
||||
BLYNK_READ(42);
|
||||
BLYNK_READ(43);
|
||||
BLYNK_READ(44);
|
||||
BLYNK_READ(45);
|
||||
BLYNK_READ(46);
|
||||
BLYNK_READ(47);
|
||||
BLYNK_READ(48);
|
||||
BLYNK_READ(49);
|
||||
BLYNK_READ(50);
|
||||
BLYNK_READ(51);
|
||||
BLYNK_READ(52);
|
||||
BLYNK_READ(53);
|
||||
BLYNK_READ(54);
|
||||
BLYNK_READ(55);
|
||||
BLYNK_READ(56);
|
||||
BLYNK_READ(57);
|
||||
BLYNK_READ(58);
|
||||
BLYNK_READ(59);
|
||||
BLYNK_READ(60);
|
||||
BLYNK_READ(61);
|
||||
BLYNK_READ(62);
|
||||
BLYNK_READ(63);
|
||||
BLYNK_READ(64);
|
||||
BLYNK_READ(65);
|
||||
BLYNK_READ(66);
|
||||
BLYNK_READ(67);
|
||||
BLYNK_READ(68);
|
||||
BLYNK_READ(69);
|
||||
BLYNK_READ(70);
|
||||
BLYNK_READ(71);
|
||||
BLYNK_READ(72);
|
||||
BLYNK_READ(73);
|
||||
BLYNK_READ(74);
|
||||
BLYNK_READ(75);
|
||||
BLYNK_READ(76);
|
||||
BLYNK_READ(77);
|
||||
BLYNK_READ(78);
|
||||
BLYNK_READ(79);
|
||||
BLYNK_READ(80);
|
||||
BLYNK_READ(81);
|
||||
BLYNK_READ(82);
|
||||
BLYNK_READ(83);
|
||||
BLYNK_READ(84);
|
||||
BLYNK_READ(85);
|
||||
BLYNK_READ(86);
|
||||
BLYNK_READ(87);
|
||||
BLYNK_READ(88);
|
||||
BLYNK_READ(89);
|
||||
BLYNK_READ(90);
|
||||
BLYNK_READ(91);
|
||||
BLYNK_READ(92);
|
||||
BLYNK_READ(93);
|
||||
BLYNK_READ(94);
|
||||
BLYNK_READ(95);
|
||||
BLYNK_READ(96);
|
||||
BLYNK_READ(97);
|
||||
BLYNK_READ(98);
|
||||
BLYNK_READ(99);
|
||||
BLYNK_READ(100);
|
||||
BLYNK_READ(101);
|
||||
BLYNK_READ(102);
|
||||
BLYNK_READ(103);
|
||||
BLYNK_READ(104);
|
||||
BLYNK_READ(105);
|
||||
BLYNK_READ(106);
|
||||
BLYNK_READ(107);
|
||||
BLYNK_READ(108);
|
||||
BLYNK_READ(109);
|
||||
BLYNK_READ(110);
|
||||
BLYNK_READ(111);
|
||||
BLYNK_READ(112);
|
||||
BLYNK_READ(113);
|
||||
BLYNK_READ(114);
|
||||
BLYNK_READ(115);
|
||||
BLYNK_READ(116);
|
||||
BLYNK_READ(117);
|
||||
BLYNK_READ(118);
|
||||
BLYNK_READ(119);
|
||||
BLYNK_READ(120);
|
||||
BLYNK_READ(121);
|
||||
BLYNK_READ(122);
|
||||
BLYNK_READ(123);
|
||||
BLYNK_READ(124);
|
||||
BLYNK_READ(125);
|
||||
BLYNK_READ(126);
|
||||
BLYNK_READ(127);
|
||||
#endif
|
||||
|
||||
BLYNK_WRITE(0 );
|
||||
BLYNK_WRITE(1 );
|
||||
BLYNK_WRITE(2 );
|
||||
BLYNK_WRITE(3 );
|
||||
BLYNK_WRITE(4 );
|
||||
BLYNK_WRITE(5 );
|
||||
BLYNK_WRITE(6 );
|
||||
BLYNK_WRITE(7 );
|
||||
BLYNK_WRITE(8 );
|
||||
BLYNK_WRITE(9 );
|
||||
BLYNK_WRITE(10);
|
||||
BLYNK_WRITE(11);
|
||||
BLYNK_WRITE(12);
|
||||
BLYNK_WRITE(13);
|
||||
BLYNK_WRITE(14);
|
||||
BLYNK_WRITE(15);
|
||||
BLYNK_WRITE(16);
|
||||
BLYNK_WRITE(17);
|
||||
BLYNK_WRITE(18);
|
||||
BLYNK_WRITE(19);
|
||||
BLYNK_WRITE(20);
|
||||
BLYNK_WRITE(21);
|
||||
BLYNK_WRITE(22);
|
||||
BLYNK_WRITE(23);
|
||||
BLYNK_WRITE(24);
|
||||
BLYNK_WRITE(25);
|
||||
BLYNK_WRITE(26);
|
||||
BLYNK_WRITE(27);
|
||||
BLYNK_WRITE(28);
|
||||
BLYNK_WRITE(29);
|
||||
BLYNK_WRITE(30);
|
||||
BLYNK_WRITE(31);
|
||||
#ifdef BLYNK_USE_128_VPINS
|
||||
BLYNK_WRITE(32);
|
||||
BLYNK_WRITE(33);
|
||||
BLYNK_WRITE(34);
|
||||
BLYNK_WRITE(35);
|
||||
BLYNK_WRITE(36);
|
||||
BLYNK_WRITE(37);
|
||||
BLYNK_WRITE(38);
|
||||
BLYNK_WRITE(39);
|
||||
BLYNK_WRITE(40);
|
||||
BLYNK_WRITE(41);
|
||||
BLYNK_WRITE(42);
|
||||
BLYNK_WRITE(43);
|
||||
BLYNK_WRITE(44);
|
||||
BLYNK_WRITE(45);
|
||||
BLYNK_WRITE(46);
|
||||
BLYNK_WRITE(47);
|
||||
BLYNK_WRITE(48);
|
||||
BLYNK_WRITE(49);
|
||||
BLYNK_WRITE(50);
|
||||
BLYNK_WRITE(51);
|
||||
BLYNK_WRITE(52);
|
||||
BLYNK_WRITE(53);
|
||||
BLYNK_WRITE(54);
|
||||
BLYNK_WRITE(55);
|
||||
BLYNK_WRITE(56);
|
||||
BLYNK_WRITE(57);
|
||||
BLYNK_WRITE(58);
|
||||
BLYNK_WRITE(59);
|
||||
BLYNK_WRITE(60);
|
||||
BLYNK_WRITE(61);
|
||||
BLYNK_WRITE(62);
|
||||
BLYNK_WRITE(63);
|
||||
BLYNK_WRITE(64);
|
||||
BLYNK_WRITE(65);
|
||||
BLYNK_WRITE(66);
|
||||
BLYNK_WRITE(67);
|
||||
BLYNK_WRITE(68);
|
||||
BLYNK_WRITE(69);
|
||||
BLYNK_WRITE(70);
|
||||
BLYNK_WRITE(71);
|
||||
BLYNK_WRITE(72);
|
||||
BLYNK_WRITE(73);
|
||||
BLYNK_WRITE(74);
|
||||
BLYNK_WRITE(75);
|
||||
BLYNK_WRITE(76);
|
||||
BLYNK_WRITE(77);
|
||||
BLYNK_WRITE(78);
|
||||
BLYNK_WRITE(79);
|
||||
BLYNK_WRITE(80);
|
||||
BLYNK_WRITE(81);
|
||||
BLYNK_WRITE(82);
|
||||
BLYNK_WRITE(83);
|
||||
BLYNK_WRITE(84);
|
||||
BLYNK_WRITE(85);
|
||||
BLYNK_WRITE(86);
|
||||
BLYNK_WRITE(87);
|
||||
BLYNK_WRITE(88);
|
||||
BLYNK_WRITE(89);
|
||||
BLYNK_WRITE(90);
|
||||
BLYNK_WRITE(91);
|
||||
BLYNK_WRITE(92);
|
||||
BLYNK_WRITE(93);
|
||||
BLYNK_WRITE(94);
|
||||
BLYNK_WRITE(95);
|
||||
BLYNK_WRITE(96);
|
||||
BLYNK_WRITE(97);
|
||||
BLYNK_WRITE(98);
|
||||
BLYNK_WRITE(99);
|
||||
BLYNK_WRITE(100);
|
||||
BLYNK_WRITE(101);
|
||||
BLYNK_WRITE(102);
|
||||
BLYNK_WRITE(103);
|
||||
BLYNK_WRITE(104);
|
||||
BLYNK_WRITE(105);
|
||||
BLYNK_WRITE(106);
|
||||
BLYNK_WRITE(107);
|
||||
BLYNK_WRITE(108);
|
||||
BLYNK_WRITE(109);
|
||||
BLYNK_WRITE(110);
|
||||
BLYNK_WRITE(111);
|
||||
BLYNK_WRITE(112);
|
||||
BLYNK_WRITE(113);
|
||||
BLYNK_WRITE(114);
|
||||
BLYNK_WRITE(115);
|
||||
BLYNK_WRITE(116);
|
||||
BLYNK_WRITE(117);
|
||||
BLYNK_WRITE(118);
|
||||
BLYNK_WRITE(119);
|
||||
BLYNK_WRITE(120);
|
||||
BLYNK_WRITE(121);
|
||||
BLYNK_WRITE(122);
|
||||
BLYNK_WRITE(123);
|
||||
BLYNK_WRITE(124);
|
||||
BLYNK_WRITE(125);
|
||||
BLYNK_WRITE(126);
|
||||
BLYNK_WRITE(127);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,379 +0,0 @@
|
||||
/**
|
||||
* @file BlynkParam.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Jan 2015
|
||||
* @brief Container for handler parameters
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkParam_h
|
||||
#define BlynkParam_h
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "BlynkConfig.h"
|
||||
#include "BlynkDebug.h"
|
||||
|
||||
#define BLYNK_PARAM_KV(k, v) k "\0" v "\0"
|
||||
|
||||
class BlynkParam
|
||||
{
|
||||
public:
|
||||
class iterator
|
||||
{
|
||||
public:
|
||||
iterator(const char* c, const char* l) : ptr(c), limit(l) {}
|
||||
static iterator invalid() { return iterator(NULL, NULL); }
|
||||
|
||||
operator const char* () const { return asStr(); }
|
||||
operator int () const { return asInt(); }
|
||||
const char* asStr() const { return ptr; }
|
||||
const char* asString() const { return ptr; }
|
||||
int asInt() const { if(!isValid()) return 0; return atoi(ptr); }
|
||||
long asLong() const { if(!isValid()) return 0; return atol(ptr); }
|
||||
//long long asLongLong() const { return atoll(ptr); }
|
||||
#ifndef BLYNK_NO_FLOAT
|
||||
double asDouble() const { if(!isValid()) return 0; return atof(ptr); }
|
||||
float asFloat() const { if(!isValid()) return 0; return atof(ptr); }
|
||||
#endif
|
||||
bool isValid() const { return ptr != NULL && ptr < limit; }
|
||||
bool isEmpty() const { if(!isValid()) return true; return *ptr == '\0'; }
|
||||
|
||||
bool operator < (const iterator& it) const { return ptr < it.ptr; }
|
||||
bool operator >= (const iterator& it) const { return ptr >= it.ptr; }
|
||||
|
||||
iterator& operator ++() {
|
||||
if(isValid()) {
|
||||
ptr += strlen(ptr) + 1;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
private:
|
||||
const char* ptr;
|
||||
const char* limit;
|
||||
};
|
||||
|
||||
public:
|
||||
explicit
|
||||
BlynkParam(void* addr, size_t length)
|
||||
: buff((char*)addr), len(length), buff_size(length)
|
||||
{}
|
||||
|
||||
explicit
|
||||
BlynkParam(void* addr, size_t length, size_t buffsize)
|
||||
: buff((char*)addr), len(length), buff_size(buffsize)
|
||||
{}
|
||||
|
||||
const char* asStr() const { return buff; }
|
||||
const char* asString() const { return buff; }
|
||||
int asInt() const { return atoi(buff); }
|
||||
long asLong() const { return atol(buff); }
|
||||
//long long asLongLong() const { return atoll(buff); }
|
||||
#ifndef BLYNK_NO_FLOAT
|
||||
double asDouble() const { return atof(buff); }
|
||||
float asFloat() const { return atof(buff); }
|
||||
#endif
|
||||
bool isEmpty() const { return *buff == '\0'; }
|
||||
|
||||
iterator begin() const { return iterator(buff, buff+len); }
|
||||
iterator end() const { return iterator(buff+len, buff+len); }
|
||||
|
||||
iterator operator[](int index) const;
|
||||
iterator operator[](const char* key) const;
|
||||
|
||||
void* getBuffer() const { return (void*)buff; }
|
||||
size_t getLength() const { return len; }
|
||||
|
||||
// Modification
|
||||
void add(int value);
|
||||
void add(unsigned int value);
|
||||
void add(long value);
|
||||
void add(unsigned long value);
|
||||
void add(long long value);
|
||||
void add(unsigned long long value);
|
||||
#ifndef BLYNK_NO_FLOAT
|
||||
void add(float value);
|
||||
void add(double value);
|
||||
#endif
|
||||
void add(const char* str);
|
||||
void add(const void* b, size_t l);
|
||||
#if defined(ARDUINO) || defined(SPARK) || defined(PARTICLE)
|
||||
void add(const String& str);
|
||||
#if defined(BLYNK_HAS_PROGMEM)
|
||||
void add(const __FlashStringHelper* str);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void add_multi(T last) {
|
||||
add(last);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void add_multi(T head, Args... tail) {
|
||||
add(head);
|
||||
add_multi(tail...);
|
||||
}
|
||||
|
||||
template <typename TV>
|
||||
void add_key(const char* key, const TV& val) {
|
||||
add(key);
|
||||
add(val);
|
||||
}
|
||||
|
||||
protected:
|
||||
char* buff;
|
||||
size_t len;
|
||||
size_t buff_size;
|
||||
};
|
||||
|
||||
|
||||
class BlynkParamAllocated
|
||||
: public BlynkParam
|
||||
{
|
||||
public:
|
||||
BlynkParamAllocated(size_t size)
|
||||
: BlynkParam(malloc(size), 0, size)
|
||||
{}
|
||||
~BlynkParamAllocated() {
|
||||
free(buff);
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
BlynkParam::iterator BlynkParam::operator[](int index) const
|
||||
{
|
||||
const iterator e = end();
|
||||
for (iterator it = begin(); it < e; ++it) {
|
||||
if (!index--) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return iterator::invalid();
|
||||
}
|
||||
|
||||
inline
|
||||
BlynkParam::iterator BlynkParam::operator[](const char* key) const
|
||||
{
|
||||
const iterator e = end();
|
||||
for (iterator it = begin(); it < e; ++it) {
|
||||
if (!strcmp(it.asStr(), key)) {
|
||||
return ++it;
|
||||
}
|
||||
++it;
|
||||
if (it >= e) break;
|
||||
}
|
||||
return iterator::invalid();
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(const void* b, size_t l)
|
||||
{
|
||||
if (len + l > buff_size)
|
||||
return;
|
||||
memcpy(buff+len, b, l);
|
||||
len += l;
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(const char* str)
|
||||
{
|
||||
if (str == NULL) {
|
||||
buff[len++] = '\0';
|
||||
return;
|
||||
}
|
||||
add(str, strlen(str)+1);
|
||||
}
|
||||
|
||||
#if defined(ARDUINO) || defined(SPARK) || defined(PARTICLE)
|
||||
inline
|
||||
void BlynkParam::add(const String& str)
|
||||
{
|
||||
#if defined(ARDUINO_AVR_DIGISPARK) \
|
||||
|| defined(__ARDUINO_X86__) \
|
||||
|| defined(__RFduino__)
|
||||
|
||||
size_t len = str.length()+1;
|
||||
char buff[len];
|
||||
const_cast<String&>(str).toCharArray(buff, len);
|
||||
add(buff, len);
|
||||
#else
|
||||
add(str.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(BLYNK_HAS_PROGMEM)
|
||||
|
||||
inline
|
||||
void BlynkParam::add(const __FlashStringHelper* ifsh)
|
||||
{
|
||||
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
|
||||
size_t l = strlen_P(p) + 1;
|
||||
if (len + l > buff_size)
|
||||
return;
|
||||
memcpy_P(buff+len, p, l);
|
||||
len += l;
|
||||
buff[len] = '\0';
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__AVR__) || defined (ARDUINO_ARCH_ARC32)
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
inline
|
||||
void BlynkParam::add(int value)
|
||||
{
|
||||
char str[2 + 8 * sizeof(value)];
|
||||
itoa(value, str, 10);
|
||||
add(str);
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(unsigned int value)
|
||||
{
|
||||
char str[1 + 8 * sizeof(value)];
|
||||
utoa(value, str, 10);
|
||||
add(str);
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(long value)
|
||||
{
|
||||
char str[2 + 8 * sizeof(value)];
|
||||
ltoa(value, str, 10);
|
||||
add(str);
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(unsigned long value)
|
||||
{
|
||||
char str[1 + 8 * sizeof(value)];
|
||||
ultoa(value, str, 10);
|
||||
add(str);
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(long long value) // TODO: this currently adds just a long
|
||||
{
|
||||
char str[2 + 8 * sizeof(value)];
|
||||
ltoa(value, str, 10);
|
||||
add(str);
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(unsigned long long value) // TODO: this currently adds just a long
|
||||
{
|
||||
char str[1 + 8 * sizeof(value)];
|
||||
ultoa(value, str, 10);
|
||||
add(str);
|
||||
}
|
||||
|
||||
#ifndef BLYNK_NO_FLOAT
|
||||
|
||||
inline
|
||||
void BlynkParam::add(float value)
|
||||
{
|
||||
char str[33];
|
||||
dtostrf(value, 5, 3, str);
|
||||
add(str);
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(double value)
|
||||
{
|
||||
char str[33];
|
||||
dtostrf(value, 5, 7, str);
|
||||
add(str);
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
inline
|
||||
void BlynkParam::add(int value)
|
||||
{
|
||||
len += snprintf(buff+len, buff_size-len, "%i", value)+1;
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(unsigned int value)
|
||||
{
|
||||
len += snprintf(buff+len, buff_size-len, "%u", value)+1;
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(long value)
|
||||
{
|
||||
len += snprintf(buff+len, buff_size-len, "%li", value)+1;
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(unsigned long value)
|
||||
{
|
||||
len += snprintf(buff+len, buff_size-len, "%lu", value)+1;
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(long long value)
|
||||
{
|
||||
len += snprintf(buff+len, buff_size-len, "%lli", value)+1;
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(unsigned long long value)
|
||||
{
|
||||
len += snprintf(buff+len, buff_size-len, "%llu", value)+1;
|
||||
}
|
||||
|
||||
#ifndef BLYNK_NO_FLOAT
|
||||
|
||||
#if defined(BLYNK_USE_INTERNAL_DTOSTRF)
|
||||
|
||||
extern char* dtostrf_internal(double number, signed char width, unsigned char prec, char *s);
|
||||
|
||||
inline
|
||||
void BlynkParam::add(float value)
|
||||
{
|
||||
char str[33];
|
||||
dtostrf_internal(value, 5, 3, str);
|
||||
add(str);
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(double value)
|
||||
{
|
||||
char str[33];
|
||||
dtostrf_internal(value, 5, 7, str);
|
||||
add(str);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline
|
||||
void BlynkParam::add(float value)
|
||||
{
|
||||
len += snprintf(buff+len, buff_size-len, "%2.3f", value)+1;
|
||||
}
|
||||
|
||||
inline
|
||||
void BlynkParam::add(double value)
|
||||
{
|
||||
len += snprintf(buff+len, buff_size-len, "%2.7f", value)+1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
@ -1,535 +0,0 @@
|
||||
/**
|
||||
* @file BlynkProtocol.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Jan 2015
|
||||
* @brief Blynk protocol implementation
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkProtocol_h
|
||||
#define BlynkProtocol_h
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "BlynkDebug.h"
|
||||
#include "BlynkProtocolDefs.h"
|
||||
#include "BlynkApi.h"
|
||||
#include "BlynkUtility.h"
|
||||
|
||||
template <class Transp>
|
||||
class BlynkProtocol
|
||||
: public BlynkApi< BlynkProtocol<Transp> >
|
||||
{
|
||||
friend class BlynkApi< BlynkProtocol<Transp> >;
|
||||
public:
|
||||
enum BlynkState {
|
||||
CONNECTING,
|
||||
CONNECTED,
|
||||
DISCONNECTED,
|
||||
};
|
||||
|
||||
BlynkProtocol(Transp& transp)
|
||||
: conn(transp)
|
||||
, authkey(NULL)
|
||||
, redir_serv(NULL)
|
||||
, lastActivityIn(0)
|
||||
, lastActivityOut(0)
|
||||
, lastHeartbeat(0)
|
||||
, msgIdOut(0)
|
||||
, msgIdOutOverride(0)
|
||||
, nesting(0)
|
||||
, state(CONNECTING)
|
||||
{}
|
||||
|
||||
bool connected() { return state == CONNECTED; }
|
||||
|
||||
bool connect(uint32_t timeout = BLYNK_TIMEOUT_MS*3) {
|
||||
conn.disconnect();
|
||||
state = CONNECTING;
|
||||
millis_time_t started = BlynkMillis();
|
||||
while ((state != CONNECTED) &&
|
||||
(BlynkMillis() - started < timeout))
|
||||
{
|
||||
run();
|
||||
}
|
||||
return state == CONNECTED;
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
conn.disconnect();
|
||||
state = DISCONNECTED;
|
||||
BLYNK_LOG1(BLYNK_F("Disconnected"));
|
||||
}
|
||||
|
||||
bool run(bool avail = false);
|
||||
|
||||
// TODO: Fixme
|
||||
void startSession() {
|
||||
conn.connect();
|
||||
state = CONNECTING;
|
||||
msgIdOut = 0;
|
||||
lastHeartbeat = lastActivityIn = lastActivityOut = (BlynkMillis() - 5000UL);
|
||||
}
|
||||
|
||||
void sendCmd(uint8_t cmd, uint16_t id = 0, const void* data = NULL, size_t length = 0, const void* data2 = NULL, size_t length2 = 0);
|
||||
|
||||
private:
|
||||
|
||||
void internalReconnect() {
|
||||
state = CONNECTING;
|
||||
conn.disconnect();
|
||||
BlynkOnDisconnected();
|
||||
}
|
||||
|
||||
int readHeader(BlynkHeader& hdr);
|
||||
uint16_t getNextMsgId();
|
||||
|
||||
protected:
|
||||
void begin(const char* auth) {
|
||||
this->authkey = auth;
|
||||
lastHeartbeat = lastActivityIn = lastActivityOut = (BlynkMillis() - 5000UL);
|
||||
|
||||
#if defined(BLYNK_NO_FANCY_LOGO)
|
||||
BLYNK_LOG1(BLYNK_F("Blynk v" BLYNK_VERSION " on " BLYNK_INFO_DEVICE));
|
||||
#else
|
||||
BLYNK_LOG1(BLYNK_F(BLYNK_NEWLINE
|
||||
" ___ __ __" BLYNK_NEWLINE
|
||||
" / _ )/ /_ _____ / /__" BLYNK_NEWLINE
|
||||
" / _ / / // / _ \\/ '_/" BLYNK_NEWLINE
|
||||
" /____/_/\\_, /_//_/_/\\_\\" BLYNK_NEWLINE
|
||||
" /___/ v" BLYNK_VERSION " on " BLYNK_INFO_DEVICE BLYNK_NEWLINE
|
||||
BLYNK_NEWLINE
|
||||
" Give Blynk a Github star! => https://github.com/blynkkk/blynk-library" BLYNK_NEWLINE
|
||||
));
|
||||
#endif
|
||||
}
|
||||
bool processInput(void);
|
||||
|
||||
Transp& conn;
|
||||
|
||||
private:
|
||||
const char* authkey;
|
||||
char* redir_serv;
|
||||
millis_time_t lastActivityIn;
|
||||
millis_time_t lastActivityOut;
|
||||
union {
|
||||
millis_time_t lastHeartbeat;
|
||||
millis_time_t lastLogin;
|
||||
};
|
||||
uint16_t msgIdOut;
|
||||
uint16_t msgIdOutOverride;
|
||||
uint8_t nesting;
|
||||
protected:
|
||||
BlynkState state;
|
||||
};
|
||||
|
||||
template <class Transp>
|
||||
bool BlynkProtocol<Transp>::run(bool avail)
|
||||
{
|
||||
BLYNK_RUN_YIELD();
|
||||
|
||||
if (state == DISCONNECTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Detect nesting
|
||||
BlynkHelperAutoInc guard(nesting);
|
||||
if (msgIdOutOverride || nesting > 2) {
|
||||
//BLYNK_LOG1(BLYNK_F("Nested run() skipped"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (conn.connected()) {
|
||||
while (avail || conn.available() > 0) {
|
||||
//BLYNK_LOG2(BLYNK_F("Available: "), conn.available());
|
||||
//const unsigned long t = micros();
|
||||
if (!processInput()) {
|
||||
conn.disconnect();
|
||||
// TODO: Only when in direct mode?
|
||||
#ifdef BLYNK_USE_DIRECT_CONNECT
|
||||
state = CONNECTING;
|
||||
#endif
|
||||
BlynkOnDisconnected();
|
||||
return false;
|
||||
}
|
||||
avail = false;
|
||||
//BLYNK_LOG2(BLYNK_F("Proc time: "), micros() - t);
|
||||
}
|
||||
}
|
||||
|
||||
const millis_time_t t = BlynkMillis();
|
||||
|
||||
// Update connection status after running commands
|
||||
const bool tconn = conn.connected();
|
||||
|
||||
if (state == CONNECTED) {
|
||||
if (!tconn) {
|
||||
lastHeartbeat = t;
|
||||
internalReconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (t - lastActivityIn > (1000UL * BLYNK_HEARTBEAT + BLYNK_TIMEOUT_MS*3)) {
|
||||
#ifdef BLYNK_DEBUG
|
||||
BLYNK_LOG6(BLYNK_F("Heartbeat timeout: "), t, BLYNK_F(", "), lastActivityIn, BLYNK_F(", "), lastHeartbeat);
|
||||
#else
|
||||
BLYNK_LOG1(BLYNK_F("Heartbeat timeout"));
|
||||
#endif
|
||||
internalReconnect();
|
||||
return false;
|
||||
} else if ((t - lastActivityIn > 1000UL * BLYNK_HEARTBEAT ||
|
||||
t - lastActivityOut > 1000UL * BLYNK_HEARTBEAT) &&
|
||||
t - lastHeartbeat > BLYNK_TIMEOUT_MS)
|
||||
{
|
||||
// Send ping if we didn't either send or receive something
|
||||
// for BLYNK_HEARTBEAT seconds
|
||||
sendCmd(BLYNK_CMD_PING);
|
||||
lastHeartbeat = t;
|
||||
}
|
||||
} else if (state == CONNECTING) {
|
||||
#ifdef BLYNK_USE_DIRECT_CONNECT
|
||||
if (!tconn)
|
||||
conn.connect();
|
||||
#else
|
||||
if (tconn && (t - lastLogin > BLYNK_TIMEOUT_MS)) {
|
||||
BLYNK_LOG1(BLYNK_F("Login timeout"));
|
||||
conn.disconnect();
|
||||
state = CONNECTING;
|
||||
return false;
|
||||
} else if (!tconn && (t - lastLogin > 5000UL)) {
|
||||
conn.disconnect();
|
||||
if (!conn.connect()) {
|
||||
lastLogin = t;
|
||||
return false;
|
||||
}
|
||||
|
||||
msgIdOut = 1;
|
||||
sendCmd(BLYNK_CMD_LOGIN, 1, authkey, strlen(authkey));
|
||||
lastLogin = lastActivityOut;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Transp>
|
||||
BLYNK_FORCE_INLINE
|
||||
bool BlynkProtocol<Transp>::processInput(void)
|
||||
{
|
||||
BlynkHeader hdr;
|
||||
const int ret = readHeader(hdr);
|
||||
|
||||
if (ret == 0) {
|
||||
return true; // Considered OK (no data on input)
|
||||
}
|
||||
|
||||
if (ret < 0 || hdr.msg_id == 0) {
|
||||
#ifdef BLYNK_DEBUG
|
||||
BLYNK_LOG2(BLYNK_F("Bad hdr len: "), ret);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hdr.type == BLYNK_CMD_RESPONSE) {
|
||||
lastActivityIn = BlynkMillis();
|
||||
|
||||
#ifndef BLYNK_USE_DIRECT_CONNECT
|
||||
if (state == CONNECTING && (1 == hdr.msg_id)) {
|
||||
switch (hdr.length) {
|
||||
case BLYNK_SUCCESS:
|
||||
case BLYNK_ALREADY_REGISTERED:
|
||||
BLYNK_LOG3(BLYNK_F("Ready (ping: "), lastActivityIn-lastHeartbeat, BLYNK_F("ms)."));
|
||||
lastHeartbeat = lastActivityIn;
|
||||
state = CONNECTED;
|
||||
#ifdef BLYNK_DEBUG
|
||||
if (size_t ram = BlynkFreeRam()) {
|
||||
BLYNK_LOG2(BLYNK_F("Free RAM: "), ram);
|
||||
}
|
||||
#endif
|
||||
this->sendInfo();
|
||||
BLYNK_RUN_YIELD();
|
||||
BlynkOnConnected();
|
||||
return true;
|
||||
case BLYNK_INVALID_TOKEN:
|
||||
BLYNK_LOG1(BLYNK_F("Invalid auth token"));
|
||||
break;
|
||||
default:
|
||||
BLYNK_LOG2(BLYNK_F("Connect failed. code: "), hdr.length);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (BLYNK_NOT_AUTHENTICATED == hdr.length) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
// TODO: return code may indicate App presence
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hdr.length > BLYNK_MAX_READBYTES) {
|
||||
BLYNK_LOG2(BLYNK_F("Packet too big: "), hdr.length);
|
||||
// TODO: Flush
|
||||
internalReconnect();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t inputBuffer[hdr.length+1]; // Add 1 to zero-terminate
|
||||
if (hdr.length != conn.read(inputBuffer, hdr.length)) {
|
||||
#ifdef BLYNK_DEBUG
|
||||
BLYNK_LOG1(BLYNK_F("Can't read body"));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
inputBuffer[hdr.length] = '\0';
|
||||
|
||||
BLYNK_DBG_DUMP(">", inputBuffer, hdr.length);
|
||||
|
||||
lastActivityIn = BlynkMillis();
|
||||
|
||||
switch (hdr.type)
|
||||
{
|
||||
case BLYNK_CMD_LOGIN: {
|
||||
#ifdef BLYNK_USE_DIRECT_CONNECT
|
||||
if (strncmp(authkey, (char*)inputBuffer, 32)) {
|
||||
BLYNK_LOG1(BLYNK_F("Invalid token"));
|
||||
sendCmd(BLYNK_CMD_RESPONSE, hdr.msg_id, NULL, BLYNK_INVALID_TOKEN);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (state == CONNECTING) {
|
||||
BLYNK_LOG1(BLYNK_F("Ready"));
|
||||
state = CONNECTED;
|
||||
#ifdef BLYNK_DEBUG
|
||||
if (size_t ram = BlynkFreeRam()) {
|
||||
BLYNK_LOG2(BLYNK_F("Free RAM: "), ram);
|
||||
}
|
||||
#endif
|
||||
this->sendInfo();
|
||||
BLYNK_RUN_YIELD();
|
||||
BlynkOnConnected();
|
||||
}
|
||||
sendCmd(BLYNK_CMD_RESPONSE, hdr.msg_id, NULL, BLYNK_SUCCESS);
|
||||
} break;
|
||||
case BLYNK_CMD_PING: {
|
||||
sendCmd(BLYNK_CMD_RESPONSE, hdr.msg_id, NULL, BLYNK_SUCCESS);
|
||||
} break;
|
||||
case BLYNK_CMD_REDIRECT: {
|
||||
if (!redir_serv) {
|
||||
redir_serv = (char*)malloc(32);
|
||||
}
|
||||
BlynkParam param(inputBuffer, hdr.length);
|
||||
uint16_t redir_port = BLYNK_DEFAULT_PORT; // TODO: Fixit
|
||||
|
||||
BlynkParam::iterator it = param.begin();
|
||||
if (it >= param.end())
|
||||
return false;
|
||||
strncpy(redir_serv, it.asStr(), 32);
|
||||
if (++it < param.end())
|
||||
redir_port = it.asLong();
|
||||
BLYNK_LOG4(BLYNK_F("Redirecting to "), redir_serv, ':', redir_port);
|
||||
conn.disconnect();
|
||||
conn.begin(redir_serv, redir_port);
|
||||
state = CONNECTING;
|
||||
lastHeartbeat = lastActivityIn = lastActivityOut = (BlynkMillis() - 5000UL);
|
||||
} break;
|
||||
case BLYNK_CMD_HARDWARE:
|
||||
case BLYNK_CMD_BRIDGE: {
|
||||
msgIdOutOverride = hdr.msg_id;
|
||||
this->processCmd(inputBuffer, hdr.length);
|
||||
msgIdOutOverride = 0;
|
||||
} break;
|
||||
case BLYNK_CMD_INTERNAL: {
|
||||
BlynkReq req = { 0 };
|
||||
BlynkParam param(inputBuffer, hdr.length);
|
||||
BlynkParam::iterator it = param.begin();
|
||||
if (it >= param.end())
|
||||
return true;
|
||||
|
||||
uint32_t cmd32;
|
||||
memcpy(&cmd32, it.asStr(), sizeof(cmd32));
|
||||
|
||||
++it;
|
||||
char* start = (char*)(it).asStr();
|
||||
unsigned length = hdr.length - (start - (char*)inputBuffer);
|
||||
BlynkParam param2(start, length);
|
||||
|
||||
switch (cmd32) {
|
||||
case BLYNK_INT_RTC: BlynkWidgetWriteInternalPinRTC(req, param2); break;
|
||||
case BLYNK_INT_OTA: BlynkWidgetWriteInternalPinOTA(req, param2); break;
|
||||
case BLYNK_INT_ACON: BlynkWidgetWriteInternalPinACON(req, param2); break;
|
||||
case BLYNK_INT_ADIS: BlynkWidgetWriteInternalPinADIS(req, param2); break;
|
||||
#ifdef BLYNK_DEBUG
|
||||
default: BLYNK_LOG2(BLYNK_F("Invalid internal cmd:"), param.asStr());
|
||||
#endif
|
||||
}
|
||||
} break;
|
||||
case BLYNK_CMD_DEBUG_PRINT: {
|
||||
if (hdr.length) {
|
||||
BLYNK_LOG2(BLYNK_F("Server: "), (char*)inputBuffer);
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
#ifdef BLYNK_DEBUG
|
||||
BLYNK_LOG2(BLYNK_F("Invalid header type: "), hdr.type);
|
||||
#endif
|
||||
// TODO: Flush
|
||||
internalReconnect();
|
||||
} break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Transp>
|
||||
int BlynkProtocol<Transp>::readHeader(BlynkHeader& hdr)
|
||||
{
|
||||
size_t rlen = conn.read(&hdr, sizeof(hdr));
|
||||
if (rlen == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sizeof(hdr) != rlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
BLYNK_DBG_DUMP(">", &hdr, sizeof(BlynkHeader));
|
||||
|
||||
hdr.msg_id = ntohs(hdr.msg_id);
|
||||
hdr.length = ntohs(hdr.length);
|
||||
|
||||
return rlen;
|
||||
}
|
||||
|
||||
#ifndef BLYNK_SEND_THROTTLE
|
||||
#define BLYNK_SEND_THROTTLE 0
|
||||
#endif
|
||||
|
||||
#ifndef BLYNK_SEND_CHUNK
|
||||
#define BLYNK_SEND_CHUNK 1024 // Just a big number
|
||||
#endif
|
||||
|
||||
template <class Transp>
|
||||
void BlynkProtocol<Transp>::sendCmd(uint8_t cmd, uint16_t id, const void* data, size_t length, const void* data2, size_t length2)
|
||||
{
|
||||
if (!conn.connected() || (cmd != BLYNK_CMD_RESPONSE && cmd != BLYNK_CMD_PING && cmd != BLYNK_CMD_LOGIN && state != CONNECTED) ) {
|
||||
#ifdef BLYNK_DEBUG_ALL
|
||||
BLYNK_LOG2(BLYNK_F("Cmd skipped:"), cmd);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == id) {
|
||||
id = getNextMsgId();
|
||||
}
|
||||
|
||||
#if defined(BLYNK_MSG_LIMIT) && BLYNK_MSG_LIMIT > 0
|
||||
if (cmd >= BLYNK_CMD_TWEET && cmd <= BLYNK_CMD_HARDWARE) {
|
||||
const millis_time_t allowed_time = BlynkMax(lastActivityOut, lastActivityIn) + 1000/BLYNK_MSG_LIMIT;
|
||||
int32_t wait_time = allowed_time - BlynkMillis();
|
||||
if (wait_time >= 0) {
|
||||
#ifdef BLYNK_DEBUG_ALL
|
||||
BLYNK_LOG2(BLYNK_F("Waiting:"), wait_time);
|
||||
#endif
|
||||
while (wait_time >= 0) {
|
||||
run();
|
||||
wait_time = allowed_time - BlynkMillis();
|
||||
}
|
||||
} else if (nesting == 0) {
|
||||
run();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const size_t full_length = (sizeof(BlynkHeader)) +
|
||||
(data ? length : 0) +
|
||||
(data2 ? length2 : 0);
|
||||
|
||||
#if defined(BLYNK_SEND_ATOMIC) || defined(ESP8266) || defined(ESP32) || defined(SPARK) || defined(PARTICLE) || defined(ENERGIA)
|
||||
// Those have more RAM and like single write at a time...
|
||||
|
||||
uint8_t buff[full_length];
|
||||
|
||||
BlynkHeader* hdr = (BlynkHeader*)buff;
|
||||
hdr->type = cmd;
|
||||
hdr->msg_id = htons(id);
|
||||
hdr->length = htons(length+length2);
|
||||
|
||||
size_t pos = sizeof(BlynkHeader);
|
||||
if (data && length) {
|
||||
memcpy(buff + pos, data, length);
|
||||
pos += length;
|
||||
}
|
||||
if (data2 && length2) {
|
||||
memcpy(buff + pos, data2, length2);
|
||||
}
|
||||
|
||||
size_t wlen = 0;
|
||||
while (wlen < full_length) {
|
||||
const size_t chunk = BlynkMin(size_t(BLYNK_SEND_CHUNK), full_length - wlen);
|
||||
BLYNK_DBG_DUMP("<", buff + wlen, chunk);
|
||||
const size_t w = conn.write(buff + wlen, chunk);
|
||||
BlynkDelay(BLYNK_SEND_THROTTLE);
|
||||
if (w == 0) {
|
||||
#ifdef BLYNK_DEBUG
|
||||
BLYNK_LOG1(BLYNK_F("Cmd error"));
|
||||
#endif
|
||||
conn.disconnect();
|
||||
state = CONNECTING;
|
||||
BlynkOnDisconnected();
|
||||
return;
|
||||
}
|
||||
wlen += w;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
BlynkHeader hdr;
|
||||
hdr.type = cmd;
|
||||
hdr.msg_id = htons(id);
|
||||
hdr.length = htons(length+length2);
|
||||
|
||||
BLYNK_DBG_DUMP("<", &hdr, sizeof(hdr));
|
||||
size_t wlen = conn.write(&hdr, sizeof(hdr));
|
||||
BlynkDelay(BLYNK_SEND_THROTTLE);
|
||||
|
||||
if (cmd != BLYNK_CMD_RESPONSE) {
|
||||
if (length) {
|
||||
BLYNK_DBG_DUMP("<", data, length);
|
||||
wlen += conn.write(data, length);
|
||||
BlynkDelay(BLYNK_SEND_THROTTLE);
|
||||
}
|
||||
if (length2) {
|
||||
BLYNK_DBG_DUMP("<", data2, length2);
|
||||
wlen += conn.write(data2, length2);
|
||||
BlynkDelay(BLYNK_SEND_THROTTLE);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (wlen != full_length) {
|
||||
#ifdef BLYNK_DEBUG
|
||||
BLYNK_LOG4(BLYNK_F("Sent "), wlen, '/', full_length);
|
||||
#endif
|
||||
internalReconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
lastActivityOut = BlynkMillis();
|
||||
|
||||
}
|
||||
|
||||
template <class Transp>
|
||||
uint16_t BlynkProtocol<Transp>::getNextMsgId()
|
||||
{
|
||||
if (msgIdOutOverride != 0)
|
||||
return msgIdOutOverride;
|
||||
if (++msgIdOut == 0)
|
||||
msgIdOut = 1;
|
||||
return msgIdOut;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,140 +0,0 @@
|
||||
/**
|
||||
* @file BlynkProtocolDefs.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Jan 2015
|
||||
* @brief Blynk protocol definitions
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkProtocolDefs_h
|
||||
#define BlynkProtocolDefs_h
|
||||
|
||||
enum BlynkCmd
|
||||
{
|
||||
BLYNK_CMD_RESPONSE = 0,
|
||||
BLYNK_CMD_REGISTER = 1,
|
||||
BLYNK_CMD_LOGIN = 2,
|
||||
BLYNK_CMD_SAVE_PROF = 3,
|
||||
BLYNK_CMD_LOAD_PROF = 4,
|
||||
BLYNK_CMD_GET_TOKEN = 5,
|
||||
BLYNK_CMD_PING = 6,
|
||||
BLYNK_CMD_ACTIVATE = 7,
|
||||
BLYNK_CMD_DEACTIVATE = 8,
|
||||
BLYNK_CMD_REFRESH = 9,
|
||||
BLYNK_CMD_GET_GRAPH_DATA = 10,
|
||||
BLYNK_CMD_GET_GRAPH_DATA_RESPONSE = 11,
|
||||
|
||||
BLYNK_CMD_TWEET = 12,
|
||||
BLYNK_CMD_EMAIL = 13,
|
||||
BLYNK_CMD_NOTIFY = 14,
|
||||
BLYNK_CMD_BRIDGE = 15,
|
||||
BLYNK_CMD_HARDWARE_SYNC = 16,
|
||||
BLYNK_CMD_INTERNAL = 17,
|
||||
BLYNK_CMD_SMS = 18,
|
||||
BLYNK_CMD_PROPERTY = 19,
|
||||
BLYNK_CMD_HARDWARE = 20,
|
||||
|
||||
BLYNK_CMD_CREATE_DASH = 21,
|
||||
BLYNK_CMD_SAVE_DASH = 22,
|
||||
BLYNK_CMD_DELETE_DASH = 23,
|
||||
BLYNK_CMD_LOAD_PROF_GZ = 24,
|
||||
BLYNK_CMD_SYNC = 25,
|
||||
BLYNK_CMD_SHARING = 26,
|
||||
BLYNK_CMD_ADD_PUSH_TOKEN = 27,
|
||||
|
||||
//sharing commands
|
||||
BLYNK_CMD_GET_SHARED_DASH = 29,
|
||||
BLYNK_CMD_GET_SHARE_TOKEN = 30,
|
||||
BLYNK_CMD_REFRESH_SHARE_TOKEN = 31,
|
||||
BLYNK_CMD_SHARE_LOGIN = 32,
|
||||
|
||||
BLYNK_CMD_REDIRECT = 41,
|
||||
|
||||
BLYNK_CMD_DEBUG_PRINT = 55,
|
||||
|
||||
BLYNK_CMD_EVENT_LOG = 64
|
||||
};
|
||||
|
||||
enum BlynkStatus
|
||||
{
|
||||
BLYNK_SUCCESS = 200,
|
||||
BLYNK_QUOTA_LIMIT_EXCEPTION = 1,
|
||||
BLYNK_ILLEGAL_COMMAND = 2,
|
||||
BLYNK_NOT_REGISTERED = 3,
|
||||
BLYNK_ALREADY_REGISTERED = 4,
|
||||
BLYNK_NOT_AUTHENTICATED = 5,
|
||||
BLYNK_NOT_ALLOWED = 6,
|
||||
BLYNK_DEVICE_NOT_IN_NETWORK = 7,
|
||||
BLYNK_NO_ACTIVE_DASHBOARD = 8,
|
||||
BLYNK_INVALID_TOKEN = 9,
|
||||
BLYNK_ILLEGAL_COMMAND_BODY = 11,
|
||||
BLYNK_GET_GRAPH_DATA_EXCEPTION = 12,
|
||||
BLYNK_NO_DATA_EXCEPTION = 17,
|
||||
BLYNK_DEVICE_WENT_OFFLINE = 18,
|
||||
BLYNK_SERVER_EXCEPTION = 19,
|
||||
|
||||
BLYNK_NTF_INVALID_BODY = 13,
|
||||
BLYNK_NTF_NOT_AUTHORIZED = 14,
|
||||
BLYNK_NTF_ECXEPTION = 15,
|
||||
|
||||
BLYNK_TIMEOUT = 16,
|
||||
|
||||
BLYNK_NOT_SUPPORTED_VERSION = 20,
|
||||
BLYNK_ENERGY_LIMIT = 21
|
||||
};
|
||||
|
||||
struct BlynkHeader
|
||||
{
|
||||
uint8_t type;
|
||||
uint16_t msg_id;
|
||||
uint16_t length;
|
||||
}
|
||||
BLYNK_ATTR_PACKED;
|
||||
|
||||
#if defined(ESP32)
|
||||
#include <lwip/ip_addr.h>
|
||||
#elif !defined(htons) && (defined(ARDUINO) || defined(ESP8266) || defined(PARTICLE) || defined(__MBED__))
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define htons(x) ( ((x)<<8) | (((x)>>8)&0xFF) )
|
||||
#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \
|
||||
((x)<< 8 & 0x00FF0000UL) | \
|
||||
((x)>> 8 & 0x0000FF00UL) | \
|
||||
((x)>>24 & 0x000000FFUL) )
|
||||
#define ntohs(x) htons(x)
|
||||
#define ntohl(x) htonl(x)
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define htons(x) (x)
|
||||
#define htonl(x) (x)
|
||||
#define ntohs(x) (x)
|
||||
#define ntohl(x) (x)
|
||||
#else
|
||||
#error byte order problem
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define BLYNK_STR_16(a,b) ((uint16_t(a) << 0) | (uint16_t(b) << 8))
|
||||
#define BLYNK_STR_32(a,b,c,d) ((uint32_t(a) << 0) | (uint32_t(b) << 8) | (uint32_t(c) << 16) | (uint32_t(d) << 24))
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define BLYNK_STR_16(a,b) ((uint16_t(b) << 0) | (uint16_t(a) << 8))
|
||||
#define BLYNK_STR_32(a,b,c,d) ((uint32_t(d) << 0) | (uint32_t(c) << 8) | (uint32_t(b) << 16) | (uint32_t(a) << 24))
|
||||
#else
|
||||
#error byte order problem
|
||||
#endif
|
||||
|
||||
#define BLYNK_HW_PM BLYNK_STR_16('p','m')
|
||||
#define BLYNK_HW_DW BLYNK_STR_16('d','w')
|
||||
#define BLYNK_HW_DR BLYNK_STR_16('d','r')
|
||||
#define BLYNK_HW_AW BLYNK_STR_16('a','w')
|
||||
#define BLYNK_HW_AR BLYNK_STR_16('a','r')
|
||||
#define BLYNK_HW_VW BLYNK_STR_16('v','w')
|
||||
#define BLYNK_HW_VR BLYNK_STR_16('v','r')
|
||||
|
||||
#define BLYNK_INT_RTC BLYNK_STR_32('r','t','c',0)
|
||||
#define BLYNK_INT_OTA BLYNK_STR_32('o','t','a',0)
|
||||
#define BLYNK_INT_ACON BLYNK_STR_32('a','c','o','n')
|
||||
#define BLYNK_INT_ADIS BLYNK_STR_32('a','d','i','s')
|
||||
|
||||
#endif
|
@ -1,47 +0,0 @@
|
||||
class BlynkStackOnly
|
||||
{
|
||||
protected:
|
||||
BlynkStackOnly() {}
|
||||
~BlynkStackOnly() {}
|
||||
|
||||
private:
|
||||
/// @brief Declared as private to prevent usage of dynamic memory
|
||||
void* operator new(size_t size);
|
||||
/// @brief Declared as private to prevent usage of dynamic memory
|
||||
void operator delete(void *p);
|
||||
};
|
||||
|
||||
class BlynkNonCopyable
|
||||
{
|
||||
protected:
|
||||
BlynkNonCopyable(){}
|
||||
~BlynkNonCopyable(){}
|
||||
|
||||
private:
|
||||
/// @brief Declared as private to prevent usage of copy constructor
|
||||
BlynkNonCopyable(const BlynkNonCopyable&);
|
||||
/// @brief Declared as private to prevent usage of assignment operator
|
||||
BlynkNonCopyable& operator=(const BlynkNonCopyable&);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class BlynkSingleton
|
||||
: public BlynkNonCopyable
|
||||
{
|
||||
public:
|
||||
/** @brief Returns the instance of the singleton type
|
||||
When called for the first time, the singleton instance will be
|
||||
created. All subsequent calls will return a reference to the
|
||||
previously created instance.
|
||||
@return The singleton instance
|
||||
*/
|
||||
static T* instance()
|
||||
{
|
||||
static T instance;
|
||||
return &instance;
|
||||
}
|
||||
protected:
|
||||
BlynkSingleton() {}
|
||||
~BlynkSingleton() {}
|
||||
};
|
||||
|
@ -1,291 +0,0 @@
|
||||
/*
|
||||
* SimpleTimer.cpp
|
||||
*
|
||||
* SimpleTimer - A timer library for Arduino.
|
||||
* Author: mromani@ottotecnica.com
|
||||
* Copyright (c) 2010 OTTOTECNICA Italy
|
||||
*
|
||||
* Callback function parameters added & compiler warnings
|
||||
* removed by Bill Knight <billk@rosw.com> 20March2017
|
||||
*
|
||||
* This library is free software; you can redistribute it
|
||||
* and/or modify it under the terms of the GNU Lesser
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will
|
||||
* be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser
|
||||
* General Public License along with this library; if not,
|
||||
* write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "BlynkTimer.h"
|
||||
#include <string.h>
|
||||
|
||||
// Select time function:
|
||||
//static inline unsigned long elapsed() { return micros(); }
|
||||
static inline unsigned long elapsed() { return BlynkMillis(); }
|
||||
|
||||
|
||||
SimpleTimer::SimpleTimer()
|
||||
: numTimers (-1)
|
||||
{
|
||||
}
|
||||
|
||||
void SimpleTimer::init() {
|
||||
unsigned long current_millis = elapsed();
|
||||
|
||||
for (int i = 0; i < MAX_TIMERS; i++) {
|
||||
memset(&timer[i], 0, sizeof (timer_t));
|
||||
timer[i].prev_millis = current_millis;
|
||||
}
|
||||
|
||||
numTimers = 0;
|
||||
}
|
||||
|
||||
|
||||
void SimpleTimer::run() {
|
||||
int i;
|
||||
unsigned long current_millis;
|
||||
|
||||
// get current time
|
||||
current_millis = elapsed();
|
||||
|
||||
for (i = 0; i < MAX_TIMERS; i++) {
|
||||
|
||||
timer[i].toBeCalled = DEFCALL_DONTRUN;
|
||||
|
||||
// no callback == no timer, i.e. jump over empty slots
|
||||
if (timer[i].callback != NULL) {
|
||||
|
||||
// is it time to process this timer ?
|
||||
// see http://arduino.cc/forum/index.php/topic,124048.msg932592.html#msg932592
|
||||
|
||||
if ((current_millis - timer[i].prev_millis) >= timer[i].delay) {
|
||||
|
||||
unsigned long skipTimes = (current_millis - timer[i].prev_millis) / timer[i].delay;
|
||||
// update time
|
||||
timer[i].prev_millis += timer[i].delay * skipTimes;
|
||||
|
||||
// check if the timer callback has to be executed
|
||||
if (timer[i].enabled) {
|
||||
|
||||
// "run forever" timers must always be executed
|
||||
if (timer[i].maxNumRuns == RUN_FOREVER) {
|
||||
timer[i].toBeCalled = DEFCALL_RUNONLY;
|
||||
}
|
||||
// other timers get executed the specified number of times
|
||||
else if (timer[i].numRuns < timer[i].maxNumRuns) {
|
||||
timer[i].toBeCalled = DEFCALL_RUNONLY;
|
||||
timer[i].numRuns++;
|
||||
|
||||
// after the last run, delete the timer
|
||||
if (timer[i].numRuns >= timer[i].maxNumRuns) {
|
||||
timer[i].toBeCalled = DEFCALL_RUNANDDEL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_TIMERS; i++) {
|
||||
if (timer[i].toBeCalled == DEFCALL_DONTRUN)
|
||||
continue;
|
||||
|
||||
if (timer[i].hasParam)
|
||||
(*(timer_callback_p)timer[i].callback)(timer[i].param);
|
||||
else
|
||||
(*(timer_callback)timer[i].callback)();
|
||||
|
||||
if (timer[i].toBeCalled == DEFCALL_RUNANDDEL)
|
||||
deleteTimer(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// find the first available slot
|
||||
// return -1 if none found
|
||||
int SimpleTimer::findFirstFreeSlot() {
|
||||
// all slots are used
|
||||
if (numTimers >= MAX_TIMERS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// return the first slot with no callback (i.e. free)
|
||||
for (int i = 0; i < MAX_TIMERS; i++) {
|
||||
if (timer[i].callback == NULL) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// no free slots found
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int SimpleTimer::setupTimer(unsigned long d, void* f, void* p, bool h, unsigned n) {
|
||||
int freeTimer;
|
||||
|
||||
if (numTimers < 0) {
|
||||
init();
|
||||
}
|
||||
|
||||
freeTimer = findFirstFreeSlot();
|
||||
if (freeTimer < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (f == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
timer[freeTimer].delay = d;
|
||||
timer[freeTimer].callback = f;
|
||||
timer[freeTimer].param = p;
|
||||
timer[freeTimer].hasParam = h;
|
||||
timer[freeTimer].maxNumRuns = n;
|
||||
timer[freeTimer].enabled = true;
|
||||
timer[freeTimer].prev_millis = elapsed();
|
||||
|
||||
numTimers++;
|
||||
|
||||
return freeTimer;
|
||||
}
|
||||
|
||||
|
||||
int SimpleTimer::setTimer(unsigned long d, timer_callback f, unsigned n) {
|
||||
return setupTimer(d, (void *)f, NULL, false, n);
|
||||
}
|
||||
|
||||
int SimpleTimer::setTimer(unsigned long d, timer_callback_p f, void* p, unsigned n) {
|
||||
return setupTimer(d, (void *)f, p, true, n);
|
||||
}
|
||||
|
||||
int SimpleTimer::setInterval(unsigned long d, timer_callback f) {
|
||||
return setupTimer(d, (void *)f, NULL, false, RUN_FOREVER);
|
||||
}
|
||||
|
||||
int SimpleTimer::setInterval(unsigned long d, timer_callback_p f, void* p) {
|
||||
return setupTimer(d, (void *)f, p, true, RUN_FOREVER);
|
||||
}
|
||||
|
||||
int SimpleTimer::setTimeout(unsigned long d, timer_callback f) {
|
||||
return setupTimer(d, (void *)f, NULL, false, RUN_ONCE);
|
||||
}
|
||||
|
||||
int SimpleTimer::setTimeout(unsigned long d, timer_callback_p f, void* p) {
|
||||
return setupTimer(d, (void *)f, p, true, RUN_ONCE);
|
||||
}
|
||||
|
||||
bool SimpleTimer::changeInterval(unsigned numTimer, unsigned long d) {
|
||||
if (numTimer >= MAX_TIMERS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Updates interval of existing specified timer
|
||||
if (timer[numTimer].callback != NULL) {
|
||||
timer[numTimer].delay = d;
|
||||
timer[numTimer].prev_millis = elapsed();
|
||||
return true;
|
||||
}
|
||||
// false return for non-used numTimer, no callback
|
||||
return false;
|
||||
}
|
||||
|
||||
void SimpleTimer::deleteTimer(unsigned timerId) {
|
||||
if (timerId >= MAX_TIMERS) {
|
||||
return;
|
||||
}
|
||||
|
||||
// nothing to delete if no timers are in use
|
||||
if (numTimers == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// don't decrease the number of timers if the
|
||||
// specified slot is already empty
|
||||
if (timer[timerId].callback != NULL) {
|
||||
memset(&timer[timerId], 0, sizeof (timer_t));
|
||||
timer[timerId].prev_millis = elapsed();
|
||||
|
||||
// update number of timers
|
||||
numTimers--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// function contributed by code@rowansimms.com
|
||||
void SimpleTimer::restartTimer(unsigned numTimer) {
|
||||
if (numTimer >= MAX_TIMERS) {
|
||||
return;
|
||||
}
|
||||
|
||||
timer[numTimer].prev_millis = elapsed();
|
||||
}
|
||||
|
||||
|
||||
bool SimpleTimer::isEnabled(unsigned numTimer) {
|
||||
if (numTimer >= MAX_TIMERS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return timer[numTimer].enabled;
|
||||
}
|
||||
|
||||
|
||||
void SimpleTimer::enable(unsigned numTimer) {
|
||||
if (numTimer >= MAX_TIMERS) {
|
||||
return;
|
||||
}
|
||||
|
||||
timer[numTimer].enabled = true;
|
||||
}
|
||||
|
||||
|
||||
void SimpleTimer::disable(unsigned numTimer) {
|
||||
if (numTimer >= MAX_TIMERS) {
|
||||
return;
|
||||
}
|
||||
|
||||
timer[numTimer].enabled = false;
|
||||
}
|
||||
|
||||
void SimpleTimer::enableAll() {
|
||||
// Enable all timers with a callback assigned (used)
|
||||
for (int i = 0; i < MAX_TIMERS; i++) {
|
||||
if (timer[i].callback != NULL && timer[i].numRuns == RUN_FOREVER) {
|
||||
timer[i].enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleTimer::disableAll() {
|
||||
// Disable all timers with a callback assigned (used)
|
||||
for (int i = 0; i < MAX_TIMERS; i++) {
|
||||
if (timer[i].callback != NULL && timer[i].numRuns == RUN_FOREVER) {
|
||||
timer[i].enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleTimer::toggle(unsigned numTimer) {
|
||||
if (numTimer >= MAX_TIMERS) {
|
||||
return;
|
||||
}
|
||||
|
||||
timer[numTimer].enabled = !timer[numTimer].enabled;
|
||||
}
|
||||
|
||||
|
||||
unsigned SimpleTimer::getNumTimers() {
|
||||
return numTimers;
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
/*
|
||||
* SimpleTimer.h
|
||||
*
|
||||
* SimpleTimer - A timer library for Arduino.
|
||||
* Author: mromani@ottotecnica.com
|
||||
* Copyright (c) 2010 OTTOTECNICA Italy
|
||||
*
|
||||
* Modifications by Bill Knight <billk@rosw.com> 18March2017
|
||||
*
|
||||
* This library is free software; you can redistribute it
|
||||
* and/or modify it under the terms of the GNU Lesser
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2.1 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will
|
||||
* be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser
|
||||
* General Public License along with this library; if not,
|
||||
* write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLYNKTIMER_H
|
||||
#define BLYNKTIMER_H
|
||||
|
||||
#include "BlynkDebug.h"
|
||||
|
||||
// Replace SimpleTimer
|
||||
#define SIMPLETIMER_H
|
||||
#define SimpleTimer BlynkTimer
|
||||
|
||||
typedef void (*timer_callback)(void);
|
||||
typedef void (*timer_callback_p)(void *);
|
||||
|
||||
class SimpleTimer {
|
||||
|
||||
public:
|
||||
// maximum number of timers
|
||||
const static int MAX_TIMERS = 16;
|
||||
|
||||
// setTimer() constants
|
||||
const static int RUN_FOREVER = 0;
|
||||
const static int RUN_ONCE = 1;
|
||||
|
||||
// constructor
|
||||
SimpleTimer();
|
||||
|
||||
void init();
|
||||
|
||||
// this function must be called inside loop()
|
||||
void run();
|
||||
|
||||
// Timer will call function 'f' every 'd' milliseconds forever
|
||||
// returns the timer number (numTimer) on success or
|
||||
// -1 on failure (f == NULL) or no free timers
|
||||
int setInterval(unsigned long d, timer_callback f);
|
||||
|
||||
// Timer will call function 'f' with parameter 'p' every 'd' milliseconds forever
|
||||
// returns the timer number (numTimer) on success or
|
||||
// -1 on failure (f == NULL) or no free timers
|
||||
int setInterval(unsigned long d, timer_callback_p f, void* p);
|
||||
|
||||
// Timer will call function 'f' after 'd' milliseconds one time
|
||||
// returns the timer number (numTimer) on success or
|
||||
// -1 on failure (f == NULL) or no free timers
|
||||
int setTimeout(unsigned long d, timer_callback f);
|
||||
|
||||
// Timer will call function 'f' with parameter 'p' after 'd' milliseconds one time
|
||||
// returns the timer number (numTimer) on success or
|
||||
// -1 on failure (f == NULL) or no free timers
|
||||
int setTimeout(unsigned long d, timer_callback_p f, void* p);
|
||||
|
||||
// Timer will call function 'f' every 'd' milliseconds 'n' times
|
||||
// returns the timer number (numTimer) on success or
|
||||
// -1 on failure (f == NULL) or no free timers
|
||||
int setTimer(unsigned long d, timer_callback f, unsigned n);
|
||||
|
||||
// Timer will call function 'f' with parameter 'p' every 'd' milliseconds 'n' times
|
||||
// returns the timer number (numTimer) on success or
|
||||
// -1 on failure (f == NULL) or no free timers
|
||||
int setTimer(unsigned long d, timer_callback_p f, void* p, unsigned n);
|
||||
|
||||
// updates interval of the specified timer
|
||||
bool changeInterval(unsigned numTimer, unsigned long d);
|
||||
|
||||
// destroy the specified timer
|
||||
void deleteTimer(unsigned numTimer);
|
||||
|
||||
// restart the specified timer
|
||||
void restartTimer(unsigned numTimer);
|
||||
|
||||
// returns true if the specified timer is enabled
|
||||
bool isEnabled(unsigned numTimer);
|
||||
|
||||
// enables the specified timer
|
||||
void enable(unsigned numTimer);
|
||||
|
||||
// disables the specified timer
|
||||
void disable(unsigned numTimer);
|
||||
|
||||
// enables all timers
|
||||
void enableAll();
|
||||
|
||||
// disables all timers
|
||||
void disableAll();
|
||||
|
||||
// enables the specified timer if it's currently disabled,
|
||||
// and vice-versa
|
||||
void toggle(unsigned numTimer);
|
||||
|
||||
// returns the number of used timers
|
||||
unsigned getNumTimers();
|
||||
|
||||
// returns the number of available timers
|
||||
unsigned getNumAvailableTimers() { return MAX_TIMERS - numTimers; };
|
||||
|
||||
private:
|
||||
// deferred call constants
|
||||
const static int DEFCALL_DONTRUN = 0; // don't call the callback function
|
||||
const static int DEFCALL_RUNONLY = 1; // call the callback function but don't delete the timer
|
||||
const static int DEFCALL_RUNANDDEL = 2; // call the callback function and delete the timer
|
||||
|
||||
// low level function to initialize and enable a new timer
|
||||
// returns the timer number (numTimer) on success or
|
||||
// -1 on failure (f == NULL) or no free timers
|
||||
int setupTimer(unsigned long d, void* f, void* p, bool h, unsigned n);
|
||||
|
||||
// find the first available slot
|
||||
int findFirstFreeSlot();
|
||||
|
||||
typedef struct {
|
||||
unsigned long prev_millis; // value returned by the millis() function in the previous run() call
|
||||
void* callback; // pointer to the callback function
|
||||
void* param; // function parameter
|
||||
bool hasParam; // true if callback takes a parameter
|
||||
unsigned long delay; // delay value
|
||||
unsigned maxNumRuns; // number of runs to be executed
|
||||
unsigned numRuns; // number of executed runs
|
||||
bool enabled; // true if enabled
|
||||
unsigned toBeCalled; // deferred function call (sort of) - N.B.: only used in run()
|
||||
} timer_t;
|
||||
|
||||
timer_t timer[MAX_TIMERS];
|
||||
|
||||
// actual number of timers in use (-1 means uninitialized)
|
||||
int numTimers;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,64 +0,0 @@
|
||||
/**
|
||||
* @file BlynkUtility.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Jun 2015
|
||||
* @brief Utility functions
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkUtility_h
|
||||
#define BlynkUtility_h
|
||||
|
||||
template<class T>
|
||||
const T& BlynkMin(const T& a, const T& b)
|
||||
{
|
||||
return (b < a) ? b : a;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
const T& BlynkMax(const T& a, const T& b)
|
||||
{
|
||||
return (b < a) ? a : b;
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
T BlynkMathMap(T x, T in_min, T in_max, T out_min, T out_max)
|
||||
{
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T BlynkMathClamp(T val, T low, T high)
|
||||
{
|
||||
return (val < low) ? low : ((val > high) ? high : val);
|
||||
}
|
||||
|
||||
|
||||
template <unsigned WSIZE, typename T>
|
||||
void BlynkAverageSample (T& avg, const T& input) {
|
||||
avg -= avg/WSIZE;
|
||||
const T add = input/WSIZE;
|
||||
// Fix for shorter delays
|
||||
if (add > 0)
|
||||
avg += add;
|
||||
else
|
||||
avg -= 1;
|
||||
}
|
||||
|
||||
class BlynkHelperAutoInc {
|
||||
public:
|
||||
BlynkHelperAutoInc(uint8_t& counter) : c(counter) { ++c; }
|
||||
~BlynkHelperAutoInc() { --c; }
|
||||
private:
|
||||
uint8_t& c;
|
||||
};
|
||||
|
||||
#define BlynkBitSet(value, bit) ((value) |= (1UL << (bit)))
|
||||
#define BlynkBitClear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||
#define BlynkBitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||
#define BlynkBitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
|
||||
|
||||
#endif
|
@ -1,102 +0,0 @@
|
||||
/**
|
||||
* @file BlynkWiFiCommon.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Jan 2015
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkWiFiCommon_h
|
||||
#define BlynkWiFiCommon_h
|
||||
|
||||
#ifndef BLYNK_INFO_CONNECTION
|
||||
#define BLYNK_INFO_CONNECTION "WiFi"
|
||||
#endif
|
||||
|
||||
#include "BlynkApiArduino.h"
|
||||
#include "BlynkProtocol.h"
|
||||
#include "BlynkArduinoClient.h"
|
||||
|
||||
class BlynkWifiCommon
|
||||
: public BlynkProtocol<BlynkArduinoClient>
|
||||
{
|
||||
typedef BlynkProtocol<BlynkArduinoClient> Base;
|
||||
public:
|
||||
BlynkWifiCommon(BlynkArduinoClient& transp)
|
||||
: Base(transp)
|
||||
{}
|
||||
|
||||
void connectWiFi(const char* ssid, const char* pass)
|
||||
{
|
||||
int status = WL_IDLE_STATUS;
|
||||
// check for the presence of the shield:
|
||||
if (WiFi.status() == WL_NO_SHIELD) {
|
||||
BLYNK_FATAL("WiFi shield not present");
|
||||
}
|
||||
|
||||
#ifdef BLYNK_DEBUG
|
||||
BLYNK_LOG2(BLYNK_F("WiFi firmware: "), WiFi.firmwareVersion());
|
||||
#endif
|
||||
|
||||
// attempt to connect to Wifi network:
|
||||
while (true) {
|
||||
BLYNK_LOG2(BLYNK_F("Connecting to "), ssid);
|
||||
if (pass && strlen(pass)) {
|
||||
status = WiFi.begin((char*)ssid, (char*)pass);
|
||||
} else {
|
||||
status = WiFi.begin((char*)ssid);
|
||||
}
|
||||
if (status == WL_CONNECTED) {
|
||||
break;
|
||||
} else {
|
||||
BlynkDelay(5000);
|
||||
}
|
||||
}
|
||||
|
||||
IPAddress myip = WiFi.localIP();
|
||||
BLYNK_LOG_IP("IP: ", myip);
|
||||
}
|
||||
|
||||
void config(const char* auth,
|
||||
const char* domain = BLYNK_DEFAULT_DOMAIN,
|
||||
uint16_t port = BLYNK_DEFAULT_PORT)
|
||||
{
|
||||
Base::begin(auth);
|
||||
this->conn.begin(domain, port);
|
||||
}
|
||||
|
||||
void config(const char* auth,
|
||||
IPAddress ip,
|
||||
uint16_t port = BLYNK_DEFAULT_PORT)
|
||||
{
|
||||
Base::begin(auth);
|
||||
this->conn.begin(ip, port);
|
||||
}
|
||||
|
||||
void begin(const char* auth,
|
||||
const char* ssid,
|
||||
const char* pass,
|
||||
const char* domain = BLYNK_DEFAULT_DOMAIN,
|
||||
uint16_t port = BLYNK_DEFAULT_PORT)
|
||||
{
|
||||
connectWiFi(ssid, pass);
|
||||
config(auth, domain, port);
|
||||
while(this->connect() != true) {}
|
||||
}
|
||||
|
||||
void begin(const char* auth,
|
||||
const char* ssid,
|
||||
const char* pass,
|
||||
IPAddress ip,
|
||||
uint16_t port = BLYNK_DEFAULT_PORT)
|
||||
{
|
||||
connectWiFi(ssid, pass);
|
||||
config(auth, ip, port);
|
||||
while(this->connect() != true) {}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -1,62 +0,0 @@
|
||||
/**
|
||||
* @file BlynkWidgetBase.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2016 Volodymyr Shymanskyy
|
||||
* @date Nov 2016
|
||||
* @brief
|
||||
*/
|
||||
|
||||
#ifndef BlynkWidgetBase_h
|
||||
#define BlynkWidgetBase_h
|
||||
|
||||
#include "BlynkApi.h"
|
||||
|
||||
class BlynkWidgetBase
|
||||
{
|
||||
public:
|
||||
BlynkWidgetBase(uint8_t vPin) : mPin(vPin) {}
|
||||
void setVPin(uint8_t vPin) { mPin = vPin; }
|
||||
|
||||
void onWrite(BlynkReq BLYNK_UNUSED &request, const BlynkParam BLYNK_UNUSED ¶m) {
|
||||
BLYNK_LOG1(BLYNK_F("BlynkWidgetBase::onWrite should not be called"));
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void setLabel(Args... args) {
|
||||
Blynk.setProperty(mPin, "label", args...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void setColor(Args... args) {
|
||||
Blynk.setProperty(mPin, "color", args...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void setMin(Args... args) {
|
||||
Blynk.setProperty(mPin, "min", args...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void setMax(Args... args) {
|
||||
Blynk.setProperty(mPin, "max", args...);
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t mPin;
|
||||
};
|
||||
|
||||
class BlynkAttachWidgetHelper {
|
||||
public:
|
||||
template<typename T>
|
||||
explicit BlynkAttachWidgetHelper(T& widget, uint8_t vPin) {
|
||||
widget.setVPin(vPin);
|
||||
}
|
||||
};
|
||||
|
||||
// Could use __attribute__ ((constructor)), but hope for better portability
|
||||
#define BLYNK_ATTACH_WIDGET(widget, pin) \
|
||||
BlynkAttachWidgetHelper BLYNK_CONCAT2(blnk_widget_helper_, __COUNTER__)((widget), (pin)); \
|
||||
BLYNK_WRITE(pin) { (widget).onWrite(request, param); }
|
||||
|
||||
#endif
|
@ -1,198 +0,0 @@
|
||||
#include "BlynkDebug.h"
|
||||
#include "BlynkDateTime.h"
|
||||
|
||||
#if !defined(BLYNK_NO_FLOAT) && defined(BLYNK_USE_INTERNAL_DTOSTRF)
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
char* dtostrf_internal(double number, signed char BLYNK_UNUSED width, unsigned char prec, char *s) {
|
||||
if(isnan(number)) {
|
||||
strcpy(s, "nan");
|
||||
return s;
|
||||
}
|
||||
if(isinf(number)) {
|
||||
strcpy(s, "inf");
|
||||
return s;
|
||||
}
|
||||
|
||||
if(number > 4294967040.0 || number < -4294967040.0) {
|
||||
strcpy(s, "ovf");
|
||||
return s;
|
||||
}
|
||||
char* out = s;
|
||||
// Handle negative numbers
|
||||
if(number < 0.0) {
|
||||
*out = '-';
|
||||
++out;
|
||||
number = -number;
|
||||
}
|
||||
|
||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||
double rounding = 0.5;
|
||||
for(uint8_t i = 0; i < prec; ++i) {
|
||||
rounding /= 10.0;
|
||||
}
|
||||
|
||||
number += rounding;
|
||||
|
||||
// Extract the integer part of the number and print it
|
||||
unsigned long int_part = (unsigned long) number;
|
||||
double remainder = number - (double) int_part;
|
||||
out += sprintf(out, "%lu", int_part);
|
||||
|
||||
// Print the decimal point, but only if there are digits beyond
|
||||
if(prec > 0) {
|
||||
*out = '.';
|
||||
++out;
|
||||
}
|
||||
|
||||
while(prec-- > 0) {
|
||||
remainder *= 10.0;
|
||||
if((int)remainder == 0) {
|
||||
*out = '0';
|
||||
++out;
|
||||
}
|
||||
}
|
||||
sprintf(out, "%d", (int) remainder);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define YEAR_0 1900
|
||||
#define YEAR_EPOCH 1970
|
||||
#define SECS_IN_DAY (24L * 60L * 60L)
|
||||
#define IS_LEAP_YEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400)))
|
||||
#define YEAR_DAYS(year) (IS_LEAP_YEAR(year) ? 366 : 365)
|
||||
|
||||
#define TIME_MAX 2147483647L
|
||||
|
||||
static const int month_tab[2][12] = {
|
||||
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
|
||||
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
};
|
||||
|
||||
struct blynk_tm* blynk_gmtime_r(const blynk_time_t* t, struct blynk_tm *tm) {
|
||||
blynk_time_t time = *t;
|
||||
unsigned long dayclock, dayno;
|
||||
int year = YEAR_EPOCH;
|
||||
|
||||
dayclock = (unsigned long) time % SECS_IN_DAY;
|
||||
dayno = (unsigned long) time / SECS_IN_DAY;
|
||||
|
||||
tm->tm_sec = dayclock % 60;
|
||||
tm->tm_min = (dayclock % 3600) / 60;
|
||||
tm->tm_hour = dayclock / 3600;
|
||||
tm->tm_wday = (dayno + 4) % 7;
|
||||
while (dayno >= (unsigned long) YEAR_DAYS(year)) {
|
||||
dayno -= YEAR_DAYS(year);
|
||||
year++;
|
||||
}
|
||||
tm->tm_year = year - YEAR_0;
|
||||
tm->tm_yday = dayno;
|
||||
tm->tm_mon = 0;
|
||||
while (dayno >= (unsigned long) month_tab[IS_LEAP_YEAR(year)][tm->tm_mon]) {
|
||||
dayno -= month_tab[IS_LEAP_YEAR(year)][tm->tm_mon];
|
||||
tm->tm_mon++;
|
||||
}
|
||||
tm->tm_mday = dayno + 1;
|
||||
tm->tm_isdst = 0;
|
||||
return tm;
|
||||
}
|
||||
|
||||
blynk_time_t blynk_mk_gmtime(struct blynk_tm *tm) {
|
||||
long day, year;
|
||||
int tm_year;
|
||||
int yday, month;
|
||||
long seconds;
|
||||
int overflow;
|
||||
|
||||
tm->tm_min += tm->tm_sec / 60;
|
||||
tm->tm_sec %= 60;
|
||||
if (tm->tm_sec < 0) {
|
||||
tm->tm_sec += 60;
|
||||
tm->tm_min--;
|
||||
}
|
||||
tm->tm_hour += tm->tm_min / 60;
|
||||
tm->tm_min = tm->tm_min % 60;
|
||||
if (tm->tm_min < 0) {
|
||||
tm->tm_min += 60;
|
||||
tm->tm_hour--;
|
||||
}
|
||||
day = tm->tm_hour / 24;
|
||||
tm->tm_hour = tm->tm_hour % 24;
|
||||
if (tm->tm_hour < 0) {
|
||||
tm->tm_hour += 24;
|
||||
day--;
|
||||
}
|
||||
tm->tm_year += tm->tm_mon / 12;
|
||||
tm->tm_mon %= 12;
|
||||
if (tm->tm_mon < 0) {
|
||||
tm->tm_mon += 12;
|
||||
tm->tm_year--;
|
||||
}
|
||||
day += (tm->tm_mday - 1);
|
||||
while (day < 0) {
|
||||
if (--tm->tm_mon < 0) {
|
||||
tm->tm_year--;
|
||||
tm->tm_mon = 11;
|
||||
}
|
||||
day += month_tab[IS_LEAP_YEAR(YEAR_0 + tm->tm_year)][tm->tm_mon];
|
||||
}
|
||||
while (day >= month_tab[IS_LEAP_YEAR(YEAR_0 + tm->tm_year)][tm->tm_mon]) {
|
||||
day -= month_tab[IS_LEAP_YEAR(YEAR_0 + tm->tm_year)][tm->tm_mon];
|
||||
if (++(tm->tm_mon) == 12) {
|
||||
tm->tm_mon = 0;
|
||||
tm->tm_year++;
|
||||
}
|
||||
}
|
||||
tm->tm_mday = day + 1;
|
||||
year = YEAR_EPOCH;
|
||||
if (tm->tm_year < year - YEAR_0)
|
||||
return (blynk_time_t) -1;
|
||||
seconds = 0;
|
||||
day = 0;
|
||||
overflow = 0;
|
||||
|
||||
tm_year = tm->tm_year + YEAR_0;
|
||||
|
||||
if (TIME_MAX / 365 < tm_year - year)
|
||||
overflow++;
|
||||
day = (tm_year - year) * 365;
|
||||
if (TIME_MAX - day < (tm_year - year) / 4 + 1)
|
||||
overflow++;
|
||||
day += (tm_year - year) / 4 + ((tm_year % 4) && tm_year % 4 < year % 4);
|
||||
day -= (tm_year - year) / 100
|
||||
+ ((tm_year % 100) && tm_year % 100 < year % 100);
|
||||
day += (tm_year - year) / 400
|
||||
+ ((tm_year % 400) && tm_year % 400 < year % 400);
|
||||
|
||||
yday = month = 0;
|
||||
while (month < tm->tm_mon) {
|
||||
yday += month_tab[IS_LEAP_YEAR(tm_year)][month];
|
||||
month++;
|
||||
}
|
||||
yday += (tm->tm_mday - 1);
|
||||
if (day + yday < 0)
|
||||
overflow++;
|
||||
day += yday;
|
||||
|
||||
tm->tm_yday = yday;
|
||||
tm->tm_wday = (day + 4) % 7;
|
||||
|
||||
seconds = ((tm->tm_hour * 60L) + tm->tm_min) * 60L + tm->tm_sec;
|
||||
|
||||
if ((TIME_MAX - seconds) / SECS_IN_DAY < day)
|
||||
overflow++;
|
||||
seconds += day * SECS_IN_DAY;
|
||||
|
||||
if (overflow)
|
||||
return (blynk_time_t) -1;
|
||||
|
||||
if ((blynk_time_t) seconds != seconds)
|
||||
return (blynk_time_t) -1;
|
||||
return (blynk_time_t) seconds;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
#include "BlynkSimpleEsp.h"
|
||||
|
||||
WiFiClient _blynkWifiClient;
|
||||
BlynkArduinoClient _blynkTransport(_blynkWifiClient);
|
||||
BlynkWifi Blynk(_blynkTransport);
|
@ -1,93 +0,0 @@
|
||||
/**
|
||||
* @file BlynkSimpleEsp32.h
|
||||
* @author Volodymyr Shymanskyy
|
||||
* @license This project is released under the MIT License (MIT)
|
||||
* @copyright Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
* @date Oct 2016
|
||||
* @brief
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BlynkSimpleEsp_h
|
||||
#define BlynkSimpleEsp_h
|
||||
|
||||
#define BLYNK_SEND_ATOMIC
|
||||
|
||||
#include "Blynk/BlynkApiArduino.h"
|
||||
#include "Blynk/BlynkProtocol.h"
|
||||
#include "Blynk/BlynkArduinoClient.h"
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#include <WiFi.h>
|
||||
#else
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
|
||||
class BlynkWifi
|
||||
: public BlynkProtocol<BlynkArduinoClient>
|
||||
{
|
||||
typedef BlynkProtocol<BlynkArduinoClient> Base;
|
||||
public:
|
||||
BlynkWifi(BlynkArduinoClient& transp)
|
||||
: Base(transp)
|
||||
{}
|
||||
|
||||
void connectWiFi(const char* ssid, const char* pass)
|
||||
{
|
||||
BLYNK_LOG2(BLYNK_F("Connecting to "), ssid);
|
||||
WiFi.mode(WIFI_STA);
|
||||
if (pass && strlen(pass)) {
|
||||
WiFi.begin(ssid, pass);
|
||||
} else {
|
||||
WiFi.begin(ssid);
|
||||
}
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
BlynkDelay(500);
|
||||
}
|
||||
BLYNK_LOG1(BLYNK_F("Connected to WiFi"));
|
||||
|
||||
BLYNK_LOG_IP("IP: ", WiFi.localIP());
|
||||
}
|
||||
|
||||
void config(const char* auth,
|
||||
const char* domain = BLYNK_DEFAULT_DOMAIN,
|
||||
uint16_t port = BLYNK_DEFAULT_PORT)
|
||||
{
|
||||
Base::begin(auth);
|
||||
this->conn.begin(domain, port);
|
||||
}
|
||||
|
||||
void config(const char* auth,
|
||||
IPAddress ip,
|
||||
uint16_t port = BLYNK_DEFAULT_PORT)
|
||||
{
|
||||
Base::begin(auth);
|
||||
this->conn.begin(ip, port);
|
||||
}
|
||||
|
||||
void begin(const char* auth,
|
||||
const char* ssid,
|
||||
const char* pass,
|
||||
const char* domain = BLYNK_DEFAULT_DOMAIN,
|
||||
uint16_t port = BLYNK_DEFAULT_PORT)
|
||||
{
|
||||
connectWiFi(ssid, pass);
|
||||
config(auth, domain, port);
|
||||
while(this->connect() != true) {}
|
||||
}
|
||||
|
||||
void begin(const char* auth,
|
||||
const char* ssid,
|
||||
const char* pass,
|
||||
IPAddress ip,
|
||||
uint16_t port = BLYNK_DEFAULT_PORT)
|
||||
{
|
||||
connectWiFi(ssid, pass);
|
||||
config(auth, ip, port);
|
||||
while(this->connect() != true) {}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
extern BlynkWifi Blynk;
|
||||
|
||||
#endif
|
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Volodymyr Shymanskyy
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -228,4 +228,30 @@ class ESPAsyncE131 {
|
||||
bool begin(bool multicast, uint16_t port = E131_DEFAULT_PORT, uint16_t universe = 1, uint8_t n = 1);
|
||||
};
|
||||
|
||||
// Class to track e131 package priority
|
||||
class E131Priority {
|
||||
private:
|
||||
uint8_t priority;
|
||||
time_t setupTime;
|
||||
uint8_t seconds;
|
||||
|
||||
public:
|
||||
E131Priority(uint8_t timeout=3) {
|
||||
seconds = timeout;
|
||||
set(0);
|
||||
};
|
||||
|
||||
// Set priority (+ remember time)
|
||||
void set(uint8_t prio) {
|
||||
setupTime = time(0);
|
||||
priority = prio;
|
||||
}
|
||||
|
||||
// Get priority (+ reset & return 0 if older timeout)
|
||||
uint8_t get() {
|
||||
if (time(0) > setupTime + seconds) priority = 0;
|
||||
return priority;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ESPASYNCE131_H_
|
@ -23,7 +23,6 @@ void notify(byte callMode, bool followUp)
|
||||
case CALL_MODE_NIGHTLIGHT: if (!notifyDirect) return; break;
|
||||
case CALL_MODE_HUE: if (!notifyHue) return; break;
|
||||
case CALL_MODE_PRESET_CYCLE: if (!notifyDirect) return; break;
|
||||
case CALL_MODE_BLYNK: if (!notifyDirect) return; break;
|
||||
case CALL_MODE_ALEXA: if (!notifyAlexa) return; break;
|
||||
default: return;
|
||||
}
|
||||
@ -714,7 +713,9 @@ void sendSysInfoUDP()
|
||||
// buffer - a buffer of at least length*4 bytes long
|
||||
// isRGBW - true if the buffer contains 4 components per pixel
|
||||
|
||||
uint8_t sequenceNumber = 0; // this needs to be shared across all outputs
|
||||
static size_t sequenceNumber = 0; // this needs to be shared across all outputs
|
||||
static const size_t ART_NET_HEADER_SIZE = 12;
|
||||
static const byte ART_NET_HEADER[] PROGMEM = {0x41,0x72,0x74,0x2d,0x4e,0x65,0x74,0x00,0x00,0x50,0x00,0x0e};
|
||||
|
||||
uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8_t *buffer, uint8_t bri, bool isRGBW) {
|
||||
if (!(apActive || interfacesInited) || !client[0] || !length) return 1; // network not initialised or dummy/unset IP address 031522 ajn added check for ap
|
||||
@ -792,6 +793,57 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8
|
||||
|
||||
case 2: //ArtNet
|
||||
{
|
||||
// calculate the number of UDP packets we need to send
|
||||
const size_t channelCount = length * (isRGBW?4:3); // 1 channel for every R,G,B,(W?) value
|
||||
const size_t ARTNET_CHANNELS_PER_PACKET = isRGBW?512:510; // 512/4=128 RGBW LEDs, 510/3=170 RGB LEDs
|
||||
const size_t packetCount = ((channelCount-1)/ARTNET_CHANNELS_PER_PACKET)+1;
|
||||
|
||||
uint32_t channel = 0;
|
||||
size_t bufferOffset = 0;
|
||||
|
||||
sequenceNumber++;
|
||||
|
||||
for (size_t currentPacket = 0; currentPacket < packetCount; currentPacket++) {
|
||||
|
||||
if (sequenceNumber > 255) sequenceNumber = 0;
|
||||
|
||||
if (!ddpUdp.beginPacket(client, ARTNET_DEFAULT_PORT)) {
|
||||
DEBUG_PRINTLN(F("Art-Net WiFiUDP.beginPacket returned an error"));
|
||||
return 1; // borked
|
||||
}
|
||||
|
||||
size_t packetSize = ARTNET_CHANNELS_PER_PACKET;
|
||||
|
||||
if (currentPacket == (packetCount - 1U)) {
|
||||
// last packet
|
||||
if (channelCount % ARTNET_CHANNELS_PER_PACKET) {
|
||||
packetSize = channelCount % ARTNET_CHANNELS_PER_PACKET;
|
||||
}
|
||||
}
|
||||
|
||||
byte buffer[ART_NET_HEADER_SIZE];
|
||||
memcpy_P(buffer, ART_NET_HEADER, ART_NET_HEADER_SIZE);
|
||||
ddpUdp.write(buffer, ART_NET_HEADER_SIZE); // This doesn't change. Hard coded ID, OpCode, and protocol version.
|
||||
ddpUdp.write(sequenceNumber & 0xFF); // sequence number. 1..255
|
||||
ddpUdp.write(0x00); // physical - more an FYI, not really used for anything. 0..3
|
||||
ddpUdp.write((currentPacket) & 0xFF); // Universe LSB. 1 full packet == 1 full universe, so just use current packet number.
|
||||
ddpUdp.write(0x00); // Universe MSB, unused.
|
||||
ddpUdp.write(0xFF & (packetSize >> 8)); // 16-bit length of channel data, MSB
|
||||
ddpUdp.write(0xFF & (packetSize )); // 16-bit length of channel data, LSB
|
||||
|
||||
for (size_t i = 0; i < packetSize; i += (isRGBW?4:3)) {
|
||||
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // R
|
||||
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // G
|
||||
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // B
|
||||
if (isRGBW) ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // W
|
||||
}
|
||||
|
||||
if (!ddpUdp.endPacket()) {
|
||||
DEBUG_PRINTLN(F("Art-Net WiFiUDP.endPacket returned an error"));
|
||||
return 1; // borked
|
||||
}
|
||||
channel += packetSize;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -40,6 +40,7 @@ bool UsermodManager::onMqttMessage(char* topic, char* payload) {
|
||||
return false;
|
||||
}
|
||||
void UsermodManager::onUpdateBegin(bool init) { for (byte i = 0; i < numMods; i++) ums[i]->onUpdateBegin(init); } // notify usermods that update is to begin
|
||||
void UsermodManager::onStateChange(uint8_t mode) { for (byte i = 0; i < numMods; i++) ums[i]->onStateChange(mode); } // notify usermods that WLED state changed
|
||||
|
||||
/*
|
||||
* Enables usermods to lookup another Usermod.
|
||||
|
@ -19,11 +19,16 @@
|
||||
#include "../usermods/Temperature/usermod_temperature.h"
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SHT
|
||||
#include "../usermods/sht/usermod_sht.h"
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SN_PHOTORESISTOR
|
||||
#include "../usermods/SN_Photoresistor/usermod_sn_photoresistor.h"
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_PWM_FAN
|
||||
// requires DALLASTEMPERATURE or SHT included before it
|
||||
#include "../usermods/PWM_fan/usermod_PWM_fan.h"
|
||||
#endif
|
||||
|
||||
@ -160,6 +165,10 @@
|
||||
#include "../usermods/ADS1115_v2/usermod_ads1115.h"
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_KLIPPER_PERCENTAGE
|
||||
#include "..\usermods\usermod_v2_klipper_percentage\usermod_v2_klipper_percentage.h"
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_BOBLIGHT
|
||||
#include "../usermods/boblight/boblight.h"
|
||||
#endif
|
||||
@ -180,10 +189,6 @@
|
||||
#include "../usermods/pwm_outputs/usermod_pwm_outputs.h"
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_SHT
|
||||
#include "../usermods/sht/usermod_sht.h"
|
||||
#endif
|
||||
|
||||
|
||||
void registerUsermods()
|
||||
{
|
||||
@ -333,6 +338,10 @@ void registerUsermods()
|
||||
usermods.add(new ADS1115Usermod());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_KLIPPER_PERCENTAGE
|
||||
usermods.add(new klipper_percentage());
|
||||
#endif
|
||||
|
||||
#ifdef USERMOD_BOBLIGHT
|
||||
usermods.add(new BobLightUsermod());
|
||||
#endif
|
||||
|
@ -503,12 +503,49 @@ um_data_t* simulateSound(uint8_t simulationId)
|
||||
}
|
||||
|
||||
|
||||
// enumerate all ledmapX.json files on FS and extract ledmap names if existing
|
||||
void enumerateLedmaps() {
|
||||
ledMaps = 1;
|
||||
for (size_t i=1; i<10; i++) {
|
||||
char fileName[16];
|
||||
for (size_t i=1; i<WLED_MAX_LEDMAPS; i++) {
|
||||
char fileName[33];
|
||||
sprintf_P(fileName, PSTR("/ledmap%d.json"), i);
|
||||
bool isFile = WLED_FS.exists(fileName);
|
||||
if (isFile) ledMaps |= 1 << i;
|
||||
|
||||
#ifndef ESP8266
|
||||
if (ledmapNames[i-1]) { //clear old name
|
||||
delete[] ledmapNames[i-1];
|
||||
ledmapNames[i-1] = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (isFile) {
|
||||
ledMaps |= 1 << i;
|
||||
|
||||
#ifndef ESP8266
|
||||
if (requestJSONBufferLock(21)) {
|
||||
if (readObjectFromFile(fileName, nullptr, &doc)) {
|
||||
size_t len = 0;
|
||||
if (!doc["n"].isNull()) {
|
||||
// name field exists
|
||||
const char *name = doc["n"].as<const char*>();
|
||||
if (name != nullptr) len = strlen(name);
|
||||
if (len > 0 && len < 33) {
|
||||
ledmapNames[i-1] = new char[len+1];
|
||||
if (ledmapNames[i-1]) strlcpy(ledmapNames[i-1], name, 33);
|
||||
}
|
||||
}
|
||||
if (!ledmapNames[i-1]) {
|
||||
char tmp[33];
|
||||
snprintf_P(tmp, 32, PSTR("ledmap%d.json"), i);
|
||||
len = strlen(tmp);
|
||||
ledmapNames[i-1] = new char[len+1];
|
||||
if (ledmapNames[i-1]) strlcpy(ledmapNames[i-1], tmp, 33);
|
||||
}
|
||||
}
|
||||
releaseJSONBufferLock();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -100,11 +100,6 @@ void WLED::loop()
|
||||
yield();
|
||||
#endif
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
handleBlynk();
|
||||
yield();
|
||||
#endif
|
||||
|
||||
handlePresets();
|
||||
yield();
|
||||
|
||||
@ -171,15 +166,14 @@ void WLED::loop()
|
||||
}
|
||||
delete busConfigs[i]; busConfigs[i] = nullptr;
|
||||
}
|
||||
strip.finalizeInit();
|
||||
loadLedmap = 0;
|
||||
strip.finalizeInit(); // also loads default ledmap if present
|
||||
if (aligned) strip.makeAutoSegments();
|
||||
else strip.fixInvalidSegments();
|
||||
yield();
|
||||
serializeConfig();
|
||||
}
|
||||
if (loadLedmap >= 0) {
|
||||
strip.deserializeMap(loadLedmap);
|
||||
if (!strip.deserializeMap(loadLedmap) && strip.isMatrix && loadLedmap == 0) strip.setUpMatrix();
|
||||
loadLedmap = -1;
|
||||
}
|
||||
|
||||
@ -273,6 +267,9 @@ void WLED::setup()
|
||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detection
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
pinMode(hardwareRX, INPUT_PULLDOWN); delay(1); // suppress noise in case RX pin is floating (at low noise energy) - see issue #3128
|
||||
#endif
|
||||
Serial.begin(115200);
|
||||
#if !ARDUINO_USB_CDC_ON_BOOT
|
||||
Serial.setTimeout(50); // this causes troubles on new MCUs that have a "virtual" USB Serial (HWCDC)
|
||||
@ -322,8 +319,7 @@ void WLED::setup()
|
||||
DEBUG_PRINT(F("esp8266 "));
|
||||
DEBUG_PRINTLN(ESP.getCoreVersion());
|
||||
#endif
|
||||
DEBUG_PRINT(F("heap "));
|
||||
DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
if (psramFound()) {
|
||||
@ -358,6 +354,8 @@ void WLED::setup()
|
||||
DEBUG_PRINTLN(F("Registering usermods ..."));
|
||||
registerUsermods();
|
||||
|
||||
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
|
||||
for (uint8_t i=1; i<WLED_MAX_BUTTONS; i++) btnPin[i] = -1;
|
||||
|
||||
bool fsinit = false;
|
||||
@ -398,10 +396,12 @@ void WLED::setup()
|
||||
|
||||
DEBUG_PRINTLN(F("Initializing strip"));
|
||||
beginStrip();
|
||||
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
|
||||
DEBUG_PRINTLN(F("Usermods setup"));
|
||||
userSetup();
|
||||
usermods.setup();
|
||||
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
|
||||
if (strcmp(clientSSID, DEFAULT_CLIENT_SSID) == 0)
|
||||
showWelcomePage = true;
|
||||
@ -457,7 +457,9 @@ void WLED::setup()
|
||||
#endif
|
||||
|
||||
// HTTP server page init
|
||||
DEBUG_PRINTLN(F("initServer"));
|
||||
initServer();
|
||||
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
|
||||
enableWatchdog();
|
||||
|
||||
@ -719,9 +721,6 @@ void WLED::initInterfaces()
|
||||
if (ntpEnabled)
|
||||
ntpConnected = ntpUdp.begin(ntpLocalPort);
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
initBlynk(blynkApiKey, blynkHost, blynkPort);
|
||||
#endif
|
||||
e131.begin(e131Multicast, e131Port, e131Universe, E131_MAX_UNIVERSE_COUNT);
|
||||
ddp.begin(false, DDP_DEFAULT_PORT);
|
||||
reconnectHue();
|
||||
@ -756,6 +755,8 @@ void WLED::handleConnection()
|
||||
DEBUG_PRINTLN(heap);
|
||||
forceReconnect = true;
|
||||
strip.purgeSegments(true); // remove all but one segments from memory
|
||||
} else if (heap < MIN_HEAP_SIZE) {
|
||||
strip.purgeSegments();
|
||||
}
|
||||
lastHeap = heap;
|
||||
heapTime = now;
|
||||
|
@ -3,12 +3,12 @@
|
||||
/*
|
||||
Main sketch, global variable declarations
|
||||
@title WLED project sketch
|
||||
@version 0.14.0-b1
|
||||
@version 0.14.0-b2
|
||||
@author Christian Schwinne
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2301240
|
||||
#define VERSION 2303240
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
@ -25,13 +25,16 @@
|
||||
|
||||
// You can choose some of these features to disable:
|
||||
//#define WLED_DISABLE_ALEXA // saves 11kb
|
||||
//#define WLED_DISABLE_BLYNK // saves 6kb
|
||||
//#define WLED_DISABLE_HUESYNC // saves 4kb
|
||||
//#define WLED_DISABLE_INFRARED // saves 12kb, there is no pin left for this on ESP8266-01
|
||||
#ifndef WLED_DISABLE_MQTT
|
||||
#define WLED_ENABLE_MQTT // saves 12kb
|
||||
#endif
|
||||
#define WLED_ENABLE_ADALIGHT // saves 500b only (uses GPIO3 (RX) for serial)
|
||||
#ifndef WLED_DISABLE_ADALIGHT // can be used to disable reading commands from serial RX pin (see issue #3128).
|
||||
#define WLED_ENABLE_ADALIGHT // disable saves 5Kb (uses GPIO3 (RX) for serial). Related serial protocols: Adalight/TPM2, Improv, Serial JSON, Continuous Serial Streaming
|
||||
#else
|
||||
#undef WLED_ENABLE_ADALIGHT // disable has priority over enable
|
||||
#endif
|
||||
//#define WLED_ENABLE_DMX // uses 3.5kb (use LEDPIN other than 2)
|
||||
//#define WLED_ENABLE_JSONLIVE // peek LED output via /json/live (WS binary peek is always enabled)
|
||||
#ifndef WLED_DISABLE_LOXONE
|
||||
@ -96,10 +99,6 @@
|
||||
#include "my_config.h"
|
||||
#endif
|
||||
|
||||
#ifdef WLED_DEBUG_HOST
|
||||
#include "net_debug.h"
|
||||
#endif
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#ifdef WLED_ADD_EEPROM_SUPPORT
|
||||
#include <EEPROM.h>
|
||||
@ -123,9 +122,6 @@
|
||||
#include "src/dependencies/espalexa/Espalexa.h"
|
||||
#include "src/dependencies/espalexa/EspalexaDevice.h"
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
#include "src/dependencies/blynk/BlynkSimpleEsp.h"
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
#ifdef ESP8266
|
||||
@ -323,6 +319,7 @@ WLED_GLOBAL bool correctWB _INIT(false); // CCT color correction of RGB co
|
||||
WLED_GLOBAL bool cctFromRgb _INIT(false); // CCT is calculated from RGB instead of using seg.cct
|
||||
WLED_GLOBAL bool gammaCorrectCol _INIT(true ); // use gamma correction on colors
|
||||
WLED_GLOBAL bool gammaCorrectBri _INIT(false); // use gamma correction on brightness
|
||||
WLED_GLOBAL float gammaCorrectVal _INIT(2.8f); // gamma correction value
|
||||
|
||||
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
|
||||
@ -381,12 +378,6 @@ WLED_GLOBAL bool alexaEnabled _INIT(false); // enable devi
|
||||
WLED_GLOBAL char alexaInvocationName[33] _INIT("Light"); // speech control name of device. Choose something voice-to-text can understand
|
||||
WLED_GLOBAL byte alexaNumPresets _INIT(0); // number of presets to expose to Alexa, starting from preset 1, up to 9
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
WLED_GLOBAL char blynkApiKey[36] _INIT(""); // Auth token for Blynk server. If empty, no connection will be made
|
||||
WLED_GLOBAL char blynkHost[33] _INIT("blynk-cloud.com"); // Default Blynk host
|
||||
WLED_GLOBAL uint16_t blynkPort _INIT(80); // Default Blynk port
|
||||
#endif
|
||||
|
||||
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
|
||||
@ -403,6 +394,8 @@ WLED_GLOBAL uint16_t e131ProxyUniverse _INIT(0); // output this
|
||||
#endif
|
||||
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 e131Priority _INIT(0); // E1.31 port priority (if != 0 priority handling is active)
|
||||
WLED_GLOBAL E131Priority highPriority _INIT(3); // E1.31 highest priority tracking, init = timeout in seconds
|
||||
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 uint16_t DMXSegmentSpacing _INIT(0); // Number of void/unused channels between each segments DMX channels
|
||||
@ -499,12 +492,13 @@ WLED_GLOBAL bool wasConnected _INIT(false);
|
||||
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); // default transition time (storec in cfg.json)
|
||||
WLED_GLOBAL uint16_t transitionDelayTemp _INIT(transitionDelay); // actual transition duration (overrides transitionDelay in certain cases)
|
||||
WLED_GLOBAL bool transitionActive _INIT(false);
|
||||
WLED_GLOBAL uint16_t transitionDelayDefault _INIT(transitionDelay); // default transition time (storec in cfg.json)
|
||||
WLED_GLOBAL uint16_t transitionDelayTemp _INIT(transitionDelay); // actual transition duration (overrides transitionDelay in certain cases)
|
||||
WLED_GLOBAL unsigned long transitionStartTime;
|
||||
WLED_GLOBAL float tperLast _INIT(0.0f); // crossfade transition progress, 0.0f - 1.0f
|
||||
WLED_GLOBAL bool jsonTransitionOnce _INIT(false); // flag to override transitionDelay (playlist, JSON API: "live" & "seg":{"i"} & "tt")
|
||||
WLED_GLOBAL float tperLast _INIT(0.0f); // crossfade transition progress, 0.0f - 1.0f
|
||||
WLED_GLOBAL bool jsonTransitionOnce _INIT(false); // flag to override transitionDelay (playlist, JSON API: "live" & "seg":{"i"} & "tt")
|
||||
WLED_GLOBAL uint8_t randomPaletteChangeTime _INIT(5); // amount of time [s] between random palette changes (min: 1s, max: 255s)
|
||||
|
||||
// nightlight
|
||||
WLED_GLOBAL bool nightlightActive _INIT(false);
|
||||
@ -580,9 +574,6 @@ WLED_GLOBAL byte timerMonth[] _INIT_N(({28,28,28,28,28,28,28,28}));
|
||||
WLED_GLOBAL byte timerDay[] _INIT_N(({1,1,1,1,1,1,1,1}));
|
||||
WLED_GLOBAL byte timerDayEnd[] _INIT_N(({31,31,31,31,31,31,31,31}));
|
||||
|
||||
// blynk
|
||||
WLED_GLOBAL bool blynkEnabled _INIT(false);
|
||||
|
||||
//improv
|
||||
WLED_GLOBAL byte improvActive _INIT(0); //0: no improv packet received, 1: improv active, 2: provisioning
|
||||
WLED_GLOBAL byte improvError _INIT(0);
|
||||
@ -681,7 +672,14 @@ WLED_GLOBAL WS2812FX strip _INIT(WS2812FX());
|
||||
WLED_GLOBAL BusConfig* busConfigs[WLED_MAX_BUSSES+WLED_MIN_VIRTUAL_BUSSES] _INIT({nullptr}); //temporary, to remember values from network callback until after
|
||||
WLED_GLOBAL bool doInitBusses _INIT(false);
|
||||
WLED_GLOBAL int8_t loadLedmap _INIT(-1);
|
||||
#ifndef ESP8266
|
||||
WLED_GLOBAL char *ledmapNames[WLED_MAX_LEDMAPS-1] _INIT_N(({nullptr}));
|
||||
#endif
|
||||
#if WLED_MAX_LEDMAPS>16
|
||||
WLED_GLOBAL uint32_t ledMaps _INIT(0); // bitfield representation of available ledmaps
|
||||
#else
|
||||
WLED_GLOBAL uint16_t ledMaps _INIT(0); // bitfield representation of available ledmaps
|
||||
#endif
|
||||
|
||||
// Usermod manager
|
||||
WLED_GLOBAL UsermodManager usermods _INIT(UsermodManager());
|
||||
@ -724,16 +722,16 @@ WLED_GLOBAL volatile uint8_t jsonBufferLock _INIT(0);
|
||||
|
||||
// enable additional debug output
|
||||
#if defined(WLED_DEBUG_HOST)
|
||||
#include "net_debug.h"
|
||||
// On the host side, use netcat to receive the log statements: nc -l 7868 -u
|
||||
// use -D WLED_DEBUG_HOST='"192.168.xxx.xxx"' or FQDN within quotes
|
||||
#define DEBUGOUT NetDebug
|
||||
WLED_GLOBAL bool netDebugEnabled _INIT(true);
|
||||
WLED_GLOBAL char netDebugPrintHost[33] _INIT(WLED_DEBUG_HOST);
|
||||
#if defined(WLED_DEBUG_NET_PORT)
|
||||
WLED_GLOBAL int netDebugPrintPort _INIT(WLED_DEBUG_PORT);
|
||||
#else
|
||||
WLED_GLOBAL int netDebugPrintPort _INIT(7868);
|
||||
#ifndef WLED_DEBUG_PORT
|
||||
#define WLED_DEBUG_PORT 7868
|
||||
#endif
|
||||
WLED_GLOBAL int netDebugPrintPort _INIT(WLED_DEBUG_PORT);
|
||||
#else
|
||||
#define DEBUGOUT Serial
|
||||
#endif
|
||||
|
@ -339,11 +339,6 @@ void loadSettingsFromEEPROM()
|
||||
//custom macro memory (16 slots/ each 64byte)
|
||||
//1024-2047 reserved
|
||||
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
readStringFromEEPROM(2220, blynkApiKey, 35);
|
||||
if (strlen(blynkApiKey) < 25) blynkApiKey[0] = 0;
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
// DMX (2530 - 2549)2535
|
||||
DMXChannels = EEPROM.read(2530);
|
||||
|
@ -70,6 +70,7 @@ void sendBytes(){
|
||||
void handleSerial()
|
||||
{
|
||||
if (pinManager.isPinAllocated(hardwareRX)) return;
|
||||
if (!Serial) return; // arduino docs: `if (Serial)` indicates whether or not the USB CDC serial connection is open. For all non-USB CDC ports, this will always return true
|
||||
|
||||
#ifdef WLED_ENABLE_ADALIGHT
|
||||
static auto state = AdaState::Header_A;
|
||||
|
@ -111,9 +111,17 @@ void sendDataWs(AsyncWebSocketClient * client)
|
||||
DEBUG_PRINTF("JSON buffer size: %u for WS request (%u).\n", doc.memoryUsage(), len);
|
||||
|
||||
size_t heap1 = ESP.getFreeHeap();
|
||||
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
#ifdef ESP8266
|
||||
if (len>heap1) {
|
||||
DEBUG_PRINTLN(F("Out of memory (WS)!"));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
buffer = ws.makeBuffer(len); // will not allocate correct memory sometimes on ESP8266
|
||||
#ifdef ESP8266
|
||||
size_t heap2 = ESP.getFreeHeap();
|
||||
DEBUG_PRINT(F("heap ")); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
#else
|
||||
size_t heap2 = 0; // ESP32 variants do not have the same issue and will work without checking heap allocation
|
||||
#endif
|
||||
@ -148,11 +156,17 @@ bool sendLiveLedsWs(uint32_t wsClient)
|
||||
AsyncWebSocketClient * wsc = ws.client(wsClient);
|
||||
if (!wsc || wsc->queueLength() > 0) return false; //only send if queue free
|
||||
|
||||
uint16_t used = strip.getLengthTotal();
|
||||
const uint16_t MAX_LIVE_LEDS_WS = strip.isMatrix ? 1024 : 256;
|
||||
uint16_t n = ((used -1)/MAX_LIVE_LEDS_WS) +1; //only serve every n'th LED if count over MAX_LIVE_LEDS_WS
|
||||
uint16_t pos = (strip.isMatrix ? 4 : 2);
|
||||
uint16_t bufSize = pos + (used/n)*3;
|
||||
size_t used = strip.getLengthTotal();
|
||||
#ifdef ESP8266
|
||||
const size_t MAX_LIVE_LEDS_WS = 256U;
|
||||
#else
|
||||
const size_t MAX_LIVE_LEDS_WS = 1024U;
|
||||
#endif
|
||||
size_t n = ((used -1)/MAX_LIVE_LEDS_WS) +1; //only serve every n'th LED if count over MAX_LIVE_LEDS_WS
|
||||
size_t pos = (strip.isMatrix ? 4 : 2); // start of data
|
||||
size_t bufSize = pos + (used/n)*3;
|
||||
size_t skipLines = 0;
|
||||
|
||||
AsyncWebSocketMessageBuffer * wsBuf = ws.makeBuffer(bufSize);
|
||||
if (!wsBuf) return false; //out of memory
|
||||
uint8_t* buffer = wsBuf->get();
|
||||
@ -163,11 +177,25 @@ bool sendLiveLedsWs(uint32_t wsClient)
|
||||
buffer[1] = 2; //version
|
||||
buffer[2] = Segment::maxWidth;
|
||||
buffer[3] = Segment::maxHeight;
|
||||
if (Segment::maxWidth * Segment::maxHeight > MAX_LIVE_LEDS_WS*4) {
|
||||
buffer[2] = Segment::maxWidth/4;
|
||||
buffer[3] = Segment::maxHeight/4;
|
||||
skipLines = 3;
|
||||
} else if (Segment::maxWidth * Segment::maxHeight > MAX_LIVE_LEDS_WS) {
|
||||
buffer[2] = Segment::maxWidth/2;
|
||||
buffer[3] = Segment::maxHeight/2;
|
||||
skipLines = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint16_t i = 0; pos < bufSize -2; i += n)
|
||||
for (size_t i = 0; pos < bufSize -2; i += n)
|
||||
{
|
||||
#ifndef WLED_DISABLE_2D
|
||||
if (strip.isMatrix && skipLines) {
|
||||
if ((i/Segment::maxWidth)%(skipLines+1)) i += Segment::maxWidth * skipLines;
|
||||
}
|
||||
#endif
|
||||
uint32_t c = strip.getPixelColor(i);
|
||||
buffer[pos++] = qadd8(W(c), R(c)); //R, add white channel to RGB channels as a simple RGBW -> RGB map
|
||||
buffer[pos++] = qadd8(W(c), G(c)); //G
|
||||
|
@ -364,7 +364,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
|
||||
if (subPage == 2)
|
||||
{
|
||||
char nS[8];
|
||||
char nS[32];
|
||||
|
||||
appendGPIOinfo();
|
||||
|
||||
@ -382,8 +382,8 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('c',SET_F("CR"),cctFromRgb);
|
||||
sappend('v',SET_F("CB"),strip.cctBlending);
|
||||
sappend('v',SET_F("FR"),strip.getTargetFps());
|
||||
sappend('v',SET_F("AW"),Bus::getAutoWhiteMode());
|
||||
sappend('v',SET_F("LD"),strip.useLedsArray);
|
||||
sappend('v',SET_F("AW"),Bus::getGlobalAWMode());
|
||||
sappend('c',SET_F("LD"),strip.useLedsArray);
|
||||
|
||||
for (uint8_t s=0; s < busses.getNumBusses(); s++) {
|
||||
Bus* bus = busses.getBus(s);
|
||||
@ -412,7 +412,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('c',cv,bus->reversed);
|
||||
sappend('v',sl,bus->skippedLeds());
|
||||
sappend('c',rf,bus->isOffRefreshRequired());
|
||||
sappend('v',aw,bus->getAWMode());
|
||||
sappend('v',aw,bus->getAutoWhiteMode());
|
||||
sappend('v',wo,bus->getColorOrder() >> 4);
|
||||
}
|
||||
sappend('v',SET_F("MA"),strip.ablMilliampsMax);
|
||||
@ -445,9 +445,11 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
|
||||
sappend('c',SET_F("GB"),gammaCorrectBri);
|
||||
sappend('c',SET_F("GC"),gammaCorrectCol);
|
||||
dtostrf(gammaCorrectVal,3,1,nS); sappends('s',SET_F("GV"),nS);
|
||||
sappend('c',SET_F("TF"),fadeTransition);
|
||||
sappend('v',SET_F("TD"),transitionDelayDefault);
|
||||
sappend('c',SET_F("PF"),strip.paletteFade);
|
||||
sappend('v',SET_F("TP"),randomPaletteChangeTime);
|
||||
sappend('v',SET_F("BF"),briMultiplier);
|
||||
sappend('v',SET_F("TB"),nightlightTargetBri);
|
||||
sappend('v',SET_F("TL"),nightlightDelayMinsDefault);
|
||||
@ -509,6 +511,7 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('v',SET_F("EU"),e131Universe);
|
||||
sappend('v',SET_F("DA"),DMXAddress);
|
||||
sappend('v',SET_F("XX"),DMXSegmentSpacing);
|
||||
sappend('v',SET_F("PY"),e131Priority);
|
||||
sappend('v',SET_F("DM"),DMXMode);
|
||||
sappend('v',SET_F("ET"),realtimeTimeoutMs);
|
||||
sappend('c',SET_F("FB"),arlsForceMaxBri);
|
||||
@ -521,13 +524,6 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
#ifdef WLED_DISABLE_ALEXA
|
||||
oappend(SET_F("toggle('Alexa');")); // hide Alexa settings
|
||||
#endif
|
||||
sappends('s',SET_F("BK"),(char*)((blynkEnabled)?SET_F("Hidden"):""));
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
sappends('s',SET_F("BH"),blynkHost);
|
||||
sappend('v',SET_F("BP"),blynkPort);
|
||||
#else
|
||||
oappend(SET_F("toggle('Blynk');")); // hide BLYNK settings
|
||||
#endif
|
||||
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
sappend('c',SET_F("MQ"),mqttEnabled);
|
||||
@ -738,10 +734,6 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
sappend('v',SET_F("PH"),strip.panel[0].height);
|
||||
}
|
||||
sappend('v',SET_F("MPC"),strip.panels);
|
||||
sappend('v',SET_F("PB"),strip.matrix.bottomStart);
|
||||
sappend('v',SET_F("PR"),strip.matrix.rightStart);
|
||||
sappend('v',SET_F("PV"),strip.matrix.vertical);
|
||||
sappend('c',SET_F("PS"),strip.matrix.serpentine);
|
||||
// panels
|
||||
for (uint8_t i=0; i<strip.panels; i++) {
|
||||
char n[5];
|
||||
|
Loading…
Reference in New Issue
Block a user