Compare commits
513 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71886c162b | ||
|
|
df1f516f6b | ||
|
|
2e55189d59 | ||
|
|
6ade40ce85 | ||
|
|
94c5f0d7a8 | ||
|
|
b1028086a3 | ||
|
|
385b3570b2 | ||
|
|
77edd12030 | ||
|
|
217fca31e4 | ||
|
|
5e1d20fc72 | ||
|
|
db60309ce8 | ||
|
|
6a5b757a24 | ||
|
|
a19098a004 | ||
|
|
ec10c29aca | ||
|
|
f90ab46794 | ||
|
|
b8ca97e019 | ||
|
|
e12757dbb9 | ||
|
|
3e9b44d193 | ||
|
|
3006d25406 | ||
|
|
f2ae9a0711 | ||
|
|
19945e4ccb | ||
|
|
61ab16acd6 | ||
|
|
3a84292f82 | ||
|
|
1d314294c7 | ||
|
|
b5b1dbfe85 | ||
|
|
5be88dd188 | ||
|
|
88b67b9541 | ||
|
|
a31da3186f | ||
|
|
9a7a38e913 | ||
|
|
a0960f5468 | ||
|
|
9b87a512cf | ||
|
|
8da985b6d0 | ||
|
|
5cb2a39746 | ||
|
|
6268cadc95 | ||
|
|
470b4b3972 | ||
|
|
a88ae2ca56 | ||
|
|
9875fbef0a | ||
|
|
cf29ddc8d0 | ||
|
|
ad70fcba7f | ||
|
|
a9a7720a11 | ||
|
|
8ff4f50f79 | ||
|
|
aea07f42d1 | ||
|
|
8d75c06852 | ||
|
|
ffbedbc1e6 | ||
|
|
a47d48c973 | ||
|
|
c54092c932 | ||
|
|
9134c3b4af | ||
|
|
7e21955211 | ||
|
|
40ac760285 | ||
|
|
de63bdac39 | ||
|
|
408d63825a | ||
|
|
3e1eb02f54 | ||
|
|
d2f55e1064 | ||
|
|
c97bead631 | ||
|
|
8264ca4e9e | ||
|
|
05bdaa4bc7 | ||
|
|
cc2de04f6b | ||
|
|
f99f13a090 | ||
|
|
f35ab125ec | ||
|
|
b8342f1c9c | ||
|
|
0ce77bbc59 | ||
|
|
e39eccb99e | ||
|
|
77ce67d685 | ||
|
|
ef125ff109 | ||
|
|
30e3bbd0e8 | ||
|
|
7bf1c35dcf | ||
|
|
c6ea2dff8a | ||
|
|
f2329476ec | ||
|
|
c4512b75d9 | ||
|
|
92e43abbc4 | ||
|
|
07d6bfa989 | ||
|
|
ccf5e66f31 | ||
|
|
6f5e71164a | ||
|
|
12131764d1 | ||
|
|
594c0b8550 | ||
|
|
ed729c32d2 | ||
|
|
ea26ee8d40 | ||
|
|
53f09c0630 | ||
|
|
2856e02eac | ||
|
|
a4f0c9195e | ||
|
|
0e73a0293b | ||
|
|
f4f5d6e562 | ||
|
|
e5c3629e2e | ||
|
|
5028471598 | ||
|
|
c28027496d | ||
|
|
c0f5509652 | ||
|
|
9bc48ececa | ||
|
|
1f53e4d4a2 | ||
|
|
dbef0e6583 | ||
|
|
c246e5af35 | ||
|
|
d36796429e | ||
|
|
37a31a9b94 | ||
|
|
c2ab3f96a7 | ||
|
|
ef36b5377d | ||
|
|
f12237d298 | ||
|
|
5b312d4c8b | ||
|
|
d21e82b020 | ||
|
|
c6e5606b4c | ||
|
|
7b4dc43147 | ||
|
|
62510ac6a3 | ||
|
|
bffe2d7bd0 | ||
|
|
cbaf1e576d | ||
|
|
0d355dbf35 | ||
|
|
d851bff762 | ||
|
|
453f4b549b | ||
|
|
8d669b12b6 | ||
|
|
ed3234d949 | ||
|
|
603a00376f | ||
|
|
4f34cfb654 | ||
|
|
fd1e536cdb | ||
|
|
0c6a880a74 | ||
|
|
89fa053310 | ||
|
|
267887908e | ||
|
|
b86f58befe | ||
|
|
b804101c24 | ||
|
|
f28502514f | ||
|
|
79da716a44 | ||
|
|
f76a440b74 | ||
|
|
18dad0c72c | ||
|
|
14a5ab6740 | ||
|
|
d0d56c4416 | ||
|
|
9dd9a01211 | ||
|
|
480e7f5b54 | ||
|
|
cffee7bfa7 | ||
|
|
5b9eda9c63 | ||
|
|
0a363d5fc0 | ||
|
|
9eb646085e | ||
|
|
e3269f6edc | ||
|
|
57d3120b45 | ||
|
|
81da8261a0 | ||
|
|
7e5949b4a9 | ||
|
|
a776b8ac31 | ||
|
|
14e19226ea | ||
|
|
5473b3e42e | ||
|
|
143179cac9 | ||
|
|
ad2c7ee363 | ||
|
|
755448f9f5 | ||
|
|
f304a6891f | ||
|
|
1221661ae3 | ||
|
|
a78f17abec | ||
|
|
70bf957a8a | ||
|
|
e8e04db7b4 | ||
|
|
d5def30c59 | ||
|
|
81176bc4e6 | ||
|
|
730ba12c8d | ||
|
|
80ad456d48 | ||
|
|
2d75526395 | ||
|
|
cd618a43d4 | ||
|
|
1979236f3a | ||
|
|
3589adcb78 | ||
|
|
4a834ecfc8 | ||
|
|
3dcc3492e8 | ||
|
|
2e77dcc660 | ||
|
|
89f60a0422 | ||
|
|
0455c09e4c | ||
|
|
7360b882ac | ||
|
|
5ffd29e31a | ||
|
|
5d7e892464 | ||
|
|
e8fd5de5b2 | ||
|
|
a8e7aa99e8 | ||
|
|
9a0db83f83 | ||
|
|
4e85566b88 | ||
|
|
8be72f6f23 | ||
|
|
513bc2c0ab | ||
|
|
036ba77a68 | ||
|
|
392277100c | ||
|
|
a7092ac503 | ||
|
|
027a16a39b | ||
|
|
c66af86d88 | ||
|
|
e621fdec0c | ||
|
|
447594b5ea | ||
|
|
a0b208cca0 | ||
|
|
1a4061fdb5 | ||
|
|
fb59f1f0a0 | ||
|
|
b1961033b3 | ||
|
|
863498f762 | ||
|
|
bdc44a4070 | ||
|
|
6451522f89 | ||
|
|
5ca1e9268c | ||
|
|
451a6841c9 | ||
|
|
3e3f46a683 | ||
|
|
2b0eaafea6 | ||
|
|
c1a8fde9a0 | ||
|
|
9dbd1b2a1b | ||
|
|
0cc1007543 | ||
|
|
8ca86181e4 | ||
|
|
8759d8f868 | ||
|
|
65a32b4166 | ||
|
|
933a0cddf8 | ||
|
|
d4c0542c84 | ||
|
|
05f5aaaeca | ||
|
|
036bd07e72 | ||
|
|
9c3e7b9ec0 | ||
|
|
1fd0383f69 | ||
|
|
9e62db5237 | ||
|
|
3062786bb3 | ||
|
|
b42847c135 | ||
|
|
5befcd24b5 | ||
|
|
61f3002568 | ||
|
|
0b7e0e166c | ||
|
|
3b52770a1b | ||
|
|
d0b9f53d8c | ||
|
|
92a9d7d26a | ||
|
|
ffd958a1b3 | ||
|
|
a7e9c7e24b | ||
|
|
9839cc6386 | ||
|
|
8d66d38fd2 | ||
|
|
a004d1647d | ||
|
|
21fe2c5f8f | ||
|
|
867e43637c | ||
|
|
c9025917b2 | ||
|
|
258def854c | ||
|
|
e8481818c8 | ||
|
|
f646e9bc59 | ||
|
|
680923bdd5 | ||
|
|
17e43a7ff2 | ||
|
|
71a5cfed4b | ||
|
|
c055477d3b | ||
|
|
ad4acca17a | ||
|
|
37b84300b4 | ||
|
|
d9a8dac266 | ||
|
|
76f704b060 | ||
|
|
cde360f7ec | ||
|
|
d69a2f1514 | ||
|
|
06a5c1a798 | ||
|
|
ca1f25ecf6 | ||
|
|
adcd7fb170 | ||
|
|
f105436b41 | ||
|
|
47738c751c | ||
|
|
0b3f2da6ef | ||
|
|
fa7092cc17 | ||
|
|
773d6e002c | ||
|
|
b78d1baaaf | ||
|
|
50ff59239c | ||
|
|
8f36878dde | ||
|
|
a29e98fd41 | ||
|
|
e4d5551f16 | ||
|
|
e610a1ffe4 | ||
|
|
ac927d188b | ||
|
|
bbf2f6c7de | ||
|
|
398816dbeb | ||
|
|
f3b399b31f | ||
|
|
2b0a38d25d | ||
|
|
b41dacb6c0 | ||
|
|
c5f5532303 | ||
|
|
09485c995e | ||
|
|
dc936b63d6 | ||
|
|
b5213794a8 | ||
|
|
2f8365a790 | ||
|
|
47be430bc1 | ||
|
|
918da24c8d | ||
|
|
0e82f2a02f | ||
|
|
447f15cfa4 | ||
|
|
8f80c206e7 | ||
|
|
e1a61985a2 | ||
|
|
16ad0c22f0 | ||
|
|
3d0d027216 | ||
|
|
b58a17a99e | ||
|
|
adaf2e15cd | ||
|
|
1723683370 | ||
|
|
9cd0a7982a | ||
|
|
d2726aae90 | ||
|
|
607a66b983 | ||
|
|
38b2adcaad | ||
|
|
d7879d8853 | ||
|
|
2d5b09a16f | ||
|
|
a06a722c23 | ||
|
|
d9d45f86cb | ||
|
|
e49b9cff67 | ||
|
|
8c69a4cb7a | ||
|
|
1042ac141a | ||
|
|
81aab35231 | ||
|
|
1c5742c7d4 | ||
|
|
4d646e67f3 | ||
|
|
59fbc51283 | ||
|
|
125e21900a | ||
|
|
569efd3e45 | ||
|
|
6c557ec015 | ||
|
|
63b917eb07 | ||
|
|
71af63dfc7 | ||
|
|
0cae048ada | ||
|
|
71021da261 | ||
|
|
1d897e491a | ||
|
|
57c0b408e5 | ||
|
|
43e0186efe | ||
|
|
8831d74cbc | ||
|
|
9a9d2cb964 | ||
|
|
2fc2a0cbdb | ||
|
|
40c041c9e7 | ||
|
|
b00c1dd055 | ||
|
|
761245049f | ||
|
|
30e142edd3 | ||
|
|
b7d84c002d | ||
|
|
551afe0cd7 | ||
|
|
5d8bfc2930 | ||
|
|
5d947cc8e1 | ||
|
|
7bf92db4c9 | ||
|
|
593c1d6b05 | ||
|
|
30e326b8b8 | ||
|
|
cf60eb52d8 | ||
|
|
8850dac291 | ||
|
|
bed52d0a4a | ||
|
|
10e564eeea | ||
|
|
ae47c4c79a | ||
|
|
e99e9fed11 | ||
|
|
79e9dbb9c6 | ||
|
|
081a6888fa | ||
|
|
ae6ba79f1e | ||
|
|
d9d2ad4382 | ||
|
|
31d277ffa2 | ||
|
|
7fe5f8907e | ||
|
|
2e9b59e2e0 | ||
|
|
5188894301 | ||
|
|
4c16efbbf7 | ||
|
|
8055243909 | ||
|
|
2eb4383e03 | ||
|
|
bafd043aae | ||
|
|
3379e7cc48 | ||
|
|
d971fc440f | ||
|
|
31658f4eab | ||
|
|
339be2b7a4 | ||
|
|
3e716e429f | ||
|
|
a8a61665f4 | ||
|
|
a7a1002509 | ||
|
|
65154e48cb | ||
|
|
32c10e5ae8 | ||
|
|
61ee1c6ff3 | ||
|
|
6642d96688 | ||
|
|
df8b085f0e | ||
|
|
7a415ccdfc | ||
|
|
2a432dc6ee | ||
|
|
322d1f09de | ||
|
|
44f4bd6e62 | ||
|
|
2bb74233cc | ||
|
|
19f6fd2295 | ||
|
|
558811e4f9 | ||
|
|
ed560a338e | ||
|
|
74741682bf | ||
|
|
d32d4e21e9 | ||
|
|
78f301d503 | ||
|
|
318ffc821c | ||
|
|
ef4ec16860 | ||
|
|
6bc927c535 | ||
|
|
2fe2b3c975 | ||
|
|
e4ad0d3b59 | ||
|
|
750261d205 | ||
|
|
df1b25f381 | ||
|
|
4af7ccd84c | ||
|
|
4282053f68 | ||
|
|
5c7d993dbe | ||
|
|
cdef7a53a4 | ||
|
|
b1f26d4ebe | ||
|
|
9bf534288c | ||
|
|
3d359229cf | ||
|
|
8013f8d5b3 | ||
|
|
cf12ab4b74 | ||
|
|
0f3eecaa8a | ||
|
|
22c1f4bb4e | ||
|
|
43c5fea782 | ||
|
|
41eab27f20 | ||
|
|
ba354f68d1 | ||
|
|
a6c7cc7b41 | ||
|
|
4dfc1631af | ||
|
|
58861fa524 | ||
|
|
1c6b1c530f | ||
|
|
21b498fece | ||
|
|
446e2c123f | ||
|
|
b3a7ee633d | ||
|
|
8b6366688a | ||
|
|
1671c78260 | ||
|
|
96ca459df8 | ||
|
|
51fb981d24 | ||
|
|
2ef46195d3 | ||
|
|
6e35b5ba8b | ||
|
|
b8ea0bd1ff | ||
|
|
8ca6ca2c88 | ||
|
|
508804d0d5 | ||
|
|
eb251050a5 | ||
|
|
67758b4980 | ||
|
|
f187d7258b | ||
|
|
5efd1f3a91 | ||
|
|
e3def22b07 | ||
|
|
ce5839ce27 | ||
|
|
50082043ef | ||
|
|
012045878d | ||
|
|
3083ccddcc | ||
|
|
f39b9041a0 | ||
|
|
37827cdd6c | ||
|
|
58f41a1f9b | ||
|
|
7712faca0a | ||
|
|
805fe1d47e | ||
|
|
0d4d1eff94 | ||
|
|
38cc460358 | ||
|
|
8600360173 | ||
|
|
f3371c443e | ||
|
|
a86f750473 | ||
|
|
92b532ce9a | ||
|
|
924f97cbe8 | ||
|
|
8817dc6d73 | ||
|
|
7324d59e08 | ||
|
|
dcd8e9250f | ||
|
|
f07578e0cb | ||
|
|
cabcf8b7b2 | ||
|
|
a90a07f46d | ||
|
|
9839bab8dc | ||
|
|
b9dd3de63b | ||
|
|
194aa90aee | ||
|
|
9bc72df1b5 | ||
|
|
b2439ca0af | ||
|
|
70d04d807b | ||
|
|
2372675c79 | ||
|
|
cb66900575 | ||
|
|
de4be44728 | ||
|
|
21dc037848 | ||
|
|
9fe5e69503 | ||
|
|
c0ac381f6f | ||
|
|
5f235c121d | ||
|
|
6b8e9a63f3 | ||
|
|
3dcda08735 | ||
|
|
f92ee8e762 | ||
|
|
94200dd3a4 | ||
|
|
512c4dd6f1 | ||
|
|
6d43854557 | ||
|
|
112ba7ac5c | ||
|
|
4c58929dd4 | ||
|
|
2188509d2c | ||
|
|
263ef14822 | ||
|
|
ed24f72cf9 | ||
|
|
c1197d06fe | ||
|
|
bd4d1cdd41 | ||
|
|
2c70d66d4a | ||
|
|
97ecace40e | ||
|
|
6ef988549d | ||
|
|
9088d79390 | ||
|
|
0c9bcb2445 | ||
|
|
c98c54bd6b | ||
|
|
225e66a522 | ||
|
|
f1810a9784 | ||
|
|
9526051766 | ||
|
|
bd435b175b | ||
|
|
42ab734256 | ||
|
|
77d89e7df3 | ||
|
|
c1dec16c50 | ||
|
|
86ae11f4c4 | ||
|
|
7ca1970fff | ||
|
|
b1cbbeb935 | ||
|
|
2dce4462a0 | ||
|
|
55e2bc27c6 | ||
|
|
2c3cad6e61 | ||
|
|
6122a8371a | ||
|
|
4ffeb05120 | ||
|
|
310f55abb6 | ||
|
|
d6c0642a02 | ||
|
|
541556874f | ||
|
|
477d7080b8 | ||
|
|
173c752d62 | ||
|
|
3b70488828 | ||
|
|
334783f89a | ||
|
|
89a54e31f1 | ||
|
|
354d18f78e | ||
|
|
0e8806eb2b | ||
|
|
731550acb3 | ||
|
|
be4019b4d3 | ||
|
|
70ffcd9adf | ||
|
|
bbe511dd15 | ||
|
|
82d5ac91d7 | ||
|
|
54de0eab6a | ||
|
|
4d5bb274d1 | ||
|
|
131fae57e5 | ||
|
|
37da53c20e | ||
|
|
6ad57a15cf | ||
|
|
4729bce16c | ||
|
|
0b5ac7a139 | ||
|
|
677e23ad14 | ||
|
|
6d838e3043 | ||
|
|
f322abceb8 | ||
|
|
e754d21598 | ||
|
|
0fdd861ef1 | ||
|
|
2e5f6a3507 | ||
|
|
4e57cab0fa | ||
|
|
9930c8f94d | ||
|
|
f8e262b87e | ||
|
|
896bdaf124 | ||
|
|
2e4f2639a3 | ||
|
|
ce89a92d0d | ||
|
|
1d9d1f6bbd | ||
|
|
767b57fc01 | ||
|
|
9e00177d76 | ||
|
|
095429a7df | ||
|
|
983efd61fb | ||
|
|
e028316308 | ||
|
|
e1354accb8 | ||
|
|
ea726f928d | ||
|
|
6b419dbfc0 | ||
|
|
006a9eaf44 | ||
|
|
76117854c6 | ||
|
|
6eae6db46b | ||
|
|
3aacb7150d | ||
|
|
81298a1034 | ||
|
|
b3d728df91 | ||
|
|
9a091ff11a | ||
|
|
6989b1730e | ||
|
|
1595542d59 | ||
|
|
fba9992a10 | ||
|
|
867dce2294 | ||
|
|
692554a899 | ||
|
|
f3cc616e07 | ||
|
|
d1c289b709 | ||
|
|
e7a0874a57 | ||
|
|
1beb9c4bb8 | ||
|
|
6eef3a9037 | ||
|
|
ddaaae46a6 | ||
|
|
4e4773a370 |
20
.github/stale.yml
vendored
Normal file
20
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 120
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- keep
|
||||
- enhancement
|
||||
- confirmed
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
Hey! This issue has been open for quite some time without any new comments now.
|
||||
It will be closed automatically in a week if no further activity occurs.
|
||||
|
||||
Thank you for using WLED!
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -5,3 +5,7 @@
|
||||
!.vscode/extensions.json
|
||||
/wled00/Release
|
||||
/wled00/extLibs
|
||||
/platformio_override.ini
|
||||
.DS_Store
|
||||
.gitignore
|
||||
.clang-format
|
||||
|
||||
14
.travis.yml
14
.travis.yml
@@ -18,18 +18,26 @@
|
||||
# it (remove "# " before each line) or use own configuration according to the
|
||||
# Travis CI documentation (see above).
|
||||
#
|
||||
# * Test the Travis config here:
|
||||
# < https://config.travis-ci.com/explore >
|
||||
#
|
||||
|
||||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
sudo: false
|
||||
# - "2.7"
|
||||
- "3.5"
|
||||
os: linux
|
||||
cache:
|
||||
bundler: true
|
||||
ccache: true
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
- "~/.buildcache"
|
||||
env:
|
||||
- PLATFORMIO_CI_SRC=wled00
|
||||
install:
|
||||
- pip install -U platformio
|
||||
- platformio update
|
||||
script:
|
||||
- platformio ci --project-conf=./platformio.ini -v
|
||||
# - platformio ci --project-conf=./platformio.ini
|
||||
- platformio run
|
||||
12
.vscode/extensions.json
vendored
12
.vscode/extensions.json
vendored
@@ -1,7 +1,7 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
||||
|
||||
111
CHANGELOG.md
Normal file
111
CHANGELOG.md
Normal 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
|
||||
|
||||
404
platformio.ini
404
platformio.ini
@@ -2,162 +2,314 @@
|
||||
; 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
|
||||
; Please uncomment one of the 5 lines below to select your board
|
||||
; env_default = nodemcuv2
|
||||
; env_default = esp01
|
||||
; env_default = esp01_1m
|
||||
; env_default = d1_mini
|
||||
; env_default = esp32dev
|
||||
lib_dir = ./wled00/src
|
||||
build_cache_dir = ~/.buildcache
|
||||
extra_configs =
|
||||
platformio_override.ini
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ENVIRONMENTS
|
||||
#
|
||||
# Please uncomment one of the lines below to select your board(s)
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Travis CI binaries (comment this out when building for single board)
|
||||
default_envs = d1_mini, esp01, esp01_1m_ota, esp32dev
|
||||
|
||||
# Release binaries
|
||||
; default_envs = nodemcuv2, esp01, esp01_1m_ota, esp01_1m_full, esp32dev, custom_WS2801, custom_APA102, custom_LEDPIN_16, custom_LEDPIN_4, custom32_LEDPIN_16
|
||||
|
||||
# Single binaries (uncomment your board)
|
||||
; default_envs = nodemcuv2
|
||||
; default_envs = esp01
|
||||
; default_envs = esp01_1m_ota
|
||||
; default_envs = esp01_1m_full
|
||||
; default_envs = esp07
|
||||
; default_envs = d1_mini
|
||||
; default_envs = heltec_wifi_kit_8
|
||||
; default_envs = h803wf
|
||||
; default_envs = d1_mini_debug
|
||||
; default_envs = d1_mini_ota
|
||||
; default_envs = esp32dev
|
||||
; default_envs = esp8285_4CH_MagicHome
|
||||
; default_envs = esp8285_4CH_H801
|
||||
; default_envs = esp8285_5CH_H801
|
||||
; default_envs = d1_mini_5CH_Shojo_PCB
|
||||
; default_envs = wemos_shield_esp32
|
||||
|
||||
[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
|
||||
# TODO replace libs in /lib with managed libs in here if possible.
|
||||
# If they are not changed it's just a matter of setting the correct version and change the import statement
|
||||
lib_deps_external =
|
||||
#Blynk@0.5.4(changed)
|
||||
#E131@1.0.0(changed)
|
||||
FastLED@3.3.2
|
||||
NeoPixelBus@2.5.1
|
||||
ESPAsyncTCP@1.2.0
|
||||
AsyncTCP@1.0.3
|
||||
Esp Async WebServer@1.2.0
|
||||
#ArduinoJson@5.13.5
|
||||
IRremoteESP8266@2.5.5
|
||||
#Time@1.5
|
||||
#Timezone@1.2.1
|
||||
|
||||
[common:esp8266]
|
||||
# ------------------------------------------------------------------------------
|
||||
# PLATFORM:
|
||||
# !! DO NOT confuse platformio's ESP8266 development platform with Arduino core for ESP8266
|
||||
# We use Arduino Core 2.5.0 (platformIO 2.0.4) as default
|
||||
#
|
||||
# arduino core 2.3.0 = platformIO 1.5.0
|
||||
# arduino core 2.4.0 = platformIO 1.6.0
|
||||
# arduino core 2.4.1 = platformIO 1.7.3
|
||||
# arduino core 2.4.2 = platformIO 1.8.0
|
||||
# arduino core 2.5.0 = platformIO 2.0.4
|
||||
# arduino core stage = platformIO feature#stage
|
||||
# arduino core 2.5.1 = platformIO 2.1.1
|
||||
# arduino core 2.5.2 = platformIO 2.2.3
|
||||
# arduino core 2.6.1 = platformIO 2.3.0
|
||||
# arduino core 2.6.2 = platformIO 2.3.1
|
||||
# arduino core 2.6.3 = platformIO 2.3.2
|
||||
# ------------------------------------------------------------------------------
|
||||
arduino_core_2_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_stage = https://github.com/platformio/platform-espressif8266.git#feature/stage
|
||||
platform = ${common:esp8266.arduino_core_2_5_2}
|
||||
build_flags =
|
||||
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
-Wl,-Teagle.flash.4m1m.ld ;;;; Required for core > v2.5.0 or staging version 4MB Flash 3MB SPIFFs
|
||||
arduino_core_2_6_1 = espressif8266@2.3.0
|
||||
arduino_core_2_6_2 = espressif8266@2.3.1
|
||||
arduino_core_2_6_3 = espressif8266@2.3.3
|
||||
|
||||
[common:esp8266_1M]
|
||||
platform = espressif8266@1.8.0
|
||||
build_flags =
|
||||
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
|
||||
-Wl,-Teagle.flash.1m0.ld ;;;; Compile with no SPIFFS to leave space for OTA
|
||||
; -D WLED_DISABLE_MOBILE_UI
|
||||
; -D WLED_DISABLE_OTA
|
||||
; -D WLED_DISABLE_ALEXA
|
||||
-D WLED_DISABLE_BLYNK
|
||||
-D WLED_DISABLE_CRONIXIE
|
||||
; -D WLED_DISABLE_HUESYNC
|
||||
-D WLED_DISABLE_INFRARED
|
||||
# Development platforms
|
||||
arduino_core_develop = https://github.com/platformio/platform-espressif8266#develop
|
||||
arduino_core_git = https://github.com/platformio/platform-espressif8266#feature/stage
|
||||
|
||||
[common:esp8266_512k]
|
||||
platform = espressif8266@1.8.0
|
||||
build_flags =
|
||||
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
|
||||
-Wl,-Teagle.flash.512k0.ld ;;;; Compile with no SPIFFS
|
||||
; -D WLED_DISABLE_MOBILE_UI
|
||||
-D WLED_DISABLE_OTA
|
||||
; -D WLED_DISABLE_ALEXA
|
||||
-D WLED_DISABLE_BLYNK
|
||||
-D WLED_DISABLE_CRONIXIE
|
||||
; -D WLED_DISABLE_HUESYNC
|
||||
-D WLED_DISABLE_INFRARED
|
||||
platform = ${common.arduino_core_2_4_2}
|
||||
platform_latest = ${common.arduino_core_2_6_3}
|
||||
|
||||
[common:esp32]
|
||||
platform = espressif32@1.7.0
|
||||
build_flags =
|
||||
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
-D ARDUINO_ARCH_ESP32
|
||||
-D WLED_DISABLE_INFRARED
|
||||
# ------------------------------------------------------------------------------
|
||||
# FLAGS: DEBUG
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
debug_flags = -D DEBUG=1 -D WLED_DEBUG -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_TLS_MEM
|
||||
#if needed (for memleaks etc) also add; -DDEBUG_ESP_OOM -include "umm_malloc/umm_malloc_cfg.h"
|
||||
#-DDEBUG_ESP_CORE is not working right now
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# FLAGS: ldscript
|
||||
# ldscript_512k ( 512 KB) = 487 KB sketch, 4 KB eeprom, no spiffs, 16 KB reserved
|
||||
# ldscript_1m0m (1024 KB) = 999 KB sketch, 4 KB eeprom, no spiffs, 16 KB reserved
|
||||
# ldscript_2m1m (2048 KB) = 1019 KB sketch, 4 KB eeprom, 1004 KB spiffs, 16 KB reserved
|
||||
# ldscript_4m1m (4096 KB) = 1019 KB sketch, 4 KB eeprom, 1002 KB spiffs, 16 KB reserved, 2048 KB empty/ota?
|
||||
# ldscript_4m3m (4096 KB) = 1019 KB sketch, 4 KB eeprom, 3040 KB spiffs, 16 KB reserved
|
||||
#
|
||||
# Available lwIP variants (macros):
|
||||
# -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH = v1.4 Higher Bandwidth (default)
|
||||
# -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY = v2 Lower Memory
|
||||
# -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH = v2 Higher Bandwidth
|
||||
#
|
||||
# BearSSL performance:
|
||||
# When building with -DSECURE_CLIENT=SECURE_CLIENT_BEARSSL, please add `board_build.f_cpu = 160000000` to the environment configuration
|
||||
#
|
||||
# BearSSL ciphers:
|
||||
# When building on core >= 2.5, you can add the build flag -DBEARSSL_SSL_BASIC in order to build BearSSL with a limited set of ciphers:
|
||||
# TLS_RSA_WITH_AES_128_CBC_SHA256 / AES128-SHA256
|
||||
# TLS_RSA_WITH_AES_256_CBC_SHA256 / AES256-SHA256
|
||||
# TLS_RSA_WITH_AES_128_CBC_SHA / AES128-SHA
|
||||
# TLS_RSA_WITH_AES_256_CBC_SHA / AES256-SHA
|
||||
# This reduces the OTA size with ~45KB, so it's especially useful on low memory boards (512k/1m).
|
||||
# ------------------------------------------------------------------------------
|
||||
build_flags = -g -w -DMQTT_MAX_PACKET_SIZE=1024 -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
||||
-DSECURE_CLIENT=SECURE_CLIENT_BEARSSL -DBEARSSL_SSL_BASIC
|
||||
#build_flags for the IRremoteESP8266 library (enabled decoders have to appear here)
|
||||
-D _IR_ENABLE_DEFAULT_=false
|
||||
-D DECODE_HASH=true
|
||||
-D DECODE_NEC=true
|
||||
-D DECODE_SONY=true
|
||||
-D DECODE_SAMSUNG=true
|
||||
-D DECODE_LG=true
|
||||
|
||||
build_flags_esp8266 = ${common.build_flags} -DESP8266
|
||||
build_flags_esp32 = ${common.build_flags} -DARDUINO_ARCH_ESP32
|
||||
|
||||
ldscript_512k = eagle.flash.512k.ld ;for older versions change this to eagle.flash.512k0.ld
|
||||
ldscript_1m0m = eagle.flash.1m.ld ;for older versions change this to eagle.flash.1m0.ld
|
||||
ldscript_2m1m = eagle.flash.2m1m.ld
|
||||
ldscript_4m1m = eagle.flash.4m1m.ld
|
||||
ldscript_4m3m = eagle.flash.4m3m.ld
|
||||
|
||||
shared_libdeps_dir = ./wled00/src
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# COMMON SETTINGS:
|
||||
# ------------------------------------------------------------------------------
|
||||
[env]
|
||||
framework = arduino
|
||||
board_build.flash_mode = dout
|
||||
monitor_speed = 115200
|
||||
upload_speed = 115200
|
||||
lib_extra_dirs =
|
||||
${common.shared_libdeps_dir}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# LIBRARIES: required dependencies
|
||||
# Please note that we don't always use the latest version of a library.
|
||||
#
|
||||
# The following libraries have been included (and some of them changd) in the source:
|
||||
# ArduinoJson@5.13.5, Blynk@0.5.4(changed), E131@1.0.0(changed), Time@1.5, Timezone@1.2.1
|
||||
# ------------------------------------------------------------------------------
|
||||
lib_compat_mode = strict
|
||||
lib_deps =
|
||||
FastLED@3.3.2
|
||||
NeoPixelBus@2.5.7
|
||||
ESPAsyncTCP@1.2.0
|
||||
ESPAsyncUDP@697c75a025
|
||||
AsyncTCP@1.0.3
|
||||
Esp Async WebServer@1.2.0
|
||||
IRremoteESP8266@2.7.3
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
#U8g2@~2.27.2
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
#OneWire@~2.3.5
|
||||
#For BME280 sensor uncomment following
|
||||
#BME280@~3.0.0
|
||||
lib_ignore =
|
||||
AsyncTCP
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# WLED BUILDS
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# see: http://docs.platformio.org/en/latest/platforms/espressif8266.html
|
||||
[env:nodemcuv2]
|
||||
board = nodemcuv2
|
||||
platform = ${common:esp8266.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266.build_flags}
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
|
||||
[env:d1_mini]
|
||||
board = d1_mini
|
||||
platform = ${common:esp8266.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266.build_flags}
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
|
||||
[env:esp01_1m]
|
||||
board = esp01_1m
|
||||
platform = ${common:esp8266_1M.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266_1M.build_flags}
|
||||
# disable IR because there is no pin for it
|
||||
-D WLED_DISABLE_INFRARED
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_4m1m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
|
||||
[env:esp01]
|
||||
board = esp01
|
||||
platform = ${common:esp8266_512k.platform}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
framework = ${common.framework}
|
||||
build_flags =
|
||||
${common.build_flags}
|
||||
${common:esp8266_512k.build_flags}
|
||||
lib_deps =
|
||||
${common.lib_deps_external}
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_512k}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA -D WLED_DISABLE_ALEXA -D WLED_DISABLE_BLYNK
|
||||
-D WLED_DISABLE_CRONIXIE -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_INFRARED
|
||||
|
||||
[env:esp01_1m_ota]
|
||||
board = esp01_1m
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_ALEXA -D WLED_DISABLE_BLYNK -D WLED_DISABLE_CRONIXIE -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_INFRARED
|
||||
|
||||
[env:esp01_1m_full]
|
||||
board = esp01_1m
|
||||
platform = ${common.platform_latest}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA
|
||||
|
||||
[env:esp07]
|
||||
board = esp07
|
||||
platform = ${common.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}
|
||||
platform = espressif32@1.11.2
|
||||
build_flags = ${common.build_flags_esp32}
|
||||
lib_ignore =
|
||||
IRremoteESP8266
|
||||
ESPAsyncTCP
|
||||
ESPAsyncUDP
|
||||
|
||||
[env:esp8285_4CH_MagicHome]
|
||||
board = esp8285
|
||||
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.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.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
|
||||
|
||||
36
platformio_override.ini.example
Normal file
36
platformio_override.ini.example
Normal file
@@ -0,0 +1,36 @@
|
||||
# Example PlatformIO Project Configuration Override
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copy to platformio_override.ini to activate overrides
|
||||
# ------------------------------------------------------------------------------
|
||||
# Please visit documentation: https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:esp8266_1m_custom]
|
||||
board = esp01_1m
|
||||
platform = ${common.arduino_core_2_4_2}
|
||||
board_build.ldscript = ${common.ldscript_1m0m}
|
||||
build_flags = ${common.build_flags_esp8266}
|
||||
-D WLED_DISABLE_OTA
|
||||
-D WLED_DISABLE_ALEXA
|
||||
-D WLED_DISABLE_BLYNK
|
||||
-D WLED_DISABLE_CRONIXIE
|
||||
-D WLED_DISABLE_HUESYNC
|
||||
-D WLED_DISABLE_INFRARED
|
||||
; PIN defines - uncomment and change, if needed:
|
||||
; -D LEDPIN=2
|
||||
; -D BTNPIN=0
|
||||
; -D IR_PIN=4
|
||||
; -D RLYPIN=12
|
||||
; -D RLYMDE=1
|
||||
; digital LED strip types - uncomment only one ! - this will disable WS281x / SK681x support
|
||||
; -D USE_APA102
|
||||
; -D USE_WS2801
|
||||
; -D USE_LPD8806
|
||||
; to drive analog LED strips (aka 5050), uncomment the following
|
||||
; PWM pins 5,12,13,15 are used with Magic Home LED Controller (default)
|
||||
; -D WLED_USE_ANALOG_LEDS
|
||||
; for the H801 controller (PINs 15,13,12,14 (W2 = 04)) uncomment this
|
||||
; -D WLED_USE_H801
|
||||
; for the BW-LT11 controller (PINs 12,4,14,5 ) uncomment this
|
||||
; -D WLED_USE_BWLT11
|
||||
; and to enable channel 5 for RGBW-CT led strips this
|
||||
; -D WLED_USE_5CH_LEDS
|
||||
29
readme.md
29
readme.md
@@ -1,6 +1,7 @@
|
||||

|
||||
|
||||
[](https://github.com/Aircoookie/WLED/releases)
|
||||
[](https://wled.discourse.group)
|
||||
[](https://discord.gg/KuqP7NE)
|
||||
[](https://github.com/Aircoookie/WLED/wiki)
|
||||
[](https://github.com/Aircoookie/WLED-App)
|
||||
@@ -10,13 +11,14 @@
|
||||
A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B, WS2811, SK6812, APA102) LEDs!
|
||||
|
||||
### Features:
|
||||
- WS2812FX library integrated for 80 special effects
|
||||
- FastLED noise effects and palettes
|
||||
- Customizable Mobile and desktop UI with color and effect controls
|
||||
- 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
|
||||
- Access Point and station mode - automatic failsafe AP
|
||||
- Support for RGBW strips
|
||||
- 25 user presets to save and load colors/effects easily, supports cycling through them.
|
||||
- 16 user presets to save and load colors/effects easily, supports cycling through them.
|
||||
- Macro functions to automatically execute API calls
|
||||
- Nightlight function (gradually dims down)
|
||||
- Full OTA software updatability (HTTP + ArduinoOTA), password protectable
|
||||
@@ -42,6 +44,16 @@ A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control
|
||||
|
||||
See the [wiki](https://github.com/Aircoookie/WLED/wiki)!
|
||||
|
||||
DrZzs has made some excellent video guides:
|
||||
[Introduction, hardware and installation](https://www.youtube.com/watch?v=tXvtxwK3jRk)
|
||||
[Settings, tips and tricks](https://www.youtube.com/watch?v=6eCE2BpLaUQ)
|
||||
|
||||
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
|
||||
@@ -50,5 +62,12 @@ Credits [here](https://github.com/Aircoookie/WLED/wiki/Contributors-&-About)!
|
||||
Uses Linearicons by Perxis!
|
||||
|
||||
Join the Discord [server](https://discord.gg/KuqP7NE) to discuss everything about WLED!
|
||||
You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com).
|
||||
Check out the WLED [Discourse forum](https://wled.discourse.group)!
|
||||
You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com), but please only do so if you want to talk to me privately.
|
||||
If WLED really brightens up your every day, you can [](https://paypal.me/aircoookie)
|
||||
|
||||
*Disclaimer:*
|
||||
If you are sensitive to photoeleptic seizures it is not recommended that you use this software.
|
||||
In case you still want to try, don't use strobe, lighting or noise modes or high effect speed settings.
|
||||
As per the MIT license, i assume no liability for any damage to you or any other person or equipment.
|
||||
|
||||
|
||||
BIN
usermods/Enclosure_with_OLED_temp_ESP07/assets/controller.jpg
Normal file
BIN
usermods/Enclosure_with_OLED_temp_ESP07/assets/controller.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 150 KiB |
BIN
usermods/Enclosure_with_OLED_temp_ESP07/assets/pcb.png
Normal file
BIN
usermods/Enclosure_with_OLED_temp_ESP07/assets/pcb.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 235 KiB |
7
usermods/Enclosure_with_OLED_temp_ESP07/assets/readme.md
Normal file
7
usermods/Enclosure_with_OLED_temp_ESP07/assets/readme.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Enclosure and PCB
|
||||
|
||||
## IP67 rated enclosure
|
||||

|
||||
|
||||
## PCB
|
||||

|
||||
68
usermods/Enclosure_with_OLED_temp_ESP07/readme.md
Normal file
68
usermods/Enclosure_with_OLED_temp_ESP07/readme.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Almost universal controller board for outdoor applications
|
||||
This usermod is using ideas from @mrVanboy and @400killer
|
||||
|
||||
Installation of file: Copy and replace file in wled00 directory.
|
||||
|
||||
For BME280 sensor use usermod_bme280.cpp. Copy to wled00 and rename to usermod.cpp
|
||||
|
||||
## Project repository
|
||||
- [Original repository](https://github.com/srg74/Controller-for-WLED-firmware) - Main controller repository
|
||||
## Features
|
||||
- SSD1306 128x32 and 128x64 I2C OLED display
|
||||
- On screen IP address, SSID and controller status (e.g. ON or OFF, recent effect)
|
||||
- Auto display shutoff for saving display lifetime
|
||||
- Dallas temperature sensor
|
||||
- Reporting temperature to MQTT broker
|
||||
|
||||
## Hardware
|
||||

|
||||
|
||||
## Functionality checked with
|
||||
- ESP-07S
|
||||
- PlatformIO
|
||||
- SSD1306 128x32 I2C OLED display
|
||||
- DS18B20 (temperature sensor)
|
||||
- BME280 (temperature, humidity and pressure sensor)
|
||||
- KY-022 (infrared receiver)
|
||||
- Push button (N.O. momentary switch)
|
||||
|
||||
For Dallas sensor uncomment `U8g2@~2.27.3`,`DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
default_envs = esp07
|
||||
; default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
DallasTemperature@~3.8.0
|
||||
OneWire@~2.3.5
|
||||
...
|
||||
```
|
||||
|
||||
For BME280 sensor uncomment `U8g2@~2.27.3`,`BME280@~3.0.0 under` `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
default_envs = esp07
|
||||
; default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For BME280 sensor uncomment following
|
||||
BME280@~3.0.0
|
||||
...
|
||||
```
|
||||
209
usermods/Enclosure_with_OLED_temp_ESP07/usermod.cpp
Normal file
209
usermods/Enclosure_with_OLED_temp_ESP07/usermod.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
#include <DallasTemperature.h> //Dallastemperature sensor
|
||||
//The SCL and SDA pins are defined here.
|
||||
//Lolin32 boards use SCL=5 SDA=4
|
||||
#define U8X8_PIN_SCL 5
|
||||
#define U8X8_PIN_SDA 4
|
||||
// Dallas sensor
|
||||
OneWire oneWire(13);
|
||||
DallasTemperature sensor(&oneWire);
|
||||
long temptimer = millis();
|
||||
long lastMeasure = 0;
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
|
||||
// If display does not work or looks corrupted check the
|
||||
// constructor reference:
|
||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||
// or check the gallery:
|
||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// gets called once at boot. Do all initialization that doesn't depend on
|
||||
// network here
|
||||
void userSetup() {
|
||||
sensor.begin(); //Start Dallas temperature sensor
|
||||
u8x8.begin();
|
||||
//u8x8.setFlipMode(1); //Uncoment if using WLED Wemos shield
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
//----> Dallas temperature sensor MQTT publishing
|
||||
temptimer = millis();
|
||||
// Timer to publishe new temperature every 60 seconds
|
||||
if (temptimer - lastMeasure > 60000)
|
||||
{
|
||||
lastMeasure = temptimer;
|
||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
sensor.requestTemperatures();
|
||||
//Gets prefered temperature scale based on selection in definitions section
|
||||
#ifdef Celsius
|
||||
float board_temperature = sensor.getTempCByIndex(0);
|
||||
#else
|
||||
float board_temperature = sensor.getTempFByIndex(0);
|
||||
#endif
|
||||
//Create character string populated with user defined device topic from the UI, and the read temperature. Then publish to MQTT server.
|
||||
char subuf[38];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/temperature");
|
||||
mqtt->publish(subuf, 0, true, String(board_temperature).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 3 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
|
||||
u8x8.setPowerSave(1);
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
u8x8.setPowerSave(0);
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#if defined(ESP8266)
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#else
|
||||
knownSsid = WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
u8x8.clear();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
u8x8.print(apPass);
|
||||
else
|
||||
u8x8.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
u8x8.setCursor(2, 2);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
u8x8.setCursor(2, 3);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
|
||||
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
|
||||
u8x8.drawGlyph(0, 0, 80); // wifi icon
|
||||
u8x8.drawGlyph(0, 1, 68); // home icon
|
||||
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
|
||||
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
|
||||
}
|
||||
266
usermods/Enclosure_with_OLED_temp_ESP07/usermod_bme280.cpp
Normal file
266
usermods/Enclosure_with_OLED_temp_ESP07/usermod_bme280.cpp
Normal file
@@ -0,0 +1,266 @@
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
#include <Wire.h>
|
||||
#include <BME280I2C.h> //BME280 sensor
|
||||
|
||||
void UpdateBME280Data();
|
||||
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
BME280I2C bme; // Default : forced mode, standby time = 1000 ms
|
||||
// Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off,
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32 //ESP32 boards
|
||||
uint8_t SCL_PIN = 22;
|
||||
uint8_t SDA_PIN = 21;
|
||||
#else //ESP8266 boards
|
||||
uint8_t SCL_PIN = 5;
|
||||
uint8_t SDA_PIN = 4;
|
||||
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
|
||||
#define U8X8_PIN_SCL SCL_PIN
|
||||
#define U8X8_PIN_SDA SDA_PIN
|
||||
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
|
||||
|
||||
// If display does not work or looks corrupted check the
|
||||
// constructor reference:
|
||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||
// or check the gallery:
|
||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
|
||||
// gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
|
||||
// BME280 sensor timer
|
||||
long tempTimer = millis();
|
||||
long lastMeasure = 0;
|
||||
|
||||
float SensorPressure(NAN);
|
||||
float SensorTemperature(NAN);
|
||||
float SensorHumidity(NAN);
|
||||
|
||||
void userSetup() {
|
||||
u8x8.begin();
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setFlipMode(1);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
Wire.begin(SDA_PIN,SCL_PIN);
|
||||
|
||||
while(!bme.begin())
|
||||
{
|
||||
Serial.println("Could not find BME280I2C sensor!");
|
||||
delay(1000);
|
||||
}
|
||||
switch(bme.chipModel())
|
||||
{
|
||||
case BME280::ChipModel_BME280:
|
||||
Serial.println("Found BME280 sensor! Success.");
|
||||
break;
|
||||
case BME280::ChipModel_BMP280:
|
||||
Serial.println("Found BMP280 sensor! No Humidity available.");
|
||||
break;
|
||||
default:
|
||||
Serial.println("Found UNKNOWN sensor! Error!");
|
||||
}
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
// BME280 sensor MQTT publishing
|
||||
tempTimer = millis();
|
||||
// Timer to publish new sensor data every 60 seconds
|
||||
if (tempTimer - lastMeasure > 60000)
|
||||
{
|
||||
lastMeasure = tempTimer;
|
||||
|
||||
// Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
UpdateBME280Data();
|
||||
float board_temperature = SensorTemperature;
|
||||
float board_pressure = SensorPressure;
|
||||
float board_humidity = SensorHumidity;
|
||||
|
||||
// Create string populated with user defined device topic from the UI, and the read temperature, humidity and pressure. Then publish to MQTT server.
|
||||
String t = String(mqttDeviceTopic);
|
||||
t += "/temperature";
|
||||
mqtt->publish(t.c_str(), 0, true, String(board_temperature).c_str());
|
||||
String p = String(mqttDeviceTopic);
|
||||
p += "/pressure";
|
||||
mqtt->publish(p.c_str(), 0, true, String(board_pressure).c_str());
|
||||
String h = String(mqttDeviceTopic);
|
||||
h += "/humidity";
|
||||
mqtt->publish(h.c_str(), 0, true, String(board_humidity).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 3 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
|
||||
u8x8.setPowerSave(1);
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
u8x8.setPowerSave(0);
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#if defined(ESP8266)
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#else
|
||||
knownSsid = WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
u8x8.clear();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
u8x8.print(apPass);
|
||||
else
|
||||
u8x8.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
u8x8.setCursor(2, 2);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
u8x8.setCursor(2, 3);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
|
||||
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
|
||||
u8x8.drawGlyph(0, 0, 80); // wifi icon
|
||||
u8x8.drawGlyph(0, 1, 68); // home icon
|
||||
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
|
||||
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
|
||||
}
|
||||
|
||||
void UpdateBME280Data() {
|
||||
float temp(NAN), hum(NAN), pres(NAN);
|
||||
#ifdef Celsius
|
||||
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
|
||||
#else
|
||||
BME280::TempUnit tempUnit(BME280::TempUnit_Fahrenheit);
|
||||
#endif
|
||||
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
|
||||
bme.read(pres, temp, hum, tempUnit, presUnit);
|
||||
SensorTemperature=temp;
|
||||
SensorHumidity=hum;
|
||||
SensorPressure=pres;
|
||||
}
|
||||
34
usermods/QuinLED_Dig_Uno_Temp_MQTT/readme.md
Normal file
34
usermods/QuinLED_Dig_Uno_Temp_MQTT/readme.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# 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.
|
||||
|
||||
Installation of file: Copy and replace file in wled00 directory
|
||||
|
||||
## 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
|
||||
...
|
||||
```
|
||||
54
usermods/QuinLED_Dig_Uno_Temp_MQTT/usermod.cpp
Normal file
54
usermods/QuinLED_Dig_Uno_Temp_MQTT/usermod.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#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
|
||||
sensor.begin();
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void userLoop()
|
||||
{
|
||||
temptimer = millis();
|
||||
|
||||
// Timer to publishe new temperature every 60 seconds
|
||||
if (temptimer - lastMeasure > 60000) {
|
||||
lastMeasure = temptimer;
|
||||
|
||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr){
|
||||
sensor.requestTemperatures();
|
||||
|
||||
//Gets prefered temperature scale based on selection in definitions section
|
||||
#ifdef Celsius
|
||||
float board_temperature = sensor.getTempCByIndex(0);
|
||||
#else
|
||||
float board_temperature = sensors.getTempFByIndex(0);
|
||||
#endif
|
||||
|
||||
//Create character string populated with user defined device topic from the UI, and the read temperature. Then publish to MQTT server.
|
||||
char subuf[38];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/temperature");
|
||||
mqtt->publish(subuf, 0, true, String(board_temperature).c_str());
|
||||
return;}
|
||||
return;}
|
||||
return;
|
||||
}
|
||||
71
usermods/Wemos_D1_mini+Wemos32_mini_shield/readme.md
Normal file
71
usermods/Wemos_D1_mini+Wemos32_mini_shield/readme.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Wemos D1 mini and Wemos32 mini shield
|
||||
- Installation of file: Copy and replace file in wled00 directory
|
||||
- For BME280 sensor use usermod_bme280.cpp. Copy to wled00 and rename to usermod.cpp
|
||||
- Added third choice of controller Heltec WiFi-Kit-8. Totally DIY but with OLED display.
|
||||
## Project repository
|
||||
- [Original repository](https://github.com/srg74/WLED-wemos-shield) - WLED Wemos shield repository
|
||||
- [Wemos shield project Wiki](https://github.com/srg74/WLED-wemos-shield/wiki)
|
||||
- [Precompiled WLED firmware](https://github.com/srg74/WLED-wemos-shield/tree/master/resources/Firmware)
|
||||
## Features
|
||||
- SSD1306 128x32 or 128x64 I2C OLED display
|
||||
- On screen IP address, SSID and controller status (e.g. ON or OFF, recent effect)
|
||||
- Auto display shutoff for saving display lifetime
|
||||
- Dallas temperature sensor
|
||||
- Reporting temperature to MQTT broker
|
||||
- Relay for energy saving
|
||||
|
||||
## Hardware
|
||||

|
||||
|
||||
## Functionality checked with
|
||||
|
||||
- Wemos D1 mini original v3.1 and clones
|
||||
- Wemos32 mini
|
||||
- PlatformIO
|
||||
- SSD1306 128x32 I2C OLED display
|
||||
- DS18B20 (temperature sensor)
|
||||
- BME280 (temperature, humidity and pressure sensor)
|
||||
- Push button (N.O. momentary switch)
|
||||
|
||||
### Platformio requirements
|
||||
|
||||
For Dallas sensor uncomment `U8g2@~2.27.3`,`DallasTemperature@~3.8.0`,`OneWire@~2.3.5 under` `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
; default_envs = esp07
|
||||
default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For Dallas sensor uncomment following 2 lines
|
||||
DallasTemperature@~3.8.0
|
||||
OneWire@~2.3.5
|
||||
...
|
||||
```
|
||||
|
||||
For BME280 sensor uncomment `U8g2@~2.27.3`,`BME280@~3.0.0 under` `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[platformio]
|
||||
...
|
||||
; default_envs = esp07
|
||||
default_envs = d1_mini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
#For use SSD1306 OLED display uncomment following
|
||||
U8g2@~2.27.3
|
||||
#For BME280 sensor uncomment following
|
||||
BME280@~3.0.0
|
||||
...
|
||||
```
|
||||
246
usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod.cpp
Normal file
246
usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
#include <OneWire.h> // Dallas temperature sensor
|
||||
|
||||
//Dallas sensor quick reading. Credit to - Author: Peter Scargill, August 17th, 2013
|
||||
int16_t Dallas(int x, byte start)
|
||||
{
|
||||
OneWire DallasSensor(x);
|
||||
byte i;
|
||||
byte data[2];
|
||||
int16_t result;
|
||||
do
|
||||
{
|
||||
DallasSensor.reset();
|
||||
DallasSensor.write(0xCC);
|
||||
DallasSensor.write(0xBE);
|
||||
for ( i = 0; i < 2; i++) data[i] = DallasSensor.read();
|
||||
result=(data[1]<<8)|data[0];
|
||||
result>>=4; if (data[1]&128) result|=61440;
|
||||
if (data[0]&8) ++result;
|
||||
DallasSensor.reset();
|
||||
DallasSensor.write(0xCC);
|
||||
DallasSensor.write(0x44,1);
|
||||
if (start) delay(1000);
|
||||
} while (start--);
|
||||
return result;
|
||||
}
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
uint8_t SCL_PIN = 22;
|
||||
uint8_t SDA_PIN = 21;
|
||||
uint8_t DALLAS_PIN =23;
|
||||
#else
|
||||
uint8_t SCL_PIN = 5;
|
||||
uint8_t SDA_PIN = 4;
|
||||
uint8_t DALLAS_PIN =13;
|
||||
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
|
||||
#define U8X8_PIN_SCL SCL_PIN
|
||||
#define U8X8_PIN_SDA SDA_PIN
|
||||
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
|
||||
|
||||
// Dallas sensor reading timer
|
||||
long temptimer = millis();
|
||||
long lastMeasure = 0;
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
|
||||
// If display does not work or looks corrupted check the
|
||||
// constructor reference:
|
||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||
// or check the gallery:
|
||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
|
||||
// gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup() {
|
||||
//Serial.begin(115200);
|
||||
|
||||
Dallas (DALLAS_PIN,1);
|
||||
u8x8.begin();
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setFlipMode(1);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
//----> Dallas temperature sensor MQTT publishing
|
||||
temptimer = millis();
|
||||
// Timer to publishe new temperature every 60 seconds
|
||||
if (temptimer - lastMeasure > 60000)
|
||||
{
|
||||
lastMeasure = temptimer;
|
||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
// Serial.println(Dallas(DALLAS_PIN,0));
|
||||
//Gets prefered temperature scale based on selection in definitions section
|
||||
#ifdef Celsius
|
||||
int16_t board_temperature = Dallas(DALLAS_PIN,0);
|
||||
#else
|
||||
int16_t board_temperature = (Dallas(DALLAS_PIN,0)* 1.8 + 32);
|
||||
#endif
|
||||
//Create character string populated with user defined device topic from the UI, and the read temperature. Then publish to MQTT server.
|
||||
String t = String(mqttDeviceTopic);
|
||||
t += "/temperature";
|
||||
mqtt->publish(t.c_str(), 0, true, String(board_temperature).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 3 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
|
||||
u8x8.setPowerSave(1);
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
u8x8.setPowerSave(0);
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
knownSsid = WiFi.SSID();
|
||||
#else
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
u8x8.clear();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
u8x8.print(apPass);
|
||||
else
|
||||
u8x8.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
u8x8.setCursor(2, 2);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
u8x8.setCursor(2, 3);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
|
||||
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
|
||||
u8x8.drawGlyph(0, 0, 80); // wifi icon
|
||||
u8x8.drawGlyph(0, 1, 68); // home icon
|
||||
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
|
||||
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
|
||||
}
|
||||
268
usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod_bme280.cpp
Normal file
268
usermods/Wemos_D1_mini+Wemos32_mini_shield/usermod_bme280.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
#include <Wire.h>
|
||||
#include <BME280I2C.h> //BME280 sensor
|
||||
|
||||
void UpdateBME280Data();
|
||||
|
||||
#define Celsius // Show temperature mesaurement in Celcius otherwise is in Fahrenheit
|
||||
BME280I2C bme; // Default : forced mode, standby time = 1000 ms
|
||||
// Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off,
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32 //ESP32 boards
|
||||
uint8_t SCL_PIN = 22;
|
||||
uint8_t SDA_PIN = 21;
|
||||
#else //ESP8266 boards
|
||||
uint8_t SCL_PIN = 5;
|
||||
uint8_t SDA_PIN = 4;
|
||||
// uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||
#endif
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//ESP8266 Wemos D1 mini board use SCL=5 SDA=4 while ESP32 Wemos32 mini board use SCL=22 SDA=21
|
||||
#define U8X8_PIN_SCL SCL_PIN
|
||||
#define U8X8_PIN_SDA SDA_PIN
|
||||
//#define U8X8_PIN_RESET RST_PIN // Uncoment for Heltec WiFi-Kit-8
|
||||
|
||||
// If display does not work or looks corrupted check the
|
||||
// constructor reference:
|
||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||
// or check the gallery:
|
||||
// https://github.com/olikraus/u8g2/wiki/gallery
|
||||
// --> First choise of cheap I2C OLED 128X32 0.91"
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Second choise of cheap I2C OLED 128X64 0.96" or 1.3"
|
||||
//U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL, U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
// --> Third choise of Heltec WiFi-Kit-8 OLED 128X32 0.91"
|
||||
//U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_RESET, U8X8_PIN_SCL, U8X8_PIN_SDA); // Constructor for Heltec WiFi-Kit-8
|
||||
// gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
|
||||
// BME280 sensor timer
|
||||
long tempTimer = millis();
|
||||
long lastMeasure = 0;
|
||||
|
||||
float SensorPressure(NAN);
|
||||
float SensorTemperature(NAN);
|
||||
float SensorHumidity(NAN);
|
||||
|
||||
void userSetup() {
|
||||
u8x8.begin();
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setFlipMode(1);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
Wire.begin(SDA_PIN,SCL_PIN);
|
||||
|
||||
while(!bme.begin())
|
||||
{
|
||||
Serial.println("Could not find BME280I2C sensor!");
|
||||
delay(1000);
|
||||
}
|
||||
switch(bme.chipModel())
|
||||
{
|
||||
case BME280::ChipModel_BME280:
|
||||
Serial.println("Found BME280 sensor! Success.");
|
||||
break;
|
||||
case BME280::ChipModel_BMP280:
|
||||
Serial.println("Found BMP280 sensor! No Humidity available.");
|
||||
break;
|
||||
default:
|
||||
Serial.println("Found UNKNOWN sensor! Error!");
|
||||
}
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
// BME280 sensor MQTT publishing
|
||||
tempTimer = millis();
|
||||
// Timer to publish new sensor data every 60 seconds
|
||||
if (tempTimer - lastMeasure > 60000)
|
||||
{
|
||||
lastMeasure = tempTimer;
|
||||
|
||||
// Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr)
|
||||
{
|
||||
UpdateBME280Data();
|
||||
float board_temperature = SensorTemperature;
|
||||
float board_pressure = SensorPressure;
|
||||
float board_humidity = SensorHumidity;
|
||||
|
||||
// Create string populated with user defined device topic from the UI, and the read temperature, humidity and pressure. Then publish to MQTT server.
|
||||
String t = String(mqttDeviceTopic);
|
||||
t += "/temperature";
|
||||
mqtt->publish(t.c_str(), 0, true, String(board_temperature).c_str());
|
||||
String p = String(mqttDeviceTopic);
|
||||
p += "/pressure";
|
||||
mqtt->publish(p.c_str(), 0, true, String(board_pressure).c_str());
|
||||
String h = String(mqttDeviceTopic);
|
||||
h += "/humidity";
|
||||
mqtt->publish(h.c_str(), 0, true, String(board_humidity).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we time interval for redrawing passes.
|
||||
if (millis() - lastUpdate < USER_LOOP_REFRESH_RATE_MS) {
|
||||
return;
|
||||
}
|
||||
lastUpdate = millis();
|
||||
|
||||
// Turn off display after 3 minutes with no change.
|
||||
if(!displayTurnedOff && millis() - lastRedraw > 3*60*1000) {
|
||||
u8x8.setPowerSave(1);
|
||||
displayTurnedOff = true;
|
||||
}
|
||||
|
||||
// Check if values which are shown on display changed from the last time.
|
||||
if (((apActive) ? String(apSSID) : WiFi.SSID()) != knownSsid) {
|
||||
needRedraw = true;
|
||||
} else if (knownIp != (apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP())) {
|
||||
needRedraw = true;
|
||||
} else if (knownBrightness != bri) {
|
||||
needRedraw = true;
|
||||
} else if (knownMode != strip.getMode()) {
|
||||
needRedraw = true;
|
||||
} else if (knownPalette != strip.getSegment(0).palette) {
|
||||
needRedraw = true;
|
||||
}
|
||||
|
||||
if (!needRedraw) {
|
||||
return;
|
||||
}
|
||||
needRedraw = false;
|
||||
|
||||
if (displayTurnedOff)
|
||||
{
|
||||
u8x8.setPowerSave(0);
|
||||
displayTurnedOff = false;
|
||||
}
|
||||
lastRedraw = millis();
|
||||
|
||||
// Update last known values.
|
||||
#if defined(ESP8266)
|
||||
knownSsid = apActive ? WiFi.softAPSSID() : WiFi.SSID();
|
||||
#else
|
||||
knownSsid = WiFi.SSID();
|
||||
#endif
|
||||
knownIp = apActive ? IPAddress(4, 3, 2, 1) : WiFi.localIP();
|
||||
knownBrightness = bri;
|
||||
knownMode = strip.getMode();
|
||||
knownPalette = strip.getSegment(0).palette;
|
||||
u8x8.clear();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
|
||||
// First row with Wifi name
|
||||
u8x8.setCursor(1, 0);
|
||||
u8x8.print(knownSsid.substring(0, u8x8.getCols() > 1 ? u8x8.getCols() - 2 : 0));
|
||||
// Print `~` char to indicate that SSID is longer, than owr dicplay
|
||||
if (knownSsid.length() > u8x8.getCols())
|
||||
u8x8.print("~");
|
||||
|
||||
// Second row with IP or Psssword
|
||||
u8x8.setCursor(1, 1);
|
||||
// Print password in AP mode and if led is OFF.
|
||||
if (apActive && bri == 0)
|
||||
u8x8.print(apPass);
|
||||
else
|
||||
u8x8.print(knownIp);
|
||||
|
||||
// Third row with mode name
|
||||
u8x8.setCursor(2, 2);
|
||||
uint8_t qComma = 0;
|
||||
bool insideQuotes = false;
|
||||
uint8_t printedChars = 0;
|
||||
char singleJsonSymbol;
|
||||
|
||||
// Find the mode name in JSON
|
||||
for (size_t i = 0; i < strlen_P(JSON_mode_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_mode_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownMode))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
// Fourth row with palette name
|
||||
u8x8.setCursor(2, 3);
|
||||
qComma = 0;
|
||||
insideQuotes = false;
|
||||
printedChars = 0;
|
||||
// Looking for palette name in JSON.
|
||||
for (size_t i = 0; i < strlen_P(JSON_palette_names); i++) {
|
||||
singleJsonSymbol = pgm_read_byte_near(JSON_palette_names + i);
|
||||
switch (singleJsonSymbol) {
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
break;
|
||||
case '[':
|
||||
case ']':
|
||||
break;
|
||||
case ',':
|
||||
qComma++;
|
||||
default:
|
||||
if (!insideQuotes || (qComma != knownPalette))
|
||||
break;
|
||||
u8x8.print(singleJsonSymbol);
|
||||
printedChars++;
|
||||
}
|
||||
if ((qComma > knownMode) || (printedChars > u8x8.getCols() - 2))
|
||||
break;
|
||||
}
|
||||
|
||||
u8x8.setFont(u8x8_font_open_iconic_embedded_1x1);
|
||||
u8x8.drawGlyph(0, 0, 80); // wifi icon
|
||||
u8x8.drawGlyph(0, 1, 68); // home icon
|
||||
u8x8.setFont(u8x8_font_open_iconic_weather_2x2);
|
||||
u8x8.drawGlyph(0, 2, 66 + (bri > 0 ? 3 : 0)); // sun/moon icon
|
||||
}
|
||||
|
||||
void UpdateBME280Data() {
|
||||
float temp(NAN), hum(NAN), pres(NAN);
|
||||
#ifdef Celsius
|
||||
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
|
||||
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
|
||||
bme.read(pres, temp, hum, tempUnit, presUnit);
|
||||
#else
|
||||
BME280::TempUnit tempUnit(BME280::TempUnit_Fahrenheit);
|
||||
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
|
||||
bme.read(pres, temp, hum, tempUnit, presUnit);
|
||||
#endif
|
||||
SensorTemperature=temp;
|
||||
SensorHumidity=hum;
|
||||
SensorPressure=pres;
|
||||
}
|
||||
12
usermods/battery_keypad_controller/README.md
Normal file
12
usermods/battery_keypad_controller/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Battery powered controller with keypad
|
||||
|
||||
I'm using this controller for a festival totem. Runs on 3 18650 Cells, can deliver >5A current.
|
||||
|
||||
Via keypad one can select 8 presets, change effect, effect speed, effect intensity and palette. Brightness can be
|
||||
adjusted with a potentiometer.
|
||||
|
||||
## Pictures
|
||||
|
||||

|
||||

|
||||

|
||||
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-1.jpg
Normal file
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 319 KiB |
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-2.jpg
Normal file
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 250 KiB |
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-3.jpg
Normal file
BIN
usermods/battery_keypad_controller/assets/bat-key-ctrl-3.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 344 KiB |
151
usermods/battery_keypad_controller/wled06_usermod.ino
Normal file
151
usermods/battery_keypad_controller/wled06_usermod.ino
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* WLED usermod for keypad and brightness-pot.
|
||||
* 3'2020 https://github.com/hobbyquaker
|
||||
*/
|
||||
|
||||
#include <Keypad.h>
|
||||
const byte keypad_rows = 4;
|
||||
const byte keypad_cols = 4;
|
||||
char keypad_keys[keypad_rows][keypad_cols] = {
|
||||
{'1', '2', '3', 'A'},
|
||||
{'4', '5', '6', 'B'},
|
||||
{'7', '8', '9', 'C'},
|
||||
{'*', '0', '#', 'D'}
|
||||
};
|
||||
|
||||
byte keypad_colPins[keypad_rows] = {D3, D2, D1, D0};
|
||||
byte keypad_rowPins[keypad_cols] = {D7, D6, D5, D4};
|
||||
|
||||
Keypad myKeypad = Keypad(makeKeymap(keypad_keys), keypad_rowPins, keypad_colPins, keypad_rows, keypad_cols);
|
||||
|
||||
void userSetup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void userConnected()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
long lastTime = 0;
|
||||
int delayMs = 20; //we want to do something every 2 seconds
|
||||
|
||||
void userLoop()
|
||||
{
|
||||
if (millis()-lastTime > delayMs)
|
||||
{
|
||||
|
||||
long analog = analogRead(0);
|
||||
int new_bri = 1;
|
||||
if (analog > 900) {
|
||||
new_bri = 255;
|
||||
} else if (analog > 30) {
|
||||
new_bri = dim8_video(map(analog, 31, 900, 16, 255));
|
||||
}
|
||||
if (bri != new_bri) {
|
||||
bri = new_bri;
|
||||
colorUpdated(1);
|
||||
|
||||
}
|
||||
|
||||
char myKey = myKeypad.getKey();
|
||||
if (myKey != NULL) {
|
||||
switch (myKey) {
|
||||
case '1':
|
||||
applyPreset(1);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '2':
|
||||
applyPreset(2);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '3':
|
||||
applyPreset(3);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '4':
|
||||
applyPreset(4);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '5':
|
||||
applyPreset(5);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '6':
|
||||
applyPreset(6);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case 'A':
|
||||
applyPreset(7);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case 'B':
|
||||
applyPreset(8);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case '7':
|
||||
effectCurrent += 1;
|
||||
if (effectCurrent >= MODE_COUNT) effectCurrent = 0;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '*':
|
||||
effectCurrent -= 1;
|
||||
if (effectCurrent < 0) effectCurrent = (MODE_COUNT-1);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case '8':
|
||||
if (effectSpeed < 240) {
|
||||
effectSpeed += 12;
|
||||
} else if (effectSpeed < 255) {
|
||||
effectSpeed += 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '0':
|
||||
if (effectSpeed > 15) {
|
||||
effectSpeed -= 12;
|
||||
} else if (effectSpeed > 0) {
|
||||
effectSpeed -= 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case '9':
|
||||
if (effectIntensity < 240) {
|
||||
effectIntensity += 12;
|
||||
} else if (effectIntensity < 255) {
|
||||
effectIntensity += 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case '#':
|
||||
if (effectIntensity > 15) {
|
||||
effectIntensity -= 12;
|
||||
} else if (effectIntensity > 0) {
|
||||
effectIntensity -= 1;
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
effectPalette += 1;
|
||||
if (effectPalette >= 50) effectPalette = 0;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
case 'D':
|
||||
effectPalette -= 1;
|
||||
if (effectPalette <= 0) effectPalette = 50;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
lastTime = millis();
|
||||
}
|
||||
|
||||
}
|
||||
28
usermods/blynk_relay_control/README.md
Normal file
28
usermods/blynk_relay_control/README.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Blynk controllable relay
|
||||
This usermod allows controlling a relay state from the user variables. It also allows the user variables to be set over Blynk.
|
||||
|
||||
Optionally, the servo can have a reset timer to go back to it's default state after an interval. This interval is set through userVar1.
|
||||
|
||||
## Instalation
|
||||
|
||||
Replace the WLED06_usermod.ino file in Aircoookies WLED folder with the one here.
|
||||
|
||||
## Customizations
|
||||
|
||||
Update the following parameters in WLED06_usermod.ino to configure the mod's behavior:
|
||||
|
||||
```cpp
|
||||
//Which pin is the relay connected to
|
||||
#define RELAY_PIN 5
|
||||
//Which pin state should the relay default to
|
||||
#define RELAY_PIN_DEFAULT LOW
|
||||
//If >0 The controller returns to RELAY_PIN_DEFAULT after this time in milliseconds
|
||||
#define RELAY_PIN_TIMER_DEFAULT 3000
|
||||
|
||||
//Blynk virtual pin for controlling relay
|
||||
#define BLYNK_USER_VAR0_PIN V9
|
||||
//Blynk virtual pin for controlling relay timer
|
||||
#define BLYNK_USER_VAR1_PIN V10
|
||||
//Number of milliseconds between updating blynk
|
||||
#define BLYNK_RELAY_UPDATE_INTERVAL 5000
|
||||
```
|
||||
96
usermods/blynk_relay_control/wled06_usermod.ino
Normal file
96
usermods/blynk_relay_control/wled06_usermod.ino
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled_eeprom.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
*/
|
||||
|
||||
//Use userVar0 (API calls &U0=, uint16_t) to set relay state
|
||||
#define relayPinState userVar0
|
||||
//Use userVar1 (API calls &U1=, uint16_t) to set relay timer duration
|
||||
//Ignored if 0, otherwise number of milliseconds to allow relay to stay in
|
||||
//non default state.
|
||||
#define relayTimerInterval userVar1
|
||||
|
||||
//Which pin is the relay connected to
|
||||
#define RELAY_PIN 5
|
||||
//Which pin state should the relay default to
|
||||
#define RELAY_PIN_DEFAULT LOW
|
||||
//If >0 The controller returns to RELAY_PIN_DEFAULT after this time in milliseconds
|
||||
#define RELAY_PIN_TIMER_DEFAULT 3000
|
||||
|
||||
//Blynk virtual pin for controlling relay
|
||||
#define BLYNK_USER_VAR0_PIN V9
|
||||
//Blynk virtual pin for controlling relay timer
|
||||
#define BLYNK_USER_VAR1_PIN V10
|
||||
//Number of milliseconds between updating blynk
|
||||
#define BLYNK_RELAY_UPDATE_INTERVAL 5000
|
||||
|
||||
//Is the timer for resetting the relay active
|
||||
bool relayTimerStarted = false;
|
||||
//millis() time after which relay will be reset
|
||||
unsigned long relayTimeToDefault = 0;
|
||||
//millis() time after which relay vars in Blynk will be sent
|
||||
unsigned long relayBlynkUpdateTime = 0;
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup()
|
||||
{
|
||||
relayPinState = RELAY_PIN_DEFAULT;
|
||||
relayTimerInterval = RELAY_PIN_TIMER_DEFAULT;
|
||||
pinMode(RELAY_PIN, OUTPUT);
|
||||
digitalWrite(RELAY_PIN, relayPinState);
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected()
|
||||
{
|
||||
}
|
||||
|
||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
||||
void userLoop()
|
||||
{
|
||||
//Normalize relayPinState to an accepted value
|
||||
if (relayPinState != HIGH && relayPinState != LOW) {
|
||||
relayPinState = RELAY_PIN_DEFAULT;
|
||||
}
|
||||
//If relay changes and relayTimerInterval is set, start a timer to change back
|
||||
if (relayTimerInterval != 0 &&
|
||||
relayPinState != RELAY_PIN_DEFAULT &&
|
||||
!relayTimerStarted ) {
|
||||
relayTimerStarted = true;
|
||||
relayTimeToDefault = millis() + relayTimerInterval;
|
||||
}
|
||||
//If manually changed back to default, cancel timer
|
||||
if (relayTimerStarted && relayPinState == RELAY_PIN_DEFAULT ) {
|
||||
relayTimerStarted = false;
|
||||
}
|
||||
//If timer completes, set relay back to default
|
||||
if (relayTimerStarted && millis() > relayTimeToDefault) {
|
||||
relayPinState = RELAY_PIN_DEFAULT;
|
||||
relayTimerStarted = false;
|
||||
}
|
||||
digitalWrite(RELAY_PIN, relayPinState);
|
||||
updateRelayBlynk();
|
||||
}
|
||||
|
||||
//Update Blynk with state of userVars at BLYNK_RELAY_UPDATE_INTERVAL
|
||||
void updateRelayBlynk()
|
||||
{
|
||||
if (!WLED_CONNECTED) return;
|
||||
if (relayBlynkUpdateTime > millis()) return;
|
||||
Blynk.virtualWrite(BLYNK_USER_VAR0_PIN, userVar0);
|
||||
Blynk.virtualWrite(BLYNK_USER_VAR1_PIN, userVar1);
|
||||
relayBlynkUpdateTime = millis() + BLYNK_RELAY_UPDATE_INTERVAL;
|
||||
}
|
||||
|
||||
//Add Blynk callback for setting userVar0
|
||||
BLYNK_WRITE(BLYNK_USER_VAR0_PIN)
|
||||
{
|
||||
userVar0 = param.asInt();
|
||||
}
|
||||
//Add Blynk callback for setting userVar1
|
||||
BLYNK_WRITE(BLYNK_USER_VAR1_PIN)
|
||||
{
|
||||
userVar1 = param.asInt();
|
||||
}
|
||||
23
usermods/project_cars_shiftlight/readme.md
Normal file
23
usermods/project_cars_shiftlight/readme.md
Normal file
@@ -0,0 +1,23 @@
|
||||
### Shift Light for Project Cars
|
||||
|
||||
Turn your WLED lights into a rev light and shift indicator for Project Cars.
|
||||
|
||||
It is pretty straight forward to use.
|
||||
|
||||
1. Make sure, your WLED device and your PC/console are on the same network and can talk to each other
|
||||
|
||||
2. Go to the gameplay settings menu in PCARS and enable UDP. There are 9 numbers you can choose from. This is the refresh rate. The lower the number, the better. But you might run into problems at faster rates.
|
||||
|
||||
| Number | Updates/Second |
|
||||
| ------ | -------------- |
|
||||
| 1 | 60 |
|
||||
| 2 | 50 |
|
||||
| 3 | 40 |
|
||||
| 4 | 30 |
|
||||
| 5 | 20 |
|
||||
| 6 | 15 |
|
||||
| 7 | 10 |
|
||||
| 8 | 05 |
|
||||
| 9 | 1 |
|
||||
|
||||
3. once you enter a race, WLED should automatically shift to PCARS mode. Done.
|
||||
96
usermods/project_cars_shiftlight/wled06_usermod.ino
Normal file
96
usermods/project_cars_shiftlight/wled06_usermod.ino
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Car rev display and shift indicator for Project Cars
|
||||
*
|
||||
* This works via the UDP telemetry function. You'll need to enable it in the settings of the game.
|
||||
* I've had good results with settings around 5 (20 fps).
|
||||
*
|
||||
*/
|
||||
const uint8_t PCARS_dimcolor = 20;
|
||||
WiFiUDP UDP;
|
||||
const unsigned int PCARS_localUdpPort = 5606; // local port to listen on
|
||||
char PCARS_packet[2048];
|
||||
|
||||
char PCARS_tempChar[2]; // Temporary array for u16 conversion
|
||||
|
||||
u16 PCARS_RPM;
|
||||
u16 PCARS_maxRPM;
|
||||
|
||||
long PCARS_lastRead = millis() - 2001;
|
||||
float PCARS_rpmRatio;
|
||||
|
||||
|
||||
void userSetup()
|
||||
{
|
||||
UDP.begin(PCARS_localUdpPort);
|
||||
}
|
||||
|
||||
void userConnected()
|
||||
{
|
||||
// new wifi, who dis?
|
||||
}
|
||||
|
||||
void userLoop()
|
||||
{
|
||||
PCARS_readValues();
|
||||
if (PCARS_lastRead > millis() - 2000) {
|
||||
PCARS_buildcolorbars();
|
||||
}
|
||||
}
|
||||
|
||||
void PCARS_readValues() {
|
||||
|
||||
int PCARS_packetSize = UDP.parsePacket();
|
||||
if (PCARS_packetSize) {
|
||||
int len = UDP.read(PCARS_packet, PCARS_packetSize);
|
||||
if (len > 0) {
|
||||
PCARS_packet[len] = 0;
|
||||
}
|
||||
if (len == 1367) { // Telemetry packet. Ignoring everything else.
|
||||
PCARS_lastRead = millis();
|
||||
|
||||
arlsLock(realtimeTimeoutMs, REALTIME_MODE_GENERIC);
|
||||
// current RPM
|
||||
memcpy(&PCARS_tempChar, &PCARS_packet[124], 2);
|
||||
PCARS_RPM = (PCARS_tempChar[1] << 8) + PCARS_tempChar[0];
|
||||
|
||||
// max RPM
|
||||
memcpy(&PCARS_tempChar, &PCARS_packet[126], 2);
|
||||
PCARS_maxRPM = (PCARS_tempChar[1] << 8) + PCARS_tempChar[0];
|
||||
|
||||
if (PCARS_maxRPM) {
|
||||
PCARS_rpmRatio = constrain((float)PCARS_RPM / (float)PCARS_maxRPM, 0, 1);
|
||||
} else {
|
||||
PCARS_rpmRatio = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void PCARS_buildcolorbars() {
|
||||
boolean activated = false;
|
||||
float ledratio = 0;
|
||||
|
||||
for (uint16_t i = 0; i < ledCount; i++) {
|
||||
if (PCARS_rpmRatio < .95 || (millis() % 100 > 70 )) {
|
||||
|
||||
ledratio = (float)i / (float)ledCount;
|
||||
if (ledratio < PCARS_rpmRatio) {
|
||||
activated = true;
|
||||
} else {
|
||||
activated = false;
|
||||
}
|
||||
if (ledratio > 0.66) {
|
||||
setRealtimePixel(i, 0, 0, PCARS_dimcolor + ((255 - PCARS_dimcolor)*activated), 0);
|
||||
} else if (ledratio > 0.33) {
|
||||
setRealtimePixel(i, PCARS_dimcolor + ((255 - PCARS_dimcolor)*activated), 0, 0, 0);
|
||||
} else {
|
||||
setRealtimePixel(i, 0, PCARS_dimcolor + ((255 - PCARS_dimcolor)*activated), 0, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
setRealtimePixel(i, 0, 0, 0, 0);
|
||||
|
||||
}
|
||||
}
|
||||
colorUpdated(5);
|
||||
strip.show();
|
||||
}
|
||||
18
usermods/readme.md
Normal file
18
usermods/readme.md
Normal file
@@ -0,0 +1,18 @@
|
||||
### Usermods
|
||||
|
||||
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 `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!
|
||||
|
||||
While I do my best to not break too much, keep in mind that as WLED is being updated, usermods might break.
|
||||
I am not actively maintaining any usermod in this directory, that is your responsibility as the creator of the usermod.
|
||||
|
||||
Thank you for your help :)
|
||||
62
usermods/rotary_encoder_change_brightness/usermod.cpp
Normal file
62
usermods/rotary_encoder_change_brightness/usermod.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
*/
|
||||
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
/*
|
||||
** Rotary Encoder Example
|
||||
** Use the Sparkfun Rotary Encoder to vary brightness of LED
|
||||
**
|
||||
** Sample the encoder at 500Hz using the millis() function
|
||||
*/
|
||||
|
||||
int fadeAmount = 5; // how many points to fade the Neopixel with each step
|
||||
unsigned long currentTime;
|
||||
unsigned long loopTime;
|
||||
const int pinA = D6; // DT from encoder
|
||||
const int pinB = D7; // CLK from encoder
|
||||
|
||||
unsigned char Enc_A;
|
||||
unsigned char Enc_B;
|
||||
unsigned char Enc_A_prev = 0;
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup() {
|
||||
pinMode(pinA, INPUT_PULLUP);
|
||||
pinMode(pinB, INPUT_PULLUP);
|
||||
currentTime = millis();
|
||||
loopTime = currentTime;
|
||||
}
|
||||
|
||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
||||
void userConnected() {
|
||||
}
|
||||
|
||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
||||
void userLoop() {
|
||||
currentTime = millis(); // get the current elapsed time
|
||||
if(currentTime >= (loopTime + 2)) // 2ms since last check of encoder = 500Hz
|
||||
{
|
||||
int Enc_A = digitalRead(pinA); // Read encoder pins
|
||||
int Enc_B = digitalRead(pinB);
|
||||
if((! Enc_A) && (Enc_A_prev)) { // A has gone from high to low
|
||||
if(Enc_B == HIGH) { // B is high so clockwise
|
||||
if(bri + fadeAmount <= 255) bri += fadeAmount; // increase the brightness, dont go over 255
|
||||
|
||||
} else if (Enc_B == LOW) { // B is low so counter-clockwise
|
||||
if(bri - fadeAmount >= 0) bri -= fadeAmount; // decrease the brightness, dont go below 0
|
||||
}
|
||||
}
|
||||
Enc_A_prev = Enc_A; // Store value of A for next time
|
||||
loopTime = currentTime; // Updates loopTime
|
||||
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
colorUpdated(6);
|
||||
}
|
||||
}
|
||||
45
usermods/rotary_encoder_change_effect/wled06_usermod.ino
Normal file
45
usermods/rotary_encoder_change_effect/wled06_usermod.ino
Normal file
@@ -0,0 +1,45 @@
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
long lastTime = 0;
|
||||
int delayMs = 10;
|
||||
const int pinA = D6; //data
|
||||
const int pinB = D7; //clk
|
||||
int oldA = LOW;
|
||||
|
||||
//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);
|
||||
}
|
||||
|
||||
//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() {
|
||||
if (millis()-lastTime > delayMs) {
|
||||
int A = digitalRead(pinA);
|
||||
int B = digitalRead(pinB);
|
||||
|
||||
if (oldA == LOW && A == HIGH) {
|
||||
if (oldB == HIGH) {
|
||||
// bri += 10;
|
||||
// if (bri > 250) bri = 10;
|
||||
effectCurrent += 1;
|
||||
if (effectCurrent >= MODE_COUNT) effectCurrent = 0;
|
||||
}
|
||||
else {
|
||||
// bri -= 10;
|
||||
// if (bri < 10) bri = 250;
|
||||
effectCurrent -= 1;
|
||||
if (effectCurrent < 0) effectCurrent = (MODE_COUNT-1);
|
||||
}
|
||||
oldA = A;
|
||||
|
||||
//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(NOTIFIER_CALL_MODE_FX_CHANGED);
|
||||
lastTime = millis();
|
||||
}
|
||||
}
|
||||
35
usermods/ssd1306_i2c_oled_u8g2/README.md
Normal file
35
usermods/ssd1306_i2c_oled_u8g2/README.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# SSD1306 128x32 OLED via I2C with u8g2
|
||||
This usermod allows to connect 128x32 Oled display to WLED controlled and show
|
||||
the next information:
|
||||
- Current SSID
|
||||
- IP address if obtained
|
||||
* in AP mode and turned off lightning AP password is shown
|
||||
- Current effect
|
||||
- Current palette
|
||||
- On/Off icon (sun/moon)
|
||||
|
||||
## Hardware
|
||||

|
||||
|
||||
## Requirements
|
||||
Functionality checked with:
|
||||
- commit 095429a7df4f9e2b34dd464f7bbfd068df6558eb
|
||||
- Wemos d1 mini
|
||||
- PlatformIO
|
||||
- Generic SSD1306 128x32 I2C OLED display from aliexpress
|
||||
|
||||
### Platformio
|
||||
Add `U8g2@~2.27.2` dependency to `lib_deps_external` under `[common]` section in `platformio.ini`:
|
||||
```ini
|
||||
# platformio.ini
|
||||
...
|
||||
[common]
|
||||
...
|
||||
lib_deps_external =
|
||||
...
|
||||
U8g2@~2.27.2
|
||||
...
|
||||
```
|
||||
|
||||
### Arduino IDE
|
||||
Install library `U8g2 by oliver` in `Tools | Include Library | Manage libraries` menu.
|
||||
BIN
usermods/ssd1306_i2c_oled_u8g2/assets/hw_connection.png
Normal file
BIN
usermods/ssd1306_i2c_oled_u8g2/assets/hw_connection.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
175
usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino
Normal file
175
usermods/ssd1306_i2c_oled_u8g2/wled06_usermod.ino
Normal file
@@ -0,0 +1,175 @@
|
||||
#include <U8x8lib.h> // from https://github.com/olikraus/u8g2/
|
||||
|
||||
//The SCL and SDA pins are defined here.
|
||||
//Lolin32 boards use SCL=5 SDA=4
|
||||
#define U8X8_PIN_SCL 5
|
||||
#define U8X8_PIN_SDA 4
|
||||
|
||||
|
||||
// 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
|
||||
U8X8_SSD1306_128X32_UNIVISION_HW_I2C u8x8(U8X8_PIN_NONE, U8X8_PIN_SCL,
|
||||
U8X8_PIN_SDA); // Pins are Reset, SCL, SDA
|
||||
|
||||
// gets called once at boot. Do all initialization that doesn't depend on
|
||||
// network here
|
||||
void userSetup() {
|
||||
u8x8.begin();
|
||||
u8x8.setPowerSave(0);
|
||||
u8x8.setContrast(10); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.drawString(0, 0, "Loading...");
|
||||
}
|
||||
|
||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||
// interfaces here
|
||||
void userConnected() {}
|
||||
|
||||
// needRedraw marks if redraw is required to prevent often redrawing.
|
||||
bool needRedraw = true;
|
||||
|
||||
// Next variables hold the previous known values to determine if redraw is
|
||||
// required.
|
||||
String knownSsid = "";
|
||||
IPAddress knownIp;
|
||||
uint8_t knownBrightness = 0;
|
||||
uint8_t knownMode = 0;
|
||||
uint8_t knownPalette = 0;
|
||||
|
||||
long lastUpdate = 0;
|
||||
long lastRedraw = 0;
|
||||
bool displayTurnedOff = false;
|
||||
// How often we are redrawing screen
|
||||
#define USER_LOOP_REFRESH_RATE_MS 5000
|
||||
|
||||
void userLoop() {
|
||||
|
||||
// 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
|
||||
}
|
||||
14
usermods/stairway_wipe_basic/readme.md
Normal file
14
usermods/stairway_wipe_basic/readme.md
Normal file
@@ -0,0 +1,14 @@
|
||||
### Stairway lighting
|
||||
|
||||
Quick usermod to accomplish something similar to [this video](https://www.youtube.com/watch?v=NHkju5ncC4A).
|
||||
|
||||
This usermod allows you to add a lightstrip alongside or on the steps of a staircase.
|
||||
When the `userVar0` variable is set, the LEDs will gradually turn on in a Wipe effect.
|
||||
Both directions are supported by setting userVar0 to 1 and 2, respectively (HTTP API commands `U0=1` and `U0=2`).
|
||||
|
||||
After the Wipe is complete, the light will either stay on (Solid effect) indefinitely or after `userVar1` seconds have elapsed.
|
||||
If userVar0 is updated (e.g. by triggering a second sensor) the light will slowly fade off.
|
||||
This could be extended to also run a Wipe effect in reverse order to turn the LEDs back off.
|
||||
|
||||
This is just a basic version to accomplish this using HTTP API calls `U0` and `U1` and/or macros.
|
||||
It should be easy to adapt this code however to interface with motion sensors or other input devices.
|
||||
111
usermods/stairway_wipe_basic/wled06_usermod.ino
Normal file
111
usermods/stairway_wipe_basic/wled06_usermod.ino
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled_eeprom.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
*/
|
||||
|
||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
||||
|
||||
byte wipeState = 0; //0: inactive 1: wiping 2: solid
|
||||
unsigned long timeStaticStart = 0;
|
||||
uint16_t previousUserVar0 = 0;
|
||||
|
||||
//comment this out if you want the turn off effect to be just fading out instead of reverse wipe
|
||||
#define STAIRCASE_WIPE_OFF
|
||||
|
||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
||||
void userSetup()
|
||||
{
|
||||
//setup PIR sensor here, if needed
|
||||
}
|
||||
|
||||
//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()
|
||||
{
|
||||
//userVar0 (U0 in HTTP API):
|
||||
//has to be set to 1 if movement is detected on the PIR that is the same side of the staircase as the ESP8266
|
||||
//has to be set to 2 if movement is detected on the PIR that is the opposite side
|
||||
//can be set to 0 if no movement is detected. Otherwise LEDs will turn off after a configurable timeout (userVar1 seconds)
|
||||
|
||||
if (userVar0 > 0)
|
||||
{
|
||||
if ((previousUserVar0 == 1 && userVar0 == 2) || (previousUserVar0 == 2 && userVar0 == 1)) wipeState = 3; //turn off if other PIR triggered
|
||||
previousUserVar0 = userVar0;
|
||||
|
||||
if (wipeState == 0) {
|
||||
startWipe();
|
||||
wipeState = 1;
|
||||
} else if (wipeState == 1) { //wiping
|
||||
uint32_t cycleTime = 360 + (255 - effectSpeed)*75; //this is how long one wipe takes (minus 25 ms to make sure we switch in time)
|
||||
if (millis() + strip.timebase > (cycleTime - 25)) { //wipe complete
|
||||
effectCurrent = FX_MODE_STATIC;
|
||||
timeStaticStart = millis();
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
wipeState = 2;
|
||||
}
|
||||
} else if (wipeState == 2) { //static
|
||||
if (userVar1 > 0) //if U1 is not set, the light will stay on until second PIR or external command is triggered
|
||||
{
|
||||
if (millis() - timeStaticStart > userVar1*1000) wipeState = 3;
|
||||
}
|
||||
} else if (wipeState == 3) { //switch to wipe off
|
||||
#ifdef STAIRCASE_WIPE_OFF
|
||||
effectCurrent = FX_MODE_COLOR_WIPE;
|
||||
strip.timebase = 360 + (255 - effectSpeed)*75 - millis(); //make sure wipe starts fully lit
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
wipeState = 4;
|
||||
#else
|
||||
turnOff();
|
||||
#endif
|
||||
} else { //wiping off
|
||||
if (millis() + strip.timebase > (725 + (255 - effectSpeed)*150)) turnOff(); //wipe complete
|
||||
}
|
||||
} else {
|
||||
wipeState = 0; //reset for next time
|
||||
if (previousUserVar0) {
|
||||
#ifdef STAIRCASE_WIPE_OFF
|
||||
userVar0 = previousUserVar0;
|
||||
wipeState = 3;
|
||||
#else
|
||||
turnOff();
|
||||
#endif
|
||||
}
|
||||
previousUserVar0 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void startWipe()
|
||||
{
|
||||
bri = briLast; //turn on
|
||||
transitionDelayTemp = 0; //no transition
|
||||
effectCurrent = FX_MODE_COLOR_WIPE;
|
||||
resetTimebase(); //make sure wipe starts from beginning
|
||||
|
||||
//set wipe direction
|
||||
WS2812FX::Segment& seg = strip.getSegment(0);
|
||||
bool doReverse = (userVar0 == 2);
|
||||
seg.setOption(1, doReverse);
|
||||
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
}
|
||||
|
||||
void turnOff()
|
||||
{
|
||||
#ifdef STAIRCASE_WIPE_OFF
|
||||
transitionDelayTemp = 0; //turn off immediately after wipe completed
|
||||
#else
|
||||
transitionDelayTemp = 4000; //fade out slowly
|
||||
#endif
|
||||
bri = 0;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
wipeState = 0;
|
||||
userVar0 = 0;
|
||||
previousUserVar0 = 0;
|
||||
}
|
||||
2114
wled00/FX.cpp
2114
wled00/FX.cpp
File diff suppressed because it is too large
Load Diff
262
wled00/FX.h
262
wled00/FX.h
@@ -28,6 +28,7 @@
|
||||
#define WS2812FX_h
|
||||
|
||||
#include "NpbWrapper.h"
|
||||
#include "const.h"
|
||||
|
||||
#define FASTLED_INTERNAL //remove annoying pragma messages
|
||||
#include "FastLED.h"
|
||||
@@ -37,22 +38,32 @@
|
||||
#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
|
||||
#define FRAMETIME 1000/WLED_FPS
|
||||
#define FRAMETIME (1000/WLED_FPS)
|
||||
|
||||
/* each segment uses 37 bytes of SRAM memory, so if you're application fails because of
|
||||
/* each segment uses 52 bytes of SRAM memory, so if you're application fails because of
|
||||
insufficient memory, decreasing MAX_NUM_SEGMENTS may help */
|
||||
#define MAX_NUM_SEGMENTS 10
|
||||
|
||||
/* How much data bytes all segments combined may allocate */
|
||||
#ifdef ESP8266
|
||||
#define MAX_SEGMENT_DATA 2048
|
||||
#else
|
||||
#define MAX_SEGMENT_DATA 8192
|
||||
#endif
|
||||
|
||||
#define LED_SKIP_AMOUNT 1
|
||||
#define MIN_SHOW_DELAY 15
|
||||
|
||||
#define NUM_COLORS 3 /* number of colors per segment */
|
||||
#define SEGMENT _segments[_segment_index]
|
||||
#define SEGCOLOR(x) gamma32(_segments[_segment_index].colors[x])
|
||||
#define SEGENV _segment_runtimes[_segment_index]
|
||||
#define SEGLEN SEGMENT.length()
|
||||
#define SEGLEN _virtualSegmentLength
|
||||
#define SEGACT SEGMENT.stop
|
||||
#define SPEED_FORMULA_L 5 + (50*(255 - SEGMENT.speed))/SEGLEN
|
||||
#define RESET_RUNTIME memset(_segment_runtimes, 0, sizeof(_segment_runtimes))
|
||||
@@ -73,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 83
|
||||
#define MODE_COUNT 103
|
||||
|
||||
#define FX_MODE_STATIC 0
|
||||
#define FX_MODE_BLINK 1
|
||||
@@ -134,10 +148,10 @@
|
||||
#define FX_MODE_FIRE_FLICKER 45
|
||||
#define FX_MODE_GRADIENT 46
|
||||
#define FX_MODE_LOADING 47
|
||||
#define FX_MODE_DUAL_COLOR_WIPE_IN_OUT 48
|
||||
#define FX_MODE_DUAL_COLOR_WIPE_IN_IN 49
|
||||
#define FX_MODE_DUAL_COLOR_WIPE_OUT_OUT 50
|
||||
#define FX_MODE_DUAL_COLOR_WIPE_OUT_IN 51
|
||||
#define FX_MODE_POLICE 48
|
||||
#define FX_MODE_POLICE_ALL 49
|
||||
#define FX_MODE_TWO_DOTS 50
|
||||
#define FX_MODE_TWO_AREAS 51
|
||||
#define FX_MODE_CIRCUS_COMBUSTUS 52
|
||||
#define FX_MODE_HALLOWEEN 53
|
||||
#define FX_MODE_TRICOLOR_CHASE 54
|
||||
@@ -149,7 +163,6 @@
|
||||
#define FX_MODE_DUAL_LARSON_SCANNER 60
|
||||
#define FX_MODE_RANDOM_CHASE 61
|
||||
#define FX_MODE_OSCILLATE 62
|
||||
//Modes that use FastLED -->
|
||||
#define FX_MODE_PRIDE_2015 63
|
||||
#define FX_MODE_JUGGLE 64
|
||||
#define FX_MODE_PALETTE 65
|
||||
@@ -170,14 +183,36 @@
|
||||
#define FX_MODE_TWINKLEFOX 80
|
||||
#define FX_MODE_TWINKLECAT 81
|
||||
#define FX_MODE_HALLOWEEN_EYES 82
|
||||
|
||||
#define FX_MODE_STATIC_PATTERN 83
|
||||
#define FX_MODE_TRI_STATIC_PATTERN 84
|
||||
#define FX_MODE_SPOTS 85
|
||||
#define FX_MODE_SPOTS_FADE 86
|
||||
#define FX_MODE_GLITTER 87
|
||||
#define FX_MODE_CANDLE 88
|
||||
#define FX_MODE_STARBURST 89
|
||||
#define FX_MODE_EXPLODING_FIREWORKS 90
|
||||
#define FX_MODE_BOUNCINGBALLS 91
|
||||
#define FX_MODE_SINELON 92
|
||||
#define FX_MODE_SINELON_DUAL 93
|
||||
#define FX_MODE_SINELON_RAINBOW 94
|
||||
#define FX_MODE_POPCORN 95
|
||||
#define FX_MODE_DRIP 96
|
||||
#define FX_MODE_PLASMA 97
|
||||
#define FX_MODE_PERCENT 98
|
||||
#define FX_MODE_RIPPLE_RAINBOW 99
|
||||
#define FX_MODE_HEARTBEAT 100
|
||||
#define FX_MODE_PACIFICA 101
|
||||
#define FX_MODE_CANDLE_MULTI 102
|
||||
|
||||
class WS2812FX {
|
||||
typedef uint16_t (WS2812FX::*mode_ptr)(void);
|
||||
|
||||
// pre show callback
|
||||
typedef void (*show_callback) (void);
|
||||
|
||||
// segment parameters
|
||||
public:
|
||||
typedef struct Segment { // 21 bytes
|
||||
typedef struct Segment { // 24 bytes
|
||||
uint16_t start;
|
||||
uint16_t stop; //segment invalid if stop == 0
|
||||
uint8_t speed;
|
||||
@@ -185,6 +220,8 @@ class WS2812FX {
|
||||
uint8_t palette;
|
||||
uint8_t mode;
|
||||
uint8_t options; //bit pattern: msb first: transitional tbd tbd tbd tbd paused reverse selected
|
||||
uint8_t grouping, spacing;
|
||||
uint8_t opacity;
|
||||
uint32_t colors[NUM_COLORS];
|
||||
void setOption(uint8_t n, bool val)
|
||||
{
|
||||
@@ -211,16 +248,45 @@ class WS2812FX {
|
||||
{
|
||||
return stop - start;
|
||||
}
|
||||
uint16_t groupLength()
|
||||
{
|
||||
return grouping + spacing;
|
||||
}
|
||||
uint16_t virtualLength()
|
||||
{
|
||||
uint16_t groupLen = groupLength();
|
||||
return (length() + groupLen -1) / groupLen;
|
||||
}
|
||||
} segment;
|
||||
|
||||
// segment runtime parameters
|
||||
typedef struct Segment_runtime { // 16 bytes
|
||||
typedef struct Segment_runtime { // 28 bytes
|
||||
unsigned long next_time;
|
||||
uint32_t step;
|
||||
uint32_t call;
|
||||
uint16_t aux0;
|
||||
uint16_t aux1;
|
||||
void reset(){next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;};
|
||||
byte* data = nullptr;
|
||||
bool allocateData(uint16_t len){
|
||||
if (data && _dataLen == len) return true; //already allocated
|
||||
deallocateData();
|
||||
if (WS2812FX::_usedSegmentData + len > MAX_SEGMENT_DATA) return false; //not enough memory
|
||||
data = new (std::nothrow) byte[len];
|
||||
if (!data) return false; //allocation failed
|
||||
WS2812FX::_usedSegmentData += len;
|
||||
_dataLen = len;
|
||||
memset(data, 0, len);
|
||||
return true;
|
||||
}
|
||||
void deallocateData(){
|
||||
delete[] data;
|
||||
data = nullptr;
|
||||
WS2812FX::_usedSegmentData -= _dataLen;
|
||||
_dataLen = 0;
|
||||
}
|
||||
void reset(){next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; deallocateData();}
|
||||
private:
|
||||
uint16_t _dataLen = 0;
|
||||
} segment_runtime;
|
||||
|
||||
WS2812FX() {
|
||||
@@ -271,10 +337,10 @@ class WS2812FX {
|
||||
_mode[FX_MODE_FIRE_FLICKER] = &WS2812FX::mode_fire_flicker;
|
||||
_mode[FX_MODE_GRADIENT] = &WS2812FX::mode_gradient;
|
||||
_mode[FX_MODE_LOADING] = &WS2812FX::mode_loading;
|
||||
_mode[FX_MODE_DUAL_COLOR_WIPE_IN_OUT] = &WS2812FX::mode_dual_color_wipe_in_out;
|
||||
_mode[FX_MODE_DUAL_COLOR_WIPE_IN_IN] = &WS2812FX::mode_dual_color_wipe_in_in;
|
||||
_mode[FX_MODE_DUAL_COLOR_WIPE_OUT_OUT] = &WS2812FX::mode_dual_color_wipe_out_out;
|
||||
_mode[FX_MODE_DUAL_COLOR_WIPE_OUT_IN] = &WS2812FX::mode_dual_color_wipe_out_in;
|
||||
_mode[FX_MODE_POLICE] = &WS2812FX::mode_police;
|
||||
_mode[FX_MODE_POLICE_ALL] = &WS2812FX::mode_police_all;
|
||||
_mode[FX_MODE_TWO_DOTS] = &WS2812FX::mode_two_dots;
|
||||
_mode[FX_MODE_TWO_AREAS] = &WS2812FX::mode_two_areas;
|
||||
_mode[FX_MODE_CIRCUS_COMBUSTUS] = &WS2812FX::mode_circus_combustus;
|
||||
_mode[FX_MODE_HALLOWEEN] = &WS2812FX::mode_halloween;
|
||||
_mode[FX_MODE_TRICOLOR_CHASE] = &WS2812FX::mode_tricolor_chase;
|
||||
@@ -308,6 +374,26 @@ class WS2812FX {
|
||||
_mode[FX_MODE_TWINKLEFOX] = &WS2812FX::mode_twinklefox;
|
||||
_mode[FX_MODE_TWINKLECAT] = &WS2812FX::mode_twinklecat;
|
||||
_mode[FX_MODE_HALLOWEEN_EYES] = &WS2812FX::mode_halloween_eyes;
|
||||
_mode[FX_MODE_STATIC_PATTERN] = &WS2812FX::mode_static_pattern;
|
||||
_mode[FX_MODE_TRI_STATIC_PATTERN] = &WS2812FX::mode_tri_static_pattern;
|
||||
_mode[FX_MODE_SPOTS] = &WS2812FX::mode_spots;
|
||||
_mode[FX_MODE_SPOTS_FADE] = &WS2812FX::mode_spots_fade;
|
||||
_mode[FX_MODE_GLITTER] = &WS2812FX::mode_glitter;
|
||||
_mode[FX_MODE_CANDLE] = &WS2812FX::mode_candle;
|
||||
_mode[FX_MODE_STARBURST] = &WS2812FX::mode_starburst;
|
||||
_mode[FX_MODE_EXPLODING_FIREWORKS] = &WS2812FX::mode_exploding_fireworks;
|
||||
_mode[FX_MODE_BOUNCINGBALLS] = &WS2812FX::mode_bouncing_balls;
|
||||
_mode[FX_MODE_SINELON] = &WS2812FX::mode_sinelon;
|
||||
_mode[FX_MODE_SINELON_DUAL] = &WS2812FX::mode_sinelon_dual;
|
||||
_mode[FX_MODE_SINELON_RAINBOW] = &WS2812FX::mode_sinelon_rainbow;
|
||||
_mode[FX_MODE_POPCORN] = &WS2812FX::mode_popcorn;
|
||||
_mode[FX_MODE_DRIP] = &WS2812FX::mode_drip;
|
||||
_mode[FX_MODE_PLASMA] = &WS2812FX::mode_plasma;
|
||||
_mode[FX_MODE_PERCENT] = &WS2812FX::mode_percent;
|
||||
_mode[FX_MODE_RIPPLE_RAINBOW] = &WS2812FX::mode_ripple_rainbow;
|
||||
_mode[FX_MODE_HEARTBEAT] = &WS2812FX::mode_heartbeat;
|
||||
_mode[FX_MODE_PACIFICA] = &WS2812FX::mode_pacifica;
|
||||
_mode[FX_MODE_CANDLE_MULTI] = &WS2812FX::mode_candle_multi;
|
||||
|
||||
_brightness = DEFAULT_BRIGHTNESS;
|
||||
currentPalette = CRGBPalette16(CRGB::Black);
|
||||
@@ -315,68 +401,60 @@ class WS2812FX {
|
||||
ablMilliampsMax = 850;
|
||||
currentMilliamps = 0;
|
||||
timebase = 0;
|
||||
_locked = nullptr;
|
||||
_modeUsesLock = false;
|
||||
bus = new NeoPixelWrapper();
|
||||
resetSegments();
|
||||
}
|
||||
|
||||
void
|
||||
init(bool supportWhite, uint16_t countPixels, bool skipFirs),
|
||||
init(bool supportWhite, uint16_t countPixels, bool skipFirst),
|
||||
service(void),
|
||||
blur(uint8_t),
|
||||
fade_out(uint8_t r),
|
||||
setMode(uint8_t m),
|
||||
setMode(uint8_t segid, uint8_t m),
|
||||
setSpeed(uint8_t s),
|
||||
setIntensity(uint8_t i),
|
||||
setPalette(uint8_t p),
|
||||
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),
|
||||
setIndividual(uint16_t i, uint32_t col),
|
||||
setRange(uint16_t i, uint16_t i2, uint32_t col),
|
||||
lock(uint16_t i),
|
||||
lockRange(uint16_t i, uint16_t i2),
|
||||
unlock(uint16_t i),
|
||||
unlockRange(uint16_t i, uint16_t i2),
|
||||
unlockAll(void),
|
||||
setShowCallback(show_callback cb),
|
||||
setTransitionMode(bool t),
|
||||
trigger(void),
|
||||
setSegment(uint8_t n, uint16_t start, uint16_t stop),
|
||||
setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t grouping = 0, uint8_t spacing = 0),
|
||||
resetSegments(),
|
||||
setPixelColor(uint16_t n, uint32_t c),
|
||||
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
|
||||
show(void);
|
||||
show(void),
|
||||
setRgbwPwm(void);
|
||||
|
||||
bool
|
||||
reverseMode = false,
|
||||
gammaCorrectBri = false,
|
||||
gammaCorrectCol = true,
|
||||
applyToAllSelected = true,
|
||||
segmentsAreIdentical(Segment* a, Segment* b),
|
||||
setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p);
|
||||
|
||||
uint8_t
|
||||
returnedSegment = 0,
|
||||
mainSegment = 0,
|
||||
rgbwMode = RGBW_MODE_DUAL,
|
||||
paletteFade = 0,
|
||||
paletteBlend = 0,
|
||||
colorOrder = 0,
|
||||
milliampsPerLed = 55,
|
||||
getBrightness(void),
|
||||
getMode(void),
|
||||
getSpeed(void),
|
||||
getModeCount(void),
|
||||
getPaletteCount(void),
|
||||
getMaxSegments(void),
|
||||
getFirstSelectedSegment(void),
|
||||
getReturnedSegmentId(void),
|
||||
//getFirstSelectedSegment(void),
|
||||
getMainSegmentId(void),
|
||||
gamma8(uint8_t),
|
||||
get_random_wheel_index(uint8_t);
|
||||
|
||||
uint16_t
|
||||
ablMilliampsMax,
|
||||
currentMilliamps;
|
||||
currentMilliamps,
|
||||
triwave16(uint16_t);
|
||||
|
||||
uint32_t
|
||||
timebase,
|
||||
@@ -384,6 +462,7 @@ class WS2812FX {
|
||||
color_from_palette(uint16_t, bool, bool, uint8_t, uint8_t pbri = 255),
|
||||
color_blend(uint32_t,uint32_t,uint8_t),
|
||||
gamma32(uint32_t),
|
||||
getLastShow(void),
|
||||
getPixelColor(uint16_t),
|
||||
getColor(void);
|
||||
|
||||
@@ -447,10 +526,10 @@ class WS2812FX {
|
||||
mode_fire_flicker(void),
|
||||
mode_gradient(void),
|
||||
mode_loading(void),
|
||||
mode_dual_color_wipe_in_out(void),
|
||||
mode_dual_color_wipe_in_in(void),
|
||||
mode_dual_color_wipe_out_out(void),
|
||||
mode_dual_color_wipe_out_in(void),
|
||||
mode_police(void),
|
||||
mode_police_all(void),
|
||||
mode_two_dots(void),
|
||||
mode_two_areas(void),
|
||||
mode_circus_combustus(void),
|
||||
mode_bicolor_chase(void),
|
||||
mode_tricolor_chase(void),
|
||||
@@ -481,7 +560,28 @@ class WS2812FX {
|
||||
mode_ripple(void),
|
||||
mode_twinklefox(void),
|
||||
mode_twinklecat(void),
|
||||
mode_halloween_eyes(void);
|
||||
mode_halloween_eyes(void),
|
||||
mode_static_pattern(void),
|
||||
mode_tri_static_pattern(void),
|
||||
mode_spots(void),
|
||||
mode_spots_fade(void),
|
||||
mode_glitter(void),
|
||||
mode_candle(void),
|
||||
mode_starburst(void),
|
||||
mode_exploding_fireworks(void),
|
||||
mode_bouncing_balls(void),
|
||||
mode_sinelon(void),
|
||||
mode_sinelon_dual(void),
|
||||
mode_sinelon_rainbow(void),
|
||||
mode_popcorn(void),
|
||||
mode_drip(void),
|
||||
mode_plasma(void),
|
||||
mode_percent(void),
|
||||
mode_ripple_rainbow(void),
|
||||
mode_heartbeat(void),
|
||||
mode_pacifica(void),
|
||||
mode_candle_multi(void);
|
||||
|
||||
|
||||
private:
|
||||
NeoPixelWrapper *bus;
|
||||
@@ -492,76 +592,92 @@ class WS2812FX {
|
||||
CRGBPalette16 targetPalette;
|
||||
|
||||
uint32_t now;
|
||||
uint16_t _length;
|
||||
uint16_t _length, _lengthRaw, _virtualSegmentLength;
|
||||
uint16_t _rand16seed;
|
||||
uint8_t _brightness;
|
||||
static uint16_t _usedSegmentData;
|
||||
|
||||
void load_gradient_palette(uint8_t);
|
||||
void handle_palette(void);
|
||||
void fill(uint32_t);
|
||||
bool modeUsesLock(uint8_t);
|
||||
void twinklefox_base(bool);
|
||||
|
||||
bool
|
||||
_modeUsesLock,
|
||||
_rgbwMode,
|
||||
_cronixieMode,
|
||||
_cronixieBacklightEnabled,
|
||||
_useRgbw = false,
|
||||
_skipFirstMode,
|
||||
_triggered;
|
||||
|
||||
byte* _locked;
|
||||
byte _cronixieDigits[6];
|
||||
|
||||
mode_ptr _mode[MODE_COUNT]; // SRAM footprint: 4 bytes per element
|
||||
|
||||
show_callback _callback = nullptr;
|
||||
|
||||
// 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),
|
||||
running_base(bool),
|
||||
larson_scanner(bool),
|
||||
sinelon_base(bool,bool),
|
||||
dissolve(uint32_t),
|
||||
chase(uint32_t, uint32_t, uint32_t, bool),
|
||||
gradient_base(bool),
|
||||
ripple_base(bool),
|
||||
police_base(uint32_t, uint32_t, bool),
|
||||
running(uint32_t, uint32_t),
|
||||
tricolor_chase(uint32_t, uint32_t);
|
||||
tricolor_chase(uint32_t, uint32_t),
|
||||
twinklefox_base(bool),
|
||||
spots_base(uint16_t);
|
||||
|
||||
CRGB twinklefox_one_twinkle(uint32_t ms, uint8_t salt, bool cat);
|
||||
CRGB pacifica_one_layer(uint16_t i, CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff);
|
||||
|
||||
uint32_t _lastPaletteChange = 0;
|
||||
uint32_t _lastShow = 0;
|
||||
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
uint32_t _analogLastShow = 0;
|
||||
RgbwColor _analogLastColor = 0;
|
||||
uint8_t _analogLastBri = 0;
|
||||
#endif
|
||||
|
||||
uint8_t _segment_index = 0;
|
||||
uint8_t _segment_index_palette_last = 99;
|
||||
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 21 bytes per element
|
||||
// start, stop, speed, intensity, palette, mode, options, color[]
|
||||
{ 0, 7, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, {DEFAULT_COLOR}}
|
||||
segment _segments[MAX_NUM_SEGMENTS] = { // SRAM footprint: 24 bytes per element
|
||||
// start, stop, speed, intensity, palette, mode, options, grouping, spacing, opacity (unused), color[]
|
||||
{ 0, 7, DEFAULT_SPEED, 128, 0, DEFAULT_MODE, NO_OPTIONS, 1, 0, 255, {DEFAULT_COLOR}}
|
||||
};
|
||||
segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 16 bytes per element
|
||||
segment_runtime _segment_runtimes[MAX_NUM_SEGMENTS]; // SRAM footprint: 28 bytes per element
|
||||
friend class Segment_runtime;
|
||||
|
||||
uint16_t realPixelIndex(uint16_t i);
|
||||
};
|
||||
|
||||
|
||||
//10 names per line
|
||||
const char JSON_mode_names[] PROGMEM = R"=====([
|
||||
"Solid","Blink","Breathe","Wipe","Wipe Random","Random Colors","Sweep","Dynamic","Colorloop","Rainbow",
|
||||
"Scan","Dual Scan","Fade","Chase","Chase Rainbow","Running","Saw","Twinkle","Dissolve","Dissolve Rnd",
|
||||
"Sparkle","Dark Sparkle","Sparkle+","Strobe","Strobe Rainbow","Mega Strobe","Blink Rainbow","Android","Chase","Chase Random",
|
||||
"Scan","Scan Dual","Fade","Theater","Theater Rainbow","Running","Saw","Twinkle","Dissolve","Dissolve Rnd",
|
||||
"Sparkle","Sparkle Dark","Sparkle+","Strobe","Strobe Rainbow","Strobe Mega","Blink Rainbow","Android","Chase","Chase Random",
|
||||
"Chase Rainbow","Chase Flash","Chase Flash Rnd","Rainbow Runner","Colorful","Traffic Light","Sweep Random","Running 2","Red & Blue","Stream",
|
||||
"Scanner","Lighthouse","Fireworks","Rain","Merry Christmas","Fire Flicker","Gradient","Loading","In Out","In In",
|
||||
"Out Out","Out In","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet",
|
||||
"Dual Scanner","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","BPM","Fill Noise",
|
||||
"Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Smooth Meteor","Railway","Ripple",
|
||||
"Twinklefox","Twinklecat","Halloween Eyes"
|
||||
"Scanner","Lighthouse","Fireworks","Rain","Merry Christmas","Fire Flicker","Gradient","Loading","Police","Police All",
|
||||
"Two Dots","Two Areas","Circus","Halloween","Tri Chase","Tri Wipe","Tri Fade","Lightning","ICU","Multi Comet",
|
||||
"Scanner Dual","Stream 2","Oscillate","Pride 2015","Juggle","Palette","Fire 2012","Colorwaves","Bpm","Fill Noise",
|
||||
"Noise 1","Noise 2","Noise 3","Noise 4","Colortwinkles","Lake","Meteor","Meteor Smooth","Railway","Ripple",
|
||||
"Twinklefox","Twinklecat","Halloween Eyes","Solid Pattern","Solid Pattern Tri","Spots","Spots Fade","Glitter","Candle","Fireworks Starburst",
|
||||
"Fireworks 1D","Bouncing Balls","Sinelon","Sinelon Dual","Sinelon Rainbow","Popcorn","Drip","Plasma","Percent","Ripple Rainbow",
|
||||
"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"
|
||||
"Magenta","Magred","Yelmag","Yelblu","Orange & Teal","Tiamat","April Night","Orangery","C9","Sakura",
|
||||
"Aurora","Atlantica"
|
||||
])=====";
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,151 +27,166 @@
|
||||
#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 == _rgbwMode && countPixels == _length && _locked != NULL) return;
|
||||
if (supportWhite == _useRgbw && countPixels == _length && _skipFirstMode == skipFirst) return;
|
||||
RESET_RUNTIME;
|
||||
_rgbwMode = supportWhite;
|
||||
_skipFirstMode = skipFirst;
|
||||
_useRgbw = supportWhite;
|
||||
_length = countPixels;
|
||||
|
||||
_skipFirstMode = skipFirst;
|
||||
|
||||
uint8_t ty = 1;
|
||||
if (supportWhite) ty =2;
|
||||
uint16_t lengthRaw = _length;
|
||||
if (_skipFirstMode) lengthRaw += LED_SKIP_AMOUNT;
|
||||
bus->Begin((NeoPixelType)ty, lengthRaw);
|
||||
|
||||
delete[] _locked;
|
||||
_locked = new byte[_length];
|
||||
if (supportWhite) ty = 2;
|
||||
_lengthRaw = _length;
|
||||
if (_skipFirstMode) {
|
||||
_lengthRaw += LED_SKIP_AMOUNT;
|
||||
}
|
||||
|
||||
bus->Begin((NeoPixelType)ty, _lengthRaw);
|
||||
|
||||
_segments[0].start = 0;
|
||||
_segments[0].stop = _length;
|
||||
|
||||
unlockAll();
|
||||
|
||||
setBrightness(_brightness);
|
||||
}
|
||||
|
||||
void WS2812FX::service() {
|
||||
now = millis() + timebase; // Be aware, millis() rolls over every 49 days
|
||||
if (now - _lastShow < MIN_SHOW_DELAY) return;
|
||||
uint32_t nowUp = millis(); // Be aware, millis() rolls over every 49 days
|
||||
now = nowUp + timebase;
|
||||
if (nowUp - _lastShow < MIN_SHOW_DELAY) return;
|
||||
bool doShow = false;
|
||||
for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
_segment_index = i;
|
||||
if (SEGMENT.isActive())
|
||||
{
|
||||
if(now > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary
|
||||
if(nowUp > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary
|
||||
{
|
||||
if (SEGMENT.grouping == 0) SEGMENT.grouping = 1; //sanity check
|
||||
_virtualSegmentLength = SEGMENT.virtualLength();
|
||||
doShow = true;
|
||||
handle_palette();
|
||||
uint16_t delay = (this->*_mode[SEGMENT.mode])();
|
||||
SEGENV.next_time = now + delay;
|
||||
SEGENV.next_time = nowUp + delay;
|
||||
if (SEGMENT.mode != FX_MODE_HALLOWEEN_EYES) SEGENV.call++;
|
||||
}
|
||||
}
|
||||
}
|
||||
_virtualSegmentLength = 0;
|
||||
if(doShow) {
|
||||
yield();
|
||||
show();
|
||||
_lastShow = millis();
|
||||
}
|
||||
_triggered = false;
|
||||
}
|
||||
|
||||
bool WS2812FX::modeUsesLock(uint8_t m)
|
||||
{
|
||||
if (m == FX_MODE_FIRE_2012 || m == FX_MODE_COLORTWINKLE ||
|
||||
m == FX_MODE_METEOR || m == FX_MODE_METEOR_SMOOTH ||
|
||||
m == FX_MODE_RIPPLE || m == FX_MODE_DYNAMIC ) return true;
|
||||
return false;
|
||||
void WS2812FX::setPixelColor(uint16_t n, uint32_t c) {
|
||||
uint8_t w = (c >> 24);
|
||||
uint8_t r = (c >> 16);
|
||||
uint8_t g = (c >> 8);
|
||||
uint8_t b = c ;
|
||||
setPixelColor(n, r, g, b, w);
|
||||
}
|
||||
|
||||
void WS2812FX::setPixelColor(uint16_t n, uint32_t c) {
|
||||
uint8_t w = (c >> 24) & 0xFF;
|
||||
uint8_t r = (c >> 16) & 0xFF;
|
||||
uint8_t g = (c >> 8) & 0xFF;
|
||||
uint8_t b = c & 0xFF;
|
||||
setPixelColor(n, r, g, b, w);
|
||||
uint16_t WS2812FX::realPixelIndex(uint16_t i) {
|
||||
int16_t iGroup = i * SEGMENT.groupLength();
|
||||
|
||||
/* reverse just an individual segment */
|
||||
int16_t realIndex = iGroup;
|
||||
if (IS_REVERSE) realIndex = SEGMENT.length() -iGroup -1;
|
||||
|
||||
realIndex += SEGMENT.start;
|
||||
/* Reverse the whole string */
|
||||
if (reverseMode) realIndex = _length - 1 - realIndex;
|
||||
|
||||
return realIndex;
|
||||
}
|
||||
|
||||
void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
|
||||
{
|
||||
if (_locked[i] && !_modeUsesLock) return;
|
||||
if (IS_REVERSE) i = SEGMENT.stop -1 -i - SEGMENT.start; //reverse just individual segment
|
||||
byte tmpg = g;
|
||||
switch (colorOrder) //0 = Grb, default
|
||||
{
|
||||
case 0: break; //0 = Grb, default
|
||||
case 1: g = r; r = tmpg; break; //1 = Rgb, common for WS2811
|
||||
case 2: g = b; b = tmpg; break; //2 = Brg
|
||||
case 3: g = b; b = r; r = tmpg; //3 = Rbg
|
||||
}
|
||||
if (!_cronixieMode)
|
||||
{
|
||||
if (reverseMode) i = _length -1 -i;
|
||||
if (_skipFirstMode)
|
||||
{
|
||||
if (i < LED_SKIP_AMOUNT) bus->SetPixelColor(i, RgbwColor(0,0,0,0));
|
||||
i += LED_SKIP_AMOUNT;
|
||||
//auto calculate white channel value if enabled
|
||||
if (_useRgbw) {
|
||||
if (rgbwMode == RGBW_MODE_AUTO_BRIGHTER || (w == 0 && (rgbwMode == RGBW_MODE_DUAL || rgbwMode == RGBW_MODE_LEGACY)))
|
||||
{
|
||||
//white value is set to lowest RGB channel
|
||||
//thank you to @Def3nder!
|
||||
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||
} else if (rgbwMode == RGBW_MODE_AUTO_ACCURATE && w == 0)
|
||||
{
|
||||
w = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||
r -= w; g -= w; b -= w;
|
||||
}
|
||||
}
|
||||
|
||||
bus->SetPixelColor(i, RgbwColor(r,g,b,w));
|
||||
} else {
|
||||
if(i>6)return;
|
||||
byte o = 10*i;
|
||||
if (_cronixieBacklightEnabled && _cronixieDigits[i] <11)
|
||||
{
|
||||
byte r2 = (_segments[0].colors[1] >>16) & 0xFF;
|
||||
byte g2 = (_segments[0].colors[1] >> 8) & 0xFF;
|
||||
byte b2 = (_segments[0].colors[1] ) & 0xFF;
|
||||
byte w2 = (_segments[0].colors[1] >>24) & 0xFF;
|
||||
for (int j=o; j< o+19; j++)
|
||||
{
|
||||
bus->SetPixelColor(j, RgbwColor(r2,g2,b2,w2));
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (int j=o; j< o+19; j++)
|
||||
{
|
||||
bus->SetPixelColor(j, RgbwColor(0,0,0,0));
|
||||
}
|
||||
}
|
||||
if (_skipFirstMode) o += LED_SKIP_AMOUNT;
|
||||
switch(_cronixieDigits[i])
|
||||
{
|
||||
case 0: bus->SetPixelColor(o+5, RgbwColor(r,g,b,w)); break;
|
||||
case 1: bus->SetPixelColor(o+0, RgbwColor(r,g,b,w)); break;
|
||||
case 2: bus->SetPixelColor(o+6, RgbwColor(r,g,b,w)); break;
|
||||
case 3: bus->SetPixelColor(o+1, RgbwColor(r,g,b,w)); break;
|
||||
case 4: bus->SetPixelColor(o+7, RgbwColor(r,g,b,w)); break;
|
||||
case 5: bus->SetPixelColor(o+2, RgbwColor(r,g,b,w)); break;
|
||||
case 6: bus->SetPixelColor(o+8, RgbwColor(r,g,b,w)); break;
|
||||
case 7: bus->SetPixelColor(o+3, RgbwColor(r,g,b,w)); break;
|
||||
case 8: bus->SetPixelColor(o+9, RgbwColor(r,g,b,w)); break;
|
||||
case 9: bus->SetPixelColor(o+4, RgbwColor(r,g,b,w)); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::driverModeCronixie(bool b)
|
||||
{
|
||||
_cronixieMode = b;
|
||||
_segments[0].stop = (b) ? 6 : _length;
|
||||
}
|
||||
|
||||
void WS2812FX::setCronixieBacklight(bool b)
|
||||
{
|
||||
_cronixieBacklightEnabled = b;
|
||||
}
|
||||
|
||||
void WS2812FX::setCronixieDigits(byte d[])
|
||||
{
|
||||
for (int i = 0; i<6; i++)
|
||||
RgbwColor col;
|
||||
switch (colorOrder)
|
||||
{
|
||||
_cronixieDigits[i] = d[i];
|
||||
case 0: col.G = g; col.R = r; col.B = b; break; //0 = GRB, default
|
||||
case 1: col.G = r; col.R = g; col.B = b; break; //1 = RGB, common for WS2811
|
||||
case 2: col.G = b; col.R = r; col.B = g; break; //2 = BRG
|
||||
case 3: col.G = r; col.R = b; col.B = g; break; //3 = RBG
|
||||
case 4: col.G = b; col.R = g; col.B = r; break; //4 = BGR
|
||||
default: col.G = g; col.R = b; col.B = r; break; //5 = GBR
|
||||
}
|
||||
col.W = w;
|
||||
|
||||
uint16_t skip = _skipFirstMode ? LED_SKIP_AMOUNT : 0;
|
||||
if (SEGLEN) {//from segment
|
||||
|
||||
//color_blend(getpixel, col, SEGMENT.opacity); (pseudocode for future blending of segments)
|
||||
if (IS_SEGMENT_ON)
|
||||
{
|
||||
if (SEGMENT.opacity < 255) {
|
||||
col.R = scale8(col.R, SEGMENT.opacity);
|
||||
col.G = scale8(col.G, SEGMENT.opacity);
|
||||
col.B = scale8(col.B, SEGMENT.opacity);
|
||||
col.W = scale8(col.W, SEGMENT.opacity);
|
||||
}
|
||||
} else {
|
||||
col = BLACK;
|
||||
}
|
||||
|
||||
/* Set all the pixels in the group, ensuring _skipFirstMode is honored */
|
||||
bool reversed = reverseMode ^ IS_REVERSE;
|
||||
uint16_t realIndex = realPixelIndex(i);
|
||||
|
||||
for (uint16_t j = 0; j < SEGMENT.grouping; j++) {
|
||||
int16_t indexSet = realIndex + (reversed ? -j : j);
|
||||
int16_t indexSetRev = indexSet;
|
||||
if (reverseMode) indexSetRev = _length - 1 - indexSet;
|
||||
#ifdef WLED_CUSTOM_LED_MAPPING
|
||||
if (indexSet < customMappingSize) indexSet = customMappingTable[indexSet];
|
||||
#endif
|
||||
if (indexSetRev >= SEGMENT.start && indexSetRev < SEGMENT.stop) bus->SetPixelColor(indexSet + skip, col);
|
||||
}
|
||||
} else { //live data, etc.
|
||||
if (reverseMode) i = _length - 1 - i;
|
||||
#ifdef WLED_CUSTOM_LED_MAPPING
|
||||
if (i < customMappingSize) i = customMappingTable[i];
|
||||
#endif
|
||||
bus->SetPixelColor(i + skip, col);
|
||||
}
|
||||
if (skip && i == 0) {
|
||||
for (uint16_t j = 0; j < skip; j++) {
|
||||
bus->SetPixelColor(j, RgbwColor(0, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,26 +198,32 @@ void WS2812FX::setCronixieDigits(byte d[])
|
||||
//Stay safe with high amperage and have a reasonable safety margin!
|
||||
//I am NOT to be held liable for burned down garages!
|
||||
|
||||
//fine tune power estimation constants for your setup
|
||||
#define PU_PER_MA 3600 //power units per milliamperere for accurate power estimation
|
||||
//formula: 195075 divided by mA per fully lit LED, here ~54mA)
|
||||
//lowering the value increases the estimated usage and therefore makes the ABL more aggressive
|
||||
|
||||
//fine tune power estimation constants for your setup
|
||||
#define MA_FOR_ESP 100 //how much mA does the ESP use (Wemos D1 about 80mA, ESP32 about 120mA)
|
||||
//you can set it to 0 if the ESP is powered by USB and the LEDs by external
|
||||
|
||||
void WS2812FX::show(void) {
|
||||
if (_callback) _callback();
|
||||
|
||||
//power limit calculation
|
||||
//each LED can draw up 195075 "power units" (approx. 53mA)
|
||||
//one PU is the power it takes to have 1 channel 1 step brighter per brightness step
|
||||
//so A=2,R=255,G=0,B=0 would use 510 PU per LED (1mA is about 3700 PU)
|
||||
|
||||
if (ablMilliampsMax > 149 && ablMilliampsMax < 65000) //lower numbers and 65000 turn off calculation
|
||||
bool useWackyWS2815PowerModel = false;
|
||||
byte actualMilliampsPerLed = milliampsPerLed;
|
||||
|
||||
if(milliampsPerLed == 255) {
|
||||
useWackyWS2815PowerModel = true;
|
||||
actualMilliampsPerLed = 12; // from testing an actual strip
|
||||
}
|
||||
|
||||
if (ablMilliampsMax > 149 && actualMilliampsPerLed > 0) //0 mA per LED and too low numbers turn off calculation
|
||||
{
|
||||
uint32_t powerBudget = (ablMilliampsMax - MA_FOR_ESP) * PU_PER_MA; //100mA for ESP power
|
||||
if (powerBudget > PU_PER_MA * _length) //each LED uses about 1mA in standby, exclude that from power budget
|
||||
uint32_t puPerMilliamp = 195075 / actualMilliampsPerLed;
|
||||
uint32_t powerBudget = (ablMilliampsMax - MA_FOR_ESP) * puPerMilliamp; //100mA for ESP power
|
||||
if (powerBudget > puPerMilliamp * _length) //each LED uses about 1mA in standby, exclude that from power budget
|
||||
{
|
||||
powerBudget -= PU_PER_MA * _length;
|
||||
powerBudget -= puPerMilliamp * _length;
|
||||
} else
|
||||
{
|
||||
powerBudget = 0;
|
||||
@@ -213,10 +234,20 @@ void WS2812FX::show(void) {
|
||||
for (uint16_t i = 0; i < _length; i++) //sum up the usage of each LED
|
||||
{
|
||||
RgbwColor c = bus->GetPixelColorRgbw(i);
|
||||
powerSum += (c.R + c.G + c.B + c.W);
|
||||
|
||||
if(useWackyWS2815PowerModel)
|
||||
{
|
||||
// ignore white component on WS2815 power calculation
|
||||
powerSum += (MAX(MAX(c.R,c.G),c.B)) * 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
powerSum += (c.R + c.G + c.B + c.W);
|
||||
}
|
||||
}
|
||||
|
||||
if (_rgbwMode) //RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
|
||||
|
||||
if (_useRgbw) //RGBW led total output with white LEDs enabled is still 50mA, so each channel uses less
|
||||
{
|
||||
powerSum *= 3;
|
||||
powerSum = powerSum >> 2; //same as /= 4
|
||||
@@ -232,10 +263,10 @@ void WS2812FX::show(void) {
|
||||
uint8_t scaleB = (scaleI > 255) ? 255 : scaleI;
|
||||
uint8_t newBri = scale8(_brightness, scaleB);
|
||||
bus->SetBrightness(newBri);
|
||||
currentMilliamps = (powerSum0 * newBri) / PU_PER_MA;
|
||||
currentMilliamps = (powerSum0 * newBri) / puPerMilliamp;
|
||||
} else
|
||||
{
|
||||
currentMilliamps = powerSum / PU_PER_MA;
|
||||
currentMilliamps = powerSum / puPerMilliamp;
|
||||
bus->SetBrightness(_brightness);
|
||||
}
|
||||
currentMilliamps += MA_FOR_ESP; //add power of ESP back to estimate
|
||||
@@ -246,6 +277,7 @@ void WS2812FX::show(void) {
|
||||
}
|
||||
|
||||
bus->Show();
|
||||
_lastShow = millis();
|
||||
}
|
||||
|
||||
void WS2812FX::trigger() {
|
||||
@@ -255,7 +287,6 @@ void WS2812FX::trigger() {
|
||||
void WS2812FX::setMode(uint8_t segid, uint8_t m) {
|
||||
if (segid >= MAX_NUM_SEGMENTS) return;
|
||||
|
||||
bool anyUsedLock = _modeUsesLock, anyUseLock = false;
|
||||
if (m >= MODE_COUNT) m = MODE_COUNT - 1;
|
||||
|
||||
if (_segments[segid].mode != m)
|
||||
@@ -263,13 +294,6 @@ void WS2812FX::setMode(uint8_t segid, uint8_t m) {
|
||||
_segment_runtimes[segid].reset();
|
||||
_segments[segid].mode = m;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (modeUsesLock(_segments[i].mode)) anyUseLock = true;
|
||||
}
|
||||
if (anyUsedLock && !anyUseLock) unlockAll();
|
||||
_modeUsesLock = anyUseLock;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getModeCount()
|
||||
@@ -279,53 +303,38 @@ uint8_t WS2812FX::getModeCount()
|
||||
|
||||
uint8_t WS2812FX::getPaletteCount()
|
||||
{
|
||||
return 13 + gGradientPaletteCount;
|
||||
return 13 + GRADIENT_PALETTE_COUNT;
|
||||
}
|
||||
|
||||
//TODO transitions
|
||||
|
||||
void WS2812FX::setMode(uint8_t m) {
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isSelected()) setMode(i, m);
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::setSpeed(uint8_t s) {
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isSelected()) _segments[i].speed = s;
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::setIntensity(uint8_t in) {
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isSelected()) _segments[i].intensity = in;
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::setPalette(uint8_t p) {
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isSelected()) _segments[i].palette = p;
|
||||
}
|
||||
}
|
||||
|
||||
bool WS2812FX::setEffectConfig(uint8_t m, uint8_t s, uint8_t in, uint8_t p) {
|
||||
uint8_t retSeg = getReturnedSegmentId();
|
||||
Segment& seg = _segments[retSeg];
|
||||
uint8_t mainSeg = getMainSegmentId();
|
||||
Segment& seg = _segments[getMainSegmentId()];
|
||||
uint8_t modePrev = seg.mode, speedPrev = seg.speed, intensityPrev = seg.intensity, palettePrev = seg.palette;
|
||||
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isSelected())
|
||||
bool applied = false;
|
||||
|
||||
if (applyToAllSelected) {
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
_segments[i].speed = s;
|
||||
_segments[i].intensity = in;
|
||||
_segments[i].palette = p;
|
||||
setMode(i, m);
|
||||
if (_segments[i].isSelected())
|
||||
{
|
||||
_segments[i].speed = s;
|
||||
_segments[i].intensity = in;
|
||||
_segments[i].palette = p;
|
||||
setMode(i, m);
|
||||
applied = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!applyToAllSelected || !applied) {
|
||||
seg.speed = s;
|
||||
seg.intensity = in;
|
||||
seg.palette = p;
|
||||
setMode(mainSegment, m);
|
||||
}
|
||||
|
||||
if (seg.mode != modePrev || seg.speed != speedPrev || seg.intensity != intensityPrev || seg.palette != palettePrev) return true;
|
||||
@@ -338,9 +347,18 @@ 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;
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isSelected()) _segments[i].colors[slot] = c;
|
||||
|
||||
bool applied = false;
|
||||
|
||||
if (applyToAllSelected) {
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isSelected()) _segments[i].colors[slot] = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (!applyToAllSelected || !applied) {
|
||||
_segments[getMainSegmentId()].colors[slot] = c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,15 +366,15 @@ 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) {
|
||||
return _segments[getReturnedSegmentId()].mode;
|
||||
return _segments[getMainSegmentId()].mode;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getSpeed(void) {
|
||||
return _segments[getReturnedSegmentId()].speed;
|
||||
return _segments[getMainSegmentId()].speed;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getBrightness(void) {
|
||||
@@ -367,7 +385,7 @@ uint8_t WS2812FX::getMaxSegments(void) {
|
||||
return MAX_NUM_SEGMENTS;
|
||||
}
|
||||
|
||||
uint8_t WS2812FX::getFirstSelectedSegment(void)
|
||||
/*uint8_t WS2812FX::getFirstSelectedSegment(void)
|
||||
{
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
@@ -378,54 +396,41 @@ uint8_t WS2812FX::getFirstSelectedSegment(void)
|
||||
if (_segments[i].isActive()) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}*/
|
||||
|
||||
uint8_t WS2812FX::getReturnedSegmentId(void) {
|
||||
if (returnedSegment >= MAX_NUM_SEGMENTS || !_segments[returnedSegment].isActive())
|
||||
{
|
||||
return getFirstSelectedSegment();
|
||||
}
|
||||
return returnedSegment;
|
||||
uint8_t WS2812FX::getMainSegmentId(void) {
|
||||
if (mainSegment >= MAX_NUM_SEGMENTS) return 0;
|
||||
return mainSegment;
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::getColor(void) {
|
||||
return _segments[getReturnedSegmentId()].colors[0];
|
||||
return _segments[getMainSegmentId()].colors[0];
|
||||
}
|
||||
|
||||
uint32_t WS2812FX::getPixelColor(uint16_t i)
|
||||
{
|
||||
if (reverseMode) i = _length- 1 -i;
|
||||
if (IS_REVERSE) i = SEGMENT.stop -1 -i - SEGMENT.start; //reverse just individual segment
|
||||
i = realPixelIndex(i);
|
||||
|
||||
#ifdef WLED_CUSTOM_LED_MAPPING
|
||||
if (i < customMappingSize) i = customMappingTable[i];
|
||||
#endif
|
||||
|
||||
if (_skipFirstMode) i += LED_SKIP_AMOUNT;
|
||||
if (_cronixieMode)
|
||||
{
|
||||
if(i>6)return 0;
|
||||
byte o = 10*i;
|
||||
switch(_cronixieDigits[i])
|
||||
{
|
||||
case 0: i=o+5; break;
|
||||
case 1: i=o+0; break;
|
||||
case 2: i=o+6; break;
|
||||
case 3: i=o+1; break;
|
||||
case 4: i=o+7; break;
|
||||
case 5: i=o+2; break;
|
||||
case 6: i=o+8; break;
|
||||
case 7: i=o+3; break;
|
||||
case 8: i=o+9; break;
|
||||
case 9: i=o+4; break;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
RgbwColor lColor = bus->GetPixelColorRgbw(i);
|
||||
byte r = lColor.R, g = lColor.G, b = lColor.B;
|
||||
|
||||
if (i >= _lengthRaw) return 0;
|
||||
|
||||
RgbwColor col = bus->GetPixelColorRgbw(i);
|
||||
switch (colorOrder)
|
||||
{
|
||||
case 0: break; //0 = Grb
|
||||
case 1: r = lColor.G; g = lColor.R; break; //1 = Rgb, common for WS2811
|
||||
case 2: g = lColor.B; b = lColor.G; break; //2 = Brg
|
||||
case 3: r = lColor.B; g = lColor.R; b = lColor.G; //3 = Rbg
|
||||
// W G R B
|
||||
case 0: return ((col.W << 24) | (col.G << 8) | (col.R << 16) | (col.B)); //0 = GRB, default
|
||||
case 1: return ((col.W << 24) | (col.R << 8) | (col.G << 16) | (col.B)); //1 = RGB, common for WS2811
|
||||
case 2: return ((col.W << 24) | (col.B << 8) | (col.R << 16) | (col.G)); //2 = BRG
|
||||
case 3: return ((col.W << 24) | (col.B << 8) | (col.G << 16) | (col.R)); //3 = RBG
|
||||
case 4: return ((col.W << 24) | (col.R << 8) | (col.B << 16) | (col.G)); //4 = BGR
|
||||
case 5: return ((col.W << 24) | (col.G << 8) | (col.B << 16) | (col.R)); //5 = GBR
|
||||
}
|
||||
return ( (lColor.W << 24) | (r << 16) | (g << 8) | (b) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
WS2812FX::Segment& WS2812FX::getSegment(uint8_t id) {
|
||||
@@ -441,99 +446,90 @@ WS2812FX::Segment* WS2812FX::getSegments(void) {
|
||||
return _segments;
|
||||
}
|
||||
|
||||
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2) {
|
||||
uint32_t WS2812FX::getLastShow(void) {
|
||||
return _lastShow;
|
||||
}
|
||||
|
||||
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2, uint8_t grouping, uint8_t spacing) {
|
||||
if (n >= MAX_NUM_SEGMENTS) return;
|
||||
Segment& seg = _segments[n];
|
||||
if (seg.start == i1 && seg.stop == i2) return;
|
||||
if (seg.isActive() && modeUsesLock(seg.mode))
|
||||
{
|
||||
_modeUsesLock = false;
|
||||
unlockRange(seg.start, seg.stop);
|
||||
_modeUsesLock = true;
|
||||
}
|
||||
|
||||
//return if neither bounds nor grouping have changed
|
||||
if (seg.start == i1 && seg.stop == i2 && (!grouping || (seg.grouping == grouping && seg.spacing == spacing))) return;
|
||||
|
||||
if (seg.stop) setRange(seg.start, seg.stop -1, 0); //turn old segment range off
|
||||
if (i2 <= i1) //disable segment
|
||||
{
|
||||
seg.stop = 0; return;
|
||||
seg.stop = 0;
|
||||
if (n == mainSegment) //if main segment is deleted, set first active as main segment
|
||||
{
|
||||
for (uint8_t i = 0; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
if (_segments[i].isActive()) {
|
||||
mainSegment = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
mainSegment = 0; //should not happen (always at least one active segment)
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (i1 < _length) seg.start = i1;
|
||||
seg.stop = i2;
|
||||
if (i2 > _length) seg.stop = _length;
|
||||
if (grouping) {
|
||||
seg.grouping = grouping;
|
||||
seg.spacing = spacing;
|
||||
}
|
||||
_segment_runtimes[n].reset();
|
||||
}
|
||||
|
||||
void WS2812FX::resetSegments() {
|
||||
mainSegment = 0;
|
||||
memset(_segments, 0, sizeof(_segments));
|
||||
memset(_segment_runtimes, 0, sizeof(_segment_runtimes));
|
||||
//memset(_segment_runtimes, 0, sizeof(_segment_runtimes));
|
||||
_segment_index = 0;
|
||||
_segments[0].mode = DEFAULT_MODE;
|
||||
_segments[0].colors[0] = DEFAULT_COLOR;
|
||||
_segments[0].start = 0;
|
||||
_segments[0].speed = DEFAULT_SPEED;
|
||||
_segments[0].stop = _length;
|
||||
_segments[0].setOption(0, 1); //select
|
||||
}
|
||||
_segments[0].grouping = 1;
|
||||
_segments[0].setOption(SEG_OPTION_SELECTED, 1);
|
||||
_segments[0].setOption(SEG_OPTION_ON, 1);
|
||||
_segments[0].opacity = 255;
|
||||
|
||||
void WS2812FX::setIndividual(uint16_t i, uint32_t col)
|
||||
{
|
||||
if (modeUsesLock(SEGMENT.mode)) return;
|
||||
if (i >= 0 && i < _length)
|
||||
for (uint16_t i = 1; i < MAX_NUM_SEGMENTS; i++)
|
||||
{
|
||||
_locked[i] = false;
|
||||
setPixelColor(i, col);
|
||||
_locked[i] = true;
|
||||
_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();
|
||||
}
|
||||
|
||||
void WS2812FX::setRange(uint16_t i, uint16_t i2, uint32_t col)
|
||||
{
|
||||
if (i2 >= i)
|
||||
{
|
||||
for (uint16_t x = i; x <= i2; x++) setIndividual(x,col);
|
||||
for (uint16_t x = i; x <= i2; x++) setPixelColor(x, col);
|
||||
} else
|
||||
{
|
||||
for (uint16_t x = i2; x <= i; x++) setIndividual(x,col);
|
||||
for (uint16_t x = i2; x <= i; x++) setPixelColor(x, col);
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::lock(uint16_t i)
|
||||
void WS2812FX::setShowCallback(show_callback cb)
|
||||
{
|
||||
if (_modeUsesLock) return;
|
||||
if (i < _length) _locked[i] = true;
|
||||
}
|
||||
|
||||
void WS2812FX::lockRange(uint16_t i, uint16_t i2)
|
||||
{
|
||||
if (_modeUsesLock) return;
|
||||
for (uint16_t x = i; x < i2; x++)
|
||||
{
|
||||
if (x < _length) _locked[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::unlock(uint16_t i)
|
||||
{
|
||||
if (_modeUsesLock) return;
|
||||
if (i < _length) _locked[i] = false;
|
||||
}
|
||||
|
||||
void WS2812FX::unlockRange(uint16_t i, uint16_t i2)
|
||||
{
|
||||
if (_modeUsesLock) return;
|
||||
for (uint16_t x = i; x < i2; x++)
|
||||
{
|
||||
if (x < _length) _locked[x] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void WS2812FX::unlockAll()
|
||||
{
|
||||
for (int i=0; i < _length; i++) _locked[i] = false;
|
||||
_callback = cb;
|
||||
}
|
||||
|
||||
void WS2812FX::setTransitionMode(bool t)
|
||||
{
|
||||
_segment_index = 0;
|
||||
SEGMENT.setOption(7,t);
|
||||
_segment_index = getMainSegmentId();
|
||||
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;
|
||||
@@ -568,7 +564,7 @@ uint32_t WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint8_t blend)
|
||||
* Fills segment with color
|
||||
*/
|
||||
void WS2812FX::fill(uint32_t c) {
|
||||
for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) {
|
||||
for(uint16_t i = 0; i < SEGLEN; i++) {
|
||||
setPixelColor(i, c);
|
||||
}
|
||||
}
|
||||
@@ -586,7 +582,7 @@ void WS2812FX::fade_out(uint8_t rate) {
|
||||
int g2 = (color >> 8) & 0xff;
|
||||
int b2 = color & 0xff;
|
||||
|
||||
for(uint16_t i=SEGMENT.start; i < SEGMENT.stop; i++) {
|
||||
for(uint16_t i = 0; i < SEGLEN; i++) {
|
||||
color = getPixelColor(i);
|
||||
int w1 = (color >> 24) & 0xff;
|
||||
int r1 = (color >> 16) & 0xff;
|
||||
@@ -616,14 +612,14 @@ void WS2812FX::blur(uint8_t blur_amount)
|
||||
uint8_t keep = 255 - blur_amount;
|
||||
uint8_t seep = blur_amount >> 1;
|
||||
CRGB carryover = CRGB::Black;
|
||||
for(uint16_t i = SEGMENT.start; i < SEGMENT.stop; i++)
|
||||
for(uint16_t i = 0; i < SEGLEN; i++)
|
||||
{
|
||||
CRGB cur = col_to_crgb(getPixelColor(i));
|
||||
CRGB part = cur;
|
||||
part.nscale8(seep);
|
||||
cur.nscale8(keep);
|
||||
cur += carryover;
|
||||
if(i > SEGMENT.start) {
|
||||
if(i > 0) {
|
||||
uint32_t c = getPixelColor(i-1);
|
||||
uint8_t r = (c >> 16 & 0xFF);
|
||||
uint8_t g = (c >> 8 & 0xFF);
|
||||
@@ -635,6 +631,12 @@ void WS2812FX::blur(uint8_t blur_amount)
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t WS2812FX::triwave16(uint16_t in)
|
||||
{
|
||||
if (in < 0x8000) return in *2;
|
||||
return 0xFFFF - (in - 0x8000)*2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put a value 0 to 255 in to get a color value.
|
||||
* The colours are a transition r -> g -> b -> back to r
|
||||
@@ -664,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;
|
||||
}
|
||||
@@ -686,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
|
||||
*/
|
||||
@@ -695,20 +706,22 @@ void WS2812FX::handle_palette(void)
|
||||
_segment_index_palette_last = _segment_index;
|
||||
|
||||
byte paletteIndex = SEGMENT.palette;
|
||||
if ((SEGMENT.mode >= FX_MODE_METEOR) && SEGMENT.palette == 0) paletteIndex = 4;
|
||||
if (SEGMENT.mode == FX_MODE_GLITTER && paletteIndex == 0) paletteIndex = 11;
|
||||
if (SEGMENT.mode >= FX_MODE_METEOR && paletteIndex == 0) paletteIndex = 4;
|
||||
|
||||
switch (paletteIndex)
|
||||
{
|
||||
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
|
||||
}
|
||||
@@ -730,24 +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
|
||||
case 3: {//primary + secondary
|
||||
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
|
||||
CRGB sec = col_to_crgb(SEGCOLOR(1));
|
||||
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 4: {//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
|
||||
CRGB prim = col_to_crgb(SEGCOLOR(0));
|
||||
CRGB sec = col_to_crgb(SEGCOLOR(1));
|
||||
targetPalette = CRGBPalette16(sec,prim,CRGB::White); break;}
|
||||
case 6: //Party colors
|
||||
targetPalette = PartyColors_p; break;
|
||||
case 7: //Cloud colors
|
||||
@@ -763,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
|
||||
@@ -779,13 +793,65 @@ uint32_t WS2812FX::color_from_palette(uint16_t i, bool mapping, bool wrap, uint8
|
||||
{
|
||||
if (SEGMENT.palette == 0 && mcol < 3) return SEGCOLOR(mcol); //WS2812FX default
|
||||
uint8_t paletteIndex = i;
|
||||
if (mapping) paletteIndex = map(i,SEGMENT.start,SEGMENT.stop-1,0,255);
|
||||
if (mapping) paletteIndex = (i*255)/(SEGLEN -1);
|
||||
if (!wrap) paletteIndex = scale8(paletteIndex, 240); //cut off blend at palette "end"
|
||||
CRGB fastled_col;
|
||||
fastled_col = ColorFromPalette( currentPalette, paletteIndex, pbri, (paletteBlend == 3)? NOBLEND:LINEARBLEND);
|
||||
return fastled_col.r*65536 + fastled_col.g*256 + fastled_col.b;
|
||||
}
|
||||
|
||||
bool WS2812FX::segmentsAreIdentical(Segment* a, Segment* b)
|
||||
{
|
||||
//if (a->start != b->start) return false;
|
||||
//if (a->stop != b->stop) return false;
|
||||
for (uint8_t i = 0; i < NUM_COLORS; i++)
|
||||
{
|
||||
if (a->colors[i] != b->colors[i]) return false;
|
||||
}
|
||||
if (a->mode != b->mode) return false;
|
||||
if (a->speed != b->speed) return false;
|
||||
if (a->intensity != b->intensity) return false;
|
||||
if (a->palette != b->palette) return false;
|
||||
//if (a->getOption(SEG_OPTION_REVERSED) != b->getOption(SEG_OPTION_REVERSED)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
void WS2812FX::setRgbwPwm(void) {
|
||||
uint32_t nowUp = millis(); // Be aware, millis() rolls over every 49 days
|
||||
if (nowUp - _analogLastShow < MIN_SHOW_DELAY) return;
|
||||
|
||||
_analogLastShow = nowUp;
|
||||
|
||||
RgbwColor color = bus->GetPixelColorRgbw(0);
|
||||
byte b = getBrightness();
|
||||
if (color == _analogLastColor && b == _analogLastBri) return;
|
||||
|
||||
// check color values for Warm / Cold white mix (for RGBW) // EsplanexaDevice.cpp
|
||||
#ifdef WLED_USE_5CH_LEDS
|
||||
if (color.R == 255 && color.G == 255 && color.B == 255 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, 0, color.W * b / 255);
|
||||
} else if (color.R == 127 && color.G == 127 && color.B == 127 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, color.W * b / 512, color.W * b / 255);
|
||||
} else if (color.R == 0 && color.G == 0 && color.B == 0 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
|
||||
} else if (color.R == 130 && color.G == 90 && color.B == 0 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, color.W * b / 255, color.W * b / 512);
|
||||
} else if (color.R == 255 && color.G == 153 && color.B == 0 && color.W == 255) {
|
||||
bus->SetRgbwPwm(0, 0, 0, color.W * b / 255, 0);
|
||||
} else { // not only white colors
|
||||
bus->SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);
|
||||
}
|
||||
#else
|
||||
bus->SetRgbwPwm(color.R * b / 255, color.G * b / 255, color.B * b / 255, color.W * b / 255);
|
||||
#endif
|
||||
_analogLastColor = color;
|
||||
_analogLastBri = b;
|
||||
}
|
||||
#else
|
||||
void WS2812FX::setRgbwPwm() {}
|
||||
#endif
|
||||
|
||||
//gamma 2.4 lookup table used for color correction
|
||||
const byte gammaT[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -813,13 +879,15 @@ uint8_t WS2812FX::gamma8(uint8_t b)
|
||||
uint32_t WS2812FX::gamma32(uint32_t color)
|
||||
{
|
||||
if (!gammaCorrectCol) return color;
|
||||
uint8_t w = (color >> 24) & 0xFF;
|
||||
uint8_t r = (color >> 16) & 0xFF;
|
||||
uint8_t g = (color >> 8) & 0xFF;
|
||||
uint8_t b = color & 0xFF;
|
||||
uint8_t w = (color >> 24);
|
||||
uint8_t r = (color >> 16);
|
||||
uint8_t g = (color >> 8);
|
||||
uint8_t b = color;
|
||||
w = gammaT[w];
|
||||
r = gammaT[r];
|
||||
g = gammaT[g];
|
||||
b = gammaT[b];
|
||||
return ((w << 24) | (r << 16) | (g << 8) | (b));
|
||||
}
|
||||
|
||||
uint16_t WS2812FX::_usedSegmentData = 0;
|
||||
|
||||
@@ -3,16 +3,41 @@
|
||||
#define NpbWrapper_h
|
||||
|
||||
//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 USE_APA102 // Uncomment for using APA102 LEDs.
|
||||
#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended)
|
||||
#define IR_PIN 4 //infrared pin (-1 to disable)
|
||||
#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 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
|
||||
|
||||
#define RLYMDE 1 //mode for relay, 0: LOW if LEDs are on 1: HIGH if LEDs are on
|
||||
#ifndef BTNPIN
|
||||
#define BTNPIN 0 //button pin. Needs to have pullup (gpio0 recommended)
|
||||
#endif
|
||||
|
||||
#ifdef USE_APA102
|
||||
#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) || defined(USE_P9813)
|
||||
#define CLKPIN 0
|
||||
#define DATAPIN 2
|
||||
#if BTNPIN == CLKPIN || BTNPIN == DATAPIN
|
||||
@@ -20,11 +45,53 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
//PWM pins - PINs 15,13,12,14 (W2 = 04)are used with H801 Wifi LED Controller
|
||||
#ifdef WLED_USE_H801
|
||||
#define RPIN 15 //R pin for analog LED strip
|
||||
#define GPIN 13 //G pin for analog LED strip
|
||||
#define BPIN 12 //B pin for analog LED strip
|
||||
#define WPIN 14 //W pin for analog LED strip
|
||||
#define W2PIN 04 //W2 pin for analog LED strip
|
||||
#undef BTNPIN
|
||||
#undef IR_PIN
|
||||
#define IR_PIN 0 //infrared pin (-1 to disable) MagicHome: 4, H801 Wifi: 0
|
||||
#elif defined(WLED_USE_BWLT11)
|
||||
//PWM pins - to use with BW-LT11
|
||||
#define RPIN 12 //R pin for analog LED strip
|
||||
#define GPIN 4 //G pin for analog LED strip
|
||||
#define BPIN 14 //B pin for analog LED strip
|
||||
#define WPIN 5 //W pin for analog LED strip
|
||||
#elif defined(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
|
||||
#endif
|
||||
#undef RLYPIN
|
||||
#define RLYPIN -1 //disable as pin 12 is used by analog LEDs
|
||||
#endif
|
||||
|
||||
//automatically uses the right driver method for each platform
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifdef USE_APA102
|
||||
#define PIXELMETHOD DotStarMethod
|
||||
#elif defined(USE_WS2801)
|
||||
#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
|
||||
@@ -32,6 +99,14 @@
|
||||
//autoselect the right method depending on strip pin
|
||||
#ifdef USE_APA102
|
||||
#define PIXELMETHOD DotStarMethod
|
||||
#elif defined(USE_WS2801)
|
||||
#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
|
||||
@@ -47,6 +122,15 @@
|
||||
#ifdef USE_APA102
|
||||
#define PIXELFEATURE3 DotStarBgrFeature
|
||||
#define PIXELFEATURE4 DotStarLbgrFeature
|
||||
#elif defined(USE_LPD8806)
|
||||
#define PIXELFEATURE3 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
|
||||
@@ -88,7 +172,7 @@ public:
|
||||
switch (_type)
|
||||
{
|
||||
case NeoPixelType_Grb:
|
||||
#ifdef USE_APA102
|
||||
#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);
|
||||
@@ -97,7 +181,7 @@ public:
|
||||
break;
|
||||
|
||||
case NeoPixelType_Grbw:
|
||||
#ifdef USE_APA102
|
||||
#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);
|
||||
@@ -105,39 +189,100 @@ public:
|
||||
_pGrbw->Begin();
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
ledcSetup(0, 5000, 8);
|
||||
ledcAttachPin(RPIN, 0);
|
||||
ledcSetup(1, 5000, 8);
|
||||
ledcAttachPin(GPIN, 1);
|
||||
ledcSetup(2, 5000, 8);
|
||||
ledcAttachPin(BPIN, 2);
|
||||
if(_type == NeoPixelType_Grbw)
|
||||
{
|
||||
ledcSetup(3, 5000, 8);
|
||||
ledcAttachPin(WPIN, 3);
|
||||
#ifdef WLED_USE_5CH_LEDS
|
||||
ledcSetup(4, 5000, 8);
|
||||
ledcAttachPin(W2PIN, 4);
|
||||
#endif
|
||||
}
|
||||
#else // ESP8266
|
||||
//init PWM pins
|
||||
pinMode(RPIN, OUTPUT);
|
||||
pinMode(GPIN, OUTPUT);
|
||||
pinMode(BPIN, OUTPUT);
|
||||
if(_type == NeoPixelType_Grbw)
|
||||
{
|
||||
pinMode(WPIN, OUTPUT);
|
||||
#ifdef WLED_USE_5CH_LEDS
|
||||
pinMode(W2PIN, OUTPUT);
|
||||
#endif
|
||||
}
|
||||
analogWriteRange(255); //same range as one RGB channel
|
||||
analogWriteFreq(880); //PWM frequency proven as good for LEDs
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
void SetRgbwPwm(uint8_t r, uint8_t g, uint8_t b, uint8_t w, uint8_t w2=0)
|
||||
{
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
ledcWrite(0, r);
|
||||
ledcWrite(1, g);
|
||||
ledcWrite(2, b);
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: break;
|
||||
#ifdef WLED_USE_5CH_LEDS
|
||||
case NeoPixelType_Grbw: ledcWrite(3, w); ledcWrite(4, w2); break;
|
||||
#else
|
||||
case NeoPixelType_Grbw: ledcWrite(3, w); break;
|
||||
#endif
|
||||
}
|
||||
#else // ESP8266
|
||||
analogWrite(RPIN, r);
|
||||
analogWrite(GPIN, g);
|
||||
analogWrite(BPIN, b);
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: break;
|
||||
#ifdef WLED_USE_5CH_LEDS
|
||||
case NeoPixelType_Grbw: analogWrite(WPIN, w); analogWrite(W2PIN, w2); break;
|
||||
#else
|
||||
case NeoPixelType_Grbw: analogWrite(WPIN, w); break;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void Show()
|
||||
{
|
||||
byte b;
|
||||
switch (_type)
|
||||
{
|
||||
case NeoPixelType_Grb: _pGrb->Show(); break;
|
||||
case NeoPixelType_Grbw: _pGrbw->Show(); break;
|
||||
}
|
||||
}
|
||||
|
||||
bool CanShow() const
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: _pGrb->CanShow(); break;
|
||||
case NeoPixelType_Grbw: _pGrbw->CanShow(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void SetPixelColor(uint16_t indexPixel, RgbColor color)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: _pGrb->SetPixelColor(indexPixel, color); break;
|
||||
case NeoPixelType_Grbw:_pGrbw->SetPixelColor(indexPixel, color); break;
|
||||
case NeoPixelType_Grb: _pGrb->Show(); break;
|
||||
case NeoPixelType_Grbw: _pGrbw->Show(); break;
|
||||
}
|
||||
}
|
||||
|
||||
void SetPixelColor(uint16_t indexPixel, RgbwColor color)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: _pGrb->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B)); break;
|
||||
case NeoPixelType_Grbw: _pGrbw->SetPixelColor(indexPixel, color); break;
|
||||
case NeoPixelType_Grb: {
|
||||
_pGrb->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B));
|
||||
}
|
||||
break;
|
||||
case NeoPixelType_Grbw: {
|
||||
#ifdef USE_LPD8806
|
||||
_pGrbw->SetPixelColor(indexPixel, RgbColor(color.R,color.G,color.B));
|
||||
#else
|
||||
_pGrbw->SetPixelColor(indexPixel, color);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SetBrightness(byte b)
|
||||
@@ -148,15 +293,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
RgbColor GetPixelColor(uint16_t indexPixel) const
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: return _pGrb->GetPixelColor(indexPixel); break;
|
||||
case NeoPixelType_Grbw: /*doesn't support it so we don't return it*/ break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// NOTE: Due to feature differences, some support RGBW but the method name
|
||||
// here needs to be unique, thus GetPixeColorRgbw
|
||||
RgbwColor GetPixelColorRgbw(uint16_t indexPixel) const
|
||||
@@ -168,21 +304,15 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ClearTo(RgbColor color)
|
||||
uint8_t* GetPixels(void)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: _pGrb->ClearTo(color); break;
|
||||
case NeoPixelType_Grbw:_pGrbw->ClearTo(color); break;
|
||||
case NeoPixelType_Grb: return _pGrb->Pixels(); break;
|
||||
case NeoPixelType_Grbw: return _pGrbw->Pixels(); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ClearTo(RgbwColor color)
|
||||
{
|
||||
switch (_type) {
|
||||
case NeoPixelType_Grb: break;
|
||||
case NeoPixelType_Grbw:_pGrbw->ClearTo(color); break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
NeoPixelType _type;
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
#define __ESP32_ESP32__
|
||||
#define ESP_PLATFORM
|
||||
#define HAVE_CONFIG_H
|
||||
#define GCC_NOT_5_2_0 0
|
||||
#define WITH_POSIX
|
||||
#define F_CPU 240000000L
|
||||
#define ARDUINO 10807
|
||||
#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
File diff suppressed because one or more lines are too long
@@ -1,10 +1,13 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Alexa Voice On/Off/Brightness Control. Emulates a Philips Hue bridge to Alexa.
|
||||
* Alexa Voice On/Off/Brightness/Color Control. Emulates a Philips Hue bridge to Alexa.
|
||||
*
|
||||
* This was put together from these two excellent projects:
|
||||
* https://github.com/kakopappa/arduino-esp8266-alexa-wemo-switch
|
||||
* https://github.com/probonopd/ESP8266HueEmulator
|
||||
*/
|
||||
#include "src/dependencies/espalexa/EspalexaDevice.h"
|
||||
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
void onAlexaChange(EspalexaDevice* dev);
|
||||
@@ -41,7 +44,7 @@ void onAlexaChange(EspalexaDevice* dev)
|
||||
if (bri == 0)
|
||||
{
|
||||
bri = briLast;
|
||||
colorUpdated(10);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||
}
|
||||
} else applyMacro(macroAlexaOn);
|
||||
} else if (m == EspalexaDeviceProperty::off)
|
||||
@@ -52,21 +55,38 @@ void onAlexaChange(EspalexaDevice* dev)
|
||||
{
|
||||
briLast = bri;
|
||||
bri = 0;
|
||||
colorUpdated(10);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||
}
|
||||
} else applyMacro(macroAlexaOff);
|
||||
} else if (m == EspalexaDeviceProperty::bri)
|
||||
{
|
||||
bri = espalexaDevice->getValue();
|
||||
colorUpdated(10);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||
} else //color
|
||||
{
|
||||
uint32_t color = espalexaDevice->getRGB();
|
||||
col[0] = ((color >> 16) & 0xFF);
|
||||
col[1] = ((color >> 8) & 0xFF);
|
||||
col[2] = (color & 0xFF);
|
||||
if (useRGBW) colorRGBtoRGBW(col);
|
||||
colorUpdated(10);
|
||||
if (espalexaDevice->getColorMode() == EspalexaColorMode::ct) //shade of white
|
||||
{
|
||||
uint16_t ct = espalexaDevice->getCt();
|
||||
if (useRGBW)
|
||||
{
|
||||
switch (ct) { //these values empirically look good on RGBW
|
||||
case 199: col[0]=255; col[1]=255; col[2]=255; col[3]=255; break;
|
||||
case 234: col[0]=127; col[1]=127; col[2]=127; col[3]=255; break;
|
||||
case 284: col[0]= 0; col[1]= 0; col[2]= 0; col[3]=255; break;
|
||||
case 350: col[0]=130; col[1]= 90; col[2]= 0; col[3]=255; break;
|
||||
case 383: col[0]=255; col[1]=153; col[2]= 0; col[3]=255; break;
|
||||
}
|
||||
} else {
|
||||
colorCTtoRGB(ct, col);
|
||||
}
|
||||
} else {
|
||||
uint32_t color = espalexaDevice->getRGB();
|
||||
|
||||
col[0] = ((color >> 16) & 0xFF);
|
||||
col[1] = ((color >> 8) & 0xFF);
|
||||
col[2] = ( color & 0xFF);
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_ALEXA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#include "wled.h"
|
||||
#include "src/dependencies/blynk/Blynk/BlynkHandlers.h"
|
||||
|
||||
/*
|
||||
* Remote light control with the free Blynk app
|
||||
*/
|
||||
@@ -41,45 +44,45 @@ void updateBlynk()
|
||||
BLYNK_WRITE(V0)
|
||||
{
|
||||
bri = param.asInt();//bri
|
||||
colorUpdated(9);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V1)
|
||||
{
|
||||
blHue = param.asInt();//hue
|
||||
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
|
||||
colorUpdated(9);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V2)
|
||||
{
|
||||
blSat = param.asInt();//sat
|
||||
colorHStoRGB(blHue*10,blSat,(false)? colSec:col);
|
||||
colorUpdated(9);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V3)
|
||||
{
|
||||
bool on = (param.asInt()>0);
|
||||
if (!on != !bri) {toggleOnOff(); colorUpdated(9);}
|
||||
if (!on != !bri) {toggleOnOff(); colorUpdated(NOTIFIER_CALL_MODE_BLYNK);}
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V4)
|
||||
{
|
||||
effectCurrent = param.asInt()-1;//fx
|
||||
colorUpdated(9);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V5)
|
||||
{
|
||||
effectSpeed = param.asInt();//sx
|
||||
colorUpdated(9);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V6)
|
||||
{
|
||||
effectIntensity = param.asInt();//ix
|
||||
colorUpdated(9);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BLYNK);
|
||||
}
|
||||
|
||||
BLYNK_WRITE(V7)
|
||||
@@ -1,3 +1,5 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Physical IO
|
||||
*/
|
||||
@@ -7,7 +9,7 @@ void shortPressAction()
|
||||
if (!macroButton)
|
||||
{
|
||||
toggleOnOff();
|
||||
colorUpdated(2);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
} else {
|
||||
applyMacro(macroButton);
|
||||
}
|
||||
@@ -44,7 +46,7 @@ void handleButton()
|
||||
|
||||
if (dur > 6000) //long press
|
||||
{
|
||||
initAP(true);
|
||||
WLED::instance().initAP(true);
|
||||
}
|
||||
else if (!buttonLongPressed) { //short press
|
||||
if (macroDoublePress)
|
||||
@@ -1,13 +1,45 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Color conversion methods
|
||||
*/
|
||||
|
||||
void colorFromUint32(uint32_t in)
|
||||
void colorFromUint32(uint32_t in, bool secondary)
|
||||
{
|
||||
col[3] = in >> 24 & 0xFF;
|
||||
col[0] = in >> 16 & 0xFF;
|
||||
col[1] = in >> 8 & 0xFF;
|
||||
col[2] = in & 0xFF;
|
||||
if (secondary) {
|
||||
colSec[3] = in >> 24 & 0xFF;
|
||||
colSec[0] = in >> 16 & 0xFF;
|
||||
colSec[1] = in >> 8 & 0xFF;
|
||||
colSec[2] = in & 0xFF;
|
||||
} else {
|
||||
col[3] = in >> 24 & 0xFF;
|
||||
col[0] = in >> 16 & 0xFF;
|
||||
col[1] = in >> 8 & 0xFF;
|
||||
col[2] = in & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
//load a color without affecting the white channel
|
||||
void colorFromUint24(uint32_t in, bool secondary)
|
||||
{
|
||||
if (secondary) {
|
||||
colSec[0] = in >> 16 & 0xFF;
|
||||
colSec[1] = in >> 8 & 0xFF;
|
||||
colSec[2] = in & 0xFF;
|
||||
} else {
|
||||
col[0] = in >> 16 & 0xFF;
|
||||
col[1] = in >> 8 & 0xFF;
|
||||
col[2] = in & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
//relatively change white brightness, minumum A=5
|
||||
void relativeChangeWhite(int8_t amount, byte lowerBoundary)
|
||||
{
|
||||
int16_t new_val = (int16_t) col[3] + amount;
|
||||
if (new_val > 0xFF) new_val = 0xFF;
|
||||
else if (new_val < lowerBoundary) new_val = lowerBoundary;
|
||||
col[3] = new_val;
|
||||
}
|
||||
|
||||
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb
|
||||
@@ -27,9 +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 && 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
|
||||
@@ -50,8 +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 && 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;
|
||||
@@ -106,6 +140,7 @@ void colorXYtoRGB(float x, float y, byte* rgb) //coordinates to rgb (https://www
|
||||
rgb[0] = 255.0*r;
|
||||
rgb[1] = 255.0*g;
|
||||
rgb[2] = 255.0*b;
|
||||
if (useRGBW) colorRGBtoRGBW(col);
|
||||
}
|
||||
|
||||
void colorRGBtoXY(byte* rgb, float* xy) //rgb to coordinates (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy)
|
||||
@@ -116,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)
|
||||
{
|
||||
@@ -150,11 +186,11 @@ float maxf (float v, float w)
|
||||
return v;
|
||||
}
|
||||
|
||||
void colorRGBtoRGBW(byte* rgb) //rgb to rgbw (http://codewelt.com/rgbw)
|
||||
void colorRGBtoRGBW(byte* rgb) //rgb to rgbw (http://codewelt.com/rgbw). (RGBW_MODE_LEGACY)
|
||||
{
|
||||
float low = minf(rgb[0],minf(rgb[1],rgb[2]));
|
||||
float high = maxf(rgb[0],maxf(rgb[1],rgb[2]));
|
||||
if (high < 0.1f) return;
|
||||
float sat = 255.0f * ((high - low) / high);
|
||||
float sat = 100.0f * ((high - low) / high);; // maximum saturation is 100 (corrected from 255)
|
||||
rgb[3] = (byte)((255.0f - sat) / 255.0f * (rgb[0] + rgb[1] + rgb[2]) / 3);
|
||||
}
|
||||
107
wled00/const.h
Normal file
107
wled00/const.h
Normal file
@@ -0,0 +1,107 @@
|
||||
#ifndef WLED_CONST_H
|
||||
#define WLED_CONST_H
|
||||
|
||||
/*
|
||||
* Readability defines and their associated numerical values + compile-time constants
|
||||
*/
|
||||
|
||||
//Defaults
|
||||
#define DEFAULT_CLIENT_SSID "Your_Network"
|
||||
#define DEFAULT_AP_PASS "wled1234"
|
||||
#define DEFAULT_OTA_PASS "wledota"
|
||||
|
||||
//Access point behavior
|
||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||
#define AP_BEHAVIOR_NO_CONN 1 //Open when no connection (either after boot or if connection is lost)
|
||||
#define AP_BEHAVIOR_ALWAYS 2 //Always open
|
||||
#define AP_BEHAVIOR_BUTTON_ONLY 3 //Only when button pressed for 6 sec
|
||||
|
||||
//Notifier callMode
|
||||
#define NOTIFIER_CALL_MODE_INIT 0 //no updates on init, can be used to disable updates
|
||||
#define NOTIFIER_CALL_MODE_DIRECT_CHANGE 1
|
||||
#define NOTIFIER_CALL_MODE_BUTTON 2
|
||||
#define NOTIFIER_CALL_MODE_NOTIFICATION 3
|
||||
#define NOTIFIER_CALL_MODE_NIGHTLIGHT 4
|
||||
#define NOTIFIER_CALL_MODE_NO_NOTIFY 5
|
||||
#define NOTIFIER_CALL_MODE_FX_CHANGED 6 //no longer used
|
||||
#define NOTIFIER_CALL_MODE_HUE 7
|
||||
#define NOTIFIER_CALL_MODE_PRESET_CYCLE 8
|
||||
#define NOTIFIER_CALL_MODE_BLYNK 9
|
||||
#define NOTIFIER_CALL_MODE_ALEXA 10
|
||||
|
||||
//RGB to RGBW conversion mode
|
||||
#define RGBW_MODE_MANUAL_ONLY 0 //No automatic white channel calculation. Manual white channel slider
|
||||
#define RGBW_MODE_AUTO_BRIGHTER 1 //New algorithm. Adds as much white as the darkest RGBW channel
|
||||
#define RGBW_MODE_AUTO_ACCURATE 2 //New algorithm. Adds as much white as the darkest RGBW channel and subtracts this amount from each RGB channel
|
||||
#define RGBW_MODE_DUAL 3 //Manual slider + auto calculation. Automatically calculates only if manual slider is set to off (0)
|
||||
#define RGBW_MODE_LEGACY 4 //Old floating algorithm. Too slow for realtime and palette support
|
||||
|
||||
//realtime modes
|
||||
#define REALTIME_MODE_INACTIVE 0
|
||||
#define REALTIME_MODE_GENERIC 1
|
||||
#define REALTIME_MODE_UDP 2
|
||||
#define REALTIME_MODE_HYPERION 3
|
||||
#define REALTIME_MODE_E131 4
|
||||
#define REALTIME_MODE_ADALIGHT 5
|
||||
#define REALTIME_MODE_ARTNET 6
|
||||
|
||||
//realtime override modes
|
||||
#define REALTIME_OVERRIDE_NONE 0
|
||||
#define REALTIME_OVERRIDE_ONCE 1
|
||||
#define REALTIME_OVERRIDE_ALWAYS 2
|
||||
|
||||
//E1.31 DMX modes
|
||||
#define DMX_MODE_DISABLED 0 //not used
|
||||
#define DMX_MODE_SINGLE_RGB 1 //all LEDs same RGB color (3 channels)
|
||||
#define DMX_MODE_SINGLE_DRGB 2 //all LEDs same RGB color and master dimmer (4 channels)
|
||||
#define DMX_MODE_EFFECT 3 //trigger standalone effects of WLED (11 channels)
|
||||
#define DMX_MODE_MULTIPLE_RGB 4 //every LED is addressed with its own RGB (ledCount * 3 channels)
|
||||
#define DMX_MODE_MULTIPLE_DRGB 5 //every LED is addressed with its own RGB and share a master dimmer (ledCount * 3 + 1 channels)
|
||||
|
||||
//Light capability byte (unused)
|
||||
#define TYPE_NONE 0 //light is not configured
|
||||
#define TYPE_RESERVED 1 //unused. Might indicate a "virtual" light
|
||||
#define TYPE_WS2812_RGB 2
|
||||
#define TYPE_SK6812_RGBW 3
|
||||
#define TYPE_WS2812_WWA 4 //amber + warm + cold white
|
||||
#define TYPE_WS2801 5
|
||||
#define TYPE_ANALOG_1CH 6 //single channel PWM. Uses value of brightest RGBW channel
|
||||
#define TYPE_ANALOG_2CH 7 //analog WW + CW
|
||||
#define TYPE_ANALOG_3CH 8 //analog RGB
|
||||
#define TYPE_ANALOG_4CH 9 //analog RGBW
|
||||
#define TYPE_ANALOG_5CH 10 //analog RGB + WW + CW
|
||||
#define TYPE_APA102 11
|
||||
#define TYPE_LPD8806 12
|
||||
|
||||
//Hue error codes
|
||||
#define HUE_ERROR_INACTIVE 0
|
||||
#define HUE_ERROR_UNAUTHORIZED 1
|
||||
#define HUE_ERROR_LIGHTID 3
|
||||
#define HUE_ERROR_PUSHLINK 101
|
||||
#define HUE_ERROR_JSON_PARSING 250
|
||||
#define HUE_ERROR_TIMEOUT 251
|
||||
#define HUE_ERROR_ACTIVE 255
|
||||
|
||||
//Segment option byte bits
|
||||
#define SEG_OPTION_SELECTED 0
|
||||
#define SEG_OPTION_REVERSED 1
|
||||
#define SEG_OPTION_ON 2
|
||||
#define SEG_OPTION_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
File diff suppressed because one or more lines are too long
64
wled00/data/liveview.htm
Normal file
64
wled00/data/liveview.htm
Normal file
@@ -0,0 +1,64 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<meta name="theme-color" content="#222222">
|
||||
<title>WLED Live Preview</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
#canv {
|
||||
background: black;
|
||||
filter: brightness(175%);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="canv" />
|
||||
<script>
|
||||
update();
|
||||
|
||||
var tmout = null;
|
||||
function update()
|
||||
{
|
||||
if (document.hidden) {
|
||||
clearTimeout(tmout);
|
||||
tmout = setTimeout(update, 250);
|
||||
return;
|
||||
}
|
||||
fetch('/json/live')
|
||||
.then(res => {
|
||||
if (!res.ok) {
|
||||
clearTimeout(tmout);
|
||||
tmout = setTimeout(update, 2500);
|
||||
}
|
||||
return res.json();
|
||||
})
|
||||
.then(json => {
|
||||
var str = "linear-gradient(90deg,";
|
||||
var len = json.leds.length;
|
||||
for (i = 0; i < len; i++) {
|
||||
var leddata = json.leds[i];
|
||||
if (leddata.length > 6) leddata = leddata.substring(2);
|
||||
str += "#" + leddata;
|
||||
if (i < len -1) str += ","
|
||||
}
|
||||
str += ")";
|
||||
document.getElementById("canv").style.background = str;
|
||||
clearTimeout(tmout);
|
||||
tmout = setTimeout(update, 40);
|
||||
})
|
||||
.catch(function (error) {
|
||||
clearTimeout(tmout);
|
||||
tmout = setTimeout(update, 2500);
|
||||
})
|
||||
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
67
wled00/dmx.cpp
Normal file
67
wled00/dmx.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Support for DMX via MAX485.
|
||||
* Change the output pin in src/dependencies/ESPDMX.cpp if needed.
|
||||
* Library from:
|
||||
* https://github.com/Rickgg/ESP-Dmx
|
||||
*/
|
||||
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
#include "src/dependencies/dmx/ESPDMX.h"
|
||||
DMXESPSerial dmx;
|
||||
|
||||
void handleDMX()
|
||||
{
|
||||
// TODO: calculate brightness manually if no shutter channel is set
|
||||
|
||||
uint8_t brightness = strip.getBrightness();
|
||||
|
||||
for (int i = DMXStartLED; i < ledCount; i++) { // uses the amount of LEDs as fixture count
|
||||
|
||||
uint32_t in = strip.getPixelColor(i); // get the colors for the individual fixtures as suggested by Aircoookie in issue #462
|
||||
byte w = in >> 24 & 0xFF;
|
||||
byte r = in >> 16 & 0xFF;
|
||||
byte g = in >> 8 & 0xFF;
|
||||
byte b = in & 0xFF;
|
||||
|
||||
int DMXFixtureStart = DMXStart + (DMXGap * (i - DMXStartLED));
|
||||
for (int j = 0; j < DMXChannels; j++) {
|
||||
int DMXAddr = DMXFixtureStart + j;
|
||||
switch (DMXFixtureMap[j]) {
|
||||
case 0: // Set this channel to 0. Good way to tell strobe- and fade-functions to fuck right off.
|
||||
dmx.write(DMXAddr, 0);
|
||||
break;
|
||||
case 1: // Red
|
||||
dmx.write(DMXAddr, r);
|
||||
break;
|
||||
case 2: // Green
|
||||
dmx.write(DMXAddr, g);
|
||||
break;
|
||||
case 3: // Blue
|
||||
dmx.write(DMXAddr, b);
|
||||
break;
|
||||
case 4: // White
|
||||
dmx.write(DMXAddr, w);
|
||||
break;
|
||||
case 5: // Shutter channel. Controls the brightness.
|
||||
dmx.write(DMXAddr, brightness);
|
||||
break;
|
||||
case 6: // Sets this channel to 255. Like 0, but more wholesome.
|
||||
dmx.write(DMXAddr, 255);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dmx.update(); // update the DMX bus
|
||||
}
|
||||
|
||||
void initDMX() {
|
||||
dmx.init(512); // initialize with bus length
|
||||
}
|
||||
|
||||
#else
|
||||
void handleDMX() {}
|
||||
void initDMX() {}
|
||||
#endif
|
||||
167
wled00/e131.cpp
Normal file
167
wled00/e131.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* E1.31 handler
|
||||
*/
|
||||
|
||||
void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet){
|
||||
//E1.31 protocol support
|
||||
|
||||
uint16_t uni = 0, dmxChannels = 0;
|
||||
uint8_t* e131_data = nullptr;
|
||||
uint8_t seq = 0, mde = REALTIME_MODE_E131;
|
||||
|
||||
if (isArtnet)
|
||||
{
|
||||
uni = p->art_universe;
|
||||
dmxChannels = htons(p->art_length);
|
||||
e131_data = p->art_data;
|
||||
seq = p->art_sequence_number;
|
||||
mde = REALTIME_MODE_ARTNET;
|
||||
} else {
|
||||
uni = htons(p->universe);
|
||||
dmxChannels = htons(p->property_value_count) -1;
|
||||
e131_data = p->property_values;
|
||||
seq = p->sequence_number;
|
||||
}
|
||||
|
||||
// only listen for universes we're handling & allocated memory
|
||||
if (uni >= (e131Universe + E131_MAX_UNIVERSE_COUNT)) return;
|
||||
|
||||
uint8_t previousUniverses = uni - e131Universe;
|
||||
uint16_t possibleLEDsInCurrentUniverse;
|
||||
|
||||
if (e131SkipOutOfSequence)
|
||||
if (seq < e131LastSequenceNumber[uni-e131Universe] && seq > 20 && e131LastSequenceNumber[uni-e131Universe] < 250){
|
||||
DEBUG_PRINT("skipping E1.31 frame (last seq=");
|
||||
DEBUG_PRINT(e131LastSequenceNumber[uni-e131Universe]);
|
||||
DEBUG_PRINT(", current seq=");
|
||||
DEBUG_PRINT(seq);
|
||||
DEBUG_PRINT(", universe=");
|
||||
DEBUG_PRINT(uni);
|
||||
DEBUG_PRINTLN(")");
|
||||
return;
|
||||
}
|
||||
e131LastSequenceNumber[uni-e131Universe] = seq;
|
||||
|
||||
// update status info
|
||||
realtimeIP = clientIP;
|
||||
byte wChannel = 0;
|
||||
|
||||
switch (DMXMode) {
|
||||
case DMX_MODE_DISABLED:
|
||||
return; // nothing to do
|
||||
break;
|
||||
|
||||
case DMX_MODE_SINGLE_RGB:
|
||||
if (uni != e131Universe) return;
|
||||
if (dmxChannels-DMXAddress+1 < 3) return;
|
||||
realtimeLock(realtimeTimeoutMs, mde);
|
||||
if (realtimeOverride) return;
|
||||
wChannel = (dmxChannels-DMXAddress+1 > 3) ? e131_data[DMXAddress+3] : 0;
|
||||
for (uint16_t i = 0; i < ledCount; i++)
|
||||
setRealtimePixel(i, e131_data[DMXAddress+0], e131_data[DMXAddress+1], e131_data[DMXAddress+2], wChannel);
|
||||
break;
|
||||
|
||||
case DMX_MODE_SINGLE_DRGB:
|
||||
if (uni != e131Universe) return;
|
||||
if (dmxChannels-DMXAddress+1 < 4) return;
|
||||
realtimeLock(realtimeTimeoutMs, mde);
|
||||
if (realtimeOverride) return;
|
||||
wChannel = (dmxChannels-DMXAddress+1 > 4) ? e131_data[DMXAddress+4] : 0;
|
||||
if (DMXOldDimmer != e131_data[DMXAddress+0]) {
|
||||
DMXOldDimmer = e131_data[DMXAddress+0];
|
||||
bri = e131_data[DMXAddress+0];
|
||||
strip.setBrightness(bri);
|
||||
}
|
||||
for (uint16_t i = 0; i < ledCount; i++)
|
||||
setRealtimePixel(i, e131_data[DMXAddress+1], e131_data[DMXAddress+2], e131_data[DMXAddress+3], wChannel);
|
||||
break;
|
||||
|
||||
case DMX_MODE_EFFECT:
|
||||
if (uni != e131Universe) return;
|
||||
if (dmxChannels-DMXAddress+1 < 11) return;
|
||||
if (DMXOldDimmer != e131_data[DMXAddress+0]) {
|
||||
DMXOldDimmer = e131_data[DMXAddress+0];
|
||||
bri = e131_data[DMXAddress+0];
|
||||
}
|
||||
if (e131_data[DMXAddress+1] < MODE_COUNT)
|
||||
effectCurrent = e131_data[DMXAddress+ 1];
|
||||
effectSpeed = e131_data[DMXAddress+ 2]; // flickers
|
||||
effectIntensity = e131_data[DMXAddress+ 3];
|
||||
effectPalette = e131_data[DMXAddress+ 4];
|
||||
col[0] = e131_data[DMXAddress+ 5];
|
||||
col[1] = e131_data[DMXAddress+ 6];
|
||||
col[2] = e131_data[DMXAddress+ 7];
|
||||
colSec[0] = e131_data[DMXAddress+ 8];
|
||||
colSec[1] = e131_data[DMXAddress+ 9];
|
||||
colSec[2] = e131_data[DMXAddress+10];
|
||||
if (dmxChannels-DMXAddress+1 > 11)
|
||||
{
|
||||
col[3] = e131_data[DMXAddress+11]; //white
|
||||
colSec[3] = e131_data[DMXAddress+12];
|
||||
}
|
||||
transitionDelayTemp = 0; // act fast
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION); // don't send UDP
|
||||
return; // don't activate realtime live mode
|
||||
break;
|
||||
|
||||
case DMX_MODE_MULTIPLE_RGB:
|
||||
realtimeLock(realtimeTimeoutMs, mde);
|
||||
if (realtimeOverride) return;
|
||||
if (previousUniverses == 0) {
|
||||
// first universe of this fixture
|
||||
possibleLEDsInCurrentUniverse = (dmxChannels - DMXAddress + 1) / 3;
|
||||
for (uint16_t i = 0; i < ledCount; i++) {
|
||||
if (i >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
|
||||
setRealtimePixel(i, e131_data[DMXAddress+i*3+0], e131_data[DMXAddress+i*3+1], e131_data[DMXAddress+i*3+2], 0);
|
||||
}
|
||||
} else if (previousUniverses > 0 && uni < (e131Universe + E131_MAX_UNIVERSE_COUNT)) {
|
||||
// additional universe(s) of this fixture
|
||||
uint16_t numberOfLEDsInPreviousUniverses = ((512 - DMXAddress + 1) / 3); // first universe
|
||||
if (previousUniverses > 1) numberOfLEDsInPreviousUniverses += (512 / 3) * (previousUniverses - 1); // extended universe(s) before current
|
||||
possibleLEDsInCurrentUniverse = dmxChannels / 3;
|
||||
for (uint16_t i = numberOfLEDsInPreviousUniverses; i < ledCount; i++) {
|
||||
uint8_t j = i - numberOfLEDsInPreviousUniverses;
|
||||
if (j >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
|
||||
setRealtimePixel(i, e131_data[j*3+1], e131_data[j*3+2], e131_data[j*3+3], 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DMX_MODE_MULTIPLE_DRGB:
|
||||
realtimeLock(realtimeTimeoutMs, mde);
|
||||
if (realtimeOverride) return;
|
||||
if (previousUniverses == 0) {
|
||||
// first universe of this fixture
|
||||
if (DMXOldDimmer != e131_data[DMXAddress+0]) {
|
||||
DMXOldDimmer = e131_data[DMXAddress+0];
|
||||
bri = e131_data[DMXAddress+0];
|
||||
strip.setBrightness(bri);
|
||||
}
|
||||
possibleLEDsInCurrentUniverse = (dmxChannels - DMXAddress) / 3;
|
||||
for (uint16_t i = 0; i < ledCount; i++) {
|
||||
if (i >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
|
||||
setRealtimePixel(i, e131_data[DMXAddress+i*3+1], e131_data[DMXAddress+i*3+2], e131_data[DMXAddress+i*3+3], 0);
|
||||
}
|
||||
} else if (previousUniverses > 0 && uni < (e131Universe + E131_MAX_UNIVERSE_COUNT)) {
|
||||
// additional universe(s) of this fixture
|
||||
uint16_t numberOfLEDsInPreviousUniverses = ((512 - DMXAddress + 1) / 3); // first universe
|
||||
if (previousUniverses > 1) numberOfLEDsInPreviousUniverses += (512 / 3) * (previousUniverses - 1); // extended universe(s) before current
|
||||
possibleLEDsInCurrentUniverse = dmxChannels / 3;
|
||||
for (uint16_t i = numberOfLEDsInPreviousUniverses; i < ledCount; i++) {
|
||||
uint8_t j = i - numberOfLEDsInPreviousUniverses;
|
||||
if (j >= possibleLEDsInCurrentUniverse) break; // more LEDs will follow in next universe(s)
|
||||
setRealtimePixel(i, e131_data[j*3+1], e131_data[j*3+2], e131_data[j*3+3], 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_PRINTLN("unknown E1.31 DMX mode");
|
||||
return; // nothing to do
|
||||
break;
|
||||
}
|
||||
|
||||
e131NewData = true;
|
||||
}
|
||||
184
wled00/fcn_declare.h
Normal file
184
wled00/fcn_declare.h
Normal file
@@ -0,0 +1,184 @@
|
||||
#ifndef WLED_FCN_DECLARE_H
|
||||
#define WLED_FCN_DECLARE_H
|
||||
#include <Arduino.h>
|
||||
#include "src/dependencies/espalexa/EspalexaDevice.h"
|
||||
#include "src/dependencies/e131/ESPAsyncE131.h"
|
||||
|
||||
/*
|
||||
* All globally accessible functions are declared here
|
||||
*/
|
||||
|
||||
//alexa.cpp
|
||||
void onAlexaChange(EspalexaDevice* dev);
|
||||
void alexaInit();
|
||||
void handleAlexa();
|
||||
void onAlexaChange(EspalexaDevice* dev);
|
||||
|
||||
//blynk.cpp
|
||||
void initBlynk(const char* auth);
|
||||
void handleBlynk();
|
||||
void updateBlynk();
|
||||
|
||||
//button.cpp
|
||||
void shortPressAction();
|
||||
void handleButton();
|
||||
void handleIO();
|
||||
|
||||
//colors.cpp
|
||||
void colorFromUint32(uint32_t in, bool secondary = false);
|
||||
void colorFromUint24(uint32_t in, bool secondary = false);
|
||||
void relativeChangeWhite(int8_t amount, byte lowerBoundary = 0);
|
||||
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb); //hue, sat to rgb
|
||||
void colorCTtoRGB(uint16_t mired, byte* rgb); //white spectrum to rgb
|
||||
|
||||
void colorXYtoRGB(float x, float y, byte* rgb); // only defined if huesync disabled TODO
|
||||
void colorRGBtoXY(byte* rgb, float* xy); // only defined if huesync disabled TODO
|
||||
|
||||
void colorFromDecOrHexString(byte* rgb, char* in);
|
||||
void colorRGBtoRGBW(byte* rgb); //rgb to rgbw (http://codewelt.com/rgbw). (RGBW_MODE_LEGACY)
|
||||
|
||||
//dmx.cpp
|
||||
void initDMX();
|
||||
void handleDMX();
|
||||
|
||||
//e131.cpp
|
||||
void handleE131Packet(e131_packet_t* p, IPAddress clientIP, bool isArtnet);
|
||||
|
||||
//file.cpp
|
||||
bool handleFileRead(AsyncWebServerRequest*, String path);
|
||||
|
||||
//hue.cpp
|
||||
void handleHue();
|
||||
void reconnectHue();
|
||||
void onHueError(void* arg, AsyncClient* client, int8_t error);
|
||||
void onHueConnect(void* arg, AsyncClient* client);
|
||||
void sendHuePoll();
|
||||
void onHueData(void* arg, AsyncClient* client, void *data, size_t len);
|
||||
|
||||
//ir.cpp
|
||||
bool decodeIRCustom(uint32_t code);
|
||||
void relativeChange(byte* property, int8_t amount, byte lowerBoundary = 0, byte higherBoundary = 0xFF);
|
||||
void changeEffectSpeed(int8_t amount);
|
||||
void changeEffectIntensity(int8_t amount);
|
||||
void decodeIR(uint32_t code);
|
||||
void decodeIR24(uint32_t code);
|
||||
void decodeIR24OLD(uint32_t code);
|
||||
void decodeIR24CT(uint32_t code);
|
||||
void decodeIR40(uint32_t code);
|
||||
void decodeIR44(uint32_t code);
|
||||
void decodeIR21(uint32_t code);
|
||||
void decodeIR6(uint32_t code);
|
||||
|
||||
void initIR();
|
||||
void handleIR();
|
||||
|
||||
//json.cpp
|
||||
#include "ESPAsyncWebServer.h"
|
||||
#include "src/dependencies/json/ArduinoJson-v6.h"
|
||||
#include "src/dependencies/json/AsyncJson-v6.h"
|
||||
#include "FX.h"
|
||||
// TODO: AsynicWebServerRequest conflict?
|
||||
|
||||
void deserializeSegment(JsonObject elem, byte it);
|
||||
bool deserializeState(JsonObject root);
|
||||
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id);
|
||||
void serializeState(JsonObject root);
|
||||
void serializeInfo(JsonObject root);
|
||||
void serveJson(AsyncWebServerRequest* request);
|
||||
void serveLiveLeds(AsyncWebServerRequest* request);
|
||||
|
||||
//led.cpp
|
||||
void setValuesFromMainSeg();
|
||||
void resetTimebase();
|
||||
void toggleOnOff();
|
||||
void setAllLeds();
|
||||
void setLedsStandard(bool justColors = false);
|
||||
bool colorChanged();
|
||||
void colorUpdated(int callMode);
|
||||
void updateInterfaces(uint8_t callMode);
|
||||
void handleTransitions();
|
||||
void handleNightlight();
|
||||
|
||||
//mqtt.cpp
|
||||
bool initMqtt();
|
||||
void publishMqtt();
|
||||
|
||||
//ntp.cpp
|
||||
void handleNetworkTime();
|
||||
void sendNTPPacket();
|
||||
bool checkNTPResponse();
|
||||
void updateLocalTime();
|
||||
void getTimeString(char* out);
|
||||
bool checkCountdown();
|
||||
void setCountdown();
|
||||
byte weekdayMondayFirst();
|
||||
void checkTimers();
|
||||
|
||||
//overlay.cpp
|
||||
void initCronixie();
|
||||
void handleOverlays();
|
||||
void handleOverlayDraw();
|
||||
void _overlayAnalogCountdown();
|
||||
void _overlayAnalogClock();
|
||||
|
||||
byte getSameCodeLength(char code, int index, char const cronixieDisplay[]);
|
||||
void setCronixie();
|
||||
void _overlayCronixie();
|
||||
void _drawOverlayCronixie();
|
||||
|
||||
//set.cpp
|
||||
void _setRandomColor(bool _sec,bool fromButton=false);
|
||||
bool isAsterisksOnly(const char* str, byte maxLen);
|
||||
void handleSettingsSet(AsyncWebServerRequest *request, byte subPage);
|
||||
bool handleSet(AsyncWebServerRequest *request, const String& req);
|
||||
int getNumVal(const String* req, uint16_t pos);
|
||||
bool updateVal(const String* req, const char* key, byte* val, byte minv=0, byte maxv=255);
|
||||
|
||||
//udp.cpp
|
||||
void notify(byte callMode, bool followUp=false);
|
||||
void realtimeLock(uint32_t timeoutMs, byte md = REALTIME_MODE_GENERIC);
|
||||
void handleNotifications();
|
||||
void setRealtimePixel(uint16_t i, byte r, byte g, byte b, byte w);
|
||||
|
||||
//usermod.cpp
|
||||
void userSetup();
|
||||
void userConnected();
|
||||
void userLoop();
|
||||
|
||||
//wled_eeprom.cpp
|
||||
void commit();
|
||||
void clearEEPROM();
|
||||
void writeStringToEEPROM(uint16_t pos, char* str, uint16_t len);
|
||||
void readStringFromEEPROM(uint16_t pos, char* str, uint16_t len);
|
||||
void saveSettingsToEEPROM();
|
||||
void loadSettingsFromEEPROM(bool first);
|
||||
void savedToPresets();
|
||||
bool applyPreset(byte index, bool loadBri = true);
|
||||
void savePreset(byte index, bool persist = true);
|
||||
void loadMacro(byte index, char* m);
|
||||
void applyMacro(byte index);
|
||||
void saveMacro(byte index, String mc, bool persist = true); //only commit on single save, not in settings
|
||||
|
||||
//wled_serial.cpp
|
||||
void handleSerial();
|
||||
|
||||
//wled_server.cpp
|
||||
bool isIp(String str);
|
||||
bool captivePortal(AsyncWebServerRequest *request);
|
||||
void initServer();
|
||||
void serveIndexOrWelcome(AsyncWebServerRequest *request);
|
||||
void serveIndex(AsyncWebServerRequest* request);
|
||||
String msgProcessor(const String& var);
|
||||
void serveMessage(AsyncWebServerRequest* request, uint16_t code, String headl, String subl="", byte optionT=255);
|
||||
String settingsProcessor(const String& var);
|
||||
String dmxProcessor(const String& var);
|
||||
void serveSettings(AsyncWebServerRequest* request);
|
||||
|
||||
//xml.cpp
|
||||
char* XML_response(AsyncWebServerRequest *request, char* dest = nullptr);
|
||||
char* URL_response(AsyncWebServerRequest *request);
|
||||
void sappend(char stype, const char* key, int val);
|
||||
void sappends(char stype, const char* key, char* val);
|
||||
void getSettingsJS(byte subPage, char* dest);
|
||||
|
||||
#endif
|
||||
@@ -1,41 +1,17 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Utility for SPIFFS filesystem & Serial console
|
||||
* Utility for SPIFFS filesystem
|
||||
*/
|
||||
void handleSerial()
|
||||
{
|
||||
if (Serial.available() > 0) //support for Adalight protocol to high-speed control LEDs over serial
|
||||
{
|
||||
if (!Serial.find("Ada")) return;
|
||||
|
||||
if (!realtimeActive && bri == 0) strip.setBrightness(briLast);
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
|
||||
yield();
|
||||
byte hi = Serial.read();
|
||||
byte ledc = Serial.read();
|
||||
byte chk = Serial.read();
|
||||
if(chk != (hi ^ ledc ^ 0x55)) return;
|
||||
if (ledCount < ledc) ledc = ledCount;
|
||||
|
||||
byte sc[3]; int t =-1; int to = 0;
|
||||
for (int i=0; i < ledc; i++)
|
||||
{
|
||||
for (byte j=0; j<3; j++)
|
||||
{
|
||||
while (Serial.peek()<0) //no data yet available
|
||||
{
|
||||
yield();
|
||||
to++;
|
||||
if (to>15) {strip.show(); return;} //unexpected end of transmission
|
||||
}
|
||||
to = 0;
|
||||
sc[j] = Serial.read();
|
||||
}
|
||||
setRealtimePixel(i,sc[0],sc[1],sc[2],0);
|
||||
}
|
||||
strip.show();
|
||||
}
|
||||
}
|
||||
|
||||
//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
|
||||
@@ -1,657 +0,0 @@
|
||||
/*
|
||||
* Binary arrays for the classic desktop UI index page.
|
||||
* gzip is used for smaller size and improved speeds.
|
||||
*
|
||||
* Workflow for creating them from HTML source:
|
||||
* 1. Minify HTML (https://htmlcompressor.com/compressor/) (optional)
|
||||
* 2. Compress with gzip (https://online-converting.com/archives/convert-to-gzip/)
|
||||
* 3. Convert gzip binary to c array (https://littlevgl.com/image-to-c-array) (select RAW as color format)
|
||||
* alternative: https://sourceforge.net/projects/bin2header/
|
||||
* 4. update length value
|
||||
*/
|
||||
|
||||
const uint16_t PAGE_index_L = 10256;
|
||||
|
||||
const uint8_t PAGE_index[] PROGMEM = {
|
||||
0x1f, 0x8b, 0x08, 0x08, 0x58, 0x17, 0x80, 0x5c, 0x00, 0x03, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65,
|
||||
0x73, 0x73, 0x65, 0x64, 0x20, 0x28, 0x31, 0x34, 0x29, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x00, 0xcc,
|
||||
0x5a, 0xe9, 0x72, 0xdb, 0x46, 0xb6, 0xfe, 0xaf, 0xa7, 0x80, 0xe9, 0x4a, 0x4c, 0x46, 0x04, 0x88,
|
||||
0x9d, 0x00, 0x29, 0x28, 0x65, 0x2b, 0xde, 0xaa, 0x1c, 0x45, 0x65, 0x69, 0x62, 0xa5, 0x32, 0x29,
|
||||
0x17, 0x88, 0x85, 0xc4, 0x18, 0x04, 0x68, 0x00, 0xa4, 0xa4, 0x30, 0x7a, 0xf7, 0xf9, 0x4e, 0x77,
|
||||
0x93, 0x04, 0xa8, 0x8d, 0xf4, 0x64, 0xe6, 0x5e, 0x57, 0x19, 0x40, 0xf7, 0x39, 0xdd, 0x67, 0x5f,
|
||||
0xba, 0xa9, 0xa3, 0x67, 0x3f, 0xfd, 0x72, 0x72, 0xf1, 0xdb, 0xd9, 0x6b, 0x69, 0x52, 0x4d, 0xd3,
|
||||
0xe3, 0x23, 0xf1, 0x8c, 0xfc, 0xf0, 0xf8, 0x68, 0x1a, 0x55, 0xbe, 0x14, 0x4c, 0xfc, 0xa2, 0x8c,
|
||||
0x2a, 0x6f, 0x5e, 0xc5, 0xb2, 0x23, 0xe6, 0x32, 0x7f, 0x1a, 0x79, 0xd5, 0x24, 0x9a, 0x46, 0x72,
|
||||
0x90, 0xa7, 0x79, 0x21, 0x05, 0x79, 0x56, 0x45, 0x59, 0xe5, 0x3d, 0x8f, 0xe3, 0xf8, 0xf8, 0x28,
|
||||
0x4d, 0xb2, 0x2f, 0x52, 0x11, 0xa5, 0xde, 0x8b, 0x72, 0x92, 0x17, 0x55, 0x30, 0xaf, 0xa4, 0x04,
|
||||
0x18, 0x2f, 0xa4, 0xea, 0x66, 0x16, 0x79, 0xc9, 0xd4, 0x1f, 0x47, 0xbd, 0x6b, 0x99, 0xa6, 0xa4,
|
||||
0x49, 0x11, 0xc5, 0xde, 0x8b, 0x5e, 0xec, 0x2f, 0x68, 0xa8, 0xe0, 0xf1, 0xa2, 0x77, 0x7c, 0x54,
|
||||
0x25, 0x55, 0x1a, 0x1d, 0x7f, 0xfa, 0xf0, 0xfa, 0x27, 0x49, 0x55, 0x1c, 0xc5, 0x3c, 0xea, 0xf1,
|
||||
0x19, 0xe9, 0xa8, 0x0c, 0x8a, 0x64, 0x56, 0x1d, 0x2f, 0xfc, 0x42, 0x0a, 0xbd, 0x30, 0x0f, 0xe6,
|
||||
0x53, 0x90, 0x1d, 0xd2, 0xf0, 0xca, 0xbb, 0x4a, 0xb2, 0x30, 0xbf, 0x52, 0xc6, 0x51, 0x75, 0x92,
|
||||
0x4f, 0x67, 0xf3, 0x2a, 0x0a, 0xcf, 0xab, 0x9b, 0x34, 0x6a, 0x87, 0xca, 0xd7, 0x79, 0x54, 0xdc,
|
||||
0x9c, 0x47, 0x69, 0x14, 0x54, 0x79, 0xd1, 0x6e, 0x91, 0x8c, 0xad, 0x4e, 0x67, 0x58, 0x44, 0xe5,
|
||||
0xcc, 0x6b, 0xb5, 0xd8, 0xf2, 0x2c, 0xf5, 0xbd, 0xd8, 0x4f, 0xcb, 0x88, 0x8f, 0x8a, 0xc6, 0xa8,
|
||||
0xac, 0x8f, 0xca, 0x2a, 0xaf, 0x8d, 0xe6, 0x57, 0x8b, 0x3a, 0x6c, 0x14, 0x7b, 0x55, 0x31, 0xe7,
|
||||
0x83, 0x38, 0x29, 0xca, 0x2a, 0xcd, 0xfd, 0x70, 0x33, 0x95, 0xfa, 0x65, 0x55, 0x5e, 0x7b, 0x2a,
|
||||
0xdf, 0xf6, 0xbc, 0xf2, 0xab, 0x48, 0x0c, 0x82, 0x85, 0xf8, 0x48, 0xa7, 0xe2, 0x23, 0xbe, 0x4e,
|
||||
0x56, 0x5f, 0xb3, 0xf5, 0xd7, 0x75, 0xe6, 0x69, 0x43, 0xff, 0x84, 0xb8, 0x1e, 0xb1, 0x67, 0xc8,
|
||||
0x9e, 0xf1, 0x3c, 0x0b, 0xaa, 0x04, 0xfa, 0x1c, 0xbf, 0x0f, 0xdb, 0x65, 0xe7, 0x60, 0x59, 0x44,
|
||||
0xd5, 0xbc, 0xc8, 0xa4, 0x90, 0xb4, 0xf1, 0x3a, 0x8d, 0x48, 0x4b, 0xaf, 0x6e, 0x18, 0x6c, 0x78,
|
||||
0x7b, 0xb0, 0xc6, 0xfe, 0xc7, 0x49, 0x9e, 0xb6, 0x81, 0x8d, 0x0d, 0x99, 0xde, 0xce, 0x8a, 0x7c,
|
||||
0x16, 0x15, 0xd5, 0xcd, 0xaf, 0x7e, 0x3a, 0x8f, 0xda, 0x2d, 0x59, 0xf6, 0x81, 0xd0, 0xea, 0x10,
|
||||
0xa9, 0xfb, 0xe1, 0x23, 0x0e, 0x0f, 0x1f, 0x82, 0x87, 0x02, 0xbe, 0x6d, 0x01, 0xf2, 0xa2, 0xdf,
|
||||
0xb7, 0xbd, 0xe8, 0x8f, 0x56, 0x47, 0x81, 0xa7, 0xbd, 0xac, 0xaa, 0x22, 0x19, 0xc1, 0x7c, 0xed,
|
||||
0x96, 0x70, 0xab, 0x56, 0x77, 0x74, 0xd2, 0xe0, 0x1b, 0x8a, 0x2b, 0xaa, 0xf9, 0x8c, 0x58, 0xff,
|
||||
0x46, 0xd3, 0x73, 0xc9, 0x87, 0x27, 0xbf, 0xb6, 0xd5, 0xce, 0x10, 0x44, 0xdf, 0x83, 0x50, 0xb1,
|
||||
0xf0, 0xd3, 0xf6, 0xdb, 0xf7, 0xbf, 0x74, 0x2d, 0x55, 0xc5, 0x2c, 0xbe, 0xda, 0x0c, 0x76, 0x91,
|
||||
0x4c, 0xa3, 0x7c, 0x5e, 0xb5, 0x57, 0xe4, 0xdb, 0x9d, 0x65, 0x9c, 0xa4, 0x69, 0x7c, 0x4d, 0x6b,
|
||||
0x6f, 0xbb, 0xba, 0xaa, 0x3e, 0x81, 0xa6, 0x11, 0x9a, 0x45, 0x68, 0x35, 0x19, 0xd8, 0xf6, 0x07,
|
||||
0xcb, 0x2c, 0x0f, 0xfc, 0x60, 0x12, 0x79, 0xad, 0xef, 0xd7, 0x5f, 0x87, 0x3f, 0xfb, 0xd5, 0x44,
|
||||
0x29, 0x7c, 0x88, 0x34, 0x6d, 0x77, 0x7e, 0xd0, 0x54, 0xf6, 0x8f, 0xd9, 0xbf, 0x88, 0x20, 0x4f,
|
||||
0x59, 0x79, 0x59, 0x74, 0x25, 0x5d, 0xfe, 0xfc, 0xe1, 0x5d, 0x55, 0xcd, 0x3e, 0xf2, 0xa9, 0x36,
|
||||
0xb9, 0x33, 0xfb, 0x52, 0xf2, 0xac, 0x40, 0xf8, 0xde, 0x94, 0xe4, 0x5d, 0x88, 0xde, 0x6c, 0x1c,
|
||||
0x79, 0x1b, 0x9e, 0x0e, 0x96, 0x49, 0xdc, 0xae, 0x26, 0x49, 0xa9, 0x30, 0x24, 0xee, 0x82, 0x9e,
|
||||
0xd9, 0x59, 0x4f, 0xd3, 0xb2, 0x79, 0xe9, 0x79, 0x24, 0x56, 0x0d, 0xb7, 0x9c, 0xe5, 0x59, 0x19,
|
||||
0x81, 0xe6, 0x33, 0x2f, 0x9b, 0xa7, 0x69, 0x67, 0x19, 0x2a, 0x27, 0xb1, 0x72, 0xfe, 0x52, 0x59,
|
||||
0x90, 0xad, 0xbd, 0x6d, 0xac, 0x9a, 0xdf, 0x95, 0xaf, 0x6e, 0x2e, 0xfc, 0xf1, 0x29, 0x8c, 0xdd,
|
||||
0x7e, 0xe1, 0x07, 0x2f, 0x3a, 0xbf, 0xab, 0x7f, 0x28, 0xc1, 0x24, 0x49, 0xc3, 0xd3, 0x3c, 0x8c,
|
||||
0x4a, 0x1a, 0x65, 0xf8, 0x60, 0x2e, 0x33, 0xe4, 0x9b, 0x7e, 0xdc, 0x6f, 0xd3, 0x20, 0xdd, 0x65,
|
||||
0xd3, 0xb7, 0xdf, 0xb0, 0xa9, 0xf6, 0xd4, 0xa6, 0xaf, 0xbe, 0x61, 0x53, 0xfd, 0xe1, 0x4d, 0xef,
|
||||
0x51, 0xf7, 0x03, 0x3b, 0x5d, 0x2d, 0x1e, 0x95, 0xf9, 0xd8, 0x53, 0x57, 0x16, 0xfa, 0xb4, 0x1f,
|
||||
0x8b, 0x4f, 0x6c, 0x3c, 0xa4, 0x7c, 0xc7, 0xd2, 0xd9, 0x6d, 0x84, 0xa4, 0xb7, 0xdc, 0xa4, 0x3f,
|
||||
0xb8, 0x36, 0x12, 0xd6, 0x8e, 0x54, 0xe2, 0xeb, 0xc7, 0xa9, 0x50, 0xc6, 0xdb, 0x75, 0xab, 0xd9,
|
||||
0x2e, 0xd6, 0xbf, 0xdc, 0x4f, 0x0b, 0xe5, 0x13, 0xfc, 0xb1, 0x4d, 0xdf, 0xef, 0xb9, 0x69, 0xf2,
|
||||
0xc4, 0xa6, 0x54, 0x82, 0x76, 0xb5, 0x7f, 0x26, 0x7c, 0x3e, 0xc9, 0xb2, 0xa8, 0x78, 0x77, 0xf1,
|
||||
0xf3, 0x87, 0xce, 0x33, 0x4f, 0xfd, 0x91, 0x0c, 0x33, 0xe0, 0xe6, 0x80, 0x2b, 0xad, 0xeb, 0x8f,
|
||||
0x70, 0x85, 0xd3, 0x13, 0x90, 0x8e, 0x82, 0x2f, 0x51, 0xb8, 0x3b, 0x99, 0xf8, 0x09, 0x32, 0x5c,
|
||||
0xbb, 0xa7, 0xfb, 0x29, 0x22, 0x0b, 0x77, 0x31, 0xd9, 0xc5, 0x9e, 0x9b, 0x56, 0x4f, 0x6d, 0xba,
|
||||
0x6a, 0x17, 0xc4, 0x62, 0x64, 0x3a, 0x94, 0x08, 0xaa, 0x38, 0xab, 0xb2, 0xb5, 0xae, 0x78, 0xdd,
|
||||
0x5d, 0xe3, 0xd9, 0x7f, 0x94, 0x66, 0x67, 0x57, 0xa2, 0xa3, 0xbd, 0x88, 0x8e, 0xfe, 0x1e, 0xa2,
|
||||
0xc1, 0x5e, 0x44, 0x1f, 0x4f, 0xdc, 0x3b, 0x13, 0x0d, 0xf7, 0x22, 0xfa, 0xb8, 0x9f, 0xec, 0x4c,
|
||||
0xb4, 0xdc, 0x8b, 0xe8, 0xfc, 0xef, 0x21, 0x5a, 0xed, 0x45, 0xf4, 0x71, 0xe7, 0xdd, 0xdd, 0xa6,
|
||||
0x6f, 0xb2, 0xdd, 0x69, 0xc6, 0x4f, 0xd0, 0xdc, 0xf4, 0x48, 0x33, 0x3a, 0x02, 0xa0, 0x45, 0xda,
|
||||
0x35, 0x6d, 0x4c, 0x9f, 0x30, 0x5c, 0x47, 0x54, 0x0f, 0x84, 0xf9, 0xc5, 0x25, 0x64, 0xa0, 0xee,
|
||||
0x2c, 0x0a, 0xdf, 0x67, 0x61, 0x74, 0xed, 0xa1, 0x8a, 0x0c, 0x79, 0x72, 0xdd, 0x9a, 0x9f, 0x25,
|
||||
0x54, 0x63, 0xd6, 0x3d, 0x35, 0xcf, 0x3f, 0xeb, 0x1e, 0x5a, 0x7c, 0xec, 0x9c, 0xd8, 0x8a, 0xfb,
|
||||
0x12, 0x9b, 0x36, 0x58, 0x6d, 0x74, 0xb8, 0xfb, 0x4e, 0xe5, 0x7d, 0x3b, 0xe9, 0xd8, 0x29, 0x6c,
|
||||
0xae, 0x38, 0x41, 0xf3, 0x5f, 0xb2, 0x35, 0x2d, 0x28, 0x24, 0x68, 0x35, 0x57, 0xed, 0x9a, 0xe6,
|
||||
0xc2, 0x6d, 0x72, 0xc3, 0x7f, 0xfc, 0x0a, 0x23, 0xdd, 0xe2, 0xdf, 0x41, 0x23, 0xe7, 0xd3, 0x56,
|
||||
0x87, 0x68, 0x2b, 0xdf, 0x5f, 0xb4, 0x0e, 0xd6, 0x9d, 0xe1, 0x2c, 0xca, 0xda, 0xad, 0xb7, 0xaf,
|
||||
0x2f, 0x5a, 0xdd, 0x16, 0x5a, 0xe6, 0xd6, 0x21, 0x43, 0x12, 0x8d, 0x67, 0x97, 0xd2, 0xfa, 0xa6,
|
||||
0x8b, 0x2c, 0xa3, 0x2c, 0x6c, 0xb3, 0x56, 0x6f, 0x7d, 0x4e, 0xaa, 0x77, 0xaf, 0x27, 0x6d, 0x76,
|
||||
0xca, 0xe0, 0x34, 0x5e, 0xa2, 0x69, 0xad, 0x75, 0x83, 0xc3, 0xd5, 0xfc, 0x47, 0x31, 0xff, 0x71,
|
||||
0x6b, 0xfe, 0xad, 0x98, 0x7f, 0xbb, 0x35, 0xff, 0x4a, 0xcc, 0x8b, 0xb6, 0x8a, 0x8a, 0x18, 0x1a,
|
||||
0x8c, 0xb5, 0x28, 0x9f, 0x04, 0x58, 0xb4, 0x34, 0x5c, 0x72, 0xde, 0xa6, 0xd7, 0x59, 0xbb, 0xac,
|
||||
0xb3, 0xf6, 0xe6, 0x92, 0x2f, 0xda, 0xf6, 0xb3, 0x35, 0xcd, 0x73, 0x81, 0xb0, 0x6a, 0x11, 0xd6,
|
||||
0x80, 0xf7, 0x02, 0xb0, 0x2a, 0xf3, 0x0f, 0x91, 0x8b, 0xaa, 0x8f, 0x6f, 0x5f, 0xad, 0x8e, 0x22,
|
||||
0x45, 0x77, 0xdc, 0x1d, 0x75, 0x93, 0x6e, 0xdc, 0x9d, 0x75, 0xbf, 0x76, 0xf9, 0xc9, 0x74, 0xe2,
|
||||
0xf1, 0x82, 0xf6, 0x8e, 0xef, 0xd3, 0x2d, 0xc5, 0xf8, 0x5c, 0x8c, 0x17, 0x9e, 0x6e, 0x59, 0xc3,
|
||||
0xc4, 0x63, 0x6d, 0x7f, 0x9c, 0xe6, 0x38, 0xa7, 0x4c, 0x7e, 0xb0, 0x3b, 0xc3, 0xd8, 0xc3, 0x4b,
|
||||
0x4e, 0x86, 0x33, 0x6f, 0xf1, 0x43, 0x5b, 0x93, 0x71, 0x74, 0xfb, 0xca, 0xbf, 0xe2, 0x1f, 0xf0,
|
||||
0x5d, 0xf1, 0x6f, 0x1a, 0x76, 0x68, 0x5c, 0x5e, 0x25, 0x55, 0x30, 0x69, 0x27, 0xdf, 0xd9, 0x9d,
|
||||
0x65, 0xe0, 0x97, 0x91, 0xa4, 0x0e, 0x0a, 0x6f, 0xd1, 0x1d, 0x7b, 0x55, 0x77, 0xe4, 0xcd, 0x86,
|
||||
0x23, 0xb4, 0xfb, 0x5f, 0x86, 0x0c, 0xa0, 0x01, 0xf0, 0x15, 0x80, 0xc5, 0x36, 0x40, 0x07, 0x60,
|
||||
0x26, 0x00, 0x55, 0x1d, 0x60, 0x08, 0xc0, 0x57, 0x00, 0x16, 0x75, 0x80, 0x09, 0x40, 0x05, 0xc0,
|
||||
0x6c, 0x1b, 0x60, 0x09, 0xe2, 0x04, 0xf8, 0x0a, 0x75, 0x35, 0x1b, 0xfb, 0x62, 0xab, 0x27, 0x1f,
|
||||
0x6f, 0xb5, 0xd3, 0xa3, 0x21, 0xf9, 0x57, 0x43, 0xcb, 0x67, 0x0d, 0xa3, 0x9e, 0x71, 0xd3, 0xbc,
|
||||
0x39, 0xdb, 0x32, 0xea, 0x1d, 0xeb, 0x20, 0x79, 0x2d, 0xf8, 0x99, 0x07, 0xc7, 0xf6, 0xce, 0x49,
|
||||
0x9a, 0x97, 0xd1, 0x79, 0x54, 0x55, 0x49, 0x36, 0x2e, 0x81, 0x48, 0xa7, 0xe5, 0x56, 0x99, 0xbe,
|
||||
0xa4, 0x83, 0x27, 0x4b, 0xa7, 0x61, 0x52, 0xce, 0x52, 0xff, 0xc6, 0x6b, 0x65, 0x79, 0x16, 0xb5,
|
||||
0x04, 0xbc, 0x18, 0x8f, 0x1e, 0x47, 0x98, 0x94, 0x8f, 0xc3, 0xd3, 0x4f, 0x8f, 0xc2, 0xab, 0xf4,
|
||||
0xf2, 0x09, 0xf8, 0xd9, 0x13, 0xf0, 0xd3, 0x87, 0xe0, 0x90, 0x7b, 0x71, 0xa4, 0xb3, 0x73, 0x1c,
|
||||
0x05, 0xd2, 0xc3, 0xec, 0x8c, 0xd2, 0x3c, 0xf8, 0xd2, 0x7a, 0x44, 0x21, 0x02, 0xe1, 0xf6, 0x40,
|
||||
0xf8, 0xd9, 0x62, 0xed, 0x65, 0x8f, 0x28, 0x49, 0x2c, 0x62, 0x57, 0x1a, 0x0d, 0x07, 0x7c, 0x58,
|
||||
0x6f, 0x9b, 0x25, 0x5a, 0xd3, 0x35, 0x1f, 0x56, 0x85, 0x58, 0xd2, 0xf0, 0xd7, 0x87, 0x15, 0x7b,
|
||||
0x17, 0xdb, 0x1c, 0x3c, 0xac, 0xc6, 0xb5, 0xd8, 0xc1, 0x02, 0x0e, 0x3e, 0x0d, 0x47, 0x02, 0x81,
|
||||
0x4e, 0xf6, 0x5e, 0x3b, 0x9d, 0x1e, 0xab, 0x9d, 0x1f, 0xfd, 0x93, 0x41, 0x78, 0x52, 0x77, 0x3a,
|
||||
0xe8, 0x42, 0x9f, 0x44, 0xd7, 0xed, 0x22, 0x0a, 0xbb, 0xe3, 0x22, 0x8a, 0xb2, 0xee, 0x88, 0xaa,
|
||||
0x1e, 0x4f, 0x10, 0xe3, 0x91, 0x47, 0xa3, 0xbf, 0xda, 0x0c, 0x72, 0x74, 0xe4, 0x74, 0xfe, 0x22,
|
||||
0xc4, 0xa3, 0x23, 0xcd, 0xa6, 0x4c, 0x4b, 0xd7, 0x36, 0x2f, 0x9e, 0xbf, 0x38, 0x6c, 0xab, 0xd7,
|
||||
0xe2, 0xe0, 0x7f, 0x88, 0x25, 0x1d, 0xa5, 0xca, 0xcf, 0xab, 0x02, 0x6e, 0xdb, 0x06, 0x9a, 0x52,
|
||||
0xa6, 0x49, 0x10, 0xb5, 0xb5, 0x4e, 0x8d, 0x66, 0x0a, 0x58, 0xe1, 0x87, 0x6d, 0x96, 0x80, 0x3a,
|
||||
0xe2, 0xfe, 0xa7, 0x85, 0xd9, 0xc8, 0x2f, 0x64, 0x82, 0x24, 0x28, 0x24, 0xed, 0xd6, 0xe1, 0xe8,
|
||||
0xe4, 0x10, 0xc9, 0xff, 0x70, 0xcd, 0x22, 0x43, 0x3f, 0x6c, 0x75, 0x1a, 0xd9, 0x9d, 0x32, 0xdd,
|
||||
0x01, 0x0e, 0x0d, 0xa3, 0x3c, 0xbc, 0x11, 0x02, 0x8f, 0xfc, 0xe0, 0xcb, 0xb8, 0xc8, 0xe7, 0x59,
|
||||
0xe8, 0xad, 0x48, 0xd5, 0x22, 0xba, 0x5b, 0x8b, 0xe6, 0x6e, 0x2d, 0x92, 0xd9, 0xc5, 0xc8, 0xbb,
|
||||
0xf3, 0xdd, 0x50, 0xe3, 0xeb, 0xa6, 0x76, 0x59, 0x4e, 0xd8, 0xce, 0xdb, 0x1b, 0x85, 0x67, 0x69,
|
||||
0x13, 0x1d, 0xc7, 0xa7, 0x35, 0xa8, 0x7a, 0x10, 0x24, 0xdc, 0x97, 0x57, 0x79, 0x08, 0x59, 0x77,
|
||||
0xe2, 0x19, 0x12, 0xb0, 0xb6, 0xf6, 0x01, 0xb6, 0x14, 0x2b, 0xd6, 0x20, 0xfd, 0x0e, 0xe8, 0xae,
|
||||
0x4f, 0xdf, 0xb3, 0x85, 0xbf, 0xeb, 0x16, 0xfa, 0xb7, 0x70, 0xe1, 0x9f, 0xdc, 0xe3, 0xf8, 0xfb,
|
||||
0x71, 0xe1, 0x93, 0xf3, 0x56, 0xe3, 0xa6, 0xca, 0x6a, 0xe5, 0x7c, 0xa3, 0xf2, 0x78, 0x76, 0xb9,
|
||||
0x15, 0x20, 0xed, 0x07, 0x4c, 0x24, 0x02, 0x67, 0x20, 0xf2, 0x50, 0x9c, 0xc7, 0xdb, 0xbb, 0xdf,
|
||||
0x59, 0x65, 0x9b, 0x6b, 0x32, 0xd3, 0xe2, 0x29, 0xec, 0x23, 0xed, 0x9e, 0xb8, 0xbb, 0x18, 0x5f,
|
||||
0x88, 0x0b, 0xae, 0x26, 0xf7, 0x9b, 0xc2, 0x71, 0xe1, 0xa9, 0xad, 0x61, 0xfd, 0xde, 0x4a, 0xe5,
|
||||
0x9d, 0x68, 0x1d, 0x43, 0xa7, 0x50, 0xb8, 0xbf, 0xd6, 0x9f, 0x5f, 0xbd, 0xb9, 0x64, 0xd7, 0xab,
|
||||
0xec, 0xfa, 0xd6, 0xbb, 0x87, 0xaf, 0xc3, 0x92, 0x72, 0x6e, 0xe6, 0x79, 0xb2, 0xf6, 0xd7, 0x5f,
|
||||
0x78, 0xc5, 0xd7, 0x59, 0x87, 0xc7, 0xe2, 0xf0, 0xbe, 0x66, 0x37, 0x63, 0xd8, 0x47, 0x6a, 0xe7,
|
||||
0x3e, 0xa0, 0xca, 0x80, 0xc7, 0xb4, 0xc5, 0x7d, 0x60, 0xd6, 0x2e, 0x4c, 0x93, 0xac, 0x6d, 0x5b,
|
||||
0x5d, 0xe0, 0xc8, 0x1a, 0x18, 0xbe, 0x6c, 0xf2, 0x7b, 0x31, 0x7e, 0x77, 0xfe, 0x4a, 0xa8, 0x24,
|
||||
0xa0, 0x42, 0x70, 0xb0, 0xc4, 0xbb, 0xf3, 0x23, 0xbb, 0xf6, 0x1c, 0xe0, 0xa9, 0xad, 0x3b, 0xf1,
|
||||
0x5f, 0x91, 0xcc, 0xa8, 0x8d, 0xac, 0x0b, 0x4b, 0x91, 0x72, 0x76, 0xde, 0xbe, 0x66, 0xb9, 0x80,
|
||||
0xca, 0xed, 0x1b, 0xa1, 0xb5, 0xf5, 0x79, 0xa0, 0x31, 0xdd, 0x39, 0xbc, 0x26, 0x8e, 0x1b, 0x73,
|
||||
0xb0, 0x53, 0x73, 0xa9, 0x76, 0x07, 0xe5, 0x58, 0xb7, 0xb6, 0x70, 0x74, 0xab, 0x2e, 0xc4, 0xd9,
|
||||
0xcb, 0x6a, 0x53, 0xfb, 0xf9, 0xd2, 0x57, 0xeb, 0x9b, 0x0c, 0x78, 0xda, 0xf7, 0x67, 0x2f, 0x3d,
|
||||
0x0d, 0x9e, 0x46, 0x6f, 0x58, 0xb7, 0x8e, 0x77, 0xd2, 0xc4, 0x3b, 0x11, 0x78, 0x27, 0xdb, 0x78,
|
||||
0x6f, 0x9a, 0x78, 0x97, 0x02, 0xef, 0x92, 0xf0, 0xea, 0x9c, 0x9c, 0xc3, 0x21, 0x4a, 0xea, 0x27,
|
||||
0x18, 0x4f, 0x24, 0x09, 0x1b, 0xad, 0x7c, 0xe7, 0xec, 0xdc, 0x5b, 0xed, 0xdb, 0x10, 0x68, 0xdb,
|
||||
0xc7, 0xce, 0x3e, 0x3c, 0x84, 0x77, 0x70, 0xc7, 0xe5, 0x7e, 0x41, 0xcb, 0xbe, 0xe9, 0x58, 0x0e,
|
||||
0x96, 0xf4, 0xeb, 0x03, 0xbb, 0x7f, 0x2b, 0x9b, 0x39, 0x0e, 0x41, 0x1c, 0x84, 0xaf, 0xee, 0xef,
|
||||
0x02, 0xca, 0x2a, 0xde, 0x06, 0x24, 0x19, 0x95, 0x06, 0xd6, 0x20, 0x94, 0xa3, 0xb8, 0xc3, 0x30,
|
||||
0x8a, 0xc0, 0x6b, 0xf5, 0x4a, 0x41, 0x0b, 0xab, 0x46, 0xf1, 0xe6, 0x6a, 0x6f, 0xdd, 0x4f, 0x35,
|
||||
0x3b, 0x28, 0xce, 0x0f, 0xc7, 0xda, 0x62, 0x28, 0xbc, 0x97, 0xa1, 0x15, 0xdd, 0x7b, 0x58, 0xe2,
|
||||
0xbc, 0x36, 0xbc, 0xf7, 0xbc, 0xbd, 0xe9, 0xdd, 0x0e, 0x96, 0xdb, 0xdd, 0x1b, 0xf7, 0xdc, 0xa6,
|
||||
0x82, 0x1a, 0x1e, 0x7c, 0x31, 0x3e, 0x65, 0x3f, 0x6f, 0xd0, 0xc5, 0xda, 0x33, 0x3c, 0x58, 0x3c,
|
||||
0xa1, 0x14, 0xac, 0x0d, 0x71, 0x0a, 0x43, 0x1c, 0x36, 0xae, 0xb0, 0xd6, 0xdd, 0xff, 0xe9, 0xc5,
|
||||
0x1a, 0x74, 0xd1, 0x00, 0xb5, 0xb7, 0xee, 0xd2, 0xc8, 0x63, 0x4e, 0xdf, 0x70, 0x8f, 0xc1, 0x9b,
|
||||
0x3c, 0x86, 0xf1, 0x55, 0xa3, 0xa1, 0x3e, 0x9c, 0x51, 0xc0, 0x22, 0xe3, 0x90, 0x1f, 0x3a, 0x0f,
|
||||
0x19, 0x87, 0xec, 0xfb, 0xd8, 0xe8, 0xac, 0xcf, 0xb6, 0x0f, 0xd4, 0xac, 0xf5, 0x09, 0xe6, 0xd4,
|
||||
0x53, 0xbf, 0xff, 0x78, 0x4a, 0x64, 0x9a, 0x5d, 0xfe, 0x16, 0x5c, 0x6b, 0x6d, 0x35, 0xfb, 0x1b,
|
||||
0xb8, 0x76, 0x77, 0xbd, 0x71, 0x07, 0xae, 0x3d, 0x2c, 0x06, 0xaf, 0xf2, 0xa2, 0xc3, 0x41, 0x4f,
|
||||
0x81, 0xa6, 0x62, 0xd4, 0x2d, 0x3c, 0xbf, 0x18, 0xb3, 0x3b, 0x0b, 0x3a, 0xfe, 0xf7, 0x70, 0xc8,
|
||||
0xc1, 0x81, 0x60, 0x33, 0xa5, 0xf1, 0xa9, 0x51, 0x6d, 0x4a, 0xe7, 0x53, 0x93, 0x6e, 0x89, 0x43,
|
||||
0x11, 0xcf, 0x6f, 0xfe, 0xaa, 0x47, 0xe9, 0x86, 0x49, 0x1c, 0x7b, 0x0b, 0x79, 0x9d, 0xf6, 0x6a,
|
||||
0xd3, 0xc1, 0xe6, 0x07, 0x8e, 0x60, 0xd5, 0xfb, 0xb4, 0x17, 0x72, 0xd0, 0xe9, 0xd9, 0x3d, 0x82,
|
||||
0x1f, 0x6a, 0x3d, 0x7d, 0x78, 0xcb, 0x32, 0x0f, 0x6d, 0x42, 0x97, 0xe3, 0x13, 0xaf, 0x5c, 0x25,
|
||||
0xff, 0x25, 0x0e, 0x64, 0x98, 0xee, 0x2d, 0x86, 0x45, 0xc1, 0xbe, 0x82, 0x76, 0x81, 0xb3, 0xc1,
|
||||
0x58, 0x7c, 0x8f, 0x3b, 0xc3, 0xd1, 0x48, 0x7c, 0x8f, 0x58, 0xd0, 0x17, 0x9e, 0xe7, 0x2d, 0x68,
|
||||
0x8b, 0xd1, 0x48, 0x1e, 0x8f, 0xf9, 0x26, 0x12, 0xe6, 0xc7, 0xab, 0xf9, 0xb6, 0xd6, 0x33, 0x3a,
|
||||
0x87, 0x45, 0x21, 0x8f, 0x46, 0x1b, 0xe8, 0x68, 0x0d, 0xd5, 0x09, 0x3a, 0x1e, 0xcb, 0x45, 0x31,
|
||||
0x64, 0x87, 0xf6, 0xc9, 0x11, 0x31, 0x74, 0x88, 0xdc, 0xb8, 0x46, 0x9e, 0x1c, 0x6b, 0x98, 0x92,
|
||||
0x69, 0x8a, 0xa1, 0x94, 0x28, 0x63, 0x8d, 0x53, 0xa4, 0x37, 0x19, 0x36, 0x4e, 0x91, 0x5e, 0xd9,
|
||||
0x08, 0xd3, 0xf3, 0x76, 0x42, 0xc1, 0x29, 0xce, 0x84, 0xf7, 0xf8, 0xcc, 0xa7, 0x87, 0x9c, 0xe5,
|
||||
0xd5, 0x43, 0x5e, 0xf2, 0x71, 0xcb, 0x81, 0x6a, 0x0e, 0x72, 0xb6, 0xd5, 0x4f, 0xaf, 0x01, 0x27,
|
||||
0xad, 0xad, 0x43, 0xe1, 0x66, 0x33, 0x16, 0x14, 0x77, 0x1c, 0x69, 0x7e, 0xf2, 0x5b, 0x7b, 0x9d,
|
||||
0x5f, 0x1b, 0xa9, 0xfc, 0xb7, 0x7a, 0xc0, 0x9d, 0xfc, 0xc6, 0x03, 0x0e, 0xef, 0x75, 0x2a, 0x47,
|
||||
0x5e, 0xd5, 0xf8, 0xb1, 0xf0, 0x4c, 0xdb, 0x0a, 0xe6, 0x33, 0x5d, 0x00, 0xf4, 0x6d, 0xc0, 0x85,
|
||||
0x00, 0xac, 0x62, 0xfc, 0x0e, 0x43, 0x1f, 0xeb, 0xe7, 0xce, 0x33, 0x16, 0xcb, 0x77, 0x70, 0xc4,
|
||||
0xcf, 0x7c, 0xf1, 0x0c, 0xa8, 0x91, 0xd7, 0x3a, 0xca, 0x67, 0x34, 0x7d, 0xfc, 0xba, 0x28, 0xf2,
|
||||
0x42, 0xa2, 0xcb, 0x18, 0xe4, 0x26, 0x34, 0xe8, 0x65, 0xf5, 0xec, 0xa8, 0x27, 0x60, 0xad, 0x61,
|
||||
0x94, 0x7a, 0xf1, 0xec, 0x47, 0x76, 0x88, 0x1d, 0xb0, 0xf2, 0x3e, 0x8c, 0x23, 0x32, 0x16, 0x26,
|
||||
0x5f, 0xf4, 0xfe, 0x55, 0xe6, 0x59, 0x6f, 0xe6, 0xa7, 0x2f, 0x06, 0xe2, 0x3b, 0x8a, 0xe3, 0x17,
|
||||
0x38, 0x04, 0x4c, 0x22, 0xf8, 0x7d, 0x54, 0x7a, 0xc7, 0x94, 0x15, 0x9f, 0xe1, 0x4b, 0xc9, 0xbf,
|
||||
0x74, 0x96, 0x51, 0x5a, 0xbb, 0x47, 0xa2, 0x74, 0x2d, 0x7e, 0xfd, 0x25, 0x38, 0xad, 0x26, 0x6e,
|
||||
0xc5, 0x62, 0x1a, 0x62, 0x35, 0xc5, 0xe9, 0x35, 0xfb, 0xe1, 0x38, 0x2f, 0xda, 0x89, 0x94, 0x64,
|
||||
0x12, 0x01, 0x3a, 0xcb, 0xeb, 0xc3, 0x35, 0xfb, 0x12, 0x77, 0xab, 0x7f, 0xb6, 0x5a, 0x87, 0xc9,
|
||||
0x61, 0xeb, 0x9f, 0xad, 0xe3, 0xd6, 0x21, 0xe1, 0xfc, 0x9e, 0xfc, 0x71, 0xd8, 0x92, 0xda, 0x6c,
|
||||
0xb2, 0x53, 0x13, 0xe7, 0xf6, 0xa0, 0xc1, 0xc5, 0x35, 0xe4, 0xbb, 0x73, 0x81, 0xf7, 0x63, 0x3c,
|
||||
0x4b, 0x06, 0x74, 0xbf, 0x47, 0xcc, 0x43, 0x5b, 0xf4, 0x6b, 0x36, 0xed, 0xa9, 0xa4, 0x51, 0x36,
|
||||
0xae, 0x26, 0xe2, 0x26, 0xab, 0xa3, 0x04, 0x3e, 0x53, 0xc4, 0xe6, 0x77, 0xd4, 0x6d, 0x01, 0x3b,
|
||||
0xb7, 0x47, 0x3d, 0xf1, 0x97, 0x00, 0xd2, 0x11, 0x2b, 0x23, 0xc7, 0x83, 0x22, 0xcf, 0xab, 0x25,
|
||||
0xbf, 0xbf, 0x1f, 0x3c, 0x0f, 0xdd, 0x91, 0xa1, 0xa9, 0x43, 0x7e, 0xb3, 0x3e, 0x78, 0xae, 0x8e,
|
||||
0x8c, 0xc0, 0x0a, 0x87, 0xfc, 0xce, 0x7b, 0xf0, 0x5c, 0x0b, 0xf5, 0xbe, 0xa1, 0x0d, 0xf9, 0x6d,
|
||||
0xf4, 0xe0, 0xb9, 0xa1, 0x3b, 0x41, 0x40, 0xc3, 0x92, 0x23, 0xab, 0xb4, 0xb0, 0x6a, 0x82, 0x82,
|
||||
0x37, 0xd9, 0xe0, 0xd7, 0xa8, 0x08, 0xfd, 0xcc, 0xbf, 0x55, 0x82, 0xaa, 0x48, 0x3f, 0x8f, 0xf2,
|
||||
0xeb, 0xe5, 0x14, 0xa9, 0x2b, 0xc9, 0x06, 0xfe, 0xbc, 0xca, 0x87, 0x57, 0x49, 0x58, 0x4d, 0x06,
|
||||
0x8e, 0xba, 0xb8, 0x1a, 0x6e, 0xce, 0x4a, 0xfc, 0x87, 0xed, 0x01, 0xd4, 0xdd, 0xe6, 0xc4, 0x3b,
|
||||
0xc3, 0x59, 0x5e, 0x26, 0x24, 0xd6, 0xc0, 0x1f, 0x95, 0x79, 0x3a, 0xaf, 0xa2, 0x61, 0x95, 0xcf,
|
||||
0x06, 0x96, 0xf5, 0xdd, 0x30, 0x8d, 0xe2, 0x6a, 0x60, 0xa9, 0xdf, 0x0d, 0xab, 0xc2, 0xcf, 0x4a,
|
||||
0x58, 0x66, 0x3a, 0x60, 0x5f, 0x29, 0xb2, 0x7e, 0x5b, 0x06, 0xa0, 0x4b, 0x0f, 0x9c, 0x93, 0x92,
|
||||
0xb4, 0x8a, 0x8a, 0x41, 0x58, 0xe4, 0x33, 0xb9, 0x9c, 0xf8, 0x61, 0x7e, 0x05, 0xe8, 0xec, 0x5a,
|
||||
0x62, 0x0f, 0xfa, 0xcf, 0xc9, 0x91, 0x34, 0x9d, 0xce, 0xad, 0x52, 0x86, 0xe5, 0x92, 0x33, 0x87,
|
||||
0x03, 0xe5, 0x77, 0xc3, 0x49, 0x94, 0x8c, 0x27, 0xd5, 0x40, 0xd3, 0x17, 0x93, 0x21, 0xe7, 0x5f,
|
||||
0x26, 0x06, 0x30, 0x04, 0x6a, 0x2a, 0x44, 0x92, 0x19, 0x2f, 0x4c, 0x2e, 0x31, 0x51, 0xb0, 0x55,
|
||||
0xf5, 0x19, 0xb1, 0x4a, 0x08, 0xde, 0xef, 0x2f, 0xae, 0x6e, 0x9f, 0x97, 0xe9, 0xcb, 0x65, 0x0d,
|
||||
0xac, 0x02, 0xbc, 0x51, 0xc6, 0x60, 0xfb, 0x34, 0x5a, 0xe5, 0x12, 0xdb, 0x16, 0xc7, 0x63, 0x20,
|
||||
0x75, 0x6f, 0xa2, 0x34, 0xcd, 0xaf, 0x3a, 0xb4, 0xcb, 0xc7, 0xe5, 0xee, 0xcb, 0x70, 0x78, 0x66,
|
||||
0x6b, 0xde, 0xee, 0xb1, 0x86, 0x9d, 0xbd, 0xd9, 0xaa, 0x57, 0x7b, 0xac, 0x62, 0xa7, 0x78, 0x5a,
|
||||
0xf4, 0x69, 0x8f, 0x45, 0x57, 0x93, 0xa4, 0xe2, 0xab, 0xde, 0xed, 0xb4, 0x8a, 0x2e, 0x0d, 0xf2,
|
||||
0x82, 0x7e, 0xb5, 0x17, 0x0a, 0x11, 0x57, 0x08, 0xc1, 0x8d, 0xcf, 0xef, 0x11, 0xba, 0x8b, 0x24,
|
||||
0x4f, 0xa3, 0x6a, 0x2d, 0xf7, 0xf9, 0x4e, 0xdb, 0x62, 0x93, 0x9b, 0x9a, 0xd8, 0xa7, 0x7b, 0x48,
|
||||
0x80, 0x5c, 0xf2, 0x75, 0x9e, 0x27, 0x25, 0x97, 0xe2, 0x62, 0x8f, 0x95, 0x2b, 0x8b, 0x2a, 0x55,
|
||||
0x9e, 0xa7, 0xe5, 0x7f, 0xec, 0x5b, 0x97, 0xdf, 0xa4, 0xf6, 0xf7, 0xfb, 0xfa, 0x12, 0xdd, 0x7a,
|
||||
0x2c, 0xe3, 0x3c, 0xab, 0xe4, 0xd8, 0x9f, 0x26, 0xe9, 0xcd, 0x2a, 0x7c, 0xdf, 0x64, 0x9d, 0xee,
|
||||
0xbb, 0x28, 0x5d, 0x44, 0x55, 0x12, 0xf8, 0xdd, 0x12, 0x91, 0x29, 0x97, 0x51, 0x91, 0xc4, 0xc3,
|
||||
0x2a, 0xba, 0xae, 0x64, 0x3f, 0x4d, 0xc6, 0xd9, 0x20, 0x88, 0xe8, 0x0f, 0x49, 0x1e, 0x73, 0x7a,
|
||||
0xbe, 0x19, 0xe5, 0xa5, 0x0e, 0x27, 0xda, 0x59, 0x87, 0x24, 0x85, 0xa7, 0x48, 0x29, 0x6a, 0x3d,
|
||||
0x89, 0x14, 0xd1, 0x2c, 0xf2, 0xab, 0x41, 0x96, 0x8b, 0xaf, 0x3a, 0xcc, 0xaf, 0x2a, 0x3f, 0x98,
|
||||
0x50, 0xfb, 0x34, 0x88, 0x93, 0xeb, 0x28, 0x1c, 0xd6, 0x33, 0x0e, 0x25, 0xb1, 0xce, 0x2d, 0xfd,
|
||||
0xcd, 0xcb, 0xb2, 0x46, 0xe3, 0x36, 0x89, 0x0b, 0x7f, 0x1a, 0x2d, 0x45, 0xe7, 0x3d, 0xa0, 0xc6,
|
||||
0x7b, 0x38, 0xca, 0x8b, 0x10, 0x49, 0x45, 0xdd, 0x2f, 0xbb, 0x0c, 0x1f, 0xc8, 0x80, 0x82, 0x9a,
|
||||
0x4d, 0x09, 0xe0, 0x3f, 0x4e, 0x78, 0xb7, 0xe5, 0x62, 0xcc, 0xfe, 0x94, 0x46, 0x48, 0x15, 0xb2,
|
||||
0x3c, 0x2a, 0x52, 0x9a, 0xbe, 0xa1, 0xa6, 0xa9, 0x0b, 0xf4, 0x85, 0x7b, 0xa6, 0xc7, 0x24, 0x9b,
|
||||
0xcd, 0xab, 0xe5, 0x7e, 0x42, 0x3f, 0xe0, 0x1b, 0x1b, 0x8f, 0xb8, 0x1d, 0xcd, 0xab, 0x2a, 0xcf,
|
||||
0xea, 0x8e, 0x57, 0x33, 0x7b, 0xc3, 0x44, 0x5c, 0x18, 0xa1, 0x7d, 0xc5, 0x0a, 0x26, 0x12, 0x94,
|
||||
0x94, 0x84, 0x52, 0x1d, 0x5f, 0x04, 0xc5, 0x28, 0xc7, 0xa6, 0xd3, 0x81, 0x06, 0x9d, 0xfe, 0xdd,
|
||||
0xfc, 0xf2, 0x4a, 0xbd, 0x0b, 0xbf, 0xd5, 0x0e, 0xfc, 0xfe, 0xdd, 0xdc, 0x31, 0x1b, 0xfd, 0xce,
|
||||
0xfe, 0x78, 0x30, 0x9b, 0x4f, 0x47, 0x51, 0xf1, 0xc7, 0xdf, 0xc5, 0x29, 0x77, 0x22, 0x23, 0x9a,
|
||||
0xd6, 0x69, 0xb0, 0xe4, 0xfb, 0xc7, 0x52, 0xbe, 0x8a, 0x46, 0x5f, 0x12, 0x04, 0xf6, 0x0c, 0x31,
|
||||
0x87, 0xb9, 0x20, 0xe2, 0x91, 0x22, 0x5c, 0x5e, 0x36, 0x21, 0x88, 0x7a, 0x77, 0xdd, 0x20, 0xce,
|
||||
0x83, 0x79, 0xb9, 0xcc, 0xe7, 0x15, 0x45, 0xfe, 0xe0, 0x3e, 0x8c, 0xc1, 0x6a, 0xeb, 0x12, 0xfc,
|
||||
0x44, 0x85, 0x5c, 0xcc, 0xb3, 0xcc, 0x1f, 0xa5, 0x91, 0x0c, 0xef, 0x0f, 0xbe, 0x3c, 0x54, 0xac,
|
||||
0x83, 0x79, 0x51, 0x42, 0xb8, 0x59, 0x9e, 0x6c, 0xa7, 0x98, 0x9a, 0x44, 0x3b, 0x50, 0xab, 0x26,
|
||||
0xd0, 0xe1, 0x9e, 0x1e, 0xbf, 0x89, 0xb0, 0x55, 0x4e, 0xd6, 0xb6, 0x6a, 0x3b, 0x47, 0xf7, 0xb9,
|
||||
0x15, 0x9a, 0x9c, 0x3e, 0xae, 0x48, 0x96, 0xeb, 0xe1, 0xd3, 0xf7, 0x72, 0x3e, 0xcd, 0xff, 0x94,
|
||||
0xd9, 0xe0, 0xbf, 0xa5, 0x9a, 0x1a, 0x81, 0xff, 0xb5, 0x5a, 0x76, 0x11, 0xbf, 0xfc, 0x56, 0xb9,
|
||||
0x59, 0x1e, 0x9d, 0xf9, 0x05, 0xfd, 0x75, 0x2c, 0x0f, 0x01, 0xd1, 0x8a, 0xd6, 0x01, 0x77, 0x66,
|
||||
0x1e, 0x62, 0x82, 0x92, 0xaf, 0x8c, 0x4a, 0x1e, 0x15, 0xf5, 0xc0, 0x7b, 0xfe, 0xa4, 0x72, 0xc5,
|
||||
0xca, 0x39, 0x0c, 0xbf, 0xf7, 0x4a, 0x6e, 0x8f, 0xbd, 0xb5, 0x5a, 0x33, 0x09, 0x1d, 0x12, 0xd8,
|
||||
0xd9, 0x40, 0x9c, 0x11, 0xa4, 0x24, 0xf4, 0x26, 0x79, 0x0a, 0x5d, 0xfc, 0x0b, 0x99, 0x85, 0xcd,
|
||||
0x30, 0xaa, 0x54, 0xbe, 0x7b, 0x41, 0x59, 0x1e, 0xaf, 0xf0, 0x8f, 0x7a, 0xfc, 0xef, 0x9f, 0xa9,
|
||||
0x11, 0x90, 0xf2, 0x8c, 0xfd, 0xb9, 0xc1, 0xfa, 0x4f, 0x4e, 0xa5, 0x80, 0x7e, 0xc7, 0xf7, 0x3e,
|
||||
0x7f, 0x46, 0xed, 0x4c, 0xb2, 0xcf, 0xb4, 0xf8, 0xf3, 0xc7, 0xd7, 0x2f, 0x7f, 0xfa, 0xed, 0xf3,
|
||||
0x67, 0x22, 0x34, 0xf3, 0x33, 0x81, 0x41, 0x3f, 0xf2, 0x1f, 0x7f, 0xe0, 0xa7, 0x3f, 0x45, 0x51,
|
||||
0xb0, 0x39, 0x60, 0x84, 0xb2, 0x18, 0x4b, 0x8c, 0x8e, 0x77, 0xb7, 0x32, 0x72, 0x71, 0xd5, 0x95,
|
||||
0x14, 0xea, 0x30, 0x5f, 0x44, 0x45, 0x0c, 0xcd, 0x0f, 0x26, 0x49, 0x18, 0x46, 0x38, 0x94, 0x45,
|
||||
0x45, 0x89, 0x15, 0x9e, 0xa6, 0x68, 0xd2, 0xf5, 0x34, 0xcd, 0x4a, 0x6f, 0x52, 0x55, 0xb3, 0x41,
|
||||
0xaf, 0x77, 0x75, 0x75, 0xa5, 0x5c, 0x19, 0x4a, 0x5e, 0x8c, 0x7b, 0x3a, 0x4e, 0x30, 0x3d, 0x50,
|
||||
0x01, 0xad, 0x30, 0x8a, 0xcb, 0x63, 0xa9, 0xd7, 0xfb, 0xc0, 0x9a, 0x10, 0xfa, 0x13, 0xeb, 0x52,
|
||||
0x09, 0xf2, 0x69, 0x2f, 0x46, 0x23, 0x08, 0x4e, 0x6e, 0xa6, 0xa3, 0x3c, 0x25, 0xb5, 0xa4, 0x59,
|
||||
0x21, 0xcf, 0xc8, 0xbe, 0x32, 0xbf, 0x32, 0x90, 0x16, 0x49, 0x74, 0xf5, 0x2a, 0xc7, 0x11, 0x51,
|
||||
0x95, 0x54, 0x49, 0x53, 0x75, 0x93, 0x3d, 0x5a, 0xc7, 0x47, 0xf4, 0xfb, 0x81, 0x14, 0x7a, 0xad,
|
||||
0x9f, 0x4d, 0xc7, 0x56, 0x4c, 0xc9, 0xd6, 0x4c, 0xc5, 0x0c, 0x64, 0x3c, 0x35, 0xc3, 0x91, 0x54,
|
||||
0x59, 0xb7, 0x14, 0x5b, 0xd6, 0x34, 0xc5, 0xb4, 0x35, 0xfe, 0x4d, 0x8f, 0x85, 0x6c, 0xda, 0xaa,
|
||||
0xe2, 0x04, 0xea, 0x0a, 0x8f, 0x21, 0xe8, 0x0c, 0x26, 0xad, 0xb1, 0x4a, 0x36, 0xe4, 0x20, 0x69,
|
||||
0x0d, 0x5a, 0x88, 0xa5, 0x12, 0x5b, 0xea, 0xca, 0x35, 0xf8, 0x66, 0xfd, 0x9f, 0x60, 0xac, 0x47,
|
||||
0x9c, 0xdd, 0xe1, 0xcf, 0xed, 0xeb, 0x58, 0x2d, 0x83, 0x79, 0xc5, 0xea, 0x83, 0x3f, 0xcd, 0x75,
|
||||
0x65, 0xc3, 0x55, 0x5c, 0xd3, 0x94, 0xf5, 0xbe, 0xa6, 0x58, 0x06, 0x36, 0xd4, 0x15, 0xb3, 0x2f,
|
||||
0x03, 0xcf, 0xd2, 0x9d, 0xd5, 0x4b, 0x4c, 0x6a, 0xb6, 0xa3, 0xb8, 0xf6, 0x6a, 0xc4, 0x17, 0x60,
|
||||
0x13, 0xc7, 0x54, 0x0c, 0xd7, 0x92, 0x74, 0x5b, 0x71, 0x2c, 0x70, 0x64, 0x43, 0x05, 0x7d, 0x47,
|
||||
0xea, 0xf7, 0x15, 0xbb, 0x8f, 0x6d, 0x0d, 0x60, 0xb9, 0xa6, 0x64, 0xba, 0x8a, 0x66, 0xc9, 0x80,
|
||||
0xb9, 0x9a, 0x05, 0xa9, 0xb0, 0x51, 0x9f, 0xb8, 0x37, 0xb0, 0x14, 0xca, 0x74, 0x6d, 0xc5, 0xd6,
|
||||
0x4d, 0x59, 0x33, 0x6c, 0xc5, 0x52, 0x35, 0x09, 0xd3, 0x96, 0x25, 0x9b, 0x8a, 0x6a, 0x98, 0x92,
|
||||
0xde, 0x57, 0x1c, 0xd5, 0x92, 0x0c, 0xc5, 0x76, 0x0c, 0x09, 0x9b, 0x39, 0xa4, 0xb0, 0xbe, 0xa2,
|
||||
0x1b, 0x66, 0x29, 0xf3, 0x49, 0x8e, 0x21, 0xf3, 0x49, 0x81, 0x02, 0x19, 0x49, 0x2e, 0xcb, 0x92,
|
||||
0x4c, 0x4d, 0xb1, 0x2d, 0xe2, 0xa3, 0xaf, 0xf4, 0x55, 0x1d, 0x4b, 0xa1, 0x81, 0xcd, 0xd0, 0xd0,
|
||||
0x5c, 0x45, 0xd5, 0x75, 0xb2, 0xaa, 0x03, 0xa2, 0x2a, 0x34, 0x0e, 0x4e, 0x75, 0xf0, 0x64, 0x18,
|
||||
0x40, 0xac, 0x3f, 0x4b, 0xf6, 0x94, 0x1b, 0x70, 0x99, 0x3d, 0x99, 0x25, 0x6d, 0x45, 0x73, 0xfa,
|
||||
0xb2, 0x8b, 0x6d, 0x2d, 0xa8, 0xa6, 0xaf, 0x18, 0x7d, 0x41, 0x45, 0x93, 0x39, 0x11, 0x12, 0x0f,
|
||||
0x62, 0xe9, 0x5c, 0x2e, 0x59, 0xd7, 0x14, 0xdd, 0x86, 0x4e, 0x1d, 0x45, 0x77, 0x1c, 0xc1, 0xbc,
|
||||
0x2c, 0xe4, 0x23, 0x0c, 0x5d, 0xa0, 0x4b, 0x84, 0xe1, 0x0a, 0x74, 0x2e, 0x5d, 0x9f, 0xa3, 0x5b,
|
||||
0x4c, 0xc7, 0x26, 0x6c, 0x6e, 0x28, 0x1a, 0xe3, 0xbc, 0xaf, 0x98, 0x50, 0x3c, 0x14, 0xee, 0xe8,
|
||||
0x5c, 0xa7, 0x06, 0xde, 0xd0, 0xa9, 0xe9, 0xba, 0x92, 0x05, 0xbf, 0xd1, 0x6c, 0xc9, 0xee, 0x2b,
|
||||
0x9a, 0xc6, 0x57, 0xf6, 0x2d, 0xb6, 0x44, 0x87, 0x1a, 0xc4, 0x90, 0x1b, 0xcb, 0xe1, 0x3e, 0x0e,
|
||||
0x0f, 0xe1, 0xbe, 0x41, 0x7b, 0x41, 0x00, 0x55, 0x17, 0x96, 0x97, 0x84, 0xab, 0x70, 0xe7, 0x90,
|
||||
0xd8, 0xcb, 0x16, 0xce, 0x21, 0x35, 0x9d, 0x83, 0x8f, 0x6a, 0xfe, 0xd8, 0xe3, 0x41, 0x76, 0xbc,
|
||||
0x1d, 0x6d, 0x74, 0x1d, 0xb4, 0x43, 0x94, 0xb9, 0xae, 0x03, 0x2f, 0x76, 0xa0, 0x4f, 0x7d, 0x22,
|
||||
0xf7, 0x6d, 0xe7, 0xa9, 0x50, 0x2b, 0xef, 0x0d, 0xad, 0x09, 0xad, 0xe4, 0x01, 0x04, 0x42, 0x9b,
|
||||
0x38, 0xd3, 0x36, 0x71, 0x56, 0xca, 0xb5, 0x99, 0xc7, 0x23, 0x8b, 0xf3, 0x64, 0xd9, 0xc6, 0xff,
|
||||
0x3b, 0x9e, 0x0c, 0xb5, 0xff, 0x18, 0x4f, 0xfa, 0xb7, 0xf2, 0xa4, 0x7f, 0x13, 0x4f, 0x7d, 0x9b,
|
||||
0x22, 0xc9, 0x72, 0x28, 0x41, 0x9a, 0xba, 0x62, 0x98, 0x94, 0x80, 0x68, 0x52, 0x36, 0x90, 0x31,
|
||||
0xc8, 0x9f, 0xe8, 0x9b, 0x1e, 0x65, 0x6d, 0x42, 0x5a, 0xcf, 0x4a, 0x7c, 0x03, 0x06, 0x92, 0x36,
|
||||
0xa0, 0xda, 0xc4, 0x06, 0xed, 0x4f, 0x4e, 0x4d, 0xb7, 0x6c, 0x2e, 0x39, 0x3c, 0x9e, 0x4b, 0xce,
|
||||
0x04, 0x70, 0xac, 0x0d, 0xa7, 0x25, 0x9f, 0xd8, 0x48, 0xb4, 0x79, 0xc8, 0x35, 0x90, 0x5c, 0x9b,
|
||||
0xd8, 0xa8, 0x4d, 0x7e, 0x54, 0x56, 0x51, 0x0c, 0xee, 0x91, 0x55, 0xdb, 0xc8, 0x8a, 0x79, 0x81,
|
||||
0x70, 0xaf, 0xd0, 0xe5, 0xbd, 0x42, 0x23, 0xff, 0xb3, 0x45, 0xee, 0xa3, 0xd2, 0x5b, 0x9a, 0xfe,
|
||||
0x7f, 0x28, 0xbd, 0xd3, 0x57, 0x9f, 0x96, 0xfe, 0x49, 0x4b, 0x6b, 0x3b, 0x5a, 0x7a, 0xed, 0xe3,
|
||||
0xff, 0x23, 0x59, 0x1f, 0xca, 0x63, 0xd3, 0x9c, 0xae, 0x8a, 0x9f, 0xcc, 0x63, 0x96, 0x6e, 0x82,
|
||||
0x69, 0x9a, 0x25, 0xae, 0x55, 0x45, 0xeb, 0xbb, 0xc4, 0x36, 0x92, 0xa6, 0x6b, 0x3b, 0xb2, 0x65,
|
||||
0x22, 0x83, 0xc3, 0xb6, 0x18, 0xaa, 0x2e, 0x6a, 0x8b, 0x65, 0xa0, 0x8a, 0x94, 0xe2, 0x8d, 0xa2,
|
||||
0xa2, 0xa2, 0x88, 0xae, 0x46, 0x02, 0x89, 0x4a, 0x90, 0x66, 0x29, 0x3a, 0x92, 0x35, 0xca, 0x83,
|
||||
0x8e, 0xed, 0x55, 0x8d, 0x68, 0xdb, 0x8a, 0xeb, 0x22, 0x8d, 0x43, 0x33, 0x16, 0x0a, 0x85, 0x61,
|
||||
0xb0, 0x72, 0x6e, 0xa2, 0xea, 0xda, 0xa8, 0x01, 0x06, 0xab, 0xd0, 0x0e, 0x9a, 0x27, 0x8b, 0x6a,
|
||||
0xb2, 0xab, 0x18, 0xba, 0xc5, 0x72, 0xbc, 0xa1, 0x1b, 0x12, 0x0a, 0x9a, 0x6a, 0xa9, 0x54, 0x91,
|
||||
0x4c, 0xf4, 0x0d, 0xa8, 0x25, 0xb6, 0x29, 0x5b, 0x96, 0x62, 0x92, 0x34, 0xa8, 0x25, 0x26, 0xc8,
|
||||
0x80, 0xb4, 0x0e, 0xad, 0xb9, 0x28, 0x2c, 0x28, 0x50, 0x8a, 0x8b, 0xca, 0xad, 0xab, 0x0c, 0x43,
|
||||
0x55, 0x0c, 0xc3, 0xa6, 0x8e, 0xc0, 0x45, 0x9b, 0x81, 0xfa, 0xa5, 0xeb, 0x25, 0x2a, 0x21, 0x55,
|
||||
0x6e, 0x14, 0x09, 0x94, 0x2a, 0x43, 0x51, 0x6d, 0x94, 0x76, 0x07, 0x5c, 0x22, 0x42, 0xc1, 0x96,
|
||||
0x8a, 0x49, 0x34, 0x07, 0x06, 0x5a, 0x1a, 0xd3, 0x41, 0xed, 0x74, 0x25, 0x0d, 0x1a, 0x47, 0x85,
|
||||
0x5e, 0x0f, 0x5d, 0x83, 0x1b, 0x17, 0x45, 0x0a, 0x45, 0xa9, 0x8f, 0x09, 0x88, 0x0b, 0x36, 0x0d,
|
||||
0xbc, 0x1a, 0x4f, 0x54, 0x38, 0x53, 0x33, 0x49, 0xf3, 0xd8, 0xbf, 0xdf, 0x87, 0x2d, 0x2d, 0xec,
|
||||
0xa0, 0xad, 0x76, 0xe0, 0x1b, 0x3a, 0xe0, 0x5a, 0x53, 0xfb, 0xa8, 0xc5, 0x50, 0x01, 0x71, 0xad,
|
||||
0x19, 0xe8, 0x26, 0x4c, 0xdb, 0x15, 0x4c, 0x71, 0x0e, 0xc9, 0x65, 0x34, 0xea, 0x19, 0x00, 0x36,
|
||||
0x99, 0x1c, 0xa6, 0x10, 0x2a, 0xa0, 0x5d, 0x1d, 0xe4, 0x3d, 0xb2, 0x42, 0xdf, 0xa0, 0x42, 0xe9,
|
||||
0x98, 0x50, 0xa2, 0x0a, 0x19, 0x1c, 0xa1, 0x19, 0x5b, 0x28, 0xca, 0x22, 0x25, 0x6a, 0xb6, 0x2d,
|
||||
0x99, 0xf0, 0x21, 0xf4, 0x40, 0x50, 0x81, 0x85, 0xf8, 0x80, 0x78, 0x30, 0xcd, 0x4a, 0xdd, 0x2b,
|
||||
0xf5, 0xbb, 0x2a, 0xea, 0x26, 0x74, 0x01, 0x19, 0x5d, 0x87, 0xfa, 0x33, 0xc5, 0xa0, 0xd2, 0xbe,
|
||||
0x65, 0x48, 0x31, 0xfe, 0xf3, 0x67, 0xa8, 0x19, 0x1d, 0x54, 0x9f, 0xf0, 0x1d, 0x97, 0x92, 0x1d,
|
||||
0xaa, 0x71, 0xdf, 0xd4, 0xc8, 0xb6, 0xae, 0x83, 0x7c, 0x0e, 0x2a, 0x1a, 0xc0, 0x3a, 0x7c, 0x4c,
|
||||
0x45, 0x73, 0xb6, 0x1a, 0x9b, 0x3a, 0xed, 0x4b, 0x4a, 0xd2, 0x6d, 0xf0, 0x06, 0x0b, 0xeb, 0x54,
|
||||
0xa9, 0x2d, 0xf0, 0x48, 0x5e, 0xd1, 0x78, 0x6a, 0x8e, 0xcb, 0x1a, 0x2b, 0x15, 0xc9, 0x1b, 0x9a,
|
||||
0xd4, 0x4c, 0xd1, 0x06, 0x58, 0xab, 0x5d, 0x56, 0xbb, 0xca, 0x16, 0xa6, 0x89, 0x59, 0x97, 0x9a,
|
||||
0x08, 0x34, 0x99, 0xa4, 0x77, 0xb4, 0x67, 0x2e, 0x03, 0x6a, 0x68, 0x5c, 0x2d, 0x90, 0x5c, 0x0d,
|
||||
0xf1, 0x76, 0xa9, 0xf1, 0x42, 0x64, 0xe9, 0xd0, 0x35, 0x56, 0xab, 0xd4, 0x28, 0x22, 0xca, 0xc1,
|
||||
0xba, 0x01, 0xab, 0x21, 0x73, 0x50, 0x49, 0x72, 0xd1, 0xf1, 0xd8, 0x2e, 0x7b, 0xf5, 0xc5, 0x24,
|
||||
0x35, 0x4f, 0xe4, 0xe0, 0xf6, 0x7a, 0xcc, 0x17, 0x51, 0x32, 0x05, 0x8b, 0x9a, 0xa1, 0xc1, 0xba,
|
||||
0x00, 0xaa, 0x30, 0x25, 0xba, 0x99, 0x26, 0x03, 0x3b, 0x04, 0x71, 0x90, 0x8f, 0x77, 0x88, 0x61,
|
||||
0x03, 0xa6, 0x22, 0xb7, 0x52, 0x41, 0xa6, 0x6f, 0x59, 0x01, 0x22, 0x40, 0x53, 0x29, 0x8c, 0x4d,
|
||||
0x84, 0xa1, 0x23, 0xab, 0xe8, 0xd7, 0x74, 0xd9, 0x26, 0x5f, 0x93, 0xa9, 0xf5, 0x92, 0x61, 0x7d,
|
||||
0xb7, 0xcf, 0x32, 0x8b, 0xa3, 0x1a, 0x64, 0x67, 0x8d, 0xf2, 0x37, 0xec, 0x62, 0x52, 0xab, 0x07,
|
||||
0x87, 0x41, 0x50, 0x23, 0xf2, 0x75, 0x8d, 0x50, 0x5c, 0x1d, 0x49, 0x11, 0x51, 0x81, 0x86, 0xdc,
|
||||
0x26, 0xdf, 0xd4, 0x75, 0x02, 0xb8, 0xd4, 0x1d, 0x53, 0x1e, 0x34, 0x4c, 0x72, 0x47, 0x38, 0x33,
|
||||
0xf4, 0xe0, 0xea, 0xf0, 0x3b, 0x32, 0x9e, 0xcb, 0xda, 0x47, 0xf8, 0x99, 0x18, 0xc1, 0xd1, 0x5d,
|
||||
0x97, 0x34, 0x6c, 0xd9, 0x4c, 0x49, 0xc4, 0x00, 0x29, 0x16, 0xad, 0x9d, 0xd9, 0x7c, 0xc2, 0xbf,
|
||||
0x75, 0xca, 0x9b, 0xd8, 0x59, 0x25, 0x3f, 0x85, 0x55, 0xd7, 0xcb, 0xc5, 0x66, 0x78, 0x69, 0x86,
|
||||
0x21, 0x51, 0x9f, 0x4e, 0xdd, 0x1d, 0x45, 0xaa, 0x04, 0x88, 0x2e, 0xd8, 0xd1, 0x05, 0x6f, 0x48,
|
||||
0x3c, 0x1a, 0xa2, 0x8a, 0x7c, 0x4a, 0xa7, 0xdc, 0x6f, 0xaa, 0x8e, 0xec, 0x90, 0xd7, 0x58, 0x5c,
|
||||
0x36, 0x4d, 0x88, 0x4a, 0xd1, 0x66, 0x18, 0x06, 0x6d, 0xeb, 0x3a, 0x2e, 0xa2, 0xcd, 0x85, 0xb3,
|
||||
0xda, 0x54, 0xd2, 0x24, 0x8d, 0x68, 0x30, 0xcd, 0xe0, 0xc5, 0xda, 0x77, 0x1c, 0x52, 0xc8, 0xde,
|
||||
0x06, 0x73, 0xf3, 0x3e, 0xf6, 0x47, 0xd0, 0xd1, 0xd1, 0x40, 0x8c, 0xd0, 0x73, 0x03, 0x56, 0xca,
|
||||
0x2c, 0x72, 0x41, 0xce, 0x90, 0x19, 0xc0, 0x61, 0x00, 0x53, 0x0d, 0x88, 0x48, 0x9f, 0xc5, 0xba,
|
||||
0xde, 0xa7, 0x90, 0x42, 0x8e, 0xd5, 0x49, 0x66, 0xdb, 0x70, 0x64, 0x8d, 0x0b, 0xc4, 0x88, 0xf5,
|
||||
0x25, 0x61, 0x1b, 0x6e, 0x29, 0x49, 0xd8, 0x86, 0x5b, 0x4a, 0x6a, 0xb0, 0x8f, 0x00, 0xe3, 0xc6,
|
||||
0x61, 0x96, 0x92, 0xb8, 0x75, 0x98, 0xa5, 0x24, 0x6e, 0x1d, 0xae, 0x0e, 0x89, 0x99, 0xc7, 0x60,
|
||||
0xa6, 0x62, 0xad, 0x3b, 0x92, 0x1e, 0xd7, 0xa7, 0xc4, 0xb4, 0xbb, 0x1a, 0x70, 0x03, 0x89, 0xb6,
|
||||
0x7b, 0x65, 0x28, 0xa9, 0x66, 0x22, 0x3a, 0xaa, 0x91, 0x91, 0x6c, 0x99, 0xdb, 0x86, 0x19, 0x8a,
|
||||
0x82, 0x68, 0x63, 0x68, 0x99, 0xab, 0x8d, 0xd9, 0x09, 0x01, 0x02, 0xd3, 0xe8, 0xcc, 0x4e, 0x26,
|
||||
0x05, 0x43, 0xcd, 0x6d, 0x98, 0x6d, 0xb8, 0xa1, 0x6c, 0x96, 0x85, 0x28, 0xa2, 0xb9, 0xa5, 0xa4,
|
||||
0x86, 0x1b, 0x6a, 0xc4, 0x9d, 0x4b, 0x11, 0x09, 0x4b, 0xb1, 0xbc, 0x47, 0xd6, 0x21, 0x4b, 0x49,
|
||||
0x2b, 0x75, 0xd9, 0xfc, 0x65, 0x92, 0x9a, 0x69, 0xe3, 0xbe, 0xca, 0x12, 0xe2, 0xda, 0x52, 0xc8,
|
||||
0xb2, 0xcc, 0x04, 0x62, 0x54, 0xc2, 0x34, 0xdc, 0x48, 0x6c, 0x1e, 0xea, 0xe7, 0x16, 0x0c, 0x40,
|
||||
0xce, 0x61, 0x56, 0xd2, 0x28, 0xd7, 0xda, 0xa6, 0xc5, 0xad, 0x64, 0x71, 0x42, 0x2e, 0xb7, 0x92,
|
||||
0x2b, 0x09, 0xbb, 0x30, 0x2b, 0xe9, 0x12, 0xd9, 0xc5, 0x12, 0x46, 0x12, 0x9c, 0x1b, 0xd2, 0x8a,
|
||||
0x73, 0x8d, 0x25, 0x17, 0x66, 0x24, 0x62, 0x13, 0xa5, 0x80, 0x19, 0x49, 0x75, 0xb8, 0x32, 0x24,
|
||||
0xe1, 0xb4, 0x64, 0x18, 0x9d, 0x5b, 0xc9, 0x66, 0xda, 0x44, 0x46, 0x67, 0x76, 0xea, 0xaf, 0x46,
|
||||
0xab, 0x20, 0x5a, 0xd9, 0xa8, 0x6e, 0x9b, 0xe6, 0x93, 0xd9, 0x87, 0xb2, 0x24, 0xb7, 0x0d, 0x33,
|
||||
0x94, 0x58, 0x2e, 0x0c, 0x25, 0x31, 0xe3, 0x38, 0xdc, 0x52, 0x12, 0x37, 0x0e, 0xb3, 0x94, 0xe0,
|
||||
0xc7, 0x14, 0xcc, 0x31, 0xdb, 0xd8, 0xc2, 0x52, 0x92, 0xc9, 0xb3, 0x2a, 0xb7, 0x14, 0x17, 0x70,
|
||||
0x65, 0x28, 0x89, 0x9b, 0x86, 0x07, 0x11, 0xec, 0xe4, 0x42, 0xb3, 0xdc, 0x4e, 0xc2, 0xb1, 0x85,
|
||||
0xa5, 0x64, 0x61, 0x1b, 0x6e, 0x29, 0x11, 0x1e, 0xc2, 0x52, 0x72, 0xc3, 0x52, 0xa5, 0xb0, 0x0f,
|
||||
0x8e, 0xd5, 0xb5, 0x79, 0x9c, 0xa7, 0x79, 0x0c, 0x49, 0x64, 0x29, 0x89, 0x87, 0x90, 0xc4, 0x43,
|
||||
0x48, 0xaa, 0x53, 0x72, 0x45, 0x7a, 0x13, 0xa6, 0x12, 0xe9, 0x8d, 0x9b, 0x4a, 0x6e, 0xb0, 0xce,
|
||||
0xb2, 0x9b, 0xc5, 0x0d, 0x65, 0xc9, 0xc2, 0x36, 0xdc, 0x52, 0x72, 0x4d, 0x19, 0xba, 0x2c, 0x8c,
|
||||
0xc3, 0x2c, 0x25, 0x37, 0x6c, 0x23, 0xd7, 0x94, 0x8b, 0xd1, 0x2a, 0x88, 0x44, 0xc4, 0xd4, 0xb3,
|
||||
0x9d, 0x30, 0x91, 0xfa, 0xef, 0xd2, 0xae, 0xf7, 0x47, 0x6e, 0x9b, 0x47, 0xff, 0x2b, 0xc2, 0x7b,
|
||||
0x5f, 0xfa, 0x02, 0xf5, 0xd6, 0x92, 0x2d, 0x59, 0x2e, 0xd2, 0x00, 0x4d, 0xee, 0xd2, 0x16, 0xb8,
|
||||
0x04, 0x8b, 0x6c, 0x70, 0xcd, 0x7d, 0x3a, 0x4c, 0xbc, 0x93, 0x1f, 0xc8, 0x64, 0x77, 0xb1, 0xde,
|
||||
0xa4, 0x4d, 0xfe, 0xfa, 0xe3, 0xf3, 0x90, 0x9e, 0xb1, 0x3d, 0xe3, 0x8d, 0x9b, 0x7c, 0xd8, 0xf1,
|
||||
0x68, 0x6d, 0x53, 0x12, 0x45, 0x52, 0xe4, 0x43, 0xda, 0xe3, 0xcc, 0xd2, 0xe9, 0xda, 0x98, 0xb5,
|
||||
0x9b, 0x2e, 0xb4, 0x89, 0x34, 0x16, 0x2a, 0xa9, 0x81, 0x1b, 0x16, 0x8a, 0xc3, 0x19, 0xd4, 0xdb,
|
||||
0xd6, 0x46, 0x57, 0xaa, 0xb0, 0xb5, 0xd1, 0x95, 0xda, 0x9b, 0x08, 0x33, 0xe6, 0x81, 0x74, 0xb1,
|
||||
0x52, 0xc9, 0x4c, 0x9c, 0xae, 0x54, 0x31, 0x16, 0xee, 0x46, 0x2d, 0x5c, 0xb6, 0x95, 0x52, 0x0b,
|
||||
0x17, 0xc7, 0x86, 0x6c, 0xd0, 0x96, 0xdc, 0x17, 0xc0, 0x3c, 0xd4, 0xd6, 0x4d, 0xd4, 0x4b, 0x1c,
|
||||
0x29, 0x89, 0xd9, 0xe1, 0x56, 0x1a, 0x98, 0xc2, 0x01, 0xcb, 0x94, 0xe1, 0xab, 0xc9, 0x48, 0xb1,
|
||||
0x4f, 0xb0, 0xf1, 0xe5, 0xa9, 0x84, 0x06, 0xe6, 0xa0, 0x47, 0x20, 0x14, 0x91, 0xa6, 0x47, 0xf6,
|
||||
0x4c, 0xd1, 0xa0, 0x2a, 0x28, 0x26, 0x25, 0xbe, 0x54, 0xeb, 0xc5, 0x79, 0x93, 0xcd, 0x19, 0xc2,
|
||||
0x0a, 0x30, 0xa1, 0x91, 0x55, 0x08, 0x10, 0x1c, 0x89, 0xf8, 0x4b, 0x42, 0x17, 0xb9, 0x21, 0x94,
|
||||
0x10, 0x5a, 0xdd, 0x7b, 0xea, 0x54, 0x44, 0xf1, 0x4f, 0x68, 0x0a, 0xcb, 0x06, 0x97, 0xd7, 0xb2,
|
||||
0x49, 0xc3, 0xbd, 0x6b, 0xa2, 0x35, 0x64, 0x97, 0xf7, 0x39, 0x28, 0x6a, 0x94, 0x5a, 0x71, 0x74,
|
||||
0xe0, 0x10, 0xd6, 0xf4, 0x66, 0xe1, 0x2f, 0x55, 0xd8, 0xb7, 0xf5, 0x7b, 0x03, 0x07, 0x4d, 0xf5,
|
||||
0x09, 0xe8, 0x46, 0x60, 0x67, 0xbc, 0xdd, 0x3b, 0xd0, 0xca, 0x94, 0xfb, 0x86, 0xa6, 0xac, 0x11,
|
||||
0x0e, 0x07, 0xb9, 0xab, 0x02, 0xfd, 0x94, 0x82, 0xb3, 0xd1, 0xd8, 0xd8, 0x6a, 0x78, 0x47, 0x60,
|
||||
0x7e, 0x80, 0x24, 0x61, 0x46, 0xe2, 0xa2, 0xc9, 0x5c, 0xc4, 0x82, 0x5b, 0x4b, 0xa7, 0x2b, 0xf1,
|
||||
0x88, 0x6a, 0xa8, 0x32, 0xc3, 0xdb, 0xec, 0x87, 0xb3, 0x9d, 0xce, 0xbf, 0x30, 0x66, 0xe8, 0xfc,
|
||||
0x0b, 0x72, 0x23, 0x15, 0xd3, 0x1e, 0x95, 0x01, 0x0e, 0xdc, 0x08, 0xca, 0x80, 0x5a, 0x07, 0x3d,
|
||||
0x30, 0x40, 0x1b, 0xc6, 0x04, 0xf5, 0xf1, 0x53, 0x31, 0x66, 0x86, 0xb1, 0x41, 0x0d, 0xbf, 0x30,
|
||||
0x82, 0xf3, 0x2f, 0x8c, 0x19, 0x23, 0x52, 0xc3, 0xfc, 0x0b, 0xe3, 0x86, 0x32, 0xa0, 0x50, 0x6e,
|
||||
0x4c, 0xd7, 0x46, 0x19, 0xe0, 0x94, 0x1b, 0x3a, 0x7f, 0x37, 0x9d, 0xbf, 0x35, 0xfb, 0x81, 0x01,
|
||||
0xc5, 0xc0, 0x0f, 0x95, 0x06, 0xe3, 0x56, 0x67, 0x1c, 0x80, 0x47, 0x8c, 0x25, 0xa5, 0x38, 0x38,
|
||||
0xb2, 0xa3, 0xb6, 0x2e, 0x6d, 0x01, 0x94, 0x01, 0x8e, 0xdc, 0x88, 0x1c, 0x35, 0x83, 0x90, 0xb2,
|
||||
0x09, 0xd6, 0xb0, 0xf5, 0x2c, 0x9d, 0x72, 0xc2, 0x38, 0x30, 0x15, 0x04, 0xfd, 0xde, 0x98, 0x77,
|
||||
0xa5, 0x1c, 0x28, 0x02, 0x3b, 0x33, 0x0e, 0x28, 0x3b, 0xc8, 0x80, 0xca, 0x91, 0x1d, 0xb5, 0x32,
|
||||
0xc0, 0x19, 0x37, 0x6c, 0x34, 0x36, 0x36, 0x32, 0xc0, 0x91, 0x1b, 0x26, 0xe0, 0x8d, 0x9b, 0xb0,
|
||||
0xc3, 0x0d, 0xe2, 0x50, 0x0c, 0xda, 0xa0, 0xca, 0x51, 0x4c, 0x4e, 0x37, 0x1d, 0xe7, 0x6f, 0xba,
|
||||
0xe1, 0x4c, 0x1d, 0x8c, 0x1b, 0xd3, 0x1e, 0x95, 0x01, 0xaa, 0x1c, 0xca, 0x80, 0xba, 0x18, 0x33,
|
||||
0xc0, 0x1a, 0x83, 0x38, 0xe8, 0x9c, 0xdd, 0x98, 0x19, 0xf6, 0xa9, 0x26, 0xac, 0x6c, 0x0b, 0x55,
|
||||
0x07, 0x63, 0x86, 0xaa, 0x83, 0xf1, 0x52, 0xe7, 0x6f, 0xca, 0x61, 0x0c, 0x50, 0xe5, 0x70, 0xd3,
|
||||
0xb5, 0x51, 0x06, 0xa8, 0x72, 0xb8, 0x89, 0x3a, 0x0c, 0xf3, 0xb7, 0xe6, 0xa9, 0x18, 0x1f, 0x16,
|
||||
0x24, 0x25, 0x09, 0x68, 0xba, 0xaf, 0x0b, 0x71, 0xbf, 0xac, 0xe4, 0x0b, 0xf3, 0x5c, 0x94, 0x03,
|
||||
0x35, 0x5d, 0x35, 0x96, 0xa3, 0xfb, 0xba, 0xc5, 0xef, 0x97, 0x76, 0xeb, 0xee, 0xab, 0x1e, 0x57,
|
||||
0xbf, 0xe8, 0x2e, 0xaf, 0x08, 0x20, 0xde, 0x6e, 0x37, 0xb7, 0x6b, 0xe0, 0xcc, 0x09, 0x28, 0x8f,
|
||||
0xad, 0x95, 0x70, 0xfa, 0x59, 0x94, 0x2d, 0xc5, 0x53, 0x46, 0xb0, 0x37, 0x01, 0x16, 0x46, 0x04,
|
||||
0x2d, 0x17, 0x64, 0xf1, 0xa6, 0xc3, 0x19, 0x36, 0x40, 0x20, 0xca, 0x59, 0x76, 0x04, 0xc5, 0xcd,
|
||||
0x83, 0x2c, 0x97, 0x0f, 0x70, 0x6a, 0xbd, 0xc4, 0x1b, 0xe4, 0x5e, 0xaa, 0xc5, 0x0d, 0x96, 0xcd,
|
||||
0x15, 0x9b, 0x25, 0x02, 0x5b, 0x1c, 0x65, 0x97, 0x4a, 0x08, 0x28, 0x02, 0x01, 0x7f, 0x9f, 0xf7,
|
||||
0x56, 0xa4, 0x92, 0xb0, 0x34, 0xcb, 0x6e, 0x20, 0xf7, 0x34, 0x11, 0x71, 0x3c, 0x83, 0x25, 0xd9,
|
||||
0x17, 0x86, 0x66, 0xa8, 0x64, 0x54, 0x99, 0xac, 0xae, 0x75, 0x0f, 0xf0, 0x12, 0x33, 0x47, 0x44,
|
||||
0x98, 0xd2, 0x17, 0x9c, 0x0e, 0xf9, 0xb4, 0xef, 0x10, 0x43, 0x51, 0x43, 0x4c, 0xb9, 0x22, 0x58,
|
||||
0x08, 0xc5, 0xc0, 0x56, 0x1f, 0x11, 0x83, 0x7a, 0x28, 0x48, 0x2b, 0x4e, 0x97, 0xec, 0xaa, 0x21,
|
||||
0x7a, 0xfa, 0x12, 0x0d, 0xf5, 0xb4, 0x16, 0x43, 0x51, 0xc3, 0x41, 0xa9, 0x10, 0xc2, 0x47, 0xf1,
|
||||
0x35, 0x65, 0x5b, 0x4b, 0xe5, 0xb0, 0x13, 0x00, 0x81, 0x89, 0xe2, 0x12, 0x4a, 0x24, 0x6b, 0x26,
|
||||
0x3d, 0x21, 0x04, 0x68, 0x90, 0x29, 0xb0, 0x0b, 0xeb, 0xa4, 0xb8, 0x89, 0x28, 0x45, 0xdd, 0x38,
|
||||
0x09, 0x9d, 0xb3, 0xf8, 0xfb, 0xd6, 0x9d, 0xf6, 0x5e, 0xee, 0x9b, 0x36, 0x8d, 0x52, 0x87, 0x3e,
|
||||
0x4c, 0xc7, 0x8d, 0xa6, 0x23, 0xe7, 0x44, 0x5f, 0x10, 0x7b, 0xa2, 0x67, 0x18, 0x81, 0x98, 0xe9,
|
||||
0x3a, 0x2b, 0x4f, 0x9c, 0xf1, 0x04, 0xa1, 0x3f, 0xf2, 0x1d, 0x49, 0xb4, 0x3a, 0x8a, 0xdf, 0x0f,
|
||||
0xdf, 0x02, 0xae, 0xb3, 0xac, 0x6c, 0x9d, 0x06, 0x66, 0xbb, 0x81, 0xd9, 0x1e, 0x96, 0x00, 0x2e,
|
||||
0x5b, 0x29, 0x5a, 0xca, 0xb4, 0x44, 0x49, 0xd7, 0x01, 0xe8, 0x79, 0x03, 0xb3, 0xa6, 0x2b, 0xe9,
|
||||
0x86, 0x95, 0xac, 0xe0, 0xef, 0x88, 0xed, 0x47, 0xac, 0xa8, 0x51, 0x04, 0x45, 0x41, 0xe5, 0x42,
|
||||
0x1b, 0x5f, 0x9e, 0xda, 0x14, 0xa0, 0x1f, 0x1d, 0x45, 0xa3, 0xcd, 0x50, 0xc7, 0x00, 0x07, 0x0d,
|
||||
0xfe, 0x5b, 0xf2, 0xb5, 0x35, 0xf4, 0x13, 0xf6, 0x25, 0x42, 0x70, 0x38, 0xed, 0x4a, 0x9c, 0x84,
|
||||
0x00, 0x47, 0x42, 0xf6, 0xab, 0x80, 0x34, 0x83, 0xfc, 0xbf, 0x92, 0xe1, 0x56, 0x32, 0x65, 0x38,
|
||||
0x6e, 0x12, 0x4d, 0x67, 0xcf, 0xd0, 0x5d, 0xac, 0x0b, 0xc0, 0x20, 0x31, 0x88, 0x67, 0x29, 0x0a,
|
||||
0x97, 0xc4, 0xc3, 0xa0, 0x3f, 0x2e, 0x7c, 0x81, 0x97, 0x27, 0xb6, 0x32, 0x42, 0x61, 0xda, 0xb3,
|
||||
0x2a, 0x83, 0x74, 0x05, 0x48, 0x04, 0x48, 0x1d, 0x98, 0x67, 0x17, 0x17, 0xc3, 0xc5, 0x12, 0x36,
|
||||
0xc3, 0x45, 0x47, 0x5c, 0x1f, 0x00, 0x1f, 0x6b, 0xc7, 0x32, 0x7f, 0x44, 0x01, 0xf5, 0xbe, 0x3d,
|
||||
0x0c, 0xa4, 0x1c, 0xe6, 0x55, 0x70, 0x3e, 0x49, 0xe7, 0x33, 0xf9, 0xcc, 0x0d, 0x32, 0x30, 0xdc,
|
||||
0x30, 0xc5, 0xbe, 0xc5, 0x84, 0x44, 0x48, 0x03, 0x40, 0xab, 0xad, 0x94, 0xc5, 0x95, 0xb0, 0xbe,
|
||||
0x05, 0x4b, 0x01, 0xf5, 0x89, 0x93, 0x04, 0xe0, 0x51, 0x46, 0x85, 0xb4, 0x8a, 0x10, 0x88, 0x00,
|
||||
0x32, 0x6a, 0x85, 0x6d, 0xd8, 0x92, 0x80, 0xb2, 0x44, 0xa0, 0x01, 0x4f, 0x35, 0x7a, 0x3b, 0x57,
|
||||
0xe8, 0xb9, 0x0e, 0xf9, 0x98, 0x3a, 0x26, 0x24, 0xb4, 0x2a, 0xd9, 0x74, 0x81, 0xc7, 0x78, 0xf4,
|
||||
0x65, 0x7d, 0x58, 0x9f, 0x43, 0x7b, 0x85, 0xc9, 0xe8, 0xef, 0x36, 0xb7, 0x2b, 0x2c, 0x46, 0x23,
|
||||
0x84, 0x91, 0xa1, 0x39, 0xd8, 0x8c, 0x32, 0xd2, 0x66, 0x20, 0xdc, 0xf3, 0x4c, 0x2c, 0x89, 0x6c,
|
||||
0x84, 0x28, 0xde, 0x25, 0xc2, 0x91, 0x9d, 0xe8, 0x64, 0x4b, 0xef, 0x15, 0x09, 0xaa, 0xd6, 0x87,
|
||||
0xa1, 0xed, 0xac, 0x0d, 0x97, 0x06, 0xf4, 0x6a, 0xee, 0xf6, 0xc2, 0x62, 0xef, 0x99, 0x7e, 0x42,
|
||||
0xc2, 0xa2, 0x01, 0x7a, 0x22, 0x44, 0x93, 0x07, 0x16, 0xd1, 0xca, 0x2e, 0x25, 0x42, 0xd3, 0xd0,
|
||||
0xfb, 0x2e, 0xd1, 0x5b, 0x3c, 0x03, 0x5d, 0xe1, 0x23, 0xf0, 0x89, 0x28, 0xf7, 0xb4, 0x3b, 0xd1,
|
||||
0x4a, 0xe6, 0xb6, 0x5a, 0x0c, 0x0c, 0x6c, 0x90, 0x6b, 0x24, 0xe8, 0xd3, 0x63, 0xec, 0x24, 0xf2,
|
||||
0x69, 0x84, 0x8c, 0x7e, 0xb6, 0xdc, 0x70, 0x3c, 0x1a, 0xc0, 0x49, 0x42, 0x43, 0x15, 0x6f, 0x7d,
|
||||
0xdd, 0x7b, 0xd8, 0x9e, 0xa0, 0x08, 0x5b, 0x20, 0x38, 0xc7, 0x8c, 0x57, 0x5d, 0xe5, 0x1d, 0x28,
|
||||
0x63, 0x3a, 0xe8, 0x28, 0x42, 0x6d, 0x03, 0x4e, 0x86, 0x9a, 0xd0, 0x61, 0x57, 0xd3, 0xc9, 0xce,
|
||||
0xc4, 0xf4, 0xb0, 0xb2, 0x44, 0x84, 0x61, 0x6b, 0x84, 0x59, 0x98, 0x0a, 0x5b, 0xbd, 0x87, 0x85,
|
||||
0x0d, 0xe2, 0x9a, 0x40, 0x6d, 0xf5, 0x94, 0xd3, 0x53, 0x3b, 0xa5, 0xe7, 0x8c, 0x9e, 0xb3, 0xde,
|
||||
0x9c, 0xf6, 0xd6, 0xb5, 0x1a, 0xc4, 0x89, 0x93, 0x4d, 0x19, 0x09, 0x35, 0x22, 0xfb, 0x0a, 0xbe,
|
||||
0x19, 0x86, 0xa8, 0xce, 0x75, 0xee, 0x15, 0xe6, 0x02, 0x2b, 0xab, 0x4a, 0xe7, 0xe5, 0x74, 0x5e,
|
||||
0xbb, 0x81, 0x1f, 0xce, 0xf8, 0xe1, 0x94, 0x5d, 0xce, 0xd8, 0xd5, 0x81, 0xd5, 0x40, 0xae, 0x00,
|
||||
0xd4, 0x51, 0xbf, 0xa1, 0x4a, 0xf0, 0xec, 0xc8, 0x63, 0xa7, 0x3c, 0x96, 0x35, 0xaf, 0x3d, 0xe2,
|
||||
0x70, 0x4f, 0x94, 0x21, 0x49, 0x80, 0x22, 0xa6, 0xa4, 0x22, 0x44, 0x22, 0x6a, 0xc7, 0xef, 0xba,
|
||||
0x4b, 0x02, 0x13, 0x47, 0x08, 0x82, 0xe4, 0x4d, 0x86, 0xdf, 0x2f, 0x43, 0xa7, 0xea, 0x41, 0x40,
|
||||
0x48, 0x41, 0x04, 0x04, 0x06, 0xa7, 0x06, 0x72, 0x19, 0x20, 0x43, 0x09, 0x48, 0x40, 0x8c, 0x58,
|
||||
0x89, 0x88, 0x38, 0x47, 0xcc, 0xc9, 0x59, 0xa5, 0xc1, 0x97, 0x5c, 0x02, 0x53, 0x81, 0x05, 0xc3,
|
||||
0xce, 0xd9, 0x20, 0xa2, 0x13, 0x6e, 0x49, 0x20, 0xb5, 0xf3, 0xb0, 0xbf, 0x4c, 0x01, 0xea, 0x31,
|
||||
0xc0, 0x50, 0x56, 0x1e, 0x38, 0xb3, 0x08, 0x0a, 0x44, 0xac, 0xcc, 0x25, 0x28, 0xd5, 0x04, 0x63,
|
||||
0xe1, 0x6f, 0x0a, 0x91, 0x86, 0x1e, 0x74, 0x82, 0x77, 0x8d, 0x90, 0x71, 0x47, 0xc0, 0x50, 0xe4,
|
||||
0x5d, 0x54, 0xab, 0x84, 0x58, 0x0f, 0x6d, 0x67, 0x6d, 0x84, 0x37, 0x89, 0x3d, 0x57, 0xe8, 0xab,
|
||||
0x04, 0xb3, 0x18, 0x57, 0x67, 0xa5, 0xe3, 0x06, 0x3a, 0xd6, 0xbd, 0xd3, 0xee, 0x9d, 0x8e, 0xaa,
|
||||
0xb6, 0x63, 0xea, 0xa2, 0x39, 0xa6, 0xc0, 0x6b, 0x45, 0x12, 0xc4, 0xa9, 0xe4, 0xe2, 0x47, 0x4e,
|
||||
0xc9, 0xd9, 0x94, 0x8c, 0x0f, 0xce, 0xf8, 0xe0, 0x94, 0x4d, 0xc0, 0x08, 0xc8, 0xa6, 0x4e, 0xba,
|
||||
0x0a, 0x88, 0xdd, 0xcb, 0x0c, 0x22, 0x08, 0xaa, 0xc9, 0x4e, 0xe3, 0xad, 0x36, 0xd6, 0x20, 0x8d,
|
||||
0xb7, 0xd7, 0x7d, 0xbf, 0x26, 0x5f, 0x50, 0xab, 0x7b, 0x1a, 0x2b, 0xb1, 0x74, 0xbb, 0x90, 0x45,
|
||||
0x6e, 0x5a, 0xa0, 0xb9, 0x38, 0x42, 0x2e, 0x81, 0x15, 0xf3, 0xd3, 0xe9, 0x77, 0xb8, 0x76, 0x25,
|
||||
0xf6, 0x80, 0x2a, 0x91, 0x95, 0x2d, 0xd1, 0x63, 0xfd, 0xd4, 0x73, 0xd6, 0xe0, 0x79, 0xd9, 0xac,
|
||||
0x77, 0x46, 0x0c, 0xf8, 0xf7, 0x84, 0xf8, 0xf0, 0xff, 0xae, 0x38, 0xf4, 0x72, 0x8a, 0x06, 0xac,
|
||||
0x10, 0x9b, 0x6e, 0x74, 0x9d, 0x1b, 0xc6, 0xe1, 0xf4, 0x9a, 0xdd, 0xb4, 0x93, 0x3c, 0xef, 0xb4,
|
||||
0x1b, 0x91, 0x68, 0x4e, 0x92, 0x10, 0x16, 0x88, 0x88, 0x63, 0xa2, 0x5e, 0xf4, 0x10, 0x6b, 0x56,
|
||||
0xb7, 0xcc, 0x2a, 0x40, 0x50, 0xd8, 0xe8, 0x7d, 0xa5, 0x52, 0xc4, 0xac, 0xb7, 0x9e, 0x29, 0x70,
|
||||
0xa6, 0xdd, 0x4d, 0x7b, 0xcd, 0x6e, 0xde, 0xbb, 0x12, 0x3e, 0x90, 0x17, 0x17, 0x64, 0x44, 0xdf,
|
||||
0x2f, 0xd2, 0xf7, 0x4a, 0xbf, 0x1b, 0xcf, 0xfc, 0xd4, 0x3a, 0x54, 0xbb, 0x19, 0x57, 0xf3, 0x0a,
|
||||
0x11, 0xd9, 0xdc, 0xde, 0x5e, 0xff, 0xc5, 0x22, 0xe1, 0xa2, 0x7b, 0x77, 0xdb, 0xed, 0xb6, 0x2b,
|
||||
0xc4, 0xc5, 0xb0, 0x73, 0xa6, 0x3c, 0x44, 0x65, 0xba, 0x11, 0x86, 0x8e, 0x0c, 0xc7, 0x14, 0x3c,
|
||||
0x77, 0x06, 0x9e, 0x0f, 0xed, 0xde, 0x00, 0x79, 0x47, 0x40, 0x3e, 0xda, 0x69, 0x94, 0x17, 0xe8,
|
||||
0xe5, 0xc3, 0x51, 0xc9, 0x1c, 0xda, 0x03, 0x70, 0x6f, 0xb7, 0x29, 0x95, 0xf6, 0xa8, 0x97, 0xe9,
|
||||
0x6d, 0xa1, 0x98, 0x92, 0x0f, 0xc5, 0x70, 0xdf, 0x24, 0x1d, 0x90, 0xf7, 0xe9, 0x80, 0xfd, 0x65,
|
||||
0x93, 0x49, 0x84, 0x7d, 0x06, 0xc0, 0x6e, 0x1b, 0xe6, 0x30, 0xeb, 0xe5, 0xcb, 0xc4, 0xe5, 0xb6,
|
||||
0x4c, 0x52, 0xa9, 0x89, 0xa3, 0x62, 0x9c, 0x51, 0x2a, 0xf8, 0xd9, 0xdb, 0xff, 0x8a, 0xd1, 0xff,
|
||||
0xf4, 0x53, 0x1c, 0x00, 0xbb, 0x59, 0xdb, 0x6e, 0x7c, 0xa1, 0x92, 0xe8, 0x97, 0x32, 0x54, 0xa7,
|
||||
0xc2, 0x29, 0x2f, 0xc3, 0x22, 0x7a, 0xea, 0x09, 0x01, 0xee, 0x82, 0xf8, 0x87, 0xc2, 0x2b, 0x7c,
|
||||
0x52, 0xac, 0xa2, 0xa9, 0xf7, 0x48, 0xf1, 0xf2, 0xa0, 0x11, 0xa5, 0x3b, 0xa8, 0xbe, 0x09, 0xde,
|
||||
0x5c, 0x6b, 0xc4, 0xb8, 0x22, 0xcf, 0x03, 0xc7, 0x34, 0x21, 0x5f, 0x98, 0xde, 0xc6, 0xc0, 0x0c,
|
||||
0x52, 0x37, 0xd4, 0x05, 0xdc, 0x5b, 0x72, 0x30, 0x2f, 0x30, 0x7a, 0x5b, 0xd8, 0xed, 0x3b, 0x23,
|
||||
0xe7, 0x8c, 0x7c, 0x77, 0x18, 0x49, 0x3c, 0x3d, 0x92, 0xa2, 0xe6, 0x28, 0xf9, 0x59, 0x50, 0xc9,
|
||||
0x1a, 0xea, 0x55, 0x82, 0x11, 0x87, 0x32, 0xb2, 0xd1, 0x17, 0x63, 0x2d, 0xb3, 0x53, 0x45, 0x43,
|
||||
0xd6, 0x14, 0x63, 0xde, 0xc8, 0x3e, 0x60, 0x56, 0x48, 0xbe, 0xb0, 0xab, 0xa0, 0xda, 0xe6, 0xff,
|
||||
0x81, 0x72, 0xb1, 0xe4, 0x7d, 0xbd, 0x76, 0x65, 0xf8, 0xec, 0x88, 0x07, 0x4c, 0xbb, 0x8a, 0x89,
|
||||
0x7a, 0x2d, 0xe5, 0xa6, 0xf6, 0xea, 0x55, 0x4c, 0xf5, 0x6b, 0xa6, 0x00, 0x75, 0x31, 0xd3, 0xaf,
|
||||
0x99, 0x02, 0x25, 0x37, 0xd5, 0xaf, 0x99, 0xfa, 0xe5, 0x99, 0x5a, 0x86, 0x99, 0xfa, 0x06, 0x37,
|
||||
0xd5, 0xaf, 0x99, 0xf2, 0x07, 0x37, 0xd3, 0xaf, 0x99, 0x02, 0xe5, 0x62, 0xaa, 0x5f, 0xc5, 0xbd,
|
||||
0xfa, 0x35, 0xd3, 0x91, 0x13, 0xca, 0xd4, 0x1f, 0xab, 0x8d, 0xe9, 0xd7, 0x54, 0x37, 0x4f, 0x64,
|
||||
0x7b, 0xfb, 0x13, 0xfa, 0xba, 0xac, 0x5f, 0x4d, 0x4e, 0x94, 0xae, 0x41, 0xbf, 0xa6, 0x42, 0x34,
|
||||
0xd2, 0xb0, 0xf1, 0xd6, 0x96, 0xf7, 0xdb, 0xe3, 0x68, 0x73, 0x6d, 0x8a, 0xd3, 0x1a, 0x36, 0x57,
|
||||
0xb0, 0x41, 0x45, 0x66, 0xa5, 0x37, 0x6e, 0x54, 0x0e, 0x74, 0x28, 0x4b, 0x18, 0x97, 0xd4, 0xa8,
|
||||
0x86, 0x0d, 0x0a, 0x56, 0xcc, 0x35, 0x6c, 0x34, 0x94, 0x78, 0x7a, 0x28, 0x6e, 0xa4, 0x62, 0x6e,
|
||||
0xac, 0x62, 0x6e, 0xa2, 0x62, 0xf3, 0x7d, 0xec, 0xa0, 0x61, 0x63, 0xde, 0x0c, 0xfa, 0xe5, 0xbe,
|
||||
0x49, 0xbf, 0x6e, 0xaf, 0xbb, 0xf7, 0xdb, 0x35, 0x48, 0x48, 0x42, 0x1c, 0xe8, 0xb4, 0xb8, 0xb1,
|
||||
0x68, 0x44, 0xc6, 0x58, 0x10, 0x81, 0x64, 0x40, 0x6c, 0x98, 0x65, 0xf4, 0xcc, 0x10, 0xe5, 0xfe,
|
||||
0xd0, 0x74, 0xf6, 0x2f, 0x1c, 0x9d, 0xfe, 0xdb, 0x0d, 0xff, 0x3e, 0x34, 0x87, 0x2b, 0xbe, 0x58,
|
||||
0x17, 0x2c, 0x09, 0x9a, 0x14, 0xa5, 0x1c, 0x15, 0xde, 0xf4, 0xf3, 0x72, 0x9b, 0x7b, 0x6a, 0x50,
|
||||
0x8e, 0x6a, 0x97, 0xf8, 0x71, 0x4a, 0x02, 0xb1, 0xaa, 0x48, 0x46, 0xb1, 0xe6, 0x23, 0xb1, 0xdc,
|
||||
0xae, 0x64, 0xf8, 0xc9, 0xda, 0x09, 0xc4, 0x58, 0xf4, 0x25, 0x92, 0xfa, 0x12, 0x08, 0x3a, 0x25,
|
||||
0x90, 0xd2, 0x4f, 0x89, 0x02, 0x62, 0xd4, 0xc8, 0x33, 0x48, 0x0c, 0xd6, 0x46, 0x3a, 0x60, 0xe2,
|
||||
0x79, 0x36, 0x99, 0x91, 0x54, 0x40, 0x0a, 0xa1, 0xce, 0x14, 0x11, 0x10, 0xaa, 0x82, 0x96, 0xfc,
|
||||
0x05, 0x14, 0x25, 0xc2, 0xc2, 0x0c, 0xed, 0xe6, 0x2c, 0x03, 0x62, 0x42, 0xe6, 0xa7, 0x45, 0x4d,
|
||||
0x05, 0xca, 0x4d, 0x00, 0x72, 0xc4, 0x94, 0x5c, 0x15, 0xb5, 0x44, 0xa4, 0x21, 0x0c, 0x35, 0x1c,
|
||||
0xc4, 0xb1, 0xf6, 0xe2, 0xf8, 0xd4, 0x2c, 0xd3, 0xac, 0x44, 0x62, 0x44, 0x52, 0x5b, 0xad, 0x02,
|
||||
0xd5, 0x54, 0x4a, 0xc3, 0xa8, 0xbb, 0x00, 0xde, 0xe1, 0x91, 0xbe, 0x13, 0xbb, 0x90, 0x25, 0x38,
|
||||
0xac, 0x82, 0xd6, 0xe2, 0xa0, 0x12, 0x25, 0x53, 0xca, 0x32, 0xca, 0x01, 0x99, 0xc6, 0x10, 0xd7,
|
||||
0xdb, 0xe3, 0x3b, 0x12, 0x05, 0x32, 0x01, 0x94, 0x33, 0xe0, 0xfb, 0x97, 0xa7, 0xa1, 0x46, 0x91,
|
||||
0x08, 0x02, 0x77, 0xe9, 0x2f, 0x22, 0xc8, 0x8e, 0x38, 0x5a, 0x56, 0xbf, 0xd5, 0x34, 0x6b, 0x5d,
|
||||
0x88, 0x2a, 0x87, 0x1c, 0x50, 0x2e, 0x12, 0x2a, 0xa6, 0x6e, 0x91, 0xf4, 0xa8, 0x25, 0xbc, 0x20,
|
||||
0xe2, 0x15, 0x10, 0xfb, 0x95, 0x1a, 0x41, 0xc8, 0x8a, 0x47, 0x66, 0x3d, 0x10, 0xeb, 0x35, 0xc0,
|
||||
0x19, 0xab, 0xc8, 0xac, 0x28, 0x22, 0x3f, 0x00, 0x14, 0x08, 0x68, 0xe0, 0xe1, 0x83, 0x19, 0x09,
|
||||
0xe1, 0x83, 0xc4, 0x3a, 0x15, 0xbd, 0xd9, 0x58, 0x83, 0xa5, 0x45, 0xd5, 0x10, 0xc0, 0x6e, 0x4a,
|
||||
0x62, 0x6f, 0x29, 0x31, 0x72, 0x14, 0x76, 0x34, 0x48, 0x1e, 0xd6, 0x5a, 0x08, 0xaa, 0x68, 0x9a,
|
||||
0x0c, 0xbd, 0xc1, 0x4a, 0x56, 0x34, 0xe9, 0x67, 0x29, 0x07, 0x45, 0x42, 0xa4, 0x03, 0x59, 0x15,
|
||||
0x98, 0x4a, 0xc4, 0x0c, 0x69, 0x38, 0x20, 0xa9, 0x04, 0xfc, 0xa7, 0x84, 0x7a, 0x22, 0xeb, 0x83,
|
||||
0xec, 0x10, 0x1b, 0xcb, 0xf5, 0x7c, 0x48, 0x65, 0xa3, 0xde, 0xb4, 0x56, 0x63, 0x22, 0x73, 0x8d,
|
||||
0x09, 0x4c, 0x89, 0x80, 0x08, 0xa5, 0xd9, 0x4a, 0xc8, 0x2a, 0x43, 0x44, 0xa4, 0x9e, 0x03, 0x95,
|
||||
0xb6, 0x4a, 0x9a, 0xe5, 0x96, 0xd9, 0x10, 0x80, 0xcf, 0x84, 0xa1, 0x83, 0xc7, 0xad, 0x59, 0x17,
|
||||
0x2b, 0x33, 0xbe, 0x64, 0xc4, 0x1c, 0xd4, 0x35, 0x2d, 0x59, 0x76, 0x1a, 0x10, 0x02, 0x23, 0x94,
|
||||
0x67, 0x22, 0x04, 0x85, 0xb9, 0x59, 0xa2, 0x43, 0x40, 0x6b, 0x72, 0x0e, 0x55, 0xa1, 0x05, 0xea,
|
||||
0x42, 0x50, 0x34, 0x5a, 0xb2, 0x36, 0x18, 0x89, 0x31, 0x44, 0xd5, 0xb2, 0x46, 0x28, 0x0a, 0x40,
|
||||
0x08, 0xa6, 0x25, 0xc1, 0x2c, 0xf7, 0x42, 0xe0, 0x9c, 0x6c, 0x3f, 0x03, 0x12, 0xc4, 0x8a, 0x97,
|
||||
0x92, 0xc1, 0x1b, 0x10, 0xb2, 0x44, 0x59, 0x06, 0x7e, 0x26, 0x26, 0x0e, 0x40, 0x98, 0xc3, 0x90,
|
||||
0x5b, 0x08, 0x56, 0x59, 0xa1, 0x2e, 0x86, 0x20, 0x13, 0xb2, 0x37, 0xd0, 0x22, 0xa6, 0x0d, 0x91,
|
||||
0x8c, 0x47, 0xb0, 0x85, 0x81, 0x66, 0x8f, 0xb0, 0x10, 0x80, 0x31, 0xf0, 0x7a, 0x56, 0x30, 0x30,
|
||||
0xc9, 0xcb, 0x59, 0xb6, 0x67, 0x4d, 0x84, 0x57, 0x0f, 0x48, 0x08, 0xc9, 0xc4, 0x36, 0x58, 0x43,
|
||||
0xa6, 0xa4, 0x38, 0x65, 0x65, 0x88, 0xba, 0x16, 0xdb, 0x96, 0x09, 0x7a, 0x87, 0xf0, 0xbb, 0x44,
|
||||
0x88, 0x8f, 0x42, 0x8e, 0x9a, 0xa0, 0xba, 0x57, 0x80, 0xa8, 0x25, 0x93, 0x6b, 0x44, 0xe2, 0x0d,
|
||||
0x52, 0x93, 0xb4, 0x1f, 0xc4, 0x4e, 0x6a, 0x24, 0x79, 0x1a, 0x4d, 0x4d, 0x06, 0x56, 0x40, 0xf9,
|
||||
0xa8, 0x1a, 0x29, 0x8a, 0x48, 0x4c, 0x2c, 0x31, 0x1c, 0xaf, 0x29, 0xef, 0x4e, 0x26, 0x0e, 0x68,
|
||||
0x5e, 0x84, 0x94, 0x29, 0x2d, 0x19, 0x9a, 0xc8, 0x3a, 0xb8, 0x83, 0x12, 0xdb, 0xc0, 0x14, 0xa2,
|
||||
0x1d, 0x50, 0x17, 0x26, 0x01, 0x2d, 0x30, 0xc2, 0x6a, 0xb8, 0x24, 0xe8, 0x1d, 0x2c, 0x93, 0xae,
|
||||
0x59, 0x3c, 0x85, 0x04, 0x29, 0x76, 0x0d, 0xa4, 0xbf, 0x59, 0xd6, 0xab, 0xdd, 0x06, 0x1b, 0x85,
|
||||
0x67, 0x4a, 0x44, 0x4b, 0x2a, 0x1a, 0x31, 0x21, 0x32, 0xfa, 0x94, 0x13, 0xe6, 0xc2, 0x2c, 0x40,
|
||||
0x83, 0x2c, 0x00, 0x26, 0x56, 0x21, 0x2d, 0x9e, 0x45, 0x41, 0xf8, 0x09, 0xe1, 0x40, 0x71, 0x16,
|
||||
0x70, 0x12, 0x14, 0xc4, 0xc9, 0x90, 0x2d, 0x85, 0x53, 0x62, 0x87, 0x89, 0xc8, 0x98, 0x66, 0x26,
|
||||
0x4c, 0x9b, 0x86, 0x99, 0xc7, 0x8a, 0xe5, 0x54, 0x0d, 0xba, 0xd5, 0x96, 0x42, 0x98, 0xa5, 0x53,
|
||||
0x05, 0x11, 0x45, 0x6a, 0xb8, 0x2b, 0xd5, 0xac, 0x52, 0x68, 0x4a, 0xa2, 0x98, 0xc8, 0xa6, 0xc9,
|
||||
0x10, 0x5b, 0x97, 0x09, 0xf6, 0xd4, 0x80, 0xa4, 0xf7, 0x4b, 0x3e, 0x88, 0x40, 0x9d, 0x88, 0x50,
|
||||
0x57, 0x0d, 0xfd, 0x1d, 0xd1, 0xd3, 0x04, 0x6b, 0x19, 0x35, 0xdb, 0x61, 0xc2, 0xa4, 0xc2, 0xc5,
|
||||
0xfc, 0x9f, 0x08, 0x7a, 0x1d, 0x81, 0x92, 0x03, 0x66, 0x41, 0xe5, 0x47, 0x5b, 0x42, 0x34, 0x07,
|
||||
0x09, 0x55, 0x81, 0xad, 0x34, 0x62, 0x07, 0x1a, 0x85, 0x2a, 0x57, 0x59, 0x5f, 0xe4, 0xce, 0x25,
|
||||
0x36, 0x03, 0xc4, 0xa2, 0x32, 0x1f, 0x34, 0x2f, 0x9a, 0x6a, 0x9a, 0x87, 0xd8, 0x70, 0xb5, 0x80,
|
||||
0xe3, 0x42, 0x38, 0x80, 0x07, 0x00, 0x4c, 0x51, 0x55, 0xaa, 0xf6, 0xaa, 0x25, 0x8a, 0x82, 0xb1,
|
||||
0xc2, 0x10, 0x25, 0xd8, 0xaa, 0xc4, 0x7a, 0xf7, 0x00, 0xca, 0xb2, 0x3e, 0xd6, 0x34, 0x9d, 0xfd,
|
||||
0xa4, 0xc5, 0xb6, 0x5a, 0x62, 0xf8, 0xd4, 0xc7, 0x96, 0xc1, 0xac, 0xd8, 0x7a, 0x58, 0xd6, 0x4e,
|
||||
0x22, 0x7f, 0xd4, 0x89, 0xc1, 0x02, 0xa9, 0xc9, 0xca, 0x35, 0x41, 0x54, 0xfa, 0x80, 0x65, 0xa3,
|
||||
0xa8, 0x04, 0x4c, 0x62, 0xc5, 0x44, 0x63, 0x90, 0xc9, 0x47, 0xcd, 0xe5, 0x00, 0x53, 0x07, 0xfe,
|
||||
0xe1, 0x3d, 0xc1, 0xbd, 0x98, 0x68, 0xcb, 0xbd, 0x30, 0x25, 0x8a, 0xd8, 0xc4, 0x96, 0x75, 0x67,
|
||||
0x95, 0x22, 0x37, 0x60, 0x5f, 0x22, 0x90, 0x95, 0x65, 0xfe, 0xa8, 0x15, 0xaf, 0x08, 0xb5, 0xa7,
|
||||
0x06, 0xd9, 0xe2, 0x80, 0xe2, 0x2b, 0x97, 0x85, 0x05, 0xb2, 0xdd, 0x74, 0x32, 0x89, 0x46, 0x5c,
|
||||
0x3e, 0x2c, 0x52, 0x04, 0x93, 0xe8, 0x88, 0x78, 0xee, 0x8b, 0xb8, 0xc3, 0x2b, 0x01, 0xd4, 0x0e,
|
||||
0xc8, 0x78, 0xf0, 0x48, 0x00, 0x4b, 0xe3, 0xa1, 0x19, 0x4c, 0x81, 0x57, 0xaa, 0x0a, 0x18, 0x06,
|
||||
0x76, 0x6a, 0x61, 0x72, 0xcb, 0x8a, 0x22, 0x40, 0xca, 0x99, 0x85, 0x40, 0xa8, 0x64, 0xac, 0xc0,
|
||||
0x64, 0x14, 0x0b, 0xb7, 0x9c, 0x1d, 0x00, 0x7d, 0xcc, 0xb6, 0xf2, 0xf1, 0xcb, 0xd3, 0xa6, 0x61,
|
||||
0x71, 0x95, 0x8b, 0x98, 0x21, 0x80, 0x21, 0xc0, 0xaf, 0x62, 0x14, 0xc5, 0x1f, 0x6f, 0xa1, 0x03,
|
||||
0xc0, 0x14, 0x29, 0x13, 0x91, 0xdb, 0x1f, 0x30, 0x65, 0x28, 0xda, 0xd0, 0x2e, 0xc9, 0x5f, 0x64,
|
||||
0x8d, 0x64, 0x7d, 0x3d, 0xf4, 0xbb, 0x82, 0xbd, 0x42, 0x61, 0x01, 0x0b, 0x01, 0x09, 0x61, 0x37,
|
||||
0x70, 0x1d, 0x2a, 0xae, 0xa9, 0xe8, 0x32, 0xac, 0xb9, 0x4c, 0x26, 0xf9, 0x0c, 0xc4, 0x17, 0x69,
|
||||
0xe6, 0xc8, 0x2c, 0x8d, 0x30, 0x06, 0x1d, 0xf0, 0x13, 0x95, 0x4a, 0xb8, 0x5a, 0xb4, 0x42, 0x77,
|
||||
0x15, 0x5c, 0xc0, 0xab, 0xb9, 0x13, 0xb4, 0x40, 0xf7, 0x51, 0xec, 0x1f, 0x87, 0x5e, 0xa4, 0xcf,
|
||||
0x46, 0x48, 0x1d, 0x5a, 0xa8, 0xdd, 0x2a, 0x15, 0xf6, 0x44, 0x94, 0x6e, 0x02, 0x96, 0x98, 0x2f,
|
||||
0xd6, 0xc1, 0x37, 0xa3, 0xc9, 0x04, 0xe6, 0xd3, 0x3d, 0x76, 0x33, 0xe8, 0xa7, 0x58, 0x83, 0x88,
|
||||
0x82, 0x2a, 0x20, 0xf9, 0xa8, 0x2f, 0x92, 0x1d, 0x23, 0xc3, 0x51, 0x2f, 0x03, 0xf5, 0x3b, 0x12,
|
||||
0xd7, 0xe4, 0xc6, 0x2a, 0x3e, 0x4a, 0x8d, 0x4d, 0x5a, 0x76, 0x77, 0x85, 0xe1, 0xf4, 0x9a, 0xfd,
|
||||
0x3d, 0x6b, 0xd0, 0xea, 0xcf, 0x57, 0xdd, 0x57, 0xbc, 0x3a, 0xb9, 0x92, 0xef, 0xdd, 0xd2, 0xf0,
|
||||
0x56, 0x42, 0x09, 0x9a, 0xe4, 0x1a, 0xcc, 0x6c, 0xcd, 0xe5, 0xfe, 0x0a, 0x22, 0x25, 0xab, 0x9f,
|
||||
0x2b, 0x4a, 0xb3, 0x1c, 0x50, 0x5e, 0x87, 0xe4, 0x55, 0x09, 0xe4, 0x94, 0x1b, 0x51, 0x8b, 0xc7,
|
||||
0x0c, 0x4a, 0x14, 0x75, 0x31, 0x37, 0x20, 0x02, 0x2b, 0x52, 0x24, 0xba, 0xc3, 0x1c, 0xbc, 0x6c,
|
||||
0x45, 0x7a, 0x10, 0xbf, 0x29, 0x97, 0x9a, 0x33, 0x61, 0xaa, 0x89, 0xc8, 0x0b, 0x08, 0x69, 0x0b,
|
||||
0x7a, 0x1b, 0xb8, 0x9d, 0xc2, 0x0c, 0x0b, 0x4f, 0x60, 0x56, 0x90, 0x31, 0x4f, 0x70, 0x11, 0x81,
|
||||
0x3d, 0x66, 0x56, 0x70, 0x26, 0xcd, 0x44, 0x59, 0x38, 0x7a, 0xa6, 0x4f, 0x9d, 0xa0, 0x72, 0x0d,
|
||||
0x46, 0x2e, 0xb1, 0x96, 0x24, 0xb6, 0x8d, 0x5e, 0x90, 0x9d, 0x5e, 0x3d, 0x5c, 0x81, 0xab, 0xf5,
|
||||
0x7c, 0x61, 0x57, 0x83, 0x38, 0x86, 0xd0, 0x00, 0x16, 0xe6, 0x93, 0x27, 0xf4, 0x0c, 0x30, 0x84,
|
||||
0x84, 0x87, 0x5c, 0x98, 0x8c, 0xd9, 0xb7, 0x7d, 0xab, 0x11, 0x1d, 0x0a, 0x30, 0x83, 0x96, 0x95,
|
||||
0x61, 0x73, 0xa4, 0xcf, 0xa6, 0x35, 0xa9, 0x15, 0x6c, 0xb9, 0x6f, 0xc9, 0xb2, 0x28, 0x53, 0xd5,
|
||||
0xc3, 0x0a, 0x26, 0x4f, 0x40, 0xc3, 0x53, 0xc1, 0x44, 0xdc, 0x8d, 0xb3, 0xa6, 0xdf, 0x09, 0x90,
|
||||
0xed, 0x46, 0x59, 0xd4, 0x25, 0xb0, 0x2c, 0xee, 0xc1, 0xb2, 0xb9, 0x1f, 0x64, 0x02, 0x15, 0x34,
|
||||
0x06, 0x4f, 0x2c, 0x5e, 0x16, 0x4b, 0xca, 0x74, 0x29, 0x6b, 0xfc, 0xe0, 0x1d, 0x83, 0xf3, 0x15,
|
||||
0xac, 0x89, 0x2d, 0x13, 0x22, 0x53, 0x5d, 0x19, 0x72, 0x1e, 0xce, 0x46, 0x85, 0x80, 0x80, 0xac,
|
||||
0x87, 0x6c, 0x90, 0xf5, 0x4e, 0x59, 0x8d, 0x42, 0x5d, 0xcd, 0x83, 0x0d, 0x6d, 0x65, 0x3d, 0x01,
|
||||
0xbc, 0xa8, 0x1d, 0x18, 0xeb, 0x0b, 0x63, 0x7d, 0x41, 0xd6, 0x07, 0xbf, 0x53, 0x96, 0x3b, 0xe3,
|
||||
0xbc, 0xf8, 0x8f, 0x23, 0x80, 0xb2, 0x1d, 0x03, 0x94, 0xed, 0x32, 0x40, 0xd9, 0x8d, 0x71, 0xcf,
|
||||
0xf1, 0xaa, 0x8d, 0x00, 0xc4, 0x31, 0x0b, 0xbf, 0x0e, 0xc9, 0xee, 0xc6, 0xd9, 0xf0, 0x15, 0xe8,
|
||||
0x6a, 0x6f, 0xed, 0x76, 0xf0, 0x1e, 0x95, 0x0a, 0x55, 0xd0, 0xf4, 0xb1, 0x83, 0x1e, 0x3a, 0xd5,
|
||||
0x43, 0xee, 0x73, 0x2d, 0x4a, 0x09, 0xa8, 0x87, 0xc1, 0x99, 0x22, 0x3a, 0x55, 0x44, 0x3e, 0x57,
|
||||
0xc4, 0x4a, 0xf3, 0x46, 0xb7, 0x5a, 0x6a, 0x62, 0xed, 0x54, 0xf7, 0x9c, 0x6a, 0x62, 0x18, 0x9a,
|
||||
0x83, 0x2a, 0x3a, 0x55, 0xc5, 0x42, 0x35, 0xd1, 0x99, 0x26, 0x16, 0xa6, 0x89, 0xd4, 0xad, 0xac,
|
||||
0xcb, 0xed, 0xa1, 0x5b, 0x78, 0x36, 0x4a, 0x97, 0x5b, 0x57, 0x98, 0xeb, 0xbd, 0x26, 0x36, 0xe5,
|
||||
0xfb, 0x73, 0x3e, 0x6c, 0x6e, 0xdf, 0xaf, 0x47, 0x7e, 0x14, 0xdc, 0xb0, 0xb2, 0xfd, 0x75, 0x05,
|
||||
0xcc, 0x75, 0x3f, 0x2b, 0x5a, 0xae, 0x67, 0xc0, 0x50, 0x42, 0xe9, 0x3e, 0x69, 0x55, 0x03, 0x22,
|
||||
0x34, 0x05, 0x2f, 0xf7, 0x17, 0xf6, 0x4a, 0xa0, 0x9a, 0x23, 0x42, 0x43, 0xbb, 0xdb, 0x0f, 0xc9,
|
||||
0xdd, 0x0f, 0xe1, 0xf6, 0xab, 0x20, 0xdc, 0xda, 0x4d, 0x41, 0x9e, 0xfd, 0xe9, 0x01, 0xf0, 0x72,
|
||||
0x5a, 0x93, 0x3d, 0x23, 0x32, 0xc7, 0xb3, 0xbe, 0x1c, 0xb8, 0x06, 0x11, 0xfc, 0x76, 0xd8, 0x74,
|
||||
0x11, 0xa5, 0x5d, 0x04, 0x69, 0x4f, 0x45, 0x52, 0xf0, 0x3d, 0x9a, 0x9a, 0x43, 0x49, 0x8c, 0x73,
|
||||
0xca, 0x23, 0xa8, 0xf1, 0x90, 0x30, 0x18, 0x17, 0xb1, 0x4c, 0xad, 0xe9, 0x49, 0xed, 0x3c, 0x91,
|
||||
0xfa, 0x28, 0x66, 0x9a, 0x84, 0xc2, 0x1a, 0x1a, 0x4c, 0x3b, 0x56, 0x56, 0xce, 0xa0, 0xc7, 0xdc,
|
||||
0x1d, 0xeb, 0xe6, 0x98, 0xc2, 0x14, 0xeb, 0xcd, 0x27, 0x11, 0xd6, 0xb8, 0xa3, 0x6d, 0xaa, 0x87,
|
||||
0x47, 0xad, 0x2c, 0x5f, 0x52, 0x8c, 0xf2, 0x25, 0xc5, 0x38, 0x5f, 0xb2, 0x1a, 0x25, 0xbd, 0xbc,
|
||||
0xfe, 0xeb, 0xea, 0x9f, 0x82, 0xa4, 0x49, 0x42, 0x4e, 0x3c, 0x08, 0x98, 0x67, 0x29, 0x88, 0x59,
|
||||
0x1d, 0xff, 0x4c, 0x76, 0x72, 0x5f, 0x4c, 0x35, 0x61, 0xae, 0x32, 0x4b, 0xaa, 0x74, 0x50, 0x35,
|
||||
0x03, 0x47, 0x27, 0x10, 0x6b, 0x9e, 0x41, 0xac, 0x61, 0x06, 0xb1, 0x86, 0x29, 0xc4, 0x5a, 0xcf,
|
||||
0x20, 0xd6, 0x30, 0x83, 0x58, 0xd3, 0xd1, 0xff, 0xa7, 0x10, 0x6b, 0x33, 0x85, 0x58, 0xf7, 0xa9,
|
||||
0x0a, 0x24, 0x67, 0x45, 0x9a, 0x99, 0xca, 0x13, 0xdd, 0x9f, 0x3c, 0xce, 0x72, 0x0c, 0x84, 0xf6,
|
||||
0x4b, 0xf8, 0x67, 0x37, 0x3c, 0x09, 0xb3, 0x88, 0x83, 0xf6, 0x8b, 0xea, 0x71, 0xb2, 0xa0, 0xab,
|
||||
0xac, 0xb9, 0x21, 0xe5, 0x8a, 0x45, 0x62, 0x47, 0x19, 0x08, 0x95, 0xeb, 0x78, 0x3a, 0xb1, 0x35,
|
||||
0xd2, 0x8a, 0x05, 0x04, 0xf5, 0x08, 0xc8, 0xfc, 0xb4, 0x07, 0x48, 0x87, 0xe7, 0xa0, 0x8f, 0x9e,
|
||||
0x94, 0xd4, 0x47, 0x13, 0x47, 0xb0, 0xe9, 0xe8, 0x01, 0xc5, 0x4f, 0x13, 0x80, 0xd4, 0xb3, 0x64,
|
||||
0x89, 0xf4, 0xd7, 0xa0, 0xb9, 0xe3, 0x1c, 0x84, 0x21, 0xa3, 0x84, 0x49, 0x8b, 0x31, 0x4c, 0xda,
|
||||
0xdb, 0x06, 0x5d, 0x99, 0xae, 0x70, 0xbf, 0xe1, 0x19, 0xe5, 0x8d, 0x3b, 0xf0, 0x06, 0xee, 0x85,
|
||||
0x33, 0x74, 0xd4, 0x53, 0x0f, 0x3d, 0x9e, 0xa2, 0x3d, 0xa9, 0x5a, 0x3f, 0xe9, 0x43, 0xe8, 0x0f,
|
||||
0xf8, 0x48, 0xfa, 0x83, 0xcb, 0x77, 0x9f, 0xa0, 0x65, 0x77, 0xaf, 0x1e, 0xd9, 0x63, 0xf2, 0x78,
|
||||
0x35, 0x10, 0x5e, 0xa6, 0x65, 0x4f, 0xc6, 0xe3, 0xdc, 0x9b, 0x57, 0xee, 0xfa, 0xaa, 0xdb, 0xbd,
|
||||
0xeb, 0xde, 0xff, 0xc2, 0x57, 0xba, 0x3e, 0x7c, 0xf0, 0xb1, 0xdf, 0xba, 0xbf, 0xf1, 0xb3, 0x62,
|
||||
0x3f, 0xf3, 0x07, 0xc3, 0xfe, 0x63, 0xfe, 0xbc, 0xba, 0xf4, 0x27, 0x97, 0x3c, 0x7c, 0x60, 0x8f,
|
||||
0xbd, 0x1b, 0xa1, 0x0f, 0x97, 0x63, 0x42, 0x7c, 0x15, 0xea, 0x69, 0x52, 0x78, 0x18, 0xf7, 0x34,
|
||||
0x89, 0x9b, 0xfe, 0x40, 0xe2, 0xf1, 0xff, 0xfc, 0x10, 0x16, 0x08, 0xb0, 0xfe, 0xed, 0x34, 0x85,
|
||||
0xd7, 0x7f, 0x4f, 0x28, 0x54, 0x0b, 0x14, 0x50, 0x0e, 0x73, 0x9a, 0xc0, 0xd5, 0x6e, 0x42, 0xa0,
|
||||
0x5e, 0x20, 0x80, 0x07, 0xf1, 0x16, 0x08, 0xf4, 0x63, 0x36, 0x3c, 0x5b, 0x62, 0x02, 0x42, 0x9c,
|
||||
0xd3, 0x04, 0xfa, 0xbb, 0x31, 0x81, 0x8b, 0x25, 0x02, 0xdd, 0xf5, 0x9b, 0xc9, 0xfd, 0xb2, 0xf2,
|
||||
0xef, 0x3e, 0xed, 0x57, 0xbc, 0xbb, 0x1c, 0x56, 0x7c, 0x78, 0x7d, 0xda, 0xc3, 0x07, 0x78, 0xe5,
|
||||
0x0f, 0x79, 0x24, 0xc7, 0xff, 0xeb, 0xf4, 0x67, 0xe5, 0x1e, 0xbf, 0x96, 0x8e, 0x5f, 0xdd, 0xee,
|
||||
0xef, 0xeb, 0x77, 0xbf, 0xda, 0x7d, 0x3d, 0xa4, 0x89, 0x6f, 0x8b, 0x70, 0x87, 0xb7, 0x45, 0x38,
|
||||
0xfe, 0x32, 0xdc, 0x2f, 0x8f, 0x98, 0xd2, 0xba, 0xda, 0xf6, 0xfd, 0x70, 0xf1, 0x65, 0xaf, 0xf4,
|
||||
0x2e, 0x7e, 0xb5, 0x37, 0xd9, 0x95, 0xee, 0xc3, 0xbb, 0x2b, 0x7c, 0x6e, 0xfe, 0xc6, 0x0b, 0xf7,
|
||||
0x5d, 0x7f, 0xb7, 0xbd, 0xf9, 0xc5, 0x63, 0x62, 0xfa, 0x1b, 0x59, 0x78, 0xe5, 0xfc, 0x6c, 0xcc,
|
||||
0x78, 0xab, 0xf9, 0x68, 0x20, 0xcf, 0x57, 0x0c, 0xe4, 0x5f, 0xcf, 0xb7, 0x97, 0x8e, 0xbf, 0x72,
|
||||
0xf1, 0xaf, 0xa3, 0x91, 0x3c, 0xff, 0x8e, 0x91, 0xec, 0x7e, 0x5b, 0xd3, 0xf9, 0x6f, 0x78, 0xc1,
|
||||
0xd7, 0x52, 0xf7, 0xbf, 0x7d, 0x4f, 0xf7, 0x8f, 0xd6, 0x74, 0xff, 0x48, 0xc8, 0x2f, 0xf5, 0xfe,
|
||||
0xe8, 0x1b, 0x7a, 0x9f, 0x8e, 0xe1, 0x6d, 0x3f, 0x1a, 0xcf, 0xef, 0x2b, 0xc6, 0xf3, 0xbb, 0x8c,
|
||||
0x66, 0x3e, 0x8c, 0xdf, 0x4f, 0x0c, 0xc3, 0xeb, 0x20, 0xca, 0xb3, 0x32, 0xc4, 0xd1, 0x40, 0xec,
|
||||
0x87, 0x1d, 0x8e, 0x58, 0x71, 0xb1, 0xa2, 0xeb, 0x8b, 0xcd, 0xdd, 0xc7, 0xdb, 0x0d, 0xdf, 0xa3,
|
||||
0x38, 0x1f, 0xc1, 0xc5, 0x37, 0x8f, 0x60, 0x36, 0x8e, 0x3f, 0xd7, 0x2c, 0xc9, 0x9f, 0x78, 0x0f,
|
||||
0xda, 0xd2, 0x9a, 0xfc, 0xf9, 0xed, 0x12, 0x71, 0xb7, 0x7b, 0x39, 0x32, 0xe0, 0x62, 0xdf, 0xff,
|
||||
0xeb, 0xf5, 0xeb, 0x6d, 0x77, 0xe7, 0xce, 0x37, 0x57, 0xdb, 0x1d, 0xf5, 0x57, 0xfe, 0x0e, 0x46,
|
||||
0xf0, 0xc3, 0xed, 0xde, 0x82, 0xf0, 0x25, 0xda, 0x45, 0xdb, 0x2e, 0x59, 0x11, 0x54, 0x08, 0x2d,
|
||||
0x98, 0xd2, 0xeb, 0x39, 0x15, 0xbf, 0x40, 0xe4, 0xa8, 0x86, 0x64, 0x81, 0xe0, 0x87, 0xd7, 0x53,
|
||||
0x82, 0xf7, 0xd3, 0x1b, 0xa7, 0xcd, 0x97, 0x46, 0x38, 0x23, 0xb8, 0x38, 0x4d, 0x4d, 0x14, 0x4e,
|
||||
0xed, 0xe5, 0x81, 0x6b, 0x7c, 0x1d, 0x97, 0x2e, 0xd2, 0x8b, 0x97, 0xa3, 0x75, 0x78, 0x89, 0x75,
|
||||
0xb0, 0x77, 0x6e, 0x8e, 0x5f, 0x2d, 0x63, 0xff, 0xc2, 0x26, 0xcb, 0x5b, 0x0f, 0xb4, 0x2e, 0xb6,
|
||||
0x77, 0xae, 0xdf, 0x76, 0xd7, 0x57, 0x97, 0x9b, 0xdb, 0xcf, 0x4e, 0x7f, 0xad, 0xf3, 0xee, 0x5a,
|
||||
0x2c, 0x2c, 0xdf, 0x50, 0xa6, 0x02, 0x63, 0xdf, 0xf7, 0x9b, 0xcc, 0xc5, 0x0f, 0xe5, 0xbf, 0x1f,
|
||||
0x52, 0x70, 0x1e, 0xfc, 0xa4, 0xe7, 0x1e, 0x7e, 0xed, 0x06, 0x61, 0xdc, 0x23, 0xbc, 0xcc, 0x6e,
|
||||
0xf5, 0x0d, 0xb2, 0x93, 0x3e, 0xe7, 0x2f, 0x1c, 0xae, 0xbe, 0x43, 0x76, 0xce, 0xf3, 0xdb, 0x77,
|
||||
0x12, 0xbf, 0x7e, 0x5e, 0x7d, 0x8b, 0xec, 0x95, 0x17, 0x7f, 0x6d, 0x6e, 0xdc, 0xf9, 0x4f, 0x17,
|
||||
0x87, 0x7b, 0x84, 0x01, 0x5f, 0xb9, 0x2d, 0xca, 0x6d, 0xc2, 0x36, 0xeb, 0x0d, 0xec, 0x9a, 0x0d,
|
||||
0x75, 0x50, 0x82, 0xd7, 0x37, 0x2f, 0x75, 0xb3, 0x7a, 0xb2, 0xe9, 0xef, 0xf0, 0x6b, 0xa5, 0xe7,
|
||||
0x9b, 0xdd, 0xf6, 0x4e, 0xd8, 0x76, 0x72, 0x25, 0x9f, 0x9c, 0x8f, 0x56, 0xf2, 0x7c, 0xf5, 0x4a,
|
||||
0xce, 0xb4, 0xfe, 0xe5, 0x1a, 0xad, 0x37, 0x65, 0xbc, 0xb8, 0xd9, 0x6e, 0x2f, 0x8f, 0xd5, 0xfe,
|
||||
0xe5, 0x5a, 0xb5, 0x7f, 0x79, 0xc2, 0xfa, 0xfd, 0xf1, 0x0f, 0xfa, 0xc7, 0xaf, 0x6a, 0x5e, 0xf5,
|
||||
0xef, 0xee, 0x3e, 0x1f, 0x8d, 0xe1, 0x8f, 0x6f, 0x19, 0xc3, 0xcc, 0x00, 0x9d, 0x4f, 0x0d, 0xd0,
|
||||
0x93, 0xcd, 0xa7, 0xeb, 0x5b, 0x18, 0xbb, 0xf3, 0xdb, 0x6d, 0xbf, 0xbd, 0xeb, 0x8f, 0x8c, 0xd0,
|
||||
0x4d, 0xbf, 0xdb, 0xaf, 0x32, 0x5f, 0xe5, 0xce, 0xf7, 0x96, 0x2f, 0x99, 0xa1, 0x19, 0x58, 0xb2,
|
||||
0xe4, 0x1e, 0xde, 0x8c, 0xf4, 0xdd, 0xde, 0x97, 0xff, 0xbd, 0x56, 0xe9, 0xa6, 0xbf, 0x3a, 0x26,
|
||||
0xfa, 0xbd, 0x96, 0xe9, 0x46, 0x3c, 0xa3, 0xc9, 0xe4, 0xf9, 0x6b, 0x4f, 0xf7, 0xd1, 0x1c, 0x85,
|
||||
0xbf, 0x33, 0x92, 0x60, 0xac, 0xae, 0x3c, 0x09, 0xff, 0x61, 0xe2, 0xfd, 0xc4, 0x8d, 0x5e, 0xd1,
|
||||
0x67, 0xcb, 0xeb, 0xb9, 0xbc, 0xde, 0x96, 0xd7, 0x56, 0xf7, 0x60, 0x9d, 0x1e, 0x63, 0x3c, 0x6e,
|
||||
0xcf, 0x6b, 0xa8, 0xda, 0xe6, 0xe6, 0x66, 0xf7, 0x79, 0x22, 0x59, 0x3c, 0x2d, 0xfe, 0xa2, 0xb3,
|
||||
0x17, 0x40, 0x9b, 0x9f, 0xf8, 0xf8, 0xa1, 0x9a, 0xb3, 0x1f, 0x57, 0x5c, 0xfc, 0x44, 0x2e, 0xde,
|
||||
0x52, 0x26, 0x7b, 0x27, 0xaa, 0x7c, 0xfa, 0x0e, 0x5e, 0xf9, 0x48, 0xae, 0x7c, 0xb5, 0x77, 0x26,
|
||||
0xcf, 0x0e, 0x23, 0xfd, 0x0c, 0x18, 0xe0, 0xee, 0xed, 0xed, 0xf5, 0xc7, 0x37, 0x6f, 0xdd, 0x8d,
|
||||
0x8a, 0x98, 0x3b, 0xb0, 0xa1, 0xfb, 0xec, 0x95, 0xc0, 0xb9, 0x5f, 0xcd, 0x06, 0x1a, 0xe2, 0x11,
|
||||
0x85, 0x60, 0x14, 0xc2, 0x09, 0x0a, 0xf1, 0x24, 0x85, 0x1f, 0xdd, 0xfb, 0xed, 0xf6, 0xc6, 0x6d,
|
||||
0x37, 0xdd, 0x5b, 0x87, 0xdd, 0x71, 0x4c, 0xed, 0x85, 0x51, 0x7b, 0x71, 0x6a, 0x3c, 0x21, 0xaa,
|
||||
0xe2, 0x45, 0xd5, 0xbc, 0x14, 0x11, 0xec, 0x19, 0xd1, 0x0f, 0xfd, 0xcf, 0xf7, 0x30, 0xe8, 0xf1,
|
||||
0xff, 0xee, 0xe5, 0x88, 0x2f, 0xeb, 0x1e, 0x6d, 0x5b, 0xf7, 0x58, 0xd5, 0xe7, 0x72, 0xe1, 0xaf,
|
||||
0x5c, 0xd9, 0x57, 0xd7, 0xd7, 0x77, 0xf8, 0xbd, 0xe8, 0xd7, 0xef, 0xde, 0x1c, 0xec, 0x29, 0x48,
|
||||
0xcc, 0xb4, 0xfb, 0xd9, 0x54, 0xbb, 0xf1, 0xeb, 0xba, 0x97, 0xee, 0xbf, 0xb1, 0x30, 0x47, 0x8a,
|
||||
0x7d, 0x35, 0x89, 0x4f, 0xf0, 0xce, 0xff, 0x7f, 0x18, 0x31, 0xee, 0x29, 0xfe, 0x76, 0xbb, 0xb9,
|
||||
0xfc, 0xb8, 0xd9, 0xc9, 0x30, 0x2f, 0xdf, 0x7d, 0x70, 0xd0, 0x80, 0x15, 0xc2, 0xf5, 0xec, 0xb1,
|
||||
0xde, 0xec, 0x7b, 0xd9, 0x6a, 0xf9, 0x8e, 0x45, 0x47, 0xe1, 0xb8, 0x1c, 0x3c, 0xc0, 0x1f, 0x10,
|
||||
0xe2, 0x47, 0x61, 0xf7, 0xbf, 0x7f, 0x74, 0x41, 0xa4, 0x8f, 0x67, 0x25, 0xde, 0x7b, 0x23, 0x9b,
|
||||
0xcc, 0x58, 0xd6, 0xf6, 0x36, 0xf6, 0xd9, 0x0a, 0x1b, 0xfb, 0x9f, 0x4b, 0xfe, 0xe5, 0x33, 0x5b,
|
||||
0xe3, 0x54, 0x4e, 0x44, 0xe6, 0xa0, 0x7c, 0x33, 0x83, 0xfe, 0x62, 0x8d, 0x41, 0x7f, 0xa1, 0xa3,
|
||||
0x3d, 0x84, 0x59, 0xc7, 0xbb, 0xca, 0x8b, 0x7b, 0x2d, 0xfa, 0xc4, 0x86, 0xab, 0x09, 0xf9, 0x09,
|
||||
0x61, 0xdf, 0xfe, 0x3f, 0xfa, 0x52, 0x5a, 0x0d, 0x37, 0x5f, 0x3b, 0xfc, 0x18, 0xc5, 0xe6, 0xd5,
|
||||
0xf5, 0xc7, 0xbb, 0x9f, 0x5f, 0xed, 0x36, 0x57, 0xef, 0xe5, 0x2a, 0x3d, 0x2f, 0x5f, 0xf0, 0x56,
|
||||
0x3e, 0xbc, 0xa2, 0x0f, 0x3f, 0x54, 0xfe, 0xff, 0x20, 0x24, 0xfe, 0x2a, 0xbe, 0x7c, 0x00, 0x00,
|
||||
};
|
||||
1223
wled00/html_mobile.h
1223
wled00/html_mobile.h
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* Various pages
|
||||
* Various web pages
|
||||
*/
|
||||
|
||||
//USER HTML HERE (/u subpage)
|
||||
const char PAGE_usermod[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><body>No usermod installed or it doesn't specify a custom web page.</body></html>)=====";
|
||||
<html><body>No usermod custom web page set.</body></html>)=====";
|
||||
|
||||
|
||||
//server message
|
||||
@@ -12,25 +12,105 @@ const char PAGE_msg[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta content='width=device-width' name='viewport'>
|
||||
<title>WLED Message</title>
|
||||
<script>function B(){window.history.back()};function RS(){window.location = "/settings";}function RP(){top.location.href="/";}</script>
|
||||
%CSS%.bt{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:20px;margin:8px;margin-top:12px}body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);color:var(--tCol);line-height:200%%;margin:0}</style></head>
|
||||
<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>
|
||||
%CSS%.bt{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:20px;margin:8px;margin-top:12px}input[type=file]{font-size:16px}body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);color:var(--tCol);line-height:200%%}</style></head>
|
||||
<body><h2>WLED Software Update</h2>Installed version: 0.8.6<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>)=====";
|
||||
<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.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
|
||||
#ifndef WLED_DISABLE_MOBILE_UI
|
||||
const char PAGE_welcome[] PROGMEM = R"=====(<!DOCTYPE html><html><head><meta charset=utf-8><meta content='width=device-width' name=viewport><meta name=theme-color content=#333333><title>WLED Setup</title> <style>body{font-family:Verdana,Helvetica,sans-serif;text-align:center;background-color:#333;margin:0;color:#fff}button{outline:0;cursor:pointer}.btn{padding:8px;margin:10px;width:230px;text-transform:uppercase;font-family:helvetica;font-size:19px;background-color:#222;color:white;border:0 solid white;border-radius:5px}svg{fill:#fff}</style></head>
|
||||
<body> <svg style=position:absolute;width:0;height:0;overflow:hidden version=1.1 xmlns=http://www.w3.org/2000/svg> <defs> <symbol id=lnr-smile viewBox="0 0 1024 1024"><path d="M486.4 1024c-129.922 0-252.067-50.594-343.936-142.464s-142.464-214.014-142.464-343.936c0-129.923 50.595-252.067 142.464-343.936s214.013-142.464 343.936-142.464c129.922 0 252.067 50.595 343.936 142.464s142.464 214.014 142.464 343.936-50.594 252.067-142.464 343.936c-91.869 91.87-214.014 142.464-343.936 142.464zM486.4 102.4c-239.97 0-435.2 195.23-435.2 435.2s195.23 435.2 435.2 435.2 435.2-195.23 435.2-435.2-195.23-435.2-435.2-435.2z"></path><path d="M332.8 409.6c-42.347 0-76.8-34.453-76.8-76.8s34.453-76.8 76.8-76.8 76.8 34.453 76.8 76.8-34.453 76.8-76.8 76.8zM332.8 307.2c-14.115 0-25.6 11.485-25.6 25.6s11.485 25.6 25.6 25.6 25.6-11.485 25.6-25.6-11.485-25.6-25.6-25.6z"></path><path d="M640 409.6c-42.349 0-76.8-34.453-76.8-76.8s34.451-76.8 76.8-76.8 76.8 34.453 76.8 76.8-34.451 76.8-76.8 76.8zM640 307.2c-14.115 0-25.6 11.485-25.6 25.6s11.485 25.6 25.6 25.6 25.6-11.485 25.6-25.6-11.485-25.6-25.6-25.6z"></path><path d="M486.4 870.4c-183.506 0-332.8-149.294-332.8-332.8 0-14.139 11.462-25.6 25.6-25.6s25.6 11.461 25.6 25.6c0 155.275 126.325 281.6 281.6 281.6s281.6-126.325 281.6-281.6c0-14.139 11.461-25.6 25.6-25.6s25.6 11.461 25.6 25.6c0 183.506-149.294 332.8-332.8 332.8z"></path></symbol> </defs></svg> <br><br>
|
||||
<svg><use xlink:href=#lnr-smile></use></svg><h1>Welcome to WLED!</h1><h3>Thank you for installing my application!</h3> If you encounter a bug or have a question/feature suggestion, feel free to open a GitHub issue!<br><br> <b>Next steps:</b><br><br> Connect the module to your local WiFi here!<br> <button class=btn onclick="window.location.href='/settings/wifi'">WiFi settings</button><br> <i>Just trying this out in AP mode?</i><br> <button class=btn onclick="window.location.href='/sliders'">To the controls!</button></body></html>)=====";
|
||||
#else
|
||||
const char PAGE_welcome[] PROGMEM = "";
|
||||
#endif
|
||||
|
||||
|
||||
//liveview
|
||||
const char PAGE_liveview[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta name=viewport content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||
<meta charset=utf-8>
|
||||
<meta name=theme-color content=#222222>
|
||||
<title>WLED Live Preview</title>
|
||||
<style>
|
||||
body {margin: 0;}
|
||||
#canv {background: black;filter: brightness(175%);width: 100%;height: 100%;position: absolute;}
|
||||
</style></head>
|
||||
<body>
|
||||
<div id="canv" />
|
||||
<script>
|
||||
update();
|
||||
var tmout = null;
|
||||
function update()
|
||||
{
|
||||
if (document.hidden) {
|
||||
clearTimeout(tmout);
|
||||
tmout = setTimeout(update, 250);
|
||||
return;
|
||||
}
|
||||
fetch('/json/live')
|
||||
.then(res => {
|
||||
if (!res.ok) {
|
||||
clearTimeout(tmout);
|
||||
tmout = setTimeout(update, 2500);
|
||||
}
|
||||
return res.json();
|
||||
})
|
||||
.then(json => {
|
||||
var str = "linear-gradient(90deg,";
|
||||
var len = json.leds.length;
|
||||
for (i = 0; i < len; i++) {
|
||||
var leddata = json.leds[i];
|
||||
if (leddata.length > 6) leddata = leddata.substring(2);
|
||||
str += "#" + leddata;
|
||||
if (i < len -1) str += ","
|
||||
}
|
||||
str += ")";
|
||||
document.getElementById("canv").style.background = str;
|
||||
clearTimeout(tmout);
|
||||
tmout = setTimeout(update, 40);
|
||||
})
|
||||
.catch(function (error) {
|
||||
clearTimeout(tmout);
|
||||
tmout = setTimeout(update, 2500);
|
||||
})
|
||||
}
|
||||
</script>
|
||||
</body></html>)=====";
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
/*
|
||||
* Settings html
|
||||
* Settings html
|
||||
*/
|
||||
|
||||
//common CSS of settings pages
|
||||
const char PAGE_settingsCss[] PROGMEM = R"=====(body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);color:var(--tCol);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(--tCol);font-family:var(--cFn),sans-serif;border:.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(--tCol);font-family:var(--cFn),sans-serif;border:.5ch solid var(--bCol);filter:drop-shadow(-5px -5px 5px var(--sCol))}input[type=number]{width:4em}select{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:0.5ch solid var(--bCol);filter:drop-shadow( -5px -5px 5px var(--sCol) );}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>%CSS%body{text-align:center;background:var(--cCol);height:100%%;margin:0;background-attachment:fixed}html{--h:11.55vh}button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),Helvetica,sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));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>)=====";
|
||||
|
||||
|
||||
//wifi settings
|
||||
const char PAGE_settings_wifi[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500">
|
||||
<html><head><meta name="viewport" content="width=500"><meta charset="utf-8">
|
||||
<title>WiFi Settings</title><script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#wifi-settings");}function B(){window.history.back();}function GetV(){var d=document;
|
||||
%CSS%%SCSS%</head><body onload="GetV()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
@@ -52,7 +52,7 @@ mDNS address (leave empty for no mDNS):<br/>
|
||||
http:// <input name="CM" maxlength="32"> .local<br>
|
||||
Client IP: <span class="sip"> Not connected </span><br>
|
||||
<h3>Configure Access Point</h3>
|
||||
AP SSID (leave empty for no AP):<br><input name="AS" maxlength="32"><br>
|
||||
AP name (SSID):<br><input name="AS" maxlength="32"><br>
|
||||
Hide AP name: <input type="checkbox" name="AH"><br>
|
||||
AP password (leave empty for open):<br> <input type="password" name="AP" maxlength="63"><br>
|
||||
Access Point WiFi channel: <input name="AC" type="number" min="1" max="13" required><br>
|
||||
@@ -62,7 +62,12 @@ AP opens:
|
||||
<option value="1">Disconnected</option>
|
||||
<option value="2">Always</option>
|
||||
<option value="3">Never (not recommended)</option></select><br>
|
||||
AP IP: <span class="sip"> Not active </span><hr>
|
||||
AP IP: <span class="sip"> Not active </span><br>
|
||||
<h3>Experimental</h3>
|
||||
Disable WiFi sleep: <input type="checkbox" name="WS"><br>
|
||||
<i>Can help with connectivity issues.<br>
|
||||
Do not enable if WiFi is working correctly, increases power consumption.</i>
|
||||
<hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save & Connect</button>
|
||||
</form>
|
||||
</body>
|
||||
@@ -71,97 +76,164 @@ AP IP: <span class="sip"> Not active </span><hr>
|
||||
|
||||
//LED settings
|
||||
const char PAGE_settings_leds[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500">
|
||||
<title>LED Settings</title><script>var f=0,p=0;function H()
|
||||
{window.open("https://github.com/Aircoookie/WLED/wiki/Settings#led-settings");}
|
||||
function B(){window.open("/settings","_self");}function S(){GetV();setTimeout(function(){fillfx(0);},200);setTimeout(function(){fillfx(1);},400);UI();}
|
||||
function UI(){var myC=document.querySelectorAll('.wc'),l=myC.length;for(i=0;i<l;i++){myC[i].style.display=(document.getElementById('rgbw').checked)?'inline':'none';}
|
||||
var val=Math.ceil((100+document.Sf.LC.value*55)/500)/2;val=(val>5)?Math.ceil(val):val;var s="";if(val<1.02){s="ESP 5V pin with 1A USB supply";}else{s="External 5V ";s+=val;s+="A supply connected to LEDs";}document.getElementById('psu').innerHTML=s;}
|
||||
function fillfx(pl){e="<option>Error loading list!</option>";el=pl?Sf.FP:Sf.FX;fetch(pl?'/json/pal':'/json/eff').then(res=>{if(!res.ok){el.innerHTML=e;}
|
||||
return res.json();}).then(json=>{var x="";for(i in json){x+="<option value=\""+i+"\">"+json[i]+" ("+i+")</option>";}
|
||||
el.innerHTML=x;el.selectedIndex=pl?p:f;}).catch(function(){el.innerHTML=e;})}function GetV(){var d=document;%CSS%%SCSS%</head>
|
||||
<html><head>
|
||||
<meta charset=utf-8>
|
||||
<meta name=viewport content="width=500">
|
||||
<title>LED Settings</title>
|
||||
<script>var d=document,laprev=55;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#led-settings")}function B(){window.open("/settings","_self")}function S(){GetV();setABL()}
|
||||
function enABL(){var a=d.getElementById("able").checked;d.Sf.LA.value=(a)?laprev:0;d.getElementById("abl").style.display=(a)?"inline":"none";d.getElementById("psu2").style.display=(a)?"inline":"none";if(d.Sf.LA.value>0){setABL()}}function enLA(){var a=d.Sf.LAsel.value;d.Sf.LA.value=a;d.getElementById("LAdis").style.display=(a==50)?"inline":"none";UI()}function setABL(){d.getElementById("able").checked=true;d.Sf.LAsel.value=50;switch(parseInt(d.Sf.LA.value)){case 0:d.getElementById("able").checked=false;enABL();break;case 30:d.Sf.LAsel.value=30;break;case 35:d.Sf.LAsel.value=35;break;case 55:d.Sf.LAsel.value=55;break;case 255:d.Sf.LAsel.value=255;break;default:d.getElementById("LAdis").style.display="inline"}UI()}function UI(){var b=d.querySelectorAll(".wc"),a=b.length;for(i=0;i<a;i++){b[i].style.display=(d.getElementById("rgbw").checked)?"inline":"none"}d.getElementById("ledwarning").style.display=(d.Sf.LC.value>1000)?"inline":"none";d.getElementById("ampwarning").style.display=(d.Sf.MA.value>7200)?"inline":"none";if(d.Sf.LA.value==255){laprev=12} else if(d.Sf.LA.value>0){laprev=d.Sf.LA.value}var j=Math.ceil((100+d.Sf.LC.value*laprev)/500)/2;j=(j>5)?Math.ceil(j):j;var g="";var e=(d.Sf.LAsel.value==30);var i=(d.Sf.LAsel.value==255);if(j<1.02&&!e&&!i){g="ESP 5V pin with 1A USB supply"}else{g+=e?"12V ":i?"WS2815 12V ":"5V ";g+=j;g+="A supply connected to LEDs"}var h=Math.ceil((100+d.Sf.LC.value*laprev)/1500)/2;h=(h>5)?Math.ceil(h):h;var c="(for most effects, ~";c+=h;c+="A is enough)<br>";d.getElementById("psu").innerHTML=g;d.getElementById("psu2").innerHTML=i?"":c}function GetV(){var d=document;
|
||||
%CSS%%SCSS%</head><body onload=S()>
|
||||
<form id=form_s name=Sf method=post>
|
||||
<div class=helpB><button type=button onclick=H()>?</button></div>
|
||||
<button type=button onclick=B()>Back</button><button type=submit>Save</button><hr>
|
||||
<h2>LED setup</h2>
|
||||
LED count: <input name=LC type=number min=1 max=1500 oninput=UI() required><br>
|
||||
<div id=ledwarning style=color:orange;display:none>
|
||||
⚠ You might run into stability or lag issues.<br>
|
||||
Use less than 1000 LEDs per ESP for the best experience!<br>
|
||||
</div>
|
||||
<i>Recommended power supply for brightest white:</i><br>
|
||||
<b><span id=psu>?</span></b><br>
|
||||
<span id=psu2><br></span>
|
||||
<br>
|
||||
Enable automatic brightness limiter: <input type=checkbox name=ABen onchange=enABL() id=able><br>
|
||||
<div id=abl>
|
||||
Maximum Current: <input name=MA type=number min=250 max=65000 oninput=UI() required> mA<br>
|
||||
<div id=ampwarning style=color:orange;display:none>
|
||||
⚠ Your power supply provides high current.<br>
|
||||
To improve the safety of your setup,<br>
|
||||
please use thick cables,<br>
|
||||
multiple power injection points and a fuse!<br>
|
||||
</div>
|
||||
<i>Automatically limits brightness to stay close to the limit.<br>
|
||||
Keep at <1A if powering LEDs directly from the ESP 5V pin!<br>
|
||||
If you are using an external power supply, enter its rating.<br>
|
||||
(Current estimated usage: <span class=pow>unknown</span>)</i><br><br>
|
||||
LED voltage (Max. current for a single LED):<br>
|
||||
<select name=LAsel onchange=enLA()>
|
||||
<option value=55 selected>5V default (55mA)</option>
|
||||
<option value=35>5V efficient (35mA)</option>
|
||||
<option value=30>12V (30mA)</option>
|
||||
<option value=255>WS2815 (12mA)</option>
|
||||
<option value=50>Custom</option>
|
||||
</select><br>
|
||||
<span id=LAdis style=display:none>Custom max. current per LED: <input name=LA type=number min=0 max=255 id=la oninput=UI() required> mA<br></span>
|
||||
<i>Keep at default if you are unsure about your type of LEDs.</i><br>
|
||||
</div>
|
||||
<br>
|
||||
LEDs are 4-channel type (RGBW): <input type=checkbox name=EW onchange=UI() id=rgbw><br>
|
||||
<span class=wc>
|
||||
Auto-calculate white channel from RGB:<br>
|
||||
<select name=AW>
|
||||
<option value=0>None</option>
|
||||
<option value=1>Brighter</option>
|
||||
<option value=2>Accurate</option>
|
||||
<option value=3>Dual</option>
|
||||
<option value=4>Legacy</option>
|
||||
</select>
|
||||
<br></span>
|
||||
Color order:
|
||||
<select name=CO>
|
||||
<option value=0>GRB</option>
|
||||
<option value=1>RGB</option>
|
||||
<option value=2>BRG</option>
|
||||
<option value=3>RBG</option>
|
||||
<option value=4>BGR</option>
|
||||
<option value=5>GBR</option>
|
||||
</select>
|
||||
<h3>Defaults</h3>
|
||||
Turn LEDs on after power up/reset: <input type=checkbox name=BO><br>
|
||||
Default brightness: <input name=CA type=number min=0 max=255 required> (0-255)<br><br>
|
||||
Apply preset <input name=BP type=number min=0 max=16 required> at boot (0 uses defaults)
|
||||
<br>- <i>or</i> -<br>
|
||||
Set current preset cycle setting as boot default: <input type=checkbox name=PC><br><br>
|
||||
Use Gamma correction for color: <input type=checkbox name=GC> (strongly recommended)<br>
|
||||
Use Gamma correction for brightness: <input type=checkbox name=GB> (not recommended)<br><br>
|
||||
Brightness factor: <input name=BF type=number min=1 max=255 required> %
|
||||
<h3>Transitions</h3>
|
||||
Crossfade: <input type=checkbox name=TF><br>
|
||||
Transition Time: <input name=TD maxlength=5 size=2> ms<br>
|
||||
Enable Palette transitions: <input type=checkbox name=PF>
|
||||
<h3>Timed light</h3>
|
||||
Default Duration: <input name=TL type=number min=1 max=255 required> min<br>
|
||||
Default Target brightness: <input name=TB type=number min=0 max=255 required><br>
|
||||
Fade down: <input type=checkbox name=TW><br>
|
||||
<h3>Advanced</h3>
|
||||
Palette blending:
|
||||
<select name=PB>
|
||||
<option value=0>Linear (wrap if moving)</option>
|
||||
<option value=1>Linear (always wrap)</option>
|
||||
<option value=2>Linear (never wrap)</option>
|
||||
<option value=3>None (not recommended)</option>
|
||||
</select><br>
|
||||
Reverse LED order (rotate 180): <input type=checkbox name=RV><br>
|
||||
Skip first LED: <input type=checkbox name=SL><hr>
|
||||
<button type=button onclick=B()>Back</button><button type=submit>Save</button>
|
||||
</form></body></html>)=====";
|
||||
|
||||
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
//DMX Output settings
|
||||
const char PAGE_settings_dmx[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500"><meta charset="utf-8"><title>DMX Settings</title><script>
|
||||
function GCH(num) {
|
||||
d=document;
|
||||
|
||||
d.getElementById('dmxchannels').innerHTML += "";
|
||||
for (i=0;i<num;i++) {
|
||||
d.getElementById('dmxchannels').innerHTML += "<span id=CH" + (i+1) + "s >Channel " + (i+1) + ": <select name=CH" + (i+1) + " id=\"CH" + (i+1) + "\"><option value=0>Set to 0</option><option value=1>Red</option><option value=2>Green</option><option value=3>Blue</option><option value=4>White</option><option value=5>Shutter (Brightness)</option><option value=6>Set to 255</option></select></span><br />\n";
|
||||
}
|
||||
}
|
||||
function mMap(){
|
||||
d=document;
|
||||
numCh=document.Sf.CN.value;
|
||||
numGap=document.Sf.CG.value;
|
||||
if (parseInt(numCh)>parseInt(numGap)) {
|
||||
d.getElementById("gapwarning").style.display="block";
|
||||
} else {
|
||||
d.getElementById("gapwarning").style.display="none";
|
||||
}
|
||||
for (i=0;i<15;i++) {
|
||||
if (i>=numCh) {
|
||||
d.getElementById("CH"+(i+1) + "s").style.opacity = "0.5";
|
||||
d.getElementById("CH"+(i+1)).disabled = true;
|
||||
|
||||
} else {
|
||||
d.getElementById("CH"+(i+1) + "s").style.opacity = "1";
|
||||
d.getElementById("CH"+(i+1)).disabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
function S(){GCH(15);GetV();mMap();}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}function B(){window.history.back();}function GetV(){var d=document;
|
||||
%CSS%%SCSS%</head>
|
||||
<body onload="S()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
<h2>LED setup</h2>
|
||||
LED count: <input name="LC" type="number" min="1" max="1500" oninput=UI() required><br>
|
||||
<i>Recommended power supply for brightest white:</i><br>
|
||||
<b><span id="psu">?</span></b><br><br>
|
||||
Maximum Current: <input name="MA" type="number" min="250" max="65000" required> mA<br>
|
||||
<i>Automatically limits brightness to stay close to the limit.<br>
|
||||
Keep at <1A if powering LEDs directly from the ESP 5V pin!<br>
|
||||
If you are using an external 5V supply, enter its rating.<br>
|
||||
"65000" completely diasbles the power calculation.<br>
|
||||
(Current estimated usage: <span class="pow">unknown</span>)</i><br><br>
|
||||
LEDs are 4-channel type (RGBW): <input type="checkbox" name="EW" onchange=UI() id="rgbw"><br>
|
||||
Color order:
|
||||
<select name="CO">
|
||||
<option value="0">GRB</option>
|
||||
<option value="1">RGB</option>
|
||||
<option value="2">BRG</option>
|
||||
<option value="3">RBG</option></select>
|
||||
<h3>Defaults</h3>
|
||||
Turn LEDs on after power up/reset: <input type="checkbox" name="BO"><br>
|
||||
Default brightness: <input name="CA" type="number" min="0" max="255" required> (0-255)<br><br>
|
||||
Set current color, brightness and effects as boot default: <input type="checkbox" name="IS"><br>
|
||||
Set current preset cycle setting as boot default: <input type="checkbox" name="PC">
|
||||
<br>- <i>or</i> -<br>
|
||||
Apply preset <input name="BP" type="number" min="0" max="25" required> at boot (0 uses defaults)
|
||||
<br>- <i>or</i> -<br>
|
||||
Default RGB<span class="wc">W</span> color:<br>
|
||||
<input name="CR" type="number" min="0" max="255" required>
|
||||
<input name="CG" type="number" min="0" max="255" required>
|
||||
<input name="CB" type="number" min="0" max="255" required>
|
||||
<span class="wc"><input name="CW" type="number" min="0" max="255" required><br>
|
||||
Auto-calculate white from RGB instead: <input type="checkbox" name="AW"></span><br>
|
||||
Default secondary RGB<span class="wc">W</span>:<br>
|
||||
<input name="SR" type="number" min="0" max="255" required>
|
||||
<input name="SG" type="number" min="0" max="255" required>
|
||||
<input name="SB" type="number" min="0" max="255" required>
|
||||
<span class="wc"><input name="SW" type="number" min="0" max="255" required></span><br>
|
||||
Default effect ID:<br>
|
||||
<select name="FX">
|
||||
<option>Loading...</option>
|
||||
</select>
|
||||
<br>Default color palette:<br>
|
||||
<select name="FP">
|
||||
<option>Loading...</option>
|
||||
</select><br>
|
||||
Default effect speed: <input name="SX" type="number" min="0" max="255" required><br>
|
||||
Default effect intensity: <input name="IX" type="number" min="0" max="255" required><br><br>
|
||||
Use Gamma correction for color: <input type="checkbox" name="GC"> (strongly recommended)<br>
|
||||
Use Gamma correction for brightness: <input type="checkbox" name="GB"> (not recommended)<br><br>
|
||||
Brightness factor: <input name="BF" type="number" min="0" max="255" required> %%
|
||||
<h3>Transitions</h3>
|
||||
Crossfade: <input type="checkbox" name="TF"><br>
|
||||
Transition Time: <input name="TD" maxlength="5" size="2"> ms<br>
|
||||
Enable transition for secondary color: <input type="checkbox" name="T2"><br>
|
||||
Enable Palette transitions: <input type="checkbox" name="PF">
|
||||
<h3>Timed light</h3>
|
||||
Default Duration: <input name="TL" type="number" min="1" max="255" required> min<br>
|
||||
Default Target brightness: <input name="TB" type="number" min="0" max="255" required><br>
|
||||
Fade down: <input type="checkbox" name="TW"><br>
|
||||
<h3>Advanced</h3>
|
||||
Palette blending:
|
||||
<select name="PB">
|
||||
<option value="0">Linear (wrap if moving)</option>
|
||||
<option value="1">Linear (always wrap)</option>
|
||||
<option value="2">Linear (never wrap)</option>
|
||||
<option value="3">None (not recommended)</option>
|
||||
</select><br>
|
||||
Reverse LED order (rotate 180): <input type="checkbox" name="RV"><br>
|
||||
Skip first LED: <input type="checkbox" name="SL"><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
<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">
|
||||
<title>UI Settings</title><script>
|
||||
<html><head><meta name="viewport" content="width=500"><meta charset="utf-8"><title>UI Settings</title><script>
|
||||
function gId(s){return document.getElementById(s);}function S(){GetV();Ct();}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#user-interface-settings");}function B(){window.history.back();}function Ct(){if (gId("co").selected){gId("cth").style.display="block";}else{gId("cth").style.display="none";}}function GetV(){var d=document;
|
||||
%CSS%%SCSS%</head>
|
||||
<body onload="S()">
|
||||
@@ -169,125 +241,118 @@ function gId(s){return document.getElementById(s);}function S(){GetV();Ct();}fun
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
<h2>Web Setup</h2>
|
||||
User Interface Mode:
|
||||
<select name="UI">
|
||||
<option value="0" selected>Auto</option>
|
||||
<option value="1">Classic</option>
|
||||
<option value="2">Mobile</option>
|
||||
</select><br>
|
||||
Server description: <input name="DS" maxlength="32"><br><br>
|
||||
<i>The following options are for the classic UI!</i><br>
|
||||
Use HSB sliders instead of RGB by default: <input type="checkbox" name="MD"><br>
|
||||
Color Theme:
|
||||
<select name="TH" onchange="Ct()">
|
||||
<option value="0" selected>Night</option>
|
||||
<option value="1">Modern</option>
|
||||
<option value="2">Bright</option>
|
||||
<option value="3">Wine</option>
|
||||
<option value="4">Electric</option>
|
||||
<option value="5">Mint</option>
|
||||
<option value="6">Amber</option>
|
||||
<option value="7">Dark</option>
|
||||
<option value="8">Air</option>
|
||||
<option value="9">Nixie</option>
|
||||
<option value="10">Terminal</option>
|
||||
<option value="11">C64</option>
|
||||
<option value="12">Easter</option>
|
||||
<option value="13">Christmas</option>
|
||||
<option value="14">The End</option>
|
||||
<option value="15" id="co">Custom</option>
|
||||
</select><br>
|
||||
<div id="cth">
|
||||
Please specify your custom hex colors (e.g. FF0000 for red)<br>
|
||||
Custom accent color: <input maxlength=9 name="C0"><br>
|
||||
Custom background: <input maxlength=9 name="C1"><br>
|
||||
Custom panel color: <input maxlength=9 name="C2"><br>
|
||||
Custom icon color: <input maxlength=9 name="C3"><br>
|
||||
Custom shadow: <input maxlength=9 name="C4"><br>
|
||||
Custom text color: <input maxlength=9 name="C5"><br></div>
|
||||
Use font: <input maxlength=32 name="CF"><br>
|
||||
Make sure the font you use is installed on your system!<br>
|
||||
Server description: <input name="DS" maxlength="32"><br>
|
||||
Sync button toggles both send and receive: <input type="checkbox" name="ST"><br><br>
|
||||
<hr><button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>)=====";
|
||||
|
||||
|
||||
|
||||
//sync settings
|
||||
const char PAGE_settings_sync[] PROGMEM = R"=====(<!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(){var d=document;
|
||||
<html><head><meta name=viewport content="width=500"><meta charset=utf-8><title>Sync Settings</title>
|
||||
<script>var d=document;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#sync-settings")}function B(){window.open("/settings","_self")}function adj(){if(d.Sf.DI.value==6454){if(d.Sf.DA.value==1){d.Sf.DA.value=0}if(d.Sf.EU.value==1){d.Sf.EU.value=0}}else{if(d.Sf.DI.value==5568){if(d.Sf.DA.value==0){d.Sf.DA.value=1}if(d.Sf.EU.value==0){d.Sf.EU.value=1}}}}function SP(){var a=d.Sf.DI.value;d.getElementById("xp").style.display=(a>0)?"none":"block";if(a>0){d.Sf.EP.value=a}}function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568:d.Sf.DI.value=5568;break;case 6454:d.Sf.DI.value=6454;break}SP()}function S(){GetV();SetVal()};function GetV(){
|
||||
%CSS%%SCSS%</head>
|
||||
<body onload="GetV()">
|
||||
<form id="form_s" name="Sf" method="post">
|
||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
<body onload=S()>
|
||||
<form id=form_s name=Sf method=post>
|
||||
<div class=helpB><button type=button onclick=H()>?</button></div>
|
||||
<button type=button onclick=B()>Back</button><button type=submit>Save</button><hr>
|
||||
<h2>Sync setup</h2>
|
||||
<h3>Button setup</h3>
|
||||
On/Off button enabled: <input type="checkbox" name="BT"><br>
|
||||
Infrared receiver enabled: <input type="checkbox" name="IR"><br>
|
||||
<a href="https://github.com/Aircoookie/WLED/wiki/Infrared-Control" target="_blank">IR info</a>
|
||||
On/Off button enabled: <input type=checkbox name=BT><br>
|
||||
Infrared remote:
|
||||
<select name=IR>
|
||||
<option value=0>Disabled</option>
|
||||
<option value=1>24-key RGB</option>
|
||||
<option value=2>24-key with CT</option>
|
||||
<option value=3>40-key blue</option>
|
||||
<option value=4>44-key RGB</option>
|
||||
<option value=5>21-key RGB</option>
|
||||
<option value=6>6-key black</option>
|
||||
</select><br>
|
||||
<a href=https://github.com/Aircoookie/WLED/wiki/Infrared-Control target=_blank>IR info</a>
|
||||
<h3>WLED Broadcast</h3>
|
||||
UDP Port: <input name="UP" type="number" min="1" max="65535" required><br>
|
||||
Receive <input type="checkbox" name="RB">Brightness, <input type="checkbox" name="RC">Color, and <input type="checkbox" name="RX">Effects<br>
|
||||
Send notifications on direct change: <input type="checkbox" name="SD"><br>
|
||||
Send notifications on button press: <input type="checkbox" name="SB"><br>
|
||||
Send Alexa notifications: <input type="checkbox" name="SA"><br>
|
||||
Send Philips Hue change notifications: <input type="checkbox" name="SH"><br>
|
||||
Send Macro notifications: <input type="checkbox" name="SM"><br>
|
||||
Send notifications twice: <input type="checkbox" name="S2">
|
||||
UDP Port: <input name=UP type=number min=1 max=65535 class=d5 required><br>
|
||||
Receive <input type=checkbox name=RB>Brightness, <input type=checkbox name=RC>Color, and <input type=checkbox name=RX>Effects<br>
|
||||
Send notifications on direct change: <input type=checkbox name=SD><br>
|
||||
Send notifications on button press: <input type=checkbox name=SB><br>
|
||||
Send Alexa notifications: <input type=checkbox name=SA><br>
|
||||
Send Philips Hue change notifications: <input type=checkbox name=SH><br>
|
||||
Send Macro notifications: <input type=checkbox name=SM><br>
|
||||
Send notifications twice: <input type=checkbox name=S2>
|
||||
<h3>Realtime</h3>
|
||||
Receive UDP realtime: <input type="checkbox" name="RD"><br><br>
|
||||
<i>E1.31 (sACN)</i><br>
|
||||
Use E1.31 multicast: <input type="checkbox" name="EM"><br>
|
||||
E1.31 start universe: <input name="EU" type="number" min="1" max="63999" required><br>
|
||||
<i>Reboot required.</i> Check out <a href="https://github.com/ahodges9/LedFx" target="_blank">LedFx</a>!<br><br>
|
||||
Timeout: <input name="ET" type="number" min="1" max="65000" required> ms<br>
|
||||
Force max brightness: <input type="checkbox" name="FB"><br>
|
||||
Disable realtime gamma correction: <input type="checkbox" name="RG"><br>
|
||||
Realtime LED offset: <input name="WO" type="number" min="-255" max="255" required>
|
||||
Receive UDP realtime: <input type=checkbox name=RD><br><br>
|
||||
<i>Network DMX input</i><br>
|
||||
Type:
|
||||
<select name=DI onchange=SP();adj()>
|
||||
<option value=5568>E1.31 (sACN)</option>
|
||||
<option value=6454>Art-Net</option>
|
||||
<option value=0 selected>Custom port</option>
|
||||
</select><br>
|
||||
<div id=xp>Port: <input name=EP type=number min=1 max=65535 value=5568 class=d5 required><br></div>
|
||||
Multicast: <input type=checkbox name=EM><br>
|
||||
Start universe: <input name=EU type=number min=0 max=63999 required><br>
|
||||
<i>Reboot required.</i> Check out <a href=https://github.com/ahodges9/LedFx target=_blank>LedFx</a>!<br>
|
||||
Skip out-of-sequence packets: <input type=checkbox name=ES><br>
|
||||
DMX start address: <input name=DA type=number min=0 max=510 required><br>
|
||||
DMX mode:
|
||||
<select name=DM>
|
||||
<option value=0>Disabled</option>
|
||||
<option value=1>Single RGB</option>
|
||||
<option value=2>Single DRGB</option>
|
||||
<option value=3>Effect</option>
|
||||
<option value=4>Multi RGB</option>
|
||||
<option value=5>Multi DRGB</option>
|
||||
</select><br>
|
||||
<a href=https://github.com/Aircoookie/WLED/wiki/E1.31-DMX target=_blank>E1.31 info</a><br>
|
||||
Timeout: <input name=ET type=number min=1 max=65000 required> ms<br>
|
||||
Force max brightness: <input type=checkbox name=FB><br>
|
||||
Disable realtime gamma correction: <input type=checkbox name=RG><br>
|
||||
Realtime LED offset: <input name=WO type=number min=-255 max=255 required>
|
||||
<h3>Alexa Voice Assistant</h3>
|
||||
Emulate Alexa device: <input type="checkbox" name="AL"><br>
|
||||
Alexa invocation name: <input name="AI" maxlength="32">
|
||||
Emulate Alexa device: <input type=checkbox name=AL><br>
|
||||
Alexa invocation name: <input name=AI maxlength=32>
|
||||
<h3>Blynk</h3>
|
||||
<b>Blynk, MQTT and Hue sync all connect to external hosts!<br>
|
||||
This may impact the responsiveness of the ESP8266.</b><br>
|
||||
For best results, only use one of these services at a time.<br>
|
||||
(alternatively, connect a second ESP to them and use the UDP sync)<br><br>
|
||||
Device Auth token: <input name="BK" maxlength="33"><br>
|
||||
<i>Clear the token field to disable. </i><a href="https://github.com/Aircoookie/WLED/wiki/Blynk" target="_blank">Setup info</a>
|
||||
Device Auth token: <input name=BK maxlength=33><br>
|
||||
<i>Clear the token field to disable. </i><a href=https://github.com/Aircoookie/WLED/wiki/Blynk target=_blank>Setup info</a>
|
||||
<h3>MQTT</h3>
|
||||
Broker: <input name="MS" maxlength="32">
|
||||
Port: <input name="MQPORT" type="number" min="1" max="65535" required><br>
|
||||
Enable MQTT: <input type=checkbox name=MQ><br>
|
||||
Broker: <input name=MS maxlength=32>
|
||||
Port: <input name=MQPORT type=number min=1 max=65535 class=d5><br>
|
||||
<b>The MQTT credentials are sent over an unsecured connection.<br>
|
||||
Never use the MQTT password for another service!</b><br>
|
||||
Username: <input name="MQUSER" maxlength="40"><br>
|
||||
Password: <input type="password" input name="MQPASS" maxlength="40"><br>
|
||||
Client ID: <input name="MQCID" maxlength="40"><br>
|
||||
Device Topic: <input name="MD" maxlength="32"><br>
|
||||
Group Topic: <input name="MG" maxlength="32"><br>
|
||||
<i>Reboot required to apply changes. </i><a href="https://github.com/Aircoookie/WLED/wiki/MQTT" target="_blank">MQTT info</a>
|
||||
Username: <input name=MQUSER maxlength=40><br>
|
||||
Password: <input type=password input name=MQPASS maxlength=40><br>
|
||||
Client ID: <input name=MQCID maxlength=40><br>
|
||||
Device Topic: <input name=MD maxlength=32><br>
|
||||
Group Topic: <input name=MG maxlength=32><br>
|
||||
<i>Reboot required to apply changes. </i><a href=https://github.com/Aircoookie/WLED/wiki/MQTT target=_blank>MQTT info</a>
|
||||
<h3>Philips Hue</h3>
|
||||
<i>You can find the bridge IP and the light number in the 'About' section of the hue app.</i><br>
|
||||
Poll Hue light <input name="HL" type="number" min="1" max="99" required> every <input name="HI" type="number" min="100" max="65000" required> ms: <input type="checkbox" name="HP"><br>
|
||||
Then, receive <input type="checkbox" name="HO"> On/Off, <input type="checkbox" name="HB"> Brightness, and <input type="checkbox" name="HC"> Color<br>
|
||||
Poll Hue light <input name=HL type=number min=1 max=99> every <input name=HI type=number min=100 max=65000> ms: <input type=checkbox name=HP><br>
|
||||
Then, receive <input type=checkbox name=HO> On/Off, <input type=checkbox name=HB> Brightness, and <input type=checkbox name=HC> Color<br>
|
||||
Hue Bridge IP:<br>
|
||||
<input name="H0" type="number" min="0" max="255" required> .
|
||||
<input name="H1" type="number" min="0" max="255" required> .
|
||||
<input name="H2" type="number" min="0" max="255" required> .
|
||||
<input name="H3" type="number" min="0" max="255" required><br>
|
||||
<input name=H0 type=number min=0 max=255> .
|
||||
<input name=H1 type=number min=0 max=255> .
|
||||
<input name=H2 type=number min=0 max=255> .
|
||||
<input name=H3 type=number min=0 max=255><br>
|
||||
<b>Press the pushlink button on the bridge, after that save this page!</b><br>
|
||||
(when first connecting)<br>
|
||||
Hue status: <span class="hms"> Internal ESP Error! </span><hr>
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button>
|
||||
Hue status: <span class=sip> Disabled in this build </span><hr>
|
||||
<button type=button onclick=B()>Back</button><button type=submit>Save</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>)=====";
|
||||
</body></html>)=====";
|
||||
|
||||
|
||||
//time and macro settings
|
||||
const char PAGE_settings_time[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500"><title>Time Settings</title>
|
||||
<html><head><meta name="viewport" content="width=500"><meta charset="utf-8"><title>Time Settings</title>
|
||||
<script>var d=document;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#time-settings");}function B(){window.open("/settings","_self");}function S(){BTa();GetV();Cs();FC();}function gId(s){return d.getElementById(s);}function Cs(){gId("cac").style.display="none";gId("coc").style.display="block";gId("ccc").style.display="none";if (gId("ca").selected){gId("cac").style.display="block";}if (gId("cc").selected){gId("coc").style.display="none";gId("ccc").style.display="block";}if (gId("cn").selected){gId("coc").style.display="none";}}
|
||||
function BTa(){var ih="<tr><th>Active</th><th>Hour</th><th>Minute</th><th>Macro</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr>";for (i=0;i<8;i++){ih+="<tr><td><input name=\"W"+i+"\" id=\"W"+i+"\" type=\"number\" style=\"display:none\"><input id=\"W"+i+"0\" type=\"checkbox\"></td><td><input name=\"H"+i+"\" type=\"number\" min=\"0\" max=\"24\"></td><td><input name=\"N"+i+"\" type=\"number\" min=\"0\" max=\"59\"></td><td><input name=\"T"+i+"\" type=\"number\" min=\"0\" max=\"16\"></td>";for (j=1;j<8;j++) ih+="<td><input id=\"W"+i+j+"\" type=\"checkbox\"></td>";}gId("TMT").innerHTML=ih;}
|
||||
function FC(){for(j=0;j<8;j++){for(i=0;i<8;i++)gId("W"+i+j).checked=gId("W"+i).value>>j&1;}}
|
||||
@@ -299,6 +364,7 @@ function Wd(){a=[0,0,0,0,0,0,0,0];for(i=0;i<8;i++){m=1;for(j=0;j<8;j++){a[i]+=gI
|
||||
<button type="button" onclick="B()">Back</button><button type="submit">Save</button><hr>
|
||||
<h2>Time setup</h2>
|
||||
Get time from NTP server: <input type="checkbox" name="NT"><br>
|
||||
<input name="NS" maxlength="32"><br>
|
||||
Use 24h format: <input type="checkbox" name="CF"><br>
|
||||
Time zone:
|
||||
<select name="TZ">
|
||||
@@ -316,6 +382,10 @@ Time zone:
|
||||
<option value="11">AEST/AEDT</option>
|
||||
<option value="12">NZST/NZDT</option>
|
||||
<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>.
|
||||
@@ -324,7 +394,7 @@ Clock Overlay:
|
||||
<select name="OL" onchange="Cs()">
|
||||
<option value="0" id="cn" selected>None</option>
|
||||
<option value="1" id="ca">Analog Clock</option>
|
||||
<option value="2">Single Digit Clock</option>
|
||||
<option value="2" disabled>-</option>
|
||||
<option value="3" id="cc">Cronixie Clock</option>
|
||||
</select><br>
|
||||
<div id="coc">
|
||||
@@ -379,7 +449,7 @@ Time-Controlled macros:<br>
|
||||
|
||||
//security settings and about
|
||||
const char PAGE_settings_sec[] PROGMEM = R"=====(<!DOCTYPE html>
|
||||
<html><head><meta name="viewport" content="width=500">
|
||||
<html><head><meta name="viewport" content="width=500"><meta charset="utf-8">
|
||||
<title>Misc Settings</title>
|
||||
<script>function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#security-settings");}function B(){window.open("/settings","_self");}function U(){window.open("/update","_self");}function GetV(){var d=document;
|
||||
%CSS%%SCSS%</head>
|
||||
@@ -402,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.8.6<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>
|
||||
(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>
|
||||
|
||||
1697
wled00/html_ui.h
Normal file
1697
wled00/html_ui.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,16 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Sync to Philips hue lights
|
||||
*/
|
||||
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
|
||||
void handleHue()
|
||||
{
|
||||
if (hueReceived)
|
||||
{
|
||||
colorUpdated(7); hueReceived = false;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_HUE); hueReceived = false;
|
||||
if (hueStoreAllowed && hueNewKey)
|
||||
{
|
||||
saveSettingsToEEPROM(); //save api key
|
||||
@@ -23,7 +27,7 @@ void handleHue()
|
||||
reconnectHue();
|
||||
} else {
|
||||
hueClient->close();
|
||||
if (hueError[0] == 'A') strcpy(hueError,"Inactive");
|
||||
if (hueError == HUE_ERROR_ACTIVE) hueError = HUE_ERROR_INACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +48,7 @@ void reconnectHue()
|
||||
void onHueError(void* arg, AsyncClient* client, int8_t error)
|
||||
{
|
||||
DEBUG_PRINTLN("Hue err");
|
||||
strcpy(hueError,"Request timeout");
|
||||
hueError = HUE_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
void onHueConnect(void* arg, AsyncClient* client)
|
||||
@@ -59,15 +63,15 @@ void sendHuePoll()
|
||||
String req = "";
|
||||
if (hueAuthRequired)
|
||||
{
|
||||
req += "POST /api HTTP/1.1\r\nHost: ";
|
||||
req += F("POST /api HTTP/1.1\r\nHost: ");
|
||||
req += hueIP.toString();
|
||||
req += "\r\nContent-Length: 25\r\n\r\n{\"devicetype\":\"wled#esp\"}";
|
||||
req += F("\r\nContent-Length: 25\r\n\r\n{\"devicetype\":\"wled#esp\"}");
|
||||
} else
|
||||
{
|
||||
req += "GET /api/";
|
||||
req += hueApiKey;
|
||||
req += "/lights/" + String(huePollLightId);
|
||||
req += " HTTP/1.1\r\nHost: ";
|
||||
req += F(" HTTP/1.1\r\nHost: ");
|
||||
req += hueIP.toString();
|
||||
req += "\r\n\r\n";
|
||||
}
|
||||
@@ -93,21 +97,18 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
|
||||
auto error = deserializeJson(root, str);
|
||||
if (error)
|
||||
{
|
||||
strcpy(hueError,"JSON parsing error"); return;
|
||||
hueError = HUE_ERROR_JSON_PARSING; return;
|
||||
}
|
||||
|
||||
int hueErrorCode = root[0]["error"]["type"];
|
||||
if (hueErrorCode)//hue bridge returned error
|
||||
{
|
||||
hueError = hueErrorCode;
|
||||
switch (hueErrorCode)
|
||||
{
|
||||
case 1: strcpy(hueError,"Unauthorized"); hueAuthRequired = true; break;
|
||||
case 3: strcpy(hueError,"Invalid light ID"); huePollingEnabled = false; break;
|
||||
case 101: strcpy(hueError,"Link button not pressed"); hueAuthRequired = true; break;
|
||||
default:
|
||||
char coerr[18];
|
||||
sprintf(coerr,"Bridge Error %i",hueErrorCode);
|
||||
strcpy(hueError,coerr);
|
||||
case 1: hueAuthRequired = true; break; //Unauthorized user
|
||||
case 3: huePollingEnabled = false; break; //Invalid light ID
|
||||
case 101: hueAuthRequired = true; break; //link button not presset
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -133,7 +134,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
|
||||
auto error = deserializeJson(root, str);
|
||||
if (error)
|
||||
{
|
||||
strcpy(hueError,"JSON parsing error"); return;
|
||||
hueError = HUE_ERROR_JSON_PARSING; return;
|
||||
}
|
||||
|
||||
float hueX=0, hueY=0;
|
||||
@@ -173,7 +174,7 @@ void onHueData(void* arg, AsyncClient* client, void *data, size_t len)
|
||||
hueBri = 0;
|
||||
}
|
||||
|
||||
strcpy(hueError,"Active");
|
||||
hueError = HUE_ERROR_ACTIVE;
|
||||
|
||||
//apply vals
|
||||
if (hueBri != hueBriLast)
|
||||
466
wled00/ir.cpp
Normal file
466
wled00/ir.cpp
Normal file
@@ -0,0 +1,466 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Infrared sensor support for generic 24/40/44 key RGB remotes
|
||||
*/
|
||||
|
||||
#if defined(WLED_DISABLE_INFRARED)
|
||||
void handleIR(){}
|
||||
#else
|
||||
|
||||
IRrecv* irrecv;
|
||||
//change pin in NpbWrapper.h
|
||||
|
||||
decode_results results;
|
||||
|
||||
unsigned long irCheckedTime = 0;
|
||||
uint32_t lastValidCode = 0;
|
||||
uint16_t irTimesRepeated = 0;
|
||||
uint8_t lastIR6ColourIdx = 0;
|
||||
|
||||
|
||||
//Add what your custom IR codes should trigger here. Guide: https://github.com/Aircoookie/WLED/wiki/Infrared-Control
|
||||
//IR codes themselves can be defined directly after "case" or in "ir_codes.h"
|
||||
bool decodeIRCustom(uint32_t code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
//just examples, feel free to modify or remove
|
||||
case IRCUSTOM_ONOFF : toggleOnOff(); break;
|
||||
case IRCUSTOM_MACRO1 : applyMacro(1); break;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
if (code != IRCUSTOM_MACRO1) colorUpdated(NOTIFIER_CALL_MODE_BUTTON); //don't update color again if we apply macro, it already does it
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//relatively change brightness, minumum A=5
|
||||
void relativeChange(byte* property, int8_t amount, byte lowerBoundary, byte higherBoundary)
|
||||
{
|
||||
int16_t new_val = (int16_t) *property + amount;
|
||||
if (new_val > higherBoundary) new_val = higherBoundary;
|
||||
else if (new_val < lowerBoundary) new_val = lowerBoundary;
|
||||
*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)
|
||||
{
|
||||
if (code == 0xFFFFFFFF) //repeated code, continue brightness up/down
|
||||
{
|
||||
irTimesRepeated++;
|
||||
if (lastValidCode == IR24_BRIGHTER || lastValidCode == IR40_BPLUS )
|
||||
{
|
||||
relativeChange(&bri, 10); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
else if (lastValidCode == IR24_DARKER || lastValidCode == IR40_BMINUS )
|
||||
{
|
||||
relativeChange(&bri, -10, 5); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
if (lastValidCode == IR40_WPLUS)
|
||||
{
|
||||
relativeChangeWhite(10); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
else if (lastValidCode == IR40_WMINUS)
|
||||
{
|
||||
relativeChangeWhite(-10, 5); colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
else if ((lastValidCode == IR24_ON || lastValidCode == IR40_ON) && irTimesRepeated > 7 )
|
||||
{
|
||||
nightlightActive = true;
|
||||
nightlightStartTime = millis();
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON);
|
||||
}
|
||||
return;
|
||||
}
|
||||
lastValidCode = 0; irTimesRepeated = 0;
|
||||
|
||||
if (decodeIRCustom(code)) return;
|
||||
if (code > 0xFFFFFF) return; //invalid code
|
||||
else if (code > 0xF70000 && code < 0xF80000) decodeIR24(code); //is in 24-key remote range
|
||||
else if (code > 0xFF0000) {
|
||||
switch (irEnabled) {
|
||||
case 1: decodeIR24OLD(code); break; // white 24-key remote (old) - it sends 0xFF0000 values
|
||||
case 2: decodeIR24CT(code); break; // white 24-key remote with CW, WW, CT+ and CT- keys
|
||||
case 3: decodeIR40(code); break; // blue 40-key remote with 25%, 50%, 75% and 100% keys
|
||||
case 4: decodeIR44(code); break; // white 44-key remote with color-up/down keys and DIY1 to 6 keys
|
||||
case 5: decodeIR21(code); break; // white 21-key remote
|
||||
case 6: decodeIR6(code); break; // black 6-key learning remote defaults: "CH" controls brightness,
|
||||
// "VOL +" controls effect, "VOL -" controls colour/palette, "MUTE"
|
||||
// sets bright plain white
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
if (nightlightActive && bri == 0) nightlightActive = false;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_BUTTON); //for notifier, IR is considered a button input
|
||||
//code <= 0xF70000 also invalid
|
||||
}
|
||||
|
||||
|
||||
void decodeIR24(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR24_BRIGHTER : relativeChange(&bri, 10); break;
|
||||
case IR24_DARKER : relativeChange(&bri, -10, 5); break;
|
||||
case IR24_OFF : briLast = bri; bri = 0; break;
|
||||
case IR24_ON : bri = briLast; break;
|
||||
case IR24_RED : colorFromUint32(COLOR_RED); break;
|
||||
case IR24_REDDISH : colorFromUint32(COLOR_REDDISH); break;
|
||||
case IR24_ORANGE : colorFromUint32(COLOR_ORANGE); break;
|
||||
case IR24_YELLOWISH : colorFromUint32(COLOR_YELLOWISH); break;
|
||||
case IR24_YELLOW : colorFromUint32(COLOR_YELLOW); break;
|
||||
case IR24_GREEN : colorFromUint32(COLOR_GREEN); break;
|
||||
case IR24_GREENISH : colorFromUint32(COLOR_GREENISH); break;
|
||||
case IR24_TURQUOISE : colorFromUint32(COLOR_TURQUOISE); break;
|
||||
case IR24_CYAN : colorFromUint32(COLOR_CYAN); break;
|
||||
case IR24_AQUA : colorFromUint32(COLOR_AQUA); break;
|
||||
case IR24_BLUE : colorFromUint32(COLOR_BLUE); break;
|
||||
case IR24_DEEPBLUE : colorFromUint32(COLOR_DEEPBLUE); break;
|
||||
case IR24_PURPLE : colorFromUint32(COLOR_PURPLE); break;
|
||||
case IR24_MAGENTA : colorFromUint32(COLOR_MAGENTA); break;
|
||||
case IR24_PINK : colorFromUint32(COLOR_PINK); break;
|
||||
case IR24_WHITE : colorFromUint32(COLOR_WHITE); effectCurrent = 0; break;
|
||||
case IR24_FLASH : if (!applyPreset(1)) effectCurrent = FX_MODE_COLORTWINKLE; break;
|
||||
case IR24_STROBE : if (!applyPreset(2)) effectCurrent = FX_MODE_RAINBOW_CYCLE; break;
|
||||
case IR24_FADE : if (!applyPreset(3)) effectCurrent = FX_MODE_BREATH; break;
|
||||
case IR24_SMOOTH : if (!applyPreset(4)) effectCurrent = FX_MODE_RAINBOW; break;
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
}
|
||||
|
||||
void decodeIR24OLD(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR24_OLD_BRIGHTER : relativeChange(&bri, 10); break;
|
||||
case IR24_OLD_DARKER : relativeChange(&bri, -10, 5); break;
|
||||
case IR24_OLD_OFF : briLast = bri; bri = 0; break;
|
||||
case IR24_OLD_ON : bri = briLast; break;
|
||||
case IR24_OLD_RED : colorFromUint32(COLOR_RED); break;
|
||||
case IR24_OLD_REDDISH : colorFromUint32(COLOR_REDDISH); break;
|
||||
case IR24_OLD_ORANGE : colorFromUint32(COLOR_ORANGE); break;
|
||||
case IR24_OLD_YELLOWISH : colorFromUint32(COLOR_YELLOWISH); break;
|
||||
case IR24_OLD_YELLOW : colorFromUint32(COLOR_YELLOW); break;
|
||||
case IR24_OLD_GREEN : colorFromUint32(COLOR_GREEN); break;
|
||||
case IR24_OLD_GREENISH : colorFromUint32(COLOR_GREENISH); break;
|
||||
case IR24_OLD_TURQUOISE : colorFromUint32(COLOR_TURQUOISE); break;
|
||||
case IR24_OLD_CYAN : colorFromUint32(COLOR_CYAN); break;
|
||||
case IR24_OLD_AQUA : colorFromUint32(COLOR_AQUA); break;
|
||||
case IR24_OLD_BLUE : colorFromUint32(COLOR_BLUE); break;
|
||||
case IR24_OLD_DEEPBLUE : colorFromUint32(COLOR_DEEPBLUE); break;
|
||||
case IR24_OLD_PURPLE : colorFromUint32(COLOR_PURPLE); break;
|
||||
case IR24_OLD_MAGENTA : colorFromUint32(COLOR_MAGENTA); break;
|
||||
case IR24_OLD_PINK : colorFromUint32(COLOR_PINK); break;
|
||||
case IR24_OLD_WHITE : colorFromUint32(COLOR_WHITE); effectCurrent = 0; break;
|
||||
case IR24_OLD_FLASH : if (!applyPreset(1)) { effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; } break;
|
||||
case IR24_OLD_STROBE : if (!applyPreset(2)) { effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; } break;
|
||||
case IR24_OLD_FADE : if (!applyPreset(3)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
|
||||
case IR24_OLD_SMOOTH : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
}
|
||||
|
||||
|
||||
void decodeIR24CT(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR24_CT_BRIGHTER : relativeChange(&bri, 10); break;
|
||||
case IR24_CT_DARKER : relativeChange(&bri, -10, 5); break;
|
||||
case IR24_CT_OFF : briLast = bri; bri = 0; break;
|
||||
case IR24_CT_ON : bri = briLast; break;
|
||||
case IR24_CT_RED : colorFromUint32(COLOR_RED); break;
|
||||
case IR24_CT_REDDISH : colorFromUint32(COLOR_REDDISH); break;
|
||||
case IR24_CT_ORANGE : colorFromUint32(COLOR_ORANGE); break;
|
||||
case IR24_CT_YELLOWISH : colorFromUint32(COLOR_YELLOWISH); break;
|
||||
case IR24_CT_YELLOW : colorFromUint32(COLOR_YELLOW); break;
|
||||
case IR24_CT_GREEN : colorFromUint32(COLOR_GREEN); break;
|
||||
case IR24_CT_GREENISH : colorFromUint32(COLOR_GREENISH); break;
|
||||
case IR24_CT_TURQUOISE : colorFromUint32(COLOR_TURQUOISE); break;
|
||||
case IR24_CT_CYAN : colorFromUint32(COLOR_CYAN); break;
|
||||
case IR24_CT_AQUA : colorFromUint32(COLOR_AQUA); break;
|
||||
case IR24_CT_BLUE : colorFromUint32(COLOR_BLUE); break;
|
||||
case IR24_CT_DEEPBLUE : colorFromUint32(COLOR_DEEPBLUE); break;
|
||||
case IR24_CT_PURPLE : colorFromUint32(COLOR_PURPLE); break;
|
||||
case IR24_CT_MAGENTA : colorFromUint32(COLOR_MAGENTA); break;
|
||||
case IR24_CT_PINK : colorFromUint32(COLOR_PINK); break;
|
||||
case IR24_CT_COLDWHITE : colorFromUint32(COLOR2_COLDWHITE); effectCurrent = 0; break;
|
||||
case IR24_CT_WARMWHITE : colorFromUint32(COLOR2_WARMWHITE); effectCurrent = 0; break;
|
||||
case IR24_CT_CTPLUS : colorFromUint32(COLOR2_COLDWHITE2); effectCurrent = 0; break;
|
||||
case IR24_CT_CTMINUS : colorFromUint32(COLOR2_WARMWHITE2); effectCurrent = 0; break;
|
||||
case IR24_CT_MEMORY : {
|
||||
if (col[3] > 0) col[3] = 0;
|
||||
else colorFromUint32(COLOR2_NEUTRALWHITE); effectCurrent = 0; } break;
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
}
|
||||
|
||||
|
||||
void decodeIR40(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR40_BPLUS : relativeChange(&bri, 10); break;
|
||||
case IR40_BMINUS : relativeChange(&bri, -10, 5); break;
|
||||
case IR40_OFF : briLast = bri; bri = 0; break;
|
||||
case IR40_ON : bri = briLast; break;
|
||||
case IR40_RED : colorFromUint24(COLOR_RED); break;
|
||||
case IR40_REDDISH : colorFromUint24(COLOR_REDDISH); break;
|
||||
case IR40_ORANGE : colorFromUint24(COLOR_ORANGE); break;
|
||||
case IR40_YELLOWISH : colorFromUint24(COLOR_YELLOWISH); break;
|
||||
case IR40_YELLOW : colorFromUint24(COLOR_YELLOW); break;
|
||||
case IR40_GREEN : colorFromUint24(COLOR_GREEN); break;
|
||||
case IR40_GREENISH : colorFromUint24(COLOR_GREENISH); break;
|
||||
case IR40_TURQUOISE : colorFromUint24(COLOR_TURQUOISE); break;
|
||||
case IR40_CYAN : colorFromUint24(COLOR_CYAN); break;
|
||||
case IR40_AQUA : colorFromUint24(COLOR_AQUA); break;
|
||||
case IR40_BLUE : colorFromUint24(COLOR_BLUE); break;
|
||||
case IR40_DEEPBLUE : colorFromUint24(COLOR_DEEPBLUE); break;
|
||||
case IR40_PURPLE : colorFromUint24(COLOR_PURPLE); break;
|
||||
case IR40_MAGENTA : colorFromUint24(COLOR_MAGENTA); break;
|
||||
case IR40_PINK : colorFromUint24(COLOR_PINK); break;
|
||||
case IR40_WARMWHITE2 : {
|
||||
if (useRGBW) { colorFromUint32(COLOR2_WARMWHITE2); effectCurrent = 0; }
|
||||
else colorFromUint24(COLOR_WARMWHITE2); } break;
|
||||
case IR40_WARMWHITE : {
|
||||
if (useRGBW) { colorFromUint32(COLOR2_WARMWHITE); effectCurrent = 0; }
|
||||
else colorFromUint24(COLOR_WARMWHITE); } break;
|
||||
case IR40_WHITE : {
|
||||
if (useRGBW) { colorFromUint32(COLOR2_NEUTRALWHITE); effectCurrent = 0; }
|
||||
else colorFromUint24(COLOR_NEUTRALWHITE); } break;
|
||||
case IR40_COLDWHITE : {
|
||||
if (useRGBW) { colorFromUint32(COLOR2_COLDWHITE); effectCurrent = 0; }
|
||||
else colorFromUint24(COLOR_COLDWHITE); } break;
|
||||
case IR40_COLDWHITE2 : {
|
||||
if (useRGBW) { colorFromUint32(COLOR2_COLDWHITE2); effectCurrent = 0; }
|
||||
else colorFromUint24(COLOR_COLDWHITE2); } break;
|
||||
case IR40_WPLUS : relativeChangeWhite(10); break;
|
||||
case IR40_WMINUS : relativeChangeWhite(-10, 5); break;
|
||||
case IR40_WOFF : whiteLast = col[3]; col[3] = 0; break;
|
||||
case IR40_WON : col[3] = whiteLast; break;
|
||||
case IR40_W25 : bri = 63; break;
|
||||
case IR40_W50 : bri = 127; break;
|
||||
case IR40_W75 : bri = 191; break;
|
||||
case IR40_W100 : bri = 255; break;
|
||||
case IR40_QUICK : changeEffectSpeed( 16); break;
|
||||
case IR40_SLOW : changeEffectSpeed(-16); break;
|
||||
case IR40_JUMP7 : changeEffectIntensity( 16); break;
|
||||
case IR40_AUTO : changeEffectIntensity(-16); break;
|
||||
case IR40_JUMP3 : if (!applyPreset(1)) { effectCurrent = FX_MODE_STATIC; effectPalette = 0; } break;
|
||||
case IR40_FADE3 : if (!applyPreset(2)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
|
||||
case IR40_FADE7 : if (!applyPreset(3)) { effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; } break;
|
||||
case IR40_FLASH : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
|
||||
}
|
||||
lastValidCode = code;
|
||||
}
|
||||
|
||||
void decodeIR44(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR44_BPLUS : relativeChange(&bri, 10); break;
|
||||
case IR44_BMINUS : relativeChange(&bri, -10, 5); break;
|
||||
case IR44_OFF : briLast = bri; bri = 0; break;
|
||||
case IR44_ON : bri = briLast; break;
|
||||
case IR44_RED : colorFromUint24(COLOR_RED); break;
|
||||
case IR44_REDDISH : colorFromUint24(COLOR_REDDISH); break;
|
||||
case IR44_ORANGE : colorFromUint24(COLOR_ORANGE); break;
|
||||
case IR44_YELLOWISH : colorFromUint24(COLOR_YELLOWISH); break;
|
||||
case IR44_YELLOW : colorFromUint24(COLOR_YELLOW); break;
|
||||
case IR44_GREEN : colorFromUint24(COLOR_GREEN); break;
|
||||
case IR44_GREENISH : colorFromUint24(COLOR_GREENISH); break;
|
||||
case IR44_TURQUOISE : colorFromUint24(COLOR_TURQUOISE); break;
|
||||
case IR44_CYAN : colorFromUint24(COLOR_CYAN); break;
|
||||
case IR44_AQUA : colorFromUint24(COLOR_AQUA); break;
|
||||
case IR44_BLUE : colorFromUint24(COLOR_BLUE); break;
|
||||
case IR44_DEEPBLUE : colorFromUint24(COLOR_DEEPBLUE); break;
|
||||
case IR44_PURPLE : colorFromUint24(COLOR_PURPLE); break;
|
||||
case IR44_MAGENTA : colorFromUint24(COLOR_MAGENTA); break;
|
||||
case IR44_PINK : colorFromUint24(COLOR_PINK); break;
|
||||
case IR44_WHITE : {
|
||||
if (useRGBW) {
|
||||
if (col[3] > 0) col[3] = 0;
|
||||
else { colorFromUint32(COLOR2_NEUTRALWHITE); effectCurrent = 0; }
|
||||
} else colorFromUint24(COLOR_NEUTRALWHITE); } break;
|
||||
case IR44_WARMWHITE2 : {
|
||||
if (useRGBW) { colorFromUint32(COLOR2_WARMWHITE2); effectCurrent = 0; }
|
||||
else colorFromUint24(COLOR_WARMWHITE2); } break;
|
||||
case IR44_WARMWHITE : {
|
||||
if (useRGBW) { colorFromUint32(COLOR2_WARMWHITE); effectCurrent = 0; }
|
||||
else colorFromUint24(COLOR_WARMWHITE); } break;
|
||||
case IR44_COLDWHITE : {
|
||||
if (useRGBW) { colorFromUint32(COLOR2_COLDWHITE); effectCurrent = 0; }
|
||||
else colorFromUint24(COLOR_COLDWHITE); } break;
|
||||
case IR44_COLDWHITE2 : {
|
||||
if (useRGBW) { colorFromUint32(COLOR2_COLDWHITE2); effectCurrent = 0; }
|
||||
else colorFromUint24(COLOR_COLDWHITE2); } 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, 0, strip.getPaletteCount() -1); break;
|
||||
case IR44_GREENMINUS : relativeChange(&effectPalette, -1, 0); break;
|
||||
case IR44_BLUEPLUS : changeEffectIntensity( 16); break;
|
||||
case IR44_BLUEMINUS : changeEffectIntensity(-16); break;
|
||||
case IR44_QUICK : changeEffectSpeed( 16); break;
|
||||
case IR44_SLOW : changeEffectSpeed(-16); break;
|
||||
case IR44_DIY1 : if (!applyPreset(1)) { effectCurrent = FX_MODE_STATIC; effectPalette = 0; } break;
|
||||
case IR44_DIY2 : if (!applyPreset(2)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
|
||||
case IR44_DIY3 : if (!applyPreset(3)) { effectCurrent = FX_MODE_FIRE_FLICKER; effectPalette = 0; } break;
|
||||
case IR44_DIY4 : if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
|
||||
case IR44_DIY5 : if (!applyPreset(5)) { effectCurrent = FX_MODE_METEOR_SMOOTH; effectPalette = 0; } break;
|
||||
case IR44_DIY6 : if (!applyPreset(6)) { effectCurrent = FX_MODE_RAIN; effectPalette = 0; } break;
|
||||
case IR44_AUTO : effectCurrent = FX_MODE_STATIC; break;
|
||||
case IR44_FLASH : effectCurrent = FX_MODE_PALETTE; break;
|
||||
case IR44_JUMP3 : bri = 63; break;
|
||||
case IR44_JUMP7 : bri = 127; break;
|
||||
case IR44_FADE3 : bri = 191; break;
|
||||
case IR44_FADE7 : bri = 255; break;
|
||||
}
|
||||
lastValidCode = code;
|
||||
}
|
||||
|
||||
void decodeIR21(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR21_BRIGHTER: relativeChange(&bri, 10); break;
|
||||
case IR21_DARKER: relativeChange(&bri, -10, 5); break;
|
||||
case IR21_OFF: briLast = bri; bri = 0; break;
|
||||
case IR21_ON: bri = briLast; break;
|
||||
case IR21_RED: colorFromUint32(COLOR_RED); break;
|
||||
case IR21_REDDISH: colorFromUint32(COLOR_REDDISH); break;
|
||||
case IR21_ORANGE: colorFromUint32(COLOR_ORANGE); break;
|
||||
case IR21_YELLOWISH: colorFromUint32(COLOR_YELLOWISH); break;
|
||||
case IR21_GREEN: colorFromUint32(COLOR_GREEN); break;
|
||||
case IR21_GREENISH: colorFromUint32(COLOR_GREENISH); break;
|
||||
case IR21_TURQUOISE: colorFromUint32(COLOR_TURQUOISE); break;
|
||||
case IR21_CYAN: colorFromUint32(COLOR_CYAN); break;
|
||||
case IR21_BLUE: colorFromUint32(COLOR_BLUE); break;
|
||||
case IR21_DEEPBLUE: colorFromUint32(COLOR_DEEPBLUE); break;
|
||||
case IR21_PURPLE: colorFromUint32(COLOR_PURPLE); break;
|
||||
case IR21_PINK: colorFromUint32(COLOR_PINK); break;
|
||||
case IR21_WHITE: colorFromUint32(COLOR_WHITE); effectCurrent = 0; break;
|
||||
case IR21_FLASH: if (!applyPreset(1)) { effectCurrent = FX_MODE_COLORTWINKLE; effectPalette = 0; } break;
|
||||
case IR21_STROBE: if (!applyPreset(2)) { effectCurrent = FX_MODE_RAINBOW_CYCLE; effectPalette = 0; } break;
|
||||
case IR21_FADE: if (!applyPreset(3)) { effectCurrent = FX_MODE_BREATH; effectPalette = 0; } break;
|
||||
case IR21_SMOOTH: if (!applyPreset(4)) { effectCurrent = FX_MODE_RAINBOW; effectPalette = 0; } break;
|
||||
default: return;
|
||||
}
|
||||
lastValidCode = code;
|
||||
}
|
||||
|
||||
void decodeIR6(uint32_t code)
|
||||
{
|
||||
switch (code) {
|
||||
case IR6_POWER: toggleOnOff(); break;
|
||||
case IR6_CHANNEL_UP: relativeChange(&bri, 10); break;
|
||||
case IR6_CHANNEL_DOWN: relativeChange(&bri, -10, 5); break;
|
||||
case IR6_VOLUME_UP: relativeChange(&effectCurrent, 1, 0, MODE_COUNT); break; // next effect
|
||||
case IR6_VOLUME_DOWN: // next palette
|
||||
relativeChange(&effectPalette, 1, 0, strip.getPaletteCount() -1);
|
||||
switch(lastIR6ColourIdx) {
|
||||
case 0: colorFromUint32(COLOR_RED); break;
|
||||
case 1: colorFromUint32(COLOR_REDDISH); break;
|
||||
case 2: colorFromUint32(COLOR_ORANGE); break;
|
||||
case 3: colorFromUint32(COLOR_YELLOWISH); break;
|
||||
case 4: colorFromUint32(COLOR_GREEN); break;
|
||||
case 5: colorFromUint32(COLOR_GREENISH); break;
|
||||
case 6: colorFromUint32(COLOR_TURQUOISE); break;
|
||||
case 7: colorFromUint32(COLOR_CYAN); break;
|
||||
case 8: colorFromUint32(COLOR_BLUE); break;
|
||||
case 9: colorFromUint32(COLOR_DEEPBLUE); break;
|
||||
case 10:colorFromUint32(COLOR_PURPLE); break;
|
||||
case 11:colorFromUint32(COLOR_PINK); break;
|
||||
case 12:colorFromUint32(COLOR_WHITE); break;
|
||||
default: break;
|
||||
}
|
||||
lastIR6ColourIdx++;
|
||||
if(lastIR6ColourIdx > 12) lastIR6ColourIdx = 0; break;
|
||||
case IR6_MUTE: effectCurrent = 0; effectPalette = 0; colorFromUint32(COLOR_WHITE); bri=255; break;
|
||||
}
|
||||
lastValidCode = code;
|
||||
}
|
||||
|
||||
|
||||
void initIR()
|
||||
{
|
||||
if (irEnabled > 0)
|
||||
{
|
||||
irrecv = new IRrecv(IR_PIN);
|
||||
irrecv->enableIRIn();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleIR()
|
||||
{
|
||||
if (irEnabled > 0 && millis() - irCheckedTime > 120)
|
||||
{
|
||||
irCheckedTime = millis();
|
||||
if (irEnabled > 0)
|
||||
{
|
||||
if (irrecv == NULL)
|
||||
{
|
||||
initIR(); return;
|
||||
}
|
||||
|
||||
if (irrecv->decode(&results))
|
||||
{
|
||||
if (results.value != 0) // only print results if anything is received ( != 0 )
|
||||
{
|
||||
Serial.print("IR recv\r\n0x");
|
||||
Serial.println((uint32_t)results.value, HEX);
|
||||
Serial.println();
|
||||
}
|
||||
decodeIR(results.value);
|
||||
irrecv->resume();
|
||||
}
|
||||
} else if (irrecv != NULL)
|
||||
{
|
||||
irrecv->disableIRIn();
|
||||
delete irrecv; irrecv = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -4,6 +4,16 @@
|
||||
#define IRCUSTOM_ONOFF 0xA55AEA15 //Pioneer RC-975R "+FAV" button (example)
|
||||
#define IRCUSTOM_MACRO1 0xFFFFFFFF //placeholder, will never be checked for
|
||||
|
||||
// Default IR codes for 6-key learning remote https://www.aliexpress.com/item/4000307837886.html
|
||||
// This cheap remote has the advantage of being more powerful (longer range) than cheap credit-card remotes
|
||||
#define IR6_POWER 0xFF0FF0
|
||||
#define IR6_CHANNEL_UP 0xFF8F70
|
||||
#define IR6_CHANNEL_DOWN 0xFF4FB0
|
||||
#define IR6_VOLUME_UP 0xFFCF30
|
||||
#define IR6_VOLUME_DOWN 0xFF2FD0
|
||||
#define IR6_MUTE 0xFFAF50
|
||||
|
||||
|
||||
//Infrared codes for 24-key remote from http://woodsgood.ca/projects/2015/02/13/rgb-led-strip-controllers-ir-codes/
|
||||
#define IR24_BRIGHTER 0xF700FF
|
||||
#define IR24_DARKER 0xF7807F
|
||||
@@ -30,52 +40,168 @@
|
||||
#define IR24_FADE 0xF7C837
|
||||
#define IR24_SMOOTH 0xF7E817
|
||||
|
||||
/* 44-key defs, to be done later
|
||||
#define IR44_BPlus 0xFF3AC5 //
|
||||
#define IR44_BMinus 0xFFBA45 //
|
||||
#define IR44_ON 0xFF827D //
|
||||
#define IR44_OFF 0xFF02FD //
|
||||
#define IR44_R 0xFF1AE5 //
|
||||
#define IR44_G 0xFF9A65 //
|
||||
#define IR44_B 0xFFA25D //
|
||||
#define IR44_W 0xFF22DD //
|
||||
#define IR44_B1 0xFF2AD5 //
|
||||
#define IR44_B2 0xFFAA55 //
|
||||
#define IR44_B3 0xFF926D //
|
||||
#define IR44_B4 0xFF12ED //
|
||||
#define IR44_B5 0xFF0AF5 //
|
||||
#define IR44_B6 0xFF8A75 //
|
||||
#define IR44_B7 0xFFB24D //
|
||||
#define IR44_B8 0xFF32CD //
|
||||
#define IR44_B9 0xFF38C7 //
|
||||
#define IR44_B10 0xFFB847 //
|
||||
#define IR44_B11 0xFF7887 //
|
||||
#define IR44_B12 0xFFF807 //
|
||||
#define IR44_B13 0xFF18E7 //
|
||||
#define IR44_B14 0xFF9867 //
|
||||
#define IR44_B15 0xFF58A7 //
|
||||
#define IR44_B16 0xFFD827 //
|
||||
#define IR44_UPR 0xFF28D7 //
|
||||
#define IR44_UPG 0xFFA857 //
|
||||
#define IR44_UPB 0xFF6897 //
|
||||
#define IR44_QUICK 0xFFE817 //
|
||||
#define IR44_DOWNR 0xFF08F7 //
|
||||
#define IR44_DOWNG 0xFF8877 //
|
||||
#define IR44_DOWNB 0xFF48B7 //
|
||||
#define IR44_SLOW 0xFFC837 //
|
||||
#define IR44_DIY1 0xFF30CF //
|
||||
#define IR44_DIY2 0xFFB04F //
|
||||
#define IR44_DIY3 0xFF708F //
|
||||
#define IR44_AUTO 0xFFF00F //
|
||||
#define IR44_DIY4 0xFF10EF //
|
||||
#define IR44_DIY5 0xFF906F //
|
||||
#define IR44_DIY6 0xFF50AF //
|
||||
#define IR44_FLASH 0xFFD02F //
|
||||
#define IR44_JUMP3 0xFF20DF //
|
||||
#define IR44_JUMP7 0xFFA05F //
|
||||
#define IR44_FADE3 0xFF609F //
|
||||
#define IR44_FADE7 0xFFE01F //
|
||||
*/
|
||||
// 24-key defs for white remote control with CW / WW / CT+ and CT- keys (from ALDI LED pillar lamp)
|
||||
#define IR24_CT_BRIGHTER 0xF700FF // BRI +
|
||||
#define IR24_CT_DARKER 0xF7807F // BRI -
|
||||
#define IR24_CT_OFF 0xF740BF // OFF
|
||||
#define IR24_CT_ON 0xF7C03F // ON
|
||||
#define IR24_CT_RED 0xF720DF // RED
|
||||
#define IR24_CT_REDDISH 0xF710EF // REDDISH
|
||||
#define IR24_CT_ORANGE 0xF730CF // ORANGE
|
||||
#define IR24_CT_YELLOWISH 0xF708F7 // YELLOWISH
|
||||
#define IR24_CT_YELLOW 0xF728D7 // YELLOW
|
||||
#define IR24_CT_GREEN 0xF7A05F // GREEN
|
||||
#define IR24_CT_GREENISH 0xF7906F // GREENISH
|
||||
#define IR24_CT_TURQUOISE 0xF7B04F // TURQUOISE
|
||||
#define IR24_CT_CYAN 0xF78877 // CYAN
|
||||
#define IR24_CT_AQUA 0xF7A857 // AQUA
|
||||
#define IR24_CT_BLUE 0xF7609F // BLUE
|
||||
#define IR24_CT_DEEPBLUE 0xF750AF // DEEPBLUE
|
||||
#define IR24_CT_PURPLE 0xF7708F // PURPLE
|
||||
#define IR24_CT_MAGENTA 0xF748B7 // MAGENTA
|
||||
#define IR24_CT_PINK 0xF76897 // PINK
|
||||
#define IR24_CT_COLDWHITE 0xF7E01F // CW
|
||||
#define IR24_CT_WARMWHITE 0xF7D02F // WW
|
||||
#define IR24_CT_CTPLUS 0xF7F00F // CT+
|
||||
#define IR24_CT_CTMINUS 0xF7C837 // CT-
|
||||
#define IR24_CT_MEMORY 0xF7E817 // MEMORY
|
||||
|
||||
// 24-key defs for old remote control
|
||||
#define IR24_OLD_BRIGHTER 0xFF906F // Brightness Up
|
||||
#define IR24_OLD_DARKER 0xFFB847 // Brightness Down
|
||||
#define IR24_OLD_OFF 0xFFF807 // Power OFF
|
||||
#define IR24_OLD_ON 0xFFB04F // Power On
|
||||
#define IR24_OLD_RED 0xFF9867 // RED
|
||||
#define IR24_OLD_REDDISH 0xFFE817 // Light RED
|
||||
#define IR24_OLD_ORANGE 0xFF02FD // Orange
|
||||
#define IR24_OLD_YELLOWISH 0xFF50AF // Light Orange
|
||||
#define IR24_OLD_YELLOW 0xFF38C7 // YELLOW
|
||||
#define IR24_OLD_GREEN 0xFFD827 // GREEN
|
||||
#define IR24_OLD_GREENISH 0xFF48B7 // Light GREEN
|
||||
#define IR24_OLD_TURQUOISE 0xFF32CD // TURQUOISE
|
||||
#define IR24_OLD_CYAN 0xFF7887 // CYAN
|
||||
#define IR24_OLD_AQUA 0xFF28D7 // AQUA
|
||||
#define IR24_OLD_BLUE 0xFF8877 // BLUE
|
||||
#define IR24_OLD_DEEPBLUE 0xFF6897 // Dark BLUE
|
||||
#define IR24_OLD_PURPLE 0xFF20DF // PURPLE
|
||||
#define IR24_OLD_MAGENTA 0xFF708F // MAGENTA
|
||||
#define IR24_OLD_PINK 0xFFF00F // PINK
|
||||
#define IR24_OLD_WHITE 0xFFA857 // WHITE
|
||||
#define IR24_OLD_FLASH 0xFFB24D // FLASH Mode
|
||||
#define IR24_OLD_STROBE 0xFF00FF // STROBE Mode
|
||||
#define IR24_OLD_FADE 0xFF58A7 // FADE Mode
|
||||
#define IR24_OLD_SMOOTH 0xFF30CF // SMOOTH Mode
|
||||
|
||||
// 40-key defs for blue remote control
|
||||
#define IR40_BPLUS 0xFF3AC5 //
|
||||
#define IR40_BMINUS 0xFFBA45 //
|
||||
#define IR40_OFF 0xFF827D //
|
||||
#define IR40_ON 0xFF02FD //
|
||||
#define IR40_RED 0xFF1AE5 //
|
||||
#define IR40_GREEN 0xFF9A65 //
|
||||
#define IR40_BLUE 0xFFA25D //
|
||||
#define IR40_WHITE 0xFF22DD // natural white
|
||||
#define IR40_REDDISH 0xFF2AD5 //
|
||||
#define IR40_GREENISH 0xFFAA55 //
|
||||
#define IR40_DEEPBLUE 0xFF926D //
|
||||
#define IR40_WARMWHITE2 0xFF12ED // warmest white
|
||||
#define IR40_ORANGE 0xFF0AF5 //
|
||||
#define IR40_TURQUOISE 0xFF8A75 //
|
||||
#define IR40_PURPLE 0xFFB24D //
|
||||
#define IR40_WARMWHITE 0xFF32CD // warm white
|
||||
#define IR40_YELLOWISH 0xFF38C7 //
|
||||
#define IR40_CYAN 0xFFB847 //
|
||||
#define IR40_MAGENTA 0xFF7887 //
|
||||
#define IR40_COLDWHITE 0xFFF807 // cold white
|
||||
#define IR40_YELLOW 0xFF18E7 //
|
||||
#define IR40_AQUA 0xFF9867 //
|
||||
#define IR40_PINK 0xFF58A7 //
|
||||
#define IR40_COLDWHITE2 0xFFD827 // coldest white
|
||||
#define IR40_WPLUS 0xFF28D7 // white chanel bright plus
|
||||
#define IR40_WMINUS 0xFFA857 // white chanel bright minus
|
||||
#define IR40_WOFF 0xFF6897 // white chanel on
|
||||
#define IR40_WON 0xFFE817 // white chanel off
|
||||
#define IR40_W25 0xFF08F7 // white chanel 25%
|
||||
#define IR40_W50 0xFF8877 // white chanel 50%
|
||||
#define IR40_W75 0xFF48B7 // white chanel 75%
|
||||
#define IR40_W100 0xFFC837 // white chanel 100%
|
||||
#define IR40_JUMP3 0xFF30CF // JUMP3
|
||||
#define IR40_FADE3 0xFFB04F // FADE3
|
||||
#define IR40_JUMP7 0xFF708F // JUMP7
|
||||
#define IR40_QUICK 0xFFF00F // QUICK
|
||||
#define IR40_FADE7 0xFF10EF // FADE7
|
||||
#define IR40_FLASH 0xFF906F // FLASH
|
||||
#define IR40_AUTO 0xFF50AF // AUTO
|
||||
#define IR40_SLOW 0xFFD02F // SLOW
|
||||
|
||||
// 44-key defs, to be done later
|
||||
#define IR44_BPLUS 0xFF3AC5 //
|
||||
#define IR44_BMINUS 0xFFBA45 //
|
||||
#define IR44_OFF 0xFF827D //
|
||||
#define IR44_ON 0xFF02FD //
|
||||
#define IR44_RED 0xFF1AE5 //
|
||||
#define IR44_GREEN 0xFF9A65 //
|
||||
#define IR44_BLUE 0xFFA25D //
|
||||
#define IR44_WHITE 0xFF22DD // natural white
|
||||
#define IR44_REDDISH 0xFF2AD5 //
|
||||
#define IR44_GREENISH 0xFFAA55 //
|
||||
#define IR44_DEEPBLUE 0xFF926D //
|
||||
#define IR44_WARMWHITE2 0xFF12ED // warmest white
|
||||
#define IR44_ORANGE 0xFF0AF5 //
|
||||
#define IR44_TURQUOISE 0xFF8A75 //
|
||||
#define IR44_PURPLE 0xFFB24D //
|
||||
#define IR44_WARMWHITE 0xFF32CD // warm white
|
||||
#define IR44_YELLOWISH 0xFF38C7 //
|
||||
#define IR44_CYAN 0xFFB847 //
|
||||
#define IR44_MAGENTA 0xFF7887 //
|
||||
#define IR44_COLDWHITE 0xFFF807 // cold white
|
||||
#define IR44_YELLOW 0xFF18E7 //
|
||||
#define IR44_AQUA 0xFF9867 //
|
||||
#define IR44_PINK 0xFF58A7 //
|
||||
#define IR44_COLDWHITE2 0xFFD827 // coldest white
|
||||
#define IR44_REDPLUS 0xFF28D7 //
|
||||
#define IR44_GREENPLUS 0xFFA857 //
|
||||
#define IR44_BLUEPLUS 0xFF6897 //
|
||||
#define IR44_QUICK 0xFFE817 //
|
||||
#define IR44_REDMINUS 0xFF08F7 //
|
||||
#define IR44_GREENMINUS 0xFF8877 //
|
||||
#define IR44_BLUEMINUS 0xFF48B7 //
|
||||
#define IR44_SLOW 0xFFC837 //
|
||||
#define IR44_DIY1 0xFF30CF //
|
||||
#define IR44_DIY2 0xFFB04F //
|
||||
#define IR44_DIY3 0xFF708F //
|
||||
#define IR44_AUTO 0xFFF00F //
|
||||
#define IR44_DIY4 0xFF10EF //
|
||||
#define IR44_DIY5 0xFF906F //
|
||||
#define IR44_DIY6 0xFF50AF //
|
||||
#define IR44_FLASH 0xFFD02F //
|
||||
#define IR44_JUMP3 0xFF20DF //
|
||||
#define IR44_JUMP7 0xFFA05F //
|
||||
#define IR44_FADE3 0xFF609F //
|
||||
#define IR44_FADE7 0xFFE01F //
|
||||
|
||||
//Infrared codes for 21-key remote https://images-na.ssl-images-amazon.com/images/I/51NMA0XucnL.jpg
|
||||
#define IR21_BRIGHTER 0xFFE01F
|
||||
#define IR21_DARKER 0xFFA857
|
||||
#define IR21_OFF 0xFF629D
|
||||
#define IR21_ON 0xFFA25D
|
||||
#define IR21_RED 0xFF6897
|
||||
#define IR21_REDDISH 0xFF30CF
|
||||
#define IR21_ORANGE 0xFF10EF
|
||||
#define IR21_YELLOWISH 0xFF42BD
|
||||
#define IR21_GREEN 0xFF9867
|
||||
#define IR21_GREENISH 0xFF18E7
|
||||
#define IR21_TURQUOISE 0xFF38C7
|
||||
#define IR21_CYAN 0xFF4AB5
|
||||
#define IR21_BLUE 0xFFB04F
|
||||
#define IR21_DEEPBLUE 0xFF7A85
|
||||
#define IR21_PURPLE 0xFF5AA5
|
||||
#define IR21_PINK 0xFF52AD
|
||||
#define IR21_WHITE 0xFF906F
|
||||
#define IR21_FLASH 0xFFE21D
|
||||
#define IR21_STROBE 0xFF22DD
|
||||
#define IR21_FADE 0xFF02FD
|
||||
#define IR21_SMOOTH 0xFFC23D
|
||||
|
||||
#define COLOR_RED 0xFF0000
|
||||
#define COLOR_REDDISH 0xFF7800
|
||||
@@ -93,3 +219,13 @@
|
||||
#define COLOR_MAGENTA 0xFF00DC
|
||||
#define COLOR_PINK 0xFF00A0
|
||||
#define COLOR_WHITE 0xFFFFDC
|
||||
#define COLOR_WARMWHITE2 0xFFAA69
|
||||
#define COLOR_WARMWHITE 0xFFBF8E
|
||||
#define COLOR_NEUTRALWHITE 0xFFD4B4
|
||||
#define COLOR_COLDWHITE 0xFFE9D9
|
||||
#define COLOR_COLDWHITE2 0xFFFFFF
|
||||
#define COLOR2_WARMWHITE2 0xFFFF9900
|
||||
#define COLOR2_WARMWHITE 0xFF825A00
|
||||
#define COLOR2_NEUTRALWHITE 0xFF000000
|
||||
#define COLOR2_COLDWHITE 0xFF7F7F7F
|
||||
#define COLOR2_COLDWHITE2 0xFFFFFFFF
|
||||
|
||||
469
wled00/json.cpp
Normal file
469
wled00/json.cpp
Normal file
@@ -0,0 +1,469 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* JSON API (De)serialization
|
||||
*/
|
||||
|
||||
void deserializeSegment(JsonObject elem, byte it)
|
||||
{
|
||||
byte id = elem["id"] | it;
|
||||
if (id < strip.getMaxSegments())
|
||||
{
|
||||
WS2812FX::Segment& seg = strip.getSegment(id);
|
||||
uint16_t start = elem["start"] | seg.start;
|
||||
int stop = elem["stop"] | -1;
|
||||
|
||||
if (stop < 0) {
|
||||
uint16_t len = elem["len"];
|
||||
stop = (len > 0) ? start + len : seg.stop;
|
||||
}
|
||||
uint16_t grp = elem["grp"] | seg.grouping;
|
||||
uint16_t spc = elem["spc"] | seg.spacing;
|
||||
strip.setSegment(id, start, stop, grp, spc);
|
||||
|
||||
int segbri = elem["bri"] | -1;
|
||||
if (segbri == 0) {
|
||||
seg.setOption(SEG_OPTION_ON, 0);
|
||||
} else if (segbri > 0) {
|
||||
seg.opacity = segbri;
|
||||
seg.setOption(SEG_OPTION_ON, 1);
|
||||
}
|
||||
|
||||
seg.setOption(SEG_OPTION_ON, elem["on"] | seg.getOption(SEG_OPTION_ON));
|
||||
|
||||
JsonArray colarr = elem["col"];
|
||||
if (!colarr.isNull())
|
||||
{
|
||||
for (uint8_t i = 0; i < 3; i++)
|
||||
{
|
||||
JsonArray colX = colarr[i];
|
||||
if (colX.isNull()) break;
|
||||
byte sz = colX.size();
|
||||
if (sz > 0 && sz < 5)
|
||||
{
|
||||
int rgbw[] = {0,0,0,0};
|
||||
byte cp = copyArray(colX, rgbw);
|
||||
|
||||
if (cp == 1 && rgbw[0] == 0) seg.colors[i] = 0;
|
||||
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(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;
|
||||
effectSpeed = elem["sx"] | effectSpeed;
|
||||
effectIntensity = elem["ix"] | effectIntensity;
|
||||
effectPalette = elem["pal"] | effectPalette;
|
||||
} else { //permanent
|
||||
byte fx = elem["fx"] | seg.mode;
|
||||
if (fx != seg.mode && fx < strip.getModeCount()) strip.setMode(id, fx);
|
||||
seg.speed = elem["sx"] | seg.speed;
|
||||
seg.intensity = elem["ix"] | seg.intensity;
|
||||
seg.palette = elem["pal"] | seg.palette;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool deserializeState(JsonObject root)
|
||||
{
|
||||
strip.applyToAllSelected = false;
|
||||
bool stateResponse = root["v"] | false;
|
||||
|
||||
int ps = root["ps"] | -1;
|
||||
if (ps >= 0) applyPreset(ps);
|
||||
|
||||
bri = root["bri"] | bri;
|
||||
|
||||
bool on = root["on"] | (bri > 0);
|
||||
if (!on != !bri) toggleOnOff();
|
||||
|
||||
int tr = root["transition"] | -1;
|
||||
if (tr >= 0)
|
||||
{
|
||||
transitionDelay = tr;
|
||||
transitionDelay *= 100;
|
||||
}
|
||||
|
||||
tr = root["tt"] | -1;
|
||||
if (tr >= 0)
|
||||
{
|
||||
transitionDelayTemp = tr;
|
||||
transitionDelayTemp *= 100;
|
||||
jsonTransitionOnce = true;
|
||||
}
|
||||
|
||||
int cy = root["pl"] | -2;
|
||||
if (cy > -2) presetCyclingEnabled = (cy >= 0);
|
||||
JsonObject ccnf = root["ccnf"];
|
||||
presetCycleMin = ccnf["min"] | presetCycleMin;
|
||||
presetCycleMax = ccnf["max"] | presetCycleMax;
|
||||
tr = ccnf["time"] | -1;
|
||||
if (tr >= 2)
|
||||
{
|
||||
presetCycleTime = tr;
|
||||
presetCycleTime *= 100;
|
||||
}
|
||||
|
||||
JsonObject nl = root["nl"];
|
||||
nightlightActive = nl["on"] | nightlightActive;
|
||||
nightlightDelayMins = nl["dur"] | nightlightDelayMins;
|
||||
nightlightFade = nl["fade"] | nightlightFade;
|
||||
nightlightTargetBri = nl["tbri"] | nightlightTargetBri;
|
||||
|
||||
JsonObject udpn = root["udpn"];
|
||||
notifyDirect = udpn["send"] | notifyDirect;
|
||||
receiveNotifications = udpn["recv"] | receiveNotifications;
|
||||
bool noNotification = udpn["nn"]; //send no notification just for this request
|
||||
|
||||
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;
|
||||
if (strip.getMainSegmentId() != prevMain) setValuesFromMainSeg();
|
||||
|
||||
int it = 0;
|
||||
JsonVariant segVar = root["seg"];
|
||||
if (segVar.is<JsonObject>())
|
||||
{
|
||||
int id = segVar["id"] | -1;
|
||||
|
||||
if (id < 0) { //set all selected segments
|
||||
bool didSet = false;
|
||||
byte lowestActive = 99;
|
||||
for (byte s = 0; s < strip.getMaxSegments(); s++)
|
||||
{
|
||||
WS2812FX::Segment sg = strip.getSegment(s);
|
||||
if (sg.isActive())
|
||||
{
|
||||
if (lowestActive == 99) lowestActive = s;
|
||||
if (sg.isSelected()) {
|
||||
deserializeSegment(segVar, s);
|
||||
didSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!didSet && lowestActive < strip.getMaxSegments()) deserializeSegment(segVar, lowestActive);
|
||||
} else { //set only the segment with the specified ID
|
||||
deserializeSegment(segVar, it);
|
||||
}
|
||||
} else {
|
||||
JsonArray segs = segVar.as<JsonArray>();
|
||||
for (JsonObject elem : segs)
|
||||
{
|
||||
deserializeSegment(elem, it);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
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, persistSaves);
|
||||
|
||||
return stateResponse;
|
||||
}
|
||||
|
||||
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id)
|
||||
{
|
||||
root["id"] = id;
|
||||
root["start"] = seg.start;
|
||||
root["stop"] = seg.stop;
|
||||
root["len"] = seg.stop - seg.start;
|
||||
root["grp"] = seg.grouping;
|
||||
root["spc"] = seg.spacing;
|
||||
root["on"] = seg.getOption(SEG_OPTION_ON);
|
||||
byte segbri = seg.opacity;
|
||||
root["bri"] = (segbri) ? segbri : 255;
|
||||
|
||||
JsonArray colarr = root.createNestedArray("col");
|
||||
|
||||
for (uint8_t i = 0; i < 3; i++)
|
||||
{
|
||||
JsonArray colX = colarr.createNestedArray();
|
||||
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;
|
||||
root["sx"] = seg.speed;
|
||||
root["ix"] = seg.intensity;
|
||||
root["pal"] = seg.palette;
|
||||
root["sel"] = seg.isSelected();
|
||||
root["rev"] = seg.getOption(SEG_OPTION_REVERSED);
|
||||
}
|
||||
|
||||
|
||||
void serializeState(JsonObject root)
|
||||
{
|
||||
if (errorFlag) root["error"] = errorFlag;
|
||||
|
||||
root["on"] = (bri > 0);
|
||||
root["bri"] = briLast;
|
||||
root["transition"] = transitionDelay/100; //in 100ms
|
||||
|
||||
root["ps"] = currentPreset;
|
||||
root["pss"] = savedPresets;
|
||||
root["pl"] = (presetCyclingEnabled) ? 0: -1;
|
||||
|
||||
//temporary for preser cycle
|
||||
JsonObject ccnf = root.createNestedObject("ccnf");
|
||||
ccnf["min"] = presetCycleMin;
|
||||
ccnf["max"] = presetCycleMax;
|
||||
ccnf["time"] = presetCycleTime/100;
|
||||
|
||||
JsonObject nl = root.createNestedObject("nl");
|
||||
nl["on"] = nightlightActive;
|
||||
nl["dur"] = nightlightDelayMins;
|
||||
nl["fade"] = nightlightFade;
|
||||
nl["tbri"] = nightlightTargetBri;
|
||||
|
||||
JsonObject udpn = root.createNestedObject("udpn");
|
||||
udpn["send"] = notifyDirect;
|
||||
udpn["recv"] = receiveNotifications;
|
||||
|
||||
root["lor"] = realtimeOverride;
|
||||
|
||||
root["mainseg"] = strip.getMainSegmentId();
|
||||
|
||||
JsonArray seg = root.createNestedArray("seg");
|
||||
for (byte s = 0; s < strip.getMaxSegments(); s++)
|
||||
{
|
||||
WS2812FX::Segment sg = strip.getSegment(s);
|
||||
if (sg.isActive())
|
||||
{
|
||||
JsonObject seg0 = seg.createNestedObject();
|
||||
serializeSegment(seg0, sg, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//by https://github.com/tzapu/WiFiManager/blob/master/WiFiManager.cpp
|
||||
int getSignalQuality(int rssi)
|
||||
{
|
||||
int quality = 0;
|
||||
|
||||
if (rssi <= -100)
|
||||
{
|
||||
quality = 0;
|
||||
}
|
||||
else if (rssi >= -50)
|
||||
{
|
||||
quality = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
quality = 2 * (rssi + 100);
|
||||
}
|
||||
return quality;
|
||||
}
|
||||
|
||||
void serializeInfo(JsonObject root)
|
||||
{
|
||||
root["ver"] = versionString;
|
||||
root["vid"] = VERSION;
|
||||
//root["cn"] = WLED_CODENAME;
|
||||
|
||||
JsonObject leds = root.createNestedObject("leds");
|
||||
leds["count"] = ledCount;
|
||||
leds["rgbw"] = useRGBW;
|
||||
leds["wv"] = useRGBW && (strip.rgbwMode == RGBW_MODE_MANUAL_ONLY || strip.rgbwMode == RGBW_MODE_DUAL); //should a white channel slider be displayed?
|
||||
JsonArray leds_pin = leds.createNestedArray("pin");
|
||||
leds_pin.add(LEDPIN);
|
||||
|
||||
leds["pwr"] = strip.currentMilliamps;
|
||||
leds["maxpwr"] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
|
||||
leds["maxseg"] = strip.getMaxSegments();
|
||||
leds["seglock"] = false; //will be used in the future to prevent modifications to segment config
|
||||
|
||||
root["str"] = syncToggleReceive;
|
||||
|
||||
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();
|
||||
|
||||
JsonObject wifi_info = root.createNestedObject("wifi");
|
||||
wifi_info["bssid"] = WiFi.BSSIDstr();
|
||||
int qrssi = WiFi.RSSI();
|
||||
wifi_info["rssi"] = qrssi;
|
||||
wifi_info["signal"] = getSignalQuality(qrssi);
|
||||
wifi_info["channel"] = WiFi.channel();
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#ifdef WLED_DEBUG
|
||||
wifi_info["txPower"] = (int) WiFi.getTxPower();
|
||||
wifi_info["sleep"] = (bool) WiFi.getSleep();
|
||||
#endif
|
||||
root["arch"] = "esp32";
|
||||
root["core"] = ESP.getSdkVersion();
|
||||
//root["maxalloc"] = ESP.getMaxAllocHeap();
|
||||
#ifdef WLED_DEBUG
|
||||
root["resetReason0"] = (int)rtc_get_reset_reason(0);
|
||||
root["resetReason1"] = (int)rtc_get_reset_reason(1);
|
||||
#endif
|
||||
root["lwip"] = 0;
|
||||
#else
|
||||
root["arch"] = "esp8266";
|
||||
root["core"] = ESP.getCoreVersion();
|
||||
//root["maxalloc"] = ESP.getMaxFreeBlockSize();
|
||||
#ifdef WLED_DEBUG
|
||||
root["resetReason"] = (int)ESP.getResetInfoPtr()->reason;
|
||||
#endif
|
||||
root["lwip"] = LWIP_VERSION_MAJOR;
|
||||
#endif
|
||||
|
||||
root["freeheap"] = ESP.getFreeHeap();
|
||||
root["uptime"] = millis()/1000 + rolloverMillis*4294967;
|
||||
|
||||
byte os = 0;
|
||||
#ifdef WLED_DEBUG
|
||||
os = 0x80;
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
os += 0x40;
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_BLYNK
|
||||
os += 0x20;
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
os += 0x10;
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_FILESYSTEM
|
||||
os += 0x08;
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
os += 0x04;
|
||||
#endif
|
||||
#ifdef WLED_ENABLE_ADALIGHT
|
||||
os += 0x02;
|
||||
#endif
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
os += 0x01;
|
||||
#endif
|
||||
root["opt"] = os;
|
||||
|
||||
root["brand"] = "WLED";
|
||||
root["product"] = "FOSS";
|
||||
root["mac"] = escapedMac;
|
||||
}
|
||||
|
||||
void serveJson(AsyncWebServerRequest* request)
|
||||
{
|
||||
byte subJson = 0;
|
||||
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;
|
||||
}
|
||||
else if (url.indexOf("eff") > 0) {
|
||||
request->send_P(200, "application/json", JSON_mode_names);
|
||||
return;
|
||||
}
|
||||
else if (url.indexOf("pal") > 0) {
|
||||
request->send_P(200, "application/json", JSON_palette_names);
|
||||
return;
|
||||
}
|
||||
else if (url.length() > 6) { //not just /json
|
||||
request->send( 501, "application/json", F("{\"error\":\"Not implemented\"}"));
|
||||
return;
|
||||
}
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject doc = response->getRoot();
|
||||
|
||||
switch (subJson)
|
||||
{
|
||||
case 1: //state
|
||||
serializeState(doc); break;
|
||||
case 2: //info
|
||||
serializeInfo(doc); break;
|
||||
default: //all
|
||||
JsonObject state = doc.createNestedObject("state");
|
||||
serializeState(state);
|
||||
JsonObject info = doc.createNestedObject("info");
|
||||
serializeInfo(info);
|
||||
if (subJson != 3)
|
||||
{
|
||||
doc["effects"] = serialized((const __FlashStringHelper*)JSON_mode_names);
|
||||
doc["palettes"] = serialized((const __FlashStringHelper*)JSON_palette_names);
|
||||
}
|
||||
}
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
#define MAX_LIVE_LEDS 180
|
||||
|
||||
void serveLiveLeds(AsyncWebServerRequest* request)
|
||||
{
|
||||
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;
|
||||
|
||||
for (uint16_t i= 0; i < used; i += n)
|
||||
{
|
||||
olen += sprintf(buffer + olen, "\"%06X\",", strip.getPixelColor(i));
|
||||
}
|
||||
olen -= 1;
|
||||
oappend("],\"n\":");
|
||||
oappendi(n);
|
||||
oappend("}");
|
||||
request->send(200, "application/json", buffer);
|
||||
}
|
||||
@@ -1,7 +1,27 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* LED methods
|
||||
*/
|
||||
|
||||
void setValuesFromMainSeg()
|
||||
{
|
||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||
colorFromUint32(seg.colors[0]);
|
||||
colorFromUint32(seg.colors[1], true);
|
||||
effectCurrent = seg.mode;
|
||||
effectSpeed = seg.speed;
|
||||
effectIntensity = seg.intensity;
|
||||
effectPalette = seg.palette;
|
||||
}
|
||||
|
||||
|
||||
void resetTimebase()
|
||||
{
|
||||
strip.timebase = 0 - millis();
|
||||
}
|
||||
|
||||
|
||||
void toggleOnOff()
|
||||
{
|
||||
if (bri == 0)
|
||||
@@ -16,21 +36,14 @@ void toggleOnOff()
|
||||
|
||||
|
||||
void setAllLeds() {
|
||||
if (!realtimeActive || !arlsForceMaxBri)
|
||||
if (!realtimeMode || !arlsForceMaxBri)
|
||||
{
|
||||
double d = briT*briMultiplier;
|
||||
int val = d/100;
|
||||
if (val > 255) val = 255;
|
||||
strip.setBrightness(val);
|
||||
}
|
||||
if (!enableSecTransition)
|
||||
{
|
||||
for (byte i = 0; i<4; i++)
|
||||
{
|
||||
colSecT[i] = colSec[i];
|
||||
}
|
||||
}
|
||||
if (useRGBW && autoRGBtoRGBW)
|
||||
if (useRGBW && strip.rgbwMode == RGBW_MODE_LEGACY)
|
||||
{
|
||||
colorRGBtoRGBW(colT);
|
||||
colorRGBtoRGBW(colSecT);
|
||||
@@ -40,7 +53,7 @@ void setAllLeds() {
|
||||
}
|
||||
|
||||
|
||||
void setLedsStandard()
|
||||
void setLedsStandard(bool justColors)
|
||||
{
|
||||
for (byte i=0; i<4; i++)
|
||||
{
|
||||
@@ -49,6 +62,7 @@ void setLedsStandard()
|
||||
colSecOld[i] = colSec[i];
|
||||
colSecT[i] = colSec[i];
|
||||
}
|
||||
if (justColors) return;
|
||||
briOld = bri;
|
||||
briT = bri;
|
||||
setAllLeds();
|
||||
@@ -71,22 +85,36 @@ void colorUpdated(int callMode)
|
||||
{
|
||||
//call for notifier -> 0: init 1: direct change 2: button 3: notification 4: nightlight 5: other (No notification)
|
||||
// 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa
|
||||
if (callMode != NOTIFIER_CALL_MODE_INIT &&
|
||||
callMode != NOTIFIER_CALL_MODE_DIRECT_CHANGE &&
|
||||
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY) strip.applyToAllSelected = true; //if not from JSON api, which directly sets segments
|
||||
|
||||
bool fxChanged = strip.setEffectConfig(effectCurrent, effectSpeed, effectIntensity, effectPalette);
|
||||
if (!colorChanged())
|
||||
bool colChanged = colorChanged();
|
||||
|
||||
if (fxChanged || colChanged)
|
||||
{
|
||||
if (nightlightActive && !nightlightActiveOld && callMode != 3 && callMode != 5)
|
||||
if (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
|
||||
if (isPreset) {isPreset = false;}
|
||||
else {currentPreset = -1;}
|
||||
|
||||
notify(callMode);
|
||||
|
||||
//set flag to update blynk and mqtt
|
||||
if (callMode != NOTIFIER_CALL_MODE_PRESET_CYCLE) interfaceUpdateCallMode = callMode;
|
||||
} else {
|
||||
if (nightlightActive && !nightlightActiveOld &&
|
||||
callMode != NOTIFIER_CALL_MODE_NOTIFICATION &&
|
||||
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY)
|
||||
{
|
||||
notify(4); interfaceUpdateCallMode = 4; return;
|
||||
notify(NOTIFIER_CALL_MODE_NIGHTLIGHT);
|
||||
interfaceUpdateCallMode = NOTIFIER_CALL_MODE_NIGHTLIGHT;
|
||||
}
|
||||
else if (fxChanged) {
|
||||
notify(6);
|
||||
if (callMode != 8) interfaceUpdateCallMode = 6;
|
||||
if (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
|
||||
}
|
||||
return; //no change
|
||||
}
|
||||
if (realtimeTimeout == UINT32_MAX) realtimeTimeout = 0;
|
||||
if (callMode != 5 && nightlightActive && nightlightFade)
|
||||
|
||||
if (!colChanged) return; //following code is for e.g. initiating transitions
|
||||
|
||||
if (callMode != NOTIFIER_CALL_MODE_NO_NOTIFY && nightlightActive && nightlightFade)
|
||||
{
|
||||
briNlT = bri;
|
||||
nightlightDelayMs -= (millis() - nightlightStartTime);
|
||||
@@ -97,15 +125,20 @@ void colorUpdated(int callMode)
|
||||
colIT[i] = col[i];
|
||||
colSecIT[i] = colSec[i];
|
||||
}
|
||||
if (briT == 0)
|
||||
{
|
||||
setLedsStandard(true); //do not color transition if starting from off
|
||||
if (callMode != NOTIFIER_CALL_MODE_NOTIFICATION) resetTimebase(); //effect start from beginning
|
||||
}
|
||||
|
||||
briIT = bri;
|
||||
if (bri > 0) briLast = bri;
|
||||
|
||||
notify(callMode);
|
||||
|
||||
if (fadeTransition)
|
||||
{
|
||||
//set correct delay if not using notification delay
|
||||
if (callMode != 3) transitionDelayTemp = transitionDelay;
|
||||
if (callMode != NOTIFIER_CALL_MODE_NOTIFICATION && !jsonTransitionOnce) transitionDelayTemp = transitionDelay;
|
||||
jsonTransitionOnce = false;
|
||||
if (transitionDelayTemp == 0) {setLedsStandard(); strip.trigger(); return;}
|
||||
|
||||
if (transitionActive)
|
||||
@@ -126,22 +159,19 @@ void colorUpdated(int callMode)
|
||||
setLedsStandard();
|
||||
strip.trigger();
|
||||
}
|
||||
|
||||
if (callMode == 8) return;
|
||||
//set flag to update blynk and mqtt
|
||||
interfaceUpdateCallMode = callMode;
|
||||
}
|
||||
|
||||
|
||||
void updateInterfaces(uint8_t callMode)
|
||||
{
|
||||
#ifndef WLED_DISABLE_ALEXA
|
||||
if (espalexaDevice != nullptr && callMode != 10) {
|
||||
if (espalexaDevice != nullptr && callMode != NOTIFIER_CALL_MODE_ALEXA) {
|
||||
espalexaDevice->setValue(bri);
|
||||
espalexaDevice->setColor(col[0], col[1], col[2]);
|
||||
}
|
||||
#endif
|
||||
if (callMode != 9 && callMode != 5) updateBlynk();
|
||||
if (callMode != NOTIFIER_CALL_MODE_BLYNK &&
|
||||
callMode != NOTIFIER_CALL_MODE_NO_NOTIFY) updateBlynk();
|
||||
doPublishMqtt = true;
|
||||
lastInterfaceUpdate = millis();
|
||||
}
|
||||
@@ -192,12 +222,17 @@ void handleNightlight()
|
||||
nightlightDelayMs = (int)(nightlightDelayMins*60000);
|
||||
nightlightActiveOld = true;
|
||||
briNlT = bri;
|
||||
for (byte i=0; i<4; i++) colNlT[i] = col[i]; // remember starting color
|
||||
}
|
||||
float nper = (millis() - nightlightStartTime)/((float)nightlightDelayMs);
|
||||
if (nightlightFade)
|
||||
{
|
||||
bri = briNlT + ((nightlightTargetBri - briNlT)*nper);
|
||||
colorUpdated(5);
|
||||
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
|
||||
}
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NO_NOTIFY);
|
||||
}
|
||||
if (nper >= 1)
|
||||
{
|
||||
@@ -205,7 +240,7 @@ void handleNightlight()
|
||||
if (!nightlightFade)
|
||||
{
|
||||
bri = nightlightTargetBri;
|
||||
colorUpdated(5);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NO_NOTIFY);
|
||||
}
|
||||
updateBlynk();
|
||||
if (bri == 0) briLast = briNlT;
|
||||
@@ -218,10 +253,10 @@ void handleNightlight()
|
||||
//also handle preset cycle here
|
||||
if (presetCyclingEnabled && (millis() - presetCycledTime > presetCycleTime))
|
||||
{
|
||||
applyPreset(presetCycCurr,presetApplyBri,presetApplyCol,presetApplyFx);
|
||||
applyPreset(presetCycCurr,presetApplyBri);
|
||||
presetCycCurr++; if (presetCycCurr > presetCycleMax) presetCycCurr = presetCycleMin;
|
||||
if (presetCycCurr > 25) presetCycCurr = 1;
|
||||
colorUpdated(8);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_PRESET_CYCLE);
|
||||
presetCycledTime = millis();
|
||||
}
|
||||
}
|
||||
143
wled00/mqtt.cpp
Normal file
143
wled00/mqtt.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* MQTT communication protocol for home automation
|
||||
*/
|
||||
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
#define MQTT_KEEP_ALIVE_TIME 60 // contact the MQTT broker every 60 seconds
|
||||
|
||||
void parseMQTTBriPayload(char* payload)
|
||||
{
|
||||
if (strstr(payload, "ON") || strstr(payload, "on") || strstr(payload, "true")) {bri = briLast; colorUpdated(1);}
|
||||
else if (strstr(payload, "T" ) || strstr(payload, "t" )) {toggleOnOff(); colorUpdated(1);}
|
||||
else {
|
||||
uint8_t in = strtoul(payload, NULL, 10);
|
||||
if (in == 0 && bri > 0) briLast = bri;
|
||||
bri = in;
|
||||
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void onMqttConnect(bool sessionPresent)
|
||||
{
|
||||
//(re)subscribe to required topics
|
||||
char subuf[38];
|
||||
|
||||
if (mqttDeviceTopic[0] != 0)
|
||||
{
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
mqtt->subscribe(subuf, 0);
|
||||
strcat(subuf, "/col");
|
||||
mqtt->subscribe(subuf, 0);
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/api");
|
||||
mqtt->subscribe(subuf, 0);
|
||||
}
|
||||
|
||||
if (mqttGroupTopic[0] != 0)
|
||||
{
|
||||
strcpy(subuf, mqttGroupTopic);
|
||||
mqtt->subscribe(subuf, 0);
|
||||
strcat(subuf, "/col");
|
||||
mqtt->subscribe(subuf, 0);
|
||||
strcpy(subuf, mqttGroupTopic);
|
||||
strcat(subuf, "/api");
|
||||
mqtt->subscribe(subuf, 0);
|
||||
}
|
||||
|
||||
doPublishMqtt = true;
|
||||
DEBUG_PRINTLN("MQTT ready");
|
||||
}
|
||||
|
||||
|
||||
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
|
||||
|
||||
DEBUG_PRINT("MQTT msg: ");
|
||||
DEBUG_PRINTLN(topic);
|
||||
DEBUG_PRINTLN(payload);
|
||||
|
||||
//no need to check the topic because we only get topics we are subscribed to
|
||||
|
||||
if (strstr(topic, "/col"))
|
||||
{
|
||||
colorFromDecOrHexString(col, (char*)payload);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
} else if (strstr(topic, "/api"))
|
||||
{
|
||||
String apireq = "win&";
|
||||
apireq += (char*)payload;
|
||||
handleSet(nullptr, apireq);
|
||||
} else parseMQTTBriPayload(payload);
|
||||
}
|
||||
|
||||
|
||||
void publishMqtt()
|
||||
{
|
||||
doPublishMqtt = false;
|
||||
if (mqtt == nullptr || !mqtt->connected()) return;
|
||||
DEBUG_PRINTLN("Publish MQTT");
|
||||
|
||||
char s[10];
|
||||
char subuf[38];
|
||||
|
||||
sprintf(s, "%ld", bri);
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/g");
|
||||
mqtt->publish(subuf, 0, true, s);
|
||||
|
||||
sprintf(s, "#%06X", (col[3] << 24) | (col[0] << 16) | (col[1] << 8) | (col[2]));
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/c");
|
||||
mqtt->publish(subuf, 0, true, s);
|
||||
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/status");
|
||||
mqtt->publish(subuf, 0, true, "online");
|
||||
|
||||
char apires[1024];
|
||||
XML_response(nullptr, apires);
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, "/v");
|
||||
mqtt->publish(subuf, 0, true, apires);
|
||||
}
|
||||
|
||||
|
||||
//HA autodiscovery was removed in favor of the native integration in HA v0.102.0
|
||||
|
||||
bool initMqtt()
|
||||
{
|
||||
lastMqttReconnectAttempt = millis();
|
||||
if (!mqttEnabled || mqttServer[0] == 0 || !WLED_CONNECTED) return false;
|
||||
|
||||
if (mqtt == nullptr) {
|
||||
mqtt = new AsyncMqttClient();
|
||||
mqtt->onMessage(onMqttMessage);
|
||||
mqtt->onConnect(onMqttConnect);
|
||||
}
|
||||
if (mqtt->connected()) return true;
|
||||
|
||||
DEBUG_PRINTLN("Reconnecting MQTT");
|
||||
IPAddress mqttIP;
|
||||
if (mqttIP.fromString(mqttServer)) //see if server is IP or domain
|
||||
{
|
||||
mqtt->setServer(mqttIP, mqttPort);
|
||||
} else {
|
||||
mqtt->setServer(mqttServer, mqttPort);
|
||||
}
|
||||
mqtt->setClientId(mqttClientID);
|
||||
if (mqttUser[0] && mqttPass[0]) mqtt->setCredentials(mqttUser, mqttPass);
|
||||
|
||||
strcpy(mqttStatusTopic, mqttDeviceTopic);
|
||||
strcat(mqttStatusTopic, "/status");
|
||||
mqtt->setWill(mqttStatusTopic, 0, true, "offline");
|
||||
mqtt->setKeepAlive(MQTT_KEEP_ALIVE_TIME);
|
||||
mqtt->connect();
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
bool initMqtt(){return false;}
|
||||
void publishMqtt(){}
|
||||
#endif
|
||||
@@ -1,3 +1,6 @@
|
||||
#include "src/dependencies/timezone/Timezone.h"
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Acquires time from NTP server
|
||||
*/
|
||||
@@ -25,6 +28,8 @@ TimeChangeRule CDT = {Second, Sun, Mar, 2, -300 }; //Daylight time = UTC - 5
|
||||
TimeChangeRule CST = {First, Sun, Nov, 2, -360 }; //Standard time = UTC - 6 hours
|
||||
Timezone tzUSCentral(CDT, CST);
|
||||
|
||||
Timezone tzCASaskatchewan(CST, CST); //Central without DST
|
||||
|
||||
TimeChangeRule MDT = {Second, Sun, Mar, 2, -360 }; //Daylight time = UTC - 6 hours
|
||||
TimeChangeRule MST = {First, Sun, Nov, 2, -420 }; //Standard time = UTC - 7 hours
|
||||
Timezone tzUSMountain(MDT, MST);
|
||||
@@ -52,7 +57,16 @@ Timezone tzNZ(NZDT, NZST);
|
||||
TimeChangeRule NKST = {Last, Sun, Mar, 1, 510}; //Pyongyang Time = UTC + 8.5 hours
|
||||
Timezone tzNK(NKST, NKST);
|
||||
|
||||
Timezone* timezones[] = {&tzUTC, &tzUK, &tzEUCentral, &tzEUEastern, &tzUSEastern, &tzUSCentral, &tzUSMountain, &tzUSArizona, &tzUSPacific, &tzChina, &tzJapan, &tzAUEastern, &tzNZ, &tzNK};
|
||||
TimeChangeRule IST = {Last, Sun, Mar, 1, 330}; // India Standard Time = UTC + 5.5 hours
|
||||
Timezone tzIndia(IST, IST);
|
||||
|
||||
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()
|
||||
{
|
||||
@@ -72,7 +86,15 @@ void handleNetworkTime()
|
||||
|
||||
void sendNTPPacket()
|
||||
{
|
||||
WiFi.hostByName(ntpServerName, ntpServerIP);
|
||||
if (!ntpServerIP.fromString(ntpServerName)) //see if server is IP or domain
|
||||
{
|
||||
#ifdef ESP8266
|
||||
WiFi.hostByName(ntpServerName, ntpServerIP, 750);
|
||||
#else
|
||||
WiFi.hostByName(ntpServerName, ntpServerIP);
|
||||
#endif
|
||||
}
|
||||
|
||||
DEBUG_PRINTLN("send NTP");
|
||||
byte pbuf[NTP_PACKET_SIZE];
|
||||
memset(pbuf, 0, NTP_PACKET_SIZE);
|
||||
@@ -150,13 +172,16 @@ void setCountdown()
|
||||
//returns true if countdown just over
|
||||
bool checkCountdown()
|
||||
{
|
||||
long diff = countdownTime - now();
|
||||
local = abs(diff);
|
||||
if (diff <0 && !countdownOverTriggered)
|
||||
{
|
||||
if (macroCountdown != 0) applyMacro(macroCountdown);
|
||||
countdownOverTriggered = true;
|
||||
return true;
|
||||
unsigned long n = now();
|
||||
if (countdownMode) local = countdownTime - n + utcOffsetSecs;
|
||||
if (n > countdownTime) {
|
||||
if (countdownMode) local = n - countdownTime + utcOffsetSecs;
|
||||
if (!countdownOverTriggered)
|
||||
{
|
||||
if (macroCountdown != 0) applyMacro(macroCountdown);
|
||||
countdownOverTriggered = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -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,14 +275,10 @@ void setCronixie()
|
||||
DEBUG_PRINTLN((int)dP[5]);
|
||||
|
||||
_overlayCronixie(); //refresh
|
||||
#endif
|
||||
}
|
||||
|
||||
void _overlayCronixie()
|
||||
{
|
||||
if (countdownMode) checkCountdown();
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
|
||||
byte h = hour(local);
|
||||
byte h0 = h;
|
||||
byte m = minute(local);
|
||||
@@ -163,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];
|
||||
@@ -186,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
|
||||
@@ -197,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
|
||||
@@ -210,7 +340,37 @@ void _overlayCronixie()
|
||||
}
|
||||
}
|
||||
}
|
||||
strip.setCronixieDigits(_digitOut);
|
||||
//strip.trigger(); //this has a drawback, no effects slower than RefreshMs. advantage: Quick update, not dependant on effect time
|
||||
#endif
|
||||
}
|
||||
|
||||
void _drawOverlayCronixie()
|
||||
{
|
||||
byte offsets[] = {5, 0, 6, 1, 7, 2, 8, 3, 9, 4};
|
||||
|
||||
for (uint16_t i = 0; i < 6; i++)
|
||||
{
|
||||
byte o = 10*i;
|
||||
byte excl = 10;
|
||||
if(_digitOut[i] < 10) excl = offsets[_digitOut[i]];
|
||||
excl += o;
|
||||
|
||||
if (cronixieBacklight && _digitOut[i] <11)
|
||||
{
|
||||
uint32_t col = strip.gamma32(strip.getSegment(0).colors[1]);
|
||||
for (uint16_t j=o; j< o+10; j++) {
|
||||
if (j != excl) strip.setPixelColor(j, col);
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (uint16_t j=o; j< o+10; j++) {
|
||||
if (j != excl) strip.setPixelColor(j, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else // WLED_DISABLE_CRONIXIE
|
||||
byte getSameCodeLength(char code, int index, char const cronixieDisplay[]) {}
|
||||
void setCronixie() {}
|
||||
void _overlayCronixie() {}
|
||||
void _drawOverlayCronixie() {}
|
||||
#endif
|
||||
@@ -13,7 +13,9 @@
|
||||
#ifndef PalettesWLED_h
|
||||
#define PalettesWLED_h
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( ib_jul01_gp ) {
|
||||
#define GRADIENT_PALETTE_COUNT 39
|
||||
|
||||
const byte ib_jul01_gp[] PROGMEM = {
|
||||
0, 194, 1, 1,
|
||||
94, 1, 29, 18,
|
||||
132, 57,131, 28,
|
||||
@@ -24,7 +26,7 @@ DEFINE_GRADIENT_PALETTE( ib_jul01_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_vintage_57_gp ) {
|
||||
const byte es_vintage_57_gp[] PROGMEM = {
|
||||
0, 2, 1, 1,
|
||||
53, 18, 1, 0,
|
||||
104, 69, 29, 1,
|
||||
@@ -37,7 +39,7 @@ DEFINE_GRADIENT_PALETTE( es_vintage_57_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 32 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_vintage_01_gp ) {
|
||||
const byte es_vintage_01_gp[] PROGMEM = {
|
||||
0, 4, 1, 1,
|
||||
51, 16, 0, 1,
|
||||
76, 97,104, 3,
|
||||
@@ -53,7 +55,7 @@ DEFINE_GRADIENT_PALETTE( es_vintage_01_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_rivendell_15_gp ) {
|
||||
const byte es_rivendell_15_gp[] PROGMEM = {
|
||||
0, 1, 14, 5,
|
||||
101, 16, 36, 14,
|
||||
165, 56, 68, 30,
|
||||
@@ -67,7 +69,7 @@ DEFINE_GRADIENT_PALETTE( es_rivendell_15_gp ) {
|
||||
// Size: 36 bytes of program space.
|
||||
// Edited to be brighter
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( rgi_15_gp ) {
|
||||
const byte rgi_15_gp[] PROGMEM = {
|
||||
0, 4, 1, 70,
|
||||
31, 55, 1, 30,
|
||||
63, 255, 4, 7,
|
||||
@@ -84,7 +86,7 @@ DEFINE_GRADIENT_PALETTE( rgi_15_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 8 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( retro2_16_gp ) {
|
||||
const byte retro2_16_gp[] PROGMEM = {
|
||||
0, 188,135, 1,
|
||||
255, 46, 7, 1};
|
||||
|
||||
@@ -94,7 +96,7 @@ DEFINE_GRADIENT_PALETTE( retro2_16_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Analogous_1_gp ) {
|
||||
const byte Analogous_1_gp[] PROGMEM = {
|
||||
0, 3, 0,255,
|
||||
63, 23, 0,255,
|
||||
127, 67, 0,255,
|
||||
@@ -107,7 +109,7 @@ DEFINE_GRADIENT_PALETTE( Analogous_1_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_pinksplash_08_gp ) {
|
||||
const byte es_pinksplash_08_gp[] PROGMEM = {
|
||||
0, 126, 11,255,
|
||||
127, 197, 1, 22,
|
||||
175, 210,157,172,
|
||||
@@ -120,7 +122,7 @@ DEFINE_GRADIENT_PALETTE( es_pinksplash_08_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 16 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_ocean_breeze_036_gp ) {
|
||||
const byte es_ocean_breeze_036_gp[] PROGMEM = {
|
||||
0, 1, 6, 7,
|
||||
89, 1, 99,111,
|
||||
153, 144,209,255,
|
||||
@@ -132,7 +134,7 @@ DEFINE_GRADIENT_PALETTE( es_ocean_breeze_036_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 88 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( departure_gp ) {
|
||||
const byte departure_gp[] PROGMEM = {
|
||||
0, 8, 3, 0,
|
||||
42, 23, 7, 0,
|
||||
63, 75, 38, 6,
|
||||
@@ -152,7 +154,7 @@ DEFINE_GRADIENT_PALETTE( departure_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 36 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_landscape_64_gp ) {
|
||||
const byte es_landscape_64_gp[] PROGMEM = {
|
||||
0, 0, 0, 0,
|
||||
37, 2, 25, 1,
|
||||
76, 15,115, 5,
|
||||
@@ -169,7 +171,7 @@ DEFINE_GRADIENT_PALETTE( es_landscape_64_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 24 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_landscape_33_gp ) {
|
||||
const byte es_landscape_33_gp[] PROGMEM = {
|
||||
0, 1, 5, 0,
|
||||
19, 32, 23, 1,
|
||||
38, 161, 55, 1,
|
||||
@@ -183,7 +185,7 @@ DEFINE_GRADIENT_PALETTE( es_landscape_33_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 28 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( rainbowsherbet_gp ) {
|
||||
const byte rainbowsherbet_gp[] PROGMEM = {
|
||||
0, 255, 33, 4,
|
||||
43, 255, 68, 25,
|
||||
86, 255, 7, 25,
|
||||
@@ -198,7 +200,7 @@ DEFINE_GRADIENT_PALETTE( rainbowsherbet_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 24 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( gr65_hult_gp ) {
|
||||
const byte gr65_hult_gp[] PROGMEM = {
|
||||
0, 247,176,247,
|
||||
48, 255,136,255,
|
||||
89, 220, 29,226,
|
||||
@@ -212,7 +214,7 @@ DEFINE_GRADIENT_PALETTE( gr65_hult_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 32 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( gr64_hult_gp ) {
|
||||
const byte gr64_hult_gp[] PROGMEM = {
|
||||
0, 1,124,109,
|
||||
66, 1, 93, 79,
|
||||
104, 52, 65, 1,
|
||||
@@ -228,7 +230,7 @@ DEFINE_GRADIENT_PALETTE( gr64_hult_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 28 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( GMT_drywet_gp ) {
|
||||
const byte GMT_drywet_gp[] PROGMEM = {
|
||||
0, 47, 30, 2,
|
||||
42, 213,147, 24,
|
||||
84, 103,219, 52,
|
||||
@@ -243,7 +245,7 @@ DEFINE_GRADIENT_PALETTE( GMT_drywet_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 24 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( ib15_gp ) {
|
||||
const byte ib15_gp[] PROGMEM = {
|
||||
0, 113, 91,147,
|
||||
72, 157, 88, 78,
|
||||
89, 208, 85, 33,
|
||||
@@ -257,7 +259,7 @@ DEFINE_GRADIENT_PALETTE( ib15_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Tertiary_01_gp ) {
|
||||
const byte Tertiary_01_gp[] PROGMEM = {
|
||||
0, 0, 1,255,
|
||||
63, 3, 68, 45,
|
||||
127, 23,255, 0,
|
||||
@@ -270,7 +272,7 @@ DEFINE_GRADIENT_PALETTE( Tertiary_01_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 52 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( lava_gp ) {
|
||||
const byte lava_gp[] PROGMEM = {
|
||||
0, 0, 0, 0,
|
||||
46, 18, 0, 0,
|
||||
96, 113, 0, 0,
|
||||
@@ -291,7 +293,7 @@ DEFINE_GRADIENT_PALETTE( lava_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 28 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( fierce_ice_gp ) {
|
||||
const byte fierce_ice_gp[] PROGMEM = {
|
||||
0, 0, 0, 0,
|
||||
59, 0, 9, 45,
|
||||
119, 0, 38,255,
|
||||
@@ -306,7 +308,7 @@ DEFINE_GRADIENT_PALETTE( fierce_ice_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 44 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Colorfull_gp ) {
|
||||
const byte Colorfull_gp[] PROGMEM = {
|
||||
0, 10, 85, 5,
|
||||
25, 29,109, 18,
|
||||
60, 59,138, 42,
|
||||
@@ -325,7 +327,7 @@ DEFINE_GRADIENT_PALETTE( Colorfull_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 44 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Pink_Purple_gp ) {
|
||||
const byte Pink_Purple_gp[] PROGMEM = {
|
||||
0, 19, 2, 39,
|
||||
25, 26, 4, 45,
|
||||
51, 33, 6, 52,
|
||||
@@ -344,7 +346,7 @@ DEFINE_GRADIENT_PALETTE( Pink_Purple_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 28 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Sunset_Real_gp ) {
|
||||
const byte Sunset_Real_gp[] PROGMEM = {
|
||||
0, 120, 0, 0,
|
||||
22, 179, 22, 0,
|
||||
51, 255,104, 0,
|
||||
@@ -359,7 +361,7 @@ DEFINE_GRADIENT_PALETTE( Sunset_Real_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 44 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Sunset_Yellow_gp ) {
|
||||
const byte Sunset_Yellow_gp[] PROGMEM = {
|
||||
0, 10, 62,123,
|
||||
36, 56,130,103,
|
||||
87, 153,225, 85,
|
||||
@@ -378,7 +380,7 @@ DEFINE_GRADIENT_PALETTE( Sunset_Yellow_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 60 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Beech_gp ) {
|
||||
const byte Beech_gp[] PROGMEM = {
|
||||
0, 255,252,214,
|
||||
12, 255,252,214,
|
||||
22, 255,252,214,
|
||||
@@ -401,7 +403,7 @@ DEFINE_GRADIENT_PALETTE( Beech_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 32 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Another_Sunset_gp ) {
|
||||
const byte Another_Sunset_gp[] PROGMEM = {
|
||||
0, 110, 49, 11,
|
||||
29, 55, 34, 10,
|
||||
68, 22, 22, 9,
|
||||
@@ -420,7 +422,7 @@ DEFINE_GRADIENT_PALETTE( Another_Sunset_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 52 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( es_autumn_19_gp ) {
|
||||
const byte es_autumn_19_gp[] PROGMEM = {
|
||||
0, 26, 1, 1,
|
||||
51, 67, 4, 1,
|
||||
84, 118, 14, 1,
|
||||
@@ -441,7 +443,7 @@ DEFINE_GRADIENT_PALETTE( es_autumn_19_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 28 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( BlacK_Blue_Magenta_White_gp ) {
|
||||
const byte BlacK_Blue_Magenta_White_gp[] PROGMEM = {
|
||||
0, 0, 0, 0,
|
||||
42, 0, 0, 45,
|
||||
84, 0, 0,255,
|
||||
@@ -456,7 +458,7 @@ DEFINE_GRADIENT_PALETTE( BlacK_Blue_Magenta_White_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( BlacK_Magenta_Red_gp ) {
|
||||
const byte BlacK_Magenta_Red_gp[] PROGMEM = {
|
||||
0, 0, 0, 0,
|
||||
63, 42, 0, 45,
|
||||
127, 255, 0,255,
|
||||
@@ -469,7 +471,7 @@ DEFINE_GRADIENT_PALETTE( BlacK_Magenta_Red_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 28 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( BlacK_Red_Magenta_Yellow_gp ) {
|
||||
const byte BlacK_Red_Magenta_Yellow_gp[] PROGMEM = {
|
||||
0, 0, 0, 0,
|
||||
42, 42, 0, 0,
|
||||
84, 255, 0, 0,
|
||||
@@ -484,7 +486,7 @@ DEFINE_GRADIENT_PALETTE( BlacK_Red_Magenta_Yellow_gp ) {
|
||||
// converted for FastLED with gammas (2.6, 2.2, 2.5)
|
||||
// Size: 20 bytes of program space.
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Blue_Cyan_Yellow_gp ) {
|
||||
const byte Blue_Cyan_Yellow_gp[] PROGMEM = {
|
||||
0, 0, 0,255,
|
||||
63, 0, 55,255,
|
||||
127, 0,255,255,
|
||||
@@ -494,7 +496,7 @@ DEFINE_GRADIENT_PALETTE( Blue_Cyan_Yellow_gp ) {
|
||||
|
||||
//Custom palette by Aircoookie
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Orange_Teal_gp ) {
|
||||
const byte Orange_Teal_gp[] PROGMEM = {
|
||||
0, 0,150, 92,
|
||||
55, 0,150, 92,
|
||||
200, 255, 72, 0,
|
||||
@@ -502,7 +504,7 @@ DEFINE_GRADIENT_PALETTE( Orange_Teal_gp ) {
|
||||
|
||||
//Custom palette by Aircoookie
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Tiamat_gp ) {
|
||||
const byte Tiamat_gp[] PROGMEM = {
|
||||
0, 1, 2, 14, //gc
|
||||
33, 2, 5, 35, //gc from 47, 61,126
|
||||
100, 13,135, 92, //gc from 88,242,247
|
||||
@@ -517,7 +519,7 @@ DEFINE_GRADIENT_PALETTE( Tiamat_gp ) {
|
||||
|
||||
//Custom palette by Aircoookie
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( April_Night_gp ) {
|
||||
const byte April_Night_gp[] PROGMEM = {
|
||||
0, 1, 5, 45, //deep blue
|
||||
10, 1, 5, 45,
|
||||
25, 5,169,175, //light blue
|
||||
@@ -536,7 +538,7 @@ DEFINE_GRADIENT_PALETTE( April_Night_gp ) {
|
||||
244, 1, 5, 45,
|
||||
255, 1, 5, 45};
|
||||
|
||||
DEFINE_GRADIENT_PALETTE( Orangery_gp ) {
|
||||
const byte Orangery_gp[] PROGMEM = {
|
||||
0, 255, 95, 23,
|
||||
30, 255, 82, 0,
|
||||
60, 223, 13, 8,
|
||||
@@ -548,7 +550,7 @@ DEFINE_GRADIENT_PALETTE( Orangery_gp ) {
|
||||
255, 213, 37, 4};
|
||||
|
||||
//inspired by Mark Kriegsman https://gist.github.com/kriegsman/756ea6dcae8e30845b5a
|
||||
DEFINE_GRADIENT_PALETTE( C9_gp ) {
|
||||
const byte C9_gp[] PROGMEM = {
|
||||
0, 184, 4, 0, //red
|
||||
60, 184, 4, 0,
|
||||
65, 144, 44, 2, //amber
|
||||
@@ -558,25 +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};
|
||||
|
||||
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
|
||||
@@ -614,11 +626,8 @@ const TProgmemRGBGradientPalettePtr gGradientPalettes[] = {
|
||||
Orangery_gp, //47-34 Orangery
|
||||
C9_gp, //48-35 C9
|
||||
Sakura_gp, //49-36 Sakura
|
||||
Aurora_gp, //50-37 Aurora
|
||||
Atlantica_gp, //51-38 Atlantica
|
||||
};
|
||||
|
||||
|
||||
// Count of how many cpt-city gradients are defined:
|
||||
const uint8_t gGradientPaletteCount =
|
||||
sizeof( gGradientPalettes) / sizeof( TProgmemRGBGradientPalettePtr );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* Receives client input
|
||||
*/
|
||||
|
||||
void _setRandomColor(bool _sec,bool fromButton=false)
|
||||
void _setRandomColor(bool _sec,bool fromButton)
|
||||
{
|
||||
lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex);
|
||||
if (_sec){
|
||||
@@ -14,27 +16,41 @@ void _setRandomColor(bool _sec,bool fromButton=false)
|
||||
}
|
||||
|
||||
|
||||
bool isAsterisksOnly(const char* str, byte maxLen)
|
||||
{
|
||||
for (byte i = 0; i < maxLen; i++) {
|
||||
if (str[i] == 0) break;
|
||||
if (str[i] != '*') return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//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)
|
||||
{
|
||||
strcpy(clientSSID,request->arg("CS").c_str());
|
||||
if (request->arg("CP").charAt(0) != '*') strcpy(clientPass, request->arg("CP").c_str());
|
||||
strlcpy(clientSSID,request->arg("CS").c_str(), 33);
|
||||
|
||||
strcpy(cmDNS, request->arg("CM").c_str());
|
||||
if (!isAsterisksOnly(request->arg("CP").c_str(), 65)) strlcpy(clientPass, request->arg("CP").c_str(), 65);
|
||||
|
||||
strlcpy(cmDNS, request->arg("CM").c_str(), 33);
|
||||
|
||||
apBehavior = request->arg("AB").toInt();
|
||||
strcpy(apSSID, request->arg("AS").c_str());
|
||||
strlcpy(apSSID, request->arg("AS").c_str(), 33);
|
||||
apHide = request->hasArg("AH");
|
||||
int passlen = request->arg("AP").length();
|
||||
if (passlen == 0 || (passlen > 7 && request->arg("AP").charAt(0) != '*')) strcpy(apPass, request->arg("AP").c_str());
|
||||
if (passlen == 0 || (passlen > 7 && !isAsterisksOnly(request->arg("AP").c_str(), 65))) strlcpy(apPass, request->arg("AP").c_str(), 65);
|
||||
int t = request->arg("AC").toInt(); if (t > 0 && t < 14) apChannel = t;
|
||||
|
||||
noWifiSleep = request->hasArg("WS");
|
||||
|
||||
char k[3]; k[2] = 0;
|
||||
for (int i = 0; i<4; i++)
|
||||
{
|
||||
@@ -56,44 +72,20 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
{
|
||||
int t = request->arg("LC").toInt();
|
||||
if (t > 0 && t <= MAX_LEDS) ledCount = t;
|
||||
#ifndef ARDUINO_ARCH_ESP32
|
||||
#ifdef ESP8266
|
||||
#if LEDPIN == 3
|
||||
if (ledCount > MAX_LEDS_DMA) ledCount = MAX_LEDS_DMA; //DMA method uses too much ram
|
||||
#endif
|
||||
#endif
|
||||
strip.ablMilliampsMax = request->arg("MA").toInt();
|
||||
strip.milliampsPerLed = request->arg("LA").toInt();
|
||||
|
||||
useRGBW = request->hasArg("EW");
|
||||
strip.colorOrder = request->arg("CO").toInt();
|
||||
autoRGBtoRGBW = request->hasArg("AW");
|
||||
strip.rgbwMode = request->arg("AW").toInt();
|
||||
|
||||
briS = request->arg("CA").toInt();
|
||||
|
||||
//ignore settings and save current brightness, colors and fx as default
|
||||
if (request->hasArg("IS"))
|
||||
{
|
||||
for (byte i=0; i<4; i++)
|
||||
{
|
||||
colS[i] = col[i];
|
||||
colSecS[i] = colSec[i];
|
||||
}
|
||||
briS = bri;
|
||||
effectDefault = effectCurrent;
|
||||
effectSpeedDefault = effectSpeed;
|
||||
effectIntensityDefault = effectIntensity;
|
||||
effectPaletteDefault = effectPalette;
|
||||
} else {
|
||||
colS[0] = request->arg("CR").toInt();
|
||||
colS[1] = request->arg("CG").toInt();
|
||||
colS[2] = request->arg("CB").toInt();
|
||||
colSecS[0] = request->arg("SR").toInt();
|
||||
colSecS[1] = request->arg("SG").toInt();
|
||||
colSecS[2] = request->arg("SB").toInt();
|
||||
colS[3] = request->arg("CW").toInt();
|
||||
colSecS[3] = request->arg("SW").toInt();
|
||||
briS = request->arg("CA").toInt();
|
||||
effectDefault = request->arg("FX").toInt();
|
||||
effectSpeedDefault = request->arg("SX").toInt();
|
||||
effectIntensityDefault = request->arg("IX").toInt();
|
||||
effectPaletteDefault = request->arg("FP").toInt();
|
||||
}
|
||||
saveCurrPresetCycConf = request->hasArg("PC");
|
||||
turnOnAtBoot = request->hasArg("BO");
|
||||
t = request->arg("BP").toInt();
|
||||
@@ -106,7 +98,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (t > 0) transitionDelay = t;
|
||||
transitionDelayDefault = t;
|
||||
strip.paletteFade = request->hasArg("PF");
|
||||
enableSecTransition = request->hasArg("T2");
|
||||
|
||||
nightlightTargetBri = request->arg("TB").toInt();
|
||||
t = request->arg("TL").toInt();
|
||||
@@ -125,26 +116,15 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
//UI
|
||||
if (subPage == 3)
|
||||
{
|
||||
int t = request->arg("UI").toInt();
|
||||
if (t >= 0 && t < 3) uiConfiguration = t;
|
||||
strcpy(serverDescription, request->arg("DS").c_str());
|
||||
useHSBDefault = request->hasArg("MD");
|
||||
useHSB = useHSBDefault;
|
||||
currentTheme = request->arg("TH").toInt();
|
||||
char k[3]; k[0]='C'; k[2]=0;
|
||||
for(int i=0;i<6;i++)
|
||||
{
|
||||
k[1] = i+48;
|
||||
strcpy(cssCol[i],request->arg(k).c_str());
|
||||
}
|
||||
strcpy(cssFont,request->arg("CF").c_str());
|
||||
strlcpy(serverDescription, request->arg("DS").c_str(), 33);
|
||||
syncToggleReceive = request->hasArg("ST");
|
||||
}
|
||||
|
||||
//SYNC
|
||||
if (subPage == 4)
|
||||
{
|
||||
buttonEnabled = request->hasArg("BT");
|
||||
irEnabled = request->hasArg("IR");
|
||||
irEnabled = request->arg("IR").toInt();
|
||||
int t = request->arg("UP").toInt();
|
||||
if (t > 0) udpPort = t;
|
||||
receiveNotificationBrightness = request->hasArg("RB");
|
||||
@@ -160,9 +140,16 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
notifyTwice = request->hasArg("S2");
|
||||
|
||||
receiveDirect = request->hasArg("RD");
|
||||
e131SkipOutOfSequence = request->hasArg("ES");
|
||||
e131Multicast = request->hasArg("EM");
|
||||
t = request->arg("EP").toInt();
|
||||
if (t > 0) e131Port = t;
|
||||
t = request->arg("EU").toInt();
|
||||
if (t > 0 && t <= 63999) e131Universe = t;
|
||||
if (t >= 0 && t <= 63999) e131Universe = t;
|
||||
t = request->arg("DA").toInt();
|
||||
if (t >= 0 && t <= 510) DMXAddress = t;
|
||||
t = request->arg("DM").toInt();
|
||||
if (t >= DMX_MODE_DISABLED && t <= DMX_MODE_MULTIPLE_DRGB) DMXMode = t;
|
||||
t = request->arg("ET").toInt();
|
||||
if (t > 99 && t <= 65000) realtimeTimeoutMs = t;
|
||||
arlsForceMaxBri = request->hasArg("FB");
|
||||
@@ -171,21 +158,25 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
if (t >= -255 && t <= 255) arlsOffset = t;
|
||||
|
||||
alexaEnabled = request->hasArg("AL");
|
||||
strcpy(alexaInvocationName, request->arg("AI").c_str());
|
||||
strlcpy(alexaInvocationName, request->arg("AI").c_str(), 33);
|
||||
|
||||
if (request->hasArg("BK") && !request->arg("BK").equals("Hidden")) {
|
||||
strcpy(blynkApiKey,request->arg("BK").c_str()); initBlynk(blynkApiKey);
|
||||
strlcpy(blynkApiKey, request->arg("BK").c_str(), 36); initBlynk(blynkApiKey);
|
||||
}
|
||||
|
||||
strcpy(mqttServer, request->arg("MS").c_str());
|
||||
#ifdef WLED_ENABLE_MQTT
|
||||
mqttEnabled = request->hasArg("MQ");
|
||||
strlcpy(mqttServer, request->arg("MS").c_str(), 33);
|
||||
t = request->arg("MQPORT").toInt();
|
||||
if (t > 0) mqttPort = t;
|
||||
strcpy(mqttUser, request->arg("MQUSER").c_str());
|
||||
if (request->arg("MQPASS").charAt(0) != '*') strcpy(mqttPass, request->arg("MQPASS").c_str());
|
||||
strcpy(mqttClientID, request->arg("MQCID").c_str());
|
||||
strcpy(mqttDeviceTopic, request->arg("MD").c_str());
|
||||
strcpy(mqttGroupTopic, request->arg("MG").c_str());
|
||||
strlcpy(mqttUser, request->arg("MQUSER").c_str(), 41);
|
||||
if (!isAsterisksOnly(request->arg("MQPASS").c_str(), 41)) strlcpy(mqttPass, request->arg("MQPASS").c_str(), 41);
|
||||
strlcpy(mqttClientID, request->arg("MQCID").c_str(), 41);
|
||||
strlcpy(mqttDeviceTopic, request->arg("MD").c_str(), 33);
|
||||
strlcpy(mqttGroupTopic, request->arg("MG").c_str(), 33);
|
||||
#endif
|
||||
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
for (int i=0;i<4;i++){
|
||||
String a = "H"+String(i);
|
||||
hueIP[i] = request->arg(a).toInt();
|
||||
@@ -203,12 +194,14 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
huePollingEnabled = request->hasArg("HP");
|
||||
hueStoreAllowed = true;
|
||||
reconnectHue();
|
||||
#endif
|
||||
}
|
||||
|
||||
//TIME
|
||||
if (subPage == 5)
|
||||
{
|
||||
ntpEnabled = request->hasArg("NT");
|
||||
strlcpy(ntpServerName, request->arg("NS").c_str(), 33);
|
||||
useAMPM = !request->hasArg("CF");
|
||||
currentTimezone = request->arg("TZ").toInt();
|
||||
utcOffsetSecs = request->arg("UO").toInt();
|
||||
@@ -218,7 +211,6 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
|
||||
if (request->hasArg("OL")){
|
||||
overlayDefault = request->arg("OL").toInt();
|
||||
if (overlayCurrent != overlayDefault) strip.unlockAll();
|
||||
overlayCurrent = overlayDefault;
|
||||
}
|
||||
|
||||
@@ -229,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();
|
||||
@@ -296,7 +283,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
}
|
||||
if (!otaLock && request->arg("OP").length() > 0)
|
||||
{
|
||||
strcpy(otaPass,request->arg("OP").c_str());
|
||||
strlcpy(otaPass,request->arg("OP").c_str(), 33);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,8 +294,37 @@ 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);
|
||||
if (subPage == 2) {
|
||||
strip.init(useRGBW,ledCount,skipFirstLed);
|
||||
}
|
||||
if (subPage == 4) alexaInit();
|
||||
}
|
||||
|
||||
@@ -322,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;
|
||||
@@ -360,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) {
|
||||
@@ -369,15 +392,93 @@ 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");
|
||||
if (pos < 1) XML_response(request, false);
|
||||
if (pos < 1) XML_response(request);
|
||||
return true;
|
||||
//if you save a macro in one request, other commands in that request are ignored due to unwanted behavior otherwise
|
||||
}
|
||||
|
||||
strip.applyToAllSelected = true;
|
||||
|
||||
//segment select (sets main segment)
|
||||
byte prevMain = strip.getMainSegmentId();
|
||||
pos = req.indexOf("SM=");
|
||||
if (pos > 0) {
|
||||
strip.mainSegment = getNumVal(&req, pos);
|
||||
}
|
||||
byte main = strip.getMainSegmentId();
|
||||
if (main != prevMain) setValuesFromMainSeg();
|
||||
|
||||
pos = req.indexOf("SS=");
|
||||
if (pos > 0) {
|
||||
byte t = getNumVal(&req, pos);
|
||||
if (t < strip.getMaxSegments()) main = t;
|
||||
}
|
||||
|
||||
WS2812FX::Segment& mainseg = strip.getSegment(main);
|
||||
pos = req.indexOf("SV="); //segment selected
|
||||
if (pos > 0) mainseg.setOption(SEG_OPTION_SELECTED, (req.charAt(pos+3) != '0'));
|
||||
|
||||
uint16_t startI = mainseg.start;
|
||||
uint16_t stopI = mainseg.stop;
|
||||
uint8_t grpI = mainseg.grouping;
|
||||
uint16_t spcI = mainseg.spacing;
|
||||
pos = req.indexOf("&S="); //segment start
|
||||
if (pos > 0) {
|
||||
startI = getNumVal(&req, pos);
|
||||
}
|
||||
pos = req.indexOf("S2="); //segment stop
|
||||
if (pos > 0) {
|
||||
stopI = getNumVal(&req, pos);
|
||||
}
|
||||
pos = req.indexOf("GP="); //segment grouping
|
||||
if (pos > 0) {
|
||||
grpI = getNumVal(&req, pos);
|
||||
if (grpI == 0) grpI = 1;
|
||||
}
|
||||
pos = req.indexOf("SP="); //segment spacing
|
||||
if (pos > 0) {
|
||||
spcI = getNumVal(&req, pos);
|
||||
}
|
||||
strip.setSegment(main, startI, stopI, grpI, spcI);
|
||||
|
||||
main = strip.getMainSegmentId();
|
||||
|
||||
//set presets
|
||||
pos = req.indexOf("P1="); //sets first preset for cycle
|
||||
if (pos > 0) presetCycleMin = getNumVal(&req, pos);
|
||||
|
||||
pos = req.indexOf("P2="); //sets last preset for cycle
|
||||
if (pos > 0) presetCycleMax = getNumVal(&req, pos);
|
||||
|
||||
//preset cycle
|
||||
pos = req.indexOf("CY=");
|
||||
if (pos > 0)
|
||||
{
|
||||
presetCyclingEnabled = (req.charAt(pos+3) != '0');
|
||||
presetCycCurr = presetCycleMin;
|
||||
}
|
||||
|
||||
pos = req.indexOf("PT="); //sets cycle time in ms
|
||||
if (pos > 0) {
|
||||
int v = getNumVal(&req, pos);
|
||||
if (v > 49) presetCycleTime = v;
|
||||
}
|
||||
|
||||
pos = req.indexOf("PA="); //apply brightness from preset
|
||||
if (pos > 0) presetApplyBri = (req.charAt(pos+3) != '0');
|
||||
|
||||
pos = req.indexOf("PS="); //saves current in preset
|
||||
if (pos > 0) savePreset(getNumVal(&req, pos), persistSaves);
|
||||
|
||||
//apply preset
|
||||
if (updateVal(&req, "PL=", &presetCycCurr, presetCycleMin, presetCycleMax)) {
|
||||
applyPreset(presetCycCurr, presetApplyBri);
|
||||
}
|
||||
|
||||
//set brightness
|
||||
updateVal(&req, "&A=", &bri);
|
||||
|
||||
@@ -412,29 +513,11 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
if (pos > 0) {
|
||||
colorFromDecOrHexString(colSec, (char*)req.substring(pos + 3).c_str());
|
||||
}
|
||||
|
||||
//set 2nd to white
|
||||
pos = req.indexOf("SW");
|
||||
pos = req.indexOf("C3=");
|
||||
if (pos > 0) {
|
||||
if(useRGBW) {
|
||||
colSec[3] = 255;
|
||||
colSec[0] = 0;
|
||||
colSec[1] = 0;
|
||||
colSec[2] = 0;
|
||||
} else {
|
||||
colSec[0] = 255;
|
||||
colSec[1] = 255;
|
||||
colSec[2] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
//set 2nd to black
|
||||
pos = req.indexOf("SB");
|
||||
if (pos > 0) {
|
||||
colSec[3] = 0;
|
||||
colSec[0] = 0;
|
||||
colSec[1] = 0;
|
||||
colSec[2] = 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
|
||||
@@ -443,15 +526,6 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
_setRandomColor(getNumVal(&req, pos));
|
||||
}
|
||||
|
||||
//set 2nd to 1st
|
||||
pos = req.indexOf("SP");
|
||||
if (pos > 0) {
|
||||
colSec[0] = col[0];
|
||||
colSec[1] = col[1];
|
||||
colSec[2] = col[2];
|
||||
colSec[3] = col[3];
|
||||
}
|
||||
|
||||
//swap 2nd & 1st
|
||||
pos = req.indexOf("SC");
|
||||
if (pos > 0) {
|
||||
@@ -470,54 +544,10 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
updateVal(&req, "IX=", &effectIntensity);
|
||||
updateVal(&req, "FP=", &effectPalette, 0, strip.getPaletteCount()-1);
|
||||
|
||||
//set hue polling light: 0 -off
|
||||
#ifndef WLED_DISABLE_HUESYNC
|
||||
pos = req.indexOf("HP=");
|
||||
if (pos > 0) {
|
||||
int id = getNumVal(&req, pos);
|
||||
if (id > 0)
|
||||
{
|
||||
if (id < 100) huePollLightId = id;
|
||||
reconnectHue();
|
||||
} else {
|
||||
huePollingEnabled = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//set default control mode (0 - RGB, 1 - HSB)
|
||||
pos = req.indexOf("MD=");
|
||||
if (pos > 0) {
|
||||
useHSB = getNumVal(&req, pos);
|
||||
}
|
||||
|
||||
//set advanced overlay
|
||||
pos = req.indexOf("OL=");
|
||||
if (pos > 0) {
|
||||
overlayCurrent = getNumVal(&req, pos);
|
||||
strip.unlockAll();
|
||||
}
|
||||
|
||||
//(un)lock pixel (ranges)
|
||||
pos = req.indexOf("&L=");
|
||||
if (pos > 0) {
|
||||
uint16_t index = getNumVal(&req, pos);
|
||||
pos = req.indexOf("L2=");
|
||||
bool unlock = req.indexOf("UL") > 0;
|
||||
if (pos > 0) {
|
||||
uint16_t index2 = getNumVal(&req, pos);
|
||||
if (unlock) {
|
||||
strip.unlockRange(index, index2);
|
||||
} else {
|
||||
strip.lockRange(index, index2);
|
||||
}
|
||||
} else {
|
||||
if (unlock) {
|
||||
strip.unlock(index);
|
||||
} else {
|
||||
strip.lock(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//apply macro
|
||||
@@ -571,6 +601,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
if (pos > 0)
|
||||
{
|
||||
nightlightFade = (req.charAt(pos+3) != '0');
|
||||
nightlightColorFade = (req.charAt(pos+3) == '2'); //NighLightColorFade can only be enabled via API or Macro with "NF=2"
|
||||
nightlightActiveOld = false; //re-init
|
||||
}
|
||||
|
||||
@@ -601,7 +632,17 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
|
||||
//Segment reverse
|
||||
pos = req.indexOf("RV=");
|
||||
if (pos > 0) strip.getSegment(0).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;
|
||||
@@ -618,66 +659,28 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
if (countdownTime - now() > 0) countdownOverTriggered = false;
|
||||
}
|
||||
|
||||
//set presets
|
||||
pos = req.indexOf("P1="); //sets first preset for cycle
|
||||
if (pos > 0) presetCycleMin = getNumVal(&req, pos);
|
||||
|
||||
pos = req.indexOf("P2="); //sets last preset for cycle
|
||||
if (pos > 0) presetCycleMax = getNumVal(&req, pos);
|
||||
|
||||
//preset cycle
|
||||
pos = req.indexOf("CY=");
|
||||
if (pos > 0)
|
||||
{
|
||||
presetCyclingEnabled = (req.charAt(pos+3) != '0');
|
||||
presetCycCurr = presetCycleMin;
|
||||
}
|
||||
|
||||
pos = req.indexOf("PT="); //sets cycle time in ms
|
||||
if (pos > 0) {
|
||||
int v = getNumVal(&req, pos);
|
||||
if (v > 49) presetCycleTime = v;
|
||||
}
|
||||
|
||||
pos = req.indexOf("PA="); //apply brightness from preset
|
||||
if (pos > 0) presetApplyBri = (req.charAt(pos+3) != '0');
|
||||
|
||||
pos = req.indexOf("PC="); //apply color from preset
|
||||
if (pos > 0) presetApplyCol = (req.charAt(pos+3) != '0');
|
||||
|
||||
pos = req.indexOf("PX="); //apply effects from preset
|
||||
if (pos > 0) presetApplyFx = (req.charAt(pos+3) != '0');
|
||||
|
||||
pos = req.indexOf("PS="); //saves current in preset
|
||||
if (pos > 0) savePreset(getNumVal(&req, pos));
|
||||
|
||||
//apply preset
|
||||
if (updateVal(&req, "PL=", &presetCycCurr, presetCycleMin, presetCycleMax)) {
|
||||
applyPreset(presetCycCurr, presetApplyBri, presetApplyCol, presetApplyFx);
|
||||
}
|
||||
pos = req.indexOf("RB");
|
||||
if (pos > 0) doReboot = true;
|
||||
|
||||
//cronixie
|
||||
#ifndef WLED_DISABLE_CRONIXIE
|
||||
pos = req.indexOf("NX="); //sets digits to code
|
||||
if (pos > 0) {
|
||||
strcpy(cronixieDisplay,req.substring(pos + 3, pos + 9).c_str());
|
||||
setCronixie();
|
||||
}
|
||||
|
||||
if (req.indexOf("NB=") > 0) //sets backlight
|
||||
{
|
||||
cronixieBacklight = true;
|
||||
if (req.indexOf("NB=0") > 0)
|
||||
{
|
||||
cronixieBacklight = false;
|
||||
}
|
||||
if (overlayCurrent == 3) strip.setCronixieBacklight(cronixieBacklight);
|
||||
overlayRefreshedTime = 0;
|
||||
}
|
||||
#endif
|
||||
//mode, 1 countdown
|
||||
pos = req.indexOf("NM=");
|
||||
if (pos > 0) countdownMode = (req.charAt(pos+3) != '0');
|
||||
|
||||
pos = req.indexOf("NX="); //sets digits to code
|
||||
if (pos > 0) {
|
||||
strlcpy(cronixieDisplay, req.substring(pos + 3, pos + 9).c_str(), 6);
|
||||
setCronixie();
|
||||
}
|
||||
|
||||
pos = req.indexOf("NB=");
|
||||
if (pos > 0) //sets backlight
|
||||
{
|
||||
cronixieBacklight = (req.charAt(pos+3) != '0');
|
||||
overlayRefreshedTime = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
pos = req.indexOf("U0="); //user var 0
|
||||
if (pos > 0) {
|
||||
@@ -692,10 +695,10 @@ bool handleSet(AsyncWebServerRequest *request, const String& req)
|
||||
|
||||
//internal call, does not send XML response
|
||||
pos = req.indexOf("IN");
|
||||
if (pos < 1) XML_response(request, (req.indexOf("&IT") > 0)); //include theme if firstload
|
||||
if (pos < 1) XML_response(request);
|
||||
|
||||
pos = req.indexOf("&NN"); //do not send UDP notifications this time
|
||||
colorUpdated((pos > 0) ? 5:1);
|
||||
colorUpdated((pos > 0) ? NOTIFIER_CALL_MODE_NO_NOTIFY : NOTIFIER_CALL_MODE_DIRECT_CHANGE);
|
||||
|
||||
return true;
|
||||
}
|
||||
318
wled00/src/dependencies/arduino/core_esp8266_waveform.cpp
Normal file
318
wled00/src/dependencies/arduino/core_esp8266_waveform.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
esp8266_waveform - General purpose waveform generation and control,
|
||||
supporting outputs on all pins in parallel.
|
||||
|
||||
Copyright (c) 2018 Earle F. Philhower, III. All rights reserved.
|
||||
|
||||
The core idea is to have a programmable waveform generator with a unique
|
||||
high and low period (defined in microseconds). TIMER1 is set to 1-shot
|
||||
mode and is always loaded with the time until the next edge of any live
|
||||
waveforms.
|
||||
|
||||
Up to one waveform generator per pin supported.
|
||||
|
||||
Each waveform generator is synchronized to the ESP cycle counter, not the
|
||||
timer. This allows for removing interrupt jitter and delay as the counter
|
||||
always increments once per 80MHz clock. Changes to a waveform are
|
||||
contiguous and only take effect on the next waveform transition,
|
||||
allowing for smooth transitions.
|
||||
|
||||
This replaces older tone(), analogWrite(), and the Servo classes.
|
||||
|
||||
Everywhere in the code where "cycles" is used, it means ESP.getCycleTime()
|
||||
cycles, not TIMER1 cycles (which may be 2 CPU clocks @ 160MHz).
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef ESP8266
|
||||
#include <Arduino.h>
|
||||
#include "ets_sys.h"
|
||||
#include "core_esp8266_waveform.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Maximum delay between IRQs
|
||||
#define MAXIRQUS (10000)
|
||||
|
||||
// Set/clear GPIO 0-15 by bitmask
|
||||
#define SetGPIO(a) do { GPOS = a; } while (0)
|
||||
#define ClearGPIO(a) do { GPOC = a; } while (0)
|
||||
|
||||
// Waveform generator can create tones, PWM, and servos
|
||||
typedef struct {
|
||||
uint32_t nextServiceCycle; // ESP cycle timer when a transition required
|
||||
uint32_t expiryCycle; // For time-limited waveform, the cycle when this waveform must stop
|
||||
uint32_t nextTimeHighCycles; // Copy over low->high to keep smooth waveform
|
||||
uint32_t nextTimeLowCycles; // Copy over high->low to keep smooth waveform
|
||||
} Waveform;
|
||||
|
||||
static Waveform waveform[17]; // State of all possible pins
|
||||
static volatile uint32_t waveformState = 0; // Is the pin high or low, updated in NMI so no access outside the NMI code
|
||||
static volatile uint32_t waveformEnabled = 0; // Is it actively running, updated in NMI so no access outside the NMI code
|
||||
|
||||
// Enable lock-free by only allowing updates to waveformState and waveformEnabled from IRQ service routine
|
||||
static volatile uint32_t waveformToEnable = 0; // Message to the NMI handler to start a waveform on a inactive pin
|
||||
static volatile uint32_t waveformToDisable = 0; // Message to the NMI handler to disable a pin from waveform generation
|
||||
|
||||
static uint32_t (*timer1CB)() = NULL;
|
||||
|
||||
|
||||
// Non-speed critical bits
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
static inline ICACHE_RAM_ATTR uint32_t GetCycleCount() {
|
||||
uint32_t ccount;
|
||||
__asm__ __volatile__("esync; rsr %0,ccount":"=a"(ccount));
|
||||
return ccount;
|
||||
}
|
||||
|
||||
// Interrupt on/off control
|
||||
static ICACHE_RAM_ATTR void timer1Interrupt();
|
||||
static bool timerRunning = false;
|
||||
|
||||
static void initTimer() {
|
||||
timer1_disable();
|
||||
ETS_FRC_TIMER1_INTR_ATTACH(NULL, NULL);
|
||||
ETS_FRC_TIMER1_NMI_INTR_ATTACH(timer1Interrupt);
|
||||
timer1_enable(TIM_DIV1, TIM_EDGE, TIM_SINGLE);
|
||||
timerRunning = true;
|
||||
}
|
||||
|
||||
static void ICACHE_RAM_ATTR deinitTimer() {
|
||||
ETS_FRC_TIMER1_NMI_INTR_ATTACH(NULL);
|
||||
timer1_disable();
|
||||
timer1_isr_init();
|
||||
timerRunning = false;
|
||||
}
|
||||
|
||||
// Set a callback. Pass in NULL to stop it
|
||||
void setTimer1Callback(uint32_t (*fn)()) {
|
||||
timer1CB = fn;
|
||||
if (!timerRunning && fn) {
|
||||
initTimer();
|
||||
timer1_write(microsecondsToClockCycles(1)); // Cause an interrupt post-haste
|
||||
} else if (timerRunning && !fn && !waveformEnabled) {
|
||||
deinitTimer();
|
||||
}
|
||||
}
|
||||
|
||||
// Start up a waveform on a pin, or change the current one. Will change to the new
|
||||
// waveform smoothly on next low->high transition. For immediate change, stopWaveform()
|
||||
// first, then it will immediately begin.
|
||||
int startWaveform(uint8_t pin, uint32_t timeHighUS, uint32_t timeLowUS, uint32_t runTimeUS) {
|
||||
if ((pin > 16) || isFlashInterfacePin(pin)) {
|
||||
return false;
|
||||
}
|
||||
Waveform *wave = &waveform[pin];
|
||||
// Adjust to shave off some of the IRQ time, approximately
|
||||
wave->nextTimeHighCycles = microsecondsToClockCycles(timeHighUS);
|
||||
wave->nextTimeLowCycles = microsecondsToClockCycles(timeLowUS);
|
||||
wave->expiryCycle = runTimeUS ? GetCycleCount() + microsecondsToClockCycles(runTimeUS) : 0;
|
||||
if (runTimeUS && !wave->expiryCycle) {
|
||||
wave->expiryCycle = 1; // expiryCycle==0 means no timeout, so avoid setting it
|
||||
}
|
||||
|
||||
uint32_t mask = 1<<pin;
|
||||
if (!(waveformEnabled & mask)) {
|
||||
// Actually set the pin high or low in the IRQ service to guarantee times
|
||||
wave->nextServiceCycle = GetCycleCount() + microsecondsToClockCycles(1);
|
||||
waveformToEnable |= mask;
|
||||
if (!timerRunning) {
|
||||
initTimer();
|
||||
timer1_write(microsecondsToClockCycles(10));
|
||||
} else {
|
||||
// Ensure timely service....
|
||||
if (T1L > microsecondsToClockCycles(10)) {
|
||||
timer1_write(microsecondsToClockCycles(10));
|
||||
}
|
||||
}
|
||||
while (waveformToEnable) {
|
||||
delay(0); // Wait for waveform to update
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Speed critical bits
|
||||
#pragma GCC optimize ("O2")
|
||||
// Normally would not want two copies like this, but due to different
|
||||
// optimization levels the inline attribute gets lost if we try the
|
||||
// other version.
|
||||
|
||||
static inline ICACHE_RAM_ATTR uint32_t GetCycleCountIRQ() {
|
||||
uint32_t ccount;
|
||||
__asm__ __volatile__("rsr %0,ccount":"=a"(ccount));
|
||||
return ccount;
|
||||
}
|
||||
|
||||
static inline ICACHE_RAM_ATTR uint32_t min_u32(uint32_t a, uint32_t b) {
|
||||
if (a < b) {
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
// Stops a waveform on a pin
|
||||
int ICACHE_RAM_ATTR stopWaveform(uint8_t pin) {
|
||||
// Can't possibly need to stop anything if there is no timer active
|
||||
if (!timerRunning) {
|
||||
return false;
|
||||
}
|
||||
// If user sends in a pin >16 but <32, this will always point to a 0 bit
|
||||
// If they send >=32, then the shift will result in 0 and it will also return false
|
||||
uint32_t mask = 1<<pin;
|
||||
if (!(waveformEnabled & mask)) {
|
||||
return false; // It's not running, nothing to do here
|
||||
}
|
||||
waveformToDisable |= mask;
|
||||
// Ensure timely service....
|
||||
if (T1L > microsecondsToClockCycles(10)) {
|
||||
timer1_write(microsecondsToClockCycles(10));
|
||||
}
|
||||
while (waveformToDisable) {
|
||||
/* no-op */ // Can't delay() since stopWaveform may be called from an IRQ
|
||||
}
|
||||
if (!waveformEnabled && !timer1CB) {
|
||||
deinitTimer();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// The SDK and hardware take some time to actually get to our NMI code, so
|
||||
// decrement the next IRQ's timer value by a bit so we can actually catch the
|
||||
// real CPU cycle counter we want for the waveforms.
|
||||
#if F_CPU == 80000000
|
||||
#define DELTAIRQ (microsecondsToClockCycles(3))
|
||||
#else
|
||||
#define DELTAIRQ (microsecondsToClockCycles(2))
|
||||
#endif
|
||||
|
||||
|
||||
static ICACHE_RAM_ATTR void timer1Interrupt() {
|
||||
// Optimize the NMI inner loop by keeping track of the min and max GPIO that we
|
||||
// are generating. In the common case (1 PWM) these may be the same pin and
|
||||
// we can avoid looking at the other pins.
|
||||
static int startPin = 0;
|
||||
static int endPin = 0;
|
||||
|
||||
uint32_t nextEventCycles = microsecondsToClockCycles(MAXIRQUS);
|
||||
uint32_t timeoutCycle = GetCycleCountIRQ() + microsecondsToClockCycles(14);
|
||||
|
||||
if (waveformToEnable || waveformToDisable) {
|
||||
// Handle enable/disable requests from main app.
|
||||
waveformEnabled = (waveformEnabled & ~waveformToDisable) | waveformToEnable; // Set the requested waveforms on/off
|
||||
waveformState &= ~waveformToEnable; // And clear the state of any just started
|
||||
waveformToEnable = 0;
|
||||
waveformToDisable = 0;
|
||||
// Find the first GPIO being generated by checking GCC's find-first-set (returns 1 + the bit of the first 1 in an int32_t)
|
||||
startPin = __builtin_ffs(waveformEnabled) - 1;
|
||||
// Find the last bit by subtracting off GCC's count-leading-zeros (no offset in this one)
|
||||
endPin = 32 - __builtin_clz(waveformEnabled);
|
||||
}
|
||||
|
||||
bool done = false;
|
||||
if (waveformEnabled) {
|
||||
do {
|
||||
nextEventCycles = microsecondsToClockCycles(MAXIRQUS);
|
||||
for (int i = startPin; i <= endPin; i++) {
|
||||
uint32_t mask = 1<<i;
|
||||
|
||||
// If it's not on, ignore!
|
||||
if (!(waveformEnabled & mask)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Waveform *wave = &waveform[i];
|
||||
uint32_t now = GetCycleCountIRQ();
|
||||
|
||||
// Disable any waveforms that are done
|
||||
if (wave->expiryCycle) {
|
||||
int32_t expiryToGo = wave->expiryCycle - now;
|
||||
if (expiryToGo < 0) {
|
||||
// Done, remove!
|
||||
waveformEnabled &= ~mask;
|
||||
if (i == 16) {
|
||||
GP16O &= ~1;
|
||||
} else {
|
||||
ClearGPIO(mask);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for toggles
|
||||
int32_t cyclesToGo = wave->nextServiceCycle - now;
|
||||
if (cyclesToGo < 0) {
|
||||
// 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) {
|
||||
GP16O |= 1; // GPIO16 write slow as it's RMW
|
||||
} else {
|
||||
SetGPIO(mask);
|
||||
}
|
||||
wave->nextServiceCycle = now + wave->nextTimeHighCycles + cyclesToGo;
|
||||
nextEventCycles = min_u32(nextEventCycles, min_u32(wave->nextTimeHighCycles + cyclesToGo, 1));
|
||||
} else {
|
||||
if (i == 16) {
|
||||
GP16O &= ~1; // GPIO16 write slow as it's RMW
|
||||
} else {
|
||||
ClearGPIO(mask);
|
||||
}
|
||||
wave->nextServiceCycle = now + wave->nextTimeLowCycles + cyclesToGo;
|
||||
nextEventCycles = min_u32(nextEventCycles, min_u32(wave->nextTimeLowCycles + cyclesToGo, 1));
|
||||
}
|
||||
} else {
|
||||
uint32_t deltaCycles = wave->nextServiceCycle - now;
|
||||
nextEventCycles = min_u32(nextEventCycles, deltaCycles);
|
||||
}
|
||||
}
|
||||
|
||||
// Exit the loop if we've hit the fixed runtime limit or the next event is known to be after that timeout would occur
|
||||
uint32_t now = GetCycleCountIRQ();
|
||||
int32_t cycleDeltaNextEvent = timeoutCycle - (now + nextEventCycles);
|
||||
int32_t cyclesLeftTimeout = timeoutCycle - now;
|
||||
done = (cycleDeltaNextEvent < 0) || (cyclesLeftTimeout < 0);
|
||||
} while (!done);
|
||||
} // if (waveformEnabled)
|
||||
|
||||
if (timer1CB) {
|
||||
nextEventCycles = min_u32(nextEventCycles, timer1CB());
|
||||
}
|
||||
|
||||
if (nextEventCycles < microsecondsToClockCycles(10)) {
|
||||
nextEventCycles = microsecondsToClockCycles(10);
|
||||
}
|
||||
nextEventCycles -= DELTAIRQ;
|
||||
|
||||
// Do it here instead of global function to save time and because we know it's edge-IRQ
|
||||
#if F_CPU == 160000000
|
||||
T1L = nextEventCycles >> 1; // Already know we're in range by MAXIRQUS
|
||||
#else
|
||||
T1L = nextEventCycles; // Already know we're in range by MAXIRQUS
|
||||
#endif
|
||||
TEIE |= TEIE1; // Edge int enable
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
71
wled00/src/dependencies/arduino/core_esp8266_waveform.h
Normal file
71
wled00/src/dependencies/arduino/core_esp8266_waveform.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
esp8266_waveform - General purpose waveform generation and control,
|
||||
supporting outputs on all pins in parallel.
|
||||
|
||||
Copyright (c) 2018 Earle F. Philhower, III. All rights reserved.
|
||||
|
||||
The core idea is to have a programmable waveform generator with a unique
|
||||
high and low period (defined in microseconds). TIMER1 is set to 1-shot
|
||||
mode and is always loaded with the time until the next edge of any live
|
||||
waveforms.
|
||||
|
||||
Up to one waveform generator per pin supported.
|
||||
|
||||
Each waveform generator is synchronized to the ESP cycle counter, not the
|
||||
timer. This allows for removing interrupt jitter and delay as the counter
|
||||
always increments once per 80MHz clock. Changes to a waveform are
|
||||
contiguous and only take effect on the next waveform transition,
|
||||
allowing for smooth transitions.
|
||||
|
||||
This replaces older tone(), analogWrite(), and the Servo classes.
|
||||
|
||||
Everywhere in the code where "cycles" is used, it means ESP.getCycleTime()
|
||||
cycles, not TIMER1 cycles (which may be 2 CPU clocks @ 160MHz).
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#ifndef __ESP8266_WAVEFORM_H
|
||||
#define __ESP8266_WAVEFORM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Start or change a waveform of the specified high and low times on specific pin.
|
||||
// If runtimeUS > 0 then automatically stop it after that many usecs.
|
||||
// Returns true or false on success or failure.
|
||||
int startWaveform(uint8_t pin, uint32_t timeHighUS, uint32_t timeLowUS, uint32_t runTimeUS);
|
||||
// Stop a waveform, if any, on the specified pin.
|
||||
// Returns true or false on success or failure.
|
||||
int stopWaveform(uint8_t pin);
|
||||
|
||||
// Add a callback function to be called on *EVERY* timer1 trigger. The
|
||||
// callback returns the number of microseconds until the next desired call.
|
||||
// However, since it is called every timer1 interrupt, it may be called
|
||||
// again before this period. It should therefore use the ESP Cycle Counter
|
||||
// to determine whether or not to perform an operation.
|
||||
// Pass in NULL to disable the callback and, if no other waveforms being
|
||||
// generated, stop the timer as well.
|
||||
// Make sure the CB function has the ICACHE_RAM_ATTR decorator.
|
||||
void setTimer1Callback(uint32_t (*fn)());
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
5
wled00/src/dependencies/blynk/BlynkSimpleEsp.cpp
Normal file
5
wled00/src/dependencies/blynk/BlynkSimpleEsp.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#include "BlynkSimpleEsp.h"
|
||||
|
||||
WiFiClient _blynkWifiClient;
|
||||
BlynkArduinoClient _blynkTransport(_blynkWifiClient);
|
||||
BlynkWifi Blynk(_blynkTransport);
|
||||
@@ -89,8 +89,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
static WiFiClient _blynkWifiClient;
|
||||
static BlynkArduinoClient _blynkTransport(_blynkWifiClient);
|
||||
BlynkWifi Blynk(_blynkTransport);
|
||||
extern BlynkWifi Blynk;
|
||||
|
||||
#endif
|
||||
|
||||
106
wled00/src/dependencies/dmx/ESPDMX.cpp
Normal file
106
wled00/src/dependencies/dmx/ESPDMX.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
// - - - - -
|
||||
// ESPDMX - A Arduino library for sending and receiving DMX using the builtin serial hardware port.
|
||||
// ESPDMX.cpp: Library implementation file
|
||||
//
|
||||
// Copyright (C) 2015 Rick <ricardogg95@gmail.com>
|
||||
// This work is licensed under a GNU style license.
|
||||
//
|
||||
// Last change: Marcel Seerig <https://github.com/mseerig>
|
||||
//
|
||||
// Documentation and samples are available at https://github.com/Rickgg/ESP-Dmx
|
||||
// - - - - -
|
||||
|
||||
/* ----- LIBRARIES ----- */
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "ESPDMX.h"
|
||||
|
||||
|
||||
|
||||
#define dmxMaxChannel 512
|
||||
#define defaultMax 32
|
||||
|
||||
#define DMXSPEED 250000
|
||||
#define DMXFORMAT SERIAL_8N2
|
||||
#define BREAKSPEED 83333
|
||||
#define BREAKFORMAT SERIAL_8N1
|
||||
|
||||
bool dmxStarted = false;
|
||||
int sendPin = 2; //dafault on ESP8266
|
||||
|
||||
//DMX value array and size. Entry 0 will hold startbyte
|
||||
uint8_t dmxData[dmxMaxChannel] = {};
|
||||
int chanSize;
|
||||
|
||||
|
||||
void DMXESPSerial::init() {
|
||||
chanSize = defaultMax;
|
||||
|
||||
Serial1.begin(DMXSPEED);
|
||||
pinMode(sendPin, OUTPUT);
|
||||
dmxStarted = true;
|
||||
}
|
||||
|
||||
// Set up the DMX-Protocol
|
||||
void DMXESPSerial::init(int chanQuant) {
|
||||
|
||||
if (chanQuant > dmxMaxChannel || chanQuant <= 0) {
|
||||
chanQuant = defaultMax;
|
||||
}
|
||||
|
||||
chanSize = chanQuant;
|
||||
|
||||
Serial1.begin(DMXSPEED);
|
||||
pinMode(sendPin, OUTPUT);
|
||||
dmxStarted = true;
|
||||
}
|
||||
|
||||
// Function to read DMX data
|
||||
uint8_t DMXESPSerial::read(int Channel) {
|
||||
if (dmxStarted == false) init();
|
||||
|
||||
if (Channel < 1) Channel = 1;
|
||||
if (Channel > dmxMaxChannel) Channel = dmxMaxChannel;
|
||||
return(dmxData[Channel]);
|
||||
}
|
||||
|
||||
// Function to send DMX data
|
||||
void DMXESPSerial::write(int Channel, uint8_t value) {
|
||||
if (dmxStarted == false) init();
|
||||
|
||||
if (Channel < 1) Channel = 1;
|
||||
if (Channel > chanSize) Channel = chanSize;
|
||||
if (value < 0) value = 0;
|
||||
if (value > 255) value = 255;
|
||||
|
||||
dmxData[Channel] = value;
|
||||
}
|
||||
|
||||
void DMXESPSerial::end() {
|
||||
delete dmxData;
|
||||
chanSize = 0;
|
||||
Serial1.end();
|
||||
dmxStarted == false;
|
||||
}
|
||||
|
||||
void DMXESPSerial::update() {
|
||||
if (dmxStarted == false) init();
|
||||
|
||||
//Send break
|
||||
digitalWrite(sendPin, HIGH);
|
||||
Serial1.begin(BREAKSPEED, BREAKFORMAT);
|
||||
Serial1.write(0);
|
||||
Serial1.flush();
|
||||
delay(1);
|
||||
Serial1.end();
|
||||
|
||||
//send data
|
||||
Serial1.begin(DMXSPEED, DMXFORMAT);
|
||||
digitalWrite(sendPin, LOW);
|
||||
Serial1.write(dmxData, chanSize);
|
||||
Serial1.flush();
|
||||
delay(1);
|
||||
Serial1.end();
|
||||
}
|
||||
|
||||
// Function to update the DMX bus
|
||||
31
wled00/src/dependencies/dmx/ESPDMX.h
Normal file
31
wled00/src/dependencies/dmx/ESPDMX.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// - - - - -
|
||||
// ESPDMX - A Arduino library for sending and receiving DMX using the builtin serial hardware port.
|
||||
// ESPDMX.cpp: Library implementation file
|
||||
//
|
||||
// Copyright (C) 2015 Rick <ricardogg95@gmail.com>
|
||||
// This work is licensed under a GNU style license.
|
||||
//
|
||||
// Last change: Marcel Seerig <https://github.com/mseerig>
|
||||
//
|
||||
// Documentation and samples are available at https://github.com/Rickgg/ESP-Dmx
|
||||
// - - - - -
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
#ifndef ESPDMX_h
|
||||
#define ESPDMX_h
|
||||
|
||||
// ---- Methods ----
|
||||
|
||||
class DMXESPSerial {
|
||||
public:
|
||||
void init();
|
||||
void init(int MaxChan);
|
||||
uint8_t read(int Channel);
|
||||
void write(int channel, uint8_t value);
|
||||
void update();
|
||||
void end();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* E131.cpp
|
||||
*
|
||||
* Project: E131 - E.131 (sACN) library for Arduino
|
||||
* Copyright (c) 2015 Shelby Merrick
|
||||
* http://www.forkineye.com
|
||||
*
|
||||
* This program is provided free for you to use in any way that you wish,
|
||||
* subject to the laws and regulations where you are using it. Due diligence
|
||||
* is strongly suggested before using this code. Please give credit where due.
|
||||
*
|
||||
* The Author makes no warranty of any kind, express or implied, with regard
|
||||
* to this program or the documentation contained in this document. The
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "E131.h"
|
||||
#include <string.h>
|
||||
|
||||
/* E1.17 ACN Packet Identifier */
|
||||
const byte E131::ACN_ID[12] = { 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00 };
|
||||
|
||||
/* Constructor */
|
||||
E131::E131() {
|
||||
#ifdef NO_DOUBLE_BUFFER
|
||||
memset(pbuff1.raw, 0, sizeof(pbuff1.raw));
|
||||
packet = &pbuff1;
|
||||
pwbuff = packet;
|
||||
#else
|
||||
memset(pbuff1.raw, 0, sizeof(pbuff1.raw));
|
||||
memset(pbuff2.raw, 0, sizeof(pbuff2.raw));
|
||||
packet = &pbuff1;
|
||||
pwbuff = &pbuff2;
|
||||
#endif
|
||||
|
||||
stats.num_packets = 0;
|
||||
stats.packet_errors = 0;
|
||||
}
|
||||
|
||||
void E131::initUnicast() {
|
||||
udp.begin(E131_DEFAULT_PORT);
|
||||
}
|
||||
|
||||
void E131::initMulticast(uint16_t universe, uint8_t n) {
|
||||
IPAddress address = IPAddress(239, 255, ((universe >> 8) & 0xff),
|
||||
((universe >> 0) & 0xff));
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
ip4_addr_t ifaddr;
|
||||
ip4_addr_t multicast_addr;
|
||||
|
||||
ifaddr.addr = static_cast<uint32_t>(WiFi.localIP());
|
||||
for (uint8_t i = 1; i < n; i++) {
|
||||
multicast_addr.addr = static_cast<uint32_t>(IPAddress(239, 255,
|
||||
(((universe + i) >> 8) & 0xff), (((universe + i) >> 0)
|
||||
& 0xff)));
|
||||
igmp_joingroup(&ifaddr, &multicast_addr);
|
||||
}
|
||||
udp.beginMulticast(address, E131_DEFAULT_PORT);
|
||||
#else
|
||||
ip_addr_t ifaddr;
|
||||
ip_addr_t multicast_addr;
|
||||
|
||||
ifaddr.addr = static_cast<uint32_t>(WiFi.localIP());
|
||||
for (uint8_t i = 1; i < n; i++) {
|
||||
multicast_addr.addr = static_cast<uint32_t>(IPAddress(239, 255,
|
||||
(((universe + i) >> 8) & 0xff), (((universe + i) >> 0)
|
||||
& 0xff)));
|
||||
igmp_joingroup(&ifaddr, &multicast_addr);
|
||||
}
|
||||
udp.beginMulticast(WiFi.localIP(), address, E131_DEFAULT_PORT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void E131::begin(e131_listen_t type, uint16_t universe, uint8_t n) {
|
||||
if (type == E131_UNICAST)
|
||||
initUnicast();
|
||||
if (type == E131_MULTICAST)
|
||||
initMulticast(universe, n);
|
||||
}
|
||||
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* E131.h
|
||||
*
|
||||
* Project: E131 - E.131 (sACN) library for Arduino
|
||||
* Copyright (c) 2015 Shelby Merrick
|
||||
* http://www.forkineye.com
|
||||
*
|
||||
* This program is provided free for you to use in any way that you wish,
|
||||
* subject to the laws and regulations where you are using it. Due diligence
|
||||
* is strongly suggested before using this code. Please give credit where due.
|
||||
*
|
||||
* The Author makes no warranty of any kind, express or implied, with regard
|
||||
* to this program or the documentation contained in this document. The
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef E131_H_
|
||||
#define E131_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
/* Network interface detection. WiFi for ESP8266 and Ethernet for AVR */
|
||||
#if defined (ARDUINO_ARCH_ESP8266)
|
||||
# include <ESP8266WiFi.h>
|
||||
# define NO_DOUBLE_BUFFER
|
||||
#elif defined (ARDUINO_ARCH_ESP32)
|
||||
# include <WiFi.h>
|
||||
#endif
|
||||
# include <WiFiUdp.h>
|
||||
# include <lwip/ip_addr.h>
|
||||
# include <lwip/igmp.h>
|
||||
# define _UDP WiFiUDP
|
||||
|
||||
/* Defaults */
|
||||
#define E131_DEFAULT_PORT 5568
|
||||
|
||||
/* E1.31 Packet Offsets */
|
||||
#define E131_ROOT_PREAMBLE_SIZE 0
|
||||
#define E131_ROOT_POSTAMBLE_SIZE 2
|
||||
#define E131_ROOT_ID 4
|
||||
#define E131_ROOT_FLENGTH 16
|
||||
#define E131_ROOT_VECTOR 18
|
||||
#define E131_ROOT_CID 22
|
||||
|
||||
#define E131_FRAME_FLENGTH 38
|
||||
#define E131_FRAME_VECTOR 40
|
||||
#define E131_FRAME_SOURCE 44
|
||||
#define E131_FRAME_PRIORITY 108
|
||||
#define E131_FRAME_RESERVED 109
|
||||
#define E131_FRAME_SEQ 111
|
||||
#define E131_FRAME_OPT 112
|
||||
#define E131_FRAME_UNIVERSE 113
|
||||
|
||||
#define E131_DMP_FLENGTH 115
|
||||
#define E131_DMP_VECTOR 117
|
||||
#define E131_DMP_TYPE 118
|
||||
#define E131_DMP_ADDR_FIRST 119
|
||||
#define E131_DMP_ADDR_INC 121
|
||||
#define E131_DMP_COUNT 123
|
||||
#define E131_DMP_DATA 125
|
||||
|
||||
/* E1.31 Packet Structure */
|
||||
typedef union {
|
||||
struct {
|
||||
/* Root Layer */
|
||||
uint16_t preamble_size;
|
||||
uint16_t postamble_size;
|
||||
uint8_t acn_id[12];
|
||||
uint16_t root_flength;
|
||||
uint32_t root_vector;
|
||||
uint8_t cid[16];
|
||||
|
||||
/* Frame Layer */
|
||||
uint16_t frame_flength;
|
||||
uint32_t frame_vector;
|
||||
uint8_t source_name[64];
|
||||
uint8_t priority;
|
||||
uint16_t reserved;
|
||||
uint8_t sequence_number;
|
||||
uint8_t options;
|
||||
uint16_t universe;
|
||||
|
||||
/* DMP Layer */
|
||||
uint16_t dmp_flength;
|
||||
uint8_t dmp_vector;
|
||||
uint8_t type;
|
||||
uint16_t first_address;
|
||||
uint16_t address_increment;
|
||||
uint16_t property_value_count;
|
||||
uint8_t property_values[513];
|
||||
} __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;
|
||||
|
||||
/* Status structure */
|
||||
typedef struct {
|
||||
uint32_t num_packets;
|
||||
uint32_t packet_errors;
|
||||
IPAddress last_clientIP;
|
||||
uint16_t last_clientPort;
|
||||
} e131_stats_t;
|
||||
|
||||
class E131 {
|
||||
private:
|
||||
/* Constants for packet validation */
|
||||
static const uint8_t ACN_ID[];
|
||||
static const uint32_t VECTOR_ROOT = 4;
|
||||
static const uint32_t VECTOR_FRAME = 2;
|
||||
static const uint8_t VECTOR_DMP = 2;
|
||||
|
||||
e131_packet_t pbuff1; /* Packet buffer */
|
||||
#ifndef NO_DOUBLE_BUFFER
|
||||
e131_packet_t pbuff2; /* Double buffer */
|
||||
#endif
|
||||
e131_packet_t *pwbuff; /* Pointer to working packet buffer */
|
||||
_UDP udp; /* UDP handle */
|
||||
|
||||
/* Internal Initializers */
|
||||
void initUnicast();
|
||||
void initMulticast(uint16_t universe, uint8_t n = 1);
|
||||
|
||||
public:
|
||||
uint8_t *data; /* Pointer to DMX channel data */
|
||||
uint16_t universe; /* DMX Universe of last valid packet */
|
||||
e131_packet_t *packet; /* Pointer to last valid packet */
|
||||
e131_stats_t stats; /* Statistics tracker */
|
||||
|
||||
E131();
|
||||
|
||||
/* Generic UDP listener, no physical or IP configuration */
|
||||
void begin(e131_listen_t type, uint16_t universe = 1, uint8_t n = 1);
|
||||
|
||||
/* Main packet parser */
|
||||
inline uint16_t parsePacket() {
|
||||
e131_error_t error;
|
||||
uint16_t retval = 0;
|
||||
|
||||
int size = udp.parsePacket();
|
||||
if (size) {
|
||||
udp.readBytes(pwbuff->raw, size);
|
||||
error = validate();
|
||||
if (!error) {
|
||||
#ifndef NO_DOUBLE_BUFFER
|
||||
e131_packet_t *swap = packet;
|
||||
packet = pwbuff;
|
||||
pwbuff = swap;
|
||||
#endif
|
||||
universe = htons(packet->universe);
|
||||
data = packet->property_values + 1;
|
||||
retval = htons(packet->property_value_count) - 1;
|
||||
stats.num_packets++;
|
||||
stats.last_clientIP = udp.remoteIP();
|
||||
stats.last_clientPort = udp.remotePort();
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Packet validater */
|
||||
inline e131_error_t validate() {
|
||||
if (memcmp(pwbuff->acn_id, ACN_ID, sizeof(pwbuff->acn_id)))
|
||||
return ERROR_ACN_ID;
|
||||
if (htonl(pwbuff->root_vector) != VECTOR_ROOT)
|
||||
return ERROR_VECTOR_ROOT;
|
||||
if (htonl(pwbuff->frame_vector) != VECTOR_FRAME)
|
||||
return ERROR_VECTOR_FRAME;
|
||||
if (pwbuff->dmp_vector != VECTOR_DMP)
|
||||
return ERROR_VECTOR_DMP;
|
||||
if (pwbuff->property_values[0] != 0)
|
||||
return ERROR_IGNORE;
|
||||
return ERROR_NONE;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* E131_H_ */
|
||||
129
wled00/src/dependencies/e131/ESPAsyncE131.cpp
Normal file
129
wled00/src/dependencies/e131/ESPAsyncE131.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* ESPAsyncE131.cpp
|
||||
*
|
||||
* Project: ESPAsyncE131 - Asynchronous E.131 (sACN) library for Arduino ESP8266 and ESP32
|
||||
* Copyright (c) 2019 Shelby Merrick
|
||||
* http://www.forkineye.com
|
||||
*
|
||||
* This program is provided free for you to use in any way that you wish,
|
||||
* subject to the laws and regulations where you are using it. Due diligence
|
||||
* is strongly suggested before using this code. Please give credit where due.
|
||||
*
|
||||
* The Author makes no warranty of any kind, express or implied, with regard
|
||||
* to this program or the documentation contained in this document. The
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ESPAsyncE131.h"
|
||||
#include <string.h>
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// Public begin() members
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool ESPAsyncE131::begin(bool multicast, uint16_t port, uint16_t universe, uint8_t n) {
|
||||
bool success = false;
|
||||
|
||||
if (multicast) {
|
||||
success = initMulticast(port, universe, n);
|
||||
} else {
|
||||
success = initUnicast(port);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// Private init() members
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool ESPAsyncE131::initUnicast(uint16_t port) {
|
||||
bool success = false;
|
||||
|
||||
if (udp.listen(port)) {
|
||||
udp.onPacket(std::bind(&ESPAsyncE131::parsePacket, this,
|
||||
std::placeholders::_1));
|
||||
success = true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
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, port)) {
|
||||
ip4_addr_t ifaddr;
|
||||
ip4_addr_t multicast_addr;
|
||||
|
||||
ifaddr.addr = static_cast<uint32_t>(WiFi.localIP());
|
||||
for (uint8_t i = 1; i < n; i++) {
|
||||
multicast_addr.addr = static_cast<uint32_t>(IPAddress(239, 255,
|
||||
(((universe + i) >> 8) & 0xff), (((universe + i) >> 0)
|
||||
& 0xff)));
|
||||
igmp_joingroup(&ifaddr, &multicast_addr);
|
||||
}
|
||||
|
||||
udp.onPacket(std::bind(&ESPAsyncE131::parsePacket, this,
|
||||
std::placeholders::_1));
|
||||
|
||||
success = true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//
|
||||
// Packet parsing - Private
|
||||
//
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void ESPAsyncE131::parsePacket(AsyncUDPPacket _packet) {
|
||||
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)))
|
||||
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(), isArtnet);
|
||||
}
|
||||
}
|
||||
153
wled00/src/dependencies/e131/ESPAsyncE131.h
Normal file
153
wled00/src/dependencies/e131/ESPAsyncE131.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* ESPAsyncE131.h
|
||||
*
|
||||
* Project: ESPAsyncE131 - Asynchronous E.131 (sACN) library for Arduino ESP8266 and ESP32
|
||||
* Copyright (c) 2019 Shelby Merrick
|
||||
* http://www.forkineye.com
|
||||
*
|
||||
* This program is provided free for you to use in any way that you wish,
|
||||
* subject to the laws and regulations where you are using it. Due diligence
|
||||
* is strongly suggested before using this code. Please give credit where due.
|
||||
*
|
||||
* The Author makes no warranty of any kind, express or implied, with regard
|
||||
* to this program or the documentation contained in this document. The
|
||||
* 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_
|
||||
|
||||
#ifdef ESP32
|
||||
#include <WiFi.h>
|
||||
#include <AsyncUDP.h>
|
||||
#elif defined (ESP8266)
|
||||
#include <ESPAsyncUDP.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266WiFiMulti.h>
|
||||
#else
|
||||
#error Platform not supported
|
||||
#endif
|
||||
|
||||
#include <lwip/ip_addr.h>
|
||||
#include <lwip/igmp.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
typedef struct ip_addr ip4_addr_t;
|
||||
#endif
|
||||
|
||||
// Defaults
|
||||
#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
|
||||
#define E131_ROOT_POSTAMBLE_SIZE 2
|
||||
#define E131_ROOT_ID 4
|
||||
#define E131_ROOT_FLENGTH 16
|
||||
#define E131_ROOT_VECTOR 18
|
||||
#define E131_ROOT_CID 22
|
||||
|
||||
#define E131_FRAME_FLENGTH 38
|
||||
#define E131_FRAME_VECTOR 40
|
||||
#define E131_FRAME_SOURCE 44
|
||||
#define E131_FRAME_PRIORITY 108
|
||||
#define E131_FRAME_RESERVED 109
|
||||
#define E131_FRAME_SEQ 111
|
||||
#define E131_FRAME_OPT 112
|
||||
#define E131_FRAME_UNIVERSE 113
|
||||
|
||||
#define E131_DMP_FLENGTH 115
|
||||
#define E131_DMP_VECTOR 117
|
||||
#define E131_DMP_TYPE 118
|
||||
#define E131_DMP_ADDR_FIRST 119
|
||||
#define E131_DMP_ADDR_INC 121
|
||||
#define E131_DMP_COUNT 123
|
||||
#define E131_DMP_DATA 125
|
||||
|
||||
// E1.31 Packet Structure
|
||||
typedef union {
|
||||
struct { //E1.31 packet
|
||||
// Root Layer
|
||||
uint16_t preamble_size;
|
||||
uint16_t postamble_size;
|
||||
uint8_t acn_id[12];
|
||||
uint16_t root_flength;
|
||||
uint32_t root_vector;
|
||||
uint8_t cid[16];
|
||||
|
||||
// Frame Layer
|
||||
uint16_t frame_flength;
|
||||
uint32_t frame_vector;
|
||||
uint8_t source_name[64];
|
||||
uint8_t priority;
|
||||
uint16_t reserved;
|
||||
uint8_t sequence_number;
|
||||
uint8_t options;
|
||||
uint16_t universe;
|
||||
|
||||
// DMP Layer
|
||||
uint16_t dmp_flength;
|
||||
uint8_t dmp_vector;
|
||||
uint8_t type;
|
||||
uint16_t first_address;
|
||||
uint16_t address_increment;
|
||||
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;
|
||||
|
||||
// new packet callback
|
||||
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;
|
||||
|
||||
e131_packet_t *sbuff; // Pointer to scratch packet buffer
|
||||
AsyncUDP udp; // AsyncUDP
|
||||
|
||||
// Internal Initializers
|
||||
bool initUnicast(uint16_t port);
|
||||
bool initMulticast(uint16_t port, uint16_t universe, uint8_t n = 1);
|
||||
|
||||
// Packet parser callback
|
||||
void parsePacket(AsyncUDPPacket _packet);
|
||||
|
||||
e131_packet_callback_function _callback = nullptr;
|
||||
|
||||
public:
|
||||
ESPAsyncE131(e131_packet_callback_function callback);
|
||||
|
||||
// Generic UDP listener, no physical or IP configuration
|
||||
bool begin(bool multicast, uint16_t port = E131_DEFAULT_PORT, uint16_t universe = 1, uint8_t n = 1);
|
||||
};
|
||||
|
||||
#endif // ESPASYNCE131_H_
|
||||
@@ -10,7 +10,7 @@
|
||||
*/
|
||||
/*
|
||||
* @title Espalexa library
|
||||
* @version 2.4.3
|
||||
* @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.3 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.3\"}";
|
||||
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.3 by Christian Schwinne 2019";
|
||||
res += "\r\n\r\nEspalexa library v2.4.5 by Christian Schwinne 2020";
|
||||
server->send(200, "text/plain", res);
|
||||
}
|
||||
#endif
|
||||
@@ -298,7 +298,7 @@ private:
|
||||
"SERVER: FreeRTOS/6.0.5, UPnP/1.0, IpBridge/1.17.0\r\n" // _modelName, _modelNumber
|
||||
"hue-bridgeid: "+ escapedMac +"\r\n"
|
||||
"ST: urn:schemas-upnp-org:device:basic:1\r\n" // _deviceType
|
||||
"USN: uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"::upnp:rootdevice\r\n" // _uuid::_deviceType
|
||||
"USN: uuid:2f402f80-da50-11e1-9b23-"+ escapedMac +"::ssdp:all\r\n" // _uuid::_deviceType
|
||||
"\r\n";
|
||||
|
||||
espalexaUdp.beginPacket(espalexaUdp.remoteIP(), espalexaUdp.remotePort());
|
||||
@@ -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) {
|
||||
//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();
|
||||
}
|
||||
@@ -443,7 +444,7 @@ public:
|
||||
if (req.indexOf("api") <0) return false; //return if not an API call
|
||||
EA_DEBUGLN("ok");
|
||||
|
||||
if (body.indexOf("devicetype") > 0) //client wants a hue api username, we dont care and give static
|
||||
if (body.indexOf("devicetype") > 0) //client wants a hue api username, we don't care and give static
|
||||
{
|
||||
EA_DEBUGLN("devType");
|
||||
body = "";
|
||||
@@ -453,7 +454,7 @@ public:
|
||||
|
||||
if (req.indexOf("state") > 0) //client wants to control light
|
||||
{
|
||||
server->send(200, "application/json", "[{\"success\":true}]"); //short valid response
|
||||
server->send(200, "application/json", "[{\"success\":{\"/lights/1/state/\": true}}]");
|
||||
|
||||
uint32_t devId = req.substring(req.indexOf("lights")+7).toInt();
|
||||
EA_DEBUG("ls"); EA_DEBUGLN(devId);
|
||||
@@ -550,7 +551,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
//we dont care about other api commands at this time and send empty JSON
|
||||
//we don't care about other api commands at this time and send empty JSON
|
||||
server->send(200, "application/json", "{}");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -110,8 +110,8 @@ uint32_t EspalexaDevice::getKelvin()
|
||||
uint32_t EspalexaDevice::getRGB()
|
||||
{
|
||||
if (_rgb != 0) return _rgb; //color has not changed
|
||||
uint8_t rgb[3];
|
||||
float r, g, b;
|
||||
byte rgb[4]{0, 0, 0, 0};
|
||||
float r, g, b, w;
|
||||
|
||||
if (_mode == EspalexaColorMode::none) return 0;
|
||||
|
||||
@@ -122,11 +122,11 @@ uint32_t EspalexaDevice::getRGB()
|
||||
float temp = 10000/ _ct; //kelvins = 1,000,000/mired (and that /100)
|
||||
float r, g, b;
|
||||
|
||||
if( temp <= 66 ){
|
||||
if (temp <= 66) {
|
||||
r = 255;
|
||||
g = temp;
|
||||
g = 99.470802 * log(g) - 161.119568;
|
||||
if( temp <= 19){
|
||||
if (temp <= 19) {
|
||||
b = 0;
|
||||
} else {
|
||||
b = temp-10;
|
||||
@@ -143,6 +143,7 @@ uint32_t EspalexaDevice::getRGB()
|
||||
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;
|
||||
@@ -220,6 +221,12 @@ uint32_t EspalexaDevice::getRGB()
|
||||
return _rgb;
|
||||
}
|
||||
|
||||
//white channel for RGBW lights. Always 0 unless colormode is ct
|
||||
uint8_t EspalexaDevice::getW()
|
||||
{
|
||||
return (getRGB() >> 24) & 0xFF;
|
||||
}
|
||||
|
||||
uint8_t EspalexaDevice::getR()
|
||||
{
|
||||
return (getRGB() >> 16) & 0xFF;
|
||||
|
||||
@@ -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 };
|
||||
@@ -51,6 +52,7 @@ public:
|
||||
uint8_t getR();
|
||||
uint8_t getG();
|
||||
uint8_t getB();
|
||||
uint8_t getW();
|
||||
EspalexaColorMode getColorMode();
|
||||
EspalexaDeviceType getType();
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "ArduinoJson-v6.h"
|
||||
#include <Print.h>
|
||||
|
||||
#define DYNAMYC_JSON_DOCUMENT_SIZE 4096
|
||||
#define DYNAMIC_JSON_DOCUMENT_SIZE 8192
|
||||
|
||||
constexpr const char* JSON_MIMETYPE = "application/json";
|
||||
|
||||
@@ -60,7 +60,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
|
||||
|
||||
public:
|
||||
|
||||
AsyncJsonResponse(size_t maxJsonBufferSize = DYNAMYC_JSON_DOCUMENT_SIZE, bool isArray=false) : _jsonBuffer(maxJsonBufferSize), _isValid{false} {
|
||||
AsyncJsonResponse(size_t maxJsonBufferSize = DYNAMIC_JSON_DOCUMENT_SIZE, bool isArray=false) : _jsonBuffer(maxJsonBufferSize), _isValid{false} {
|
||||
_code = 200;
|
||||
_contentType = JSON_MIMETYPE;
|
||||
if(isArray)
|
||||
@@ -90,7 +90,7 @@ class AsyncJsonResponse: public AsyncAbstractResponse {
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::function<void(AsyncWebServerRequest *request, JsonObject json)> ArJsonRequestHandlerFunction;
|
||||
typedef std::function<void(AsyncWebServerRequest *request)> ArJsonRequestHandlerFunction;
|
||||
|
||||
class AsyncCallbackJsonWebHandler: public AsyncWebHandler {
|
||||
private:
|
||||
@@ -103,7 +103,7 @@ protected:
|
||||
int _maxContentLength;
|
||||
public:
|
||||
|
||||
AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize=DYNAMYC_JSON_DOCUMENT_SIZE)
|
||||
AsyncCallbackJsonWebHandler(const String& uri, ArJsonRequestHandlerFunction onRequest, size_t maxJsonBufferSize=DYNAMIC_JSON_DOCUMENT_SIZE)
|
||||
: _uri(uri), _method(HTTP_POST|HTTP_PUT|HTTP_PATCH), _onRequest(onRequest), maxJsonBufferSize(maxJsonBufferSize), _maxContentLength(16384) {}
|
||||
|
||||
void setMethod(WebRequestMethodComposite method){ _method = method; }
|
||||
@@ -127,15 +127,8 @@ public:
|
||||
virtual void handleRequest(AsyncWebServerRequest *request) override final {
|
||||
if(_onRequest) {
|
||||
if (request->_tempObject != NULL) {
|
||||
|
||||
DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize);
|
||||
DeserializationError error = deserializeJson(jsonBuffer, (uint8_t*)(request->_tempObject));
|
||||
if(!error) {
|
||||
JsonObject json = jsonBuffer.as<JsonObject>();
|
||||
|
||||
_onRequest(request, json);
|
||||
return;
|
||||
}
|
||||
_onRequest(request);
|
||||
return;
|
||||
}
|
||||
request->send(_contentLength > _maxContentLength ? 413 : 400);
|
||||
} else {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#include "TimeLib.h"
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "Timezone.h"
|
||||
|
||||
//THIS LINE WAS ADDED FOR COMPATIBILY WITH THE WLED DEPENDENCY STRUCTURE. REMOVE IF YOU USE IT OUTSIDE OF WLED!
|
||||
#include "../time/Time.h"
|
||||
#include "../time/TimeLib.h"
|
||||
|
||||
#ifdef __AVR__
|
||||
#include <avr/eeprom.h>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
|
||||
#include "../time/Time.h" //http://www.arduino.cc/playground/Code/Time
|
||||
#include "../time/TimeLib.h" //http://www.arduino.cc/playground/Code/Time
|
||||
|
||||
//convenient constants for dstRules
|
||||
enum week_t {Last, First, Second, Third, Fourth};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
https://github.com/kitesurfer1404/WS2812FX/
|
||||
|
||||
The WS2812FX implementation was heavily altered and differs from its master branch.
|
||||
Due to regural changes to the library code it is kept in the source dir for now.
|
||||
Due to regular changes to the library code it is kept in the source dir for now.
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
#include "wled.h"
|
||||
|
||||
/*
|
||||
* UDP notifier
|
||||
* UDP sync notifier
|
||||
*/
|
||||
|
||||
#define WLEDPACKETSIZE 29
|
||||
#define UDP_IN_MAXSIZE 1472
|
||||
|
||||
|
||||
void notify(byte callMode, bool followUp=false)
|
||||
void notify(byte callMode, bool followUp)
|
||||
{
|
||||
if (!udpConnected) return;
|
||||
switch (callMode)
|
||||
{
|
||||
case 0: return;
|
||||
case 1: if (!notifyDirect) return; break;
|
||||
case 2: if (!notifyButton) return; break;
|
||||
case 4: if (!notifyDirect) return; break;
|
||||
case 6: if (!notifyDirect) return; break; //fx change
|
||||
case 7: if (!notifyHue) return; break;
|
||||
case 8: if (!notifyDirect) return; break;
|
||||
case 9: if (!notifyDirect) return; break;
|
||||
case 10: if (!notifyAlexa) return; break;
|
||||
case NOTIFIER_CALL_MODE_INIT: return;
|
||||
case NOTIFIER_CALL_MODE_DIRECT_CHANGE: if (!notifyDirect) return; break;
|
||||
case NOTIFIER_CALL_MODE_BUTTON: if (!notifyButton) return; break;
|
||||
case NOTIFIER_CALL_MODE_NIGHTLIGHT: if (!notifyDirect) return; break;
|
||||
case NOTIFIER_CALL_MODE_HUE: if (!notifyHue) return; break;
|
||||
case NOTIFIER_CALL_MODE_PRESET_CYCLE: if (!notifyDirect) return; break;
|
||||
case NOTIFIER_CALL_MODE_BLYNK: if (!notifyDirect) return; break;
|
||||
case NOTIFIER_CALL_MODE_ALEXA: if (!notifyAlexa) return; break;
|
||||
default: return;
|
||||
}
|
||||
byte udpOut[WLEDPACKETSIZE];
|
||||
@@ -38,7 +38,7 @@ void notify(byte callMode, bool followUp=false)
|
||||
//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] = 6;
|
||||
udpOut[11] = 7;
|
||||
udpOut[12] = colSec[0];
|
||||
udpOut[13] = colSec[1];
|
||||
udpOut[14] = colSec[2];
|
||||
@@ -47,10 +47,12 @@ void notify(byte callMode, bool followUp=false)
|
||||
udpOut[17] = (transitionDelay >> 0) & 0xFF;
|
||||
udpOut[18] = (transitionDelay >> 8) & 0xFF;
|
||||
udpOut[19] = effectPalette;
|
||||
/*udpOut[20] = colTer[0];
|
||||
udpOut[21] = colTer[1];
|
||||
udpOut[22] = colTer[2];
|
||||
udpOut[23] = colTer[3];*/
|
||||
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;
|
||||
@@ -70,52 +72,20 @@ void notify(byte callMode, bool followUp=false)
|
||||
}
|
||||
|
||||
|
||||
void arlsLock(uint32_t timeoutMs)
|
||||
void realtimeLock(uint32_t timeoutMs, byte md)
|
||||
{
|
||||
if (!realtimeActive){
|
||||
if (!realtimeMode && !realtimeOverride){
|
||||
for (uint16_t i = 0; i < ledCount; i++)
|
||||
{
|
||||
strip.setPixelColor(i,0,0,0,0);
|
||||
}
|
||||
strip.unlockAll();
|
||||
realtimeActive = true;
|
||||
}
|
||||
|
||||
realtimeTimeout = millis() + timeoutMs;
|
||||
if (timeoutMs == 255001 || timeoutMs == 65000) realtimeTimeout = UINT32_MAX;
|
||||
if (arlsForceMaxBri) strip.setBrightness(255);
|
||||
}
|
||||
realtimeMode = md;
|
||||
|
||||
|
||||
void initE131(){
|
||||
if (WLED_CONNECTED && e131Enabled)
|
||||
{
|
||||
if (e131 == nullptr) e131 = new E131();
|
||||
e131->begin((e131Multicast) ? E131_MULTICAST : E131_UNICAST , e131Universe);
|
||||
} else {
|
||||
e131Enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handleE131(){
|
||||
//E1.31 protocol support
|
||||
if(WLED_CONNECTED && e131Enabled) {
|
||||
uint16_t len = e131->parsePacket();
|
||||
if (!len || e131->universe < e131Universe || e131->universe > e131Universe +4) return;
|
||||
len /= 3; //one LED is 3 DMX channels
|
||||
|
||||
uint16_t multipacketOffset = (e131->universe - e131Universe)*170; //if more than 170 LEDs (510 channels), client will send in next higher universe
|
||||
if (ledCount <= multipacketOffset) return;
|
||||
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
if (len + multipacketOffset > ledCount) len = ledCount - multipacketOffset;
|
||||
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
int j = i * 3;
|
||||
setRealtimePixel(i + multipacketOffset, e131->data[j], e131->data[j+1], e131->data[j+2], 0);
|
||||
}
|
||||
strip.show();
|
||||
}
|
||||
if (arlsForceMaxBri && !realtimeOverride) strip.setBrightness(255);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,15 +96,18 @@ void handleNotifications()
|
||||
notify(notificationSentCallMode,true);
|
||||
}
|
||||
|
||||
handleE131();
|
||||
if (e131NewData && millis() - strip.getLastShow() > 15)
|
||||
{
|
||||
e131NewData = false;
|
||||
strip.show();
|
||||
}
|
||||
|
||||
//unlock strip when realtime UDP times out
|
||||
if (realtimeActive && millis() > realtimeTimeout)
|
||||
if (realtimeMode && millis() > realtimeTimeout)
|
||||
{
|
||||
//strip.unlockAll();
|
||||
if (realtimeOverride == REALTIME_OVERRIDE_ONCE) realtimeOverride = REALTIME_OVERRIDE_NONE;
|
||||
strip.setBrightness(bri);
|
||||
realtimeActive = false;
|
||||
//strip.setMode(effectCurrent);
|
||||
realtimeMode = REALTIME_MODE_INACTIVE;
|
||||
realtimeIP[0] = 0;
|
||||
}
|
||||
|
||||
@@ -152,7 +125,8 @@ void handleNotifications()
|
||||
DEBUG_PRINTLN(rgbUdp.remoteIP());
|
||||
uint8_t lbuf[packetSize];
|
||||
rgbUdp.read(lbuf, packetSize);
|
||||
arlsLock(realtimeTimeoutMs);
|
||||
realtimeLock(realtimeTimeoutMs, REALTIME_MODE_HYPERION);
|
||||
if (realtimeOverride) return;
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 0; i < packetSize -2; i += 3)
|
||||
{
|
||||
@@ -172,10 +146,11 @@ void handleNotifications()
|
||||
notifierUdp.read(udpIn, packetSize);
|
||||
|
||||
//wled notifier, block if realtime packets active
|
||||
if (udpIn[0] == 0 && !realtimeActive && receiveNotifications)
|
||||
if (udpIn[0] == 0 && !realtimeMode && receiveNotifications)
|
||||
{
|
||||
//ignore notification if received within a second after sending a notification ourselves
|
||||
if (millis() - notificationSentTime < 1000) return;
|
||||
if (udpIn[1] > 199) return; //do not receive custom versions
|
||||
|
||||
bool someSel = (receiveNotificationBrightness || receiveNotificationColor || receiveNotificationEffects);
|
||||
//apply colors from notification
|
||||
@@ -184,7 +159,7 @@ void handleNotifications()
|
||||
col[0] = udpIn[3];
|
||||
col[1] = udpIn[4];
|
||||
col[2] = udpIn[5];
|
||||
if (udpIn[11] > 0) //check if sending modules white val is inteded
|
||||
if (udpIn[11] > 0) //sending module's white val is intended
|
||||
{
|
||||
col[3] = udpIn[10];
|
||||
if (udpIn[11] > 1)
|
||||
@@ -197,17 +172,14 @@ void handleNotifications()
|
||||
if (udpIn[11] > 5)
|
||||
{
|
||||
uint32_t t = (udpIn[25] << 24) | (udpIn[26] << 16) | (udpIn[27] << 8) | (udpIn[28]);
|
||||
t -= 2;
|
||||
t += 2;
|
||||
t -= millis();
|
||||
strip.timebase = t;
|
||||
}
|
||||
/*if (udpIn[11] > 6)
|
||||
if (udpIn[11] > 6)
|
||||
{
|
||||
colTer[0] = udpIn[20];
|
||||
colTer[1] = udpIn[21];
|
||||
colTer[2] = udpIn[22];
|
||||
colSec[3] = udpIn[23];
|
||||
}*/
|
||||
strip.setColor(2, udpIn[20], udpIn[21], udpIn[22], udpIn[23]); //tertiary color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,56 +201,58 @@ void handleNotifications()
|
||||
if (nightlightActive) nightlightDelayMins = udpIn[7];
|
||||
|
||||
if (receiveNotificationBrightness || !someSel) bri = udpIn[2];
|
||||
colorUpdated(3);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_NOTIFICATION);
|
||||
|
||||
} else if (udpIn[0] > 0 && udpIn[0] < 4 && receiveDirect) //1 warls //2 drgb //3 drgbw
|
||||
} else if (udpIn[0] > 0 && udpIn[0] < 5 && receiveDirect) //1 warls //2 drgb //3 drgbw
|
||||
{
|
||||
realtimeIP = notifierUdp.remoteIP();
|
||||
DEBUG_PRINTLN(notifierUdp.remoteIP());
|
||||
if (packetSize > 1) {
|
||||
if (udpIn[1] == 0)
|
||||
{
|
||||
realtimeTimeout = 0;
|
||||
return;
|
||||
} else {
|
||||
arlsLock(udpIn[1]*1000 +1);
|
||||
}
|
||||
if (udpIn[0] == 1) //warls
|
||||
{
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0);
|
||||
}
|
||||
} else if (udpIn[0] == 2) //drgb
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -2; i += 3)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
if (packetSize < 2) return;
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 3) //drgbw
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 4) //dnrgb
|
||||
{
|
||||
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
|
||||
for (uint16_t i = 4; i < packetSize -2; i += 3)
|
||||
{
|
||||
if (id >= ledCount) break;
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||
id++;
|
||||
}
|
||||
}
|
||||
strip.show();
|
||||
if (udpIn[1] == 0)
|
||||
{
|
||||
realtimeTimeout = 0;
|
||||
return;
|
||||
} else {
|
||||
realtimeLock(udpIn[1]*1000 +1, REALTIME_MODE_UDP);
|
||||
}
|
||||
if (realtimeOverride) return;
|
||||
|
||||
if (udpIn[0] == 1) //warls
|
||||
{
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0);
|
||||
}
|
||||
} else if (udpIn[0] == 2) //drgb
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -2; i += 3)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 3) //drgbw
|
||||
{
|
||||
uint16_t id = 0;
|
||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
||||
{
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||
|
||||
id++; if (id >= ledCount) break;
|
||||
}
|
||||
} else if (udpIn[0] == 4) //dnrgb
|
||||
{
|
||||
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
|
||||
for (uint16_t i = 4; i < packetSize -2; i += 3)
|
||||
{
|
||||
if (id >= ledCount) break;
|
||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||
id++;
|
||||
}
|
||||
}
|
||||
strip.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "wled.h"
|
||||
/*
|
||||
* This file allows you to add own functionality to WLED more easily
|
||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled01_eeprom.h)
|
||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
|
||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
||||
*/
|
||||
|
||||
461
wled00/wled.cpp
Normal file
461
wled00/wled.cpp
Normal file
@@ -0,0 +1,461 @@
|
||||
#define WLED_DEFINE_GLOBAL_VARS //only in one source file, wled.cpp!
|
||||
#include "wled.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
/*
|
||||
* Main WLED class implementation. Mostly initialization and connection logic
|
||||
*/
|
||||
|
||||
WLED::WLED()
|
||||
{
|
||||
}
|
||||
|
||||
// turns all LEDs off and restarts ESP
|
||||
void WLED::reset()
|
||||
{
|
||||
briT = 0;
|
||||
long dly = millis();
|
||||
while (millis() - dly < 250) {
|
||||
yield(); // enough time to send response to client
|
||||
}
|
||||
setAllLeds();
|
||||
DEBUG_PRINTLN("MODULE RESET");
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
bool oappendi(int i)
|
||||
{
|
||||
char s[11];
|
||||
sprintf(s, "%ld", i);
|
||||
return oappend(s);
|
||||
}
|
||||
|
||||
bool oappend(const char* txt)
|
||||
{
|
||||
uint16_t len = strlen(txt);
|
||||
if (olen + len >= OMAX)
|
||||
return false; // buffer full
|
||||
strcpy(obuf + olen, txt);
|
||||
olen += len;
|
||||
return true;
|
||||
}
|
||||
|
||||
void WLED::loop()
|
||||
{
|
||||
handleIR(); // 2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too
|
||||
handleConnection();
|
||||
handleSerial();
|
||||
handleNotifications();
|
||||
handleTransitions();
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
handleDMX();
|
||||
#endif
|
||||
userLoop();
|
||||
|
||||
yield();
|
||||
handleIO();
|
||||
handleIR();
|
||||
handleNetworkTime();
|
||||
handleAlexa();
|
||||
|
||||
handleOverlays();
|
||||
yield();
|
||||
#ifdef WLED_USE_ANALOG_LEDS
|
||||
strip.setRgbwPwm();
|
||||
#endif
|
||||
|
||||
if (doReboot)
|
||||
reset();
|
||||
|
||||
if (!realtimeMode || realtimeOverride) // block stuff if WARLS/Adalight is enabled
|
||||
{
|
||||
if (apActive)
|
||||
dnsServer.processNextRequest();
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (WLED_CONNECTED && aOtaEnabled)
|
||||
ArduinoOTA.handle();
|
||||
#endif
|
||||
handleNightlight();
|
||||
yield();
|
||||
|
||||
handleHue();
|
||||
handleBlynk();
|
||||
|
||||
yield();
|
||||
if (!offMode)
|
||||
strip.service();
|
||||
}
|
||||
yield();
|
||||
#ifdef ESP8266
|
||||
MDNS.update();
|
||||
#endif
|
||||
if (millis() - lastMqttReconnectAttempt > 30000) {
|
||||
if (lastMqttReconnectAttempt > millis()) rolloverMillis++; //millis() rolls over every 50 days
|
||||
initMqtt();
|
||||
}
|
||||
|
||||
// DEBUG serial logging
|
||||
#ifdef WLED_DEBUG
|
||||
if (millis() - debugTime > 9999) {
|
||||
DEBUG_PRINTLN("---DEBUG INFO---");
|
||||
DEBUG_PRINT("Runtime: ");
|
||||
DEBUG_PRINTLN(millis());
|
||||
DEBUG_PRINT("Unix time: ");
|
||||
DEBUG_PRINTLN(now());
|
||||
DEBUG_PRINT("Free heap: ");
|
||||
DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
DEBUG_PRINT("Wifi state: ");
|
||||
DEBUG_PRINTLN(WiFi.status());
|
||||
if (WiFi.status() != lastWifiState) {
|
||||
wifiStateChangedTime = millis();
|
||||
}
|
||||
lastWifiState = WiFi.status();
|
||||
DEBUG_PRINT("State time: ");
|
||||
DEBUG_PRINTLN(wifiStateChangedTime);
|
||||
DEBUG_PRINT("NTP last sync: ");
|
||||
DEBUG_PRINTLN(ntpLastSyncTime);
|
||||
DEBUG_PRINT("Client IP: ");
|
||||
DEBUG_PRINTLN(WiFi.localIP());
|
||||
DEBUG_PRINT("Loops/sec: ");
|
||||
DEBUG_PRINTLN(loops / 10);
|
||||
loops = 0;
|
||||
debugTime = millis();
|
||||
}
|
||||
loops++;
|
||||
#endif // WLED_DEBU
|
||||
}
|
||||
|
||||
void WLED::setup()
|
||||
{
|
||||
EEPROM.begin(EEPSIZE);
|
||||
ledCount = EEPROM.read(229) + ((EEPROM.read(398) << 8) & 0xFF00);
|
||||
if (ledCount > MAX_LEDS || ledCount == 0)
|
||||
ledCount = 30;
|
||||
|
||||
#ifdef ESP8266
|
||||
#if LEDPIN == 3
|
||||
if (ledCount > MAX_LEDS_DMA)
|
||||
ledCount = MAX_LEDS_DMA; // DMA method uses too much ram
|
||||
#endif
|
||||
#endif
|
||||
Serial.begin(115200);
|
||||
Serial.setTimeout(50);
|
||||
DEBUG_PRINTLN();
|
||||
DEBUG_PRINT("---WLED ");
|
||||
DEBUG_PRINT(versionString);
|
||||
DEBUG_PRINT(" ");
|
||||
DEBUG_PRINT(VERSION);
|
||||
DEBUG_PRINTLN(" INIT---");
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
DEBUG_PRINT("esp32 ");
|
||||
DEBUG_PRINTLN(ESP.getSdkVersion());
|
||||
#else
|
||||
DEBUG_PRINT("esp8266 ");
|
||||
DEBUG_PRINTLN(ESP.getCoreVersion());
|
||||
#endif
|
||||
int heapPreAlloc = ESP.getFreeHeap();
|
||||
DEBUG_PRINT("heap ");
|
||||
DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
|
||||
strip.init(EEPROM.read(372), ledCount, EEPROM.read(2204)); // init LEDs quickly
|
||||
strip.setBrightness(0);
|
||||
|
||||
DEBUG_PRINT("LEDs inited. heap usage ~");
|
||||
DEBUG_PRINTLN(heapPreAlloc - ESP.getFreeHeap());
|
||||
|
||||
#ifndef WLED_DISABLE_FILESYSTEM
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
SPIFFS.begin(true);
|
||||
#endif
|
||||
SPIFFS.begin();
|
||||
#endif
|
||||
|
||||
DEBUG_PRINTLN("Load EEPROM");
|
||||
loadSettingsFromEEPROM(true);
|
||||
beginStrip();
|
||||
userSetup();
|
||||
if (strcmp(clientSSID, DEFAULT_CLIENT_SSID) == 0)
|
||||
showWelcomePage = true;
|
||||
WiFi.persistent(false);
|
||||
|
||||
if (macroBoot > 0)
|
||||
applyMacro(macroBoot);
|
||||
Serial.println("Ada");
|
||||
|
||||
// generate module IDs
|
||||
escapedMac = WiFi.macAddress();
|
||||
escapedMac.replace(":", "");
|
||||
escapedMac.toLowerCase();
|
||||
if (strcmp(cmDNS, "x") == 0) // fill in unique mdns default
|
||||
{
|
||||
strcpy(cmDNS, "wled-");
|
||||
sprintf(cmDNS + 5, "%*s", 6, escapedMac.c_str() + 6);
|
||||
}
|
||||
if (mqttDeviceTopic[0] == 0) {
|
||||
strcpy(mqttDeviceTopic, "wled/");
|
||||
sprintf(mqttDeviceTopic + 5, "%*s", 6, escapedMac.c_str() + 6);
|
||||
}
|
||||
if (mqttClientID[0] == 0) {
|
||||
strcpy(mqttClientID, "WLED-");
|
||||
sprintf(mqttClientID + 5, "%*s", 6, escapedMac.c_str() + 6);
|
||||
}
|
||||
|
||||
strip.service();
|
||||
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (aOtaEnabled) {
|
||||
ArduinoOTA.onStart([]() {
|
||||
#ifdef ESP8266
|
||||
wifi_set_sleep_type(NONE_SLEEP_T);
|
||||
#endif
|
||||
DEBUG_PRINTLN("Start ArduinoOTA");
|
||||
});
|
||||
if (strlen(cmDNS) > 0)
|
||||
ArduinoOTA.setHostname(cmDNS);
|
||||
}
|
||||
#endif
|
||||
#ifdef WLED_ENABLE_DMX
|
||||
initDMX();
|
||||
#endif
|
||||
// HTTP server page init
|
||||
initServer();
|
||||
}
|
||||
|
||||
void WLED::beginStrip()
|
||||
{
|
||||
// Initialize NeoPixel Strip and button
|
||||
strip.setShowCallback(handleOverlayDraw);
|
||||
|
||||
#ifdef BTNPIN
|
||||
pinMode(BTNPIN, INPUT_PULLUP);
|
||||
#endif
|
||||
|
||||
if (bootPreset > 0)
|
||||
applyPreset(bootPreset, turnOnAtBoot);
|
||||
colorUpdated(NOTIFIER_CALL_MODE_INIT);
|
||||
|
||||
// init relay pin
|
||||
#if RLYPIN >= 0
|
||||
pinMode(RLYPIN, OUTPUT);
|
||||
#if RLYMDE
|
||||
digitalWrite(RLYPIN, bri);
|
||||
#else
|
||||
digitalWrite(RLYPIN, !bri);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// disable button if it is "pressed" unintentionally
|
||||
#ifdef BTNPIN
|
||||
if (digitalRead(BTNPIN) == LOW)
|
||||
buttonEnabled = false;
|
||||
#else
|
||||
buttonEnabled = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void WLED::initAP(bool resetAP)
|
||||
{
|
||||
if (apBehavior == AP_BEHAVIOR_BUTTON_ONLY && !resetAP)
|
||||
return;
|
||||
|
||||
if (!apSSID[0] || resetAP)
|
||||
strcpy(apSSID, "WLED-AP");
|
||||
if (resetAP)
|
||||
strcpy(apPass, DEFAULT_AP_PASS);
|
||||
DEBUG_PRINT("Opening access point ");
|
||||
DEBUG_PRINTLN(apSSID);
|
||||
WiFi.softAPConfig(IPAddress(4, 3, 2, 1), IPAddress(4, 3, 2, 1), IPAddress(255, 255, 255, 0));
|
||||
WiFi.softAP(apSSID, apPass, apChannel, apHide);
|
||||
|
||||
if (!apActive) // start captive portal if AP active
|
||||
{
|
||||
DEBUG_PRINTLN("Init AP interfaces");
|
||||
server.begin();
|
||||
if (udpPort > 0 && udpPort != ntpLocalPort) {
|
||||
udpConnected = notifierUdp.begin(udpPort);
|
||||
}
|
||||
if (udpRgbPort > 0 && udpRgbPort != ntpLocalPort && udpRgbPort != udpPort) {
|
||||
udpRgbConnected = rgbUdp.begin(udpRgbPort);
|
||||
}
|
||||
|
||||
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
|
||||
dnsServer.start(53, "*", WiFi.softAPIP());
|
||||
}
|
||||
apActive = true;
|
||||
}
|
||||
|
||||
void WLED::initConnection()
|
||||
{
|
||||
WiFi.disconnect(true); // close old connections
|
||||
#ifdef ESP8266
|
||||
WiFi.setPhyMode(WIFI_PHY_MODE_11N);
|
||||
#endif
|
||||
|
||||
if (staticIP[0] != 0 && staticGateway[0] != 0) {
|
||||
WiFi.config(staticIP, staticGateway, staticSubnet, IPAddress(8, 8, 8, 8));
|
||||
} else {
|
||||
WiFi.config(0U, 0U, 0U);
|
||||
}
|
||||
|
||||
lastReconnectAttempt = millis();
|
||||
|
||||
if (!WLED_WIFI_CONFIGURED) {
|
||||
DEBUG_PRINT("No connection configured. ");
|
||||
if (!apActive)
|
||||
initAP(); // instantly go to ap mode
|
||||
return;
|
||||
} else if (!apActive) {
|
||||
if (apBehavior == AP_BEHAVIOR_ALWAYS) {
|
||||
initAP();
|
||||
} else {
|
||||
DEBUG_PRINTLN("Access point disabled.");
|
||||
WiFi.softAPdisconnect(true);
|
||||
WiFi.mode(WIFI_STA);
|
||||
}
|
||||
}
|
||||
showWelcomePage = false;
|
||||
|
||||
DEBUG_PRINT("Connecting to ");
|
||||
DEBUG_PRINT(clientSSID);
|
||||
DEBUG_PRINTLN("...");
|
||||
|
||||
#ifdef ESP8266
|
||||
WiFi.hostname(serverDescription);
|
||||
#endif
|
||||
|
||||
WiFi.begin(clientSSID, clientPass);
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
WiFi.setSleep(!noWifiSleep);
|
||||
WiFi.setHostname(serverDescription);
|
||||
#else
|
||||
wifi_set_sleep_type((noWifiSleep) ? NONE_SLEEP_T : MODEM_SLEEP_T);
|
||||
#endif
|
||||
}
|
||||
|
||||
void WLED::initInterfaces()
|
||||
{
|
||||
DEBUG_PRINTLN("Init STA interfaces");
|
||||
|
||||
if (hueIP[0] == 0) {
|
||||
hueIP[0] = WiFi.localIP()[0];
|
||||
hueIP[1] = WiFi.localIP()[1];
|
||||
hueIP[2] = WiFi.localIP()[2];
|
||||
}
|
||||
|
||||
// init Alexa hue emulation
|
||||
if (alexaEnabled)
|
||||
alexaInit();
|
||||
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (aOtaEnabled)
|
||||
ArduinoOTA.begin();
|
||||
#endif
|
||||
|
||||
strip.service();
|
||||
// Set up mDNS responder:
|
||||
if (strlen(cmDNS) > 0) {
|
||||
if (!aOtaEnabled)
|
||||
MDNS.begin(cmDNS);
|
||||
|
||||
DEBUG_PRINTLN("mDNS started");
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
MDNS.addService("wled", "tcp", 80);
|
||||
MDNS.addServiceTxt("wled", "tcp", "mac", escapedMac.c_str());
|
||||
}
|
||||
server.begin();
|
||||
|
||||
if (udpPort > 0 && udpPort != ntpLocalPort) {
|
||||
udpConnected = notifierUdp.begin(udpPort);
|
||||
if (udpConnected && udpRgbPort != udpPort)
|
||||
udpRgbConnected = rgbUdp.begin(udpRgbPort);
|
||||
}
|
||||
if (ntpEnabled)
|
||||
ntpConnected = ntpUdp.begin(ntpLocalPort);
|
||||
|
||||
initBlynk(blynkApiKey);
|
||||
e131.begin(e131Multicast, e131Port, e131Universe, E131_MAX_UNIVERSE_COUNT);
|
||||
reconnectHue();
|
||||
initMqtt();
|
||||
interfacesInited = true;
|
||||
wasConnected = true;
|
||||
}
|
||||
|
||||
byte stacO = 0;
|
||||
uint32_t lastHeap;
|
||||
unsigned long heapTime = 0;
|
||||
|
||||
void WLED::handleConnection()
|
||||
{
|
||||
if (millis() < 2000 && (!WLED_WIFI_CONFIGURED || apBehavior == AP_BEHAVIOR_ALWAYS))
|
||||
return;
|
||||
if (lastReconnectAttempt == 0)
|
||||
initConnection();
|
||||
|
||||
// reconnect WiFi to clear stale allocations if heap gets too low
|
||||
if (millis() - heapTime > 5000) {
|
||||
uint32_t heap = ESP.getFreeHeap();
|
||||
if (heap < 9000 && lastHeap < 9000) {
|
||||
DEBUG_PRINT("Heap too low! ");
|
||||
DEBUG_PRINTLN(heap);
|
||||
forceReconnect = true;
|
||||
}
|
||||
lastHeap = heap;
|
||||
heapTime = millis();
|
||||
}
|
||||
|
||||
byte stac = 0;
|
||||
if (apActive) {
|
||||
#ifdef ESP8266
|
||||
stac = wifi_softap_get_station_num();
|
||||
#else
|
||||
wifi_sta_list_t stationList;
|
||||
esp_wifi_ap_get_sta_list(&stationList);
|
||||
stac = stationList.num;
|
||||
#endif
|
||||
if (stac != stacO) {
|
||||
stacO = stac;
|
||||
DEBUG_PRINT("Connected AP clients: ");
|
||||
DEBUG_PRINTLN(stac);
|
||||
if (!WLED_CONNECTED && WLED_WIFI_CONFIGURED) { // trying to connect, but not connected
|
||||
if (stac)
|
||||
WiFi.disconnect(); // disable search so that AP can work
|
||||
else
|
||||
initConnection(); // restart search
|
||||
}
|
||||
}
|
||||
}
|
||||
if (forceReconnect) {
|
||||
DEBUG_PRINTLN("Forcing reconnect.");
|
||||
initConnection();
|
||||
interfacesInited = false;
|
||||
forceReconnect = false;
|
||||
wasConnected = false;
|
||||
return;
|
||||
}
|
||||
if (!WLED_CONNECTED) {
|
||||
if (interfacesInited) {
|
||||
DEBUG_PRINTLN("Disconnected!");
|
||||
interfacesInited = false;
|
||||
initConnection();
|
||||
}
|
||||
if (millis() - lastReconnectAttempt > ((stac) ? 300000 : 20000) && WLED_WIFI_CONFIGURED)
|
||||
initConnection();
|
||||
if (!apActive && millis() - lastReconnectAttempt > 12000 && (!wasConnected || apBehavior == AP_BEHAVIOR_NO_CONN))
|
||||
initAP();
|
||||
} else if (!interfacesInited) { // newly connected
|
||||
DEBUG_PRINTLN("");
|
||||
DEBUG_PRINT("Connected! IP address: ");
|
||||
DEBUG_PRINTLN(WiFi.localIP());
|
||||
initInterfaces();
|
||||
userConnected();
|
||||
|
||||
// shut down AP
|
||||
if (apBehavior != AP_BEHAVIOR_ALWAYS && apActive) {
|
||||
dnsServer.stop();
|
||||
WiFi.softAPdisconnect(true);
|
||||
apActive = false;
|
||||
DEBUG_PRINTLN("Access point disabled.");
|
||||
}
|
||||
}
|
||||
}
|
||||
523
wled00/wled.h
Normal file
523
wled00/wled.h
Normal file
@@ -0,0 +1,523 @@
|
||||
#ifndef WLED_H
|
||||
#define WLED_H
|
||||
/*
|
||||
Main sketch, global variable declarations
|
||||
@title WLED project sketch
|
||||
@version 0.10.0
|
||||
@author Christian Schwinne
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 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
|
||||
@@ -1,576 +1,21 @@
|
||||
/*
|
||||
* Main sketch, global variable declarations
|
||||
*/
|
||||
/*
|
||||
* @title WLED project sketch
|
||||
* @version 0.8.6
|
||||
* @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
|
||||
|
||||
//You need to choose 1-2 of these features to disable:
|
||||
//#define WLED_DISABLE_ALEXA
|
||||
//#define WLED_DISABLE_BLYNK
|
||||
//#define WLED_DISABLE_CRONIXIE
|
||||
//#define WLED_DISABLE_HUESYNC
|
||||
//#define WLED_DISABLE_INFRARED //there is no pin left for this on ESP8266-01
|
||||
//#define WLED_DISABLE_MOBILE_UI
|
||||
|
||||
|
||||
#define WLED_DISABLE_FILESYSTEM //SPIFFS is not used by any WLED feature yet
|
||||
//#define WLED_ENABLE_FS_SERVING //Enable sending html file from SPIFFS before serving progmem version
|
||||
//#define WLED_ENABLE_FS_EDITOR //enable /edit page for editing SPIFFS content. Will also be disabled with OTA lock
|
||||
|
||||
//to toggle usb serial debug (un)comment the following line
|
||||
//#define WLED_DEBUG
|
||||
|
||||
|
||||
//library inclusions
|
||||
#include <Arduino.h>
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <ESPAsyncTCP.h>
|
||||
#else
|
||||
#include <WiFi.h>
|
||||
#include "esp_wifi.h"
|
||||
#include <ESPmDNS.h>
|
||||
#include <AsyncTCP.h>
|
||||
#include "SPIFFS.h"
|
||||
#endif
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <EEPROM.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <DNSServer.h>
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
#include <ArduinoOTA.h>
|
||||
#endif
|
||||
#include <SPIFFSEditor.h>
|
||||
#include "src/dependencies/time/Time.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/E131.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_classic.h"
|
||||
#include "html_mobile.h"
|
||||
#include "html_settings.h"
|
||||
#include "html_other.h"
|
||||
#include "FX.h"
|
||||
#include "ir_codes.h"
|
||||
|
||||
|
||||
#if IR_PIN < 0
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
#define WLED_DISABLE_INFRARED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
/*#ifndef WLED_DISABLE_INFRARED
|
||||
#include <IRremote.h>
|
||||
#endif*/ //there are issues with ESP32 infrared, so it is disabled for now
|
||||
#else
|
||||
#ifndef WLED_DISABLE_INFRARED
|
||||
#include <IRremoteESP8266.h>
|
||||
#include <IRrecv.h>
|
||||
#include <IRutils.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
//version code in format yymmddb (b = daily build)
|
||||
#define VERSION 1910255
|
||||
char versionString[] = "0.8.6";
|
||||
|
||||
|
||||
//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[] = "0.wled.pool.ntp.org"; //NTP server to use
|
||||
|
||||
|
||||
//WiFi CONFIG (all these can be changed via web UI, no need to set them here)
|
||||
char clientSSID[33] = "Your_Network";
|
||||
char clientPass[65] = "";
|
||||
char cmDNS[33] = "x"; //mDNS address (placeholder, will be replaced by wledXXXXXXXXXXXX.local)
|
||||
char apSSID[33] = ""; //AP off by default (unless setup)
|
||||
byte apChannel = 1; //2.4GHz WiFi AP channel (1-13)
|
||||
byte apHide = 0; //hidden AP SSID
|
||||
//byte apWaitTimeSecs = 32; //time to wait for connection before opening AP
|
||||
byte apBehavior = 0; //0: Open AP when no connection after boot 1: Open when no connection 2: Always open 3: Only when button pressed for 6 sec
|
||||
//bool recoveryAPDisabled = false; //never open AP (not recommended)
|
||||
IPAddress staticIP(0, 0, 0, 0); //static IP of ESP
|
||||
IPAddress staticGateway(0, 0, 0, 0); //gateway (router) IP
|
||||
IPAddress staticSubnet(255, 255, 255, 0); //most common subnet in home networks
|
||||
|
||||
//LED CONFIG
|
||||
uint16_t ledCount = 30; //overcurrent prevented by ABL
|
||||
bool useRGBW = false; //SK6812 strips can contain an extra White channel
|
||||
bool autoRGBtoRGBW = false; //if RGBW enabled, calculate White channel from RGB
|
||||
#define ABL_MILLIAMPS_DEFAULT 850; //auto lower brightness to stay close to milliampere limit
|
||||
bool turnOnAtBoot = true; //turn on LEDs at power-up
|
||||
byte bootPreset = 0; //save preset to load after power-up
|
||||
|
||||
byte colS[]{255, 159, 0, 0}; //default RGB(W) color
|
||||
byte colSecS[]{0, 0, 0, 0}; //default RGB(W) secondary color
|
||||
byte briS = 127; //default brightness
|
||||
byte effectDefault = 0;
|
||||
byte effectSpeedDefault = 75;
|
||||
byte effectIntensityDefault = 128; //intensity is supported on some effects as an additional parameter (e.g. for blink you can change the duty cycle)
|
||||
byte effectPaletteDefault = 0; //palette is supported on the FastLED effects, otherwise it has no effect
|
||||
|
||||
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 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 strip.reverseMode = false; //flip entire LED strip (reverses all effect directions) --> edit in WS2812FX.h
|
||||
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
|
||||
byte currentTheme = 7; //UI theme index for settings and classic UI
|
||||
byte uiConfiguration = 2; //0: automatic (depends on user-agent) 1: classic UI 2: mobile UI
|
||||
bool useHSB = true; //classic UI: use HSB sliders instead of RGB by default
|
||||
char cssFont[33] = "Verdana"; //font to use in classic UI
|
||||
|
||||
bool useHSBDefault = useHSB;
|
||||
|
||||
|
||||
//Sync CONFIG
|
||||
bool buttonEnabled = true;
|
||||
bool irEnabled = false; //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
|
||||
|
||||
bool e131Enabled = true; //settings for E1.31 (sACN) protocol
|
||||
uint16_t e131Universe = 1;
|
||||
bool e131Multicast = 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 = 19, 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 col[]{255, 159, 0, 0}; //target RGB(W) 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 colSec[]{0, 0, 0, 0};
|
||||
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
|
||||
|
||||
//nightlight
|
||||
bool nightlightActive = false;
|
||||
bool nightlightActiveOld = false;
|
||||
uint32_t nightlightDelayMs = 10;
|
||||
uint8_t nightlightDelayMinsDefault = nightlightDelayMins;
|
||||
unsigned long nightlightStartTime;
|
||||
byte briNlT = 0; //current nightlight brightness
|
||||
|
||||
//brightness
|
||||
unsigned long lastOnTime = 0;
|
||||
bool offMode = !turnOnAtBoot;
|
||||
byte bri = briS;
|
||||
byte briOld = 0;
|
||||
byte briT = 0;
|
||||
byte briIT = 0;
|
||||
byte briLast = 127; //brightness before turned off. Used for toggle function
|
||||
|
||||
//button
|
||||
bool buttonPressedBefore = false;
|
||||
bool buttonLongPressed = false;
|
||||
unsigned long buttonPressedTime = 0;
|
||||
unsigned long buttonWaitTime = 0;
|
||||
|
||||
//notifications
|
||||
bool notifyDirectDefault = notifyDirect;
|
||||
bool receiveNotifications = true;
|
||||
unsigned long notificationSentTime = 0;
|
||||
byte notificationSentCallMode = 0;
|
||||
bool notificationTwoRequired = false;
|
||||
|
||||
//effects
|
||||
byte effectCurrent = effectDefault;
|
||||
byte effectSpeed = effectSpeedDefault;
|
||||
byte effectIntensity = effectIntensityDefault;
|
||||
byte effectPalette = effectPaletteDefault;
|
||||
|
||||
//network
|
||||
bool udpConnected = false, udpRgbConnected = false;
|
||||
|
||||
//ui style
|
||||
char cssCol[6][9]={"","","","","",""};
|
||||
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;
|
||||
int overlayArr[6];
|
||||
uint16_t overlayDur[6];
|
||||
uint16_t overlayPauseDur[6];
|
||||
int nixieClockI = -1;
|
||||
bool nixiePause = false;
|
||||
|
||||
//cronixie
|
||||
byte dP[]{0,0,0,0,0,0};
|
||||
bool cronixieInit = false;
|
||||
|
||||
//countdown
|
||||
unsigned long countdownTime = 1514764800L;
|
||||
bool countdownOverTriggered = true;
|
||||
|
||||
//timer
|
||||
byte lastTimerMinute = 0;
|
||||
byte timerHours[] = {0,0,0,0,0,0,0,0};
|
||||
byte timerMinutes[] = {0,0,0,0,0,0,0,0};
|
||||
byte timerMacro[] = {0,0,0,0,0,0,0,0};
|
||||
byte timerWeekday[] = {255,255,255,255,255,255,255,255}; //weekdays to activate on
|
||||
//bit pattern of arr elem: 0b11111111: sun,sat,fri,thu,wed,tue,mon,validity
|
||||
|
||||
//blynk
|
||||
bool blynkEnabled = false;
|
||||
|
||||
//preset cycling
|
||||
bool presetCyclingEnabled = false;
|
||||
byte presetCycleMin = 1, presetCycleMax = 5;
|
||||
uint16_t presetCycleTime = 1250;
|
||||
unsigned long presetCycledTime = 0; byte presetCycCurr = presetCycleMin;
|
||||
bool presetApplyBri = false, presetApplyCol = true, presetApplyFx = true;
|
||||
bool saveCurrPresetCycConf = false;
|
||||
|
||||
//realtime
|
||||
bool realtimeActive = false;
|
||||
IPAddress realtimeIP = (0,0,0,0);
|
||||
unsigned long realtimeTimeout = 0;
|
||||
|
||||
//mqtt
|
||||
long lastMqttReconnectAttempt = 0;
|
||||
long lastInterfaceUpdate = 0;
|
||||
byte interfaceUpdateCallMode = 0;
|
||||
|
||||
#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;
|
||||
unsigned int 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;
|
||||
|
||||
String messageHead, messageSub;
|
||||
byte optionType;
|
||||
|
||||
bool doReboot = false; //flag to initiate reboot from async handlers
|
||||
bool doPublishMqtt = false;
|
||||
bool doSendHADiscovery = true;
|
||||
|
||||
//server library objects
|
||||
AsyncWebServer server(80);
|
||||
AsyncClient* hueClient = NULL;
|
||||
AsyncMqttClient* mqtt = NULL;
|
||||
|
||||
//udp interface objects
|
||||
WiFiUDP notifierUdp, rgbUdp;
|
||||
WiFiUDP ntpUdp;
|
||||
E131* e131;
|
||||
|
||||
//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
|
||||
|
||||
|
||||
//function prototypes
|
||||
void serveMessage(AsyncWebServerRequest*,uint16_t,String,String,byte);
|
||||
|
||||
|
||||
//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(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() {
|
||||
handleConnection();
|
||||
handleSerial();
|
||||
handleNotifications();
|
||||
handleTransitions();
|
||||
userLoop();
|
||||
|
||||
yield();
|
||||
handleIO();
|
||||
handleIR();
|
||||
handleNetworkTime();
|
||||
handleAlexa();
|
||||
|
||||
handleOverlays();
|
||||
if (doSendHADiscovery) sendHADiscoveryMQTT();
|
||||
yield();
|
||||
if (doReboot) reset();
|
||||
|
||||
if (!realtimeActive) //block stuff if WARLS/Adalight is enabled
|
||||
{
|
||||
if (apActive) dnsServer.processNextRequest();
|
||||
#ifndef WLED_DISABLE_OTA
|
||||
if (WLED_CONNECTED && aOtaEnabled) ArduinoOTA.handle();
|
||||
#endif
|
||||
handleNightlight();
|
||||
yield();
|
||||
|
||||
handleHue();
|
||||
handleBlynk();
|
||||
|
||||
yield();
|
||||
if (!offMode) strip.service();
|
||||
}
|
||||
yield();
|
||||
if (millis() - lastMqttReconnectAttempt > 30000) initMqtt();
|
||||
|
||||
//DEBUG serial logging
|
||||
#ifdef WLED_DEBUG
|
||||
if (millis() - debugTime > 9999)
|
||||
{
|
||||
DEBUG_PRINTLN("---DEBUG INFO---");
|
||||
DEBUG_PRINT("Runtime: "); DEBUG_PRINTLN(millis());
|
||||
DEBUG_PRINT("Unix time: "); DEBUG_PRINTLN(now());
|
||||
DEBUG_PRINT("Free heap: "); DEBUG_PRINTLN(ESP.getFreeHeap());
|
||||
DEBUG_PRINT("Wifi state: "); DEBUG_PRINTLN(WiFi.status());
|
||||
if (WiFi.status() != lastWifiState)
|
||||
{
|
||||
wifiStateChangedTime = millis();
|
||||
}
|
||||
lastWifiState = WiFi.status();
|
||||
DEBUG_PRINT("State time: "); DEBUG_PRINTLN(wifiStateChangedTime);
|
||||
DEBUG_PRINT("NTP last sync: "); DEBUG_PRINTLN(ntpLastSyncTime);
|
||||
DEBUG_PRINT("Client IP: "); DEBUG_PRINTLN(WiFi.localIP());
|
||||
DEBUG_PRINT("Loops/sec: "); DEBUG_PRINTLN(loops/10);
|
||||
loops = 0;
|
||||
debugTime = millis();
|
||||
}
|
||||
loops++;
|
||||
#endif
|
||||
WLED::instance().loop();
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user