Compare commits

...

230 Commits

Author SHA1 Message Date
cschwinne
71886c162b Release of WLED v0.10.0
DMX Single RGW and Single DRGB modes now support an additional white channel
Improved palettes derived from set colors and changed their names
2020-05-03 20:57:53 +02:00
cschwinne
df1f516f6b Added ACST and ACST/ACDT timezones ( closes #881 ) 2020-05-03 01:48:23 +02:00
cschwinne
2e55189d59 New web UI features 2020-05-02 01:59:41 +02:00
srg74
6ade40ce85 Updated Wemos shield usermod (#880)
* Added support for H803FW controller

* Create usermod_bme280.cpp

* Create usermod_bme280.cpp

* Added BME280 sensor

* Update readme.md

* Update usermod_bme280.cpp

* Update platformio.ini

* Update for lightweight sensor
2020-04-30 23:40:14 +02:00
cschwinne
94c5f0d7a8 New API properties
-   Added realtime override option and `lor` JSON property
-   Added `lm` (live mode) and `lip` (live IP) properties to info in JSON API
-   Added reset commands to APIs
-   Added `json/si`, returning state and info, but no FX or Palette lists
-   Added rollover detection to millis(). Can track uptimes longer than 49 days
-   Attempted to fix Wifi issues with Unifi brand APs
2020-04-30 01:52:36 +02:00
Aircoookie
b1028086a3 Merge pull request #870 from pille/cleanup-segment-options
cleanup code to use descriptive segment options
2020-04-25 14:37:26 +02:00
pille
385b3570b2 cleanup code to use descriptive segment options 2020-04-24 23:35:39 +02:00
cschwinne
77edd12030 Added brightness and power for individual segments ( #289 , #290 ) 2020-04-23 23:52:33 +02:00
Aircoookie
217fca31e4 Merge pull request #865 from o0shojo0o/master
Add DIY PCB SHOJO_PCB (analog)
2020-04-23 00:31:05 +02:00
Dennis Hinzpeter
5e1d20fc72 Add DIY PCB SHOJO_PCB analog 2020-04-22 23:09:21 +02:00
cschwinne
db60309ce8 Added Candle Multi effect
Added Palette capability to Pacifica effect
2020-04-22 00:51:00 +02:00
cschwinne
6a5b757a24 TM1814 support (closes #518 ) 2020-04-19 13:25:27 +02:00
Aircoookie
a19098a004 Merge pull request #835 from martament/f-bw-lt11
Added support for BW-LT11
2020-04-16 23:44:41 +02:00
srg74
ec10c29aca Added BME280 sensor (#850)
* Added support for H803FW controller

* Create usermod_bme280.cpp

* Create usermod_bme280.cpp

* Added BME280 sensor

* Update readme.md

* Update usermod_bme280.cpp
2020-04-15 23:52:10 +02:00
cschwinne
f90ab46794 Add rotary encoder brightness usermod 2020-04-15 01:21:07 +02:00
srg74
b8ca97e019 Added support for H803FW controller (#844) 2020-04-14 00:16:06 +02:00
cschwinne
e12757dbb9 Add Art-Net support (#417) 2020-04-13 00:42:27 +02:00
Ament Martin
3e9b44d193 Added support for BW-LT11 2020-04-10 21:33:16 +02:00
Aircoookie
3006d25406 Merge pull request #809 from raresserban/dmx_settings
DMX: Ability to work together with LEDs and set segment and start LED for fixtures
2020-04-10 12:52:22 +02:00
Aircoookie
f2ae9a0711 Merge branch 'master' into dmx_settings 2020-04-10 12:36:02 +02:00
cschwinne
19945e4ccb Fix DMX compilation 2020-04-10 12:30:08 +02:00
Aircoookie
61ab16acd6 Merge pull request #830 from srg74/patch-1
Update readme.md
2020-04-09 17:04:35 +02:00
srg74
3a84292f82 Update readme.md 2020-04-09 09:06:44 -04:00
Aircoookie
1d314294c7 Merge pull request #828 from srg74/master
Update user mode directories
2020-04-08 16:25:28 +02:00
Bukovina
b5b1dbfe85 Fix platformio.ini 2020-04-08 09:30:49 -04:00
Bukovina
5be88dd188 QuinLED mod update 2020-04-08 09:18:26 -04:00
Bukovina
88b67b9541 Usermod changes 2020-04-08 08:40:44 -04:00
Bukovina
a31da3186f UserMod files update 2020-04-08 08:35:32 -04:00
Bukovina
9a7a38e913 Merge branch 'Aircoookie-master' 2020-04-08 07:28:35 -04:00
Bukovina
a0960f5468 Merge branch 'master' of https://github.com/Aircoookie/WLED into Aircoookie-master 2020-04-08 07:20:33 -04:00
Aircoookie
9b87a512cf Merge pull request #827 from Aircoookie/refactor-cpp
Project structure refactor to .cpp/.h
2020-04-07 00:14:57 +02:00
cschwinne
8da985b6d0 Fixed RBG and BGR getPixelColor (#825)
Improved formatting
2020-04-07 00:04:09 +02:00
cschwinne
5cb2a39746 Consolidated global variables in wled.h 2020-04-06 02:25:17 +02:00
cschwinne
6268cadc95 Function definitions in func_declare.h
Significantly reducing number of header files
2020-03-31 02:38:08 +02:00
Aircoookie
470b4b3972 Merge pull request #814 from TravisDean/refactor-remove-ino
Refactor to remove ino usage
2020-03-31 02:33:38 +02:00
Travis Dean
a88ae2ca56 Delete .clang-format 2020-03-30 08:48:01 -04:00
Travis J Dean
9875fbef0a Layout changes. 2020-03-30 08:34:20 -04:00
Travis J Dean
cf29ddc8d0 Typo fix. 2020-03-30 08:03:55 -04:00
Travis J Dean
ad70fcba7f Typo fix. 2020-03-30 08:00:58 -04:00
Travis J Dean
a9a7720a11 Import dmx output library into project. 2020-03-30 07:45:33 -04:00
Travis J Dean
8ff4f50f79 Fix visual studio project files and organize. 2020-03-30 07:24:45 -04:00
Travis J Dean
aea07f42d1 Fix mistaken substitute. 2020-03-30 06:56:51 -04:00
Travis J Dean
8d75c06852 Format changes. 2020-03-30 06:42:21 -04:00
Travis J Dean
ffbedbc1e6 Add clang format to git ignore. 2020-03-30 06:27:36 -04:00
Travis J Dean
a47d48c973 Add clang format. 2020-03-30 05:19:09 -04:00
Travis J Dean
c54092c932 Remove redundant defines. 2020-03-30 05:04:20 -04:00
Travis J Dean
9134c3b4af Merge branch 'master' into refactor-remove-ino 2020-03-30 04:51:56 -04:00
Travis J Dean
7e21955211 wledInit -> setup 2020-03-30 04:43:37 -04:00
Travis J Dean
40ac760285 Move getSignalQuality to json.cpp 2020-03-30 04:41:42 -04:00
Travis J Dean
de63bdac39 Code reorg. 2020-03-30 04:35:52 -04:00
Travis J Dean
408d63825a Function prototype cleanup. 2020-03-30 04:26:41 -04:00
Travis J Dean
3e1eb02f54 Comment cleanup and line reduction. 2020-03-30 04:21:47 -04:00
Travis J Dean
d2f55e1064 Make dmx.h header only. 2020-03-30 03:55:44 -04:00
srg74
c97bead631 Merge pull request #65 from Aircoookie/master
Update
2020-03-28 17:33:57 -04:00
Aircoookie
8264ca4e9e Create stale.yml (to reduce older open issues) 2020-03-28 21:30:32 +01:00
Aircoookie
05bdaa4bc7 Merge pull request #808 from feindsender/P9813
Add P9813 LED driver support
2020-03-28 21:22:08 +01:00
Travis J Dean
cc2de04f6b Avoid name collision. 2020-03-28 09:24:07 -04:00
Travis J Dean
f99f13a090 Avoid name collision. Fix wled instance access in ino. 2020-03-28 08:45:20 -04:00
Travis J Dean
f35ab125ec Rename files to remove wled_ 2020-03-28 08:30:51 -04:00
Travis J Dean
b8342f1c9c actually call the setup function. 2020-03-28 07:32:02 -04:00
Rares Serban
0ce77bbc59 Add ability to set DMX fixtures to a segment and from what LED they should start. 2020-03-28 13:13:39 +02:00
srg74
e39eccb99e Merge pull request #64 from Aircoookie/master
update
2020-03-27 18:28:50 -04:00
feindsender
77ce67d685 Add P9813 LED driver support
Adds support for the P9813 LED driver
2020-03-27 10:03:23 +01:00
cschwinne
ef125ff109 Fixed compilation for Analog LEDs
Fixed sync settings network port fields too small
2020-03-26 19:43:23 +01:00
Travis J Dean
30e3bbd0e8 Renamed min/max macros to fix potential std::min/max conflict (depending on include order). 2020-03-26 05:18:19 -04:00
Travis J Dean
7bf1c35dcf Change interface of BlynkSimpleEsp. 2020-03-26 04:56:19 -04:00
Travis J Dean
c6ea2dff8a Add further includes. 2020-03-26 04:49:35 -04:00
Travis J Dean
f2329476ec Fix linker errors. All global vars declared extern. 2020-03-26 04:12:55 -04:00
cschwinne
c4512b75d9 Fixed live preview not displaying whole light if over 255 LEDs 2020-03-26 01:44:38 +01:00
srg74
92e43abbc4 Merge pull request #63 from Aircoookie/master
Updates
2020-03-25 16:58:17 -04:00
cschwinne
07d6bfa989 Added Pacifica effect (closes #790) 2020-03-25 11:17:45 +01:00
Travis J Dean
ccf5e66f31 Compiles, but does not link. 2020-03-25 05:43:12 -04:00
Travis J Dean
6f5e71164a Further fixing of includes. 2020-03-25 05:14:23 -04:00
Travis J Dean
12131764d1 Prior to refactoring includes and forward definitions. 2020-03-25 04:36:55 -04:00
Travis J Dean
594c0b8550 Transform ino to h/cpp. Class WLED created. 2020-03-25 04:00:55 -04:00
cschwinne
ed729c32d2 Fixed Alexa whites 2020-03-25 00:59:48 +01:00
srg74
ea26ee8d40 Merge pull request #62 from Aircoookie/master
Update
2020-03-22 22:38:23 -04:00
cschwinne
53f09c0630 Moved Cronixie driver from FX library to drawOverlay handler 2020-03-22 17:45:09 +01:00
Aircoookie
2856e02eac Merge pull request #787 from stockklauser/master
Fix a code Issue for non DMX usage and Adaopt Project structure to Visual Studio
2020-03-22 16:21:36 +01:00
Thomas Stockklauser
a4f0c9195e 1. Fix an Issue withtin the DMX Compiler Flags if you dont use it in wled00.ino
2. Fix the Build / working environment for Visual Studio and make a better Folder Structure within the Visual Studio Project
2020-03-22 11:38:29 +01:00
srg74
0e73a0293b Merge pull request #61 from Aircoookie/master
Update
2020-03-20 22:29:33 -04:00
cschwinne
f4f5d6e562 Merge branch 'master' of https://github.com/Aircoookie/WLED 2020-03-21 00:57:58 +01:00
cschwinne
e5c3629e2e Added custom per-LED mapping 2020-03-21 00:57:54 +01:00
Aircoookie
5028471598 Merge pull request #784 from TravisDean/fix-skip-first
Fix initialization bug when toggling skip first.
2020-03-19 19:18:16 +01:00
Travis J Dean
c28027496d Fix initialization bug when toggling skip first. 2020-03-19 00:37:35 -04:00
srg74
c0f5509652 Merge pull request #60 from Aircoookie/master
Add on
2020-03-16 16:27:00 -04:00
Aircoookie
9bc48ececa Merge pull request #774 from hobbyquaker/battery-keypad-controller
add battery-keypad-controller usermod
2020-03-15 22:11:51 +01:00
srg74
1f53e4d4a2 Merge pull request #59 from Aircoookie/master
Various small fixes
2020-03-15 11:06:31 -04:00
hobbyquaker
dbef0e6583 fix lint issues 2020-03-15 12:43:09 +01:00
hobbyquaker
c246e5af35 add battery-keypad-controller usermod 2020-03-15 12:38:49 +01:00
cschwinne
d36796429e Various small fixes
Fixed color of main segment returned in JSON API during transition not being target color
- Fixed arlsLock() being called after pixels set in E1.31, (closes #772)
- Fixed HTTP API calls not having an effect if no segment selected (now applies to main segment)
2020-03-14 11:28:42 +01:00
srg74
37a31a9b94 Update platformio.ini 2020-03-13 20:44:05 -04:00
srg74
c2ab3f96a7 gitignore update 2020-03-13 20:42:15 -04:00
srg74
ef36b5377d Merge pull request #58 from Aircoookie/master
Update
2020-03-13 18:44:41 -04:00
Aircoookie
f12237d298 Merge pull request #769 from mike2nl/patch-1
CHANGELOG.md - Make it more readable
2020-03-13 09:51:38 +01:00
Mike
5b312d4c8b Make it better readable
Make it better readable and make use of single line for add/chgange and/or delete
2020-03-13 08:04:55 +01:00
Aircoookie
d21e82b020 Create changelog 2020-03-12 23:26:38 +01:00
srg74
c6e5606b4c Merge pull request #57 from Aircoookie/master
Update
2020-03-10 19:20:40 -04:00
Aircoookie
7b4dc43147 Merge pull request #766 from pille/E1.31-sequencenumber-per-universe
fixes #742
2020-03-10 23:02:38 +01:00
pille
62510ac6a3 add E1.31 packet out-of-sequence config option, wrt #742 2020-03-10 18:28:51 +01:00
pille
bffe2d7bd0 track E1.31 seqcuence numbers for each universe individually, wrt #742 2020-03-10 17:33:23 +01:00
srg74
cbaf1e576d Merge pull request #56 from Aircoookie/master
Usermod: Project Cars rpm indicator and shift lights (#759)
2020-03-06 21:25:30 -05:00
jwingefeld
0d355dbf35 Usermod: Project Cars rpm indicator and shift lights (#759)
* project cars shiftlight usermod

* added readme

* rephrased stuff in readme.md because reasons

Co-authored-by: Jan <jan.wingefeld@gmail.com>
2020-03-06 23:45:45 +01:00
srg74
d851bff762 Merge pull request #54 from Aircoookie/master
Trying to fix failed build (#756)
2020-03-05 17:14:15 -05:00
Aircoookie
453f4b549b Trying to fix failed build (#756) 2020-03-05 09:39:43 +01:00
srg74
8d669b12b6 Truing to fix failed build 2020-03-04 23:15:12 -05:00
srg74
ed3234d949 Update UserMod
Updating UserMod as per request from discourse forum user. He want to use with ESP32 also as QuinLED board support to types - ESP8266 ans ESP32.
Removed .txt file as it create an extra step in setup.
2020-03-04 23:01:00 -05:00
srg74
603a00376f Merge pull request #53 from Aircoookie/master
Add custom32_LEDPIN_16 environment (from #748 )
2020-03-04 20:31:56 -05:00
cschwinne
4f34cfb654 Add custom32_LEDPIN_16 environment (from #748 ) 2020-03-04 11:45:25 +01:00
srg74
fd1e536cdb Merge pull request #52 from Aircoookie/master
Update
2020-03-03 17:47:19 -05:00
cschwinne
0c6a880a74 Merge branch 'master' of https://github.com/Aircoookie/WLED 2020-03-03 17:53:51 +01:00
cschwinne
89fa053310 Add "np" API option to not commit
Re-add IRremote flags to platformio.ini
2020-03-03 17:53:47 +01:00
Def3nder
267887908e New IRremote functions (#746)
* Switch to strip.getPaletteCount()

* fixed color conversion errors

Co-authored-by: Aircoookie <cschwinne@gmail.com>
2020-03-02 13:31:34 +01:00
Def3nder
b86f58befe IR remotes can disable NightLight with "OFF" (#745)
* IR can disable Nightlight with "OFF"
2020-03-02 12:41:14 +01:00
Def3nder
b804101c24 lift NeoPixelBus library to 2.5.7 (#747) 2020-03-02 12:24:10 +01:00
Def3nder
f28502514f Remember lastColor and last Bri for Solid RGBW (#743) 2020-03-01 12:25:44 +01:00
cschwinne
79da716a44 Split esp01_1m env into 1m_full and 1m_ota (closes #740 ) 2020-02-29 19:52:47 +01:00
srg74
f76a440b74 Merge pull request #51 from Aircoookie/master
Update
2020-02-29 13:39:36 -05:00
cschwinne
18dad0c72c Remove defunct presetApplyCol and presetApplyFx 2020-02-29 18:42:55 +01:00
cschwinne
14a5ab6740 Fixed Chase modes 2020-02-29 18:24:51 +01:00
Def3nder
d0d56c4416 Travis.CI builds only for default_envs (#739) 2020-02-29 16:30:15 +01:00
srg74
9dd9a01211 Merge pull request #50 from Aircoookie/master
Update
2020-02-28 16:42:15 -05:00
Def3nder
480e7f5b54 Add all release environments to platformio.ini (#736) 2020-02-28 18:53:38 +01:00
Def3nder
cffee7bfa7 Fix 24-key IR remote (#738) 2020-02-28 16:27:18 +01:00
srg74
5b9eda9c63 Merge pull request #49 from Aircoookie/master
Update
2020-02-27 14:34:55 -05:00
Aircoookie
0a363d5fc0 Merge pull request #732 from Jason2866/patch-1
Reduce CPU load during interrupt handler
2020-02-27 18:56:54 +01:00
Jason2866
9eb646085e Reduce CPU load during interrupt handler
See https://github.com/esp8266/Arduino/pull/7057#issuecomment-591632232
2020-02-27 09:52:48 +01:00
Ser Ko
e3269f6edc Update wled06_usermod.ino 2020-02-26 20:36:27 -05:00
Ser Ko
57d3120b45 Grammar correction 2020-02-26 19:21:57 -05:00
Ser Ko
81da8261a0 Added board heltec_wifi_kit_8 2020-02-26 19:16:33 -05:00
srg74
7e5949b4a9 Merge pull request #46 from Aircoookie/master
Refactor platformio.ini (#721)
2020-02-26 19:01:27 -05:00
Def3nder
a776b8ac31 Refactor platformio.ini (#721)
* Override script updated accordingly

* ldscriipt for 1m0 adjusted

* backup files deleted

* deletion of wled00,ino.cpp

* remove travis build from PIO
2020-02-26 11:17:56 +01:00
srg74
14e19226ea Merge pull request #43 from Aircoookie/master
Update
2020-02-25 16:30:04 -05:00
Aircoookie
5473b3e42e Merge pull request #719 from zewelor/use_new_platformio_ldscript_syntax
Use new platformio ldscript syntax
2020-02-25 09:00:09 +01:00
zewelor
143179cac9 Use new platformio ldscript syntax 2020-02-25 08:42:28 +01:00
srg74
ad2c7ee363 Merge pull request #40 from Aircoookie/master
Update
2020-02-24 21:21:20 -05:00
cschwinne
755448f9f5 Fix LED pin changed 2020-02-25 02:25:17 +01:00
cschwinne
f304a6891f Free more than 2kB of RAM
Store Palettes in PROGMEM
F() select long and rarely used strings
Refactor hue error
2020-02-25 02:19:12 +01:00
srg74
1221661ae3 Added Heltec WiFi-Kit-8 to UserMod (#717) 2020-02-24 22:51:11 +01:00
srg74
a78f17abec Update readme.md 2020-02-24 16:48:01 -05:00
srg74
70bf957a8a Added Heltec WiFi-Kit-8 2020-02-24 16:44:56 -05:00
Ser Ko
e8e04db7b4 Merge branch 'master' of https://github.com/srg74/WLED 2020-02-24 16:39:37 -05:00
Ser Ko
d5def30c59 Update wled06_usermod.ino 2020-02-24 16:36:03 -05:00
srg74
81176bc4e6 Merge pull request #39 from Aircoookie/master
Indents for the #ifdef's in wled00.ino (#716)
2020-02-24 16:32:34 -05:00
Def3nder
730ba12c8d Indents for the #ifdef's in wled00.ino (#716) 2020-02-24 22:09:33 +01:00
srg74
80ad456d48 Merge pull request #38 from Aircoookie/master
Update
2020-02-24 15:23:35 -05:00
cschwinne
2d75526395 Fix brightness transition updating too often 2020-02-24 19:36:25 +01:00
Aircoookie
cd618a43d4 Merge pull request #714 from zewelor/allow_platformio_ini_overrides
Allow platformio ini overrides
2020-02-24 19:11:46 +01:00
Aircoookie
1979236f3a Merge pull request #715 from zewelor/allow_to_override_some_const
Allow to override some costs
2020-02-24 19:10:37 +01:00
cschwinne
3589adcb78 Merge branch 'master' of https://github.com/Aircoookie/WLED 2020-02-24 19:08:35 +01:00
cschwinne
4a834ecfc8 Fix UTC offset not working 2020-02-24 19:08:29 +01:00
zewelor
3dcc3492e8 Allow to override some costs 2020-02-24 18:48:21 +01:00
Def3nder
2e77dcc660 Correct sun rise (#713) 2020-02-24 17:27:59 +01:00
cschwinne
89f60a0422 Refactor colorUpdated() 2020-02-24 17:25:40 +01:00
zewelor
0455c09e4c Allow platformio ini overrides 2020-02-24 16:42:24 +01:00
cschwinne
7360b882ac DMX settings only when enabled 2020-02-24 12:54:23 +01:00
cschwinne
5ffd29e31a Merge branch 'master' of https://github.com/Aircoookie/WLED 2020-02-24 12:45:47 +01:00
cschwinne
5d7e892464 Different PIO settings 2020-02-24 12:44:41 +01:00
Def3nder
e8fd5de5b2 HTML API "/url" for the current effect settings (#664) 2020-02-24 12:18:30 +01:00
srg74
a8e7aa99e8 Update wled06_usermod.ino 2020-02-23 22:48:58 -05:00
srg74
9a0db83f83 Added Heltec WiFi-Kit-8 with 0.91" display 2020-02-23 21:03:36 -05:00
srg74
4e85566b88 Merge pull request #37 from Aircoookie/master
Update
2020-02-23 20:53:18 -05:00
jwingefeld
8be72f6f23 DMX Support for WLED (#704)
* initial dmx setup

* adds support for multiple fixtures, addr gaps, start addresses and all that good DMX stuff

* removes init function. do not need.

* adds some comments, removes others. words.

* added menu entry and dummy HTML

* added server request handler

* cloned options page UI for DMX

* only add code when DMX is enabled

* added infobutton to HTML

* DMX settings form

* procedurally generated HTML form. OBACHT: Values still not coming from the EEPROM.

* upped eeprom version to 15

* changed index for set to 255 to 6 because web interface wants it that way

* gets values for XML from actual settings

* changes the default values for dmx to blanks

* reads and writes DMX settings from EEPROM (2550 - 2569)

* fixes addressing bug in DMX EEPROM read

* saves settings from WebUI to memory

* disables DMX by default

* changed a comment in the ENABLE_DMX line

* makes the display of the DMX entry in settings dependant on WLED_DMX_ENABLE

* adds the server listener for the DMX map

* fixes a bug when selecting 255 for a channel at the dmx settings page

* now actually reads the DMX settings back to the HTML UI.

* cleans up a little

* adds a warning message to the HTML UI when setting up defunct DMX settings

* changed DMX EEPROM addressing to close a gap

* basic DMX map

* fixes a few styling flaws and bugs in the DMX map

* changes config variables to uint16_t

Co-authored-by: Aircoookie <cschwinne@gmail.com>
2020-02-23 22:24:51 +01:00
Def3nder
513bc2c0ab Correct SunRise/NightLight with Color Fade (#710) 2020-02-23 22:21:32 +01:00
srg74
036ba77a68 Merge pull request #35 from Aircoookie/master
Release of WLED v0.9.1
2020-02-22 22:06:30 -05:00
srg74
a7092ac503 Merge pull request #33 from Aircoookie/master
Update from orig
2020-02-22 17:38:00 -05:00
srg74
fb59f1f0a0 Update wled06_usermod.ino 2020-02-21 16:55:58 -05:00
srg74
b1961033b3 Update readme.md 2020-02-20 22:48:20 -05:00
srg74
863498f762 Update readme.md 2020-02-20 22:43:59 -05:00
srg74
bdc44a4070 Update readme.md 2020-02-20 20:53:17 -05:00
srg74
6451522f89 Update readme.md 2020-02-20 20:50:38 -05:00
srg74
5ca1e9268c Update readme.md 2020-02-20 20:49:33 -05:00
srg74
451a6841c9 Update readme.md 2020-02-20 20:48:25 -05:00
Ser Ko
3e3f46a683 Added new mod 2020-02-20 20:46:00 -05:00
srg74
2b0eaafea6 Merge pull request #29 from Aircoookie/master
Update
2020-02-20 14:40:58 -05:00
srg74
0cc1007543 Merge pull request #28 from Aircoookie/master
Update
2020-02-19 19:29:53 -05:00
Ser Ko
8ca86181e4 Updated wled06_usermod.ino
User mode file updated for flip display in case of using on WLED Wemos shield
2020-02-19 19:27:09 -05:00
srg74
036bd07e72 Merge pull request #27 from Aircoookie/master
Update
2020-02-18 19:46:45 -05:00
srg74
8d66d38fd2 Merge pull request #26 from Aircoookie/master
Simplify Code for Gradient / Loading effect (#671)
2020-02-11 21:43:22 -05:00
srg74
21fe2c5f8f Merge pull request #24 from Aircoookie/master
Update
2020-02-09 17:36:06 -05:00
srg74
c9025917b2 Merge pull request #23 from Aircoookie/master
Update
2020-02-09 14:24:45 -05:00
srg74
680923bdd5 Merge pull request #22 from Aircoookie/master
Update
2020-02-09 08:57:15 -05:00
srg74
cde360f7ec Merge pull request #21 from Aircoookie/master
Update
2020-02-05 20:13:49 -05:00
Ser Ko
adcd7fb170 Added tested display sizes 2020-02-05 12:25:26 -05:00
Ser Ko
f105436b41 Corrected comment
Since 2 common size of OLED display can be used (0.91" and 0.96") removed comment about display size
2020-02-05 12:23:06 -05:00
Ser Ko
47738c751c Update wled06_usermod.ino
Controller design changed. New version with relay. Dallas sensor pin changed to GPIO 13.
2020-02-05 12:03:24 -05:00
srg74
0b3f2da6ef Merge pull request #20 from Aircoookie/master
Update
2020-02-04 15:59:06 -05:00
srg74
8f36878dde Merge pull request #19 from Aircoookie/master
Update
2020-01-30 15:32:47 -05:00
srg74
e610a1ffe4 Merge pull request #18 from Aircoookie/master
Update
2020-01-28 22:43:03 -05:00
srg74
b5213794a8 Merge pull request #17 from Aircoookie/master
update
2020-01-26 08:51:46 -05:00
srg74
447f15cfa4 Merge pull request #16 from Aircoookie/master
Update from original
2020-01-24 17:24:22 -05:00
srg74
3d0d027216 Update platformio.ini 2020-01-24 16:52:41 -05:00
srg74
b58a17a99e Display size is irrelevant 2020-01-20 15:28:39 -05:00
srg74
adaf2e15cd Merge pull request #15 from Aircoookie/master
Update to usermod Enclosure_with_OLED_temp_ESP07 (#607)
2020-01-20 14:52:21 -05:00
srg74
9cd0a7982a Merge pull request #14 from Aircoookie/master
Re-add NEC decoder (closes #608)
2020-01-20 11:59:56 -05:00
srg74
607a66b983 Update readme.md 2020-01-19 18:54:48 -05:00
srg74
38b2adcaad Fixed wled06_usermod.ino
And added link to readme.md
2020-01-19 18:53:11 -05:00
srg74
d7879d8853 Merge pull request #13 from Aircoookie/master
Update
2020-01-19 11:59:13 -05:00
srg74
1042ac141a Delete main.yml 2020-01-18 20:27:35 -05:00
srg74
81aab35231 Create main.yml 2020-01-18 20:22:44 -05:00
srg74
1c5742c7d4 Delete ccpp.yml 2020-01-18 20:04:15 -05:00
srg74
4d646e67f3 Create ccpp.yml 2020-01-18 20:03:18 -05:00
srg74
59fbc51283 Merge pull request #12 from Aircoookie/master
Update
2020-01-18 19:42:28 -05:00
srg74
71af63dfc7 Update readme.md 2020-01-18 17:45:11 -05:00
srg74
0cae048ada Update readme.md 2020-01-18 17:40:52 -05:00
Ser Ko
71021da261 Update readme.md 2020-01-18 17:36:04 -05:00
Ser Ko
1d897e491a Update readme.md 2020-01-18 17:31:36 -05:00
Ser Ko
57c0b408e5 Update readme.md 2020-01-18 17:26:06 -05:00
Ser Ko
43e0186efe Update readme.md 2020-01-18 16:46:48 -05:00
srg74
8831d74cbc Update readme.md 2020-01-18 16:29:28 -05:00
srg74
9a9d2cb964 Update readme.md 2020-01-18 16:17:45 -05:00
srg74
2fc2a0cbdb Update readme.md 2020-01-18 16:16:51 -05:00
srg74
40c041c9e7 Update readme.md 2020-01-18 16:15:37 -05:00
srg74
b00c1dd055 Update readme.md 2020-01-18 16:14:32 -05:00
srg74
761245049f Update readme.md 2020-01-18 16:10:03 -05:00
srg74
30e142edd3 Update readme.md 2020-01-18 16:09:39 -05:00
srg74
b7d84c002d Add files via upload 2020-01-18 16:08:49 -05:00
srg74
551afe0cd7 Add files via upload 2020-01-18 16:08:14 -05:00
srg74
5d8bfc2930 Create readme.md 2020-01-18 16:07:27 -05:00
srg74
5d947cc8e1 Create readme.md 2020-01-18 16:06:26 -05:00
srg74
7bf92db4c9 Delete Enclosure_with_OLED_temp_ESP07 2020-01-18 16:05:49 -05:00
srg74
593c1d6b05 Create Enclosure_with_OLED_temp_ESP07 2020-01-18 16:01:31 -05:00
srg74
30e326b8b8 Merge pull request #11 from Aircoookie/master
Update
2020-01-15 16:20:06 -05:00
srg74
bed52d0a4a Merge pull request #9 from Aircoookie/master
Sync with orig
2020-01-14 16:23:08 -05:00
srg74
d9d2ad4382 Merge pull request #7 from Aircoookie/master
Sync to parent
2020-01-13 15:31:01 -05:00
srg74
3379e7cc48 Merge pull request #6 from Aircoookie/master
Update to recent
2020-01-12 10:08:50 -05:00
srg74
339be2b7a4 Merge pull request #5 from Aircoookie/master
Add staircase wipe usermod
2020-01-10 20:08:23 -05:00
srg74
a8a61665f4 Merge pull request #4 from Aircoookie/master
Include new branch of IRremoteESP8266 to save 21k (#582)
2020-01-10 17:48:45 -05:00
srg74
65154e48cb Merge pull request #3 from Aircoookie/master
Update to recent
2020-01-08 17:06:52 -05:00
srg74
19f6fd2295 Merge pull request #2 from Aircoookie/master
Update repository
2020-01-06 21:01:36 -05:00
81 changed files with 7753 additions and 4725 deletions

20
.github/stale.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 120
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- keep
- enhancement
- confirmed
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
Hey! This issue has been open for quite some time without any new comments now.
It will be closed automatically in a week if no further activity occurs.
Thank you for using WLED!
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

4
.gitignore vendored
View File

@@ -5,3 +5,7 @@
!.vscode/extensions.json
/wled00/Release
/wled00/extLibs
/platformio_override.ini
.DS_Store
.gitignore
.clang-format

View File

@@ -18,18 +18,26 @@
# it (remove "# " before each line) or use own configuration according to the
# Travis CI documentation (see above).
#
# * Test the Travis config here:
# < https://config.travis-ci.com/explore >
#
language: python
python:
- "2.7"
sudo: false
# - "2.7"
- "3.5"
os: linux
cache:
bundler: true
ccache: true
directories:
- "~/.platformio"
- "~/.buildcache"
env:
- PLATFORMIO_CI_SRC=wled00
install:
- pip install -U platformio
- platformio update
script:
- platformio ci --project-conf=./platformio.ini
# - platformio ci --project-conf=./platformio.ini
- platformio run

111
CHANGELOG.md Normal file
View File

@@ -0,0 +1,111 @@
## WLED changelog
### WLED version 0.10.0
#### Build 2005030
- DMX Single RGW and Single DRGB modes now support an additional white channel
- Improved palettes derived from set colors and changed their names
### Development versions between 0.9.1 and 0.10.0 release
#### Build 2005020
- Added ACST and ACST/ACDT timezones
#### Build 2005010
- Added module info page to web UI
- Added realtime override functionality to web UI
- Added individial segment power and brightness to web UI
- Added feature to one-click select single segment only by tapping segment name
- Removed palette jumping to default if color is changed
#### Build 2004300
- Added realtime override option and `lor` JSON property
- Added `lm` (live mode) and `lip` (live IP) properties to info in JSON API
- Added reset commands to APIs
- Added `json/si`, returning state and info, but no FX or Palette lists
- Added rollover detection to millis(). Can track uptimes longer than 49 days
- Attempted to fix Wifi issues with Unifi brand APs
#### Build 2004230
- Added brightness and power for individual segments
- Added `on` and `bri` properties to Segment object in JSON API
- Added `C3` an `SB` commands to HTTP get API
- Merged pull request #865 for 5CH_Shojo_PCB environment
#### Build 2004220
- Added Candle Multi effect
- Added Palette capability to Pacifica effect
#### Build 2004190
- Added TM1814 type LED defines
#### Build 2004120
- Added Art-Net support
- Added OTA platform to platformio.ini
#### Build 2004100
- Fixed DMX output compilation
- Added DMX start LED setting
#### Build 2004061
- Fixed RBG and BGR getPixelColor (#825)
- Improved formatting
#### Build 2004060
- Consolidated global variables in wled.h
#### Build 2003300
- Major change of project structure from .ino to .cpp and func_declare.h
#### Build 2003262
- Fixed compilation for Analog LEDs
- Fixed sync settings network port fields too small
#### Build 2003261
- Fixed live preview not displaying whole light if over 255 LEDs
#### Build 2003251
- Added Pacifica effect (tentative, doesn't yet support other colors)
- Added Atlantica palette
- Fixed ESP32 build of Espalexa
#### Build 2003222
- Fixed Alexa Whites on non-RGBW lights (bump Espalexa to 2.4.5)
#### Build 2003221
- Moved Cronixie driver from FX library to drawOverlay handler
#### Build 2003211
- Added custom mapping compile define to FX_fcn.h
- Merged pull request #784 by @TravisDean: Fixed initialization bug when toggling skip first
- Added link to youtube videos by Room31 to readme
#### Build 2003141
- Fixed color of main segment returned in JSON API during transition not being target color (closes #765)
- Fixed arlsLock() being called after pixels set in E1.31 (closes #772)
- Fixed HTTP API calls not having an effect if no segment selected (now applies to main segment)
#### Build 2003121
- Created changelog.md - make tracking changes to code easier
- Merged pull request #766 by @pille: Fix E1.31 out-of sequence detection

View File

@@ -2,31 +2,111 @@
; Please visit documentation: https://docs.platformio.org/page/projectconf.html
[platformio]
src_dir = ./wled00
src_dir = ./wled00
data_dir = ./wled00/data
;lib_extra_dirs = ./wled00/src
lib_dir = ./wled00/src
; Please uncomment one of the 5 lines below to select your board
default_envs = nodemcuv2
lib_dir = ./wled00/src
build_cache_dir = ~/.buildcache
extra_configs =
platformio_override.ini
# ------------------------------------------------------------------------------
# ENVIRONMENTS
#
# Please uncomment one of the lines below to select your board(s)
# ------------------------------------------------------------------------------
# Travis CI binaries (comment this out when building for single board)
default_envs = d1_mini, esp01, esp01_1m_ota, esp32dev
# Release binaries
; default_envs = nodemcuv2, esp01, esp01_1m_ota, esp01_1m_full, esp32dev, custom_WS2801, custom_APA102, custom_LEDPIN_16, custom_LEDPIN_4, custom32_LEDPIN_16
# Single binaries (uncomment your board)
; default_envs = nodemcuv2
; default_envs = esp01
; default_envs = esp01_1m
; default_envs = esp01_1m_ota
; default_envs = esp01_1m_full
; default_envs = esp07
; default_envs = d1_mini
; default_envs = heltec_wifi_kit_8
; default_envs = h803wf
; default_envs = d1_mini_debug
; default_envs = d1_mini_ota
; default_envs = esp32dev
; default_envs = esp8285_4CH_MagicHome
; default_envs = esp8285_4CH_H801
; default_envs = esp8285_5CH_H801
; default_envs = d1_mini_5CH_Shojo_PCB
; default_envs = wemos_shield_esp32
[common]
framework = arduino
monitor_speed = 115200
board_build.flash_mode = dout
upload_speed = 115200
upload_speed_fast = 921600
build_flags =
-w ; supresses all C/C++ warnings
; -D VERSION=0.8.5
; -D DEBUG
# ------------------------------------------------------------------------------
# PLATFORM:
# !! DO NOT confuse platformio's ESP8266 development platform with Arduino core for ESP8266
#
# arduino core 2.3.0 = platformIO 1.5.0
# arduino core 2.4.0 = platformIO 1.6.0
# arduino core 2.4.1 = platformIO 1.7.3
# arduino core 2.4.2 = platformIO 1.8.0
# arduino core 2.5.0 = platformIO 2.0.4
# arduino core 2.5.1 = platformIO 2.1.1
# arduino core 2.5.2 = platformIO 2.2.3
# arduino core 2.6.1 = platformIO 2.3.0
# arduino core 2.6.2 = platformIO 2.3.1
# arduino core 2.6.3 = platformIO 2.3.2
# ------------------------------------------------------------------------------
arduino_core_2_3_0 = espressif8266@1.5.0
arduino_core_2_4_0 = espressif8266@1.6.0
arduino_core_2_4_1 = espressif8266@1.7.3
arduino_core_2_4_2 = espressif8266@1.8.0
arduino_core_2_5_0 = espressif8266@2.0.4
arduino_core_2_5_1 = espressif8266@2.1.1
arduino_core_2_5_2 = espressif8266@2.2.3
arduino_core_2_6_1 = espressif8266@2.3.0
arduino_core_2_6_2 = espressif8266@2.3.1
arduino_core_2_6_3 = espressif8266@2.3.3
# Development platforms
arduino_core_develop = https://github.com/platformio/platform-espressif8266#develop
arduino_core_git = https://github.com/platformio/platform-espressif8266#feature/stage
platform = ${common.arduino_core_2_4_2}
platform_latest = ${common.arduino_core_2_6_3}
# ------------------------------------------------------------------------------
# FLAGS: DEBUG
#
# ------------------------------------------------------------------------------
debug_flags = -D DEBUG=1 -D WLED_DEBUG -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_TLS_MEM
#if needed (for memleaks etc) also add; -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h"
#-DDEBUG_ESP_CORE is not working right now
# ------------------------------------------------------------------------------
# FLAGS: ldscript
# ldscript_512k ( 512 KB) = 487 KB sketch, 4 KB eeprom, no spiffs, 16 KB reserved
# ldscript_1m0m (1024 KB) = 999 KB sketch, 4 KB eeprom, no spiffs, 16 KB reserved
# ldscript_2m1m (2048 KB) = 1019 KB sketch, 4 KB eeprom, 1004 KB spiffs, 16 KB reserved
# ldscript_4m1m (4096 KB) = 1019 KB sketch, 4 KB eeprom, 1002 KB spiffs, 16 KB reserved, 2048 KB empty/ota?
# ldscript_4m3m (4096 KB) = 1019 KB sketch, 4 KB eeprom, 3040 KB spiffs, 16 KB reserved
#
# Available lwIP variants (macros):
# -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH = v1.4 Higher Bandwidth (default)
# -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY = v2 Lower Memory
# -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH = v2 Higher Bandwidth
#
# BearSSL performance:
# When building with -DSECURE_CLIENT=SECURE_CLIENT_BEARSSL, please add `board_build.f_cpu = 160000000` to the environment configuration
#
# BearSSL ciphers:
# When building on core >= 2.5, you can add the build flag -DBEARSSL_SSL_BASIC in order to build BearSSL with a limited set of ciphers:
# TLS_RSA_WITH_AES_128_CBC_SHA256 / AES128-SHA256
# TLS_RSA_WITH_AES_256_CBC_SHA256 / AES256-SHA256
# TLS_RSA_WITH_AES_128_CBC_SHA / AES128-SHA
# TLS_RSA_WITH_AES_256_CBC_SHA / AES256-SHA
# This reduces the OTA size with ~45KB, so it's especially useful on low memory boards (512k/1m).
# ------------------------------------------------------------------------------
build_flags = -g -w -DMQTT_MAX_PACKET_SIZE=1024 -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
-DSECURE_CLIENT=SECURE_CLIENT_BEARSSL -DBEARSSL_SSL_BASIC
#build_flags for the IRremoteESP8266 library (enabled decoders have to appear here)
-D _IR_ENABLE_DEFAULT_=false
-D DECODE_HASH=true
@@ -34,231 +114,202 @@ build_flags =
-D DECODE_SONY=true
-D DECODE_SAMSUNG=true
-D DECODE_LG=true
build_flags_esp8266 = ${common.build_flags} -DESP8266
build_flags_esp32 = ${common.build_flags} -DARDUINO_ARCH_ESP32
ldscript_512k = eagle.flash.512k.ld ;for older versions change this to eagle.flash.512k0.ld
ldscript_1m0m = eagle.flash.1m.ld ;for older versions change this to eagle.flash.1m0.ld
ldscript_2m1m = eagle.flash.2m1m.ld
ldscript_4m1m = eagle.flash.4m1m.ld
ldscript_4m3m = eagle.flash.4m3m.ld
shared_libdeps_dir = ./wled00/src
# TODO replace libs in /lib with managed libs in here if possible.
# If they are not changed it's just a matter of setting the correct version and change the import statement
lib_deps_external =
#Blynk@0.5.4(changed)
#E131@1.0.0(changed)
FastLED@3.3.2
NeoPixelBus@2.5.6
ESPAsyncTCP@1.2.0
ESPAsyncUDP@697c75a025
AsyncTCP@1.0.3
Esp Async WebServer@1.2.0
#ArduinoJson@5.13.5
#IRremoteESP8266@2.7.2
https://github.com/crankyoldgit/IRremoteESP8266.git
#Time@1.5
#Timezone@1.2.1
#For use SSD1306 OLED display uncomment following
#U8g2@~2.27.2
#For Dallas sensor uncomment following 2 lines
#DallasTemperature@~3.8.0
#OneWire@~2.3.5
[common:esp8266]
# ------------------------------------------------------------------------------
# PLATFORM:
# !! DO NOT confuse platformio's ESP8266 development platform with Arduino core for ESP8266
# We use Arduino Core 2.5.0 (platformIO 2.0.4) as default
# COMMON SETTINGS:
# ------------------------------------------------------------------------------
[env]
framework = arduino
board_build.flash_mode = dout
monitor_speed = 115200
upload_speed = 115200
lib_extra_dirs =
${common.shared_libdeps_dir}
# ------------------------------------------------------------------------------
# LIBRARIES: required dependencies
# Please note that we don't always use the latest version of a library.
#
# arduino core 2.3.0 = platformIO 1.5.0
# arduino core 2.4.0 = platformIO 1.6.0
# arduino core 2.4.1 = platformIO 1.7.3
# arduino core 2.4.2 = platformIO 1.8.0
# arduino core 2.5.0 = platformIO 2.0.4
# arduino core stage = platformIO feature#stage
# 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
# ------------------------------------------------------------------------------
arduino_core_2_3_0 = espressif8266@1.5.0
arduino_core_2_4_0 = espressif8266@1.6.0
arduino_core_2_4_1 = espressif8266@1.7.3
arduino_core_2_4_2 = espressif8266@1.8.0
arduino_core_2_5_0 = espressif8266@2.0.4
arduino_core_2_5_2 = espressif8266@2.2.3
arduino_core_2_6_1 = espressif8266@2.3.0
arduino_core_2_6_2 = espressif8266@2.3.1
arduino_core_2_6_3 = espressif8266@2.3.3
arduino_core_stage = https://github.com/platformio/platform-espressif8266.git#feature/stage
platform = ${common:esp8266.arduino_core_2_6_3}
build_flags =
-D ESP8266
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
-Wl,-Teagle.flash.4m1m.ld ;;;; Required for core > v2.5.0 or staging version 4MB Flash 3MB SPIFFs
lib_ignore = AsyncTCP
lib_compat_mode = strict
lib_deps =
FastLED@3.3.2
NeoPixelBus@2.5.7
ESPAsyncTCP@1.2.0
ESPAsyncUDP@697c75a025
AsyncTCP@1.0.3
Esp Async WebServer@1.2.0
IRremoteESP8266@2.7.3
#For use SSD1306 OLED display uncomment following
#U8g2@~2.27.2
#For Dallas sensor uncomment following 2 lines
#OneWire@~2.3.5
#For BME280 sensor uncomment following
#BME280@~3.0.0
lib_ignore =
AsyncTCP
[common:esp8266_1M]
platform = espressif8266@1.8.0
build_flags =
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
-Wl,-Teagle.flash.1m0.ld ;;;; Compile with no SPIFFS to leave space for OTA
; -D WLED_DISABLE_MOBILE_UI
; -D WLED_DISABLE_OTA
; -D WLED_DISABLE_ALEXA
-D WLED_DISABLE_BLYNK
-D WLED_DISABLE_CRONIXIE
; -D WLED_DISABLE_HUESYNC
; -D WLED_DISABLE_INFRARED
lib_ignore = ${common:esp8266.lib_ignore}
# ------------------------------------------------------------------------------
# WLED BUILDS
# ------------------------------------------------------------------------------
[common:esp8266_512k]
platform = espressif8266@1.8.0
build_flags =
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
-Wl,-Teagle.flash.512k0.ld ;;;; Compile with no SPIFFS
; -D WLED_DISABLE_MOBILE_UI
-D WLED_DISABLE_OTA
; -D WLED_DISABLE_ALEXA
-D WLED_DISABLE_BLYNK
-D WLED_DISABLE_CRONIXIE
-D WLED_DISABLE_HUESYNC
; -D WLED_DISABLE_INFRARED
lib_ignore = ${common:esp8266.lib_ignore}
[common:esp32]
platform = espressif32@1.11.2
build_flags =
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
-D ARDUINO_ARCH_ESP32
lib_ignore =
ESPAsyncTCP
ESPAsyncUDP
# see: http://docs.platformio.org/en/latest/platforms/espressif8266.html
[env:nodemcuv2]
board = nodemcuv2
platform = ${common:esp8266.platform}
monitor_speed = ${common.monitor_speed}
upload_speed = ${common.upload_speed}
framework = ${common.framework}
build_flags =
${common.build_flags}
${common:esp8266.build_flags}
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = ${common:esp8266.lib_ignore}
[env:d1_mini]
board = d1_mini
platform = ${common:esp8266.platform}
monitor_speed = ${common.monitor_speed}
upload_speed = ${common.upload_speed}
framework = ${common.framework}
build_flags =
${common.build_flags}
${common:esp8266.build_flags}
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = ${common:esp8266.lib_ignore}
[env:esp01_1m]
board = esp01_1m
platform = ${common:esp8266_1M.platform}
monitor_speed = ${common.monitor_speed}
upload_speed = ${common.upload_speed}
framework = ${common.framework}
build_flags =
${common.build_flags}
${common:esp8266_1M.build_flags}
# disable IR because there is no pin for it
-D WLED_DISABLE_INFRARED
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = ${common:esp8266.lib_ignore}
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_4m1m}
build_flags = ${common.build_flags_esp8266}
[env:esp01]
board = esp01
platform = ${common:esp8266_512k.platform}
monitor_speed = ${common.monitor_speed}
upload_speed = ${common.upload_speed}
framework = ${common.framework}
build_flags =
${common.build_flags}
${common:esp8266_512k.build_flags}
-D WLED_DISABLE_INFRARED
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = ${common:esp8266.lib_ignore}
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_512k}
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA -D WLED_DISABLE_ALEXA -D WLED_DISABLE_BLYNK
-D WLED_DISABLE_CRONIXIE -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_INFRARED
[env:esp01_1m_ota]
board = esp01_1m
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_1m0m}
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_ALEXA -D WLED_DISABLE_BLYNK -D WLED_DISABLE_CRONIXIE -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_INFRARED
[env:esp01_1m_full]
board = esp01_1m
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_1m0m}
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA
[env:esp07]
board = esp07
platform = ${common:esp8266.platform}
monitor_speed = ${common.monitor_speed}
upload_speed = ${common.upload_speed}
framework = ${common.framework}
build_flags =
${common.build_flags}
${common:esp8266.build_flags}
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = ${common:esp8266.lib_ignore}
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_4m1m}
build_flags = ${common.build_flags_esp8266}
[env:d1_mini]
board = d1_mini
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_4m1m}
build_flags = ${common.build_flags_esp8266}
[env:heltec_wifi_kit_8]
board = d1_mini
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_4m1m}
build_flags = ${common.build_flags_esp8266}
[env:h803wf]
board = d1_mini
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_4m1m}
build_flags = ${common.build_flags_esp8266} -D LEDPIN=1 -D WLED_DISABLE_INFRARED
# see: http://docs.platformio.org/en/latest/platforms/espressif32.html
[env:esp32dev]
board = esp32dev
platform = ${common:esp32.platform}
monitor_speed = ${common.monitor_speed}
upload_speed = ${common.upload_speed_fast}
framework = ${common.framework}
build_flags =
${common.build_flags}
${common:esp32.build_flags}
lib_deps =
${common.lib_deps_external}
lib_ignore = ${common:esp32.lib_ignore}
lib_compat_mode = strict
platform = espressif32@1.11.2
build_flags = ${common.build_flags_esp32}
lib_ignore =
ESPAsyncTCP
ESPAsyncUDP
[env:esp8285_4CH_MagicHome]
board = esp8285
platform = ${common:esp8266_1M.platform}
monitor_speed = ${common.monitor_speed}
upload_speed = ${common.upload_speed}
framework = ${common.framework}
build_flags =
${common.build_flags}
${common:esp8266_1M.build_flags}
-D WLED_DISABLE_HUESYNC
-D WLED_USE_ANALOG_LEDS
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = ${common:esp8266.lib_ignore}
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_1m0m}
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_HUESYNC -D WLED_USE_ANALOG_LEDS
[env:esp8285_4CH_H801]
board = esp8285
platform = ${common:esp8266_1M.platform}
monitor_speed = ${common.monitor_speed}
upload_speed = ${common.upload_speed}
framework = ${common.framework}
build_flags =
${common.build_flags}
${common:esp8266_1M.build_flags}
-D WLED_DISABLE_HUESYNC
-D WLED_USE_ANALOG_LEDS
-D WLED_USE_H801
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = ${common:esp8266.lib_ignore}
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_1m0m}
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_HUESYNC -D WLED_USE_ANALOG_LEDS -D WLED_USE_H801
[env:esp8285_5CH_H801]
board = esp8285
platform = ${common:esp8266_1M.platform}
monitor_speed = ${common.monitor_speed}
upload_speed = ${common.upload_speed}
framework = ${common.framework}
build_flags =
${common.build_flags}
${common:esp8266_1M.build_flags}
-D WLED_DISABLE_HUESYNC
-D WLED_USE_ANALOG_LEDS
-D WLED_USE_H801
-D WLED_ENABLE_5CH_LEDS
lib_deps =
${common.lib_deps_external}
lib_compat_mode = strict
lib_ignore = ${common:esp8266.lib_ignore}
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_1m0m}
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_HUESYNC -D WLED_USE_ANALOG_LEDS -D WLED_USE_H801 -D WLED_ENABLE_5CH_LEDS
[env:d1_mini_5CH_Shojo_PCB]
board = d1_mini
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_4m1m}
build_flags = ${common.build_flags_esp8266} -D WLED_USE_ANALOG_LEDS -D SHOJO_PCB -D WLED_ENABLE_5CH_LEDS
# ------------------------------------------------------------------------------
# DEVELOPMENT BOARDS
# ------------------------------------------------------------------------------
[env:d1_mini_debug]
board = d1_mini
build_type = debug
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_4m1m}
build_flags = ${common.build_flags_esp8266} ${common.debug_flags}
[env:d1_mini_ota]
board = d1_mini
upload_protocol = espota
# exchange for your WLED IP
upload_port = "10.10.1.27"
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_4m1m}
build_flags = ${common.build_flags_esp8266}
# ------------------------------------------------------------------------------
# custom board configurations
# ------------------------------------------------------------------------------
[env:custom_LEDPIN_4]
board = d1_mini
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_4m1m}
build_flags = ${common.build_flags_esp8266} -D LEDPIN=4 -D IRPIN=5
[env:custom_LEDPIN_16]
board = d1_mini
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_4m1m}
build_flags = ${common.build_flags_esp8266} -D LEDPIN=16
[env:custom_APA102]
board = d1_mini
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_4m1m}
build_flags = ${common.build_flags_esp8266} -D USE_APA102
[env:custom_WS2801]
board = d1_mini
platform = ${common.platform_latest}
board_build.ldscript = ${common.ldscript_4m1m}
build_flags = ${common.build_flags_esp8266} -D USE_WS2801
[env:custom32_LEDPIN_16]
board = esp32dev
platform = espressif32@1.11.2
build_flags = ${common.build_flags_esp32} -D LEDPIN=16
lib_ignore =
ESPAsyncTCP
ESPAsyncUDP
[env:wemos_shield_esp32]
board = esp32dev
platform = espressif32@1.11.2
upload_port = /dev/cu.SLAB_USBtoUART
monitor_port = /dev/cu.SLAB_USBtoUART
upload_speed = 460800
build_flags = ${common.build_flags_esp32} -D LEDPIN=16 -D RLYPIN=19 -D BTNPIN=17
lib_ignore =
ESPAsyncTCP
ESPAsyncUDP

View File

@@ -0,0 +1,36 @@
# Example PlatformIO Project Configuration Override
# ------------------------------------------------------------------------------
# Copy to platformio_override.ini to activate overrides
# ------------------------------------------------------------------------------
# Please visit documentation: https://docs.platformio.org/page/projectconf.html
[env:esp8266_1m_custom]
board = esp01_1m
platform = ${common.arduino_core_2_4_2}
board_build.ldscript = ${common.ldscript_1m0m}
build_flags = ${common.build_flags_esp8266}
-D WLED_DISABLE_OTA
-D WLED_DISABLE_ALEXA
-D WLED_DISABLE_BLYNK
-D WLED_DISABLE_CRONIXIE
-D WLED_DISABLE_HUESYNC
-D WLED_DISABLE_INFRARED
; PIN defines - uncomment and change, if needed:
; -D LEDPIN=2
; -D BTNPIN=0
; -D IR_PIN=4
; -D RLYPIN=12
; -D RLYMDE=1
; digital LED strip types - uncomment only one ! - this will disable WS281x / SK681x support
; -D USE_APA102
; -D USE_WS2801
; -D USE_LPD8806
; to drive analog LED strips (aka 5050), uncomment the following
; PWM pins 5,12,13,15 are used with Magic Home LED Controller (default)
; -D WLED_USE_ANALOG_LEDS
; for the H801 controller (PINs 15,13,12,14 (W2 = 04)) uncomment this
; -D WLED_USE_H801
; for the BW-LT11 controller (PINs 12,4,14,5 ) uncomment this
; -D WLED_USE_BWLT11
; and to enable channel 5 for RGBW-CT led strips this
; -D WLED_USE_5CH_LEDS

View File

@@ -11,8 +11,8 @@
A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812, APA102) LEDs!
### Features:
- WS2812FX library integrated for almost 100 special effects
- FastLED noise effects and palettes
- WS2812FX library integrated for over 100 special effects
- FastLED noise effects and 50 palettes
- Modern UI with color, effect and segment controls
- Segments to set different effects and colors to parts of the LEDs
- Settings page - configuration over network
@@ -50,6 +50,10 @@ DrZzs has made some excellent video guides:
If you'd rather read, here is a very [detailed step-by-step beginner tutorial](https://tynick.com/blog/11-03-2019/getting-started-with-wled-on-esp8266/) by tynick!
Russian speakers, check out the videos by Room31:
[WLED Firmware Overview: Interface and Settings](https://youtu.be/h7lKsczEI7E)
[ESP8266 based LED controller for WS2812b strip. WLED Firmware + OpenHAB](https://youtu.be/K4ioTt3XvGc)
### Other
Licensed under the MIT license

View File

@@ -1,30 +1,40 @@
# Almost universal controller board for outdoor applications
This usermod is using ideas from @mrVanboy and @400killer
Installation of file: Copy and replace file in wled00 directory.
For BME280 sensor use usermod_bme280.cpp. Copy to wled00 and rename to usermod.cpp
## Project repository
- [Original repository](https://github.com/srg74/Controller-for-WLED-firmware) - Main controller repository
## Features
* SSD1306 128x32 and 128x64 I2C OLED display
* On screen IP address, SSID and controller status (e.g. ON or OFF, recent effect)
* Auto display shutoff for saving display lifetime
* Dallas temperature sensor
* Reporting temperature to MQTT broker
- SSD1306 128x32 and 128x64 I2C OLED display
- On screen IP address, SSID and controller status (e.g. ON or OFF, recent effect)
- Auto display shutoff for saving display lifetime
- Dallas temperature sensor
- Reporting temperature to MQTT broker
## Hardware
![Hardware connection](assets/controller.jpg)
## Functionality checked with
* ESP-07S
* PlatformIO
* SSD1306 128x32 I2C OLED display
* DS18B20 (temperature sensor)
* KY-022 (infrared receiver)
* Push button (N.O. momentary switch)
- ESP-07S
- PlatformIO
- SSD1306 128x32 I2C OLED display
- DS18B20 (temperature sensor)
- BME280 (temperature, humidity and pressure sensor)
- KY-022 (infrared receiver)
- Push button (N.O. momentary switch)
### Platformio requirements
Uncomment `U8g2@~2.27.3`,`DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
For Dallas sensor uncomment `U8g2@~2.27.3`,`DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
```ini
# platformio.ini
...
[platformio]
...
default_envs = esp07
; default_envs = d1_mini
...
[common]
...
lib_deps_external =
@@ -36,3 +46,23 @@ lib_deps_external =
OneWire@~2.3.5
...
```
For BME280 sensor uncomment `U8g2@~2.27.3`,`BME280@~3.0.0 under` `[common]` section in `platformio.ini`:
```ini
# platformio.ini
...
[platformio]
...
default_envs = esp07
; default_envs = d1_mini
...
[common]
...
lib_deps_external =
...
#For use SSD1306 OLED display uncomment following
U8g2@~2.27.3
#For BME280 sensor uncomment following
BME280@~3.0.0
...
```

View File

@@ -1,3 +1,5 @@
#include "wled.h"
#include <Arduino.h>
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
#include <DallasTemperature.h> //Dallastemperature sensor
//The SCL and SDA pins are defined here.

View File

@@ -0,0 +1,266 @@
#include "wled.h"
#include <Arduino.h>
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
#include <Wire.h>
#include <BME280I2C.h> //BME280 sensor
void UpdateBME280Data();
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
BME280I2C bme; // Default : forced mode, standby time = 1000 ms
// Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off,
#ifdef ARDUINO_ARCH_ESP32 //ESP32 boards
uint8_t SCL_PIN = 22;
uint8_t SDA_PIN = 21;
#else //ESP8266 boards
uint8_t SCL_PIN = 5;
uint8_t SDA_PIN = 4;
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
#endif
//The SCL and SDA pins are defined here.
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
#define U8X8_PIN_SCL SCL_PIN
#define U8X8_PIN_SDA SDA_PIN
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
// If display does not work or looks corrupted check the
// constructor reference:
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
// or check the gallery:
// https://github.com/olikraus/u8g2/wiki/gallery
// --> First choise of cheap I2C OLED 128X32 0.91"
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
// gets called once at boot. Do all initialization that doesn't depend on network here
// BME280 sensor timer
long tempTimer = millis();
long lastMeasure = 0;
float SensorPressure(NAN);
float SensorTemperature(NAN);
float SensorHumidity(NAN);
void userSetup() {
u8x8.begin();
u8x8.setPowerSave(0);
u8x8.setFlipMode(1);
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.drawString(0, 0, "Loading...");
Wire.begin(SDA_PIN,SCL_PIN);
while(!bme.begin())
{
Serial.println("Could not find BME280I2C sensor!");
delay(1000);
}
switch(bme.chipModel())
{
case BME280::ChipModel_BME280:
Serial.println("Found BME280 sensor! Success.");
break;
case BME280::ChipModel_BMP280:
Serial.println("Found BMP280 sensor! No Humidity available.");
break;
default:
Serial.println("Found UNKNOWN sensor! Error!");
}
}
// gets called every time WiFi is (re-)connected. Initialize own network
// interfaces here
void userConnected() {}
// needRedraw marks if redraw is required to prevent often redrawing.
bool needRedraw = true;
// Next variables hold the previous known values to determine if redraw is
// required.
String knownSsid = "";
IPAddress knownIp;
uint8_t knownBrightness = 0;
uint8_t knownMode = 0;
uint8_t knownPalette = 0;
long lastUpdate = 0;
long lastRedraw = 0;
bool displayTurnedOff = false;
// How often we are redrawing screen
#define USER_LOOP_REFRESH_RATE_MS 5000
void userLoop() {
// BME280 sensor MQTT publishing
tempTimer = millis();
// Timer to publish new sensor data every 60 seconds
if (tempTimer - lastMeasure > 60000)
{
lastMeasure = tempTimer;
// Check if MQTT Connected, otherwise it will crash the 8266
if (mqtt != nullptr)
{
UpdateBME280Data();
float board_temperature = SensorTemperature;
float board_pressure = SensorPressure;
float board_humidity = SensorHumidity;
// Create string populated with user defined device topic from the UI, and the read temperature, humidity and pressure. Then publish to MQTT server.
String t = String(mqttDeviceTopic);
t += "/temperature";
mqtt->publish(t.c_str(), 0, true, String(board_temperature).c_str());
String p = String(mqttDeviceTopic);
p += "/pressure";
mqtt->publish(p.c_str(), 0, true, String(board_pressure).c_str());
String h = String(mqttDeviceTopic);
h += "/humidity";
mqtt->publish(h.c_str(), 0, true, String(board_humidity).c_str());
}
}
// Check if we time interval for redrawing passes.
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
return;
}
lastUpdate = millis();
// Turn off display after 3 minutes with no change.
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
u8x8.setPowerSave(1);
displayTurnedOff = true;
}
// Check if values which are shown on display changed from the last time.
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
needRedraw = true;
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
needRedraw = true;
} else if (knownBrightness != bri) {
needRedraw = true;
} else if (knownMode != strip.getMode()) {
needRedraw = true;
} else if (knownPalette != strip.getSegment(0).palette) {
needRedraw = true;
}
if (!needRedraw) {
return;
}
needRedraw = false;
if (displayTurnedOff)
{
u8x8.setPowerSave(0);
displayTurnedOff = false;
}
lastRedraw = millis();
// Update last known values.
#if defined(ESP8266)
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
#else
knownSsid = WiFi.SSID();
#endif
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
knownBrightness = bri;
knownMode = strip.getMode();
knownPalette = strip.getSegment(0).palette;
u8x8.clear();
u8x8.setFont(u8x8_font_chroma48medium8_r);
// First row with Wifi name
u8x8.setCursor(1, 0);
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
// Print `~` char to indicate that SSID is longer, than owr dicplay
if (knownSsid.length() > u8x8.getCols())
u8x8.print("~");
// Second row with IP or Psssword
u8x8.setCursor(1, 1);
// Print password in AP mode and if led is OFF.
if (apActive && bri == 0)
u8x8.print(apPass);
else
u8x8.print(knownIp);
// Third row with mode name
u8x8.setCursor(2, 2);
uint8_t qComma = 0;
bool insideQuotes = false;
uint8_t printedChars = 0;
char singleJsonSymbol;
// Find the mode name in JSON
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
switch (singleJsonSymbol) {
case '"':
insideQuotes = !insideQuotes;
break;
case '[':
case ']':
break;
case ',':
qComma++;
default:
if (!insideQuotes || (qComma != knownMode))
break;
u8x8.print(singleJsonSymbol);
printedChars++;
}
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
break;
}
// Fourth row with palette name
u8x8.setCursor(2, 3);
qComma = 0;
insideQuotes = false;
printedChars = 0;
// Looking for palette name in JSON.
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
switch (singleJsonSymbol) {
case '"':
insideQuotes = !insideQuotes;
break;
case '[':
case ']':
break;
case ',':
qComma++;
default:
if (!insideQuotes || (qComma != knownPalette))
break;
u8x8.print(singleJsonSymbol);
printedChars++;
}
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
break;
}
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
u8x8.drawGlyph(0, 0, 80); // wifi icon
u8x8.drawGlyph(0, 1, 68); // home icon
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
}
void UpdateBME280Data() {
float temp(NAN), hum(NAN), pres(NAN);
#ifdef Celsius
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
#else
BME280::TempUnit tempUnit(BME280::TempUnit_Fahrenheit);
#endif
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
bme.read(pres, temp, hum, tempUnit, presUnit);
SensorTemperature=temp;
SensorHumidity=hum;
SensorPressure=pres;
}

View File

@@ -1,8 +1,34 @@
These files allow WLED 0.8.6 to report the temp sensor on the Quinled board to MQTT. I use it to report the board temp to Home Assistant via MQTT, so it will send notifications if something happens and the board start to heat up.
# QuinLED Dig Uno board
These files allow WLED 0.9.1 to report the temp sensor on the Quinled board to MQTT. I use it to report the board temp to Home Assistant via MQTT, so it will send notifications if something happens and the board start to heat up.
This code uses Aircookie's WLED software. It has a premade file for user modifications. I use it to publish the temperature from the dallas temperature sensor on the Quinled board. The entries for the top of the WLED00 file, initializes the required libraries, and variables for the sensor. The .ino file waits for 60 seconds, and checks to see if the MQTT server is connected (thanks Aircoookie). It then poles the sensor, and published it using the MQTT service already running, using the main topic programmed in the WLED UI.
To install:
Installation of file: Copy and replace file in wled00 directory
Add the entries in the WLED00 file to the top of the same file from Aircoookies WLED.
Replace the WLED06_usermod.ino file in Aircoookies WLED folder.
## Project link
* [QuinLED-Dig-Uno](https://quinled.info/2018/09/15/quinled-dig-uno/) - Project link
### Platformio requirements
Uncomment `DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
```ini
# platformio.ini
...
[platformio]
...
; default_envs = esp07
default_envs = d1_mini
...
[common]
...
lib_deps_external =
...
#For use SSD1306 OLED display uncomment following
U8g2@~2.27.3
#For Dallas sensor uncomment following 2 lines
DallasTemperature@~3.8.0
OneWire@~2.3.5
...
```

View File

@@ -1,8 +1,21 @@
//starts Dallas Temp service on boot
#include <Arduino.h>
#include "wled.h"
//Intiating code for QuinLED Dig-Uno temp sensor
//Uncomment Celsius if that is your prefered temperature scale
#include <DallasTemperature.h> //Dallastemperature sensor
#ifdef ARDUINO_ARCH_ESP32 //ESP32 boards
OneWire oneWire(18);
#else //ESP8266 boards
OneWire oneWire(14);
#endif
DallasTemperature sensor(&oneWire);
long temptimer = millis();
long lastMeasure = 0;
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
void userSetup()
{
// Start the DS18B20 sensor
sensors.begin();
sensor.begin();
}
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
@@ -21,11 +34,11 @@ void userLoop()
//Check if MQTT Connected, otherwise it will crash the 8266
if (mqtt != nullptr){
sensors.requestTemperatures();
sensor.requestTemperatures();
//Gets prefered temperature scale based on selection in definitions section
#ifdef Celsius
float board_temperature = sensors.getTempCByIndex(0);
float board_temperature = sensor.getTempCByIndex(0);
#else
float board_temperature = sensors.getTempFByIndex(0);
#endif

View File

@@ -1,8 +0,0 @@
//Intiating code for QuinLED Dig-Uno temp sensor
//Uncomment Celsius if that is your prefered temperature scale
#include <DallasTemperature.h>
OneWire oneWire(14);
DallasTemperature sensors(&oneWire);
long temptimer = millis();
long lastMeasure = 0;
//#define Celsius

View File

@@ -1,4 +1,7 @@
# Wemos D1 mini and Wemos32 mini shield
- Installation of file: Copy and replace file in wled00 directory
- For BME280 sensor use usermod_bme280.cpp. Copy to wled00 and rename to usermod.cpp
- Added third choice of controller Heltec WiFi-Kit-8. Totally DIY but with OLED display.
## Project repository
- [Original repository](https://github.com/srg74/WLED-wemos-shield) - WLED Wemos shield repository
- [Wemos shield project Wiki](https://github.com/srg74/WLED-wemos-shield/wiki)
@@ -15,9 +18,54 @@
![Shield](https://github.com/srg74/WLED-wemos-shield/blob/master/resources/Images/Assembly_8.jpg)
## Functionality checked with
- Wemos D1 mini original v3.1 and clones
- Wemos32 mini
- PlatformIO
- SSD1306 128x32 I2C OLED display
- DS18B20 (temperature sensor)
- BME280 (temperature, humidity and pressure sensor)
- Push button (N.O. momentary switch)
### Platformio requirements
For Dallas sensor uncomment `U8g2@~2.27.3`,`DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
```ini
# platformio.ini
...
[platformio]
...
; default_envs = esp07
default_envs = d1_mini
...
[common]
...
lib_deps_external =
...
#For use SSD1306 OLED display uncomment following
U8g2@~2.27.3
#For Dallas sensor uncomment following 2 lines
DallasTemperature@~3.8.0
OneWire@~2.3.5
...
```
For BME280 sensor uncomment `U8g2@~2.27.3`,`BME280@~3.0.0 under` `[common]` section in `platformio.ini`:
```ini
# platformio.ini
...
[platformio]
...
; default_envs = esp07
default_envs = d1_mini
...
[common]
...
lib_deps_external =
...
#For use SSD1306 OLED display uncomment following
U8g2@~2.27.3
#For BME280 sensor uncomment following
BME280@~3.0.0
...
```

View File

@@ -1,21 +1,49 @@
#include "wled.h"
#include <Arduino.h>
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
#include <DallasTemperature.h> //Dallastemperature sensor
#ifdef ARDUINO_ARCH_ESP32 //ESP32 boards
#include <OneWire.h> // Dallas temperature sensor
//Dallas sensor quick reading. Credit to - Author: Peter Scargill, August 17th, 2013
int16_t Dallas(int x, byte start)
{
OneWire DallasSensor(x);
byte i;
byte data[2];
int16_t result;
do
{
DallasSensor.reset();
DallasSensor.write(0xCC);
DallasSensor.write(0xBE);
for ( i = 0; i < 2; i++) data[i] = DallasSensor.read();
result=(data[1]<<8)|data[0];
result>>=4; if (data[1]&128) result|=61440;
if (data[0]&8) ++result;
DallasSensor.reset();
DallasSensor.write(0xCC);
DallasSensor.write(0x44,1);
if (start) delay(1000);
} while (start--);
return result;
}
#ifdef ARDUINO_ARCH_ESP32
uint8_t SCL_PIN = 22;
uint8_t SDA_PIN = 21;
OneWire oneWire(23);
#else //ESP8266 boards
uint8_t SDA_PIN = 21;
uint8_t DALLAS_PIN =23;
#else
uint8_t SCL_PIN = 5;
uint8_t SDA_PIN = 4;
OneWire oneWire(13);
uint8_t DALLAS_PIN =13;
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
#endif
//The SCL and SDA pins are defined here.
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
#define U8X8_PIN_SCL SCL_PIN
#define U8X8_PIN_SDA SDA_PIN
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
// Dallas sensor
DallasTemperature sensor(&oneWire);
// Dallas sensor reading timer
long temptimer = millis();
long lastMeasure = 0;
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
@@ -29,10 +57,13 @@ long lastMeasure = 0;
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
// gets called once at boot. Do all initialization that doesn't depend on
// network here
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
// gets called once at boot. Do all initialization that doesn't depend on network here
void userSetup() {
sensor.begin(); //Start Dallas temperature sensor
//Serial.begin(115200);
Dallas (DALLAS_PIN,1);
u8x8.begin();
u8x8.setPowerSave(0);
u8x8.setFlipMode(1);
@@ -73,18 +104,17 @@ void userLoop() {
//Check if MQTT Connected, otherwise it will crash the 8266
if (mqtt != nullptr)
{
sensor.requestTemperatures();
// Serial.println(Dallas(DALLAS_PIN,0));
//Gets prefered temperature scale based on selection in definitions section
#ifdef Celsius
float board_temperature = sensor.getTempCByIndex(0);
#else
float board_temperature = sensor.getTempFByIndex(0);
#endif
#ifdef Celsius
int16_t board_temperature = Dallas(DALLAS_PIN,0);
#else
int16_t board_temperature = (Dallas(DALLAS_PIN,0)* 1.8 + 32);
#endif
//Create character string populated with user defined device topic from the UI, and the read temperature. Then publish to MQTT server.
char subuf[38];
strcpy(subuf, mqttDeviceTopic);
strcat(subuf, "/temperature");
mqtt->publish(subuf, 0, true, String(board_temperature).c_str());
String t = String(mqttDeviceTopic);
t += "/temperature";
mqtt->publish(t.c_str(), 0, true, String(board_temperature).c_str());
}
}
@@ -126,10 +156,10 @@ void userLoop() {
lastRedraw = millis();
// Update last known values.
#if defined(ESP8266)
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
#else
#ifdef ARDUINO_ARCH_ESP32
knownSsid = WiFi.SSID();
#else
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
#endif
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
knownBrightness = bri;

View File

@@ -0,0 +1,268 @@
#include "wled.h"
#include <Arduino.h>
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
#include <Wire.h>
#include <BME280I2C.h> //BME280 sensor
void UpdateBME280Data();
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
BME280I2C bme; // Default : forced mode, standby time = 1000 ms
// Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off,
#ifdef ARDUINO_ARCH_ESP32 //ESP32 boards
uint8_t SCL_PIN = 22;
uint8_t SDA_PIN = 21;
#else //ESP8266 boards
uint8_t SCL_PIN = 5;
uint8_t SDA_PIN = 4;
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
#endif
//The SCL and SDA pins are defined here.
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
#define U8X8_PIN_SCL SCL_PIN
#define U8X8_PIN_SDA SDA_PIN
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
// If display does not work or looks corrupted check the
// constructor reference:
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
// or check the gallery:
// https://github.com/olikraus/u8g2/wiki/gallery
// --> First choise of cheap I2C OLED 128X32 0.91"
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
// gets called once at boot. Do all initialization that doesn't depend on network here
// BME280 sensor timer
long tempTimer = millis();
long lastMeasure = 0;
float SensorPressure(NAN);
float SensorTemperature(NAN);
float SensorHumidity(NAN);
void userSetup() {
u8x8.begin();
u8x8.setPowerSave(0);
u8x8.setFlipMode(1);
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.drawString(0, 0, "Loading...");
Wire.begin(SDA_PIN,SCL_PIN);
while(!bme.begin())
{
Serial.println("Could not find BME280I2C sensor!");
delay(1000);
}
switch(bme.chipModel())
{
case BME280::ChipModel_BME280:
Serial.println("Found BME280 sensor! Success.");
break;
case BME280::ChipModel_BMP280:
Serial.println("Found BMP280 sensor! No Humidity available.");
break;
default:
Serial.println("Found UNKNOWN sensor! Error!");
}
}
// gets called every time WiFi is (re-)connected. Initialize own network
// interfaces here
void userConnected() {}
// needRedraw marks if redraw is required to prevent often redrawing.
bool needRedraw = true;
// Next variables hold the previous known values to determine if redraw is
// required.
String knownSsid = "";
IPAddress knownIp;
uint8_t knownBrightness = 0;
uint8_t knownMode = 0;
uint8_t knownPalette = 0;
long lastUpdate = 0;
long lastRedraw = 0;
bool displayTurnedOff = false;
// How often we are redrawing screen
#define USER_LOOP_REFRESH_RATE_MS 5000
void userLoop() {
// BME280 sensor MQTT publishing
tempTimer = millis();
// Timer to publish new sensor data every 60 seconds
if (tempTimer - lastMeasure > 60000)
{
lastMeasure = tempTimer;
// Check if MQTT Connected, otherwise it will crash the 8266
if (mqtt != nullptr)
{
UpdateBME280Data();
float board_temperature = SensorTemperature;
float board_pressure = SensorPressure;
float board_humidity = SensorHumidity;
// Create string populated with user defined device topic from the UI, and the read temperature, humidity and pressure. Then publish to MQTT server.
String t = String(mqttDeviceTopic);
t += "/temperature";
mqtt->publish(t.c_str(), 0, true, String(board_temperature).c_str());
String p = String(mqttDeviceTopic);
p += "/pressure";
mqtt->publish(p.c_str(), 0, true, String(board_pressure).c_str());
String h = String(mqttDeviceTopic);
h += "/humidity";
mqtt->publish(h.c_str(), 0, true, String(board_humidity).c_str());
}
}
// Check if we time interval for redrawing passes.
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
return;
}
lastUpdate = millis();
// Turn off display after 3 minutes with no change.
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
u8x8.setPowerSave(1);
displayTurnedOff = true;
}
// Check if values which are shown on display changed from the last time.
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
needRedraw = true;
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
needRedraw = true;
} else if (knownBrightness != bri) {
needRedraw = true;
} else if (knownMode != strip.getMode()) {
needRedraw = true;
} else if (knownPalette != strip.getSegment(0).palette) {
needRedraw = true;
}
if (!needRedraw) {
return;
}
needRedraw = false;
if (displayTurnedOff)
{
u8x8.setPowerSave(0);
displayTurnedOff = false;
}
lastRedraw = millis();
// Update last known values.
#if defined(ESP8266)
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
#else
knownSsid = WiFi.SSID();
#endif
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
knownBrightness = bri;
knownMode = strip.getMode();
knownPalette = strip.getSegment(0).palette;
u8x8.clear();
u8x8.setFont(u8x8_font_chroma48medium8_r);
// First row with Wifi name
u8x8.setCursor(1, 0);
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
// Print `~` char to indicate that SSID is longer, than owr dicplay
if (knownSsid.length() > u8x8.getCols())
u8x8.print("~");
// Second row with IP or Psssword
u8x8.setCursor(1, 1);
// Print password in AP mode and if led is OFF.
if (apActive && bri == 0)
u8x8.print(apPass);
else
u8x8.print(knownIp);
// Third row with mode name
u8x8.setCursor(2, 2);
uint8_t qComma = 0;
bool insideQuotes = false;
uint8_t printedChars = 0;
char singleJsonSymbol;
// Find the mode name in JSON
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
switch (singleJsonSymbol) {
case '"':
insideQuotes = !insideQuotes;
break;
case '[':
case ']':
break;
case ',':
qComma++;
default:
if (!insideQuotes || (qComma != knownMode))
break;
u8x8.print(singleJsonSymbol);
printedChars++;
}
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
break;
}
// Fourth row with palette name
u8x8.setCursor(2, 3);
qComma = 0;
insideQuotes = false;
printedChars = 0;
// Looking for palette name in JSON.
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
switch (singleJsonSymbol) {
case '"':
insideQuotes = !insideQuotes;
break;
case '[':
case ']':
break;
case ',':
qComma++;
default:
if (!insideQuotes || (qComma != knownPalette))
break;
u8x8.print(singleJsonSymbol);
printedChars++;
}
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
break;
}
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
u8x8.drawGlyph(0, 0, 80); // wifi icon
u8x8.drawGlyph(0, 1, 68); // home icon
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
}
void UpdateBME280Data() {
float temp(NAN), hum(NAN), pres(NAN);
#ifdef Celsius
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
bme.read(pres, temp, hum, tempUnit, presUnit);
#else
BME280::TempUnit tempUnit(BME280::TempUnit_Fahrenheit);
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
bme.read(pres, temp, hum, tempUnit, presUnit);
#endif
SensorTemperature=temp;
SensorHumidity=hum;
SensorPressure=pres;
}

View File

@@ -0,0 +1,12 @@
# Battery powered controller with keypad
I'm using this controller for a festival totem. Runs on 3 18650 Cells, can deliver >5A current.
Via keypad one can select 8 presets, change effect, effect speed, effect intensity and palette. Brightness can be
adjusted with a potentiometer.
## Pictures
![bat-key-ctrl-1](assets/bat-key-ctrl-1.jpg)
![bat-key-ctrl-2](assets/bat-key-ctrl-2.jpg)
![bat-key-ctrl-3](assets/bat-key-ctrl-3.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 319 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

View File

@@ -0,0 +1,151 @@
/*
* WLED usermod for keypad and brightness-pot.
* 3'2020 https://github.com/hobbyquaker
*/
#include <Keypad.h>
const byte keypad_rows = 4;
const byte keypad_cols = 4;
char keypad_keys[keypad_rows][keypad_cols] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte keypad_colPins[keypad_rows] = {D3, D2, D1, D0};
byte keypad_rowPins[keypad_cols] = {D7, D6, D5, D4};
Keypad myKeypad = Keypad(makeKeymap(keypad_keys), keypad_rowPins, keypad_colPins, keypad_rows, keypad_cols);
void userSetup()
{
}
void userConnected()
{
}
long lastTime = 0;
int delayMs = 20; //we want to do something every 2 seconds
void userLoop()
{
if (millis()-lastTime > delayMs)
{
long analog = analogRead(0);
int new_bri = 1;
if (analog > 900) {
new_bri = 255;
} else if (analog > 30) {
new_bri = dim8_video(map(analog, 31, 900, 16, 255));
}
if (bri != new_bri) {
bri = new_bri;
colorUpdated(1);
}
char myKey = myKeypad.getKey();
if (myKey != NULL) {
switch (myKey) {
case '1':
applyPreset(1);
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case '2':
applyPreset(2);
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case '3':
applyPreset(3);
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case '4':
applyPreset(4);
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case '5':
applyPreset(5);
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case '6':
applyPreset(6);
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case 'A':
applyPreset(7);
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case 'B':
applyPreset(8);
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case '7':
effectCurrent += 1;
if (effectCurrent >= MODE_COUNT) effectCurrent = 0;
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case '*':
effectCurrent -= 1;
if (effectCurrent < 0) effectCurrent = (MODE_COUNT-1);
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case '8':
if (effectSpeed < 240) {
effectSpeed += 12;
} else if (effectSpeed < 255) {
effectSpeed += 1;
}
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case '0':
if (effectSpeed > 15) {
effectSpeed -= 12;
} else if (effectSpeed > 0) {
effectSpeed -= 1;
}
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case '9':
if (effectIntensity < 240) {
effectIntensity += 12;
} else if (effectIntensity < 255) {
effectIntensity += 1;
}
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case '#':
if (effectIntensity > 15) {
effectIntensity -= 12;
} else if (effectIntensity > 0) {
effectIntensity -= 1;
}
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case 'C':
effectPalette += 1;
if (effectPalette >= 50) effectPalette = 0;
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
case 'D':
effectPalette -= 1;
if (effectPalette <= 0) effectPalette = 50;
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
break;
}
}
lastTime = millis();
}
}

View File

@@ -1,7 +1,7 @@
/*
* This file allows you to add own functionality to WLED more easily
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled01_eeprom.h)
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled_eeprom.h)
* bytes 2400+ are currently ununsed, but might be used for future wled features
*/

View File

@@ -0,0 +1,23 @@
### Shift Light for Project Cars
Turn your WLED lights into a rev light and shift indicator for Project Cars.
It is pretty straight forward to use.
1. Make sure, your WLED device and your PC/console are on the same network and can talk to each other
2. Go to the gameplay settings menu in PCARS and enable UDP. There are 9 numbers you can choose from. This is the refresh rate. The lower the number, the better. But you might run into problems at faster rates.
| Number | Updates/Second |
| ------ | -------------- |
| 1 | 60 |
| 2 | 50 |
| 3 | 40 |
| 4 | 30 |
| 5 | 20 |
| 6 | 15 |
| 7 | 10 |
| 8 | 05 |
| 9 | 1 |
3. once you enter a race, WLED should automatically shift to PCARS mode. Done.

View File

@@ -0,0 +1,96 @@
/*
* Car rev display and shift indicator for Project Cars
*
* This works via the UDP telemetry function. You'll need to enable it in the settings of the game.
* I've had good results with settings around 5 (20 fps).
*
*/
const uint8_t PCARS_dimcolor = 20;
WiFiUDP UDP;
const unsigned int PCARS_localUdpPort = 5606; // local port to listen on
char PCARS_packet[2048];
char PCARS_tempChar[2]; // Temporary array for u16 conversion
u16 PCARS_RPM;
u16 PCARS_maxRPM;
long PCARS_lastRead = millis() - 2001;
float PCARS_rpmRatio;
void userSetup()
{
UDP.begin(PCARS_localUdpPort);
}
void userConnected()
{
// new wifi, who dis?
}
void userLoop()
{
PCARS_readValues();
if (PCARS_lastRead > millis() - 2000) {
PCARS_buildcolorbars();
}
}
void PCARS_readValues() {
int PCARS_packetSize = UDP.parsePacket();
if (PCARS_packetSize) {
int len = UDP.read(PCARS_packet, PCARS_packetSize);
if (len > 0) {
PCARS_packet[len] = 0;
}
if (len == 1367) { // Telemetry packet. Ignoring everything else.
PCARS_lastRead = millis();
arlsLock(realtimeTimeoutMs, REALTIME_MODE_GENERIC);
// current RPM
memcpy(&PCARS_tempChar, &PCARS_packet[124], 2);
PCARS_RPM = (PCARS_tempChar[1] << 8) + PCARS_tempChar[0];
// max RPM
memcpy(&PCARS_tempChar, &PCARS_packet[126], 2);
PCARS_maxRPM = (PCARS_tempChar[1] << 8) + PCARS_tempChar[0];
if (PCARS_maxRPM) {
PCARS_rpmRatio = constrain((float)PCARS_RPM / (float)PCARS_maxRPM, 0, 1);
} else {
PCARS_rpmRatio = 0.0;
}
}
}
}
void PCARS_buildcolorbars() {
boolean activated = false;
float ledratio = 0;
for (uint16_t i = 0; i < ledCount; i++) {
if (PCARS_rpmRatio < .95 || (millis() % 100 > 70 )) {
ledratio = (float)i / (float)ledCount;
if (ledratio < PCARS_rpmRatio) {
activated = true;
} else {
activated = false;
}
if (ledratio > 0.66) {
setRealtimePixel(i, 0, 0, PCARS_dimcolor + ((255 - PCARS_dimcolor)*activated), 0);
} else if (ledratio > 0.33) {
setRealtimePixel(i, PCARS_dimcolor + ((255 - PCARS_dimcolor)*activated), 0, 0, 0);
} else {
setRealtimePixel(i, 0, PCARS_dimcolor + ((255 - PCARS_dimcolor)*activated), 0, 0);
}
}
else {
setRealtimePixel(i, 0, 0, 0, 0);
}
}
colorUpdated(5);
strip.show();
}

View File

@@ -1,13 +1,13 @@
### Usermods
This folder serves as a repository for usermods (custom `wled06_usermod.ino` files)!
This folder serves as a repository for usermods (custom `usermod.cpp` files)!
If you have created an usermod that you believe is useful (for example to support a particular sensor, display, feature...), feel free to contribute by opening a pull request!
In order for other people to be able to have fun with your usermod, please keep these points in mind:
- Create a folder in this folder with a descriptive name (for example `usermod_ds18b20_temp_sensor_mqtt`)
- Include your custom `wled06_usermod.ino` file
- Include your custom `usermod.cpp` file
- If your usermod requires changes to other WLED files, please write a `readme.md` outlining the steps one has to take to use the usermod
- Create a pull request!
- If your feature is useful for the majority of WLED users, I will consider adding it to the base code!

View File

@@ -0,0 +1,62 @@
#include "wled.h"
/*
* This file allows you to add own functionality to WLED more easily
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
* bytes 2400+ are currently ununsed, but might be used for future wled features
*/
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
/*
** Rotary Encoder Example
** Use the Sparkfun Rotary Encoder to vary brightness of LED
**
** Sample the encoder at 500Hz using the millis() function
*/
int fadeAmount = 5; // how many points to fade the Neopixel with each step
unsigned long currentTime;
unsigned long loopTime;
const int pinA = D6; // DT from encoder
const int pinB = D7; // CLK from encoder
unsigned char Enc_A;
unsigned char Enc_B;
unsigned char Enc_A_prev = 0;
//gets called once at boot. Do all initialization that doesn't depend on network here
void userSetup() {
pinMode(pinA, INPUT_PULLUP);
pinMode(pinB, INPUT_PULLUP);
currentTime = millis();
loopTime = currentTime;
}
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
void userConnected() {
}
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
void userLoop() {
currentTime = millis(); // get the current elapsed time
if(currentTime >= (loopTime + 2)) // 2ms since last check of encoder = 500Hz
{
int Enc_A = digitalRead(pinA); // Read encoder pins
int Enc_B = digitalRead(pinB);
if((! Enc_A) && (Enc_A_prev)) { // A has gone from high to low
if(Enc_B == HIGH) { // B is high so clockwise
if(bri + fadeAmount <= 255) bri += fadeAmount; // increase the brightness, dont go over 255
} else if (Enc_B == LOW) { // B is low so counter-clockwise
if(bri - fadeAmount >= 0) bri -= fadeAmount; // decrease the brightness, dont go below 0
}
}
Enc_A_prev = Enc_A; // Store value of A for next time
loopTime = currentTime; // Updates loopTime
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
colorUpdated(6);
}
}

View File

@@ -1,7 +1,7 @@
/*
* This file allows you to add own functionality to WLED more easily
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled01_eeprom.h)
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled_eeprom.h)
* bytes 2400+ are currently ununsed, but might be used for future wled features
*/

View File

@@ -35,7 +35,7 @@
*/
uint16_t WS2812FX::mode_static(void) {
fill(SEGCOLOR(0));
return (SEGMENT.getOption(7)) ? FRAMETIME : 500; //update faster if in transition
return (SEGMENT.getOption(SEG_OPTION_TRANSITIONAL)) ? FRAMETIME : 500; //update faster if in transition
}
@@ -379,7 +379,7 @@ uint16_t WS2812FX::mode_rainbow_cycle(void) {
/*
* theater chase function
*/
uint16_t WS2812FX::theater_chase(uint32_t color1, uint32_t color2, bool dopalette) {
uint16_t WS2812FX::theater_chase(uint32_t color1, uint32_t color2, bool do_palette) {
byte gap = 2 + ((255 - SEGMENT.intensity) >> 5);
uint32_t cycleTime = 50 + (255 - SEGMENT.speed)*2;
uint32_t it = now / cycleTime;
@@ -391,7 +391,7 @@ uint16_t WS2812FX::theater_chase(uint32_t color1, uint32_t color2, bool dopalett
for(uint16_t i = 0; i < SEGLEN; i++) {
if((i % gap) == SEGENV.aux0) {
if (dopalette)
if (do_palette)
{
setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0));
} else {
@@ -601,7 +601,7 @@ uint16_t WS2812FX::mode_hyper_sparkle(void) {
}
if(random8(5) < 2) {
for(uint16_t i = 0; i < max(1, SEGLEN/3); i++) {
for(uint16_t i = 0; i < MAX(1, SEGLEN/3); i++) {
setPixelColor(random16(SEGLEN), SEGCOLOR(1));
}
return 20;
@@ -690,58 +690,68 @@ uint16_t WS2812FX::mode_android(void) {
* color1 = background color
* color2 and color3 = colors of two adjacent leds
*/
uint16_t WS2812FX::chase(uint32_t color1, uint32_t color2, uint32_t color3, bool dopalette) {
uint16_t WS2812FX::chase(uint32_t color1, uint32_t color2, uint32_t color3, bool do_palette) {
uint16_t counter = now * ((SEGMENT.speed >> 2) + 1);
uint16_t a = counter * SEGLEN >> 16;
bool chase_random = (SEGMENT.mode == FX_MODE_CHASE_RANDOM);
if (chase_random) {
if (a < SEGENV.step) //we hit the start again, choose new color for Chase random
{
SEGENV.aux1 = SEGENV.aux0; //store previous random color
SEGENV.aux0 = get_random_wheel_index(SEGENV.aux0);
}
color1 = color_wheel(SEGENV.aux0);
}
SEGENV.step = a;
uint8_t size = 1 + (SEGMENT.intensity * SEGLEN >> 10);
if (SEGENV.call == 0) {SEGENV.aux0 = 0; SEGENV.aux1 = a;}
// Use intensity setting to vary chase up to 1/2 string length
uint16_t b = (a + size) % SEGLEN;
uint16_t c = (b + size) % SEGLEN;
uint8_t size = 1 + (SEGMENT.intensity * SEGLEN >> 10);
if (dopalette) color1 = color_from_palette(a, true, PALETTE_SOLID_WRAP, 1);
uint16_t b = a + size; //"trail" of chase, filled with color1
if (b > SEGLEN) b -= SEGLEN;
uint16_t c = b + size;
if (c > SEGLEN) c -= SEGLEN;
setPixelColor(a, color1);
if (SEGENV.aux0 == 0) { // catch the first pixels after color change from "chase random" (because they have the "old" color)
for (uint16_t i = 0; i < a; i++) {
uint32_t color = getPixelColor(0);
setPixelColor(i, color1);
//background
if (do_palette)
{
for(uint16_t i = 0; i < SEGLEN; i++) {
setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 1));
}
SEGENV.aux0 = 1;
}
setPixelColor(b, color2);
setPixelColor(c, color3);
} else fill(color1);
if (a != SEGENV.aux1) { // when speed is too fast, this catches the gaps
if (a > SEGENV.aux1) {
for (uint16_t i = SEGENV.aux1; i <= a; i++) { // sometimes the step-length varies from one to the next call - therefor "<= a" and not "< a"
setPixelColor(i, color1);
uint16_t b1 = (i + size) % SEGLEN;
uint16_t c1 = (b1 + size) % SEGLEN;
setPixelColor(b1, color2);
setPixelColor(c1, color3);
}
} else {
for (uint16_t i = SEGENV.aux1; i <= SEGLEN; i++) { // from last position to the end
setPixelColor(i, color1);
uint16_t b1 = (i + size) % SEGLEN;
uint16_t c1 = (b1 + size) % SEGLEN;
setPixelColor(b1, color2);
setPixelColor(c1, color3);
}
for (uint16_t i = 0; i < a; i++) { // from 0 to the actual position
setPixelColor(i, color1);
uint16_t b1 = (i + size) % SEGLEN;
uint16_t c1 = (b1 + size) % SEGLEN;
setPixelColor(b1, color2);
setPixelColor(c1, color3);
}
SEGENV.step = 0;
SEGENV.aux0 = 0;
}
//if random, fill old background between a and end
if (chase_random)
{
color1 = color_wheel(SEGENV.aux1);
for (uint16_t i = a; i < SEGLEN; i++)
setPixelColor(i, color1);
}
//fill between points a and b with color2
if (a < b)
{
for (uint16_t i = a; i < b; i++)
setPixelColor(i, color2);
} else {
for (uint16_t i = a; i < SEGLEN; i++) //fill until end
setPixelColor(i, color2);
for (uint16_t i = 0; i < b; i++) //fill from start until b
setPixelColor(i, color2);
}
//fill between points b and c with color2
if (b < c)
{
for (uint16_t i = b; i < c; i++)
setPixelColor(i, color3);
} else {
for (uint16_t i = b; i < SEGLEN; i++) //fill until end
setPixelColor(i, color3);
for (uint16_t i = 0; i < c; i++) //fill from start until c
setPixelColor(i, color3);
}
SEGENV.aux1 = ++a;
return FRAMETIME;
}
@@ -751,7 +761,7 @@ uint16_t WS2812FX::chase(uint32_t color1, uint32_t color2, uint32_t color3, bool
* Bicolor chase, more primary color.
*/
uint16_t WS2812FX::mode_chase_color(void) {
return chase(SEGCOLOR(1), SEGCOLOR(0), SEGCOLOR(0), true);
return chase(SEGCOLOR(1), (SEGCOLOR(2)) ? SEGCOLOR(2) : SEGCOLOR(0), SEGCOLOR(0), true);
}
@@ -759,12 +769,19 @@ uint16_t WS2812FX::mode_chase_color(void) {
* Primary running followed by random color.
*/
uint16_t WS2812FX::mode_chase_random(void) {
if (!SEGENV.allocateData(2)) return mode_static(); //allocation failed
if (SEGENV.call == 0) SEGENV.data[0] = 0;
if (SEGENV.step == 0) {
SEGENV.data[0] = get_random_wheel_index(SEGENV.data[0]);
}
return chase(color_wheel(SEGENV.data[0]), SEGCOLOR(0), SEGCOLOR(0), false);
return chase(SEGCOLOR(1), (SEGCOLOR(2)) ? SEGCOLOR(2) : SEGCOLOR(0), SEGCOLOR(0), false);
}
/*
* Primary, secondary running on rainbow.
*/
uint16_t WS2812FX::mode_chase_rainbow(void) {
uint8_t color_sep = 256 / SEGLEN;
uint8_t color_index = SEGENV.call & 0xFF;
uint32_t color = color_wheel(((SEGENV.step * color_sep) + color_index) & 0xFF);
return chase(color, SEGCOLOR(0), SEGCOLOR(1), false);
}
@@ -860,18 +877,6 @@ uint16_t WS2812FX::mode_traffic_light(void) {
}
/*
* Primary, secondary running on rainbow.
*/
uint16_t WS2812FX::mode_chase_rainbow(void) {
uint8_t color_sep = 256 / SEGLEN;
uint8_t color_index = SEGENV.call & 0xFF;
uint32_t color = color_wheel(((SEGENV.step * color_sep) + color_index) & 0xFF);
return chase(color, SEGCOLOR(0), SEGCOLOR(1), 0);
}
/*
* Sec flashes running on prim.
*/
@@ -1110,7 +1115,7 @@ uint16_t WS2812FX::mode_fireworks() {
if (valid1) setPixelColor(SEGENV.aux0 , sv1);
if (valid2) setPixelColor(SEGENV.aux1, sv2);
for(uint16_t i=0; i<max(1, SEGLEN/20); i++) {
for(uint16_t i=0; i<MAX(1, SEGLEN/20); i++) {
if(random8(129 - (SEGMENT.intensity >> 1)) == 0) {
uint16_t index = random(SEGLEN);
setPixelColor(index, color_from_palette(random8(), false, false, 0));
@@ -1157,12 +1162,12 @@ uint16_t WS2812FX::mode_fire_flicker(void) {
byte r = (SEGCOLOR(0) >> 16) & 0xFF;
byte g = (SEGCOLOR(0) >> 8) & 0xFF;
byte b = (SEGCOLOR(0) & 0xFF);
byte lum = (SEGMENT.palette == 0) ? max(w, max(r, max(g, b))) : 255;
byte lum = (SEGMENT.palette == 0) ? MAX(w, MAX(r, MAX(g, b))) : 255;
lum /= (((256-SEGMENT.intensity)/16)+1);
for(uint16_t i = 0; i < SEGLEN; i++) {
byte flicker = random8(lum);
if (SEGMENT.palette == 0) {
setPixelColor(i, max(r - flicker, 0), max(g - flicker, 0), max(b - flicker, 0), max(w - flicker, 0));
setPixelColor(i, MAX(r - flicker, 0), MAX(g - flicker, 0), MAX(b - flicker, 0), MAX(w - flicker, 0));
} else {
setPixelColor(i, color_from_palette(i, true, PALETTE_SOLID_WRAP, 0, 255 - flicker));
}
@@ -1192,7 +1197,7 @@ uint16_t WS2812FX::gradient_base(bool loading) {
{
val = abs(((i>pp) ? p2:pp) -i);
} else {
val = min(abs(pp-i),min(abs(p1-i),abs(p2-i)));
val = MIN(abs(pp-i),MIN(abs(p1-i),abs(p2-i)));
}
val = (brd > val) ? val/brd * 255 : 255;
setPixelColor(i, color_blend(SEGCOLOR(0), color_from_palette(i, true, PALETTE_SOLID_WRAP, 1), val));
@@ -1773,7 +1778,7 @@ uint16_t WS2812FX::mode_fire_2012()
// Step 4. Map from heat cells to LED colors
for (uint16_t j = 0; j < SEGLEN; j++) {
CRGB color = ColorFromPalette(currentPalette, min(heat[j],240), 255, LINEARBLEND);
CRGB color = ColorFromPalette(currentPalette, MIN(heat[j],240), 255, LINEARBLEND);
setPixelColor(j, color.red, color.green, color.blue);
}
return FRAMETIME;
@@ -2568,7 +2573,7 @@ uint16_t WS2812FX::mode_bouncing_balls(void) {
uint32_t color = SEGCOLOR(0);
if (SEGMENT.palette) {
color = color_wheel(i*(256/max(numBalls, 8)));
color = color_wheel(i*(256/MAX(numBalls, 8)));
} else if (hasCol2) {
color = SEGCOLOR(i % NUM_COLORS);
}
@@ -2714,50 +2719,92 @@ uint16_t WS2812FX::mode_popcorn(void) {
//Inspired by https://github.com/avanhanegem/ArduinoCandleEffectNeoPixel
//and https://cpldcpu.wordpress.com/2016/01/05/reverse-engineering-a-real-candle/
uint16_t WS2812FX::mode_candle()
uint16_t WS2812FX::candle(bool multi)
{
if (SEGENV.call == 0) {
SEGENV.aux0 = 128; SEGENV.aux1 = 132; SEGENV.step = 1;
}
bool newTarget = false;
uint8_t s = SEGENV.aux0, target = SEGENV.aux1, fadeStep = SEGENV.step;
if (target > s) { //fade up
s = qadd8(s, fadeStep);
if (s >= target) newTarget = true;
} else {
s = qsub8(s, fadeStep);
if (s <= target) newTarget = true;
}
SEGENV.aux0 = s;
for (uint16_t i = 0; i < SEGLEN; i++) {
setPixelColor(i, color_blend(color_from_palette(i, true, PALETTE_SOLID_WRAP, 0), SEGCOLOR(1), 255-s));
}
if (newTarget)
if (multi)
{
uint8_t valrange = SEGMENT.intensity;
uint8_t rndval = valrange >> 1;
target = random8(rndval) + random8(rndval);
if (target < (rndval >> 1)) target = (rndval >> 1) + random8(rndval);
uint8_t offset = (255 - valrange) >> 1;
target += offset;
//allocate segment data
uint16_t dataSize = (SEGLEN -1) *3;
if (!SEGENV.allocateData(dataSize)) return candle(false); //allocation failed
}
uint8_t dif = (target > s) ? target - s : s - target;
//how much to move closer to target per frame
fadeStep = dif >> 2; //mode called every ~25 ms, so 4 frames to have a new target every 100ms
if (fadeStep == 0) fadeStep = 1;
//max. flicker range controlled by intensity
uint8_t valrange = SEGMENT.intensity;
uint8_t rndval = valrange >> 1;
//step (how much to move closer to target per frame) coarsely set by speed
uint8_t speedFactor = 4;
if (SEGMENT.speed > 252) { //epilepsy
speedFactor = 1;
} else if (SEGMENT.speed > 99) { //regular candle (mode called every ~25 ms, so 4 frames to have a new target every 100ms)
speedFactor = 2;
} else if (SEGMENT.speed > 49) { //slower fade
speedFactor = 3;
} //else 4 (slowest)
uint16_t numCandles = (multi) ? SEGLEN : 1;
for (uint16_t i = 0; i < numCandles; i++)
{
uint16_t d = 0; //data location
uint8_t s = SEGENV.aux0, s_target = SEGENV.aux1, fadeStep = SEGENV.step;
if (i > 0) {
d = (i-1) *3;
s = SEGENV.data[d]; s_target = SEGENV.data[d+1]; fadeStep = SEGENV.data[d+2];
}
if (fadeStep == 0) { //init vals
s = 128; s_target = 130 + random8(4); fadeStep = 1;
}
bool newTarget = false;
if (s_target > s) { //fade up
s = qadd8(s, fadeStep);
if (s >= s_target) newTarget = true;
} else {
s = qsub8(s, fadeStep);
if (s <= s_target) newTarget = true;
}
if (newTarget) {
s_target = random8(rndval) + random8(rndval);
if (s_target < (rndval >> 1)) s_target = (rndval >> 1) + random8(rndval);
uint8_t offset = (255 - valrange) >> 1;
s_target += offset;
uint8_t dif = (s_target > s) ? s_target - s : s - s_target;
SEGENV.step = fadeStep;
SEGENV.aux1 = target;
fadeStep = dif >> speedFactor;
if (fadeStep == 0) fadeStep = 1;
}
if (i > 0) {
setPixelColor(i, color_blend(SEGCOLOR(1), color_from_palette(i, true, PALETTE_SOLID_WRAP, 0), s));
SEGENV.data[d] = s; SEGENV.data[d+1] = s_target; SEGENV.data[d+2] = fadeStep;
} else {
for (uint16_t j = 0; j < SEGLEN; j++) {
setPixelColor(j, color_blend(SEGCOLOR(1), color_from_palette(j, true, PALETTE_SOLID_WRAP, 0), s));
}
SEGENV.aux0 = s; SEGENV.aux1 = s_target; SEGENV.step = fadeStep;
}
}
return FRAMETIME;
}
uint16_t WS2812FX::mode_candle()
{
return candle(false);
}
uint16_t WS2812FX::mode_candle_multi()
{
return candle(true);
}
/*
/ Fireworks in starburst effect
@@ -2896,9 +2943,9 @@ uint16_t WS2812FX::mode_exploding_fireworks(void)
fill(BLACK);
bool actuallyReverse = SEGMENT.getOption(1);
bool actuallyReverse = SEGMENT.getOption(SEG_OPTION_REVERSED);
//have fireworks start in either direction based on intensity
SEGMENT.setOption(1, SEGENV.step);
SEGMENT.setOption(SEG_OPTION_REVERSED, SEGENV.step);
Spark* sparks = reinterpret_cast<Spark*>(SEGENV.data);
Spark* flare = sparks; //first spark is flare data
@@ -2989,7 +3036,7 @@ uint16_t WS2812FX::mode_exploding_fireworks(void)
}
}
SEGMENT.setOption(1, actuallyReverse);
SEGMENT.setOption(SEG_OPTION_REVERSED, actuallyReverse);
return FRAMETIME;
}
@@ -3089,13 +3136,14 @@ uint16_t WS2812FX::mode_plasma(void) {
return FRAMETIME;
}
/*
* Percentage display
* Intesity values from 0-100 turn on the leds.
*/
uint16_t WS2812FX::mode_percent(void) {
uint8_t percent = max(0, min(200, SEGMENT.intensity));
uint8_t percent = MAX(0, MIN(200, SEGMENT.intensity));
uint16_t active_leds = (percent < 100) ? SEGLEN * percent / 100.0
: SEGLEN * (200 - percent) / 100.0;
@@ -3161,4 +3209,116 @@ uint16_t WS2812FX::mode_heartbeat(void) {
}
return FRAMETIME;
}
}
// "Pacifica"
// Gentle, blue-green ocean waves.
// December 2019, Mark Kriegsman and Mary Corey March.
// For Dan.
//
//
// In this animation, there are four "layers" of waves of light.
//
// Each layer moves independently, and each is scaled separately.
//
// All four wave layers are added together on top of each other, and then
// another filter is applied that adds "whitecaps" of brightness where the
// waves line up with each other more. Finally, another pass is taken
// over the led array to 'deepen' (dim) the blues and greens.
//
// The speed and scale and motion each layer varies slowly within independent
// hand-chosen ranges, which is why the code has a lot of low-speed 'beatsin8' functions
// with a lot of oddly specific numeric ranges.
//
// These three custom blue-green color palettes were inspired by the colors found in
// the waters off the southern coast of California, https://goo.gl/maps/QQgd97jjHesHZVxQ7
//
// Modified for WLED, based on https://github.com/FastLED/FastLED/blob/master/examples/Pacifica/Pacifica.ino
//
uint16_t WS2812FX::mode_pacifica()
{
CRGBPalette16 pacifica_palette_1 =
{ 0x000507, 0x000409, 0x00030B, 0x00030D, 0x000210, 0x000212, 0x000114, 0x000117,
0x000019, 0x00001C, 0x000026, 0x000031, 0x00003B, 0x000046, 0x14554B, 0x28AA50 };
CRGBPalette16 pacifica_palette_2 =
{ 0x000507, 0x000409, 0x00030B, 0x00030D, 0x000210, 0x000212, 0x000114, 0x000117,
0x000019, 0x00001C, 0x000026, 0x000031, 0x00003B, 0x000046, 0x0C5F52, 0x19BE5F };
CRGBPalette16 pacifica_palette_3 =
{ 0x000208, 0x00030E, 0x000514, 0x00061A, 0x000820, 0x000927, 0x000B2D, 0x000C33,
0x000E39, 0x001040, 0x001450, 0x001860, 0x001C70, 0x002080, 0x1040BF, 0x2060FF };
if (SEGMENT.palette) {
pacifica_palette_1 = currentPalette;
pacifica_palette_2 = currentPalette;
pacifica_palette_3 = currentPalette;
}
// Increment the four "color index start" counters, one for each wave layer.
// Each is incremented at a different speed, and the speeds vary over time.
uint16_t sCIStart1 = SEGENV.aux0, sCIStart2 = SEGENV.aux1, sCIStart3 = SEGENV.step, sCIStart4 = SEGENV.step >> 16;
//static uint16_t sCIStart1, sCIStart2, sCIStart3, sCIStart4;
uint32_t deltams = 26 + (SEGMENT.speed >> 3);
uint16_t speedfactor1 = beatsin16(3, 179, 269);
uint16_t speedfactor2 = beatsin16(4, 179, 269);
uint32_t deltams1 = (deltams * speedfactor1) / 256;
uint32_t deltams2 = (deltams * speedfactor2) / 256;
uint32_t deltams21 = (deltams1 + deltams2) / 2;
sCIStart1 += (deltams1 * beatsin88(1011,10,13));
sCIStart2 -= (deltams21 * beatsin88(777,8,11));
sCIStart3 -= (deltams1 * beatsin88(501,5,7));
sCIStart4 -= (deltams2 * beatsin88(257,4,6));
SEGENV.aux0 = sCIStart1; SEGENV.aux1 = sCIStart2;
SEGENV.step = sCIStart4; SEGENV.step = (SEGENV.step << 16) + sCIStart3;
// Clear out the LED array to a dim background blue-green
//fill(132618);
uint8_t basethreshold = beatsin8( 9, 55, 65);
uint8_t wave = beat8( 7 );
for( uint16_t i = 0; i < SEGLEN; i++) {
CRGB c = CRGB(2, 6, 10);
// Render each of four layers, with different scales and speeds, that vary over time
c += pacifica_one_layer(i, pacifica_palette_1, sCIStart1, beatsin16(3, 11 * 256, 14 * 256), beatsin8(10, 70, 130), 0-beat16(301));
c += pacifica_one_layer(i, pacifica_palette_2, sCIStart2, beatsin16(4, 6 * 256, 9 * 256), beatsin8(17, 40, 80), beat16(401));
c += pacifica_one_layer(i, pacifica_palette_3, sCIStart3, 6 * 256 , beatsin8(9, 10,38) , 0-beat16(503));
c += pacifica_one_layer(i, pacifica_palette_3, sCIStart4, 5 * 256 , beatsin8(8, 10,28) , beat16(601));
// Add extra 'white' to areas where the four layers of light have lined up brightly
uint8_t threshold = scale8( sin8( wave), 20) + basethreshold;
wave += 7;
uint8_t l = c.getAverageLight();
if (l > threshold) {
uint8_t overage = l - threshold;
uint8_t overage2 = qadd8(overage, overage);
c += CRGB(overage, overage2, qadd8(overage2, overage2));
}
//deepen the blues and greens
c.blue = scale8(c.blue, 145);
c.green = scale8(c.green, 200);
c |= CRGB( 2, 5, 7);
setPixelColor(i, c.red, c.green, c.blue);
}
return FRAMETIME;
}
// Add one layer of waves into the led array
CRGB WS2812FX::pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff)
{
uint16_t ci = cistart;
uint16_t waveangle = ioff;
uint16_t wavescale_half = (wavescale >> 1) + 20;
waveangle += ((120 + SEGMENT.intensity) * i); //original 250 * i
uint16_t s16 = sin16(waveangle) + 32768;
uint16_t cs = scale16(s16, wavescale_half) + wavescale_half;
ci += (cs * i);
uint16_t sindex16 = sin16(ci) + 32768;
uint8_t sindex8 = scale16(sindex16, 240);
return ColorFromPalette(p, sindex8, bri, LINEARBLEND);
}

View File

@@ -38,8 +38,8 @@
#define DEFAULT_SPEED (uint8_t)128
#define DEFAULT_COLOR (uint32_t)0xFFAA00
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
/* Not used in all effects yet */
#define WLED_FPS 42
@@ -56,6 +56,9 @@
#define MAX_SEGMENT_DATA 8192
#endif
#define LED_SKIP_AMOUNT 1
#define MIN_SHOW_DELAY 15
#define NUM_COLORS 3 /* number of colors per segment */
#define SEGMENT _segments[_segment_index]
#define SEGCOLOR(x) gamma32(_segments[_segment_index].colors[x])
@@ -81,18 +84,21 @@
// options
// bit 7: segment is in transition mode
// bits 2-6: TBD
// bits 3-6: TBD
// bit 2: segment is on
// bit 1: reverse segment
// bit 0: segment is selected
#define NO_OPTIONS (uint8_t)0x00
#define TRANSITIONAL (uint8_t)0x80
#define SEGMENT_ON (uint8_t)0x04
#define REVERSE (uint8_t)0x02
#define SELECTED (uint8_t)0x01
#define IS_TRANSITIONAL ((SEGMENT.options & TRANSITIONAL) == TRANSITIONAL)
#define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE )
#define IS_SELECTED ((SEGMENT.options & SELECTED) == SELECTED )
#define IS_SEGMENT_ON ((SEGMENT.options & SEGMENT_ON ) == SEGMENT_ON )
#define IS_REVERSE ((SEGMENT.options & REVERSE ) == REVERSE )
#define IS_SELECTED ((SEGMENT.options & SELECTED ) == SELECTED )
#define MODE_COUNT 101
#define MODE_COUNT 103
#define FX_MODE_STATIC 0
#define FX_MODE_BLINK 1
@@ -195,6 +201,8 @@
#define FX_MODE_PERCENT 98
#define FX_MODE_RIPPLE_RAINBOW 99
#define FX_MODE_HEARTBEAT 100
#define FX_MODE_PACIFICA 101
#define FX_MODE_CANDLE_MULTI 102
class WS2812FX {
typedef uint16_t (WS2812FX::*mode_ptr)(void);
@@ -384,6 +392,8 @@ class WS2812FX {
_mode[FX_MODE_PERCENT] = &WS2812FX::mode_percent;
_mode[FX_MODE_RIPPLE_RAINBOW] = &WS2812FX::mode_ripple_rainbow;
_mode[FX_MODE_HEARTBEAT] = &WS2812FX::mode_heartbeat;
_mode[FX_MODE_PACIFICA] = &WS2812FX::mode_pacifica;
_mode[FX_MODE_CANDLE_MULTI] = &WS2812FX::mode_candle_multi;
_brightness = DEFAULT_BRIGHTNESS;
currentPalette = CRGBPalette16(CRGB::Black);
@@ -404,9 +414,6 @@ class WS2812FX {
setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
setColor(uint8_t slot, uint32_t c),
setBrightness(uint8_t b),
driverModeCronixie(bool b),
setCronixieDigits(byte* d),
setCronixieBacklight(bool b),
setRange(uint16_t i, uint16_t i2, uint32_t col),
setShowCallback(show_callback cb),
setTransitionMode(bool t),
@@ -571,7 +578,9 @@ class WS2812FX {
mode_plasma(void),
mode_percent(void),
mode_ripple_rainbow(void),
mode_heartbeat(void);
mode_heartbeat(void),
mode_pacifica(void),
mode_candle_multi(void);
private:
@@ -588,18 +597,15 @@ class WS2812FX {
uint8_t _brightness;
static uint16_t _usedSegmentData;
void load_gradient_palette(uint8_t);
void handle_palette(void);
void fill(uint32_t);
bool
_useRgbw = false,
_cronixieMode,
_cronixieBacklightEnabled,
_skipFirstMode,
_triggered;
byte _cronixieDigits[6];
mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element
show_callback _callback = nullptr;
@@ -607,6 +613,7 @@ class WS2812FX {
// mode helper functions
uint16_t
blink(uint32_t, uint32_t, bool strobe, bool),
candle(bool),
color_wipe(bool, bool),
scan(bool),
theater_chase(uint32_t, uint32_t, bool),
@@ -624,13 +631,14 @@ class WS2812FX {
spots_base(uint16_t);
CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat);
CRGB pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff);
uint32_t _lastPaletteChange = 0;
uint32_t _lastShow = 0;
#ifdef WLED_USE_ANALOG_LEDS
uint32_t _analogLastShow = 0;
uint32_t _analogLastColor = 0;
RgbwColor _analogLastColor = 0;
uint8_t _analogLastBri = 0;
#endif
@@ -659,17 +667,17 @@ const char JSON_mode_names[] PROGMEM = R"=====([
"Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple",
"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst",
"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip","Plasma","Percent","Ripple Rainbow",
"Heartbeat"
"Heartbeat","Pacifica","Candle Multi"
])=====";
const char JSON_palette_names[] PROGMEM = R"=====([
"Default","Random Cycle","Primary Color","Based on Primary","Set Colors","Based on Set","Party","Cloud","Lava","Ocean",
"Default","* Random Cycle","* Color 1","* Colors 1&2","* Color Gradient","* Colors Only","Party","Cloud","Lava","Ocean",
"Forest","Rainbow","Rainbow Bands","Sunset","Rivendell","Breeze","Red & Blue","Yellowout","Analogous","Splash",
"Pastel","Sunset 2","Beech","Vintage","Departure","Landscape","Beach","Sherbet","Hult","Hult 64",
"Drywet","Jul","Grintage","Rewhi","Tertiary","Fire","Icefire","Cyane","Light Pink","Autumn",
"Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery","C9","Sakura",
"Aurora"
"Aurora","Atlantica"
])=====";
#endif

View File

@@ -27,16 +27,30 @@
#include "FX.h"
#include "palettes.h"
#define LED_SKIP_AMOUNT 1
#define MIN_SHOW_DELAY 15
//enable custom per-LED mapping. This can allow for better effects on matrices or special displays
//#define WLED_CUSTOM_LED_MAPPING
#ifdef WLED_CUSTOM_LED_MAPPING
//this is just an example (30 LEDs). It will first set all even, then all uneven LEDs.
const uint16_t customMappingTable[] = {
0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28,
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29};
//another example. Switches direction every 5 LEDs.
/*const uint16_t customMappingTable[] = {
0, 1, 2, 3, 4, 9, 8, 7, 6, 5, 10, 11, 12, 13, 14,
19, 18, 17, 16, 15, 20, 21, 22, 23, 24, 29, 28, 27, 26, 25};*/
const uint16_t customMappingSize = sizeof(customMappingTable)/sizeof(uint16_t); //30 in example
#endif
void WS2812FX::init(bool supportWhite, uint16_t countPixels, bool skipFirst)
{
if (supportWhite == _useRgbw && countPixels == _length) return;
if (supportWhite == _useRgbw && countPixels == _length && _skipFirstMode == skipFirst) return;
RESET_RUNTIME;
_useRgbw = supportWhite;
_skipFirstMode = skipFirst;
_length = countPixels;
_skipFirstMode = skipFirst;
uint8_t ty = 1;
if (supportWhite) ty = 2;
@@ -133,84 +147,46 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
}
col.W = w;
if (!_cronixieMode)
{
uint16_t skip = _skipFirstMode ? LED_SKIP_AMOUNT : 0;
if (SEGLEN) {//from segment
/* Set all the pixels in the group, ensuring _skipFirstMode is honored */
bool reversed = reverseMode ^ IS_REVERSE;
uint16_t realIndex = realPixelIndex(i);
uint16_t skip = _skipFirstMode ? LED_SKIP_AMOUNT : 0;
if (SEGLEN) {//from segment
for (uint16_t j = 0; j < SEGMENT.grouping; j++) {
int16_t indexSet = realIndex + (reversed ? -j : j);
int16_t indexSetRev = indexSet;
if (reverseMode) indexSetRev = _length - 1 - indexSet;
if (indexSetRev >= SEGMENT.start && indexSetRev < SEGMENT.stop) bus->SetPixelColor(indexSet + skip, col);
}
} else { //live data, etc.
if (reverseMode) i = _length - 1 - i;
bus->SetPixelColor(i + skip, col);
}
if (skip && i == 0) {
for (uint16_t j = 0; j < skip; j++) {
bus->SetPixelColor(j, RgbwColor(0, 0, 0, 0));
}
}
return;
}
//CRONIXIE
if(i>6)return;
byte o = 10*i;
if (_cronixieBacklightEnabled && _cronixieDigits[i] <11)
{
byte r2 = _segments[0].colors[1] >>16;
byte g2 = _segments[0].colors[1] >> 8;
byte b2 = _segments[0].colors[1];
byte w2 = _segments[0].colors[1] >>24;
for (int j=o; j< o+19; j++)
//color_blend(getpixel, col, SEGMENT.opacity); (pseudocode for future blending of segments)
if (IS_SEGMENT_ON)
{
bus->SetPixelColor(j, RgbwColor(r2,g2,b2,w2));
if (SEGMENT.opacity < 255) {
col.R = scale8(col.R, SEGMENT.opacity);
col.G = scale8(col.G, SEGMENT.opacity);
col.B = scale8(col.B, SEGMENT.opacity);
col.W = scale8(col.W, SEGMENT.opacity);
}
} else {
col = BLACK;
}
} else
{
for (int j=o; j< o+19; j++)
{
bus->SetPixelColor(j, RgbwColor(0,0,0,0));
/* Set all the pixels in the group, ensuring _skipFirstMode is honored */
bool reversed = reverseMode ^ IS_REVERSE;
uint16_t realIndex = realPixelIndex(i);
for (uint16_t j = 0; j < SEGMENT.grouping; j++) {
int16_t indexSet = realIndex + (reversed ? -j : j);
int16_t indexSetRev = indexSet;
if (reverseMode) indexSetRev = _length - 1 - indexSet;
#ifdef WLED_CUSTOM_LED_MAPPING
if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet];
#endif
if (indexSetRev >= SEGMENT.start && indexSetRev < SEGMENT.stop) bus->SetPixelColor(indexSet + skip, col);
}
} else { //live data, etc.
if (reverseMode) i = _length - 1 - i;
#ifdef WLED_CUSTOM_LED_MAPPING
if (i < customMappingSize) i = customMappingTable[i];
#endif
bus->SetPixelColor(i + skip, col);
}
if (_skipFirstMode) o += LED_SKIP_AMOUNT;
switch(_cronixieDigits[i])
{
case 0: bus->SetPixelColor(o+5, col); break;
case 1: bus->SetPixelColor(o+0, col); break;
case 2: bus->SetPixelColor(o+6, col); break;
case 3: bus->SetPixelColor(o+1, col); break;
case 4: bus->SetPixelColor(o+7, col); break;
case 5: bus->SetPixelColor(o+2, col); break;
case 6: bus->SetPixelColor(o+8, col); break;
case 7: bus->SetPixelColor(o+3, col); break;
case 8: bus->SetPixelColor(o+9, col); break;
case 9: bus->SetPixelColor(o+4, col); break;
}
}
void WS2812FX::driverModeCronixie(bool b)
{
_cronixieMode = b;
_segments[0].stop = (b) ? 6 : _length;
}
void WS2812FX::setCronixieBacklight(bool b)
{
_cronixieBacklightEnabled = b;
}
void WS2812FX::setCronixieDigits(byte d[])
{
for (int i = 0; i<6; i++)
{
_cronixieDigits[i] = d[i];
if (skip && i == 0) {
for (uint16_t j = 0; j < skip; j++) {
bus->SetPixelColor(j, RgbwColor(0, 0, 0, 0));
}
}
}
@@ -262,7 +238,7 @@ void WS2812FX::show(void) {
if(useWackyWS2815PowerModel)
{
// ignore white component on WS2815 power calculation
powerSum += (max(max(c.R,c.G),c.B)) * 3;
powerSum += (MAX(MAX(c.R,c.G),c.B)) * 3;
}
else
{
@@ -327,7 +303,7 @@ uint8_t WS2812FX::getModeCount()
uint8_t WS2812FX::getPaletteCount()
{
return 13 + gGradientPaletteCount;
return 13 + GRADIENT_PALETTE_COUNT;
}
//TODO transitions
@@ -338,6 +314,8 @@ bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t in, uint8_t p) {
Segment& seg = _segments[getMainSegmentId()];
uint8_t modePrev = seg.mode, speedPrev = seg.speed, intensityPrev = seg.intensity, palettePrev = seg.palette;
bool applied = false;
if (applyToAllSelected) {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
@@ -347,9 +325,12 @@ bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t in, uint8_t p) {
_segments[i].intensity = in;
_segments[i].palette = p;
setMode(i, m);
applied = true;
}
}
} else {
}
if (!applyToAllSelected || !applied) {
seg.speed = s;
seg.intensity = in;
seg.palette = p;
@@ -366,12 +347,17 @@ void WS2812FX::setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w
void WS2812FX::setColor(uint8_t slot, uint32_t c) {
if (slot >= NUM_COLORS) return;
bool applied = false;
if (applyToAllSelected) {
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
{
if (_segments[i].isSelected()) _segments[i].colors[slot] = c;
}
} else {
}
if (!applyToAllSelected || !applied) {
_segments[getMainSegmentId()].colors[slot] = c;
}
}
@@ -380,7 +366,7 @@ void WS2812FX::setBrightness(uint8_t b) {
if (_brightness == b) return;
_brightness = (gammaCorrectBri) ? gamma8(b) : b;
_segment_index = 0;
if (SEGENV.next_time > millis() + 22) show();//apply brightness change immediately if no refresh soon
if (SEGENV.next_time > millis() + 22 && millis() - _lastShow > MIN_SHOW_DELAY) show();//apply brightness change immediately if no refresh soon
}
uint8_t WS2812FX::getMode(void) {
@@ -423,27 +409,14 @@ uint32_t WS2812FX::getColor(void) {
uint32_t WS2812FX::getPixelColor(uint16_t i)
{
i = realPixelIndex(i) + (_skipFirstMode ? LED_SKIP_AMOUNT : 0);
i = realPixelIndex(i);
#ifdef WLED_CUSTOM_LED_MAPPING
if (i < customMappingSize) i = customMappingTable[i];
#endif
if (_skipFirstMode) i += LED_SKIP_AMOUNT;
if (_cronixieMode)
{
if(i>6)return 0;
byte o = 10*i;
switch(_cronixieDigits[i])
{
case 0: i=o+5; break;
case 1: i=o+0; break;
case 2: i=o+6; break;
case 3: i=o+1; break;
case 4: i=o+7; break;
case 5: i=o+2; break;
case 6: i=o+8; break;
case 7: i=o+3; break;
case 8: i=o+9; break;
case 9: i=o+4; break;
default: return 0;
}
}
if (i >= _lengthRaw) return 0;
RgbwColor col = bus->GetPixelColorRgbw(i);
@@ -453,8 +426,8 @@ uint32_t WS2812FX::getPixelColor(uint16_t i)
case 0: return ((col.W << 24) | (col.G << 8) | (col.R << 16) | (col.B)); //0 = GRB, default
case 1: return ((col.W << 24) | (col.R << 8) | (col.G << 16) | (col.B)); //1 = RGB, common for WS2811
case 2: return ((col.W << 24) | (col.B << 8) | (col.R << 16) | (col.G)); //2 = BRG
case 3: return ((col.W << 24) | (col.R << 8) | (col.B << 16) | (col.G)); //3 = RBG
case 4: return ((col.W << 24) | (col.B << 8) | (col.G << 16) | (col.R)); //4 = BGR
case 3: return ((col.W << 24) | (col.B << 8) | (col.G << 16) | (col.R)); //3 = RBG
case 4: return ((col.W << 24) | (col.R << 8) | (col.B << 16) | (col.G)); //4 = BGR
case 5: return ((col.W << 24) | (col.G << 8) | (col.B << 16) | (col.R)); //5 = GBR
}
return 0;
@@ -522,11 +495,16 @@ void WS2812FX::resetSegments() {
_segments[0].speed = DEFAULT_SPEED;
_segments[0].stop = _length;
_segments[0].grouping = 1;
_segments[0].setOption(0, 1); //select
_segments[0].setOption(SEG_OPTION_SELECTED, 1);
_segments[0].setOption(SEG_OPTION_ON, 1);
_segments[0].opacity = 255;
for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++)
{
_segments[i].colors[0] = color_wheel(i*51);
_segments[i].grouping = 1;
_segments[i].setOption(SEG_OPTION_ON, 1);
_segments[i].opacity = 255;
_segment_runtimes[i].reset();
}
_segment_runtimes[0].reset();
@@ -551,7 +529,7 @@ void WS2812FX::setShowCallback(show_callback cb)
void WS2812FX::setTransitionMode(bool t)
{
_segment_index = getMainSegmentId();
SEGMENT.setOption(7,t);
SEGMENT.setOption(SEG_OPTION_TRANSITIONAL, t);
if (!t) return;
unsigned long waitMax = millis() + 20; //refresh after 20 ms if transition enabled
if (SEGMENT.mode == FX_MODE_STATIC && SEGENV.next_time > waitMax) SEGENV.next_time = waitMax;
@@ -688,7 +666,7 @@ uint8_t WS2812FX::get_random_wheel_index(uint8_t pos) {
r = random8();
x = abs(pos - r);
y = 255 - x;
d = min(x, y);
d = MIN(x, y);
}
return r;
}
@@ -710,6 +688,15 @@ CRGB WS2812FX::col_to_crgb(uint32_t color)
}
void WS2812FX::load_gradient_palette(uint8_t index)
{
byte i = constrain(index, 0, GRADIENT_PALETTE_COUNT -1);
byte tcp[72]; //support gradient palettes with up to 18 entries
memcpy_P(tcp, (byte*)pgm_read_dword(&(gGradientPalettes[i])), 72);
targetPalette.loadDynamicGradientPalette(tcp);
}
/*
* FastLED palette modes helper function. Limitation: Due to memory reasons, multiple active segments with FastLED will disable the Palette transitions
*/
@@ -727,13 +714,13 @@ void WS2812FX::handle_palette(void)
case 0: {//default palette. Differs depending on effect
switch (SEGMENT.mode)
{
case FX_MODE_FIRE_2012 : targetPalette = gGradientPalettes[22]; break;//heat palette
case FX_MODE_COLORWAVES : targetPalette = gGradientPalettes[13]; break;//landscape 33
case FX_MODE_FIRE_2012 : load_gradient_palette(22); break;//heat palette
case FX_MODE_COLORWAVES : load_gradient_palette(13); break;//landscape 33
case FX_MODE_FILLNOISE8 : targetPalette = OceanColors_p; break;
case FX_MODE_NOISE16_1 : targetPalette = gGradientPalettes[17]; break;//Drywet
case FX_MODE_NOISE16_2 : targetPalette = gGradientPalettes[30]; break;//Blue cyan yellow
case FX_MODE_NOISE16_3 : targetPalette = gGradientPalettes[22]; break;//heat palette
case FX_MODE_NOISE16_4 : targetPalette = gGradientPalettes[13]; break;//landscape 33
case FX_MODE_NOISE16_1 : load_gradient_palette(17); break;//Drywet
case FX_MODE_NOISE16_2 : load_gradient_palette(30); break;//Blue cyan yellow
case FX_MODE_NOISE16_3 : load_gradient_palette(22); break;//heat palette
case FX_MODE_NOISE16_4 : load_gradient_palette(13); break;//landscape 33
//case FX_MODE_GLITTER : targetPalette = RainbowColors_p; break;
default: targetPalette = PartyColors_p; break;//palette, bpm
@@ -756,25 +743,25 @@ void WS2812FX::handle_palette(void)
case 2: {//primary color only
CRGB prim = col_to_crgb(SEGCOLOR(0));
targetPalette = CRGBPalette16(prim); break;}
case 3: {//based on primary
//considering performance implications
CRGB prim = col_to_crgb(SEGCOLOR(0));
CHSV prim_hsv = rgb2hsv_approximate(prim);
targetPalette = CRGBPalette16(
CHSV(prim_hsv.h, prim_hsv.s, prim_hsv.v), //color itself
CHSV(prim_hsv.h, max(prim_hsv.s - 50,0), prim_hsv.v), //less saturated
CHSV(prim_hsv.h, prim_hsv.s, max(prim_hsv.v - 50,0)), //darker
CHSV(prim_hsv.h, prim_hsv.s, prim_hsv.v)); //color itself
break;}
case 4: {//primary + secondary
case 3: {//primary + secondary
CRGB prim = col_to_crgb(SEGCOLOR(0));
CRGB sec = col_to_crgb(SEGCOLOR(1));
targetPalette = CRGBPalette16(sec,prim); break;}
case 5: {//based on primary + secondary
targetPalette = CRGBPalette16(prim,prim,sec,sec); break;}
case 4: {//primary + secondary + tertiary
CRGB prim = col_to_crgb(SEGCOLOR(0));
CRGB sec = col_to_crgb(SEGCOLOR(1));
CRGB ter = col_to_crgb(SEGCOLOR(2));
targetPalette = CRGBPalette16(ter,sec,prim); break;}
case 5: {//primary + secondary (+tert if not off), more distinct
CRGB prim = col_to_crgb(SEGCOLOR(0));
CRGB sec = col_to_crgb(SEGCOLOR(1));
if (SEGCOLOR(2)) {
CRGB ter = col_to_crgb(SEGCOLOR(2));
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,ter,ter,ter,ter,ter,prim);
} else {
targetPalette = CRGBPalette16(prim,prim,prim,prim,prim,prim,prim,prim,sec,sec,sec,sec,sec,sec,sec,sec);
}
break;}
case 6: //Party colors
targetPalette = PartyColors_p; break;
case 7: //Cloud colors
@@ -790,7 +777,7 @@ void WS2812FX::handle_palette(void)
case 12: //Rainbow stripe colors
targetPalette = RainbowStripeColors_p; break;
default: //progmem palettes
targetPalette = gGradientPalettes[constrain(SEGMENT.palette -13, 0, gGradientPaletteCount -1)];
load_gradient_palette(SEGMENT.palette -13);
}
if (singleSegmentMode && paletteFade) //only blend if just one segment uses FastLED mode
@@ -825,7 +812,7 @@ bool WS2812FX::segmentsAreIdentical(Segment* a, Segment* b)
if (a->speed != b->speed) return false;
if (a->intensity != b->intensity) return false;
if (a->palette != b->palette) return false;
//if (a->getOption(1) != b->getOption(1)) return false; //reverse
//if (a->getOption(SEG_OPTION_REVERSED) != b->getOption(SEG_OPTION_REVERSED)) return false;
return true;
}
@@ -857,7 +844,9 @@ void WS2812FX::setRgbwPwm(void) {
}
#else
bus->SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);
#endif
#endif
_analogLastColor = color;
_analogLastBri = b;
}
#else
void WS2812FX::setRgbwPwm() {}

View File

@@ -4,25 +4,40 @@
//PIN CONFIGURATION
#ifndef LEDPIN
#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 or 3 is recommended for ESP8266 (gpio2/3 are labeled D4/RX on NodeMCU and Wemos)
#define LEDPIN 2 //strip pin. Any for ESP32, gpio2 or 3 is recommended for ESP8266 (gpio2/3 are labeled D4/RX on NodeMCU and Wemos)
#endif
//#define USE_APA102 // Uncomment for using APA102 LEDs.
//#define USE_WS2801 // Uncomment for using WS2801 LEDs (make sure you have NeoPixelBus v2.5.6 or newer)
//#define USE_LPD8806 // Uncomment for using LPD8806
//#define USE_TM1814 // Uncomment for using TM1814 LEDs (make sure you have NeoPixelBus v2.5.7 or newer)
//#define USE_P9813 // Uncomment for using P9813 LEDs (make sure you have NeoPixelBus v2.5.8 or newer)
//#define WLED_USE_ANALOG_LEDS //Uncomment for using "dumb" PWM controlled LEDs (see pins below, default R: gpio5, G: 12, B: 15, W: 13)
//#define WLED_USE_H801 //H801 controller. Please uncomment #define WLED_USE_ANALOG_LEDS as well
//#define WLED_USE_5CH_LEDS //5 Channel H801 for cold and warm white
#ifndef BTNPIN
#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended)
#define IR_PIN 4 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
#define RLYPIN 12 //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,...
#define AUXPIN -1 //debug auxiliary output pin (-1 to disable)
#endif
#define RLYMDE 1 //mode for relay, 0: LOW if LEDs are on 1: HIGH if LEDs are on
#ifndef IR_PIN
#define IR_PIN 4 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
#endif
#ifndef RLYPIN
#define RLYPIN 12 //pin for relay, will be set HIGH if LEDs are on (-1 to disable). Also usable for standby leds, triggers,...
#endif
#ifndef AUXPIN
#define AUXPIN -1 //debug auxiliary output pin (-1 to disable)
#endif
#ifndef RLYMDE
#define RLYMDE 1 //mode for relay, 0: LOW if LEDs are on 1: HIGH if LEDs are on
#endif
//END CONFIGURATION
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806)
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) || defined(USE_P9813)
#define CLKPIN 0
#define DATAPIN 2
#if BTNPIN == CLKPIN || BTNPIN == DATAPIN
@@ -41,12 +56,25 @@
#undef BTNPIN
#undef IR_PIN
#define IR_PIN 0 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
#elif defined(WLED_USE_BWLT11)
//PWM pins - to use with BW-LT11
#define RPIN 12 //R pin for analog LED strip
#define GPIN 4 //G pin for analog LED strip
#define BPIN 14 //B pin for analog LED strip
#define WPIN 5 //W pin for analog LED strip
#elif defined(SHOJO_PCB)
//PWM pins - to use with Shojo PCB (https://www.bastelbunker.de/esp-rgbww-wifi-led-controller-vbs-edition/)
#define RPIN 14 //R pin for analog LED strip
#define GPIN 4 //G pin for analog LED strip
#define BPIN 5 //B pin for analog LED strip
#define WPIN 15 //W pin for analog LED strip
#define W2PIN 12 //W2 pin for analog LED strip
#else
//PWM pins - PINs 5,12,13,15 are used with Magic Home LED Controller
#define RPIN 5 //R pin for analog LED strip
#define GPIN 12 //G pin for analog LED strip
#define BPIN 15 //B pin for analog LED strip
#define WPIN 13 //W pin for analog LED strip
#define RPIN 5 //R pin for analog LED strip
#define GPIN 12 //G pin for analog LED strip
#define BPIN 15 //B pin for analog LED strip
#define WPIN 13 //W pin for analog LED strip
#endif
#undef RLYPIN
#define RLYPIN -1 //disable as pin 12 is used by analog LEDs
@@ -60,6 +88,10 @@
#define PIXELMETHOD NeoWs2801Method
#elif defined(USE_LPD8806)
#define PIXELMETHOD Lpd8806Method
#elif defined(USE_TM1814)
#define PIXELMETHOD NeoTm1814Method
#elif defined(USE_P9813)
#define PIXELMETHOD P9813Method
#else
#define PIXELMETHOD NeoEsp32Rmt0Ws2812xMethod
#endif
@@ -71,6 +103,10 @@
#define PIXELMETHOD NeoWs2801Method
#elif defined(USE_LPD8806)
#define PIXELMETHOD Lpd8806Method
#elif defined(USE_TM1814)
#define PIXELMETHOD NeoTm1814Method
#elif defined(USE_P9813)
#define PIXELMETHOD P9813Method
#elif LEDPIN == 2
#define PIXELMETHOD NeoEsp8266Uart1Ws2813Method //if you get an error here, try to change to NeoEsp8266UartWs2813Method or update Neopixelbus
#elif LEDPIN == 3
@@ -88,7 +124,13 @@
#define PIXELFEATURE4 DotStarLbgrFeature
#elif defined(USE_LPD8806)
#define PIXELFEATURE3 Lpd8806GrbFeature
#define PIXELFEATURE4 Lpd8806GrbFeature
#define PIXELFEATURE4 Lpd8806GrbFeature
#elif defined(USE_TM1814)
#define PIXELFEATURE3 NeoWrgbTm1814Feature
#define PIXELFEATURE4 NeoWrgbTm1814Feature
#elif defined(USE_P9813)
#define PIXELFEATURE3 P9813BgrFeature
#define PIXELFEATURE4 NeoGrbwFeature
#else
#define PIXELFEATURE3 NeoGrbFeature
#define PIXELFEATURE4 NeoGrbwFeature
@@ -130,7 +172,7 @@ public:
switch (_type)
{
case NeoPixelType_Grb:
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806)
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) || defined(USE_P9813)
_pGrb = new NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>(countPixels, CLKPIN, DATAPIN);
#else
_pGrb = new NeoPixelBrightnessBus<PIXELFEATURE3,PIXELMETHOD>(countPixels, LEDPIN);
@@ -139,7 +181,7 @@ public:
break;
case NeoPixelType_Grbw:
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806)
#if defined(USE_APA102) || defined(USE_WS2801) || defined(USE_LPD8806) || defined(USE_P9813)
_pGrbw = new NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>(countPixels, CLKPIN, DATAPIN);
#else
_pGrbw = new NeoPixelBrightnessBus<PIXELFEATURE4,PIXELMETHOD>(countPixels, LEDPIN);

View File

@@ -17,8 +17,10 @@
#define __ESP32_ESP32__
#define ESP_PLATFORM
#define HAVE_CONFIG_H
#define GCC_NOT_5_2_0 0
#define WITH_POSIX
#define F_CPU 240000000L
#define ARDUINO 10809
#define ARDUINO 108011
#define ARDUINO_ESP32_DEV
#define ARDUINO_ARCH_ESP32
#define ESP32
@@ -92,18 +94,11 @@ typedef long pthread_cond_t;
#include "arduino.h"
#include <pins_arduino.h>
//#include "..\generic\Common.h"
//#include "..\generic\pins_arduino.h"
//#undef F
//#define F(string_literal) ((const PROGMEM char *)(string_literal))
//#undef PSTR
//#define PSTR(string_literal) ((const PROGMEM char *)(string_literal))
//current vc++ does not understand this syntax so use older arduino example for intellisense
//todo:move to the new clang/gcc project types.
#define interrupts() sei()
#define noInterrupts() cli()
#define ESP_LOGI(tag, ...)
#include "wled00.ino"
#include "wled01_eeprom.ino"
#include "wled02_xml.ino"

File diff suppressed because one or more lines are too long

View File

@@ -1,10 +1,13 @@
#include "wled.h"
/*
* Alexa Voice On/Off/Brightness Control. Emulates a Philips Hue bridge to Alexa.
* Alexa Voice On/Off/Brightness/Color Control. Emulates a Philips Hue bridge to Alexa.
*
* This was put together from these two excellent projects:
* https://github.com/kakopappa/arduino-esp8266-alexa-wemo-switch
* https://github.com/probonopd/ESP8266HueEmulator
*/
#include "src/dependencies/espalexa/EspalexaDevice.h"
#ifndef WLED_DISABLE_ALEXA
void onAlexaChange(EspalexaDevice* dev);
@@ -61,12 +64,28 @@ void onAlexaChange(EspalexaDevice* dev)
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
} else //color
{
uint32_t color = espalexaDevice->getRGB();
col[3] = ((color >> 24) & 0xFF); // white color from Alexa is "pure white only"
col[0] = ((color >> 16) & 0xFF);
col[1] = ((color >> 8) & 0xFF);
col[2] = (color & 0xFF);
if (useRGBW && col[3] == 0) colorRGBtoRGBW(col); // do not touch white value if EspalexaDevice.cpp did set the white channel
if (espalexaDevice->getColorMode() == EspalexaColorMode::ct) //shade of white
{
uint16_t ct = espalexaDevice->getCt();
if (useRGBW)
{
switch (ct) { //these values empirically look good on RGBW
case 199: col[0]=255; col[1]=255; col[2]=255; col[3]=255; break;
case 234: col[0]=127; col[1]=127; col[2]=127; col[3]=255; break;
case 284: col[0]= 0; col[1]= 0; col[2]= 0; col[3]=255; break;
case 350: col[0]=130; col[1]= 90; col[2]= 0; col[3]=255; break;
case 383: col[0]=255; col[1]=153; col[2]= 0; col[3]=255; break;
}
} else {
colorCTtoRGB(ct, col);
}
} else {
uint32_t color = espalexaDevice->getRGB();
col[0] = ((color >> 16) & 0xFF);
col[1] = ((color >> 8) & 0xFF);
col[2] = ( color & 0xFF);
}
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
}
}

View File

@@ -1,3 +1,6 @@
#include "wled.h"
#include "src/dependencies/blynk/Blynk/BlynkHandlers.h"
/*
* Remote light control with the free Blynk app
*/

View File

@@ -1,3 +1,5 @@
#include "wled.h"
/*
* Physical IO
*/
@@ -44,7 +46,7 @@ void handleButton()
if (dur > 6000) //long press
{
initAP(true);
WLED::instance().initAP(true);
}
else if (!buttonLongPressed) { //short press
if (macroDoublePress)

View File

@@ -1,3 +1,5 @@
#include "wled.h"
/*
* Color conversion methods
*/
@@ -18,7 +20,7 @@ void colorFromUint32(uint32_t in, bool secondary)
}
//load a color without affecting the white channel
void colorFromUint24(uint32_t in, bool secondary = false)
void colorFromUint24(uint32_t in, bool secondary)
{
if (secondary) {
colSec[0] = in >> 16 & 0xFF;
@@ -32,7 +34,7 @@ void colorFromUint24(uint32_t in, bool secondary = false)
}
//relatively change white brightness, minumum A=5
void relativeChangeWhite(int8_t amount, byte lowerBoundary =0)
void relativeChangeWhite(int8_t amount, byte lowerBoundary)
{
int16_t new_val = (int16_t) col[3] + amount;
if (new_val > 0xFF) new_val = 0xFF;
@@ -57,10 +59,9 @@ void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb
case 4: rgb[0]=t,rgb[1]=p,rgb[2]=255;break;
case 5: rgb[0]=255,rgb[1]=p,rgb[2]=q;
}
if (useRGBW) colorRGBtoRGBW(col);
if (useRGBW && strip.rgbwMode == RGBW_MODE_LEGACY) colorRGBtoRGBW(col);
}
#ifndef WLED_DISABLE_HUESYNC
void colorCTtoRGB(uint16_t mired, byte* rgb) //white spectrum to rgb
{
//this is only an approximation using WS2812B with gamma correction enabled
@@ -81,9 +82,10 @@ void colorCTtoRGB(uint16_t mired, byte* rgb) //white spectrum to rgb
} else {
rgb[0]=237;rgb[1]=255;rgb[2]=239;//150
}
if (useRGBW) colorRGBtoRGBW(col);
if (useRGBW && strip.rgbwMode == RGBW_MODE_LEGACY) colorRGBtoRGBW(col);
}
#ifndef WLED_DISABLE_HUESYNC
void colorXYtoRGB(float x, float y, byte* rgb) //coordinates to rgb (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
{
float z = 1.0f - x - y;
@@ -149,7 +151,8 @@ void colorRGBtoXY(byte* rgb, float* xy) //rgb to coordinates (https://www.develo
xy[0] = X / (X + Y + Z);
xy[1] = Y / (X + Y + Z);
}
#endif
#endif // WLED_DISABLE_HUESYNC
void colorFromDecOrHexString(byte* rgb, char* in)
{

View File

@@ -1,5 +1,14 @@
#ifndef wled_const_h
#define wled_const_h
#ifndef WLED_CONST_H
#define WLED_CONST_H
/*
* Readability defines and their associated numerical values + compile-time constants
*/
//Defaults
#define DEFAULT_CLIENT_SSID "Your_Network"
#define DEFAULT_AP_PASS "wled1234"
#define DEFAULT_OTA_PASS "wledota"
//Access point behavior
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
@@ -8,13 +17,13 @@
#define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec
//Notifier callMode
#define NOTIFIER_CALL_MODE_INIT 0 // no updates on init, can be used to disable updates
#define NOTIFIER_CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
#define NOTIFIER_CALL_MODE_DIRECT_CHANGE 1
#define NOTIFIER_CALL_MODE_BUTTON 2
#define NOTIFIER_CALL_MODE_NOTIFICATION 3
#define NOTIFIER_CALL_MODE_NIGHTLIGHT 4
#define NOTIFIER_CALL_MODE_NO_NOTIFY 5
#define NOTIFIER_CALL_MODE_FX_CHANGED 6
#define NOTIFIER_CALL_MODE_FX_CHANGED 6 //no longer used
#define NOTIFIER_CALL_MODE_HUE 7
#define NOTIFIER_CALL_MODE_PRESET_CYCLE 8
#define NOTIFIER_CALL_MODE_BLYNK 9
@@ -34,13 +43,65 @@
#define REALTIME_MODE_HYPERION 3
#define REALTIME_MODE_E131 4
#define REALTIME_MODE_ADALIGHT 5
#define REALTIME_MODE_ARTNET 6
//realtime override modes
#define REALTIME_OVERRIDE_NONE 0
#define REALTIME_OVERRIDE_ONCE 1
#define REALTIME_OVERRIDE_ALWAYS 2
//E1.31 DMX modes
#define DMX_MODE_DISABLED 0 //not used
#define DMX_MODE_SINGLE_RGB 1 //all LEDs same RGB color (3 channels)
#define DMX_MODE_SINGLE_DRGB 2 //all LEDs same RGB color and master dimmer (4 channels)
#define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (11 channels)
#define DMX_MODE_MULTIPLE_RGB 4 //every LED is addressed with its own RGB (ledCount * 3 channels)
#define DMX_MODE_MULTIPLE_DRGB 5 //every LED is addressed with its own RGB and share a master dimmer (ledCount * 3 + 1 channels)
#define DMX_MODE_DISABLED 0 //not used
#define DMX_MODE_SINGLE_RGB 1 //all LEDs same RGB color (3 channels)
#define DMX_MODE_SINGLE_DRGB 2 //all LEDs same RGB color and master dimmer (4 channels)
#define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (11 channels)
#define DMX_MODE_MULTIPLE_RGB 4 //every LED is addressed with its own RGB (ledCount * 3 channels)
#define DMX_MODE_MULTIPLE_DRGB 5 //every LED is addressed with its own RGB and share a master dimmer (ledCount * 3 + 1 channels)
//Light capability byte (unused)
#define TYPE_NONE 0 //light is not configured
#define TYPE_RESERVED 1 //unused. Might indicate a "virtual" light
#define TYPE_WS2812_RGB 2
#define TYPE_SK6812_RGBW 3
#define TYPE_WS2812_WWA 4 //amber + warm + cold white
#define TYPE_WS2801 5
#define TYPE_ANALOG_1CH 6 //single channel PWM. Uses value of brightest RGBW channel
#define TYPE_ANALOG_2CH 7 //analog WW + CW
#define TYPE_ANALOG_3CH 8 //analog RGB
#define TYPE_ANALOG_4CH 9 //analog RGBW
#define TYPE_ANALOG_5CH 10 //analog RGB + WW + CW
#define TYPE_APA102 11
#define TYPE_LPD8806 12
//Hue error codes
#define HUE_ERROR_INACTIVE 0
#define HUE_ERROR_UNAUTHORIZED 1
#define HUE_ERROR_LIGHTID 3
#define HUE_ERROR_PUSHLINK 101
#define HUE_ERROR_JSON_PARSING 250
#define HUE_ERROR_TIMEOUT 251
#define HUE_ERROR_ACTIVE 255
//Segment option byte bits
#define SEG_OPTION_SELECTED 0
#define SEG_OPTION_REVERSED 1
#define SEG_OPTION_ON 2
#define SEG_OPTION_TRANSITIONAL 7
//EEPROM size
#define EEPSIZE 2560 //Maximum is 4096
#define NTP_PACKET_SIZE 48
// maximum number of LEDs - MAX_LEDS is coming from the JSON response getting too big, MAX_LEDS_DMA will become a timing issue
#define MAX_LEDS 1500
#define MAX_LEDS_DMA 500
// string temp buffer (now stored in stack locally)
#define OMAX 2048
#define E131_MAX_UNIVERSE_COUNT 9
#define ABL_MILLIAMPS_DEFAULT 850; // auto lower brightness to stay close to milliampere limit
#endif

File diff suppressed because one or more lines are too long

View File

@@ -88,12 +88,12 @@
<button type="button" onclick="U()">Manual OTA Update</button><br>
Enable ArduinoOTA: <input type="checkbox" name="AO"><br>
<h3>About</h3>
<a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.9.0<br><br>
<a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.10.0<br><br>
<a href="https://github.com/Aircoookie/WLED/wiki/Contributors-&-About" target="_blank">Contributors, dependencies and special thanks</a><br>
A huge thank you to everyone who helped me create WLED!<br><br>
(c) 2016-2019 Christian Schwinne <br>
<i>Licensed under the MIT license</i><br><br>
Server message: <span class="msg"> Response error! </span><hr>
Server message: <span class="sip"> Response error! </span><hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save & Reboot</button>
</form>
</body>

View File

@@ -1,140 +1,105 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=500">
<title>Sync Settings</title>
<script>
function H()
{
window.open("https://github.com/Aircoookie/WLED/wiki/Settings#sync-settings");
}
function B()
{
window.open("/settings","_self");
}
function GetV()
{
//values injected by server while sending HTML
}
</script>
<style>
:root {
--aCol: #abc;
--bCol: #fff;
--cCol: #ddd;
--dCol: #000;
--sCol: #0004;
}
body {
font-family: Verdana, Helvetica, sans-serif;
text-align: center;
background: var(--cCol);
color: var(--dCol);
line-height: 200%;
margin: 0;
background-attachment: fixed;
}
hr {
border-color: var(--dCol);
filter: drop-shadow( -5px -5px 5px var(--sCol) );
}
button {
background: var(--bCol);
color: var(--dCol);
border: 0.3ch solid var(--bCol);
display: inline-block;
filter: drop-shadow( -5px -5px 5px var(--sCol) );
font-size: 20px;
margin: 8px;
margin-top: 12px;
}
.helpB {
text-align: left;
position: absolute;
width:60px;
}
input {
background: var(--bCol);
color: var(--dCol);
border: 0.5ch solid var(--bCol);
filter: drop-shadow( -5px -5px 5px var(--sCol) );
}
input[type=number] {
width: 3em;
}
</style>
</head>
<body onload="GetV()">
<form id="form_s" name="Sf" method="post">
<div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
<h2>Sync setup</h2>
<h3>Button setup</h3>
On/Off button enabled: <input type="checkbox" name="BT"><br>
Infrared receiver enabled: <input type="checkbox" name="IR"><br>
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a>
<h3>WLED Sync UDP Broadcast</h3>
UDP Port: <input name="UP" type="number" min="1" max="65535" required><br>
Receive <input type="checkbox" name="RB">Brightness, <input type="checkbox" name="RC">Color, and <input type="checkbox" name="RX">Effects<br>
Send notifications on direct change: <input type="checkbox" name="SD"><br>
Send notifications on button press: <input type="checkbox" name="SB"><br>
Send Alexa notifications: <input type="checkbox" name="SA"><br>
Send Philips Hue change notifications: <input type="checkbox" name="SH"><br>
Send Macro notifications: <input type="checkbox" name="SM"><br>
Send notifications twice: <input type="checkbox" name="S2">
<h3>Realtime</h3>
Receive UDP realtime: <input type="checkbox" name="RD"><br><br>
E1.31 (sACN)<br>
Multicast mode: <input type="checkbox" name="EM"><br>
E1.31 start universe: <input name="EU" type="number" min="1" max="63999" required><br>
<i>Reboot required.</i> Check out <a href="https://github.com/ahodges9/LedFx" target="_blank">LedFx</a>!<br><br>
DMX start address: <input name="DA" type="number" min="1" max="510" value="1" required><br>
DMX mode: <input name="DM" type="radio" value="0"> disabled<br>
<input name="DM" type="radio" value="1"> Single RGB (3 Channels for all LEDs: Red Green Blue)<br>
<input name="DM" type="radio" value="2"> Single DRGB (4 Channels for all LEDs: Dimmer Red Green Blue)<br>
<input name="DM" type="radio" value="3"> Effect (11 Channels parametrizing Effects: Dimmer Effect Speed Intensity Palette PriRed PriGreen PriBlue SecRed SecGreen SecBlue)<br>
<input name="DM" type="radio" value="4"> Multiple RGB (3 Channels for each LED: Red Green Blue)<br>
<input name="DM" type="radio" value="5"> Multiple DRGB (1+3 Channels for each LED: Dimmer Red1 Green1 Blue1 Red2 Green2 Blue2...)<br>
<i>Reboot required.</i> Check out <a href="https://github.com/ahodges9/LedFx" target="_blank">LedFx</a>!<br><br>
Timeout: <input name="ET" type="number" min="100" max="65000" required> ms<br>
Force max brightness: <input type="checkbox" name="FB"><br>
Disable realtime gamma correction: <input type="checkbox" name="RG"><br>
Realtime LED offset: <input name="WO" type="number" min="-255" max="255" required>
<h3>Alexa Voice Assistant</h3>
Emulate Alexa device: <input type="checkbox" name="AL"><br>
Alexa invocation name: <input name="AI" maxlength="32">
<h3>Blynk</h3>
<b>Blynk, MQTT and Hue sync all connect to external hosts!<br>
This may impact the responsiveness of the ESP8266.</b><br>
For best results, only use one of these services at a time.<br>
(alternatively, connect a second ESP to them and use the UDP sync)<br><br>
Device Auth token: <input name="BK" maxlength="33"><br>
<i>Clear the token field to disable. </i><a href="https://github.com/Aircoookie/WLED/wiki/Blynk" target="_blank">Setup info</a>
<h3>MQTT</h3>
Enable MQTT: <input type="checkbox" name="MQ"><br>
Broker: <input name="MS" maxlength="32"><br>
Port: <input name="MQPORT" type="number" min="1" max="65535"><br>
<b>The MQTT credentials are sent over an unsecured connection.<br>
Never use the MQTT password for another service!</b><br>
Username: <input name="MQTTUSER" maxlength="32"><br>
Password: <input type="password" input name="MQTTPASS" maxlength="32"><br>
Client ID: <input name="MQTTCID" maxlength="32"><br>
Device Topic: <input name="MD" maxlength="32"><br>
Group Topic: <input name="MG" maxlength="32"><br>
<a href="https://github.com/Aircoookie/WLED/wiki/MQTT" target="_blank">MQTT info</a>
<h3>Philips Hue</h3>
<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
Poll Hue light <input name="HL" type="number" min="1" max="99"> every <input name="HI" type="number" min="100" max="65000"> ms: <input type="checkbox" name="HP"><br>
Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br>
Hue Bridge IP:<br>
<input name="H0" type="number" min="0" max="255"> .
<input name="H1" type="number" min="0" max="255"> .
<input name="H2" type="number" min="0" max="255"> .
<input name="H3" type="number" min="0" max="255"><br>
<b>Press the pushlink button on the bridge, after that save this page!</b><br>
(when first connecting)<br>
Hue status: <span class="hms"> Internal ESP Error! </span><hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form>
<html><head><meta name="viewport" content="width=500"><meta charset="utf-8"><title>Sync Settings</title>
<script>var d=document;
function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#sync-settings");}function B(){window.open("/settings","_self");}function GetV(){var d=document;}
function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.DA.value == 1) d.Sf.DA.value = 0; if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
else if (d.Sf.DI.value == 5568) {if (d.Sf.DA.value == 0) d.Sf.DA.value = 1; if (d.Sf.EU.value == 0) d.Sf.EU.value = 1;} }
function SP(){var p = d.Sf.DI.value; d.getElementById("xp").style.display = (p > 0)?"none":"block"; if (p > 0) d.Sf.EP.value = p;}
function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568: d.Sf.DI.value = 5568; break; case 6454: d.Sf.DI.value = 6454; break; }; SP();}
function S(){GetV();SetVal();}
</script>
<style>body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%;margin:0}hr{border-color:#666}button{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}.helpB{text-align:left;position:absolute;width:60px}input{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.5ch solid #333}input[type=number]{width:4em}select{background:#333;color:#fff;font-family:Verdana,sans-serif;border:0.5ch solid #333}td{padding:2px;}.d5{width:4.5em !important;}</style></head>
<body onload="S()">
<form id="form_s" name="Sf" method="post">
<div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
<h2>Sync setup</h2>
<h3>Button setup</h3>
On/Off button enabled: <input type="checkbox" name="BT"><br>
Infrared remote:
<select name=IR>
<option value=0>Disabled</option>
<option value=1>24-key RGB</option>
<option value=2>24-key with CT</option>
<option value=3>40-key blue</option>
<option value=4>44-key RGB</option>
<option value=5>21-key RGB</option>
<option value=6>6-key black</option>
</select><br>
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a>
<h3>WLED Broadcast</h3>
UDP Port: <input name="UP" type="number" min="1" max="65535" class="d5" required><br>
Receive <input type="checkbox" name="RB">Brightness, <input type="checkbox" name="RC">Color, and <input type="checkbox" name="RX">Effects<br>
Send notifications on direct change: <input type="checkbox" name="SD"><br>
Send notifications on button press: <input type="checkbox" name="SB"><br>
Send Alexa notifications: <input type="checkbox" name="SA"><br>
Send Philips Hue change notifications: <input type="checkbox" name="SH"><br>
Send Macro notifications: <input type="checkbox" name="SM"><br>
Send notifications twice: <input type="checkbox" name="S2">
<h3>Realtime</h3>
Receive UDP realtime: <input type="checkbox" name="RD"><br><br>
<i>Network DMX input</i><br>
Type:
<select name=DI onchange="SP(); adj();">
<option value=5568>E1.31 (sACN)</option>
<option value=6454>Art-Net</option>
<option value=0 selected>Custom port</option>
</select><br>
<div id=xp>Port: <input name="EP" type="number" min="1" max="65535" value="5568" class="d5" required><br></div>
Multicast: <input type="checkbox" name="EM"><br>
Start universe: <input name="EU" type="number" min="0" max="63999" required><br>
<i>Reboot required.</i> Check out <a href="https://github.com/ahodges9/LedFx" target="_blank">LedFx</a>!<br>
Skip out-of-sequence packets: <input type="checkbox" name="ES"><br>
DMX start address: <input name="DA" type="number" min="0" max="510" required><br>
DMX mode:
<select name=DM>
<option value=0>Disabled</option>
<option value=1>Single RGB</option>
<option value=2>Single DRGB</option>
<option value=3>Effect</option>
<option value=4>Multi RGB</option>
<option value=5>Multi DRGB</option>
</select><br>
<a href="https://github.com/Aircoookie/WLED/wiki/E1.31-DMX" target="_blank">E1.31 info</a><br>
Timeout: <input name="ET" type="number" min="1" max="65000" required> ms<br>
Force max brightness: <input type="checkbox" name="FB"><br>
Disable realtime gamma correction: <input type="checkbox" name="RG"><br>
Realtime LED offset: <input name="WO" type="number" min="-255" max="255" required>
<h3>Alexa Voice Assistant</h3>
Emulate Alexa device: <input type="checkbox" name="AL"><br>
Alexa invocation name: <input name="AI" maxlength="32">
<h3>Blynk</h3>
<b>Blynk, MQTT and Hue sync all connect to external hosts!<br>
This may impact the responsiveness of the ESP8266.</b><br>
For best results, only use one of these services at a time.<br>
(alternatively, connect a second ESP to them and use the UDP sync)<br><br>
Device Auth token: <input name="BK" maxlength="33"><br>
<i>Clear the token field to disable. </i><a href="https://github.com/Aircoookie/WLED/wiki/Blynk" target="_blank">Setup info</a>
<h3>MQTT</h3>
Enable MQTT: <input type="checkbox" name="MQ"><br>
Broker: <input name="MS" maxlength="32">
Port: <input name="MQPORT" type="number" min="1" max="65535" class="d5"><br>
<b>The MQTT credentials are sent over an unsecured connection.<br>
Never use the MQTT password for another service!</b><br>
Username: <input name="MQUSER" maxlength="40"><br>
Password: <input type="password" input name="MQPASS" maxlength="40"><br>
Client ID: <input name="MQCID" maxlength="40"><br>
Device Topic: <input name="MD" maxlength="32"><br>
Group Topic: <input name="MG" maxlength="32"><br>
<i>Reboot required to apply changes. </i><a href="https://github.com/Aircoookie/WLED/wiki/MQTT" target="_blank">MQTT info</a>
<h3>Philips Hue</h3>
<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
Poll Hue light <input name="HL" type="number" min="1" max="99" > every <input name="HI" type="number" min="100" max="65000"> ms: <input type="checkbox" name="HP"><br>
Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br>
Hue Bridge IP:<br>
<input name="H0" type="number" min="0" max="255" > .
<input name="H1" type="number" min="0" max="255" > .
<input name="H2" type="number" min="0" max="255" > .
<input name="H3" type="number" min="0" max="255" ><br>
<b>Press the pushlink button on the bridge, after that save this page!</b><br>
(when first connecting)<br>
Hue status: <span class="hms"> Disabled in this build </span><hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form>
</body>
</html>

67
wled00/dmx.cpp Normal file
View File

@@ -0,0 +1,67 @@
#include "wled.h"
/*
* Support for DMX via MAX485.
* Change the output pin in src/dependencies/ESPDMX.cpp if needed.
* Library from:
* https://github.com/Rickgg/ESP-Dmx
*/
#ifdef WLED_ENABLE_DMX
#include "src/dependencies/dmx/ESPDMX.h"
DMXESPSerial dmx;
void handleDMX()
{
// TODO: calculate brightness manually if no shutter channel is set
uint8_t brightness = strip.getBrightness();
for (int i = DMXStartLED; i < ledCount; i++) { // uses the amount of LEDs as fixture count
uint32_t in = strip.getPixelColor(i); // get the colors for the individual fixtures as suggested by Aircoookie in issue #462
byte w = in >> 24 & 0xFF;
byte r = in >> 16 & 0xFF;
byte g = in >> 8 & 0xFF;
byte b = in & 0xFF;
int DMXFixtureStart = DMXStart + (DMXGap * (i - DMXStartLED));
for (int j = 0; j < DMXChannels; j++) {
int DMXAddr = DMXFixtureStart + j;
switch (DMXFixtureMap[j]) {
case 0: // Set this channel to 0. Good way to tell strobe- and fade-functions to fuck right off.
dmx.write(DMXAddr, 0);
break;
case 1: // Red
dmx.write(DMXAddr, r);
break;
case 2: // Green
dmx.write(DMXAddr, g);
break;
case 3: // Blue
dmx.write(DMXAddr, b);
break;
case 4: // White
dmx.write(DMXAddr, w);
break;
case 5: // Shutter channel. Controls the brightness.
dmx.write(DMXAddr, brightness);
break;
case 6: // Sets this channel to 255. Like 0, but more wholesome.
dmx.write(DMXAddr, 255);
break;
}
}
}
dmx.update(); // update the DMX bus
}
void initDMX() {
dmx.init(512); // initialize with bus length
}
#else
void handleDMX() {}
void initDMX() {}
#endif

167
wled00/e131.cpp Normal file
View File

@@ -0,0 +1,167 @@
#include "wled.h"
/*
* E1.31 handler
*/
void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet){
//E1.31 protocol support
uint16_t uni = 0, dmxChannels = 0;
uint8_t* e131_data = nullptr;
uint8_t seq = 0, mde = REALTIME_MODE_E131;
if (isArtnet)
{
uni = p->art_universe;
dmxChannels = htons(p->art_length);
e131_data = p->art_data;
seq = p->art_sequence_number;
mde = REALTIME_MODE_ARTNET;
} else {
uni = htons(p->universe);
dmxChannels = htons(p->property_value_count) -1;
e131_data = p->property_values;
seq = p->sequence_number;
}
// only listen for universes we're handling & allocated memory
if (uni >= (e131Universe + E131_MAX_UNIVERSE_COUNT)) return;
uint8_t previousUniverses = uni - e131Universe;
uint16_t possibleLEDsInCurrentUniverse;
if (e131SkipOutOfSequence)
if (seq < e131LastSequenceNumber[uni-e131Universe] && seq > 20 && e131LastSequenceNumber[uni-e131Universe] < 250){
DEBUG_PRINT("skipping E1.31 frame (last seq=");
DEBUG_PRINT(e131LastSequenceNumber[uni-e131Universe]);
DEBUG_PRINT(", current seq=");
DEBUG_PRINT(seq);
DEBUG_PRINT(", universe=");
DEBUG_PRINT(uni);
DEBUG_PRINTLN(")");
return;
}
e131LastSequenceNumber[uni-e131Universe] = seq;
// update status info
realtimeIP = clientIP;
byte wChannel = 0;
switch (DMXMode) {
case DMX_MODE_DISABLED:
return; // nothing to do
break;
case DMX_MODE_SINGLE_RGB:
if (uni != e131Universe) return;
if (dmxChannels-DMXAddress+1 < 3) return;
realtimeLock(realtimeTimeoutMs, mde);
if (realtimeOverride) return;
wChannel = (dmxChannels-DMXAddress+1 > 3) ? e131_data[DMXAddress+3] : 0;
for (uint16_t i = 0; i < ledCount; i++)
setRealtimePixel(i, e131_data[DMXAddress+0], e131_data[DMXAddress+1], e131_data[DMXAddress+2], wChannel);
break;
case DMX_MODE_SINGLE_DRGB:
if (uni != e131Universe) return;
if (dmxChannels-DMXAddress+1 < 4) return;
realtimeLock(realtimeTimeoutMs, mde);
if (realtimeOverride) return;
wChannel = (dmxChannels-DMXAddress+1 > 4) ? e131_data[DMXAddress+4] : 0;
if (DMXOldDimmer != e131_data[DMXAddress+0]) {
DMXOldDimmer = e131_data[DMXAddress+0];
bri = e131_data[DMXAddress+0];
strip.setBrightness(bri);
}
for (uint16_t i = 0; i < ledCount; i++)
setRealtimePixel(i, e131_data[DMXAddress+1], e131_data[DMXAddress+2], e131_data[DMXAddress+3], wChannel);
break;
case DMX_MODE_EFFECT:
if (uni != e131Universe) return;
if (dmxChannels-DMXAddress+1 < 11) return;
if (DMXOldDimmer != e131_data[DMXAddress+0]) {
DMXOldDimmer = e131_data[DMXAddress+0];
bri = e131_data[DMXAddress+0];
}
if (e131_data[DMXAddress+1] < MODE_COUNT)
effectCurrent = e131_data[DMXAddress+ 1];
effectSpeed = e131_data[DMXAddress+ 2]; // flickers
effectIntensity = e131_data[DMXAddress+ 3];
effectPalette = e131_data[DMXAddress+ 4];
col[0] = e131_data[DMXAddress+ 5];
col[1] = e131_data[DMXAddress+ 6];
col[2] = e131_data[DMXAddress+ 7];
colSec[0] = e131_data[DMXAddress+ 8];
colSec[1] = e131_data[DMXAddress+ 9];
colSec[2] = e131_data[DMXAddress+10];
if (dmxChannels-DMXAddress+1 > 11)
{
col[3] = e131_data[DMXAddress+11]; //white
colSec[3] = e131_data[DMXAddress+12];
}
transitionDelayTemp = 0; // act fast
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); // don't send UDP
return; // don't activate realtime live mode
break;
case DMX_MODE_MULTIPLE_RGB:
realtimeLock(realtimeTimeoutMs, mde);
if (realtimeOverride) return;
if (previousUniverses == 0) {
// first universe of this fixture
possibleLEDsInCurrentUniverse = (dmxChannels - DMXAddress + 1) / 3;
for (uint16_t i = 0; i < ledCount; i++) {
if (i >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
setRealtimePixel(i, e131_data[DMXAddress+i*3+0], e131_data[DMXAddress+i*3+1], e131_data[DMXAddress+i*3+2], 0);
}
} else if (previousUniverses > 0 && uni < (e131Universe + E131_MAX_UNIVERSE_COUNT)) {
// additional universe(s) of this fixture
uint16_t numberOfLEDsInPreviousUniverses = ((512 - DMXAddress + 1) / 3); // first universe
if (previousUniverses > 1) numberOfLEDsInPreviousUniverses += (512 / 3) * (previousUniverses - 1); // extended universe(s) before current
possibleLEDsInCurrentUniverse = dmxChannels / 3;
for (uint16_t i = numberOfLEDsInPreviousUniverses; i < ledCount; i++) {
uint8_t j = i - numberOfLEDsInPreviousUniverses;
if (j >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
setRealtimePixel(i, e131_data[j*3+1], e131_data[j*3+2], e131_data[j*3+3], 0);
}
}
break;
case DMX_MODE_MULTIPLE_DRGB:
realtimeLock(realtimeTimeoutMs, mde);
if (realtimeOverride) return;
if (previousUniverses == 0) {
// first universe of this fixture
if (DMXOldDimmer != e131_data[DMXAddress+0]) {
DMXOldDimmer = e131_data[DMXAddress+0];
bri = e131_data[DMXAddress+0];
strip.setBrightness(bri);
}
possibleLEDsInCurrentUniverse = (dmxChannels - DMXAddress) / 3;
for (uint16_t i = 0; i < ledCount; i++) {
if (i >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
setRealtimePixel(i, e131_data[DMXAddress+i*3+1], e131_data[DMXAddress+i*3+2], e131_data[DMXAddress+i*3+3], 0);
}
} else if (previousUniverses > 0 && uni < (e131Universe + E131_MAX_UNIVERSE_COUNT)) {
// additional universe(s) of this fixture
uint16_t numberOfLEDsInPreviousUniverses = ((512 - DMXAddress + 1) / 3); // first universe
if (previousUniverses > 1) numberOfLEDsInPreviousUniverses += (512 / 3) * (previousUniverses - 1); // extended universe(s) before current
possibleLEDsInCurrentUniverse = dmxChannels / 3;
for (uint16_t i = numberOfLEDsInPreviousUniverses; i < ledCount; i++) {
uint8_t j = i - numberOfLEDsInPreviousUniverses;
if (j >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
setRealtimePixel(i, e131_data[j*3+1], e131_data[j*3+2], e131_data[j*3+3], 0);
}
}
break;
default:
DEBUG_PRINTLN("unknown E1.31 DMX mode");
return; // nothing to do
break;
}
e131NewData = true;
}

184
wled00/fcn_declare.h Normal file
View File

@@ -0,0 +1,184 @@
#ifndef WLED_FCN_DECLARE_H
#define WLED_FCN_DECLARE_H
#include <Arduino.h>
#include "src/dependencies/espalexa/EspalexaDevice.h"
#include "src/dependencies/e131/ESPAsyncE131.h"
/*
* All globally accessible functions are declared here
*/
//alexa.cpp
void onAlexaChange(EspalexaDevice* dev);
void alexaInit();
void handleAlexa();
void onAlexaChange(EspalexaDevice* dev);
//blynk.cpp
void initBlynk(const char* auth);
void handleBlynk();
void updateBlynk();
//button.cpp
void shortPressAction();
void handleButton();
void handleIO();
//colors.cpp
void colorFromUint32(uint32_t in, bool secondary = false);
void colorFromUint24(uint32_t in, bool secondary = false);
void relativeChangeWhite(int8_t amount, byte lowerBoundary = 0);
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb); //hue, sat to rgb
void colorCTtoRGB(uint16_t mired, byte* rgb); //white spectrum to rgb
void colorXYtoRGB(float x, float y, byte* rgb); // only defined if huesync disabled TODO
void colorRGBtoXY(byte* rgb, float* xy); // only defined if huesync disabled TODO
void colorFromDecOrHexString(byte* rgb, char* in);
void colorRGBtoRGBW(byte* rgb); //rgb to rgbw (http://codewelt.com/rgbw). (RGBW_MODE_LEGACY)
//dmx.cpp
void initDMX();
void handleDMX();
//e131.cpp
void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet);
//file.cpp
bool handleFileRead(AsyncWebServerRequest*, String path);
//hue.cpp
void handleHue();
void reconnectHue();
void onHueError(void* arg, AsyncClient* client, int8_t error);
void onHueConnect(void* arg, AsyncClient* client);
void sendHuePoll();
void onHueData(void* arg, AsyncClient* client, void *data, size_t len);
//ir.cpp
bool decodeIRCustom(uint32_t code);
void relativeChange(byte* property, int8_t amount, byte lowerBoundary = 0, byte higherBoundary = 0xFF);
void changeEffectSpeed(int8_t amount);
void changeEffectIntensity(int8_t amount);
void decodeIR(uint32_t code);
void decodeIR24(uint32_t code);
void decodeIR24OLD(uint32_t code);
void decodeIR24CT(uint32_t code);
void decodeIR40(uint32_t code);
void decodeIR44(uint32_t code);
void decodeIR21(uint32_t code);
void decodeIR6(uint32_t code);
void initIR();
void handleIR();
//json.cpp
#include "ESPAsyncWebServer.h"
#include "src/dependencies/json/ArduinoJson-v6.h"
#include "src/dependencies/json/AsyncJson-v6.h"
#include "FX.h"
// TODO: AsynicWebServerRequest conflict?
void deserializeSegment(JsonObject elem, byte it);
bool deserializeState(JsonObject root);
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id);
void serializeState(JsonObject root);
void serializeInfo(JsonObject root);
void serveJson(AsyncWebServerRequest* request);
void serveLiveLeds(AsyncWebServerRequest* request);
//led.cpp
void setValuesFromMainSeg();
void resetTimebase();
void toggleOnOff();
void setAllLeds();
void setLedsStandard(bool justColors = false);
bool colorChanged();
void colorUpdated(int callMode);
void updateInterfaces(uint8_t callMode);
void handleTransitions();
void handleNightlight();
//mqtt.cpp
bool initMqtt();
void publishMqtt();
//ntp.cpp
void handleNetworkTime();
void sendNTPPacket();
bool checkNTPResponse();
void updateLocalTime();
void getTimeString(char* out);
bool checkCountdown();
void setCountdown();
byte weekdayMondayFirst();
void checkTimers();
//overlay.cpp
void initCronixie();
void handleOverlays();
void handleOverlayDraw();
void _overlayAnalogCountdown();
void _overlayAnalogClock();
byte getSameCodeLength(char code, int index, char const cronixieDisplay[]);
void setCronixie();
void _overlayCronixie();
void _drawOverlayCronixie();
//set.cpp
void _setRandomColor(bool _sec,bool fromButton=false);
bool isAsterisksOnly(const char* str, byte maxLen);
void handleSettingsSet(AsyncWebServerRequest *request, byte subPage);
bool handleSet(AsyncWebServerRequest *request, const String& req);
int getNumVal(const String* req, uint16_t pos);
bool updateVal(const String* req, const char* key, byte* val, byte minv=0, byte maxv=255);
//udp.cpp
void notify(byte callMode, bool followUp=false);
void realtimeLock(uint32_t timeoutMs, byte md = REALTIME_MODE_GENERIC);
void handleNotifications();
void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w);
//usermod.cpp
void userSetup();
void userConnected();
void userLoop();
//wled_eeprom.cpp
void commit();
void clearEEPROM();
void writeStringToEEPROM(uint16_t pos, char* str, uint16_t len);
void readStringFromEEPROM(uint16_t pos, char* str, uint16_t len);
void saveSettingsToEEPROM();
void loadSettingsFromEEPROM(bool first);
void savedToPresets();
bool applyPreset(byte index, bool loadBri = true);
void savePreset(byte index, bool persist = true);
void loadMacro(byte index, char* m);
void applyMacro(byte index);
void saveMacro(byte index, String mc, bool persist = true); //only commit on single save, not in settings
//wled_serial.cpp
void handleSerial();
//wled_server.cpp
bool isIp(String str);
bool captivePortal(AsyncWebServerRequest *request);
void initServer();
void serveIndexOrWelcome(AsyncWebServerRequest *request);
void serveIndex(AsyncWebServerRequest* request);
String msgProcessor(const String& var);
void serveMessage(AsyncWebServerRequest* request, uint16_t code, String headl, String subl="", byte optionT=255);
String settingsProcessor(const String& var);
String dmxProcessor(const String& var);
void serveSettings(AsyncWebServerRequest* request);
//xml.cpp
char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr);
char* URL_response(AsyncWebServerRequest *request);
void sappend(char stype, const char* key, int val);
void sappends(char stype, const char* key, char* val);
void getSettingsJS(byte subPage, char* dest);
#endif

55
wled00/file.cpp Normal file
View File

@@ -0,0 +1,55 @@
#include "wled.h"
/*
* Utility for SPIFFS filesystem
*/
//filesystem
#ifndef WLED_DISABLE_FILESYSTEM
#include <FS.h>
#ifdef ARDUINO_ARCH_ESP32
#include "SPIFFS.h"
#endif
#include "SPIFFSEditor.h"
#endif
#if !defined WLED_DISABLE_FILESYSTEM && defined WLED_ENABLE_FS_SERVING
//Un-comment any file types you need
String getContentType(AsyncWebServerRequest* request, String filename){
if(request->hasArg("download")) return "application/octet-stream";
else if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".html")) return "text/html";
// else if(filename.endsWith(".css")) return "text/css";
// else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".json")) return "application/json";
else if(filename.endsWith(".png")) return "image/png";
// else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
// else if(filename.endsWith(".xml")) return "text/xml";
// else if(filename.endsWith(".pdf")) return "application/x-pdf";
// else if(filename.endsWith(".zip")) return "application/x-zip";
// else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
bool handleFileRead(AsyncWebServerRequest* request, String path){
DEBUG_PRINTLN("FileRead: " + path);
if(path.endsWith("/")) path += "index.htm";
String contentType = getContentType(request, path);
String pathWithGz = path + ".gz";
if(SPIFFS.exists(pathWithGz)){
request->send(SPIFFS, pathWithGz, contentType);
return true;
}
if(SPIFFS.exists(path)) {
request->send(SPIFFS, path, contentType);
return true;
}
return false;
}
#else
bool handleFileRead(AsyncWebServerRequest*, String path){return false;}
#endif

View File

@@ -1,5 +1,5 @@
/*
* Various pages
* Various web pages
*/
//USER HTML HERE (/u subpage)
@@ -15,12 +15,42 @@ const char PAGE_msg[] PROGMEM = R"=====(<!DOCTYPE html>
<style>.bt{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%%;margin:0}</style></head>
<body><h2>%MSG%</body></html>)=====";
//DMX channel map
const char PAGE_dmxmap[] PROGMEM = R"=====(<!DOCTYPE html>
<html><head><meta content='width=device-width' name='viewport'>
<title>DMX Map</title>
<script>function B(){window.history.back()};function RS(){window.location = "/settings";}function RP(){top.location.href="/";}function FM() {%DMXVARS%
var dmxlabels = ["SET 0","RED","GREEN","BLUE","WHITE","SHUTTER","SET 255", "DISABLED"];
var dmxchans = [];
for (i=0;i<512;i++) {
dmxchans.push(7); // set all to DISABLED
}
for (i=0;i<LC;i++) {
FS = CS + (CG * i);
for (j=0;j<CN;j++) {
DA=FS+j;
dmxchans[DA-1] = CH[j];
}
}
DMXMap = "";
for (i=0;i<512;i++) {
isstart = "";
if ((i+1) % 10 == 0) {
isstart="S"
}
DMXMap += "<div class=\"anytype " + isstart + " type" + dmxchans[i] + "\">" + String(i+1) + "<br />" + dmxlabels[dmxchans[i]] + "</div>";
}
document.getElementById("map").innerHTML = DMXMap;
}</script>
<style>.anytype{border: 1px solid white; margin: 1px; float: left; width: 100px; height: 100px;}.S { margin: 0px; border: 2px solid white;} .type7{color: #888; border: 1px dotted grey;}.type6{color: #FFF;}.type4{color: #FFF; font-weight: bold; }.type3{color: #00F; font-weight: bold; }.type2{color: #0F0; font-weight: bold; }.type1{color: #F00; font-weight: bold; } .bt{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%%;margin:0}</style></head>
<body onload="FM();"><div id="map">...</div></body></html>)=====";
//firmware update page
const char PAGE_update[] PROGMEM = R"=====(<!DOCTYPE html>
<html><head><meta content='width=device-width' name='viewport'><title>WLED Update</title><script>function B(){window.history.back()}</script>
<style>.bt{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}input[type=file]{font-size:16px}body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%}</style></head>
<body><h2>WLED Software Update</h2>Installed version: 0.9.1<br>Download the latest binary: <a href="https://github.com/Aircoookie/WLED/releases"><img src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square"></a><br><form method='POST' action='/update' enctype='multipart/form-data'><input type='file' class="bt" name='update' required><br><input type='submit' class="bt" value='Update!'></form><button type="button" class="bt" onclick="B()">Back</button></body></html>)=====";
<body><h2>WLED Software Update</h2>Installed version: 0.10.0<br>Download the latest binary: <a href="https://github.com/Aircoookie/WLED/releases"><img src="https://img.shields.io/github/release/Aircoookie/WLED.svg?style=flat-square"></a><br><form method='POST' action='/update' enctype='multipart/form-data'><input type='file' class="bt" name='update' required><br><input type='submit' class="bt" value='Update!'></form><button type="button" class="bt" onclick="B()">Back</button></body></html>)=====";
//new user welcome page

View File

@@ -1,23 +1,23 @@
/*
* Settings html
* Settings html
*/
//common CSS of settings pages
const char PAGE_settingsCss[] PROGMEM = R"=====(<style>body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%%;margin:0}hr{border-color:#666}button{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}.helpB{text-align:left;position:absolute;width:60px}input{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.5ch solid #333}input[type=number]{width:4em}select{background:#333;color:#fff;font-family:Verdana,sans-serif;border:0.5ch solid #333}td{padding:2px;}</style>)=====";
const char PAGE_settingsCss[] PROGMEM = R"=====(<style>body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%%;margin:0}hr{border-color:#666}button{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;display:inline-block;font-size:20px;margin:8px;margin-top:12px}.helpB{text-align:left;position:absolute;width:60px}input{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.5ch solid #333}input[type=number]{width:4em}select{background:#333;color:#fff;font-family:Verdana,sans-serif;border:0.5ch solid #333}td{padding:2px;}.d5{width:4.5em !important;}</style>)=====";
//settings menu
const char PAGE_settings[] PROGMEM = R"=====(<!DOCTYPE html>
<html><head><title>WLED Settings</title><style>body{text-align:center;background:#222;height:100%;margin:0}html{--h:11.55vh}button{background:#333;color:#fff;font-family:Verdana,Helvetica,sans-serif;border:.3ch solid #333;display:inline-block;font-size:8vmin;height:var(--h);width:95%;margin-top:2.4vh}</style>
<html><head><title>WLED Settings</title><style>body{text-align:center;background:#222;height:100%%;margin:0}html{--h:11.55vh}button{background:#333;color:#fff;font-family:Verdana,Helvetica,sans-serif;border:.3ch solid #333;display:inline-block;font-size:8vmin;height:var(--h);width:95%%;margin-top:2.4vh}</style>
<script>function BB(){if(window.frameElement){document.getElementById("b").style.display="none";document.documentElement.style.setProperty("--h","13.86vh")}};</script></head>
<body onload=BB()>
<form action=/><button type=submit id=b>Back</button></form>
<form action=/settings/wifi><button type=submit>WiFi Setup</button></form>
<form action=/settings/leds><button type=submit>LED Preferences</button></form>
<form action=/settings/ui><button type=submit>User Interface</button></form>
<form action=/settings/ui><button type=submit>User Interface</button></form>%DMXMENU%
<form action=/settings/sync><button type=submit>Sync Interfaces</button></form>
<form action=/settings/time><button type=submit>Time & Macros</button></form>
<form action=/settings/sec><button type=submit>Security & Updates</button></form>
</body></html>)=====";
@@ -172,6 +172,65 @@ Skip first LED: <input type=checkbox name=SL><hr>
</form></body></html>)=====";
#ifdef WLED_ENABLE_DMX
//DMX Output settings
const char PAGE_settings_dmx[] PROGMEM = R"=====(<!DOCTYPE html>
<html><head><meta name="viewport" content="width=500"><meta charset="utf-8"><title>DMX Settings</title><script>
function GCH(num) {
d=document;
d.getElementById('dmxchannels').innerHTML += "";
for (i=0;i<num;i++) {
d.getElementById('dmxchannels').innerHTML += "<span id=CH" + (i+1) + "s >Channel " + (i+1) + ": <select name=CH" + (i+1) + " id=\"CH" + (i+1) + "\"><option value=0>Set to 0</option><option value=1>Red</option><option value=2>Green</option><option value=3>Blue</option><option value=4>White</option><option value=5>Shutter (Brightness)</option><option value=6>Set to 255</option></select></span><br />\n";
}
}
function mMap(){
d=document;
numCh=document.Sf.CN.value;
numGap=document.Sf.CG.value;
if (parseInt(numCh)>parseInt(numGap)) {
d.getElementById("gapwarning").style.display="block";
} else {
d.getElementById("gapwarning").style.display="none";
}
for (i=0;i<15;i++) {
if (i>=numCh) {
d.getElementById("CH"+(i+1) + "s").style.opacity = "0.5";
d.getElementById("CH"+(i+1)).disabled = true;
} else {
d.getElementById("CH"+(i+1) + "s").style.opacity = "1";
d.getElementById("CH"+(i+1)).disabled = false;
}
}
}
function S(){GCH(15);GetV();mMap();}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}function B(){window.history.back();}function GetV(){var d=document;
%CSS%%SCSS%</head>
<body onload="S()">
<form id="form_s" name="Sf" method="post">
<div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
<h2>Imma firin ma lazer (if it has DMX support)</h2><!-- TODO: Change to something less-meme-related //-->
<i>Number of fixtures is taken from LED config page</i><br>
Channels per fixture (15 max): <input type="number" min="1" max="15" name="CN" maxlength="2" onchange="mMap();"><br />
Start channel: <input type="number" min="1" max="512" name="CS" maxlength="2"><br />
Spacing between start channels: <input type="number" min="1" max="512" name="CG" maxlength="2" onchange="mMap();"> [ <a href="javascript:alert('if set to 10, first fixture will start at 10,\nsecond will start at 20 etc.\nRegardless of the channel count.\nMakes memorizing channel numbers easier.');">info</a> ]<br>
<div id="gapwarning" style="color: orange; display: none;">WARNING: Channel gap is lower than channels per fixture.<br />This will cause overlap.</div>
<button type="button" onclick="location.href='/dmxmap';">DMX Map</button><br>
DMX fixtures start LED: <input type="number" min="0" max="1500" name="SL">
<h3>channel functions</h3>
<div id="dmxchannels"></div>
<hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button>
</form>
</body>
</html>)=====";
#else
const char PAGE_settings_dmx[] PROGMEM = R"=====()=====";
#endif
//User Interface settings
const char PAGE_settings_ui[] PROGMEM = R"=====(<!DOCTYPE html>
<html><head><meta name="viewport" content="width=500"><meta charset="utf-8"><title>UI Settings</title><script>
@@ -190,18 +249,19 @@ Sync button toggles both send and receive: <input type="checkbox" name="ST"><br>
</html>)=====";
//sync settings
const char PAGE_settings_sync[] PROGMEM = R"=====(<!DOCTYPE html>
<html><head><meta name="viewport" content="width=500"><meta charset="utf-8"><title>Sync Settings</title>
<script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#sync-settings");}function B(){window.open("/settings","_self");}function GetV(){var d=document;
<html><head><meta name=viewport content="width=500"><meta charset=utf-8><title>Sync Settings</title>
<script>var d=document;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#sync-settings")}function B(){window.open("/settings","_self")}function adj(){if(d.Sf.DI.value==6454){if(d.Sf.DA.value==1){d.Sf.DA.value=0}if(d.Sf.EU.value==1){d.Sf.EU.value=0}}else{if(d.Sf.DI.value==5568){if(d.Sf.DA.value==0){d.Sf.DA.value=1}if(d.Sf.EU.value==0){d.Sf.EU.value=1}}}}function SP(){var a=d.Sf.DI.value;d.getElementById("xp").style.display=(a>0)?"none":"block";if(a>0){d.Sf.EP.value=a}}function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568:d.Sf.DI.value=5568;break;case 6454:d.Sf.DI.value=6454;break}SP()}function S(){GetV();SetVal()};function GetV(){
%CSS%%SCSS%</head>
<body onload="GetV()">
<form id="form_s" name="Sf" method="post">
<div class="helpB"><button type="button" onclick="H()">?</button></div>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
<body onload=S()>
<form id=form_s name=Sf method=post>
<div class=helpB><button type=button onclick=H()>?</button></div>
<button type=button onclick=B()>Back</button><button type=submit>Save</button><hr>
<h2>Sync setup</h2>
<h3>Button setup</h3>
On/Off button enabled: <input type="checkbox" name="BT"><br>
On/Off button enabled: <input type=checkbox name=BT><br>
Infrared remote:
<select name=IR>
<option value=0>Disabled</option>
@@ -212,23 +272,31 @@ Infrared remote:
<option value=5>21-key RGB</option>
<option value=6>6-key black</option>
</select><br>
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a>
<a href=https://github.com/Aircoookie/WLED/wiki/Infrared-Control target=_blank>IR info</a>
<h3>WLED Broadcast</h3>
UDP Port: <input name="UP" type="number" min="1" max="65535" required><br>
Receive <input type="checkbox" name="RB">Brightness, <input type="checkbox" name="RC">Color, and <input type="checkbox" name="RX">Effects<br>
Send notifications on direct change: <input type="checkbox" name="SD"><br>
Send notifications on button press: <input type="checkbox" name="SB"><br>
Send Alexa notifications: <input type="checkbox" name="SA"><br>
Send Philips Hue change notifications: <input type="checkbox" name="SH"><br>
Send Macro notifications: <input type="checkbox" name="SM"><br>
Send notifications twice: <input type="checkbox" name="S2">
UDP Port: <input name=UP type=number min=1 max=65535 class=d5 required><br>
Receive <input type=checkbox name=RB>Brightness, <input type=checkbox name=RC>Color, and <input type=checkbox name=RX>Effects<br>
Send notifications on direct change: <input type=checkbox name=SD><br>
Send notifications on button press: <input type=checkbox name=SB><br>
Send Alexa notifications: <input type=checkbox name=SA><br>
Send Philips Hue change notifications: <input type=checkbox name=SH><br>
Send Macro notifications: <input type=checkbox name=SM><br>
Send notifications twice: <input type=checkbox name=S2>
<h3>Realtime</h3>
Receive UDP realtime: <input type="checkbox" name="RD"><br><br>
<i>E1.31 (sACN)</i><br>
Use E1.31 multicast: <input type="checkbox" name="EM"><br>
E1.31 start universe: <input name="EU" type="number" min="1" max="63999" required><br>
<i>Reboot required.</i> Check out <a href="https://github.com/ahodges9/LedFx" target="_blank">LedFx</a>!<br>
DMX start address: <input name="DA" type="number" min="1" max="510" value="1" required><br>
Receive UDP realtime: <input type=checkbox name=RD><br><br>
<i>Network DMX input</i><br>
Type:
<select name=DI onchange=SP();adj()>
<option value=5568>E1.31 (sACN)</option>
<option value=6454>Art-Net</option>
<option value=0 selected>Custom port</option>
</select><br>
<div id=xp>Port: <input name=EP type=number min=1 max=65535 value=5568 class=d5 required><br></div>
Multicast: <input type=checkbox name=EM><br>
Start universe: <input name=EU type=number min=0 max=63999 required><br>
<i>Reboot required.</i> Check out <a href=https://github.com/ahodges9/LedFx target=_blank>LedFx</a>!<br>
Skip out-of-sequence packets: <input type=checkbox name=ES><br>
DMX start address: <input name=DA type=number min=0 max=510 required><br>
DMX mode:
<select name=DM>
<option value=0>Disabled</option>
@@ -238,49 +306,48 @@ DMX mode:
<option value=4>Multi RGB</option>
<option value=5>Multi DRGB</option>
</select><br>
<a href="https://github.com/Aircoookie/WLED/wiki/E1.31-DMX" target="_blank">E1.31 info</a><br>
Timeout: <input name="ET" type="number" min="1" max="65000" required> ms<br>
Force max brightness: <input type="checkbox" name="FB"><br>
Disable realtime gamma correction: <input type="checkbox" name="RG"><br>
Realtime LED offset: <input name="WO" type="number" min="-255" max="255" required>
<a href=https://github.com/Aircoookie/WLED/wiki/E1.31-DMX target=_blank>E1.31 info</a><br>
Timeout: <input name=ET type=number min=1 max=65000 required> ms<br>
Force max brightness: <input type=checkbox name=FB><br>
Disable realtime gamma correction: <input type=checkbox name=RG><br>
Realtime LED offset: <input name=WO type=number min=-255 max=255 required>
<h3>Alexa Voice Assistant</h3>
Emulate Alexa device: <input type="checkbox" name="AL"><br>
Alexa invocation name: <input name="AI" maxlength="32">
Emulate Alexa device: <input type=checkbox name=AL><br>
Alexa invocation name: <input name=AI maxlength=32>
<h3>Blynk</h3>
<b>Blynk, MQTT and Hue sync all connect to external hosts!<br>
This may impact the responsiveness of the ESP8266.</b><br>
For best results, only use one of these services at a time.<br>
(alternatively, connect a second ESP to them and use the UDP sync)<br><br>
Device Auth token: <input name="BK" maxlength="33"><br>
<i>Clear the token field to disable. </i><a href="https://github.com/Aircoookie/WLED/wiki/Blynk" target="_blank">Setup info</a>
Device Auth token: <input name=BK maxlength=33><br>
<i>Clear the token field to disable. </i><a href=https://github.com/Aircoookie/WLED/wiki/Blynk target=_blank>Setup info</a>
<h3>MQTT</h3>
Enable MQTT: <input type="checkbox" name="MQ"><br>
Broker: <input name="MS" maxlength="32">
Port: <input name="MQPORT" type="number" min="1" max="65535"><br>
Enable MQTT: <input type=checkbox name=MQ><br>
Broker: <input name=MS maxlength=32>
Port: <input name=MQPORT type=number min=1 max=65535 class=d5><br>
<b>The MQTT credentials are sent over an unsecured connection.<br>
Never use the MQTT password for another service!</b><br>
Username: <input name="MQUSER" maxlength="40"><br>
Password: <input type="password" input name="MQPASS" maxlength="40"><br>
Client ID: <input name="MQCID" maxlength="40"><br>
Device Topic: <input name="MD" maxlength="32"><br>
Group Topic: <input name="MG" maxlength="32"><br>
<i>Reboot required to apply changes. </i><a href="https://github.com/Aircoookie/WLED/wiki/MQTT" target="_blank">MQTT info</a>
Username: <input name=MQUSER maxlength=40><br>
Password: <input type=password input name=MQPASS maxlength=40><br>
Client ID: <input name=MQCID maxlength=40><br>
Device Topic: <input name=MD maxlength=32><br>
Group Topic: <input name=MG maxlength=32><br>
<i>Reboot required to apply changes. </i><a href=https://github.com/Aircoookie/WLED/wiki/MQTT target=_blank>MQTT info</a>
<h3>Philips Hue</h3>
<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
Poll Hue light <input name="HL" type="number" min="1" max="99" > every <input name="HI" type="number" min="100" max="65000"> ms: <input type="checkbox" name="HP"><br>
Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br>
Poll Hue light <input name=HL type=number min=1 max=99> every <input name=HI type=number min=100 max=65000> ms: <input type=checkbox name=HP><br>
Then, receive <input type=checkbox name=HO> On/Off, <input type=checkbox name=HB> Brightness, and <input type=checkbox name=HC> Color<br>
Hue Bridge IP:<br>
<input name="H0" type="number" min="0" max="255" > .
<input name="H1" type="number" min="0" max="255" > .
<input name="H2" type="number" min="0" max="255" > .
<input name="H3" type="number" min="0" max="255" ><br>
<input name=H0 type=number min=0 max=255> .
<input name=H1 type=number min=0 max=255> .
<input name=H2 type=number min=0 max=255> .
<input name=H3 type=number min=0 max=255><br>
<b>Press the pushlink button on the bridge, after that save this page!</b><br>
(when first connecting)<br>
Hue status: <span class="hms"> Internal ESP Error! </span><hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
Hue status: <span class=sip> Disabled in this build </span><hr>
<button type=button onclick=B()>Back</button><button type=submit>Save</button>
</form>
</body>
</html>)=====";
</body></html>)=====";
//time and macro settings
@@ -317,6 +384,8 @@ Time zone:
<option value="13">North Korea</option>
<option value="14">IST (India)</option>
<option value="15">CA-Saskatchewan</option>
<option value="16">ACST</option>
<option value="17">ACST/ACDT</option>
</select><br>
UTC offset: <input name="UO" type="number" min="-65500" max="65500" required> seconds (max. 18 hours)<br>
Current local time is <span class="times">unknown</span>.
@@ -403,12 +472,12 @@ HTTP traffic is unencrypted. An attacker in the same network can intercept form
<button type="button" onclick="U()">Manual OTA Update</button><br>
Enable ArduinoOTA: <input type="checkbox" name="AO"><br>
<h3>About</h3>
<a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.9.1<br><br>
<a href="https://github.com/Aircoookie/WLED" target="_blank">WLED</a> version 0.10.0<br><br>
<a href="https://github.com/Aircoookie/WLED/wiki/Contributors-&-About" target="_blank">Contributors, dependencies and special thanks</a><br>
A huge thank you to everyone who helped me create WLED!<br><br>
(c) 2016-2020 Christian Schwinne <br>
<i>Licensed under the MIT license</i><br><br>
Server message: <span class="msg"> Response error! </span><hr>
Server message: <span class="sip"> Response error! </span><hr>
<button type="button" onclick="B()">Back</button><button type="submit">Save & Reboot</button>
</form>
</body>

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,11 @@
#include "wled.h"
/*
* Sync to Philips hue lights
*/
#ifndef WLED_DISABLE_HUESYNC
void handleHue()
{
if (hueReceived)
@@ -23,7 +27,7 @@ void handleHue()
reconnectHue();
} else {
hueClient->close();
if (hueError[0] == 'A') strcpy(hueError,"Inactive");
if (hueError == HUE_ERROR_ACTIVE) hueError = HUE_ERROR_INACTIVE;
}
}
@@ -44,7 +48,7 @@ void reconnectHue()
void onHueError(void* arg, AsyncClient* client, int8_t error)
{
DEBUG_PRINTLN("Hue err");
strcpy(hueError,"Request timeout");
hueError = HUE_ERROR_TIMEOUT;
}
void onHueConnect(void* arg, AsyncClient* client)
@@ -59,15 +63,15 @@ void sendHuePoll()
String req = "";
if (hueAuthRequired)
{
req += "POST /api HTTP/1.1\r\nHost: ";
req += F("POST /api HTTP/1.1\r\nHost: ");
req += hueIP.toString();
req += "\r\nContent-Length: 25\r\n\r\n{\"devicetype\":\"wled#esp\"}";
req += F("\r\nContent-Length: 25\r\n\r\n{\"devicetype\":\"wled#esp\"}");
} else
{
req += "GET /api/";
req += hueApiKey;
req += "/lights/" + String(huePollLightId);
req += " HTTP/1.1\r\nHost: ";
req += F(" HTTP/1.1\r\nHost: ");
req += hueIP.toString();
req += "\r\n\r\n";
}
@@ -93,21 +97,18 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
auto error = deserializeJson(root, str);
if (error)
{
strcpy(hueError,"JSON parsing error"); return;
hueError = HUE_ERROR_JSON_PARSING; return;
}
int hueErrorCode = root[0]["error"]["type"];
if (hueErrorCode)//hue bridge returned error
{
hueError = hueErrorCode;
switch (hueErrorCode)
{
case 1: strcpy(hueError,"Unauthorized"); hueAuthRequired = true; break;
case 3: strcpy(hueError,"Invalid light ID"); huePollingEnabled = false; break;
case 101: strcpy(hueError,"Link button not pressed"); hueAuthRequired = true; break;
default:
char coerr[18];
sprintf(coerr,"Bridge Error %i",hueErrorCode);
strcpy(hueError,coerr);
case 1: hueAuthRequired = true; break; //Unauthorized user
case 3: huePollingEnabled = false; break; //Invalid light ID
case 101: hueAuthRequired = true; break; //link button not presset
}
return;
}
@@ -133,7 +134,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
auto error = deserializeJson(root, str);
if (error)
{
strcpy(hueError,"JSON parsing error"); return;
hueError = HUE_ERROR_JSON_PARSING; return;
}
float hueX=0, hueY=0;
@@ -173,7 +174,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
hueBri = 0;
}
strcpy(hueError,"Active");
hueError = HUE_ERROR_ACTIVE;
//apply vals
if (hueBri != hueBriLast)

View File

@@ -1,3 +1,5 @@
#include "wled.h"
/*
* Infrared sensor support for generic 24/40/44 key RGB remotes
*/
@@ -35,14 +37,55 @@ bool decodeIRCustom(uint32_t code)
//relatively change brightness, minumum A=5
void relativeChange(byte* property, int8_t amount, byte lowerBoundary =0)
void relativeChange(byte* property, int8_t amount, byte lowerBoundary, byte higherBoundary)
{
int16_t new_val = (int16_t) *property + amount;
if (new_val > 0xFF) new_val = 0xFF;
if (new_val > higherBoundary) new_val = higherBoundary;
else if (new_val < lowerBoundary) new_val = lowerBoundary;
*property = new_val;
*property = (byte)constrain(new_val,0.1,255.1);
}
void changeEffectSpeed(int8_t amount)
{
if (effectCurrent != 0) {
int16_t new_val = (int16_t) effectSpeed + amount;
effectSpeed = (byte)constrain(new_val,0.1,255.1);
} else { // if Effect == "solid Color", change the hue of the primary color
CRGB fastled_col;
fastled_col.red = col[0];
fastled_col.green = col[1];
fastled_col.blue = col[2];
CHSV prim_hsv = rgb2hsv_approximate(fastled_col);
int16_t new_val = (int16_t) prim_hsv.h + amount;
if (new_val > 255) new_val -= 255; // roll-over if bigger than 255
if (new_val < 0) new_val += 255; // roll-over if smaller than 0
prim_hsv.h = (byte)new_val;
hsv2rgb_rainbow(prim_hsv, fastled_col);
col[0] = fastled_col.red;
col[1] = fastled_col.green;
col[2] = fastled_col.blue;
}
}
void changeEffectIntensity(int8_t amount)
{
if (effectCurrent != 0) {
int16_t new_val = (int16_t) effectIntensity + amount;
effectIntensity = (byte)constrain(new_val,0.1,255.1);
} else { // if Effect == "solid Color", change the saturation of the primary color
CRGB fastled_col;
fastled_col.red = col[0];
fastled_col.green = col[1];
fastled_col.blue = col[2];
CHSV prim_hsv = rgb2hsv_approximate(fastled_col);
int16_t new_val = (int16_t) prim_hsv.s + amount;
prim_hsv.s = (byte)constrain(new_val,0.1,255.1); // constrain to 0-255
hsv2rgb_rainbow(prim_hsv, fastled_col);
col[0] = fastled_col.red;
col[1] = fastled_col.green;
col[2] = fastled_col.blue;
}
}
void decodeIR(uint32_t code)
{
@@ -90,8 +133,9 @@ void decodeIR(uint32_t code)
// sets bright plain white
default: return;
}
colorUpdated(NOTIFIER_CALL_MODE_BUTTON); //for notifier, IR is considered a button input
}
if (nightlightActive && bri == 0) nightlightActive = false;
colorUpdated(NOTIFIER_CALL_MODE_BUTTON); //for notifier, IR is considered a button input
//code <= 0xF70000 also invalid
}
@@ -241,10 +285,10 @@ void decodeIR40(uint32_t code)
case IR40_W50 : bri = 127; break;
case IR40_W75 : bri = 191; break;
case IR40_W100 : bri = 255; break;
case IR40_QUICK : relativeChange(&effectSpeed, 10); break;
case IR40_SLOW : relativeChange(&effectSpeed, -10, 5); break;
case IR40_JUMP7 : relativeChange(&effectIntensity, 10); break;
case IR40_AUTO : relativeChange(&effectIntensity, -10, 5); break;
case IR40_QUICK : changeEffectSpeed( 16); break;
case IR40_SLOW : changeEffectSpeed(-16); break;
case IR40_JUMP7 : changeEffectIntensity( 16); break;
case IR40_AUTO : changeEffectIntensity(-16); break;
case IR40_JUMP3 : if (!applyPreset(1)) { effectCurrent = FX_MODE_STATIC; effectPalette = 0; } break;
case IR40_FADE3 : if (!applyPreset(2)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
case IR40_FADE7 : if (!applyPreset(3)) { effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; } break;
@@ -292,14 +336,14 @@ void decodeIR44(uint32_t code)
case IR44_COLDWHITE2 : {
if (useRGBW) { colorFromUint32(COLOR2_COLDWHITE2); effectCurrent = 0; }
else colorFromUint24(COLOR_COLDWHITE2); } break;
case IR44_REDPLUS : relativeChange(&effectCurrent, 1); break;
case IR44_REDPLUS : relativeChange(&effectCurrent, 1, 0, MODE_COUNT); break;
case IR44_REDMINUS : relativeChange(&effectCurrent, -1, 0); break;
case IR44_GREENPLUS : relativeChange(&effectPalette, 1); break;
case IR44_GREENPLUS : relativeChange(&effectPalette, 1, 0, strip.getPaletteCount() -1); break;
case IR44_GREENMINUS : relativeChange(&effectPalette, -1, 0); break;
case IR44_BLUEPLUS : relativeChange(&effectIntensity, 10); break;
case IR44_BLUEMINUS : relativeChange(&effectIntensity, -10, 5); break;
case IR44_QUICK : relativeChange(&effectSpeed, 10); break;
case IR44_SLOW : relativeChange(&effectSpeed, -10, 5); break;
case IR44_BLUEPLUS : changeEffectIntensity( 16); break;
case IR44_BLUEMINUS : changeEffectIntensity(-16); break;
case IR44_QUICK : changeEffectSpeed( 16); break;
case IR44_SLOW : changeEffectSpeed(-16); break;
case IR44_DIY1 : if (!applyPreset(1)) { effectCurrent = FX_MODE_STATIC; effectPalette = 0; } break;
case IR44_DIY2 : if (!applyPreset(2)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
case IR44_DIY3 : if (!applyPreset(3)) { effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; } break;
@@ -318,7 +362,7 @@ void decodeIR44(uint32_t code)
void decodeIR21(uint32_t code)
{
switch (code) {
switch (code) {
case IR21_BRIGHTER: relativeChange(&bri, 10); break;
case IR21_DARKER: relativeChange(&bri, -10, 5); break;
case IR21_OFF: briLast = bri; bri = 0; break;
@@ -341,40 +385,38 @@ void decodeIR21(uint32_t code)
case IR21_FADE: if (!applyPreset(3)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
case IR21_SMOOTH: if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
default: return;
}
lastValidCode = code;
}
lastValidCode = code;
}
void decodeIR6(uint32_t code)
{
switch (code) {
case IR6_POWER: toggleOnOff(); break;
case IR6_CHANNEL_UP: relativeChange(&bri, 10); break;
case IR6_CHANNEL_DOWN: relativeChange(&bri, -10, 5); break;
case IR6_VOLUME_UP: /* next effect */ relativeChange(&effectCurrent, 1); break;
case IR6_VOLUME_DOWN:
/* next palette */
relativeChange(&effectPalette, 1);
case IR6_POWER: toggleOnOff(); break;
case IR6_CHANNEL_UP: relativeChange(&bri, 10); break;
case IR6_CHANNEL_DOWN: relativeChange(&bri, -10, 5); break;
case IR6_VOLUME_UP: relativeChange(&effectCurrent, 1, 0, MODE_COUNT); break; // next effect
case IR6_VOLUME_DOWN: // next palette
relativeChange(&effectPalette, 1, 0, strip.getPaletteCount() -1);
switch(lastIR6ColourIdx) {
case 0: colorFromUint32(COLOR_RED); break;
case 1: colorFromUint32(COLOR_REDDISH); break;
case 2:colorFromUint32(COLOR_ORANGE); break;
case 3:colorFromUint32(COLOR_YELLOWISH); break;
case 4:colorFromUint32(COLOR_GREEN); break;
case 5:colorFromUint32(COLOR_GREENISH); break;
case 6:colorFromUint32(COLOR_TURQUOISE); break;
case 7: colorFromUint32(COLOR_CYAN); break;
case 8:colorFromUint32(COLOR_BLUE); break;
case 9:colorFromUint32(COLOR_DEEPBLUE); break;
case 10:colorFromUint32(COLOR_PURPLE); break;
case 11:colorFromUint32(COLOR_PINK); break;
case 12:colorFromUint32(COLOR_WHITE); break;
default:break;
case 0: colorFromUint32(COLOR_RED); break;
case 1: colorFromUint32(COLOR_REDDISH); break;
case 2: colorFromUint32(COLOR_ORANGE); break;
case 3: colorFromUint32(COLOR_YELLOWISH); break;
case 4: colorFromUint32(COLOR_GREEN); break;
case 5: colorFromUint32(COLOR_GREENISH); break;
case 6: colorFromUint32(COLOR_TURQUOISE); break;
case 7: colorFromUint32(COLOR_CYAN); break;
case 8: colorFromUint32(COLOR_BLUE); break;
case 9: colorFromUint32(COLOR_DEEPBLUE); break;
case 10:colorFromUint32(COLOR_PURPLE); break;
case 11:colorFromUint32(COLOR_PINK); break;
case 12:colorFromUint32(COLOR_WHITE); break;
default: break;
}
lastIR6ColourIdx++;
if(lastIR6ColourIdx > 12) lastIR6ColourIdx = 0;
break;
case IR6_MUTE: effectCurrent = 0; effectPalette = 0; colorFromUint32(COLOR_WHITE); bri=255; break;
if(lastIR6ColourIdx > 12) lastIR6ColourIdx = 0; break;
case IR6_MUTE: effectCurrent = 0; effectPalette = 0; colorFromUint32(COLOR_WHITE); bri=255; break;
}
lastValidCode = code;
}

View File

@@ -1,3 +1,5 @@
#include "wled.h"
/*
* JSON API (De)serialization
*/
@@ -18,6 +20,16 @@ void deserializeSegment(JsonObject elem, byte it)
uint16_t grp = elem["grp"] | seg.grouping;
uint16_t spc = elem["spc"] | seg.spacing;
strip.setSegment(id, start, stop, grp, spc);
int segbri = elem["bri"] | -1;
if (segbri == 0) {
seg.setOption(SEG_OPTION_ON, 0);
} else if (segbri > 0) {
seg.opacity = segbri;
seg.setOption(SEG_OPTION_ON, 1);
}
seg.setOption(SEG_OPTION_ON, elem["on"] | seg.getOption(SEG_OPTION_ON));
JsonArray colarr = elem["col"];
if (!colarr.isNull())
@@ -31,21 +43,23 @@ void deserializeSegment(JsonObject elem, byte it)
{
int rgbw[] = {0,0,0,0};
byte cp = copyArray(colX, rgbw);
seg.colors[i] = ((rgbw[3] << 24) | ((rgbw[0]&0xFF) << 16) | ((rgbw[1]&0xFF) << 8) | ((rgbw[2]&0xFF)));
if (cp == 1 && rgbw[0] == 0) seg.colors[i] = 0;
if (id == strip.getMainSegmentId()) //temporary
if (id == strip.getMainSegmentId() && i < 2) //temporary, to make transition work on main segment
{
if (i == 0) {col[0] = rgbw[0]; col[1] = rgbw[1]; col[2] = rgbw[2]; col[3] = rgbw[3];}
if (i == 1) {colSec[0] = rgbw[0]; colSec[1] = rgbw[1]; colSec[2] = rgbw[2]; colSec[3] = rgbw[3];}
} else {
seg.colors[i] = ((rgbw[3] << 24) | ((rgbw[0]&0xFF) << 16) | ((rgbw[1]&0xFF) << 8) | ((rgbw[2]&0xFF)));
}
}
}
}
//if (pal != seg.palette && pal < strip.getPaletteCount()) strip.setPalette(pal);
seg.setOption(0, elem["sel"] | seg.getOption(0)); //selected
seg.setOption(1, elem["rev"] | seg.getOption(1)); //reverse
//int cln = seg_0["cln"];
seg.setOption(SEG_OPTION_SELECTED, elem["sel"] | seg.getOption(SEG_OPTION_SELECTED));
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
//temporary, strip object gets updated via colorUpdated()
if (id == strip.getMainSegmentId()) {
effectCurrent = elem["fx"] | effectCurrent;
@@ -115,6 +129,10 @@ bool deserializeState(JsonObject root)
int timein = root["time"] | -1;
if (timein != -1) setTime(timein);
doReboot = root["rb"] | doReboot;
realtimeOverride = root["lor"] | realtimeOverride;
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
byte prevMain = strip.getMainSegmentId();
strip.mainSegment = root["mainseg"] | prevMain;
@@ -156,8 +174,11 @@ bool deserializeState(JsonObject root)
colorUpdated(noNotification ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);
//write presets to flash directly?
bool persistSaves = !(root["np"] | false);
ps = root["psave"] | -1;
if (ps >= 0) savePreset(ps);
if (ps >= 0) savePreset(ps, persistSaves);
return stateResponse;
}
@@ -170,17 +191,29 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id)
root["len"] = seg.stop - seg.start;
root["grp"] = seg.grouping;
root["spc"] = seg.spacing;
root["on"] = seg.getOption(SEG_OPTION_ON);
byte segbri = seg.opacity;
root["bri"] = (segbri) ? segbri : 255;
JsonArray colarr = root.createNestedArray("col");
for (uint8_t i = 0; i < 3; i++)
{
JsonArray colX = colarr.createNestedArray();
colX.add((seg.colors[i] >> 16) & 0xFF);
colX.add((seg.colors[i] >> 8) & 0xFF);
colX.add((seg.colors[i]) & 0xFF);
if (useRGBW)
colX.add((seg.colors[i] >> 24) & 0xFF);
if (id == strip.getMainSegmentId() && i < 2) //temporary, to make transition work on main segment
{
if (i == 0) {
colX.add(col[0]); colX.add(col[1]); colX.add(col[2]); if (useRGBW) colX.add(col[3]);
} else {
colX.add(colSec[0]); colX.add(colSec[1]); colX.add(colSec[2]); if (useRGBW) colX.add(colSec[3]);
}
} else {
colX.add((seg.colors[i] >> 16) & 0xFF);
colX.add((seg.colors[i] >> 8) & 0xFF);
colX.add((seg.colors[i]) & 0xFF);
if (useRGBW)
colX.add((seg.colors[i] >> 24) & 0xFF);
}
}
root["fx"] = seg.mode;
@@ -188,7 +221,7 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id)
root["ix"] = seg.intensity;
root["pal"] = seg.palette;
root["sel"] = seg.isSelected();
root["rev"] = seg.getOption(1);
root["rev"] = seg.getOption(SEG_OPTION_REVERSED);
}
@@ -220,6 +253,8 @@ void serializeState(JsonObject root)
udpn["send"] = notifyDirect;
udpn["recv"] = receiveNotifications;
root["lor"] = realtimeOverride;
root["mainseg"] = strip.getMainSegmentId();
JsonArray seg = root.createNestedArray("seg");
@@ -234,10 +269,31 @@ void serializeState(JsonObject root)
}
}
//by https://github.com/tzapu/WiFiManager/blob/master/WiFiManager.cpp
int getSignalQuality(int rssi)
{
int quality = 0;
if (rssi <= -100)
{
quality = 0;
}
else if (rssi >= -50)
{
quality = 100;
}
else
{
quality = 2 * (rssi + 100);
}
return quality;
}
void serializeInfo(JsonObject root)
{
root["ver"] = versionString;
root["vid"] = VERSION;
//root["cn"] = WLED_CODENAME;
JsonObject leds = root.createNestedObject("leds");
leds["count"] = ledCount;
@@ -256,6 +312,24 @@ void serializeInfo(JsonObject root)
root["name"] = serverDescription;
root["udpport"] = udpPort;
root["live"] = (bool)realtimeMode;
switch (realtimeMode) {
case REALTIME_MODE_INACTIVE: root["lm"] = ""; break;
case REALTIME_MODE_GENERIC: root["lm"] = ""; break;
case REALTIME_MODE_UDP: root["lm"] = "UDP"; break;
case REALTIME_MODE_HYPERION: root["lm"] = "Hyperion"; break;
case REALTIME_MODE_E131: root["lm"] = "E1.31"; break;
case REALTIME_MODE_ADALIGHT: root["lm"] = F("USB Adalight");
case REALTIME_MODE_ARTNET: root["lm"] = "Art-Net"; break;
}
if (realtimeIP[0] == 0)
{
root["lip"] = "";
} else {
root["lip"] = realtimeIP.toString();
}
root["fxcount"] = strip.getModeCount();
root["palcount"] = strip.getPaletteCount();
@@ -290,7 +364,7 @@ void serializeInfo(JsonObject root)
#endif
root["freeheap"] = ESP.getFreeHeap();
root["uptime"] = millis()/1000;
root["uptime"] = millis()/1000 + rolloverMillis*4294967;
byte os = 0;
#ifdef WLED_DEBUG
@@ -320,8 +394,7 @@ void serializeInfo(JsonObject root)
root["opt"] = os;
root["brand"] = "WLED";
root["product"] = "DIY light";
root["btype"] = "src";
root["product"] = "FOSS";
root["mac"] = escapedMac;
}
@@ -331,6 +404,7 @@ void serveJson(AsyncWebServerRequest* request)
const String& url = request->url();
if (url.indexOf("state") > 0) subJson = 1;
else if (url.indexOf("info") > 0) subJson = 2;
else if (url.indexOf("si") > 0) subJson = 3;
else if (url.indexOf("live") > 0) {
serveLiveLeds(request);
return;
@@ -344,7 +418,7 @@ void serveJson(AsyncWebServerRequest* request)
return;
}
else if (url.length() > 6) { //not just /json
request->send( 501, "application/json", "{\"error\":\"Not implemented\"}");
request->send( 501, "application/json", F("{\"error\":\"Not implemented\"}"));
return;
}
@@ -362,8 +436,11 @@ void serveJson(AsyncWebServerRequest* request)
serializeState(state);
JsonObject info = doc.createNestedObject("info");
serializeInfo(info);
doc["effects"] = serialized((const __FlashStringHelper*)JSON_mode_names);
doc["palettes"] = serialized((const __FlashStringHelper*)JSON_palette_names);
if (subJson != 3)
{
doc["effects"] = serialized((const __FlashStringHelper*)JSON_mode_names);
doc["palettes"] = serialized((const __FlashStringHelper*)JSON_palette_names);
}
}
response->setLength();
@@ -374,8 +451,8 @@ void serveJson(AsyncWebServerRequest* request)
void serveLiveLeds(AsyncWebServerRequest* request)
{
byte used = ledCount;
byte n = (used -1) /MAX_LIVE_LEDS +1; //only serve every n'th LED if count over MAX_LIVE_LEDS
uint16_t used = ledCount;
uint16_t n = (used -1) /MAX_LIVE_LEDS +1; //only serve every n'th LED if count over MAX_LIVE_LEDS
char buffer[2000] = "{\"leds\":[";
olen = 9;
obuf = buffer;

View File

@@ -1,6 +1,9 @@
#include "wled.h"
/*
* LED methods
*/
void setValuesFromMainSeg()
{
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
@@ -40,13 +43,6 @@ void setAllLeds() {
if (val > 255) val = 255;
strip.setBrightness(val);
}
if (!enableSecTransition)
{
for (byte i = 0; i<4; i++)
{
colSecT[i] = colSec[i];
}
}
if (useRGBW && strip.rgbwMode == RGBW_MODE_LEGACY)
{
colorRGBtoRGBW(colT);
@@ -57,7 +53,7 @@ void setAllLeds() {
}
void setLedsStandard(bool justColors = false)
void setLedsStandard(bool justColors)
{
for (byte i=0; i<4; i++)
{
@@ -79,7 +75,6 @@ bool colorChanged()
{
if (col[i] != colIT[i]) return true;
if (colSec[i] != colSecIT[i]) return true;
//if (col[i] != colNlT[i]) return true; (this effectively made the ESP send out sync packets every time colorUpdated() is called, even if nothing changed)
}
if (bri != briIT) return true;
return false;
@@ -95,28 +90,30 @@ void colorUpdated(int callMode)
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY) strip.applyToAllSelected = true; //if not from JSON api, which directly sets segments
bool fxChanged = strip.setEffectConfig(effectCurrent, effectSpeed, effectIntensity, effectPalette);
if (!colorChanged())
bool colChanged = colorChanged();
if (fxChanged || colChanged)
{
if (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
if (isPreset) {isPreset = false;}
else {currentPreset = -1;}
notify(callMode);
//set flag to update blynk and mqtt
if (callMode != NOTIFIER_CALL_MODE_PRESET_CYCLE) interfaceUpdateCallMode = callMode;
} else {
if (nightlightActive && !nightlightActiveOld &&
callMode != NOTIFIER_CALL_MODE_NOTIFICATION &&
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY)
{
notify(NOTIFIER_CALL_MODE_NIGHTLIGHT);
interfaceUpdateCallMode = NOTIFIER_CALL_MODE_NIGHTLIGHT;
return;
}
else if (fxChanged) {
notify(NOTIFIER_CALL_MODE_FX_CHANGED);
if (callMode != NOTIFIER_CALL_MODE_PRESET_CYCLE) interfaceUpdateCallMode = NOTIFIER_CALL_MODE_FX_CHANGED;
if (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
if (isPreset) {isPreset = false;}
else {currentPreset = -1;}
}
return; //no change
}
if (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
if (isPreset) {isPreset = false;}
else {currentPreset = -1;}
if (!colChanged) return; //following code is for e.g. initiating transitions
if (callMode != NOTIFIER_CALL_MODE_NO_NOTIFY && nightlightActive && nightlightFade)
{
briNlT = bri;
@@ -137,8 +134,6 @@ void colorUpdated(int callMode)
briIT = bri;
if (bri > 0) briLast = bri;
notify(callMode);
if (fadeTransition)
{
//set correct delay if not using notification delay
@@ -164,10 +159,6 @@ void colorUpdated(int callMode)
setLedsStandard();
strip.trigger();
}
if (callMode == NOTIFIER_CALL_MODE_PRESET_CYCLE) return;
//set flag to update blynk and mqtt
interfaceUpdateCallMode = callMode;
}
@@ -231,15 +222,15 @@ void handleNightlight()
nightlightDelayMs = (int)(nightlightDelayMins*60000);
nightlightActiveOld = true;
briNlT = bri;
for (byte i=0; i<4; i++) colNlT[i] = col[i]; // remember starting color
for (byte i=0; i<4; i++) colNlT[i] = col[i]; // remember starting color
}
float nper = (millis() - nightlightStartTime)/((float)nightlightDelayMs);
if (nightlightFade)
{
bri = briNlT + ((nightlightTargetBri - briNlT)*nper);
if (nightlightColorFade) // color fading only is enabled with "NF=2"
if (nightlightColorFade) // color fading only is enabled with "NF=2"
{
for (byte i=0; i<4; i++) col[i] = colNlT[i]+ ((colSec[i] - colNlT[i])*nper); // fading from actual color to secondary color
for (byte i=0; i<4; i++) col[i] = colNlT[i]+ ((colSec[i] - colNlT[i])*nper); // fading from actual color to secondary color
}
colorUpdated(NOTIFIER_CALL_MODE_NO_NOTIFY);
}
@@ -262,7 +253,7 @@ void handleNightlight()
//also handle preset cycle here
if (presetCyclingEnabled && (millis() - presetCycledTime > presetCycleTime))
{
applyPreset(presetCycCurr,presetApplyBri,presetApplyCol,presetApplyFx);
applyPreset(presetCycCurr,presetApplyBri);
presetCycCurr++; if (presetCycCurr > presetCycleMax) presetCycCurr = presetCycleMin;
if (presetCycCurr > 25) presetCycCurr = 1;
colorUpdated(NOTIFIER_CALL_MODE_PRESET_CYCLE);

View File

@@ -1,3 +1,5 @@
#include "wled.h"
/*
* MQTT communication protocol for home automation
*/

View File

@@ -1,3 +1,6 @@
#include "src/dependencies/timezone/Timezone.h"
#include "wled.h"
/*
* Acquires time from NTP server
*/
@@ -57,7 +60,13 @@ Timezone tzNK(NKST, NKST);
TimeChangeRule IST = {Last, Sun, Mar, 1, 330}; // India Standard Time = UTC + 5.5 hours
Timezone tzIndia(IST, IST);
Timezone* timezones[] = {&tzUTC, &tzUK, &tzEUCentral, &tzEUEastern, &tzUSEastern, &tzUSCentral, &tzUSMountain, &tzUSArizona, &tzUSPacific, &tzChina, &tzJapan, &tzAUEastern, &tzNZ, &tzNK, &tzIndia, &tzCASaskatchewan};
TimeChangeRule ACST = {First, Sun, Apr, 3, 570}; //Australian Central Standard = UTC + 9.5 hours
TimeChangeRule ACDT = {First, Sun, Oct, 2, 630}; //Australian Central Daylight = UTC + 10.5 hours
Timezone tzAUNorthern(ACST, ACST);
Timezone tzAUSouthern(ACDT, ACST);
// Pick your timezone from here.
Timezone* timezones[] = {&tzUTC, &tzUK, &tzEUCentral, &tzEUEastern, &tzUSEastern, &tzUSCentral, &tzUSMountain, &tzUSArizona, &tzUSPacific, &tzChina, &tzJapan, &tzAUEastern, &tzNZ, &tzNK, &tzIndia, &tzCASaskatchewan, &tzAUNorthern, &tzAUSouthern};
void handleNetworkTime()
{
@@ -164,9 +173,9 @@ void setCountdown()
bool checkCountdown()
{
unsigned long n = now();
local = countdownTime - n;
if (countdownMode) local = countdownTime - n + utcOffsetSecs;
if (n > countdownTime) {
local = n - countdownTime;
if (countdownMode) local = n - countdownTime + utcOffsetSecs;
if (!countdownOverTriggered)
{
if (macroCountdown != 0) applyMacro(macroCountdown);

View File

@@ -1,6 +1,142 @@
#include "wled.h"
/*
* Used to draw clock overlays over the strip
*/
void initCronixie()
{
if (overlayCurrent == 3 && !cronixieInit)
{
setCronixie();
strip.getSegment(0).grouping = 10; //10 LEDs per digit
cronixieInit = true;
} else if (cronixieInit && overlayCurrent != 3)
{
strip.getSegment(0).grouping = 1;
cronixieInit = false;
}
}
void handleOverlays()
{
if (millis() - overlayRefreshedTime > overlayRefreshMs)
{
initCronixie();
updateLocalTime();
checkTimers();
checkCountdown();
if (overlayCurrent == 3) _overlayCronixie();//Diamex cronixie clock kit
overlayRefreshedTime = millis();
}
}
void _overlayAnalogClock()
{
int overlaySize = overlayMax - overlayMin +1;
if (countdownMode)
{
_overlayAnalogCountdown(); return;
}
double hourP = ((double)(hour(local)%12))/12;
double minuteP = ((double)minute(local))/60;
hourP = hourP + minuteP/12;
double secondP = ((double)second(local))/60;
int hourPixel = floor(analogClock12pixel + overlaySize*hourP);
if (hourPixel > overlayMax) hourPixel = overlayMin -1 + hourPixel - overlayMax;
int minutePixel = floor(analogClock12pixel + overlaySize*minuteP);
if (minutePixel > overlayMax) minutePixel = overlayMin -1 + minutePixel - overlayMax;
int secondPixel = floor(analogClock12pixel + overlaySize*secondP);
if (secondPixel > overlayMax) secondPixel = overlayMin -1 + secondPixel - overlayMax;
if (analogClockSecondsTrail)
{
if (secondPixel < analogClock12pixel)
{
strip.setRange(analogClock12pixel, overlayMax, 0xFF0000);
strip.setRange(overlayMin, secondPixel, 0xFF0000);
} else
{
strip.setRange(analogClock12pixel, secondPixel, 0xFF0000);
}
}
if (analogClock5MinuteMarks)
{
int pix;
for (int i = 0; i <= 12; i++)
{
pix = analogClock12pixel + round((overlaySize / 12.0) *i);
if (pix > overlayMax) pix -= overlaySize;
strip.setPixelColor(pix, 0x00FFAA);
}
}
if (!analogClockSecondsTrail) strip.setPixelColor(secondPixel, 0xFF0000);
strip.setPixelColor(minutePixel, 0x00FF00);
strip.setPixelColor(hourPixel, 0x0000FF);
overlayRefreshMs = 998;
}
void _overlayAnalogCountdown()
{
if (now() < countdownTime)
{
long diff = countdownTime - now();
double pval = 60;
if (diff > 31557600L) //display in years if more than 365 days
{
pval = 315576000L; //10 years
} else if (diff > 2592000L) //display in months if more than a month
{
pval = 31557600L; //1 year
} else if (diff > 604800) //display in weeks if more than a week
{
pval = 2592000L; //1 month
} else if (diff > 86400) //display in days if more than 24 hours
{
pval = 604800; //1 week
} else if (diff > 3600) //display in hours if more than 60 minutes
{
pval = 86400; //1 day
} else if (diff > 60) //display in minutes if more than 60 seconds
{
pval = 3600; //1 hour
}
int overlaySize = overlayMax - overlayMin +1;
double perc = (pval-(double)diff)/pval;
if (perc > 1.0) perc = 1.0;
byte pixelCnt = perc*overlaySize;
if (analogClock12pixel + pixelCnt > overlayMax)
{
strip.setRange(analogClock12pixel, overlayMax, ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
strip.setRange(overlayMin, overlayMin +pixelCnt -(1+ overlayMax -analogClock12pixel), ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
} else
{
strip.setRange(analogClock12pixel, analogClock12pixel + pixelCnt, ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
}
}
overlayRefreshMs = 998;
}
void handleOverlayDraw() {
if (!overlayCurrent) return;
switch (overlayCurrent)
{
case 1: _overlayAnalogClock(); break;
case 3: _drawOverlayCronixie(); break;
}
}
/*
* Support for the Cronixie clock
*/
#ifndef WLED_DISABLE_CRONIXIE
byte _digitOut[6] = {10,10,10,10,10,10};
byte getSameCodeLength(char code, int index, char const cronixieDisplay[])
{
byte counter = 0;
@@ -19,7 +155,6 @@ byte getSameCodeLength(char code, int index, char const cronixieDisplay[])
void setCronixie()
{
#ifndef WLED_DISABLE_CRONIXIE
/*
* digit purpose index
* 0-9 | 0-9 (incl. random)
@@ -97,8 +232,8 @@ void setCronixie()
case '-': dP[i] = 11; break;
case 'r': dP[i] = random(1,7); break; //random btw. 1-6
case 'R': dP[i] = random(0,10); break; //random btw. 0-9
case 't': break; //Test upw.
case 'T': break; //Test dnw.
//case 't': break; //Test upw.
//case 'T': break; //Test dnw.
case 'b': dP[i] = 14 + getSameCodeLength('b',i,cronixieDisplay); i = i+dP[i]-14; break;
case 'B': dP[i] = 14 + getSameCodeLength('B',i,cronixieDisplay); i = i+dP[i]-14; break;
case 'h': dP[i] = 70 + getSameCodeLength('h',i,cronixieDisplay); i = i+dP[i]-70; break;
@@ -113,8 +248,8 @@ void setCronixie()
case 'y': dP[i] = 86 + getSameCodeLength('y',i,cronixieDisplay); i = i+dP[i]-86; break;
case 'I': dP[i] = 39 + getSameCodeLength('I',i,cronixieDisplay); i = i+dP[i]-39; break; //Month. Don't ask me why month and minute both start with M.
case 'i': dP[i] = 89 + getSameCodeLength('i',i,cronixieDisplay); i = i+dP[i]-89; break;
case 'W': break;
case 'w': break;
//case 'W': break;
//case 'w': break;
case 'D': dP[i] = 43 + getSameCodeLength('D',i,cronixieDisplay); i = i+dP[i]-43; break;
case 'd': dP[i] = 93 + getSameCodeLength('d',i,cronixieDisplay); i = i+dP[i]-93; break;
case '0': dP[i] = 0; break;
@@ -127,8 +262,8 @@ void setCronixie()
case '7': dP[i] = 7; break;
case '8': dP[i] = 8; break;
case '9': dP[i] = 9; break;
case 'V': break; //user var0
case 'v': break; //user var1
//case 'V': break; //user var0
//case 'v': break; //user var1
}
}
DEBUG_PRINT("result ");
@@ -140,12 +275,10 @@ void setCronixie()
DEBUG_PRINTLN((int)dP[5]);
_overlayCronixie(); //refresh
#endif
}
void _overlayCronixie()
{
#ifndef WLED_DISABLE_CRONIXIE
byte h = hour(local);
byte h0 = h;
byte m = minute(local);
@@ -161,7 +294,6 @@ void _overlayCronixie()
if (h>12) h-=12;
else if (h==0) h+=12;
}
byte _digitOut[]{10,10,10,10,10,10};
for (int i = 0; i < 6; i++)
{
if (dP[i] < 12) _digitOut[i] = dP[i];
@@ -184,8 +316,8 @@ void _overlayCronixie()
case 37: _digitOut[i] = y/10; _digitOut[i+1] = y- _digitOut[i]*10; i++; break; //YY
case 39: _digitOut[i] = 2; _digitOut[i+1] = 0; _digitOut[i+2] = y/10; _digitOut[i+3] = y- _digitOut[i+2]*10; i+=3; break; //YYYY
case 16: _digitOut[i+2] = ((h0/3)&1)?1:0; i++; //BBB (BBBB NI)
case 15: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:0; i++; //BB
//case 16: _digitOut[i+2] = ((h0/3)&1)?1:0; i++; //BBB (BBBB NI)
//case 15: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:0; i++; //BB
case 14: _digitOut[i] = (h0>11)?1:0; break; //B
}
} else
@@ -195,8 +327,8 @@ void _overlayCronixie()
case 71: _digitOut[i] = h/10; _digitOut[i+1] = h- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //hh
case 75: _digitOut[i] = m/10; _digitOut[i+1] = m- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //mm
case 81: _digitOut[i] = s/10; _digitOut[i+1] = s- _digitOut[i]*10; if(_digitOut[i] == 0) _digitOut[i]=10; i++; break; //ss
case 66: _digitOut[i+2] = ((h0/3)&1)?1:10; i++; //bbb (bbbb NI)
case 65: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:10; i++; //bb
//case 66: _digitOut[i+2] = ((h0/3)&1)?1:10; i++; //bbb (bbbb NI)
//case 65: _digitOut[i+1] = (h0>17 || (h0>5 && h0<12))?1:10; i++; //bb
case 64: _digitOut[i] = (h0>11)?1:10; break; //b
case 93: _digitOut[i] = weekday(local); _digitOut[i]--; if (_digitOut[i]<1) _digitOut[i]= 7; break; //d
@@ -208,7 +340,37 @@ void _overlayCronixie()
}
}
}
strip.setCronixieDigits(_digitOut);
//strip.trigger(); //this has a drawback, no effects slower than RefreshMs. advantage: Quick update, not dependant on effect time
#endif
}
void _drawOverlayCronixie()
{
byte offsets[] = {5, 0, 6, 1, 7, 2, 8, 3, 9, 4};
for (uint16_t i = 0; i < 6; i++)
{
byte o = 10*i;
byte excl = 10;
if(_digitOut[i] < 10) excl = offsets[_digitOut[i]];
excl += o;
if (cronixieBacklight && _digitOut[i] <11)
{
uint32_t col = strip.gamma32(strip.getSegment(0).colors[1]);
for (uint16_t j=o; j< o+10; j++) {
if (j != excl) strip.setPixelColor(j, col);
}
} else
{
for (uint16_t j=o; j< o+10; j++) {
if (j != excl) strip.setPixelColor(j, 0);
}
}
}
}
#else // WLED_DISABLE_CRONIXIE
byte getSameCodeLength(char code, int index, char const cronixieDisplay[]) {}
void setCronixie() {}
void _overlayCronixie() {}
void _drawOverlayCronixie() {}
#endif

View File

@@ -13,7 +13,9 @@
#ifndef PalettesWLED_h
#define PalettesWLED_h
DEFINE_GRADIENT_PALETTE( ib_jul01_gp ) {
#define GRADIENT_PALETTE_COUNT 39
const byte ib_jul01_gp[] PROGMEM = {
0, 194, 1, 1,
94, 1, 29, 18,
132, 57,131, 28,
@@ -24,7 +26,7 @@ DEFINE_GRADIENT_PALETTE( ib_jul01_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_vintage_57_gp ) {
const byte es_vintage_57_gp[] PROGMEM = {
0, 2, 1, 1,
53, 18, 1, 0,
104, 69, 29, 1,
@@ -37,7 +39,7 @@ DEFINE_GRADIENT_PALETTE( es_vintage_57_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 32 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_vintage_01_gp ) {
const byte es_vintage_01_gp[] PROGMEM = {
0, 4, 1, 1,
51, 16, 0, 1,
76, 97,104, 3,
@@ -53,7 +55,7 @@ DEFINE_GRADIENT_PALETTE( es_vintage_01_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_rivendell_15_gp ) {
const byte es_rivendell_15_gp[] PROGMEM = {
0, 1, 14, 5,
101, 16, 36, 14,
165, 56, 68, 30,
@@ -67,7 +69,7 @@ DEFINE_GRADIENT_PALETTE( es_rivendell_15_gp ) {
// Size: 36 bytes of program space.
// Edited to be brighter
DEFINE_GRADIENT_PALETTE( rgi_15_gp ) {
const byte rgi_15_gp[] PROGMEM = {
0, 4, 1, 70,
31, 55, 1, 30,
63, 255, 4, 7,
@@ -84,7 +86,7 @@ DEFINE_GRADIENT_PALETTE( rgi_15_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 8 bytes of program space.
DEFINE_GRADIENT_PALETTE( retro2_16_gp ) {
const byte retro2_16_gp[] PROGMEM = {
0, 188,135, 1,
255, 46, 7, 1};
@@ -94,7 +96,7 @@ DEFINE_GRADIENT_PALETTE( retro2_16_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( Analogous_1_gp ) {
const byte Analogous_1_gp[] PROGMEM = {
0, 3, 0,255,
63, 23, 0,255,
127, 67, 0,255,
@@ -107,7 +109,7 @@ DEFINE_GRADIENT_PALETTE( Analogous_1_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_pinksplash_08_gp ) {
const byte es_pinksplash_08_gp[] PROGMEM = {
0, 126, 11,255,
127, 197, 1, 22,
175, 210,157,172,
@@ -120,7 +122,7 @@ DEFINE_GRADIENT_PALETTE( es_pinksplash_08_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 16 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_ocean_breeze_036_gp ) {
const byte es_ocean_breeze_036_gp[] PROGMEM = {
0, 1, 6, 7,
89, 1, 99,111,
153, 144,209,255,
@@ -132,7 +134,7 @@ DEFINE_GRADIENT_PALETTE( es_ocean_breeze_036_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 88 bytes of program space.
DEFINE_GRADIENT_PALETTE( departure_gp ) {
const byte departure_gp[] PROGMEM = {
0, 8, 3, 0,
42, 23, 7, 0,
63, 75, 38, 6,
@@ -152,7 +154,7 @@ DEFINE_GRADIENT_PALETTE( departure_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 36 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_landscape_64_gp ) {
const byte es_landscape_64_gp[] PROGMEM = {
0, 0, 0, 0,
37, 2, 25, 1,
76, 15,115, 5,
@@ -169,7 +171,7 @@ DEFINE_GRADIENT_PALETTE( es_landscape_64_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 24 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_landscape_33_gp ) {
const byte es_landscape_33_gp[] PROGMEM = {
0, 1, 5, 0,
19, 32, 23, 1,
38, 161, 55, 1,
@@ -183,7 +185,7 @@ DEFINE_GRADIENT_PALETTE( es_landscape_33_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 28 bytes of program space.
DEFINE_GRADIENT_PALETTE( rainbowsherbet_gp ) {
const byte rainbowsherbet_gp[] PROGMEM = {
0, 255, 33, 4,
43, 255, 68, 25,
86, 255, 7, 25,
@@ -198,7 +200,7 @@ DEFINE_GRADIENT_PALETTE( rainbowsherbet_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 24 bytes of program space.
DEFINE_GRADIENT_PALETTE( gr65_hult_gp ) {
const byte gr65_hult_gp[] PROGMEM = {
0, 247,176,247,
48, 255,136,255,
89, 220, 29,226,
@@ -212,7 +214,7 @@ DEFINE_GRADIENT_PALETTE( gr65_hult_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 32 bytes of program space.
DEFINE_GRADIENT_PALETTE( gr64_hult_gp ) {
const byte gr64_hult_gp[] PROGMEM = {
0, 1,124,109,
66, 1, 93, 79,
104, 52, 65, 1,
@@ -228,7 +230,7 @@ DEFINE_GRADIENT_PALETTE( gr64_hult_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 28 bytes of program space.
DEFINE_GRADIENT_PALETTE( GMT_drywet_gp ) {
const byte GMT_drywet_gp[] PROGMEM = {
0, 47, 30, 2,
42, 213,147, 24,
84, 103,219, 52,
@@ -243,7 +245,7 @@ DEFINE_GRADIENT_PALETTE( GMT_drywet_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 24 bytes of program space.
DEFINE_GRADIENT_PALETTE( ib15_gp ) {
const byte ib15_gp[] PROGMEM = {
0, 113, 91,147,
72, 157, 88, 78,
89, 208, 85, 33,
@@ -257,7 +259,7 @@ DEFINE_GRADIENT_PALETTE( ib15_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( Tertiary_01_gp ) {
const byte Tertiary_01_gp[] PROGMEM = {
0, 0, 1,255,
63, 3, 68, 45,
127, 23,255, 0,
@@ -270,7 +272,7 @@ DEFINE_GRADIENT_PALETTE( Tertiary_01_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 52 bytes of program space.
DEFINE_GRADIENT_PALETTE( lava_gp ) {
const byte lava_gp[] PROGMEM = {
0, 0, 0, 0,
46, 18, 0, 0,
96, 113, 0, 0,
@@ -291,7 +293,7 @@ DEFINE_GRADIENT_PALETTE( lava_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 28 bytes of program space.
DEFINE_GRADIENT_PALETTE( fierce_ice_gp ) {
const byte fierce_ice_gp[] PROGMEM = {
0, 0, 0, 0,
59, 0, 9, 45,
119, 0, 38,255,
@@ -306,7 +308,7 @@ DEFINE_GRADIENT_PALETTE( fierce_ice_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 44 bytes of program space.
DEFINE_GRADIENT_PALETTE( Colorfull_gp ) {
const byte Colorfull_gp[] PROGMEM = {
0, 10, 85, 5,
25, 29,109, 18,
60, 59,138, 42,
@@ -325,7 +327,7 @@ DEFINE_GRADIENT_PALETTE( Colorfull_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 44 bytes of program space.
DEFINE_GRADIENT_PALETTE( Pink_Purple_gp ) {
const byte Pink_Purple_gp[] PROGMEM = {
0, 19, 2, 39,
25, 26, 4, 45,
51, 33, 6, 52,
@@ -344,7 +346,7 @@ DEFINE_GRADIENT_PALETTE( Pink_Purple_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 28 bytes of program space.
DEFINE_GRADIENT_PALETTE( Sunset_Real_gp ) {
const byte Sunset_Real_gp[] PROGMEM = {
0, 120, 0, 0,
22, 179, 22, 0,
51, 255,104, 0,
@@ -359,7 +361,7 @@ DEFINE_GRADIENT_PALETTE( Sunset_Real_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 44 bytes of program space.
DEFINE_GRADIENT_PALETTE( Sunset_Yellow_gp ) {
const byte Sunset_Yellow_gp[] PROGMEM = {
0, 10, 62,123,
36, 56,130,103,
87, 153,225, 85,
@@ -378,7 +380,7 @@ DEFINE_GRADIENT_PALETTE( Sunset_Yellow_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 60 bytes of program space.
DEFINE_GRADIENT_PALETTE( Beech_gp ) {
const byte Beech_gp[] PROGMEM = {
0, 255,252,214,
12, 255,252,214,
22, 255,252,214,
@@ -401,7 +403,7 @@ DEFINE_GRADIENT_PALETTE( Beech_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 32 bytes of program space.
DEFINE_GRADIENT_PALETTE( Another_Sunset_gp ) {
const byte Another_Sunset_gp[] PROGMEM = {
0, 110, 49, 11,
29, 55, 34, 10,
68, 22, 22, 9,
@@ -420,7 +422,7 @@ DEFINE_GRADIENT_PALETTE( Another_Sunset_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 52 bytes of program space.
DEFINE_GRADIENT_PALETTE( es_autumn_19_gp ) {
const byte es_autumn_19_gp[] PROGMEM = {
0, 26, 1, 1,
51, 67, 4, 1,
84, 118, 14, 1,
@@ -441,7 +443,7 @@ DEFINE_GRADIENT_PALETTE( es_autumn_19_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 28 bytes of program space.
DEFINE_GRADIENT_PALETTE( BlacK_Blue_Magenta_White_gp ) {
const byte BlacK_Blue_Magenta_White_gp[] PROGMEM = {
0, 0, 0, 0,
42, 0, 0, 45,
84, 0, 0,255,
@@ -456,7 +458,7 @@ DEFINE_GRADIENT_PALETTE( BlacK_Blue_Magenta_White_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( BlacK_Magenta_Red_gp ) {
const byte BlacK_Magenta_Red_gp[] PROGMEM = {
0, 0, 0, 0,
63, 42, 0, 45,
127, 255, 0,255,
@@ -469,7 +471,7 @@ DEFINE_GRADIENT_PALETTE( BlacK_Magenta_Red_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 28 bytes of program space.
DEFINE_GRADIENT_PALETTE( BlacK_Red_Magenta_Yellow_gp ) {
const byte BlacK_Red_Magenta_Yellow_gp[] PROGMEM = {
0, 0, 0, 0,
42, 42, 0, 0,
84, 255, 0, 0,
@@ -484,7 +486,7 @@ DEFINE_GRADIENT_PALETTE( BlacK_Red_Magenta_Yellow_gp ) {
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( Blue_Cyan_Yellow_gp ) {
const byte Blue_Cyan_Yellow_gp[] PROGMEM = {
0, 0, 0,255,
63, 0, 55,255,
127, 0,255,255,
@@ -494,7 +496,7 @@ DEFINE_GRADIENT_PALETTE( Blue_Cyan_Yellow_gp ) {
//Custom palette by Aircoookie
DEFINE_GRADIENT_PALETTE( Orange_Teal_gp ) {
const byte Orange_Teal_gp[] PROGMEM = {
0, 0,150, 92,
55, 0,150, 92,
200, 255, 72, 0,
@@ -502,7 +504,7 @@ DEFINE_GRADIENT_PALETTE( Orange_Teal_gp ) {
//Custom palette by Aircoookie
DEFINE_GRADIENT_PALETTE( Tiamat_gp ) {
const byte Tiamat_gp[] PROGMEM = {
0, 1, 2, 14, //gc
33, 2, 5, 35, //gc from 47, 61,126
100, 13,135, 92, //gc from 88,242,247
@@ -517,7 +519,7 @@ DEFINE_GRADIENT_PALETTE( Tiamat_gp ) {
//Custom palette by Aircoookie
DEFINE_GRADIENT_PALETTE( April_Night_gp ) {
const byte April_Night_gp[] PROGMEM = {
0, 1, 5, 45, //deep blue
10, 1, 5, 45,
25, 5,169,175, //light blue
@@ -536,7 +538,7 @@ DEFINE_GRADIENT_PALETTE( April_Night_gp ) {
244, 1, 5, 45,
255, 1, 5, 45};
DEFINE_GRADIENT_PALETTE( Orangery_gp ) {
const byte Orangery_gp[] PROGMEM = {
0, 255, 95, 23,
30, 255, 82, 0,
60, 223, 13, 8,
@@ -548,7 +550,7 @@ DEFINE_GRADIENT_PALETTE( Orangery_gp ) {
255, 213, 37, 4};
//inspired by Mark Kriegsman https://gist.github.com/kriegsman/756ea6dcae8e30845b5a
DEFINE_GRADIENT_PALETTE( C9_gp ) {
const byte C9_gp[] PROGMEM = {
0, 184, 4, 0, //red
60, 184, 4, 0,
65, 144, 44, 2, //amber
@@ -558,33 +560,35 @@ DEFINE_GRADIENT_PALETTE( C9_gp ) {
195, 7, 7, 88, //blue
255, 7, 7, 88};
DEFINE_GRADIENT_PALETTE( Sakura_gp ) {
const byte Sakura_gp[] PROGMEM = {
0, 196, 19, 10,
65, 255, 69, 45,
130, 223, 45, 72,
195, 255, 82,103,
255, 223, 13, 17};
DEFINE_GRADIENT_PALETTE( Aurora_gp ) {
const byte Aurora_gp[] PROGMEM = {
0, 1, 5, 45, //deep blue
64, 0,200, 23,
128, 0,255, 0, //green
170, 0,243, 45,
200, 0,135, 7,
255, 1, 5, 45};//deep blue
const byte Atlantica_gp[] PROGMEM = {
0, 0, 28,112, //#001C70
50, 32, 96,255, //#2060FF
100, 0,243, 45,
150, 12, 95, 82, //#0C5F52
200, 25,190, 95, //#19BE5F
255, 40,170, 80};//#28AA50
// Single array of defined cpt-city color palettes.
// This will let us programmatically choose one based on
// a number, rather than having to activate each explicitly
// by name every time.
// Since it is const, this array could also be moved
// into PROGMEM to save SRAM, but for simplicity of illustration
// we'll keep it in a regular SRAM array.
//
// This list of color palettes acts as a "playlist"; you can
// add or delete, or re-arrange as you wish.
const TProgmemRGBGradientPalettePtr gGradientPalettes[] = {
const byte* const gGradientPalettes[] PROGMEM = {
Sunset_Real_gp, //13-00 Sunset
es_rivendell_15_gp, //14-01 Rivendell
es_ocean_breeze_036_gp, //15-02 Breeze
@@ -623,11 +627,7 @@ const TProgmemRGBGradientPalettePtr gGradientPalettes[] = {
C9_gp, //48-35 C9
Sakura_gp, //49-36 Sakura
Aurora_gp, //50-37 Aurora
Atlantica_gp, //51-38 Atlantica
};
// Count of how many cpt-city gradients are defined:
const uint8_t gGradientPaletteCount =
sizeof( gGradientPalettes) / sizeof( TProgmemRGBGradientPalettePtr );
#endif

View File

@@ -1,8 +1,10 @@
#include "wled.h"
/*
* Receives client input
*/
void _setRandomColor(bool _sec,bool fromButton=false)
void _setRandomColor(bool _sec,bool fromButton)
{
lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex);
if (_sec){
@@ -27,8 +29,9 @@ bool isAsterisksOnly(const char* str, byte maxLen)
//called upon POST settings form submit
void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
{
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec
if (subPage <1 || subPage >6) return;
//0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX
if (subPage <1 || subPage >7) return;
//WIFI SETTINGS
if (subPage == 1)
@@ -137,11 +140,14 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
notifyTwice = request->hasArg("S2");
receiveDirect = request->hasArg("RD");
e131SkipOutOfSequence = request->hasArg("ES");
e131Multicast = request->hasArg("EM");
t = request->arg("EP").toInt();
if (t > 0) e131Port = t;
t = request->arg("EU").toInt();
if (t > 0 && t <= 63999) e131Universe = t;
if (t >= 0 && t <= 63999) e131Universe = t;
t = request->arg("DA").toInt();
if (t > 0 && t <= 510) DMXAddress = t;
if (t >= 0 && t <= 510) DMXAddress = t;
t = request->arg("DM").toInt();
if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_MULTIPLE_DRGB) DMXMode = t;
t = request->arg("ET").toInt();
@@ -215,12 +221,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
analogClockSecondsTrail = request->hasArg("OS");
strcpy(cronixieDisplay,request->arg("CX").c_str());
bool cbOld = cronixieBacklight;
cronixieBacklight = request->hasArg("CB");
if (cbOld != cronixieBacklight && overlayCurrent == 3)
{
strip.setCronixieBacklight(cronixieBacklight); overlayRefreshedTime = 0;
}
countdownMode = request->hasArg("CE");
countdownYear = request->arg("CY").toInt();
countdownMonth = request->arg("CI").toInt();
@@ -293,6 +294,33 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
aOtaEnabled = request->hasArg("AO");
}
}
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
if (subPage == 7)
{
int t = request->arg("CN").toInt();
if (t>0 && t<16) {
DMXChannels = t;
}
t = request->arg("CS").toInt();
if (t>0 && t<513) {
DMXStart = t;
}
t = request->arg("CG").toInt();
if (t>0 && t<513) {
DMXGap = t;
}
t = request->arg("SL").toInt();
if (t>=0 && t < MAX_LEDS) {
DMXStartLED = t;
}
for (int i=0; i<15; i++) {
String argname = "CH" + String((i+1));
t = request->arg(argname).toInt();
DMXFixtureMap[i] = t;
}
}
#endif
if (subPage != 6 || !doReboot) saveSettingsToEEPROM(); //do not save if factory reset
if (subPage == 2) {
strip.init(useRGBW,ledCount,skipFirstLed);
@@ -310,7 +338,7 @@ int getNumVal(const String* req, uint16_t pos)
//helper to get int value at a position in string
bool updateVal(const String* req, const char* key, byte* val, byte minv=0, byte maxv=255)
bool updateVal(const String* req, const char* key, byte* val, byte minv, byte maxv)
{
int pos = req->indexOf(key);
if (pos < 1) return false;
@@ -348,6 +376,13 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
DEBUG_PRINT("API req: ");
DEBUG_PRINTLN(req);
//write presets and macros saved to flash directly?
bool persistSaves = true;
pos = req.indexOf("NP");
if (pos > 0) {
persistSaves = false;
}
//save macro, requires &MS=<slot>(<macro>) format
pos = req.indexOf("&MS=");
if (pos > 0) {
@@ -357,7 +392,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
int en = req.indexOf(')');
String mc = req.substring(pos);
if (en > 0) mc = req.substring(pos, en);
saveMacro(i, mc);
saveMacro(i, mc, persistSaves);
}
pos = req.indexOf("IN");
@@ -385,7 +420,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
WS2812FX::Segment& mainseg = strip.getSegment(main);
pos = req.indexOf("SV="); //segment selected
if (pos > 0) mainseg.setOption(0, (req.charAt(pos+3) != '0'));
if (pos > 0) mainseg.setOption(SEG_OPTION_SELECTED, (req.charAt(pos+3) != '0'));
uint16_t startI = mainseg.start;
uint16_t stopI = mainseg.stop;
@@ -436,18 +471,12 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
pos = req.indexOf("PA="); //apply brightness from preset
if (pos > 0) presetApplyBri = (req.charAt(pos+3) != '0');
pos = req.indexOf("PC="); //apply color from preset
if (pos > 0) presetApplyCol = (req.charAt(pos+3) != '0');
pos = req.indexOf("PX="); //apply effects from preset
if (pos > 0) presetApplyFx = (req.charAt(pos+3) != '0');
pos = req.indexOf("PS="); //saves current in preset
if (pos > 0) savePreset(getNumVal(&req, pos));
if (pos > 0) savePreset(getNumVal(&req, pos), persistSaves);
//apply preset
if (updateVal(&req, "PL=", &presetCycCurr, presetCycleMin, presetCycleMax)) {
applyPreset(presetCycCurr, presetApplyBri, presetApplyCol, presetApplyFx);
applyPreset(presetCycCurr, presetApplyBri);
}
//set brightness
@@ -484,6 +513,12 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
if (pos > 0) {
colorFromDecOrHexString(colSec, (char*)req.substring(pos + 3).c_str());
}
pos = req.indexOf("C3=");
if (pos > 0) {
byte t[4];
colorFromDecOrHexString(t, (char*)req.substring(pos + 3).c_str());
strip.setColor(2, t[0], t[1], t[2], t[3]);
}
//set to random hue SR=0->1st SR=1->2nd
pos = req.indexOf("SR");
@@ -597,7 +632,17 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
//Segment reverse
pos = req.indexOf("RV=");
if (pos > 0) strip.getSegment(main).setOption(1, req.charAt(pos+3) != '0');
if (pos > 0) strip.getSegment(main).setOption(SEG_OPTION_REVERSED, req.charAt(pos+3) != '0');
//Segment brightness/opacity
pos = req.indexOf("SB=");
if (pos > 0) {
byte segbri = getNumVal(&req, pos);
strip.getSegment(main).setOption(SEG_OPTION_ON, segbri);
if (segbri) {
strip.getSegment(main).opacity = segbri;
}
}
//deactivate nightlight if target brightness is reached
if (bri == nightlightTargetBri) nightlightActive = false;
@@ -614,6 +659,9 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
if (countdownTime - now() > 0) countdownOverTriggered = false;
}
pos = req.indexOf("RB");
if (pos > 0) doReboot = true;
//cronixie
#ifndef WLED_DISABLE_CRONIXIE
//mode, 1 countdown
@@ -629,8 +677,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
pos = req.indexOf("NB=");
if (pos > 0) //sets backlight
{
presetApplyFx = (req.charAt(pos+3) != '0');
if (overlayCurrent == 3) strip.setCronixieBacklight(cronixieBacklight);
cronixieBacklight = (req.charAt(pos+3) != '0');
overlayRefreshedTime = 0;
}
#endif

View File

@@ -224,8 +224,8 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
endPin = 32 - __builtin_clz(waveformEnabled);
}
if (waveformEnabled) {
bool done = false;
if (waveformEnabled) {
do {
nextEventCycles = microsecondsToClockCycles(MAXIRQUS);
for (int i = startPin; i <= endPin; i++) {
@@ -257,7 +257,13 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
// Check for toggles
int32_t cyclesToGo = wave->nextServiceCycle - now;
if (cyclesToGo < 0) {
cyclesToGo = -((-cyclesToGo) % (wave->nextTimeHighCycles + wave->nextTimeLowCycles));
// See #7057
// The following is a no-op unless we have overshot by an entire waveform cycle.
// As modulus is an expensive operation, this code is removed for now:
// cyclesToGo = -((-cyclesToGo) % (wave->nextTimeHighCycles + wave->nextTimeLowCycles));
//
// Alternative version with lower CPU impact:
// while (-cyclesToGo > wave->nextTimeHighCycles + wave->nextTimeLowCycles) { cyclesToGo += wave->nextTimeHighCycles + wave->nextTimeLowCycles)};
waveformState ^= mask;
if (waveformState & mask) {
if (i == 16) {
@@ -309,4 +315,4 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
}
};
#endif
#endif

View File

@@ -0,0 +1,5 @@
#include "BlynkSimpleEsp.h"
WiFiClient _blynkWifiClient;
BlynkArduinoClient _blynkTransport(_blynkWifiClient);
BlynkWifi Blynk(_blynkTransport);

View File

@@ -89,8 +89,6 @@ public:
};
static WiFiClient _blynkWifiClient;
static BlynkArduinoClient _blynkTransport(_blynkWifiClient);
BlynkWifi Blynk(_blynkTransport);
extern BlynkWifi Blynk;
#endif

View File

@@ -0,0 +1,106 @@
// - - - - -
// ESPDMX - A Arduino library for sending and receiving DMX using the builtin serial hardware port.
// ESPDMX.cpp: Library implementation file
//
// Copyright (C) 2015 Rick <ricardogg95@gmail.com>
// This work is licensed under a GNU style license.
//
// Last change: Marcel Seerig <https://github.com/mseerig>
//
// Documentation and samples are available at https://github.com/Rickgg/ESP-Dmx
// - - - - -
/* ----- LIBRARIES ----- */
#include <Arduino.h>
#include "ESPDMX.h"
#define dmxMaxChannel 512
#define defaultMax 32
#define DMXSPEED 250000
#define DMXFORMAT SERIAL_8N2
#define BREAKSPEED 83333
#define BREAKFORMAT SERIAL_8N1
bool dmxStarted = false;
int sendPin = 2; //dafault on ESP8266
//DMX value array and size. Entry 0 will hold startbyte
uint8_t dmxData[dmxMaxChannel] = {};
int chanSize;
void DMXESPSerial::init() {
chanSize = defaultMax;
Serial1.begin(DMXSPEED);
pinMode(sendPin, OUTPUT);
dmxStarted = true;
}
// Set up the DMX-Protocol
void DMXESPSerial::init(int chanQuant) {
if (chanQuant > dmxMaxChannel || chanQuant <= 0) {
chanQuant = defaultMax;
}
chanSize = chanQuant;
Serial1.begin(DMXSPEED);
pinMode(sendPin, OUTPUT);
dmxStarted = true;
}
// Function to read DMX data
uint8_t DMXESPSerial::read(int Channel) {
if (dmxStarted == false) init();
if (Channel < 1) Channel = 1;
if (Channel > dmxMaxChannel) Channel = dmxMaxChannel;
return(dmxData[Channel]);
}
// Function to send DMX data
void DMXESPSerial::write(int Channel, uint8_t value) {
if (dmxStarted == false) init();
if (Channel < 1) Channel = 1;
if (Channel > chanSize) Channel = chanSize;
if (value < 0) value = 0;
if (value > 255) value = 255;
dmxData[Channel] = value;
}
void DMXESPSerial::end() {
delete dmxData;
chanSize = 0;
Serial1.end();
dmxStarted == false;
}
void DMXESPSerial::update() {
if (dmxStarted == false) init();
//Send break
digitalWrite(sendPin, HIGH);
Serial1.begin(BREAKSPEED, BREAKFORMAT);
Serial1.write(0);
Serial1.flush();
delay(1);
Serial1.end();
//send data
Serial1.begin(DMXSPEED, DMXFORMAT);
digitalWrite(sendPin, LOW);
Serial1.write(dmxData, chanSize);
Serial1.flush();
delay(1);
Serial1.end();
}
// Function to update the DMX bus

View File

@@ -0,0 +1,31 @@
// - - - - -
// ESPDMX - A Arduino library for sending and receiving DMX using the builtin serial hardware port.
// ESPDMX.cpp: Library implementation file
//
// Copyright (C) 2015 Rick <ricardogg95@gmail.com>
// This work is licensed under a GNU style license.
//
// Last change: Marcel Seerig <https://github.com/mseerig>
//
// Documentation and samples are available at https://github.com/Rickgg/ESP-Dmx
// - - - - -
#include <inttypes.h>
#ifndef ESPDMX_h
#define ESPDMX_h
// ---- Methods ----
class DMXESPSerial {
public:
void init();
void init(int MaxChan);
uint8_t read(int Channel);
void write(int channel, uint8_t value);
void update();
void end();
};
#endif

View File

@@ -23,6 +23,9 @@
// E1.17 ACN Packet Identifier
const byte ESPAsyncE131::ACN_ID[12] = { 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00 };
// Art-Net Packet Identifier
const byte ESPAsyncE131::ART_ID[8] = { 0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00 };
// Constructor
ESPAsyncE131::ESPAsyncE131(e131_packet_callback_function callback) {
_callback = callback;
@@ -34,13 +37,14 @@ ESPAsyncE131::ESPAsyncE131(e131_packet_callback_function callback) {
//
/////////////////////////////////////////////////////////
bool ESPAsyncE131::begin(e131_listen_t type, uint16_t universe, uint8_t n) {
bool ESPAsyncE131::begin(bool multicast, uint16_t port, uint16_t universe, uint8_t n) {
bool success = false;
if (type == E131_UNICAST)
success = initUnicast();
if (type == E131_MULTICAST)
success = initMulticast(universe, n);
if (multicast) {
success = initMulticast(port, universe, n);
} else {
success = initUnicast(port);
}
return success;
}
@@ -51,10 +55,10 @@ bool ESPAsyncE131::begin(e131_listen_t type, uint16_t universe, uint8_t n) {
//
/////////////////////////////////////////////////////////
bool ESPAsyncE131::initUnicast() {
bool ESPAsyncE131::initUnicast(uint16_t port) {
bool success = false;
if (udp.listen(E131_DEFAULT_PORT)) {
if (udp.listen(port)) {
udp.onPacket(std::bind(&ESPAsyncE131::parsePacket, this,
std::placeholders::_1));
success = true;
@@ -62,13 +66,13 @@ bool ESPAsyncE131::initUnicast() {
return success;
}
bool ESPAsyncE131::initMulticast(uint16_t universe, uint8_t n) {
bool ESPAsyncE131::initMulticast(uint16_t port, uint16_t universe, uint8_t n) {
bool success = false;
IPAddress address = IPAddress(239, 255, ((universe >> 8) & 0xff),
((universe >> 0) & 0xff));
if (udp.listenMulticast(address, E131_DEFAULT_PORT)) {
if (udp.listenMulticast(address, port)) {
ip4_addr_t ifaddr;
ip4_addr_t multicast_addr;
@@ -95,22 +99,31 @@ bool ESPAsyncE131::initMulticast(uint16_t universe, uint8_t n) {
/////////////////////////////////////////////////////////
void ESPAsyncE131::parsePacket(AsyncUDPPacket _packet) {
e131_error_t error = ERROR_NONE;
bool error = false, isArtnet = false;
sbuff = reinterpret_cast<e131_packet_t *>(_packet.data());
//E1.31 packet identifier ("ACS-E1.17")
if (memcmp(sbuff->acn_id, ESPAsyncE131::ACN_ID, sizeof(sbuff->acn_id)))
error = ERROR_ACN_ID;
if (htonl(sbuff->root_vector) != ESPAsyncE131::VECTOR_ROOT)
error = ERROR_VECTOR_ROOT;
if (htonl(sbuff->frame_vector) != ESPAsyncE131::VECTOR_FRAME)
error = ERROR_VECTOR_FRAME;
if (sbuff->dmp_vector != ESPAsyncE131::VECTOR_DMP)
error = ERROR_VECTOR_DMP;
if (sbuff->property_values[0] != 0)
error = ERROR_IGNORE;
isArtnet = true; //not E1.31
if (isArtnet) {
if (memcmp(sbuff->art_id, ESPAsyncE131::ART_ID, sizeof(sbuff->art_id)))
error = true; //not "Art-Net"
if (sbuff->art_opcode != ARTNET_OPCODE_OPDMX)
error = true; //not a DMX packet
} else { //E1.31 error handling
if (htonl(sbuff->root_vector) != ESPAsyncE131::VECTOR_ROOT)
error = true;
if (htonl(sbuff->frame_vector) != ESPAsyncE131::VECTOR_FRAME)
error = true;
if (sbuff->dmp_vector != ESPAsyncE131::VECTOR_DMP)
error = true;
if (sbuff->property_values[0] != 0)
error = true;
}
if (!error) {
_callback(sbuff, _packet.remoteIP());
_callback(sbuff, _packet.remoteIP(), isArtnet);
}
}
}

View File

@@ -14,9 +14,12 @@
* Author shall not be liable in any event for incidental or consequential
* damages in connection with, or arising out of, the furnishing, performance
* or use of these programs.
*
*/
/*
* Inspired by https://github.com/hideakitai/ArtNet for ArtNet support
*/
#ifndef ESPASYNCE131_H_
#define ESPASYNCE131_H_
@@ -40,7 +43,10 @@ typedef struct ip_addr ip4_addr_t;
#endif
// Defaults
#define E131_DEFAULT_PORT 5568
#define E131_DEFAULT_PORT 5568
#define ARTNET_DEFAULT_PORT 6454
#define ARTNET_OPCODE_OPDMX 0x5000
// E1.31 Packet Offsets
#define E131_ROOT_PREAMBLE_SIZE 0
@@ -69,7 +75,7 @@ typedef struct ip_addr ip4_addr_t;
// E1.31 Packet Structure
typedef union {
struct {
struct { //E1.31 packet
// Root Layer
uint16_t preamble_size;
uint16_t postamble_size;
@@ -97,34 +103,30 @@ typedef union {
uint16_t property_value_count;
uint8_t property_values[513];
} __attribute__((packed));
struct { //Art-Net packet
uint8_t art_id[8];
uint16_t art_opcode;
uint16_t art_protocol_ver;
uint8_t art_sequence_number;
uint8_t art_physical;
uint16_t art_universe;
uint16_t art_length;
uint8_t art_data[512];
} __attribute__((packed));
uint8_t raw[638];
} e131_packet_t;
// Error Types
typedef enum {
ERROR_NONE,
ERROR_IGNORE,
ERROR_ACN_ID,
ERROR_PACKET_SIZE,
ERROR_VECTOR_ROOT,
ERROR_VECTOR_FRAME,
ERROR_VECTOR_DMP
} e131_error_t;
// E1.31 Listener Types
typedef enum {
E131_UNICAST,
E131_MULTICAST
} e131_listen_t;
// new packet callback
typedef void (*e131_packet_callback_function) (e131_packet_t* p, IPAddress clientIP);
typedef void (*e131_packet_callback_function) (e131_packet_t* p, IPAddress clientIP, bool isArtnet);
class ESPAsyncE131 {
private:
// Constants for packet validation
static const uint8_t ACN_ID[];
static const uint8_t ART_ID[];
static const uint32_t VECTOR_ROOT = 4;
static const uint32_t VECTOR_FRAME = 2;
static const uint8_t VECTOR_DMP = 2;
@@ -133,8 +135,8 @@ class ESPAsyncE131 {
AsyncUDP udp; // AsyncUDP
// Internal Initializers
bool initUnicast();
bool initMulticast(uint16_t universe, uint8_t n = 1);
bool initUnicast(uint16_t port);
bool initMulticast(uint16_t port, uint16_t universe, uint8_t n = 1);
// Packet parser callback
void parsePacket(AsyncUDPPacket _packet);
@@ -145,7 +147,7 @@ class ESPAsyncE131 {
ESPAsyncE131(e131_packet_callback_function callback);
// Generic UDP listener, no physical or IP configuration
bool begin(e131_listen_t type, uint16_t universe = 1, uint8_t n = 1);
bool begin(bool multicast, uint16_t port = E131_DEFAULT_PORT, uint16_t universe = 1, uint8_t n = 1);
};
#endif // ESPASYNCE131_H_
#endif // ESPASYNCE131_H_

View File

@@ -10,7 +10,7 @@
*/
/*
* @title Espalexa library
* @version 2.4.4
* @version 2.4.5
* @author Christian Schwinne
* @license MIT
* @contributors d-999
@@ -49,7 +49,7 @@
#include <WiFiUdp.h>
#ifdef ESPALEXA_DEBUG
#pragma message "Espalexa 2.4.4 debug mode"
#pragma message "Espalexa 2.4.5 debug mode"
#define EA_DEBUG(x) Serial.print (x)
#define EA_DEBUGLN(x) Serial.println (x)
#else
@@ -164,7 +164,7 @@ private:
json += "\",\"modelid\":\"" + modelidString(dev->getType());
json += "\",\"manufacturername\":\"Philips\",\"productname\":\"E" + String(static_cast<uint8_t>(dev->getType()));
json += "\",\"uniqueid\":\"" + String(encodeLightId(deviceId+1));
json += "\",\"swversion\":\"espalexa-2.4.4\"}";
json += "\",\"swversion\":\"espalexa-2.4.5\"}";
return json;
}
@@ -188,7 +188,7 @@ private:
}
res += "\r\nFree Heap: " + (String)ESP.getFreeHeap();
res += "\r\nUptime: " + (String)millis();
res += "\r\n\r\nEspalexa library v2.4.4 by Christian Schwinne 2020";
res += "\r\n\r\nEspalexa library v2.4.5 by Christian Schwinne 2020";
server->send(200, "text/plain", res);
}
#endif
@@ -370,9 +370,10 @@ public:
if (!discoverable) return; //do not reply to M-SEARCH if not discoverable
String request = packetBuffer;
if(request.indexOf("M-SEARCH") >= 0) {
if(request.indexOf("M-SEA") >= 0) { //M-SEARCH
EA_DEBUGLN(request);
if(request.indexOf("upnp:rootdevice") > 0 || request.indexOf("asic:1") > 0 || request.indexOf("ssdp:all") > 0) {
//match upnp:rootdevice, device:basic:1, ssdp:all and ssdp:discover
if(request.indexOf("np:rootd") > 0 || request.indexOf("asic:1") > 0 || request.indexOf("dp:all") > 0 || request.indexOf("dp:dis") > 0) {
EA_DEBUGLN("Responding search req...");
respondToSearch();
}

View File

@@ -122,37 +122,28 @@ uint32_t EspalexaDevice::getRGB()
float temp = 10000/ _ct; //kelvins = 1,000,000/mired (and that /100)
float r, g, b;
// Cold white to warm white receiving from Alexa: _ct = 199, 234, 284, 350, 383 (from cold white to warm white)
switch (_ct) {
case 199: rgb[0]=255,rgb[1]=255,rgb[2]=255;rgb[3]=255;break;
case 234: rgb[0]=127,rgb[1]=127,rgb[2]=127;rgb[3]=255;break;
case 284: rgb[0]=0,rgb[1]=0,rgb[2]=0;rgb[3]=255;break;
case 350: rgb[0]=130,rgb[1]=90,rgb[2]=0;rgb[3]=255;break;
case 383: rgb[0]=255,rgb[1]=153,rgb[2]=0;rgb[3]=255;break;
default: {
if( temp <= 66 ){
r = 255;
g = temp;
g = 99.470802 * log(g) - 161.119568;
if( temp <= 19){
b = 0;
} else {
b = temp-10;
b = 138.517731 * log(b) - 305.044793;
}
} else {
r = temp - 60;
r = 329.698727 * pow(r, -0.13320476);
g = temp - 60;
g = 288.12217 * pow(g, -0.07551485 );
b = 255;
}
rgb[0] = (byte)constrain(r,0.1,255.1);
rgb[1] = (byte)constrain(g,0.1,255.1);
rgb[2] = (byte)constrain(b,0.1,255.1);
if (temp <= 66) {
r = 255;
g = temp;
g = 99.470802 * log(g) - 161.119568;
if (temp <= 19) {
b = 0;
} else {
b = temp-10;
b = 138.517731 * log(b) - 305.044793;
}
} else {
r = temp - 60;
r = 329.698727 * pow(r, -0.13320476);
g = temp - 60;
g = 288.12217 * pow(g, -0.07551485 );
b = 255;
}
rgb[0] = (byte)constrain(r,0.1,255.1);
rgb[1] = (byte)constrain(g,0.1,255.1);
rgb[2] = (byte)constrain(b,0.1,255.1);
} else if (_mode == EspalexaColorMode::hs)
{
float h = ((float)_hue)/65535.0;
@@ -226,7 +217,7 @@ uint32_t EspalexaDevice::getRGB()
rgb[1] = 255.0*g;
rgb[2] = 255.0*b;
}
_rgb = ((rgb[3] << 24) | (rgb[0] << 16) | (rgb[1] << 8) | (rgb[2])); //white value is only >0 if Alexa did provide a CT value, RGB colors will not be touched.
_rgb = ((rgb[0] << 16) | (rgb[1] << 8) | (rgb[2]));
return _rgb;
}

View File

@@ -1,13 +1,14 @@
#ifndef EspalexaDevice_h
#define EspalexaDevice_h
#include <functional>
#include "Arduino.h"
#include <functional>
typedef class EspalexaDevice;
typedef void (*BrightnessCallbackFunction) (uint8_t b);
typedef void (*DeviceCallbackFunction) (EspalexaDevice* d);
typedef void (*ColorCallbackFunction) (uint8_t br, uint32_t col);
typedef std::function<void(uint8_t b)> BrightnessCallbackFunction;
typedef std::function<void(EspalexaDevice* d)> DeviceCallbackFunction;
typedef std::function<void(uint8_t br, uint32_t col)> ColorCallbackFunction;
enum class EspalexaColorMode : uint8_t { none = 0, ct = 1, hs = 2, xy = 3 };
enum class EspalexaDeviceType : uint8_t { onoff = 0, dimmable = 1, whitespectrum = 2, color = 3, extendedcolor = 4 };

273
wled00/udp.cpp Normal file
View File

@@ -0,0 +1,273 @@
#include "wled.h"
/*
* UDP sync notifier
*/
#define WLEDPACKETSIZE 29
#define UDP_IN_MAXSIZE 1472
void notify(byte callMode, bool followUp)
{
if (!udpConnected) return;
switch (callMode)
{
case NOTIFIER_CALL_MODE_INIT: return;
case NOTIFIER_CALL_MODE_DIRECT_CHANGE: if (!notifyDirect) return; break;
case NOTIFIER_CALL_MODE_BUTTON: if (!notifyButton) return; break;
case NOTIFIER_CALL_MODE_NIGHTLIGHT: if (!notifyDirect) return; break;
case NOTIFIER_CALL_MODE_HUE: if (!notifyHue) return; break;
case NOTIFIER_CALL_MODE_PRESET_CYCLE: if (!notifyDirect) return; break;
case NOTIFIER_CALL_MODE_BLYNK: if (!notifyDirect) return; break;
case NOTIFIER_CALL_MODE_ALEXA: if (!notifyAlexa) return; break;
default: return;
}
byte udpOut[WLEDPACKETSIZE];
udpOut[0] = 0; //0: wled notifier protocol 1: WARLS protocol
udpOut[1] = callMode;
udpOut[2] = bri;
udpOut[3] = col[0];
udpOut[4] = col[1];
udpOut[5] = col[2];
udpOut[6] = nightlightActive;
udpOut[7] = nightlightDelayMins;
udpOut[8] = effectCurrent;
udpOut[9] = effectSpeed;
udpOut[10] = col[3];
//compatibilityVersionByte:
//0: old 1: supports white 2: supports secondary color
//3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
//6: supports timebase syncing, 29 byte packet 7: supports tertiary color
udpOut[11] = 7;
udpOut[12] = colSec[0];
udpOut[13] = colSec[1];
udpOut[14] = colSec[2];
udpOut[15] = colSec[3];
udpOut[16] = effectIntensity;
udpOut[17] = (transitionDelay >> 0) & 0xFF;
udpOut[18] = (transitionDelay >> 8) & 0xFF;
udpOut[19] = effectPalette;
uint32_t colTer = strip.getSegment(strip.getMainSegmentId()).colors[2];
udpOut[20] = (colTer >> 16) & 0xFF;
udpOut[21] = (colTer >> 8) & 0xFF;
udpOut[22] = (colTer >> 0) & 0xFF;
udpOut[23] = (colTer >> 24) & 0xFF;
udpOut[24] = followUp;
uint32_t t = millis() + strip.timebase;
udpOut[25] = (t >> 24) & 0xFF;
udpOut[26] = (t >> 16) & 0xFF;
udpOut[27] = (t >> 8) & 0xFF;
udpOut[28] = (t >> 0) & 0xFF;
IPAddress broadcastIp;
broadcastIp = ~uint32_t(WiFi.subnetMask()) | uint32_t(WiFi.gatewayIP());
notifierUdp.beginPacket(broadcastIp, udpPort);
notifierUdp.write(udpOut, WLEDPACKETSIZE);
notifierUdp.endPacket();
notificationSentCallMode = callMode;
notificationSentTime = millis();
notificationTwoRequired = (followUp)? false:notifyTwice;
}
void realtimeLock(uint32_t timeoutMs, byte md)
{
if (!realtimeMode && !realtimeOverride){
for (uint16_t i = 0; i < ledCount; i++)
{
strip.setPixelColor(i,0,0,0,0);
}
}
realtimeTimeout = millis() + timeoutMs;
if (timeoutMs == 255001 || timeoutMs == 65000) realtimeTimeout = UINT32_MAX;
realtimeMode = md;
if (arlsForceMaxBri && !realtimeOverride) strip.setBrightness(255);
}
void handleNotifications()
{
//send second notification if enabled
if(udpConnected && notificationTwoRequired && millis()-notificationSentTime > 250){
notify(notificationSentCallMode,true);
}
if (e131NewData && millis() - strip.getLastShow() > 15)
{
e131NewData = false;
strip.show();
}
//unlock strip when realtime UDP times out
if (realtimeMode && millis() > realtimeTimeout)
{
if (realtimeOverride == REALTIME_OVERRIDE_ONCE) realtimeOverride = REALTIME_OVERRIDE_NONE;
strip.setBrightness(bri);
realtimeMode = REALTIME_MODE_INACTIVE;
realtimeIP[0] = 0;
}
//receive UDP notifications
if (!udpConnected || !(receiveNotifications || receiveDirect)) return;
uint16_t packetSize = notifierUdp.parsePacket();
//hyperion / raw RGB
if (!packetSize && udpRgbConnected) {
packetSize = rgbUdp.parsePacket();
if (!receiveDirect) return;
if (packetSize > UDP_IN_MAXSIZE || packetSize < 3) return;
realtimeIP = rgbUdp.remoteIP();
DEBUG_PRINTLN(rgbUdp.remoteIP());
uint8_t lbuf[packetSize];
rgbUdp.read(lbuf, packetSize);
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_HYPERION);
if (realtimeOverride) return;
uint16_t id = 0;
for (uint16_t i = 0; i < packetSize -2; i += 3)
{
setRealtimePixel(id, lbuf[i], lbuf[i+1], lbuf[i+2], 0);
id++; if (id >= ledCount) break;
}
strip.show();
return;
}
//notifier and UDP realtime
if (packetSize > UDP_IN_MAXSIZE) return;
if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves
{
uint8_t udpIn[packetSize];
notifierUdp.read(udpIn, packetSize);
//wled notifier, block if realtime packets active
if (udpIn[0] == 0 && !realtimeMode && receiveNotifications)
{
//ignore notification if received within a second after sending a notification ourselves
if (millis() - notificationSentTime < 1000) return;
if (udpIn[1] > 199) return; //do not receive custom versions
bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
//apply colors from notification
if (receiveNotificationColor || !someSel)
{
col[0] = udpIn[3];
col[1] = udpIn[4];
col[2] = udpIn[5];
if (udpIn[11] > 0) //sending module's white val is intended
{
col[3] = udpIn[10];
if (udpIn[11] > 1)
{
colSec[0] = udpIn[12];
colSec[1] = udpIn[13];
colSec[2] = udpIn[14];
colSec[3] = udpIn[15];
}
if (udpIn[11] > 5)
{
uint32_t t = (udpIn[25] << 24) | (udpIn[26] << 16) | (udpIn[27] << 8) | (udpIn[28]);
t += 2;
t -= millis();
strip.timebase = t;
}
if (udpIn[11] > 6)
{
strip.setColor(2, udpIn[20], udpIn[21], udpIn[22], udpIn[23]); //tertiary color
}
}
}
//apply effects from notification
if (udpIn[11] < 200 && (receiveNotificationEffects || !someSel))
{
if (udpIn[8] < strip.getModeCount()) effectCurrent = udpIn[8];
effectSpeed = udpIn[9];
if (udpIn[11] > 2) effectIntensity = udpIn[16];
if (udpIn[11] > 4 && udpIn[19] < strip.getPaletteCount()) effectPalette = udpIn[19];
}
if (udpIn[11] > 3)
{
transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00);
}
nightlightActive = udpIn[6];
if (nightlightActive) nightlightDelayMins = udpIn[7];
if (receiveNotificationBrightness || !someSel) bri = udpIn[2];
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
} else if (udpIn[0] > 0 && udpIn[0] < 5 && receiveDirect) //1 warls //2 drgb //3 drgbw
{
realtimeIP = notifierUdp.remoteIP();
DEBUG_PRINTLN(notifierUdp.remoteIP());
if (packetSize < 2) return;
if (udpIn[1] == 0)
{
realtimeTimeout = 0;
return;
} else {
realtimeLock(udpIn[1]*1000 +1, REALTIME_MODE_UDP);
}
if (realtimeOverride) return;
if (udpIn[0] == 1) //warls
{
for (uint16_t i = 2; i < packetSize -3; i += 4)
{
setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0);
}
} else if (udpIn[0] == 2) //drgb
{
uint16_t id = 0;
for (uint16_t i = 2; i < packetSize -2; i += 3)
{
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
id++; if (id >= ledCount) break;
}
} else if (udpIn[0] == 3) //drgbw
{
uint16_t id = 0;
for (uint16_t i = 2; i < packetSize -3; i += 4)
{
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
id++; if (id >= ledCount) break;
}
} else if (udpIn[0] == 4) //dnrgb
{
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
for (uint16_t i = 4; i < packetSize -2; i += 3)
{
if (id >= ledCount) break;
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
id++;
}
}
strip.show();
}
}
}
void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w)
{
uint16_t pix = i + arlsOffset;
if (pix < ledCount)
{
if (!arlsDisableGammaCorrection && strip.gammaCorrectCol)
{
strip.setPixelColor(pix, strip.gamma8(r), strip.gamma8(g), strip.gamma8(b), strip.gamma8(w));
} else {
strip.setPixelColor(pix, r, g, b, w);
}
}
}

View File

@@ -1,7 +1,8 @@
#include "wled.h"
/*
* This file allows you to add own functionality to WLED more easily
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled01_eeprom.h)
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
* bytes 2400+ are currently ununsed, but might be used for future wled features
*/

461
wled00/wled.cpp Normal file
View File

@@ -0,0 +1,461 @@
#define WLED_DEFINE_GLOBAL_VARS //only in one source file, wled.cpp!
#include "wled.h"
#include <Arduino.h>
/*
* Main WLED class implementation. Mostly initialization and connection logic
*/
WLED::WLED()
{
}
// turns all LEDs off and restarts ESP
void WLED::reset()
{
briT = 0;
long dly = millis();
while (millis() - dly < 250) {
yield(); // enough time to send response to client
}
setAllLeds();
DEBUG_PRINTLN("MODULE RESET");
ESP.restart();
}
bool oappendi(int i)
{
char s[11];
sprintf(s, "%ld", i);
return oappend(s);
}
bool oappend(const char* txt)
{
uint16_t len = strlen(txt);
if (olen + len >= OMAX)
return false; // buffer full
strcpy(obuf + olen, txt);
olen += len;
return true;
}
void WLED::loop()
{
handleIR(); // 2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too
handleConnection();
handleSerial();
handleNotifications();
handleTransitions();
#ifdef WLED_ENABLE_DMX
handleDMX();
#endif
userLoop();
yield();
handleIO();
handleIR();
handleNetworkTime();
handleAlexa();
handleOverlays();
yield();
#ifdef WLED_USE_ANALOG_LEDS
strip.setRgbwPwm();
#endif
if (doReboot)
reset();
if (!realtimeMode || realtimeOverride) // block stuff if WARLS/Adalight is enabled
{
if (apActive)
dnsServer.processNextRequest();
#ifndef WLED_DISABLE_OTA
if (WLED_CONNECTED && aOtaEnabled)
ArduinoOTA.handle();
#endif
handleNightlight();
yield();
handleHue();
handleBlynk();
yield();
if (!offMode)
strip.service();
}
yield();
#ifdef ESP8266
MDNS.update();
#endif
if (millis() - lastMqttReconnectAttempt > 30000) {
if (lastMqttReconnectAttempt > millis()) rolloverMillis++; //millis() rolls over every 50 days
initMqtt();
}
// DEBUG serial logging
#ifdef WLED_DEBUG
if (millis() - debugTime > 9999) {
DEBUG_PRINTLN("---DEBUG INFO---");
DEBUG_PRINT("Runtime: ");
DEBUG_PRINTLN(millis());
DEBUG_PRINT("Unix time: ");
DEBUG_PRINTLN(now());
DEBUG_PRINT("Free heap: ");
DEBUG_PRINTLN(ESP.getFreeHeap());
DEBUG_PRINT("Wifi state: ");
DEBUG_PRINTLN(WiFi.status());
if (WiFi.status() != lastWifiState) {
wifiStateChangedTime = millis();
}
lastWifiState = WiFi.status();
DEBUG_PRINT("State time: ");
DEBUG_PRINTLN(wifiStateChangedTime);
DEBUG_PRINT("NTP last sync: ");
DEBUG_PRINTLN(ntpLastSyncTime);
DEBUG_PRINT("Client IP: ");
DEBUG_PRINTLN(WiFi.localIP());
DEBUG_PRINT("Loops/sec: ");
DEBUG_PRINTLN(loops / 10);
loops = 0;
debugTime = millis();
}
loops++;
#endif // WLED_DEBU
}
void WLED::setup()
{
EEPROM.begin(EEPSIZE);
ledCount = EEPROM.read(229) + ((EEPROM.read(398) << 8) & 0xFF00);
if (ledCount > MAX_LEDS || ledCount == 0)
ledCount = 30;
#ifdef ESP8266
#if LEDPIN == 3
if (ledCount > MAX_LEDS_DMA)
ledCount = MAX_LEDS_DMA; // DMA method uses too much ram
#endif
#endif
Serial.begin(115200);
Serial.setTimeout(50);
DEBUG_PRINTLN();
DEBUG_PRINT("---WLED ");
DEBUG_PRINT(versionString);
DEBUG_PRINT(" ");
DEBUG_PRINT(VERSION);
DEBUG_PRINTLN(" INIT---");
#ifdef ARDUINO_ARCH_ESP32
DEBUG_PRINT("esp32 ");
DEBUG_PRINTLN(ESP.getSdkVersion());
#else
DEBUG_PRINT("esp8266 ");
DEBUG_PRINTLN(ESP.getCoreVersion());
#endif
int heapPreAlloc = ESP.getFreeHeap();
DEBUG_PRINT("heap ");
DEBUG_PRINTLN(ESP.getFreeHeap());
strip.init(EEPROM.read(372), ledCount, EEPROM.read(2204)); // init LEDs quickly
strip.setBrightness(0);
DEBUG_PRINT("LEDs inited. heap usage ~");
DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
#ifndef WLED_DISABLE_FILESYSTEM
#ifdef ARDUINO_ARCH_ESP32
SPIFFS.begin(true);
#endif
SPIFFS.begin();
#endif
DEBUG_PRINTLN("Load EEPROM");
loadSettingsFromEEPROM(true);
beginStrip();
userSetup();
if (strcmp(clientSSID, DEFAULT_CLIENT_SSID) == 0)
showWelcomePage = true;
WiFi.persistent(false);
if (macroBoot > 0)
applyMacro(macroBoot);
Serial.println("Ada");
// generate module IDs
escapedMac = WiFi.macAddress();
escapedMac.replace(":", "");
escapedMac.toLowerCase();
if (strcmp(cmDNS, "x") == 0) // fill in unique mdns default
{
strcpy(cmDNS, "wled-");
sprintf(cmDNS + 5, "%*s", 6, escapedMac.c_str() + 6);
}
if (mqttDeviceTopic[0] == 0) {
strcpy(mqttDeviceTopic, "wled/");
sprintf(mqttDeviceTopic + 5, "%*s", 6, escapedMac.c_str() + 6);
}
if (mqttClientID[0] == 0) {
strcpy(mqttClientID, "WLED-");
sprintf(mqttClientID + 5, "%*s", 6, escapedMac.c_str() + 6);
}
strip.service();
#ifndef WLED_DISABLE_OTA
if (aOtaEnabled) {
ArduinoOTA.onStart([]() {
#ifdef ESP8266
wifi_set_sleep_type(NONE_SLEEP_T);
#endif
DEBUG_PRINTLN("Start ArduinoOTA");
});
if (strlen(cmDNS) > 0)
ArduinoOTA.setHostname(cmDNS);
}
#endif
#ifdef WLED_ENABLE_DMX
initDMX();
#endif
// HTTP server page init
initServer();
}
void WLED::beginStrip()
{
// Initialize NeoPixel Strip and button
strip.setShowCallback(handleOverlayDraw);
#ifdef BTNPIN
pinMode(BTNPIN, INPUT_PULLUP);
#endif
if (bootPreset > 0)
applyPreset(bootPreset, turnOnAtBoot);
colorUpdated(NOTIFIER_CALL_MODE_INIT);
// init relay pin
#if RLYPIN >= 0
pinMode(RLYPIN, OUTPUT);
#if RLYMDE
digitalWrite(RLYPIN, bri);
#else
digitalWrite(RLYPIN, !bri);
#endif
#endif
// disable button if it is "pressed" unintentionally
#ifdef BTNPIN
if (digitalRead(BTNPIN) == LOW)
buttonEnabled = false;
#else
buttonEnabled = false;
#endif
}
void WLED::initAP(bool resetAP)
{
if (apBehavior == AP_BEHAVIOR_BUTTON_ONLY && !resetAP)
return;
if (!apSSID[0] || resetAP)
strcpy(apSSID, "WLED-AP");
if (resetAP)
strcpy(apPass, DEFAULT_AP_PASS);
DEBUG_PRINT("Opening access point ");
DEBUG_PRINTLN(apSSID);
WiFi.softAPConfig(IPAddress(4, 3, 2, 1), IPAddress(4, 3, 2, 1), IPAddress(255, 255, 255, 0));
WiFi.softAP(apSSID, apPass, apChannel, apHide);
if (!apActive) // start captive portal if AP active
{
DEBUG_PRINTLN("Init AP interfaces");
server.begin();
if (udpPort > 0 && udpPort != ntpLocalPort) {
udpConnected = notifierUdp.begin(udpPort);
}
if (udpRgbPort > 0 && udpRgbPort != ntpLocalPort && udpRgbPort != udpPort) {
udpRgbConnected = rgbUdp.begin(udpRgbPort);
}
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start(53, "*", WiFi.softAPIP());
}
apActive = true;
}
void WLED::initConnection()
{
WiFi.disconnect(true); // close old connections
#ifdef ESP8266
WiFi.setPhyMode(WIFI_PHY_MODE_11N);
#endif
if (staticIP[0] != 0 && staticGateway[0] != 0) {
WiFi.config(staticIP, staticGateway, staticSubnet, IPAddress(8, 8, 8, 8));
} else {
WiFi.config(0U, 0U, 0U);
}
lastReconnectAttempt = millis();
if (!WLED_WIFI_CONFIGURED) {
DEBUG_PRINT("No connection configured. ");
if (!apActive)
initAP(); // instantly go to ap mode
return;
} else if (!apActive) {
if (apBehavior == AP_BEHAVIOR_ALWAYS) {
initAP();
} else {
DEBUG_PRINTLN("Access point disabled.");
WiFi.softAPdisconnect(true);
WiFi.mode(WIFI_STA);
}
}
showWelcomePage = false;
DEBUG_PRINT("Connecting to ");
DEBUG_PRINT(clientSSID);
DEBUG_PRINTLN("...");
#ifdef ESP8266
WiFi.hostname(serverDescription);
#endif
WiFi.begin(clientSSID, clientPass);
#ifdef ARDUINO_ARCH_ESP32
WiFi.setSleep(!noWifiSleep);
WiFi.setHostname(serverDescription);
#else
wifi_set_sleep_type((noWifiSleep) ? NONE_SLEEP_T : MODEM_SLEEP_T);
#endif
}
void WLED::initInterfaces()
{
DEBUG_PRINTLN("Init STA interfaces");
if (hueIP[0] == 0) {
hueIP[0] = WiFi.localIP()[0];
hueIP[1] = WiFi.localIP()[1];
hueIP[2] = WiFi.localIP()[2];
}
// init Alexa hue emulation
if (alexaEnabled)
alexaInit();
#ifndef WLED_DISABLE_OTA
if (aOtaEnabled)
ArduinoOTA.begin();
#endif
strip.service();
// Set up mDNS responder:
if (strlen(cmDNS) > 0) {
if (!aOtaEnabled)
MDNS.begin(cmDNS);
DEBUG_PRINTLN("mDNS started");
MDNS.addService("http", "tcp", 80);
MDNS.addService("wled", "tcp", 80);
MDNS.addServiceTxt("wled", "tcp", "mac", escapedMac.c_str());
}
server.begin();
if (udpPort > 0 && udpPort != ntpLocalPort) {
udpConnected = notifierUdp.begin(udpPort);
if (udpConnected && udpRgbPort != udpPort)
udpRgbConnected = rgbUdp.begin(udpRgbPort);
}
if (ntpEnabled)
ntpConnected = ntpUdp.begin(ntpLocalPort);
initBlynk(blynkApiKey);
e131.begin(e131Multicast, e131Port, e131Universe, E131_MAX_UNIVERSE_COUNT);
reconnectHue();
initMqtt();
interfacesInited = true;
wasConnected = true;
}
byte stacO = 0;
uint32_t lastHeap;
unsigned long heapTime = 0;
void WLED::handleConnection()
{
if (millis() < 2000 && (!WLED_WIFI_CONFIGURED || apBehavior == AP_BEHAVIOR_ALWAYS))
return;
if (lastReconnectAttempt == 0)
initConnection();
// reconnect WiFi to clear stale allocations if heap gets too low
if (millis() - heapTime > 5000) {
uint32_t heap = ESP.getFreeHeap();
if (heap < 9000 && lastHeap < 9000) {
DEBUG_PRINT("Heap too low! ");
DEBUG_PRINTLN(heap);
forceReconnect = true;
}
lastHeap = heap;
heapTime = millis();
}
byte stac = 0;
if (apActive) {
#ifdef ESP8266
stac = wifi_softap_get_station_num();
#else
wifi_sta_list_t stationList;
esp_wifi_ap_get_sta_list(&stationList);
stac = stationList.num;
#endif
if (stac != stacO) {
stacO = stac;
DEBUG_PRINT("Connected AP clients: ");
DEBUG_PRINTLN(stac);
if (!WLED_CONNECTED && WLED_WIFI_CONFIGURED) { // trying to connect, but not connected
if (stac)
WiFi.disconnect(); // disable search so that AP can work
else
initConnection(); // restart search
}
}
}
if (forceReconnect) {
DEBUG_PRINTLN("Forcing reconnect.");
initConnection();
interfacesInited = false;
forceReconnect = false;
wasConnected = false;
return;
}
if (!WLED_CONNECTED) {
if (interfacesInited) {
DEBUG_PRINTLN("Disconnected!");
interfacesInited = false;
initConnection();
}
if (millis() - lastReconnectAttempt > ((stac) ? 300000 : 20000) && WLED_WIFI_CONFIGURED)
initConnection();
if (!apActive && millis() - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == AP_BEHAVIOR_NO_CONN))
initAP();
} else if (!interfacesInited) { // newly connected
DEBUG_PRINTLN("");
DEBUG_PRINT("Connected! IP address: ");
DEBUG_PRINTLN(WiFi.localIP());
initInterfaces();
userConnected();
// shut down AP
if (apBehavior != AP_BEHAVIOR_ALWAYS && apActive) {
dnsServer.stop();
WiFi.softAPdisconnect(true);
apActive = false;
DEBUG_PRINTLN("Access point disabled.");
}
}
}

523
wled00/wled.h Normal file
View File

@@ -0,0 +1,523 @@
#ifndef WLED_H
#define WLED_H
/*
Main sketch, global variable declarations
@title WLED project sketch
@version 0.10.0
@author Christian Schwinne
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2005030
// ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS).
// ESP8266-01 (black) has 1MB flash and can thus fit the whole program. Use 1M(64K SPIFFS).
// Uncomment some of the following lines to disable features to compile for ESP8266-01 (max flash size 434kB):
// Alternatively, with platformio pass your chosen flags to your custom build target in platformio.ini.override
// You are required to disable over-the-air updates:
//#define WLED_DISABLE_OTA // saves 14kb
// You need to choose some of these features to disable:
//#define WLED_DISABLE_ALEXA // saves 11kb
//#define WLED_DISABLE_BLYNK // saves 6kb
//#define WLED_DISABLE_CRONIXIE // saves 3kb
//#define WLED_DISABLE_HUESYNC // saves 4kb
//#define WLED_DISABLE_INFRARED // there is no pin left for this on ESP8266-01, saves 12kb
#define WLED_ENABLE_MQTT // saves 12kb
#define WLED_ENABLE_ADALIGHT // saves 500b only
//#define WLED_ENABLE_DMX // uses 3.5kb (use LEDPIN other than 2)
#define WLED_DISABLE_FILESYSTEM // SPIFFS is not used by any WLED feature yet
//#define WLED_ENABLE_FS_SERVING // Enable sending html file from SPIFFS before serving progmem version
//#define WLED_ENABLE_FS_EDITOR // enable /edit page for editing SPIFFS content. Will also be disabled with OTA lock
// to toggle usb serial debug (un)comment the following line
//#define WLED_DEBUG
// Library inclusions.
#include <Arduino.h>
#ifdef ESP8266
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ESPAsyncTCP.h>
extern "C"
{
#include <user_interface.h>
}
#else // ESP32
#include <WiFi.h>
#include "esp_wifi.h"
#include <ESPmDNS.h>
#include <AsyncTCP.h>
#include "SPIFFS.h"
#endif
#include <ESPAsyncWebServer.h>
#include <EEPROM.h>
#include <WiFiUdp.h>
#include <DNSServer.h>
#ifndef WLED_DISABLE_OTA
#include <ArduinoOTA.h>
#endif
#include <SPIFFSEditor.h>
#include "src/dependencies/time/TimeLib.h"
#include "src/dependencies/timezone/Timezone.h"
#ifndef WLED_DISABLE_ALEXA
#define ESPALEXA_ASYNC
#define ESPALEXA_NO_SUBPAGE
#define ESPALEXA_MAXDEVICES 1
// #define ESPALEXA_DEBUG
#include "src/dependencies/espalexa/Espalexa.h"
#endif
#ifndef WLED_DISABLE_BLYNK
#include "src/dependencies/blynk/BlynkSimpleEsp.h"
#endif
#include "src/dependencies/e131/ESPAsyncE131.h"
#include "src/dependencies/async-mqtt-client/AsyncMqttClient.h"
#include "src/dependencies/json/AsyncJson-v6.h"
#include "src/dependencies/json/ArduinoJson-v6.h"
#include "fcn_declare.h"
#include "html_ui.h"
#include "html_settings.h"
#include "html_other.h"
#include "FX.h"
#include "ir_codes.h"
#include "const.h"
#ifndef CLIENT_SSID
#define CLIENT_SSID DEFAULT_CLIENT_SSID
#endif
#ifndef CLIENT_PASS
#define CLIENT_PASS ""
#endif
#if IR_PIN < 0
#ifndef WLED_DISABLE_INFRARED
#define WLED_DISABLE_INFRARED
#endif
#endif
#ifndef WLED_DISABLE_INFRARED
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRutils.h>
#endif
// remove flicker because PWM signal of RGB channels can become out of phase
#if defined(WLED_USE_ANALOG_LEDS) && defined(ESP8266)
#include "src/dependencies/arduino/core_esp8266_waveform.h"
#endif
// enable additional debug output
#ifdef WLED_DEBUG
#ifndef ESP8266
#include <rom/rtc.h>
#endif
#define DEBUG_PRINT(x) Serial.print(x)
#define DEBUG_PRINTLN(x) Serial.println(x)
#define DEBUG_PRINTF(x) Serial.printf(x)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#define DEBUG_PRINTF(x)
#endif
// GLOBAL VARIABLES
// both declared and defined in header (solution from http://www.keil.com/support/docs/1868.htm)
//
//e.g. byte test = 2 becomes WLED_GLOBAL byte test _INIT(2);
// int arr[]{0,1,2} becomes WLED_GLOBAL int arr[] _INIT_N(({0,1,2}));
#ifndef WLED_DEFINE_GLOBAL_VARS
# define WLED_GLOBAL extern
# define _INIT(x)
# define _INIT_N(x)
#else
# define WLED_GLOBAL
# define _INIT(x) = x
//needed to ignore commas in array definitions
#define UNPACK( ... ) __VA_ARGS__
# define _INIT_N(x) UNPACK x
#endif
// Global Variable definitions
WLED_GLOBAL char versionString[] _INIT("0.10.0");
#define WLED_CODENAME "Namigai"
// AP and OTA default passwords (for maximum security change them!)
WLED_GLOBAL char apPass[65] _INIT(DEFAULT_AP_PASS);
WLED_GLOBAL char otaPass[33] _INIT(DEFAULT_OTA_PASS);
// Hardware CONFIG (only changeble HERE, not at runtime)
// LED strip pin, button pin and IR pin changeable in NpbWrapper.h!
WLED_GLOBAL byte auxDefaultState _INIT(0); // 0: input 1: high 2: low
WLED_GLOBAL byte auxTriggeredState _INIT(0); // 0: input 1: high 2: low
WLED_GLOBAL char ntpServerName[33] _INIT("0.wled.pool.ntp.org"); // NTP server to use
// WiFi CONFIG (all these can be changed via web UI, no need to set them here)
WLED_GLOBAL char clientSSID[33] _INIT(CLIENT_SSID);
WLED_GLOBAL char clientPass[65] _INIT(CLIENT_PASS);
WLED_GLOBAL char cmDNS[33] _INIT("x"); // mDNS address (placeholder, is replaced by wledXXXXXX.local)
WLED_GLOBAL char apSSID[33] _INIT(""); // AP off by default (unless setup)
WLED_GLOBAL byte apChannel _INIT(1); // 2.4GHz WiFi AP channel (1-13)
WLED_GLOBAL byte apHide _INIT(0); // hidden AP SSID
WLED_GLOBAL byte apBehavior _INIT(AP_BEHAVIOR_BOOT_NO_CONN); // access point opens when no connection after boot by default
WLED_GLOBAL IPAddress staticIP _INIT_N((( 0, 0, 0, 0))); // static IP of ESP
WLED_GLOBAL IPAddress staticGateway _INIT_N((( 0, 0, 0, 0))); // gateway (router) IP
WLED_GLOBAL IPAddress staticSubnet _INIT_N(((255, 255, 255, 0))); // most common subnet in home networks
WLED_GLOBAL bool noWifiSleep _INIT(false); // disabling modem sleep modes will increase heat output and power usage, but may help with connection issues
// LED CONFIG
WLED_GLOBAL uint16_t ledCount _INIT(30); // overcurrent prevented by ABL
WLED_GLOBAL bool useRGBW _INIT(false); // SK6812 strips can contain an extra White channel
WLED_GLOBAL bool turnOnAtBoot _INIT(true); // turn on LEDs at power-up
WLED_GLOBAL byte bootPreset _INIT(0); // save preset to load after power-up
WLED_GLOBAL byte col[] _INIT_N(({ 255, 160, 0, 0 })); // current RGB(W) primary color. col[] should be updated if you want to change the color.
WLED_GLOBAL byte colSec[] _INIT_N(({ 0, 0, 0, 0 })); // current RGB(W) secondary color
WLED_GLOBAL byte briS _INIT(128); // default brightness
WLED_GLOBAL byte nightlightTargetBri _INIT(0); // brightness after nightlight is over
WLED_GLOBAL byte nightlightDelayMins _INIT(60);
WLED_GLOBAL bool nightlightFade _INIT(true); // if enabled, light will gradually dim towards the target bri. Otherwise, it will instantly set after delay over
WLED_GLOBAL bool nightlightColorFade _INIT(false); // if enabled, light will gradually fade color from primary to secondary color.
WLED_GLOBAL bool fadeTransition _INIT(true); // enable crossfading color transition
WLED_GLOBAL uint16_t transitionDelay _INIT(750); // default crossfade duration in ms
WLED_GLOBAL bool skipFirstLed _INIT(false); // ignore first LED in strip (useful if you need the LED as signal repeater)
WLED_GLOBAL byte briMultiplier _INIT(100); // % of brightness to set (to limit power, if you set it to 50 and set bri to 255, actual brightness will be 127)
// User Interface CONFIG
WLED_GLOBAL char serverDescription[33] _INIT("WLED"); // Name of module
WLED_GLOBAL bool syncToggleReceive _INIT(false); // UIs which only have a single button for sync should toggle send+receive if this is true, only send otherwise
// Sync CONFIG
WLED_GLOBAL bool buttonEnabled _INIT(true);
WLED_GLOBAL byte irEnabled _INIT(0); // Infrared receiver
WLED_GLOBAL uint16_t udpPort _INIT(21324); // WLED notifier default port
WLED_GLOBAL uint16_t udpRgbPort _INIT(19446); // Hyperion port
WLED_GLOBAL bool receiveNotificationBrightness _INIT(true); // apply brightness from incoming notifications
WLED_GLOBAL bool receiveNotificationColor _INIT(true); // apply color
WLED_GLOBAL bool receiveNotificationEffects _INIT(true); // apply effects setup
WLED_GLOBAL bool notifyDirect _INIT(false); // send notification if change via UI or HTTP API
WLED_GLOBAL bool notifyButton _INIT(false); // send if updated by button or infrared remote
WLED_GLOBAL bool notifyAlexa _INIT(false); // send notification if updated via Alexa
WLED_GLOBAL bool notifyMacro _INIT(false); // send notification for macro
WLED_GLOBAL bool notifyHue _INIT(true); // send notification if Hue light changes
WLED_GLOBAL bool notifyTwice _INIT(false); // notifications use UDP: enable if devices don't sync reliably
WLED_GLOBAL bool alexaEnabled _INIT(true); // enable device discovery by Amazon Echo
WLED_GLOBAL char alexaInvocationName[33] _INIT("Light"); // speech control name of device. Choose something voice-to-text can understand
WLED_GLOBAL char blynkApiKey[36] _INIT(""); // Auth token for Blynk server. If empty, no connection will be made
WLED_GLOBAL uint16_t realtimeTimeoutMs _INIT(2500); // ms timeout of realtime mode before returning to normal mode
WLED_GLOBAL int arlsOffset _INIT(0); // realtime LED offset
WLED_GLOBAL bool receiveDirect _INIT(true); // receive UDP realtime
WLED_GLOBAL bool arlsDisableGammaCorrection _INIT(true); // activate if gamma correction is handled by the source
WLED_GLOBAL bool arlsForceMaxBri _INIT(false); // enable to force max brightness if source has very dark colors that would be black
WLED_GLOBAL uint16_t e131Universe _INIT(1); // settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consequtive universes)
WLED_GLOBAL uint16_t e131Port _INIT(5568); // DMX in port. E1.31 default is 5568, Art-Net is 6454
WLED_GLOBAL byte DMXMode _INIT(DMX_MODE_MULTIPLE_RGB); // DMX mode (s.a.)
WLED_GLOBAL uint16_t DMXAddress _INIT(1); // DMX start address of fixture, a.k.a. first Channel [for E1.31 (sACN) protocol]
WLED_GLOBAL byte DMXOldDimmer _INIT(0); // only update brightness on change
WLED_GLOBAL byte e131LastSequenceNumber[E131_MAX_UNIVERSE_COUNT]; // to detect packet loss
WLED_GLOBAL bool e131Multicast _INIT(false); // multicast or unicast
WLED_GLOBAL bool e131SkipOutOfSequence _INIT(false); // freeze instead of flickering
WLED_GLOBAL bool mqttEnabled _INIT(false);
WLED_GLOBAL char mqttDeviceTopic[33] _INIT(""); // main MQTT topic (individual per device, default is wled/mac)
WLED_GLOBAL char mqttGroupTopic[33] _INIT("wled/all"); // second MQTT topic (for example to group devices)
WLED_GLOBAL char mqttServer[33] _INIT(""); // both domains and IPs should work (no SSL)
WLED_GLOBAL char mqttUser[41] _INIT(""); // optional: username for MQTT auth
WLED_GLOBAL char mqttPass[41] _INIT(""); // optional: password for MQTT auth
WLED_GLOBAL char mqttClientID[41] _INIT(""); // override the client ID
WLED_GLOBAL uint16_t mqttPort _INIT(1883);
WLED_GLOBAL bool huePollingEnabled _INIT(false); // poll hue bridge for light state
WLED_GLOBAL uint16_t huePollIntervalMs _INIT(2500); // low values (< 1sec) may cause lag but offer quicker response
WLED_GLOBAL char hueApiKey[47] _INIT("api"); // key token will be obtained from bridge
WLED_GLOBAL byte huePollLightId _INIT(1); // ID of hue lamp to sync to. Find the ID in the hue app ("about" section)
WLED_GLOBAL IPAddress hueIP _INIT((0, 0, 0, 0)); // IP address of the bridge
WLED_GLOBAL bool hueApplyOnOff _INIT(true);
WLED_GLOBAL bool hueApplyBri _INIT(true);
WLED_GLOBAL bool hueApplyColor _INIT(true);
// Time CONFIG
WLED_GLOBAL bool ntpEnabled _INIT(false); // get internet time. Only required if you use clock overlays or time-activated macros
WLED_GLOBAL bool useAMPM _INIT(false); // 12h/24h clock format
WLED_GLOBAL byte currentTimezone _INIT(0); // Timezone ID. Refer to timezones array in wled10_ntp.ino
WLED_GLOBAL int utcOffsetSecs _INIT(0); // Seconds to offset from UTC before timzone calculation
WLED_GLOBAL byte overlayDefault _INIT(0); // 0: no overlay 1: analog clock 2: single-digit clocl 3: cronixie
WLED_GLOBAL byte overlayMin _INIT(0), overlayMax _INIT(ledCount - 1); // boundaries of overlay mode
WLED_GLOBAL byte analogClock12pixel _INIT(0); // The pixel in your strip where "midnight" would be
WLED_GLOBAL bool analogClockSecondsTrail _INIT(false); // Display seconds as trail of LEDs instead of a single pixel
WLED_GLOBAL bool analogClock5MinuteMarks _INIT(false); // Light pixels at every 5-minute position
WLED_GLOBAL char cronixieDisplay[7] _INIT("HHMMSS"); // Cronixie Display mask. See wled13_cronixie.ino
WLED_GLOBAL bool cronixieBacklight _INIT(true); // Allow digits to be back-illuminated
WLED_GLOBAL bool countdownMode _INIT(false); // Clock will count down towards date
WLED_GLOBAL byte countdownYear _INIT(20), countdownMonth _INIT(1); // Countdown target date, year is last two digits
WLED_GLOBAL byte countdownDay _INIT(1) , countdownHour _INIT(0);
WLED_GLOBAL byte countdownMin _INIT(0) , countdownSec _INIT(0);
WLED_GLOBAL byte macroBoot _INIT(0); // macro loaded after startup
WLED_GLOBAL byte macroNl _INIT(0); // after nightlight delay over
WLED_GLOBAL byte macroCountdown _INIT(0);
WLED_GLOBAL byte macroAlexaOn _INIT(0), macroAlexaOff _INIT(0);
WLED_GLOBAL byte macroButton _INIT(0), macroLongPress _INIT(0), macroDoublePress _INIT(0);
// Security CONFIG
WLED_GLOBAL bool otaLock _INIT(false); // prevents OTA firmware updates without password. ALWAYS enable if system exposed to any public networks
WLED_GLOBAL bool wifiLock _INIT(false); // prevents access to WiFi settings when OTA lock is enabled
WLED_GLOBAL bool aOtaEnabled _INIT(true); // ArduinoOTA allows easy updates directly from the IDE. Careful, it does not auto-disable when OTA lock is on
WLED_GLOBAL uint16_t userVar0 _INIT(0), userVar1 _INIT(0); //available for use in usermod
#ifdef WLED_ENABLE_DMX
// dmx CONFIG
WLED_GLOBAL byte DMXChannels _INIT(7); // number of channels per fixture
WLED_GLOBAL byte DMXFixtureMap[15] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }));
// assigns the different channels to different functions. See wled21_dmx.ino for more information.
WLED_GLOBAL uint16_t DMXGap _INIT(10); // gap between the fixtures. makes addressing easier because you don't have to memorize odd numbers when climbing up onto a rig.
WLED_GLOBAL uint16_t DMXStart _INIT(10); // start address of the first fixture
WLED_GLOBAL uint16_t DMXStartLED _INIT(0); // LED from which DMX fixtures start
#endif
// internal global variable declarations
// wifi
WLED_GLOBAL bool apActive _INIT(false);
WLED_GLOBAL bool forceReconnect _INIT(false);
WLED_GLOBAL uint32_t lastReconnectAttempt _INIT(0);
WLED_GLOBAL bool interfacesInited _INIT(false);
WLED_GLOBAL bool wasConnected _INIT(false);
// color
WLED_GLOBAL byte colOld[] _INIT_N(({ 0, 0, 0, 0 })); // color before transition
WLED_GLOBAL byte colT[] _INIT_N(({ 0, 0, 0, 0 })); // color that is currently displayed on the LEDs
WLED_GLOBAL byte colIT[] _INIT_N(({ 0, 0, 0, 0 })); // color that was last sent to LEDs
WLED_GLOBAL byte colSecT[] _INIT_N(({ 0, 0, 0, 0 }));
WLED_GLOBAL byte colSecOld[] _INIT_N(({ 0, 0, 0, 0 }));
WLED_GLOBAL byte colSecIT[] _INIT_N(({ 0, 0, 0, 0 }));
WLED_GLOBAL byte lastRandomIndex _INIT(0); // used to save last random color so the new one is not the same
// transitions
WLED_GLOBAL bool transitionActive _INIT(false);
WLED_GLOBAL uint16_t transitionDelayDefault _INIT(transitionDelay);
WLED_GLOBAL uint16_t transitionDelayTemp _INIT(transitionDelay);
WLED_GLOBAL unsigned long transitionStartTime;
WLED_GLOBAL float tperLast _INIT(0); // crossfade transition progress, 0.0f - 1.0f
WLED_GLOBAL bool jsonTransitionOnce _INIT(false);
// nightlight
WLED_GLOBAL bool nightlightActive _INIT(false);
WLED_GLOBAL bool nightlightActiveOld _INIT(false);
WLED_GLOBAL uint32_t nightlightDelayMs _INIT(10);
WLED_GLOBAL byte nightlightDelayMinsDefault _INIT(nightlightDelayMins);
WLED_GLOBAL unsigned long nightlightStartTime;
WLED_GLOBAL byte briNlT _INIT(0); // current nightlight brightness
WLED_GLOBAL byte colNlT[] _INIT_N(({ 0, 0, 0, 0 })); // current nightlight color
// brightness
WLED_GLOBAL unsigned long lastOnTime _INIT(0);
WLED_GLOBAL bool offMode _INIT(!turnOnAtBoot);
WLED_GLOBAL byte bri _INIT(briS);
WLED_GLOBAL byte briOld _INIT(0);
WLED_GLOBAL byte briT _INIT(0);
WLED_GLOBAL byte briIT _INIT(0);
WLED_GLOBAL byte briLast _INIT(128); // brightness before turned off. Used for toggle function
WLED_GLOBAL byte whiteLast _INIT(128); // white channel before turned off. Used for toggle function
// button
WLED_GLOBAL bool buttonPressedBefore _INIT(false);
WLED_GLOBAL bool buttonLongPressed _INIT(false);
WLED_GLOBAL unsigned long buttonPressedTime _INIT(0);
WLED_GLOBAL unsigned long buttonWaitTime _INIT(0);
// notifications
WLED_GLOBAL bool notifyDirectDefault _INIT(notifyDirect);
WLED_GLOBAL bool receiveNotifications _INIT(true);
WLED_GLOBAL unsigned long notificationSentTime _INIT(0);
WLED_GLOBAL byte notificationSentCallMode _INIT(NOTIFIER_CALL_MODE_INIT);
WLED_GLOBAL bool notificationTwoRequired _INIT(false);
// effects
WLED_GLOBAL byte effectCurrent _INIT(0);
WLED_GLOBAL byte effectSpeed _INIT(128);
WLED_GLOBAL byte effectIntensity _INIT(128);
WLED_GLOBAL byte effectPalette _INIT(0);
// network
WLED_GLOBAL bool udpConnected _INIT(false), udpRgbConnected _INIT(false);
// ui style
WLED_GLOBAL bool showWelcomePage _INIT(false);
// hue
WLED_GLOBAL byte hueError _INIT(HUE_ERROR_INACTIVE);
// WLED_GLOBAL uint16_t hueFailCount _INIT(0);
WLED_GLOBAL float hueXLast _INIT(0), hueYLast _INIT(0);
WLED_GLOBAL uint16_t hueHueLast _INIT(0), hueCtLast _INIT(0);
WLED_GLOBAL byte hueSatLast _INIT(0), hueBriLast _INIT(0);
WLED_GLOBAL unsigned long hueLastRequestSent _INIT(0);
WLED_GLOBAL bool hueAuthRequired _INIT(false);
WLED_GLOBAL bool hueReceived _INIT(false);
WLED_GLOBAL bool hueStoreAllowed _INIT(false), hueNewKey _INIT(false);
// overlays
WLED_GLOBAL byte overlayCurrent _INIT(overlayDefault);
WLED_GLOBAL byte overlaySpeed _INIT(200);
WLED_GLOBAL unsigned long overlayRefreshMs _INIT(200);
WLED_GLOBAL unsigned long overlayRefreshedTime;
// cronixie
WLED_GLOBAL byte dP[] _INIT_N(({ 0, 0, 0, 0, 0, 0 }));
WLED_GLOBAL bool cronixieInit _INIT(false);
// countdown
WLED_GLOBAL unsigned long countdownTime _INIT(1514764800L);
WLED_GLOBAL bool countdownOverTriggered _INIT(true);
// timer
WLED_GLOBAL byte lastTimerMinute _INIT(0);
WLED_GLOBAL byte timerHours[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0 }));
WLED_GLOBAL byte timerMinutes[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0 }));
WLED_GLOBAL byte timerMacro[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0 }));
WLED_GLOBAL byte timerWeekday[] _INIT_N(({ 255, 255, 255, 255, 255, 255, 255, 255 })); // weekdays to activate on
// bit pattern of arr elem: 0b11111111: sun,sat,fri,thu,wed,tue,mon,validity
// blynk
WLED_GLOBAL bool blynkEnabled _INIT(false);
// preset cycling
WLED_GLOBAL bool presetCyclingEnabled _INIT(false);
WLED_GLOBAL byte presetCycleMin _INIT(1), presetCycleMax _INIT(5);
WLED_GLOBAL uint16_t presetCycleTime _INIT(1250);
WLED_GLOBAL unsigned long presetCycledTime _INIT(0);
WLED_GLOBAL byte presetCycCurr _INIT(presetCycleMin);
WLED_GLOBAL bool presetApplyBri _INIT(true);
WLED_GLOBAL bool saveCurrPresetCycConf _INIT(false);
// realtime
WLED_GLOBAL byte realtimeMode _INIT(REALTIME_MODE_INACTIVE);
WLED_GLOBAL byte realtimeOverride _INIT(REALTIME_OVERRIDE_NONE);
WLED_GLOBAL IPAddress realtimeIP _INIT((0, 0, 0, 0));
WLED_GLOBAL unsigned long realtimeTimeout _INIT(0);
// mqtt
WLED_GLOBAL long lastMqttReconnectAttempt _INIT(0);
WLED_GLOBAL long lastInterfaceUpdate _INIT(0);
WLED_GLOBAL byte interfaceUpdateCallMode _INIT(NOTIFIER_CALL_MODE_INIT);
WLED_GLOBAL char mqttStatusTopic[40] _INIT(""); // this must be global because of async handlers
#if AUXPIN >= 0
// auxiliary debug pin
WLED_GLOBAL byte auxTime _INIT(0);
WLED_GLOBAL unsigned long auxStartTime _INIT(0);
WLED_GLOBAL bool auxActive _INIT(false, auxActiveBefore _INIT(false);
#endif
// alexa udp
WLED_GLOBAL String escapedMac;
#ifndef WLED_DISABLE_ALEXA
WLED_GLOBAL Espalexa espalexa;
WLED_GLOBAL EspalexaDevice* espalexaDevice;
#endif
// dns server
WLED_GLOBAL DNSServer dnsServer;
// network time
WLED_GLOBAL bool ntpConnected _INIT(false);
WLED_GLOBAL time_t local _INIT(0);
WLED_GLOBAL unsigned long ntpLastSyncTime _INIT(999000000L);
WLED_GLOBAL unsigned long ntpPacketSentTime _INIT(999000000L);
WLED_GLOBAL IPAddress ntpServerIP;
WLED_GLOBAL uint16_t ntpLocalPort _INIT(2390);
WLED_GLOBAL uint16_t rolloverMillis _INIT(0);
// Temp buffer
WLED_GLOBAL char* obuf;
WLED_GLOBAL uint16_t olen _INIT(0);
// presets
WLED_GLOBAL uint16_t savedPresets _INIT(0);
WLED_GLOBAL int8_t currentPreset _INIT(-1);
WLED_GLOBAL bool isPreset _INIT(false);
WLED_GLOBAL byte errorFlag _INIT(0);
WLED_GLOBAL String messageHead, messageSub;
WLED_GLOBAL byte optionType;
WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers
WLED_GLOBAL bool doPublishMqtt _INIT(false);
// server library objects
WLED_GLOBAL AsyncWebServer server _INIT_N(((80)));
WLED_GLOBAL AsyncClient* hueClient _INIT(NULL);
WLED_GLOBAL AsyncMqttClient* mqtt _INIT(NULL);
// udp interface objects
WLED_GLOBAL WiFiUDP notifierUdp, rgbUdp;
WLED_GLOBAL WiFiUDP ntpUdp;
WLED_GLOBAL ESPAsyncE131 e131 _INIT_N(((handleE131Packet)));
WLED_GLOBAL bool e131NewData _INIT(false);
// led fx library object
WLED_GLOBAL WS2812FX strip _INIT(WS2812FX());
// debug macro variable definitions
#ifdef WLED_DEBUG
WLED_GLOBAL unsigned long debugTime _INIT(0);
WLED_GLOBAL int lastWifiState _INIT(3);
WLED_GLOBAL unsigned long wifiStateChangedTime _INIT(0);
WLED_GLOBAL int loops _INIT(0);
#endif
#define WLED_CONNECTED (WiFi.status() == WL_CONNECTED)
#define WLED_WIFI_CONFIGURED (strlen(clientSSID) >= 1 && strcmp(clientSSID, DEFAULT_CLIENT_SSID) != 0)
// append new c string to temp buffer efficiently
bool oappend(const char* txt);
// append new number to temp buffer efficiently
bool oappendi(int i);
class WLED {
public:
WLED();
static WLED& instance()
{
static WLED instance;
return instance;
}
// boot starts here
void setup();
void loop();
void reset();
void beginStrip();
void handleConnection();
void initAP(bool resetAP = false);
void initConnection();
void initInterfaces();
};
#endif // WLED_H

View File

@@ -1,591 +1,21 @@
/*
* Main sketch, global variable declarations
*/
/*
* @title WLED project sketch
* @version 0.9.1
* @author Christian Schwinne
* WLED Arduino IDE compatibility file.
*
* Where has everything gone?
*
* In April 2020, the project's structure underwent a major change.
* Global variables are now found in file "wled.h"
* Global function declarations are found in "fcn_declare.h"
*
* Usermod compatibility: Existing wled06_usermod.ino mods should continue to work. Delete usermod.cpp.
* New usermods should use usermod.cpp instead.
*/
#include "wled.h"
//ESP8266-01 (blue) got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.4.2 and the setting 512K(No SPIFFS).
//ESP8266-01 (black) has 1MB flash and can thus fit the whole program. Use 1M(64K SPIFFS).
//Uncomment some of the following lines to disable features to compile for ESP8266-01 (max flash size 434kB):
//You are required to disable over-the-air updates:
//#define WLED_DISABLE_OTA //saves 14kb
//You need to choose some of these features to disable:
//#define WLED_DISABLE_ALEXA //saves 11kb
//#define WLED_DISABLE_BLYNK //saves 6kb
//#define WLED_DISABLE_CRONIXIE //saves 3kb
//#define WLED_DISABLE_HUESYNC //saves 4kb
//#define WLED_DISABLE_INFRARED //there is no pin left for this on ESP8266-01, saves 25kb (!)
#define WLED_ENABLE_MQTT //saves 12kb
#define WLED_ENABLE_ADALIGHT //saves 500b only
#define WLED_DISABLE_FILESYSTEM //SPIFFS is not used by any WLED feature yet
//#define WLED_ENABLE_FS_SERVING //Enable sending html file from SPIFFS before serving progmem version
//#define WLED_ENABLE_FS_EDITOR //enable /edit page for editing SPIFFS content. Will also be disabled with OTA lock
//to toggle usb serial debug (un)comment the following line
//#define WLED_DEBUG
//library inclusions
#include <Arduino.h>
#ifdef ESP8266
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <ESPAsyncTCP.h>
extern "C" {
#include <user_interface.h>
}
#else
#include <WiFi.h>
#include "esp_wifi.h"
#include <ESPmDNS.h>
#include <AsyncTCP.h>
#include "SPIFFS.h"
#endif
#include <ESPAsyncWebServer.h>
#include <EEPROM.h>
#include <WiFiUdp.h>
#include <DNSServer.h>
#ifndef WLED_DISABLE_OTA
#include <ArduinoOTA.h>
#endif
#include <SPIFFSEditor.h>
#include "src/dependencies/time/TimeLib.h"
#include "src/dependencies/timezone/Timezone.h"
#ifndef WLED_DISABLE_ALEXA
#define ESPALEXA_ASYNC
#define ESPALEXA_NO_SUBPAGE
#define ESPALEXA_MAXDEVICES 1
//#define ESPALEXA_DEBUG
#include "src/dependencies/espalexa/Espalexa.h"
#endif
#ifndef WLED_DISABLE_BLYNK
#include "src/dependencies/blynk/BlynkSimpleEsp.h"
#endif
#include "src/dependencies/e131/ESPAsyncE131.h"
#include "src/dependencies/async-mqtt-client/AsyncMqttClient.h"
#include "src/dependencies/json/AsyncJson-v6.h"
#include "src/dependencies/json/ArduinoJson-v6.h"
#include "html_ui.h"
#include "html_settings.h"
#include "html_other.h"
#include "FX.h"
#include "ir_codes.h"
#include "const.h"
#if IR_PIN < 0
#ifndef WLED_DISABLE_INFRARED
#define WLED_DISABLE_INFRARED
#endif
#endif
#ifndef WLED_DISABLE_INFRARED
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRutils.h>
#endif
// remove flicker because PWM signal of RGB channels can become out of phase
#if defined(WLED_USE_ANALOG_LEDS) && defined(ESP8266)
#include "src/dependencies/arduino/core_esp8266_waveform.h"
#endif
// enable additional debug output
#ifdef WLED_DEBUG
#ifndef ESP8266
#include <rom/rtc.h>
#endif
#endif
//version code in format yymmddb (b = daily build)
#define VERSION 2002192
char versionString[] = "0.9.1";
//AP and OTA default passwords (for maximum change them!)
char apPass[65] = "wled1234";
char otaPass[33] = "wledota";
//Hardware CONFIG (only changeble HERE, not at runtime)
//LED strip pin, button pin and IR pin changeable in NpbWrapper.h!
byte auxDefaultState = 0; //0: input 1: high 2: low
byte auxTriggeredState = 0; //0: input 1: high 2: low
char ntpServerName[33] = "0.wled.pool.ntp.org";//NTP server to use
//WiFi CONFIG (all these can be changed via web UI, no need to set them here)
char clientSSID[33] = "Your_Network";
char clientPass[65] = "";
char cmDNS[33] = "x"; //mDNS address (placeholder, will be replaced by wledXXXXXXXXXXXX.local)
char apSSID[33] = ""; //AP off by default (unless setup)
byte apChannel = 1; //2.4GHz WiFi AP channel (1-13)
byte apHide = 0; //hidden AP SSID
byte apBehavior = AP_BEHAVIOR_BOOT_NO_CONN; //access point opens when no connection after boot by default
IPAddress staticIP(0, 0, 0, 0); //static IP of ESP
IPAddress staticGateway(0, 0, 0, 0); //gateway (router) IP
IPAddress staticSubnet(255, 255, 255, 0); //most common subnet in home networks
bool noWifiSleep = false; //disabling modem sleep modes will increase heat output and power usage, but may help with connection issues
//LED CONFIG
uint16_t ledCount = 30; //overcurrent prevented by ABL
bool useRGBW = false; //SK6812 strips can contain an extra White channel
#define ABL_MILLIAMPS_DEFAULT 850; //auto lower brightness to stay close to milliampere limit
bool turnOnAtBoot = true; //turn on LEDs at power-up
byte bootPreset = 0; //save preset to load after power-up
byte col[]{255, 160, 0, 0}; //default RGB(W) color
byte colSec[]{0, 0, 0, 0}; //default RGB(W) secondary color
byte briS = 128; //default brightness
byte nightlightTargetBri = 0; //brightness after nightlight is over
byte nightlightDelayMins = 60;
bool nightlightFade = true; //if enabled, light will gradually dim towards the target bri. Otherwise, it will instantly set after delay over
bool nightlightColorFade = false; //if enabled, light will gradually fade color from primary to secondary color.
bool fadeTransition = true; //enable crossfading color transition
bool enableSecTransition = true; //also enable transition for secondary color
uint16_t transitionDelay = 750; //default crossfade duration in ms
bool skipFirstLed = false; //ignore first LED in strip (useful if you need the LED as signal repeater)
byte briMultiplier = 100; //% of brightness to set (to limit power, if you set it to 50 and set bri to 255, actual brightness will be 127)
//User Interface CONFIG
char serverDescription[33] = "WLED"; //Name of module
bool syncToggleReceive = false; //UIs which only have a single button for sync should toggle send+receive if this is true, only send otherwise
//Sync CONFIG
bool buttonEnabled = true;
byte irEnabled = 0; //Infrared receiver
uint16_t udpPort = 21324; //WLED notifier default port
uint16_t udpRgbPort = 19446; //Hyperion port
bool receiveNotificationBrightness = true; //apply brightness from incoming notifications
bool receiveNotificationColor = true; //apply color
bool receiveNotificationEffects = true; //apply effects setup
bool notifyDirect = false; //send notification if change via UI or HTTP API
bool notifyButton = false; //send if updated by button or infrared remote
bool notifyAlexa = false; //send notification if updated via Alexa
bool notifyMacro = false; //send notification for macro
bool notifyHue = true; //send notification if Hue light changes
bool notifyTwice = false; //notifications use UDP: enable if devices don't sync reliably
bool alexaEnabled = true; //enable device discovery by Amazon Echo
char alexaInvocationName[33] = "Light"; //speech control name of device. Choose something voice-to-text can understand
char blynkApiKey[36] = ""; //Auth token for Blynk server. If empty, no connection will be made
uint16_t realtimeTimeoutMs = 2500; //ms timeout of realtime mode before returning to normal mode
int arlsOffset = 0; //realtime LED offset
bool receiveDirect = true; //receive UDP realtime
bool arlsDisableGammaCorrection = true; //activate if gamma correction is handled by the source
bool arlsForceMaxBri = false; //enable to force max brightness if source has very dark colors that would be black
uint16_t e131Universe = 1; //settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consequtive universes)
uint8_t DMXMode = DMX_MODE_MULTIPLE_RGB; //DMX mode (s.a.)
uint16_t DMXAddress = 1; //DMX start address of fixture, a.k.a. first Channel [for E1.31 (sACN) protocol]
uint8_t DMXOldDimmer = 0; //only update brightness on change
uint8_t e131LastSequenceNumber = 0; //to detect packet loss
bool e131Multicast = false; //multicast or unicast
bool mqttEnabled = false;
char mqttDeviceTopic[33] = ""; //main MQTT topic (individual per device, default is wled/mac)
char mqttGroupTopic[33] = "wled/all"; //second MQTT topic (for example to group devices)
char mqttServer[33] = ""; //both domains and IPs should work (no SSL)
char mqttUser[41] = ""; //optional: username for MQTT auth
char mqttPass[41] = ""; //optional: password for MQTT auth
char mqttClientID[41] = ""; //override the client ID
uint16_t mqttPort = 1883;
bool huePollingEnabled = false; //poll hue bridge for light state
uint16_t huePollIntervalMs = 2500; //low values (< 1sec) may cause lag but offer quicker response
char hueApiKey[47] = "api"; //key token will be obtained from bridge
byte huePollLightId = 1; //ID of hue lamp to sync to. Find the ID in the hue app ("about" section)
IPAddress hueIP = (0,0,0,0); //IP address of the bridge
bool hueApplyOnOff = true;
bool hueApplyBri = true;
bool hueApplyColor = true;
//Time CONFIG
bool ntpEnabled = false; //get internet time. Only required if you use clock overlays or time-activated macros
bool useAMPM = false; //12h/24h clock format
byte currentTimezone = 0; //Timezone ID. Refer to timezones array in wled10_ntp.ino
int utcOffsetSecs = 0; //Seconds to offset from UTC before timzone calculation
byte overlayDefault = 0; //0: no overlay 1: analog clock 2: single-digit clocl 3: cronixie
byte overlayMin = 0, overlayMax = ledCount-1; //boundaries of overlay mode
byte analogClock12pixel = 0; //The pixel in your strip where "midnight" would be
bool analogClockSecondsTrail = false; //Display seconds as trail of LEDs instead of a single pixel
bool analogClock5MinuteMarks = false; //Light pixels at every 5-minute position
char cronixieDisplay[7] = "HHMMSS"; //Cronixie Display mask. See wled13_cronixie.ino
bool cronixieBacklight = true; //Allow digits to be back-illuminated
bool countdownMode = false; //Clock will count down towards date
byte countdownYear = 20, countdownMonth = 1; //Countdown target date, year is last two digits
byte countdownDay = 1, countdownHour = 0;
byte countdownMin = 0, countdownSec = 0;
byte macroBoot = 0; //macro loaded after startup
byte macroNl = 0; //after nightlight delay over
byte macroCountdown = 0;
byte macroAlexaOn = 0, macroAlexaOff = 0;
byte macroButton = 0, macroLongPress = 0, macroDoublePress = 0;
//Security CONFIG
bool otaLock = false; //prevents OTA firmware updates without password. ALWAYS enable if system exposed to any public networks
bool wifiLock = false; //prevents access to WiFi settings when OTA lock is enabled
bool aOtaEnabled = true; //ArduinoOTA allows easy updates directly from the IDE. Careful, it does not auto-disable when OTA lock is on
uint16_t userVar0 = 0, userVar1 = 0;
//internal global variable declarations
//wifi
bool apActive = false;
bool forceReconnect = false;
uint32_t lastReconnectAttempt = 0;
bool interfacesInited = false;
bool wasConnected = false;
//color
byte colOld[]{0, 0, 0, 0}; //color before transition
byte colT[]{0, 0, 0, 0}; //current color
byte colIT[]{0, 0, 0, 0}; //color that was last sent to LEDs
byte colSecT[]{0, 0, 0, 0};
byte colSecOld[]{0, 0, 0, 0};
byte colSecIT[]{0, 0, 0, 0};
byte lastRandomIndex = 0; //used to save last random color so the new one is not the same
//transitions
bool transitionActive = false;
uint16_t transitionDelayDefault = transitionDelay;
uint16_t transitionDelayTemp = transitionDelay;
unsigned long transitionStartTime;
float tperLast = 0; //crossfade transition progress, 0.0f - 1.0f
bool jsonTransitionOnce = false;
//nightlight
bool nightlightActive = false;
bool nightlightActiveOld = false;
uint32_t nightlightDelayMs = 10;
uint8_t nightlightDelayMinsDefault = nightlightDelayMins;
unsigned long nightlightStartTime;
byte briNlT = 0; //current nightlight brightness
byte colNlT[]{0, 0, 0, 0}; //current nightlight color
//brightness
unsigned long lastOnTime = 0;
bool offMode = !turnOnAtBoot;
byte bri = briS;
byte briOld = 0;
byte briT = 0;
byte briIT = 0;
byte briLast = 128; //brightness before turned off. Used for toggle function
byte whiteLast = 128; //white channel before turned off. Used for toggle function
//button
bool buttonPressedBefore = false;
bool buttonLongPressed = false;
unsigned long buttonPressedTime = 0;
unsigned long buttonWaitTime = 0;
//notifications
bool notifyDirectDefault = notifyDirect;
bool receiveNotifications = true;
unsigned long notificationSentTime = 0;
byte notificationSentCallMode = NOTIFIER_CALL_MODE_INIT;
bool notificationTwoRequired = false;
//effects
byte effectCurrent = 0;
byte effectSpeed = 128;
byte effectIntensity = 128;
byte effectPalette = 0;
//network
bool udpConnected = false, udpRgbConnected = false;
//ui style
bool showWelcomePage = false;
//hue
char hueError[25] = "Inactive";
//uint16_t hueFailCount = 0;
float hueXLast=0, hueYLast=0;
uint16_t hueHueLast=0, hueCtLast=0;
byte hueSatLast=0, hueBriLast=0;
unsigned long hueLastRequestSent = 0;
bool hueAuthRequired = false;
bool hueReceived = false;
bool hueStoreAllowed = false, hueNewKey = false;
//overlays
byte overlayCurrent = overlayDefault;
byte overlaySpeed = 200;
unsigned long overlayRefreshMs = 200;
unsigned long overlayRefreshedTime;
//cronixie
byte dP[]{0,0,0,0,0,0};
bool cronixieInit = false;
//countdown
unsigned long countdownTime = 1514764800L;
bool countdownOverTriggered = true;
//timer
byte lastTimerMinute = 0;
byte timerHours[] = {0,0,0,0,0,0,0,0};
byte timerMinutes[] = {0,0,0,0,0,0,0,0};
byte timerMacro[] = {0,0,0,0,0,0,0,0};
byte timerWeekday[] = {255,255,255,255,255,255,255,255}; //weekdays to activate on
//bit pattern of arr elem: 0b11111111: sun,sat,fri,thu,wed,tue,mon,validity
//blynk
bool blynkEnabled = false;
//preset cycling
bool presetCyclingEnabled = false;
byte presetCycleMin = 1, presetCycleMax = 5;
uint16_t presetCycleTime = 1250;
unsigned long presetCycledTime = 0; byte presetCycCurr = presetCycleMin;
bool presetApplyBri = false, presetApplyCol = true, presetApplyFx = true;
bool saveCurrPresetCycConf = false;
//realtime
byte realtimeMode = REALTIME_MODE_INACTIVE;
IPAddress realtimeIP = (0,0,0,0);
unsigned long realtimeTimeout = 0;
//mqtt
long lastMqttReconnectAttempt = 0;
long lastInterfaceUpdate = 0;
byte interfaceUpdateCallMode = NOTIFIER_CALL_MODE_INIT;
char mqttStatusTopic[40] = ""; //this must be global because of async handlers
#if AUXPIN >= 0
//auxiliary debug pin
byte auxTime = 0;
unsigned long auxStartTime = 0;
bool auxActive = false, auxActiveBefore = false;
#endif
//alexa udp
String escapedMac;
#ifndef WLED_DISABLE_ALEXA
Espalexa espalexa;
EspalexaDevice* espalexaDevice;
#endif
//dns server
DNSServer dnsServer;
//network time
bool ntpConnected = false;
time_t local = 0;
unsigned long ntpLastSyncTime = 999000000L;
unsigned long ntpPacketSentTime = 999000000L;
IPAddress ntpServerIP;
uint16_t ntpLocalPort = 2390;
#define NTP_PACKET_SIZE 48
#define MAX_LEDS 1500
#define MAX_LEDS_DMA 500
//string temp buffer (now stored in stack locally)
#define OMAX 2048
char* obuf;
uint16_t olen = 0;
uint16_t savedPresets = 0;
int8_t currentPreset = -1;
bool isPreset = false;
byte errorFlag = 0;
String messageHead, messageSub;
byte optionType;
bool doReboot = false; //flag to initiate reboot from async handlers
bool doPublishMqtt = false;
//server library objects
AsyncWebServer server(80);
AsyncClient* hueClient = NULL;
AsyncMqttClient* mqtt = NULL;
//function prototypes
void colorFromUint32(uint32_t,bool=false);
void serveMessage(AsyncWebServerRequest*,uint16_t,String,String,byte);
void handleE131Packet(e131_packet_t*, IPAddress);
void arlsLock(uint32_t,byte);
void handleOverlayDraw();
#define E131_MAX_UNIVERSE_COUNT 9
//udp interface objects
WiFiUDP notifierUdp, rgbUdp;
WiFiUDP ntpUdp;
ESPAsyncE131 e131(handleE131Packet);
bool e131NewData = false;
//led fx library object
WS2812FX strip = WS2812FX();
#define WLED_CONNECTED (WiFi.status() == WL_CONNECTED)
#define WLED_WIFI_CONFIGURED (strlen(clientSSID) >= 1 && strcmp(clientSSID,"Your_Network") != 0)
//debug macros
#ifdef WLED_DEBUG
#define DEBUG_PRINT(x) Serial.print (x)
#define DEBUG_PRINTLN(x) Serial.println (x)
#define DEBUG_PRINTF(x) Serial.printf (x)
unsigned long debugTime = 0;
int lastWifiState = 3;
unsigned long wifiStateChangedTime = 0;
int loops = 0;
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTLN(x)
#define DEBUG_PRINTF(x)
#endif
//filesystem
#ifndef WLED_DISABLE_FILESYSTEM
#include <FS.h>
#ifdef ARDUINO_ARCH_ESP32
#include "SPIFFS.h"
#endif
#include "SPIFFSEditor.h"
#endif
//turns all LEDs off and restarts ESP
void reset()
{
briT = 0;
long dly = millis();
while(millis() - dly < 250)
{
yield(); //enough time to send response to client
}
setAllLeds();
DEBUG_PRINTLN("MODULE RESET");
ESP.restart();
}
//append new c string to temp buffer efficiently
bool oappend(const char* txt)
{
uint16_t len = strlen(txt);
if (olen + len >= OMAX) return false; //buffer full
strcpy(obuf + olen, txt);
olen += len;
return true;
}
//append new number to temp buffer efficiently
bool oappendi(int i)
{
char s[11];
sprintf(s,"%ld", i);
return oappend(s);
}
//boot starts here
void setup() {
wledInit();
WLED::instance().setup();
}
//main program loop
void loop() {
handleIR(); //2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too
handleConnection();
handleSerial();
handleNotifications();
handleTransitions();
userLoop();
yield();
handleIO();
handleIR();
handleNetworkTime();
handleAlexa();
handleOverlays();
yield();
#ifdef WLED_USE_ANALOG_LEDS
strip.setRgbwPwm();
#endif
if (doReboot) reset();
if (!realtimeMode) //block stuff if WARLS/Adalight is enabled
{
if (apActive) dnsServer.processNextRequest();
#ifndef WLED_DISABLE_OTA
if (WLED_CONNECTED && aOtaEnabled) ArduinoOTA.handle();
#endif
handleNightlight();
yield();
handleHue();
handleBlynk();
yield();
if (!offMode) strip.service();
}
yield();
#ifdef ESP8266
MDNS.update();
#endif
if (millis() - lastMqttReconnectAttempt > 30000) initMqtt();
//DEBUG serial logging
#ifdef WLED_DEBUG
if (millis() - debugTime > 9999)
{
DEBUG_PRINTLN("---DEBUG INFO---");
DEBUG_PRINT("Runtime: "); DEBUG_PRINTLN(millis());
DEBUG_PRINT("Unix time: "); DEBUG_PRINTLN(now());
DEBUG_PRINT("Free heap: "); DEBUG_PRINTLN(ESP.getFreeHeap());
DEBUG_PRINT("Wifi state: "); DEBUG_PRINTLN(WiFi.status());
if (WiFi.status() != lastWifiState)
{
wifiStateChangedTime = millis();
}
lastWifiState = WiFi.status();
DEBUG_PRINT("State time: "); DEBUG_PRINTLN(wifiStateChangedTime);
DEBUG_PRINT("NTP last sync: "); DEBUG_PRINTLN(ntpLastSyncTime);
DEBUG_PRINT("Client IP: "); DEBUG_PRINTLN(WiFi.localIP());
DEBUG_PRINT("Loops/sec: "); DEBUG_PRINTLN(loops/10);
loops = 0;
debugTime = millis();
}
loops++;
#endif
WLED::instance().loop();
}

File diff suppressed because one or more lines are too long

View File

@@ -13,29 +13,15 @@
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Source Files\Dependencies">
<UniqueIdentifier>{72fe60da-ba26-45b4-82c1-bdff809975da}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Dependencies">
<UniqueIdentifier>{8880888d-efea-4189-a25a-834b7b3bb756}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="wled00.ino" />
<None Include="wled01_eeprom.ino" />
<None Include="wled02_xml.ino" />
<None Include="wled03_set.ino" />
<None Include="wled04_file.ino" />
<None Include="wled05_init.ino" />
<None Include="wled06_usermod.ino" />
<None Include="wled07_notify.ino" />
<None Include="wled08_led.ino" />
<None Include="wled09_button.ino" />
<None Include="wled10_ntp.ino" />
<None Include="wled11_ol.ino" />
<None Include="wled12_alexa.ino" />
<None Include="wled13_cronixie.ino" />
<None Include="wled14_colors.ino" />
<None Include="wled15_hue.ino" />
<None Include="wled16_blynk.ino" />
<None Include="wled17_mqtt.ino" />
<None Include="wled18_server.ino" />
<None Include="wled19_json.ino" />
<None Include="wled20_ir.ino" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="__vm\.wled00.vsarduino.h">
@@ -53,219 +39,348 @@
<ClInclude Include="html_settings.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ir_codes.h">
<ClInclude Include="FX.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\json\ArduinoJson-v6.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\json\AsyncJson-v6.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkApi.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkApiArduino.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkArduinoClient.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkConfig.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkDateTime.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkDebug.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkDetectDevice.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkEveryN.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkFifo.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkHandlers.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkParam.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkProtocol.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkProtocolDefs.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\BlynkSimpleEsp.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkTemplates.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkTimer.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkUtility.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkWidgetBase.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkWiFiCommon.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Callbacks.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\ConnAckPacket.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\DisconnectReasons.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\espalexa\Espalexa.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\espalexa\EspalexaDevice.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\e131\ESPAsyncE131.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Flags.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Helpers.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\MessageProperties.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="NpbWrapper.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\Packet.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\ParsingInformation.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PingRespPacket.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubAckPacket.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubCompPacket.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PublishPacket.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRecPacket.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRelPacket.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Storage.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\SubAckPacket.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\time\Time.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\time\TimeLib.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\timezone\Timezone.h">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\UnsubAckPacket.hpp">
<Filter>Header Files\Dependencies</Filter>
</ClInclude>
<ClInclude Include="alexa.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="blynk.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="button.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="colors.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="const.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="cronixie.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="dmx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="file.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="html_ui.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ir.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="json.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="led.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mqtt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="notify.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ntp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="overlay.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="set.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="usermod.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wled.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wled_eeprom.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="wled_server.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="xml.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ir_codes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="palettes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Callbacks.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\DisconnectReasons.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Flags.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Helpers.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\MessageProperties.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\ParsingInformation.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Storage.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\ConnAckPacket.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\Packet.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PingRespPacket.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubAckPacket.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubCompPacket.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PublishPacket.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRecPacket.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRelPacket.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\SubAckPacket.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\UnsubAckPacket.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\BlynkSimpleEsp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkApi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkApiArduino.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkArduinoClient.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkConfig.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkDateTime.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkDebug.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkDetectDevice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkEveryN.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkFifo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkHandlers.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkParam.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkProtocol.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkProtocolDefs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkTemplates.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkTimer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkUtility.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkWidgetBase.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\blynk\Blynk\BlynkWiFiCommon.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\espalexa\Espalexa.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\espalexa\EspalexaDevice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\json\ArduinoJson-v6.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\json\AsyncJson-v6.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\time\Time.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\time\TimeLib.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\timezone\Timezone.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FX.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\dependencies\e131\ESPAsyncE131.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\ConnAckPacket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PingRespPacket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubAckPacket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubCompPacket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PublishPacket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRecPacket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRelPacket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\SubAckPacket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\UnsubAckPacket.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\blynk\Blynk\BlynkDebug.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\blynk\Blynk\BlynkHandlers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\blynk\Blynk\BlynkTimer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\blynk\Blynk\utility.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\espalexa\EspalexaDevice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\time\DateStrings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\time\Time.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\timezone\Timezone.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FX.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FX_fcn.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\blynk\Blynk\utility.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\blynk\Blynk\BlynkDebug.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\blynk\Blynk\BlynkHandlers.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\blynk\Blynk\BlynkTimer.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\ConnAckPacket.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\time\DateStrings.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\espalexa\EspalexaDevice.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\e131\ESPAsyncE131.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PingRespPacket.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubAckPacket.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubCompPacket.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PublishPacket.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRecPacket.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\PubRelPacket.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\SubAckPacket.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\time\Time.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\timezone\Timezone.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="src\dependencies\async-mqtt-client\AsyncMqttClient\Packets\UnsubAckPacket.cpp">
<Filter>Source Files\Dependencies</Filter>
</ClCompile>
<ClCompile Include="alexa.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="blynk.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="button.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="colors.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="cronixie.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="file.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hue.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ir.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="json.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="led.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mqtt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="notify.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ntp.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="overlay.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="set.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="usermod.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wled.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wled_eeprom.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="wled_server.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="xml.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

View File

@@ -1,337 +0,0 @@
/*
* Setup code
*/
void wledInit()
{
EEPROM.begin(EEPSIZE);
ledCount = EEPROM.read(229) + ((EEPROM.read(398) << 8) & 0xFF00);
if (ledCount > MAX_LEDS || ledCount == 0) ledCount = 30;
#ifdef ESP8266
#if LEDPIN == 3
if (ledCount > MAX_LEDS_DMA) ledCount = MAX_LEDS_DMA; //DMA method uses too much ram
#endif
#endif
Serial.begin(115200);
Serial.setTimeout(50);
DEBUG_PRINTLN();
DEBUG_PRINT("---WLED "); DEBUG_PRINT(versionString); DEBUG_PRINT(" "); DEBUG_PRINT(VERSION); DEBUG_PRINTLN(" INIT---");
#ifdef ARDUINO_ARCH_ESP32
DEBUG_PRINT("esp32 "); DEBUG_PRINTLN(ESP.getSdkVersion());
#else
DEBUG_PRINT("esp8266 "); DEBUG_PRINTLN(ESP.getCoreVersion());
#endif
int heapPreAlloc = ESP.getFreeHeap();
DEBUG_PRINT("heap ");
DEBUG_PRINTLN(ESP.getFreeHeap());
strip.init(EEPROM.read(372),ledCount,EEPROM.read(2204)); //init LEDs quickly
strip.setBrightness(0);
DEBUG_PRINT("LEDs inited. heap usage ~");
DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
#ifndef WLED_DISABLE_FILESYSTEM
#ifdef ARDUINO_ARCH_ESP32
SPIFFS.begin(true);
#endif
SPIFFS.begin();
#endif
DEBUG_PRINTLN("Load EEPROM");
loadSettingsFromEEPROM(true);
beginStrip();
userSetup();
if (strcmp(clientSSID,"Your_Network") == 0) showWelcomePage = true;
WiFi.persistent(false);
if (macroBoot>0) applyMacro(macroBoot);
Serial.println("Ada");
//generate module IDs
escapedMac = WiFi.macAddress();
escapedMac.replace(":", "");
escapedMac.toLowerCase();
if (strcmp(cmDNS,"x") == 0) //fill in unique mdns default
{
strcpy(cmDNS, "wled-");
sprintf(cmDNS+5, "%*s", 6, escapedMac.c_str()+6);
}
if (mqttDeviceTopic[0] == 0)
{
strcpy(mqttDeviceTopic, "wled/");
sprintf(mqttDeviceTopic+5, "%*s", 6, escapedMac.c_str()+6);
}
if (mqttClientID[0] == 0)
{
strcpy(mqttClientID, "WLED-");
sprintf(mqttClientID+5, "%*s", 6, escapedMac.c_str()+6);
}
strip.service();
#ifndef WLED_DISABLE_OTA
if (aOtaEnabled)
{
ArduinoOTA.onStart([]() {
#ifdef ESP8266
wifi_set_sleep_type(NONE_SLEEP_T);
#endif
DEBUG_PRINTLN("Start ArduinoOTA");
});
if (strlen(cmDNS) > 0) ArduinoOTA.setHostname(cmDNS);
}
#endif
//HTTP server page init
initServer();
}
void beginStrip()
{
// Initialize NeoPixel Strip and button
strip.setShowCallback(handleOverlayDraw);
#ifdef BTNPIN
pinMode(BTNPIN, INPUT_PULLUP);
#endif
if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true);
colorUpdated(NOTIFIER_CALL_MODE_INIT);
//init relay pin
#if RLYPIN >= 0
pinMode(RLYPIN, OUTPUT);
#if RLYMDE
digitalWrite(RLYPIN, bri);
#else
digitalWrite(RLYPIN, !bri);
#endif
#endif
//disable button if it is "pressed" unintentionally
#ifdef BTNPIN
if(digitalRead(BTNPIN) == LOW) buttonEnabled = false;
#else
buttonEnabled = false;
#endif
}
void initAP(bool resetAP=false){
if (apBehavior == AP_BEHAVIOR_BUTTON_ONLY && !resetAP) return;
if (!apSSID[0] || resetAP) strcpy(apSSID, "WLED-AP");
if (resetAP) strcpy(apPass,"wled1234");
DEBUG_PRINT("Opening access point ");
DEBUG_PRINTLN(apSSID);
WiFi.softAPConfig(IPAddress(4, 3, 2, 1), IPAddress(4, 3, 2, 1), IPAddress(255,255,255,0));
WiFi.softAP(apSSID, apPass, apChannel, apHide);
if (!apActive) //start captive portal if AP active
{
DEBUG_PRINTLN("Init AP interfaces");
server.begin();
if (udpPort > 0 && udpPort != ntpLocalPort)
{
udpConnected = notifierUdp.begin(udpPort);
}
if (udpRgbPort > 0 && udpRgbPort != ntpLocalPort && udpRgbPort != udpPort)
{
udpRgbConnected = rgbUdp.begin(udpRgbPort);
}
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start(53, "*", WiFi.softAPIP());
}
apActive = true;
}
void initConnection()
{
WiFi.disconnect(); //close old connections
#ifdef ESP8266
WiFi.setPhyMode(WIFI_PHY_MODE_11N);
#endif
if (staticIP[0] != 0 && staticGateway[0] != 0)
{
WiFi.config(staticIP, staticGateway, staticSubnet, IPAddress(8,8,8,8));
} else
{
WiFi.config(0U, 0U, 0U);
}
lastReconnectAttempt = millis();
if (!WLED_WIFI_CONFIGURED)
{
DEBUG_PRINT("No connection configured. ");
if (!apActive) initAP(); //instantly go to ap mode
return;
} else if (!apActive) {
if (apBehavior == AP_BEHAVIOR_ALWAYS)
{
initAP();
} else
{
DEBUG_PRINTLN("Access point disabled.");
WiFi.softAPdisconnect(true);
}
}
showWelcomePage = false;
DEBUG_PRINT("Connecting to ");
DEBUG_PRINT(clientSSID);
DEBUG_PRINTLN("...");
#ifdef ESP8266
WiFi.hostname(serverDescription);
#endif
WiFi.begin(clientSSID, clientPass);
#ifdef ARDUINO_ARCH_ESP32
WiFi.setSleep(!noWifiSleep);
WiFi.setHostname(serverDescription);
#else
wifi_set_sleep_type((noWifiSleep) ? NONE_SLEEP_T : MODEM_SLEEP_T);
#endif
}
void initInterfaces() {
DEBUG_PRINTLN("Init STA interfaces");
if (hueIP[0] == 0)
{
hueIP[0] = WiFi.localIP()[0];
hueIP[1] = WiFi.localIP()[1];
hueIP[2] = WiFi.localIP()[2];
}
//init Alexa hue emulation
if (alexaEnabled) alexaInit();
#ifndef WLED_DISABLE_OTA
if (aOtaEnabled) ArduinoOTA.begin();
#endif
strip.service();
// Set up mDNS responder:
if (strlen(cmDNS) > 0)
{
if (!aOtaEnabled) MDNS.begin(cmDNS);
DEBUG_PRINTLN("mDNS started");
MDNS.addService("http", "tcp", 80);
MDNS.addService("wled", "tcp", 80);
MDNS.addServiceTxt("wled", "tcp", "mac", escapedMac.c_str());
}
server.begin();
if (udpPort > 0 && udpPort != ntpLocalPort)
{
udpConnected = notifierUdp.begin(udpPort);
if (udpConnected && udpRgbPort != udpPort) udpRgbConnected = rgbUdp.begin(udpRgbPort);
}
if (ntpEnabled) ntpConnected = ntpUdp.begin(ntpLocalPort);
initBlynk(blynkApiKey);
e131.begin((e131Multicast) ? E131_MULTICAST : E131_UNICAST , e131Universe, E131_MAX_UNIVERSE_COUNT);
reconnectHue();
initMqtt();
interfacesInited = true;
wasConnected = true;
}
byte stacO = 0;
uint32_t lastHeap;
unsigned long heapTime = 0;
void handleConnection() {
if (millis() < 2000 && (!WLED_WIFI_CONFIGURED || apBehavior == AP_BEHAVIOR_ALWAYS)) return;
if (lastReconnectAttempt == 0) initConnection();
//reconnect WiFi to clear stale allocations if heap gets too low
if (millis() - heapTime > 5000)
{
uint32_t heap = ESP.getFreeHeap();
if (heap < 9000 && lastHeap < 9000) {
DEBUG_PRINT("Heap too low! ");
DEBUG_PRINTLN(heap);
forceReconnect = true;
}
lastHeap = heap;
heapTime = millis();
}
byte stac = 0;
if (apActive) {
#ifdef ESP8266
stac = wifi_softap_get_station_num();
#else
wifi_sta_list_t stationList;
esp_wifi_ap_get_sta_list(&stationList);
stac = stationList.num;
#endif
if (stac != stacO)
{
stacO = stac;
DEBUG_PRINT("Connected AP clients: ");
DEBUG_PRINTLN(stac);
if (!WLED_CONNECTED && WLED_WIFI_CONFIGURED) { //trying to connect, but not connected
if (stac) WiFi.disconnect(); //disable search so that AP can work
else initConnection(); //restart search
}
}
}
if (forceReconnect) {
DEBUG_PRINTLN("Forcing reconnect.");
initConnection();
interfacesInited = false;
forceReconnect = false;
wasConnected = false;
return;
}
if (!WLED_CONNECTED) {
if (interfacesInited) {
DEBUG_PRINTLN("Disconnected!");
interfacesInited = false;
initConnection();
}
if (millis() - lastReconnectAttempt > ((stac) ? 300000 : 20000) && WLED_WIFI_CONFIGURED) initConnection();
if (!apActive && millis() - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == AP_BEHAVIOR_NO_CONN)) initAP();
} else if (!interfacesInited) { //newly connected
DEBUG_PRINTLN("");
DEBUG_PRINT("Connected! IP address: ");
DEBUG_PRINTLN(WiFi.localIP());
initInterfaces();
userConnected();
//shut down AP
if (apBehavior != AP_BEHAVIOR_ALWAYS && apActive)
{
dnsServer.stop();
WiFi.softAPdisconnect(true);
apActive = false;
DEBUG_PRINTLN("Access point disabled.");
}
}
}
//by https://github.com/tzapu/WiFiManager/blob/master/WiFiManager.cpp
int getSignalQuality(int rssi)
{
int quality = 0;
if (rssi <= -100) {
quality = 0;
} else if (rssi >= -50) {
quality = 100;
} else {
quality = 2 * (rssi + 100);
}
return quality;
}

View File

@@ -1,398 +0,0 @@
/*
* UDP notifier
*/
#define WLEDPACKETSIZE 29
#define UDP_IN_MAXSIZE 1472
void notify(byte callMode, bool followUp=false)
{
if (!udpConnected) return;
switch (callMode)
{
case NOTIFIER_CALL_MODE_INIT: return;
case NOTIFIER_CALL_MODE_DIRECT_CHANGE: if (!notifyDirect) return; break;
case NOTIFIER_CALL_MODE_BUTTON: if (!notifyButton) return; break;
case NOTIFIER_CALL_MODE_NIGHTLIGHT: if (!notifyDirect) return; break;
case NOTIFIER_CALL_MODE_FX_CHANGED: if (!notifyDirect) return; break; //fx change
case NOTIFIER_CALL_MODE_HUE: if (!notifyHue) return; break;
case NOTIFIER_CALL_MODE_PRESET_CYCLE: if (!notifyDirect) return; break;
case NOTIFIER_CALL_MODE_BLYNK: if (!notifyDirect) return; break;
case NOTIFIER_CALL_MODE_ALEXA: if (!notifyAlexa) return; break;
default: return;
}
byte udpOut[WLEDPACKETSIZE];
udpOut[0] = 0; //0: wled notifier protocol 1: WARLS protocol
udpOut[1] = callMode;
udpOut[2] = bri;
udpOut[3] = col[0];
udpOut[4] = col[1];
udpOut[5] = col[2];
udpOut[6] = nightlightActive;
udpOut[7] = nightlightDelayMins;
udpOut[8] = effectCurrent;
udpOut[9] = effectSpeed;
udpOut[10] = col[3];
//compatibilityVersionByte:
//0: old 1: supports white 2: supports secondary color
//3: supports FX intensity, 24 byte packet 4: supports transitionDelay 5: sup palette
//6: supports timebase syncing, 29 byte packet 7: supports tertiary color
udpOut[11] = 7;
udpOut[12] = colSec[0];
udpOut[13] = colSec[1];
udpOut[14] = colSec[2];
udpOut[15] = colSec[3];
udpOut[16] = effectIntensity;
udpOut[17] = (transitionDelay >> 0) & 0xFF;
udpOut[18] = (transitionDelay >> 8) & 0xFF;
udpOut[19] = effectPalette;
uint32_t colTer = strip.getSegment(strip.getMainSegmentId()).colors[2];
udpOut[20] = (colTer >> 16) & 0xFF;
udpOut[21] = (colTer >> 8) & 0xFF;
udpOut[22] = (colTer >> 0) & 0xFF;
udpOut[23] = (colTer >> 24) & 0xFF;
udpOut[24] = followUp;
uint32_t t = millis() + strip.timebase;
udpOut[25] = (t >> 24) & 0xFF;
udpOut[26] = (t >> 16) & 0xFF;
udpOut[27] = (t >> 8) & 0xFF;
udpOut[28] = (t >> 0) & 0xFF;
IPAddress broadcastIp;
broadcastIp = ~uint32_t(WiFi.subnetMask()) | uint32_t(WiFi.gatewayIP());
notifierUdp.beginPacket(broadcastIp, udpPort);
notifierUdp.write(udpOut, WLEDPACKETSIZE);
notifierUdp.endPacket();
notificationSentCallMode = callMode;
notificationSentTime = millis();
notificationTwoRequired = (followUp)? false:notifyTwice;
}
void arlsLock(uint32_t timeoutMs, byte md = REALTIME_MODE_GENERIC)
{
if (!realtimeMode){
for (uint16_t i = 0; i < ledCount; i++)
{
strip.setPixelColor(i,0,0,0,0);
}
realtimeMode = md;
}
realtimeTimeout = millis() + timeoutMs;
if (timeoutMs == 255001 || timeoutMs == 65000) realtimeTimeout = UINT32_MAX;
if (arlsForceMaxBri) strip.setBrightness(255);
}
void handleE131Packet(e131_packet_t* p, IPAddress clientIP){
//E1.31 protocol support
// skip out-of-sequence packets
if (p->sequence_number < e131LastSequenceNumber && p->sequence_number > 20 && e131LastSequenceNumber < 250){
DEBUG_PRINT("skipping E1.31 frame (last seq=");
DEBUG_PRINT(e131LastSequenceNumber);
DEBUG_PRINT(", current seq=");
DEBUG_PRINT(p->sequence_number);
DEBUG_PRINTLN(")");
return;
}
e131LastSequenceNumber = p->sequence_number;
// update status info
realtimeIP = clientIP;
uint16_t uni = htons(p->universe);
uint8_t previousUniverses = uni - e131Universe;
uint16_t possibleLEDsInCurrentUniverse;
uint16_t dmxChannels = htons(p->property_value_count) -1;
switch (DMXMode) {
case DMX_MODE_DISABLED:
return; // nothing to do
break;
case DMX_MODE_SINGLE_RGB:
if (uni != e131Universe) return;
if (dmxChannels-DMXAddress+1 < 3) return;
for (uint16_t i = 0; i < ledCount; i++)
setRealtimePixel(i, p->property_values[DMXAddress+0], p->property_values[DMXAddress+1], p->property_values[DMXAddress+2], 0);
break;
case DMX_MODE_SINGLE_DRGB:
if (uni != e131Universe) return;
if (dmxChannels-DMXAddress+1 < 4) return;
if (DMXOldDimmer != p->property_values[DMXAddress+0]) {
DMXOldDimmer = p->property_values[DMXAddress+0];
bri = p->property_values[DMXAddress+0];
strip.setBrightness(bri);
}
for (uint16_t i = 0; i < ledCount; i++)
setRealtimePixel(i, p->property_values[DMXAddress+1], p->property_values[DMXAddress+2], p->property_values[DMXAddress+3], 0);
break;
case DMX_MODE_EFFECT:
if (uni != e131Universe) return;
if (dmxChannels-DMXAddress+1 < 11) return;
if (DMXOldDimmer != p->property_values[DMXAddress+0]) {
DMXOldDimmer = p->property_values[DMXAddress+0];
bri = p->property_values[DMXAddress+0];
}
if (p->property_values[DMXAddress+1] < MODE_COUNT)
effectCurrent = p->property_values[DMXAddress+ 1];
effectSpeed = p->property_values[DMXAddress+ 2]; // flickers
effectIntensity = p->property_values[DMXAddress+ 3];
effectPalette = p->property_values[DMXAddress+ 4];
col[0] = p->property_values[DMXAddress+ 5];
col[1] = p->property_values[DMXAddress+ 6];
col[2] = p->property_values[DMXAddress+ 7];
colSec[0] = p->property_values[DMXAddress+ 8];
colSec[1] = p->property_values[DMXAddress+ 9];
colSec[2] = p->property_values[DMXAddress+10];
if (dmxChannels-DMXAddress+1 > 11)
{
col[3] = p->property_values[DMXAddress+11]; //white
colSec[3] = p->property_values[DMXAddress+12];
}
transitionDelayTemp = 0; // act fast
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); // don't send UDP
return; // don't activate realtime live mode
break;
case DMX_MODE_MULTIPLE_RGB:
if (previousUniverses == 0) {
// first universe of this fixture
possibleLEDsInCurrentUniverse = (dmxChannels - DMXAddress + 1) / 3;
for (uint16_t i = 0; i < ledCount; i++) {
if (i >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
setRealtimePixel(i, p->property_values[DMXAddress+i*3+0], p->property_values[DMXAddress+i*3+1], p->property_values[DMXAddress+i*3+2], 0);
}
} else if (previousUniverses > 0 && uni < (e131Universe + E131_MAX_UNIVERSE_COUNT)) {
// additional universe(s) of this fixture
uint16_t numberOfLEDsInPreviousUniverses = ((512 - DMXAddress + 1) / 3); // first universe
if (previousUniverses > 1) numberOfLEDsInPreviousUniverses += (512 / 3) * (previousUniverses - 1); // extended universe(s) before current
possibleLEDsInCurrentUniverse = dmxChannels / 3;
for (uint16_t i = numberOfLEDsInPreviousUniverses; i < ledCount; i++) {
uint8_t j = i - numberOfLEDsInPreviousUniverses;
if (j >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
setRealtimePixel(i, p->property_values[j*3+1], p->property_values[j*3+2], p->property_values[j*3+3], 0);
}
}
break;
case DMX_MODE_MULTIPLE_DRGB:
if (previousUniverses == 0) {
// first universe of this fixture
if (DMXOldDimmer != p->property_values[DMXAddress+0]) {
DMXOldDimmer = p->property_values[DMXAddress+0];
bri = p->property_values[DMXAddress+0];
strip.setBrightness(bri);
}
possibleLEDsInCurrentUniverse = (dmxChannels - DMXAddress) / 3;
for (uint16_t i = 0; i < ledCount; i++) {
if (i >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
setRealtimePixel(i, p->property_values[DMXAddress+i*3+1], p->property_values[DMXAddress+i*3+2], p->property_values[DMXAddress+i*3+3], 0);
}
} else if (previousUniverses > 0 && uni < (e131Universe + E131_MAX_UNIVERSE_COUNT)) {
// additional universe(s) of this fixture
uint16_t numberOfLEDsInPreviousUniverses = ((512 - DMXAddress + 1) / 3); // first universe
if (previousUniverses > 1) numberOfLEDsInPreviousUniverses += (512 / 3) * (previousUniverses - 1); // extended universe(s) before current
possibleLEDsInCurrentUniverse = dmxChannels / 3;
for (uint16_t i = numberOfLEDsInPreviousUniverses; i < ledCount; i++) {
uint8_t j = i - numberOfLEDsInPreviousUniverses;
if (j >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
setRealtimePixel(i, p->property_values[j*3+1], p->property_values[j*3+2], p->property_values[j*3+3], 0);
}
}
break;
default:
DEBUG_PRINTLN("unknown E1.31 DMX mode");
return; // nothing to do
break;
}
arlsLock(realtimeTimeoutMs, REALTIME_MODE_E131);
e131NewData = true;
}
void handleNotifications()
{
//send second notification if enabled
if(udpConnected && notificationTwoRequired && millis()-notificationSentTime > 250){
notify(notificationSentCallMode,true);
}
if (e131NewData && millis() - strip.getLastShow() > 15)
{
e131NewData = false;
strip.show();
}
//unlock strip when realtime UDP times out
if (realtimeMode && millis() > realtimeTimeout)
{
strip.setBrightness(bri);
realtimeMode = REALTIME_MODE_INACTIVE;
}
//receive UDP notifications
if (!udpConnected || !(receiveNotifications || receiveDirect)) return;
uint16_t packetSize = notifierUdp.parsePacket();
//hyperion / raw RGB
if (!packetSize && udpRgbConnected) {
packetSize = rgbUdp.parsePacket();
if (!receiveDirect) return;
if (packetSize > UDP_IN_MAXSIZE || packetSize < 3) return;
realtimeIP = rgbUdp.remoteIP();
DEBUG_PRINTLN(rgbUdp.remoteIP());
uint8_t lbuf[packetSize];
rgbUdp.read(lbuf, packetSize);
arlsLock(realtimeTimeoutMs, REALTIME_MODE_HYPERION);
uint16_t id = 0;
for (uint16_t i = 0; i < packetSize -2; i += 3)
{
setRealtimePixel(id, lbuf[i], lbuf[i+1], lbuf[i+2], 0);
id++; if (id >= ledCount) break;
}
strip.show();
return;
}
//notifier and UDP realtime
if (packetSize > UDP_IN_MAXSIZE) return;
if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves
{
uint8_t udpIn[packetSize];
notifierUdp.read(udpIn, packetSize);
//wled notifier, block if realtime packets active
if (udpIn[0] == 0 && !realtimeMode && receiveNotifications)
{
//ignore notification if received within a second after sending a notification ourselves
if (millis() - notificationSentTime < 1000) return;
if (udpIn[1] > 199) return; //do not receive custom versions
bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
//apply colors from notification
if (receiveNotificationColor || !someSel)
{
col[0] = udpIn[3];
col[1] = udpIn[4];
col[2] = udpIn[5];
if (udpIn[11] > 0) //sending module's white val is intended
{
col[3] = udpIn[10];
if (udpIn[11] > 1)
{
colSec[0] = udpIn[12];
colSec[1] = udpIn[13];
colSec[2] = udpIn[14];
colSec[3] = udpIn[15];
}
if (udpIn[11] > 5)
{
uint32_t t = (udpIn[25] << 24) | (udpIn[26] << 16) | (udpIn[27] << 8) | (udpIn[28]);
t += 2;
t -= millis();
strip.timebase = t;
}
if (udpIn[11] > 6)
{
strip.setColor(2, udpIn[20], udpIn[21], udpIn[22], udpIn[23]); //tertiary color
}
}
}
//apply effects from notification
if (udpIn[11] < 200 && (receiveNotificationEffects || !someSel))
{
if (udpIn[8] < strip.getModeCount()) effectCurrent = udpIn[8];
effectSpeed = udpIn[9];
if (udpIn[11] > 2) effectIntensity = udpIn[16];
if (udpIn[11] > 4 && udpIn[19] < strip.getPaletteCount()) effectPalette = udpIn[19];
}
if (udpIn[11] > 3)
{
transitionDelayTemp = ((udpIn[17] << 0) & 0xFF) + ((udpIn[18] << 8) & 0xFF00);
}
nightlightActive = udpIn[6];
if (nightlightActive) nightlightDelayMins = udpIn[7];
if (receiveNotificationBrightness || !someSel) bri = udpIn[2];
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
} else if (udpIn[0] > 0 && udpIn[0] < 5 && receiveDirect) //1 warls //2 drgb //3 drgbw
{
realtimeIP = notifierUdp.remoteIP();
DEBUG_PRINTLN(notifierUdp.remoteIP());
if (packetSize > 1) {
if (udpIn[1] == 0)
{
realtimeTimeout = 0;
return;
} else {
arlsLock(udpIn[1]*1000 +1, REALTIME_MODE_UDP);
}
if (udpIn[0] == 1) //warls
{
for (uint16_t i = 2; i < packetSize -3; i += 4)
{
setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0);
}
} else if (udpIn[0] == 2) //drgb
{
uint16_t id = 0;
for (uint16_t i = 2; i < packetSize -2; i += 3)
{
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
id++; if (id >= ledCount) break;
}
} else if (udpIn[0] == 3) //drgbw
{
uint16_t id = 0;
for (uint16_t i = 2; i < packetSize -3; i += 4)
{
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
id++; if (id >= ledCount) break;
}
} else if (udpIn[0] == 4) //dnrgb
{
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
for (uint16_t i = 4; i < packetSize -2; i += 3)
{
if (id >= ledCount) break;
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
id++;
}
}
strip.show();
}
}
}
}
void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w)
{
uint16_t pix = i + arlsOffset;
if (pix < ledCount)
{
if (!arlsDisableGammaCorrection && strip.gammaCorrectCol)
{
strip.setPixelColor(pix, strip.gamma8(r), strip.gamma8(g), strip.gamma8(b), strip.gamma8(w));
} else {
strip.setPixelColor(pix, r, g, b, w);
}
}
}

View File

@@ -1,125 +0,0 @@
/*
* Used to draw clock overlays over the strip
*/
void initCronixie()
{
if (overlayCurrent == 3 && !cronixieInit)
{
strip.driverModeCronixie(true);
strip.setCronixieBacklight(cronixieBacklight);
setCronixie();
cronixieInit = true;
} else if (cronixieInit && overlayCurrent != 3)
{
strip.driverModeCronixie(false);
cronixieInit = false;
}
}
void handleOverlays()
{
if (millis() - overlayRefreshedTime > overlayRefreshMs)
{
initCronixie();
updateLocalTime();
checkTimers();
checkCountdown();
if (overlayCurrent == 3) _overlayCronixie();//Diamex cronixie clock kit
overlayRefreshedTime = millis();
}
}
void _overlayAnalogClock()
{
int overlaySize = overlayMax - overlayMin +1;
if (countdownMode)
{
_overlayAnalogCountdown(); return;
}
double hourP = ((double)(hour(local)%12))/12;
double minuteP = ((double)minute(local))/60;
hourP = hourP + minuteP/12;
double secondP = ((double)second(local))/60;
int hourPixel = floor(analogClock12pixel + overlaySize*hourP);
if (hourPixel > overlayMax) hourPixel = overlayMin -1 + hourPixel - overlayMax;
int minutePixel = floor(analogClock12pixel + overlaySize*minuteP);
if (minutePixel > overlayMax) minutePixel = overlayMin -1 + minutePixel - overlayMax;
int secondPixel = floor(analogClock12pixel + overlaySize*secondP);
if (secondPixel > overlayMax) secondPixel = overlayMin -1 + secondPixel - overlayMax;
if (analogClockSecondsTrail)
{
if (secondPixel < analogClock12pixel)
{
strip.setRange(analogClock12pixel, overlayMax, 0xFF0000);
strip.setRange(overlayMin, secondPixel, 0xFF0000);
} else
{
strip.setRange(analogClock12pixel, secondPixel, 0xFF0000);
}
}
if (analogClock5MinuteMarks)
{
int pix;
for (int i = 0; i <= 12; i++)
{
pix = analogClock12pixel + round((overlaySize / 12.0) *i);
if (pix > overlayMax) pix -= overlaySize;
strip.setPixelColor(pix, 0x00FFAA);
}
}
if (!analogClockSecondsTrail) strip.setPixelColor(secondPixel, 0xFF0000);
strip.setPixelColor(minutePixel, 0x00FF00);
strip.setPixelColor(hourPixel, 0x0000FF);
overlayRefreshMs = 998;
}
void _overlayAnalogCountdown()
{
if (now() < countdownTime)
{
long diff = countdownTime - now();
double pval = 60;
if (diff > 31557600L) //display in years if more than 365 days
{
pval = 315576000L; //10 years
} else if (diff > 2592000L) //display in months if more than a month
{
pval = 31557600L; //1 year
} else if (diff > 604800) //display in weeks if more than a week
{
pval = 2592000L; //1 month
} else if (diff > 86400) //display in days if more than 24 hours
{
pval = 604800; //1 week
} else if (diff > 3600) //display in hours if more than 60 minutes
{
pval = 86400; //1 day
} else if (diff > 60) //display in minutes if more than 60 seconds
{
pval = 3600; //1 hour
}
int overlaySize = overlayMax - overlayMin +1;
double perc = (pval-(double)diff)/pval;
if (perc > 1.0) perc = 1.0;
byte pixelCnt = perc*overlaySize;
if (analogClock12pixel + pixelCnt > overlayMax)
{
strip.setRange(analogClock12pixel, overlayMax, ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
strip.setRange(overlayMin, overlayMin +pixelCnt -(1+ overlayMax -analogClock12pixel), ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
} else
{
strip.setRange(analogClock12pixel, analogClock12pixel + pixelCnt, ((uint32_t)colSec[3] << 24)| ((uint32_t)colSec[0] << 16) | ((uint32_t)colSec[1] << 8) | colSec[2]);
}
}
overlayRefreshMs = 998;
}
void handleOverlayDraw() {
if (overlayCurrent != 1) return; //only analog clock
_overlayAnalogClock();
}

View File

@@ -1,12 +1,13 @@
#include <EEPROM.h>
#include "wled.h"
/*
* Methods to handle saving and loading to non-volatile memory
* EEPROM Map: https://github.com/Aircoookie/WLED/wiki/EEPROM-Map
*/
#define EEPSIZE 2560 //Maximum is 4096
//eeprom Version code, enables default settings instead of 0 init on update
#define EEPVER 16
#define EEPVER 19
//0 -> old version, default
//1 -> 0.4p 1711272 and up
//2 -> 0.4p 1711302 and up
@@ -24,6 +25,9 @@
//14-> 0.9.0-b1
//15-> 0.9.0-b3
//16-> 0.9.1
//17-> 0.9.1-dmx
//18-> 0.9.1-e131
//19-> 0.9.1n
void commit()
{
@@ -63,7 +67,6 @@ void readStringFromEEPROM(uint16_t pos, char* str, uint16_t len)
str[len] = 0; //make sure every string is properly terminated. str must be at least len +1 big.
}
/*
* Write configuration to flash
*/
@@ -159,7 +162,7 @@ void saveSettingsToEEPROM()
EEPROM.write(396, (utcOffsetSecs<0)); //is negative
EEPROM.write(397, syncToggleReceive);
EEPROM.write(398, (ledCount >> 8) & 0xFF);
EEPROM.write(399, !enableSecTransition);
//EEPROM.write(399, was !enableSecTransition);
//favorite setting (preset) memory (25 slots/ each 20byte)
//400 - 940 reserved
@@ -208,6 +211,10 @@ void saveSettingsToEEPROM()
EEPROM.write(2181, macroNl);
EEPROM.write(2182, macroDoublePress);
EEPROM.write(2187, e131Port & 0xFF);
EEPROM.write(2188, (e131Port >> 8) & 0xFF);
EEPROM.write(2189, e131SkipOutOfSequence);
EEPROM.write(2190, e131Universe & 0xFF);
EEPROM.write(2191, (e131Universe >> 8) & 0xFF);
EEPROM.write(2192, e131Multicast);
@@ -232,8 +239,8 @@ void saveSettingsToEEPROM()
EEPROM.write(2208, presetCycleMin);
EEPROM.write(2209, presetCycleMax);
EEPROM.write(2210, presetApplyBri);
EEPROM.write(2211, presetApplyCol);
EEPROM.write(2212, presetApplyFx);
// was EEPROM.write(2211, presetApplyCol);
// was EEPROM.write(2212, presetApplyFx);
saveCurrPresetCycConf = false;
}
@@ -257,6 +264,19 @@ void saveSettingsToEEPROM()
EEPROM.write(2522, mqttPort & 0xFF);
EEPROM.write(2523, (mqttPort >> 8) & 0xFF);
// DMX (2530 - 2549)
#ifdef WLED_ENABLE_DMX
EEPROM.write(2530, DMXChannels);
EEPROM.write(2531, DMXGap & 0xFF);
EEPROM.write(2532, (DMXGap >> 8) & 0xFF);
EEPROM.write(2533, DMXStart & 0xFF);
EEPROM.write(2534, (DMXStart >> 8) & 0xFF);
for (int i=0; i<15; i++) {
EEPROM.write(2535+i, DMXFixtureMap[i]);
} // last used: 2549. maybe leave a few bytes for future expansion and go on with 2600 kthxbye.
#endif
commit();
}
@@ -492,6 +512,17 @@ void loadSettingsFromEEPROM(bool first)
noWifiSleep = EEPROM.read(370);
//}
if (lastEEPROMversion > 17)
{
e131SkipOutOfSequence = EEPROM.read(2189);
} else {
e131SkipOutOfSequence = true;
}
if (lastEEPROMversion > 18)
{
e131Port = EEPROM.read(2187) + ((EEPROM.read(2188) << 8) & 0xFF00);
}
receiveDirect = !EEPROM.read(2200);
notifyMacro = EEPROM.read(2201);
@@ -506,15 +537,15 @@ void loadSettingsFromEEPROM(bool first)
presetCycleMin = EEPROM.read(2208);
presetCycleMax = EEPROM.read(2209);
presetApplyBri = EEPROM.read(2210);
presetApplyCol = EEPROM.read(2211);
presetApplyFx = EEPROM.read(2212);
//was presetApplyCol = EEPROM.read(2211);
//was presetApplyFx = EEPROM.read(2212);
}
bootPreset = EEPROM.read(389);
wifiLock = EEPROM.read(393);
utcOffsetSecs = EEPROM.read(394) + ((EEPROM.read(395) << 8) & 0xFF00);
if (EEPROM.read(396)) utcOffsetSecs = -utcOffsetSecs; //negative
enableSecTransition = !EEPROM.read(399);
//!EEPROM.read(399); was enableSecTransition
//favorite setting (preset) memory (25 slots/ each 20byte)
//400 - 899 reserved
@@ -525,6 +556,18 @@ void loadSettingsFromEEPROM(bool first)
readStringFromEEPROM(2220, blynkApiKey, 35);
if (strlen(blynkApiKey) < 25) blynkApiKey[0] = 0;
#ifdef WLED_ENABLE_DMX
// DMX (2530 - 2549)2535
DMXChannels = EEPROM.read(2530);
DMXGap = EEPROM.read(2531) + ((EEPROM.read(2532) << 8) & 0xFF00);
DMXStart = EEPROM.read(2533) + ((EEPROM.read(2534) << 8) & 0xFF00);
for (int i=0;i<15;i++) {
DMXFixtureMap[i] = EEPROM.read(2535+i);
} //last used: 2549
EEPROM.write(2550, DMXStartLED);
#endif
//user MOD memory
//2944 - 3071 reserved
@@ -559,7 +602,7 @@ void savedToPresets()
}
}
bool applyPreset(byte index, bool loadBri = true, bool loadCol = true, bool loadFX = true)
bool applyPreset(byte index, bool loadBri)
{
if (index == 255 || index == 0)
{
@@ -568,32 +611,37 @@ bool applyPreset(byte index, bool loadBri = true, bool loadCol = true, bool load
}
if (index > 16 || index < 1) return false;
uint16_t i = 380 + index*20;
byte ver = EEPROM.read(i);
if (index < 16) {
if (EEPROM.read(i) != 1) return false;
if (ver != 1) return false;
strip.applyToAllSelected = true;
if (loadBri) bri = EEPROM.read(i+1);
if (loadCol)
for (byte j=0; j<4; j++)
{
for (byte j=0; j<4; j++)
{
col[j] = EEPROM.read(i+j+2);
colSec[j] = EEPROM.read(i+j+6);
}
strip.setColor(2, EEPROM.read(i+12), EEPROM.read(i+13), EEPROM.read(i+14), EEPROM.read(i+15)); //tertiary color
}
if (loadFX)
{
effectCurrent = EEPROM.read(i+10);
effectSpeed = EEPROM.read(i+11);
effectIntensity = EEPROM.read(i+16);
effectPalette = EEPROM.read(i+17);
col[j] = EEPROM.read(i+j+2);
colSec[j] = EEPROM.read(i+j+6);
}
strip.setColor(2, EEPROM.read(i+12), EEPROM.read(i+13), EEPROM.read(i+14), EEPROM.read(i+15)); //tertiary color
effectCurrent = EEPROM.read(i+10);
effectSpeed = EEPROM.read(i+11);
effectIntensity = EEPROM.read(i+16);
effectPalette = EEPROM.read(i+17);
} else {
if (EEPROM.read(i) != 2) return false;
if (ver != 2 && ver != 3) return false;
strip.applyToAllSelected = false;
if (loadBri) bri = EEPROM.read(i+1);
WS2812FX::Segment* seg = strip.getSegments();
memcpy(seg, EEPROM.getDataPtr() +i+2, 240);
if (ver == 2) { //versions before 2004230 did not have opacity
for (byte j = 0; j < strip.getMaxSegments(); j++)
{
strip.getSegment(j).opacity = 255;
strip.getSegment(j).setOption(SEG_OPTION_ON, 1);
}
}
setValuesFromMainSeg();
}
currentPreset = index;
@@ -601,7 +649,7 @@ bool applyPreset(byte index, bool loadBri = true, bool loadCol = true, bool load
return true;
}
void savePreset(byte index)
void savePreset(byte index, bool persist)
{
if (index > 16) return;
if (index < 1) {saveSettingsToEEPROM();return;}
@@ -627,13 +675,13 @@ void savePreset(byte index)
EEPROM.write(i+16, effectIntensity);
EEPROM.write(i+17, effectPalette);
} else { //segment 16 can save segments
EEPROM.write(i, 2);
EEPROM.write(i, 3);
EEPROM.write(i+1, bri);
WS2812FX::Segment* seg = strip.getSegments();
memcpy(EEPROM.getDataPtr() +i+2, seg, 240);
}
commit();
if (persist) commit();
savedToPresets();
currentPreset = index;
isPreset = true;
@@ -669,7 +717,7 @@ void applyMacro(byte index)
}
void saveMacro(byte index, String mc, bool sing=true) //only commit on single save, not in settings
void saveMacro(byte index, String mc, bool persist) //only commit on single save, not in settings
{
index-=1;
if (index > 15) return;
@@ -678,5 +726,5 @@ void saveMacro(byte index, String mc, bool sing=true) //only commit on single sa
{
EEPROM.write(i, mc.charAt(i-s));
}
if (sing) commit();
if (persist) commit();
}

View File

@@ -1,6 +1,9 @@
#include "wled.h"
/*
* Utility for SPIFFS filesystem & Serial console
* Adalight handler
*/
enum class AdaState {
Header_A,
Header_d,
@@ -64,13 +67,13 @@ void handleSerial()
break;
case AdaState::Data_Blue:
byte blue = next;
setRealtimePixel(pixel++, red, green, blue, 0);
if (!realtimeOverride) setRealtimePixel(pixel++, red, green, blue, 0);
if (--count > 0) state = AdaState::Data_Red;
else {
if (!realtimeMode && bri == 0) strip.setBrightness(briLast);
arlsLock(realtimeTimeoutMs, REALTIME_MODE_ADALIGHT);
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_ADALIGHT);
strip.show();
if (!realtimeOverride) strip.show();
state = AdaState::Header_A;
}
break;
@@ -78,44 +81,3 @@ void handleSerial()
}
#endif
}
#if !defined WLED_DISABLE_FILESYSTEM && defined WLED_ENABLE_FS_SERVING
//Un-comment any file types you need
String getContentType(AsyncWebServerRequest* request, String filename){
if(request->hasArg("download")) return "application/octet-stream";
else if(filename.endsWith(".htm")) return "text/html";
else if(filename.endsWith(".html")) return "text/html";
// else if(filename.endsWith(".css")) return "text/css";
// else if(filename.endsWith(".js")) return "application/javascript";
else if(filename.endsWith(".json")) return "application/json";
else if(filename.endsWith(".png")) return "image/png";
// else if(filename.endsWith(".gif")) return "image/gif";
else if(filename.endsWith(".jpg")) return "image/jpeg";
else if(filename.endsWith(".ico")) return "image/x-icon";
// else if(filename.endsWith(".xml")) return "text/xml";
// else if(filename.endsWith(".pdf")) return "application/x-pdf";
// else if(filename.endsWith(".zip")) return "application/x-zip";
// else if(filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}
bool handleFileRead(AsyncWebServerRequest* request, String path){
DEBUG_PRINTLN("FileRead: " + path);
if(path.endsWith("/")) path += "index.htm";
String contentType = getContentType(request, path);
String pathWithGz = path + ".gz";
if(SPIFFS.exists(pathWithGz)){
request->send(SPIFFS, pathWithGz, contentType);
return true;
}
if(SPIFFS.exists(path)) {
request->send(SPIFFS, path, contentType);
return true;
}
return false;
}
#else
bool handleFileRead(AsyncWebServerRequest*, String path){return false;}
#endif

View File

@@ -1,5 +1,7 @@
#include "wled.h"
/*
* Server page definitions
* Integrated HTTP web server page declarations
*/
//Is this an IP?
@@ -62,39 +64,44 @@ void initServer()
});
server.on("/reset", HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 200,"Rebooting now...","Please wait ~10 seconds...",129);
serveMessage(request, 200,"Rebooting now...",F("Please wait ~10 seconds..."),129);
doReboot = true;
});
server.on("/settings/wifi", HTTP_POST, [](AsyncWebServerRequest *request){
if (!(wifiLock && otaLock)) handleSettingsSet(request, 1);
serveMessage(request, 200,"WiFi settings saved.","Please connect to the new IP (if changed)",129);
serveMessage(request, 200,F("WiFi settings saved."),F("Please connect to the new IP (if changed)"),129);
forceReconnect = true;
});
server.on("/settings/leds", HTTP_POST, [](AsyncWebServerRequest *request){
handleSettingsSet(request, 2);
serveMessage(request, 200,"LED settings saved.","Redirecting...",1);
serveMessage(request, 200,F("LED settings saved."),"Redirecting...",1);
});
server.on("/settings/ui", HTTP_POST, [](AsyncWebServerRequest *request){
handleSettingsSet(request, 3);
serveMessage(request, 200,"UI settings saved.","Redirecting...",1);
serveMessage(request, 200,F("UI settings saved."),"Redirecting...",1);
});
server.on("/settings/dmx", HTTP_POST, [](AsyncWebServerRequest *request){
handleSettingsSet(request, 7);
serveMessage(request, 200,F("UI settings saved."),"Redirecting...",1);
});
server.on("/settings/sync", HTTP_POST, [](AsyncWebServerRequest *request){
handleSettingsSet(request, 4);
serveMessage(request, 200,"Sync settings saved.","Redirecting...",1);
serveMessage(request, 200,F("Sync settings saved."),"Redirecting...",1);
});
server.on("/settings/time", HTTP_POST, [](AsyncWebServerRequest *request){
handleSettingsSet(request, 5);
serveMessage(request, 200,"Time settings saved.","Redirecting...",1);
serveMessage(request, 200,F("Time settings saved."),"Redirecting...",1);
});
server.on("/settings/sec", HTTP_POST, [](AsyncWebServerRequest *request){
handleSettingsSet(request, 6);
if (!doReboot) serveMessage(request, 200,"Security settings saved.","Rebooting, please wait ~10 seconds...",129);
if (!doReboot) serveMessage(request, 200,F("Security settings saved."),F("Rebooting, please wait ~10 seconds..."),129);
doReboot = true;
});
@@ -138,8 +145,12 @@ void initServer()
request->send_P(200, "text/html", PAGE_usermod);
});
server.on("/url", HTTP_GET, [](AsyncWebServerRequest *request){
URL_response(request);
});
server.on("/teapot", HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 418, "418. I'm a teapot.", "(Tangible Embedded Advanced Project Of Twinkling)", 254);
serveMessage(request, 418, F("418. I'm a teapot."), F("(Tangible Embedded Advanced Project Of Twinkling)"), 254);
});
//if OTA is allowed
@@ -152,7 +163,7 @@ void initServer()
#endif
#else
server.on("/edit", HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 501, "Not implemented", "The SPIFFS editor is disabled in this build.", 254);
serveMessage(request, 501, "Not implemented", F("The SPIFFS editor is disabled in this build."), 254);
});
#endif
//init ota page
@@ -164,9 +175,9 @@ void initServer()
server.on("/update", HTTP_POST, [](AsyncWebServerRequest *request){
if (Update.hasError())
{
serveMessage(request, 500, "Failed updating firmware!", "Please check your file and retry!", 254); return;
serveMessage(request, 500, F("Failed updating firmware!"), F("Please check your file and retry!"), 254); return;
}
serveMessage(request, 200, "Successfully updated firmware!", "Please wait while the module reboots...", 131);
serveMessage(request, 200, F("Successfully updated firmware!"), F("Please wait while the module reboots..."), 131);
doReboot = true;
},[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
if(!index){
@@ -188,7 +199,7 @@ void initServer()
#else
server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 501, "Not implemented", "OTA updates are disabled in this build.", 254);
serveMessage(request, 501, "Not implemented", F("OTA updates are disabled in this build."), 254);
});
#endif
} else
@@ -201,6 +212,16 @@ void initServer()
});
}
#ifdef WLED_ENABLE_DMX
server.on("/dmxmap", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", PAGE_dmxmap , dmxProcessor);
});
#else
server.on("/dmxmap", HTTP_GET, [](AsyncWebServerRequest *request){
serveMessage(request, 501, "Not implemented", F("DMX support is not enabled in this build."), 254);
});
#endif
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
if (captivePortal(request)) return;
serveIndexOrWelcome(request);
@@ -273,10 +294,10 @@ String msgProcessor(const String& var)
messageBody += "<script>setTimeout(RP," + String((optt-120)*1000) + ")</script>";
} else if (optt == 253)
{
messageBody += "<br><br><form action=/settings><button class=\"bt\" type=submit>Back</button></form>"; //button to settings
messageBody += F("<br><br><form action=/settings><button class=\"bt\" type=submit>Back</button></form>"); //button to settings
} else if (optt == 254)
{
messageBody += "<br><br><button type=\"button\" class=\"bt\" onclick=\"B()\">Back</button>";
messageBody += F("<br><br><button type=\"button\" class=\"bt\" onclick=\"B()\">Back</button>");
}
return messageBody;
}
@@ -284,7 +305,7 @@ String msgProcessor(const String& var)
}
void serveMessage(AsyncWebServerRequest* request, uint16_t code, String headl, String subl="", byte optionT=255)
void serveMessage(AsyncWebServerRequest* request, uint16_t code, String headl, String subl, byte optionT)
{
messageHead = headl;
messageSub = subl;
@@ -301,10 +322,38 @@ String settingsProcessor(const String& var)
getSettingsJS(optionType, buf);
return String(buf);
}
#ifdef WLED_ENABLE_DMX
if (var == "DMXMENU") {
return String(F("<form action=/settings/dmx><button type=submit>DMX Output</button></form>"));
}
#endif
if (var == "SCSS") return String(FPSTR(PAGE_settingsCss));
return String();
}
String dmxProcessor(const String& var)
{
String mapJS;
#ifdef WLED_ENABLE_DMX
if (var == "DMXVARS") {
mapJS += "\nCN=" + String(DMXChannels) + ";\n";
mapJS += "CS=" + String(DMXStart) + ";\n";
mapJS += "CG=" + String(DMXGap) + ";\n";
mapJS += "LC=" + String(ledCount) + ";\n";
mapJS += "var CH=[";
for (int i=0;i<15;i++) {
mapJS += String(DMXFixtureMap[i]) + ",";
}
mapJS += "0];";
}
#endif
return mapJS;
}
void serveSettings(AsyncWebServerRequest* request)
{
@@ -318,6 +367,9 @@ void serveSettings(AsyncWebServerRequest* request)
else if (url.indexOf("sync") > 0) subPage = 4;
else if (url.indexOf("time") > 0) subPage = 5;
else if (url.indexOf("sec") > 0) subPage = 6;
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
else if (url.indexOf("dmx") > 0) subPage = 7;
#endif
} else subPage = 255; //welcome page
if (subPage == 1 && wifiLock && otaLock)
@@ -339,7 +391,8 @@ void serveSettings(AsyncWebServerRequest* request)
case 4: request->send_P(200, "text/html", PAGE_settings_sync, settingsProcessor); break;
case 5: request->send_P(200, "text/html", PAGE_settings_time, settingsProcessor); break;
case 6: request->send_P(200, "text/html", PAGE_settings_sec , settingsProcessor); break;
case 7: request->send_P(200, "text/html", PAGE_settings_dmx , settingsProcessor); break;
case 255: request->send_P(200, "text/html", PAGE_welcome); break;
default: request->send_P(200, "text/html", PAGE_settings);
default: request->send_P(200, "text/html", PAGE_settings , settingsProcessor);
}
}

View File

@@ -1,15 +1,17 @@
#include "wled.h"
/*
* Sending XML status files to client
*/
//build XML response to HTTP /win API request
char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr)
char* XML_response(AsyncWebServerRequest *request, char* dest)
{
char sbuf[(dest == nullptr)?1024:1]; //allocate local buffer if none passed
obuf = (dest == nullptr)? sbuf:dest;
olen = 0;
oappend("<?xml version=\"1.0\" ?><vs><ac>");
oappend((const char*)F("<?xml version=\"1.0\" ?><vs><ac>"));
oappendi((nightlightActive && nightlightFade) ? briT : bri);
oappend("</ac>");
@@ -61,11 +63,12 @@ char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr)
if (realtimeMode)
{
String mesg = "Live ";
if (realtimeMode == REALTIME_MODE_E131)
if (realtimeMode == REALTIME_MODE_E131 || realtimeMode == REALTIME_MODE_ARTNET)
{
mesg += "E1.31 mode ";
mesg += (realtimeMode == REALTIME_MODE_E131) ? "E1.31" : "Art-Net";
mesg += " mode ";
mesg += DMXMode;
mesg += " at DMX Address ";
mesg += F(" at DMX Address ");
mesg += DMXAddress;
mesg += " from ";
mesg += realtimeIP[0];
@@ -74,8 +77,6 @@ char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr)
mesg += ".";
mesg += realtimeIP[i];
}
mesg += " seq=";
mesg += e131LastSequenceNumber;
} else if (realtimeMode == REALTIME_MODE_UDP || realtimeMode == REALTIME_MODE_HYPERION) {
mesg += "UDP from ";
mesg += realtimeIP[0];
@@ -85,7 +86,7 @@ char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr)
mesg += realtimeIP[i];
}
} else if (realtimeMode == REALTIME_MODE_ADALIGHT) {
mesg += "USB Adalight";
mesg += F("USB Adalight");
} else { //generic
mesg += "data";
}
@@ -99,6 +100,53 @@ char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr)
if (request != nullptr) request->send(200, "text/xml", obuf);
}
char* URL_response(AsyncWebServerRequest *request)
{
char sbuf[256]; //allocate local buffer if none passed
char s2buf[100];
obuf = s2buf;
olen = 0;
char s[16];
oappend("http://");
IPAddress localIP = WiFi.localIP();
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
oappend(s);
oappend("/win&A=");
oappendi(bri);
oappend("&CL=h");
for (int i = 0; i < 3; i++)
{
sprintf(s,"%02X", col[i]);
oappend(s);
}
oappend("&C2=h");
for (int i = 0; i < 3; i++)
{
sprintf(s,"%02X", colSec[i]);
oappend(s);
}
oappend("&FX=");
oappendi(effectCurrent);
oappend("&SX=");
oappendi(effectSpeed);
oappend("&IX=");
oappendi(effectIntensity);
oappend("&FP=");
oappendi(effectPalette);
obuf = sbuf;
olen = 0;
oappend((const char*)F("<html><body><a href=\""));
oappend(s2buf);
oappend((const char*)F("\" target=\"_blank\">"));
oappend(s2buf);
oappend((const char*)F("</a></body></html>"));
if (request != nullptr) request->send(200, "text/html", obuf);
}
//append a numeric setting to string buffer
void sappend(char stype, const char* key, int val)
{
@@ -162,7 +210,7 @@ void getSettingsJS(byte subPage, char* dest)
obuf = dest;
olen = 0;
if (subPage <1 || subPage >6) return;
if (subPage <1 || subPage >7) return;
if (subPage == 1) {
sappends('s',"CS",clientSSID);
@@ -279,6 +327,8 @@ void getSettingsJS(byte subPage, char* dest)
sappend('c',"SM",notifyMacro);
sappend('c',"S2",notifyTwice);
sappend('c',"RD",receiveDirect);
sappend('v',"EP",e131Port);
sappend('c',"ES",e131SkipOutOfSequence);
sappend('c',"EM",e131Multicast);
sappend('v',"EU",e131Universe);
sappend('v',"DA",DMXAddress);
@@ -308,9 +358,7 @@ void getSettingsJS(byte subPage, char* dest)
sappends('s',"MG",mqttGroupTopic);
#endif
#ifdef WLED_DISABLE_HUESYNC
sappends('m',"(\"hms\")[0]","Unsupported in build");
#else
#ifndef WLED_DISABLE_HUESYNC
sappend('v',"H0",hueIP[0]);
sappend('v',"H1",hueIP[1]);
sappend('v',"H2",hueIP[2]);
@@ -321,7 +369,20 @@ void getSettingsJS(byte subPage, char* dest)
sappend('c',"HO",hueApplyOnOff);
sappend('c',"HB",hueApplyBri);
sappend('c',"HC",hueApplyColor);
sappends('m',"(\"hms\")[0]",hueError);
char hueErrorString[25];
switch (hueError)
{
case HUE_ERROR_INACTIVE : strcpy(hueErrorString,(char*)F("Inactive")); break;
case HUE_ERROR_ACTIVE : strcpy(hueErrorString,(char*)F("Active")); break;
case HUE_ERROR_UNAUTHORIZED : strcpy(hueErrorString,(char*)F("Unauthorized")); break;
case HUE_ERROR_LIGHTID : strcpy(hueErrorString,(char*)F("Invalid light ID")); break;
case HUE_ERROR_PUSHLINK : strcpy(hueErrorString,(char*)F("Link button not pressed")); break;
case HUE_ERROR_JSON_PARSING : strcpy(hueErrorString,(char*)F("JSON parsing error")); break;
case HUE_ERROR_TIMEOUT : strcpy(hueErrorString,(char*)F("Timeout")); break;
default: sprintf(hueErrorString,"Bridge Error %i",hueError);
}
sappends('m',"(\"sip\")[0]",hueErrorString);
#endif
}
@@ -384,12 +445,38 @@ void getSettingsJS(byte subPage, char* dest)
sappend('c',"NO",otaLock);
sappend('c',"OW",wifiLock);
sappend('c',"AO",aOtaEnabled);
sappends('m',"(\"msg\")[0]","WLED ");
sappends('m',"(\"sip\")[0]","WLED ");
olen -= 2; //delete ";
oappend(versionString);
oappend(" (build ");
oappendi(VERSION);
oappend(") OK\";");
oappend(")\";");
}
#ifdef WLED_ENABLE_DMX // include only if DMX is enabled
if (subPage == 7)
{
sappend('v',"CN",DMXChannels);
sappend('v',"CG",DMXGap);
sappend('v',"CS",DMXStart);
sappend('v',"SL",DMXStartLED);
sappend('i',"CH1",DMXFixtureMap[0]);
sappend('i',"CH2",DMXFixtureMap[1]);
sappend('i',"CH3",DMXFixtureMap[2]);
sappend('i',"CH4",DMXFixtureMap[3]);
sappend('i',"CH5",DMXFixtureMap[4]);
sappend('i',"CH6",DMXFixtureMap[5]);
sappend('i',"CH7",DMXFixtureMap[6]);
sappend('i',"CH8",DMXFixtureMap[7]);
sappend('i',"CH9",DMXFixtureMap[8]);
sappend('i',"CH10",DMXFixtureMap[9]);
sappend('i',"CH11",DMXFixtureMap[10]);
sappend('i',"CH12",DMXFixtureMap[11]);
sappend('i',"CH13",DMXFixtureMap[12]);
sappend('i',"CH14",DMXFixtureMap[13]);
sappend('i',"CH15",DMXFixtureMap[14]);
}
#endif
oappend("}</script>");
}