diff --git a/tools/cdata.js b/tools/cdata.js index 71fafdcb..5c9e74df 100644 --- a/tools/cdata.js +++ b/tools/cdata.js @@ -365,6 +365,12 @@ writeChunks( /function GetV().*\<\/script\>/gms, "" ) + }, + { + file: "settings_pin.htm", + name: "PAGE_settings_pin", + method: "gzip", + filter: "html-minify" } ], "wled00/html_settings.h" diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 8ca08d81..c2dbe91f 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -864,6 +864,9 @@ bool deserializeConfigSec() { getStringFromJson(hueApiKey, interfaces["hue"][F("key")], 47); #endif + getStringFromJson(settingsPIN, doc["pin"], 5); + correctPIN = !strlen(settingsPIN); + JsonObject ota = doc["ota"]; getStringFromJson(otaPass, ota[F("pwd")], 33); CJSON(otaLock, ota[F("lock")]); @@ -903,6 +906,8 @@ void serializeConfigSec() { if_hue[F("key")] = hueApiKey; #endif + doc["pin"] = settingsPIN; + JsonObject ota = doc.createNestedObject("ota"); ota[F("pwd")] = otaPass; ota[F("lock")] = otaLock; diff --git a/wled00/data/msg.htm b/wled00/data/msg.htm index e25aeda0..bb598338 100644 --- a/wled00/data/msg.htm +++ b/wled00/data/msg.htm @@ -4,27 +4,13 @@ WLED Message - + diff --git a/wled00/data/settings_pin.htm b/wled00/data/settings_pin.htm new file mode 100644 index 00000000..7faf2467 --- /dev/null +++ b/wled00/data/settings_pin.htm @@ -0,0 +1,31 @@ + + + + + + + Misc Settings + + + + +
+
+
+
+
+

Please enter settings PIN code

+
+
+ +
+ + \ No newline at end of file diff --git a/wled00/data/settings_sec.htm b/wled00/data/settings_sec.htm index 2c07389f..42fa8910 100644 --- a/wled00/data/settings_sec.htm +++ b/wled00/data/settings_sec.htm @@ -60,9 +60,10 @@
-
+

Security & Update setup

+ Settings PIN:
Lock wireless (OTA) software update:
Passphrase:
To enable OTA, for security reasons you need to also enter the correct password!
@@ -76,7 +77,8 @@

Software Update


- Enable ArduinoOTA:
+ Enable ArduinoOTA: +

Backup & Restore

Backup presets
Restore presets


@@ -85,6 +87,7 @@
⚠ Restoring presets/configuration will OVERWRITE your current presets/configuration.
Incorrect configuration may require a factory reset or re-flashing of your ESP.
For security reasons, passwords are not backed up. +

About

WLED version ##VERSION##

Contributors, dependencies and special thanks
@@ -93,7 +96,7 @@ Licensed under the MIT license

Server message: Response error!
- +
diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 26ba161c..f3004bf0 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -320,6 +320,7 @@ void updateBaudRate(uint32_t rate); //wled_server.cpp bool isIp(String str); +void createEditHandler(bool enable); bool captivePortal(AsyncWebServerRequest *request); void initServer(); void serveIndexOrWelcome(AsyncWebServerRequest *request); diff --git a/wled00/html_other.h b/wled00/html_other.h index acc1458d..406335d5 100644 --- a/wled00/html_other.h +++ b/wled00/html_other.h @@ -21,9 +21,7 @@ const uint8_t PAGE_usermod[] PROGMEM = { const char PAGE_msg[] PROGMEM = R"=====( WLED Message

%MSG%)====="; +

%MSG%)====="; #ifdef WLED_ENABLE_DMX diff --git a/wled00/html_settings.h b/wled00/html_settings.h index 59189ca9..b785d2b4 100644 --- a/wled00/html_settings.h +++ b/wled00/html_settings.h @@ -1275,121 +1275,123 @@ const uint8_t PAGE_settings_time[] PROGMEM = { // Autogenerated from wled00/data/settings_sec.htm, do not edit!! -const uint16_t PAGE_settings_sec_length = 1802; +const uint16_t PAGE_settings_sec_length = 1830; const uint8_t PAGE_settings_sec[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x95, 0x57, 0x6d, 0x6f, 0xdb, 0x38, - 0x12, 0xfe, 0xae, 0x5f, 0xc1, 0xb0, 0x40, 0xd7, 0x06, 0x6c, 0x29, 0x71, 0xef, 0xf6, 0xba, 0x89, - 0xa5, 0x5e, 0xd2, 0x38, 0x9b, 0x00, 0xc9, 0x26, 0x88, 0xdd, 0xed, 0x1d, 0x0e, 0x87, 0x82, 0x96, - 0x46, 0x16, 0xd7, 0x32, 0xa9, 0x25, 0x29, 0xbb, 0x46, 0xd1, 0xff, 0x7e, 0x33, 0x94, 0xe4, 0xd8, - 0x69, 0x17, 0xb9, 0x7e, 0xc8, 0x8b, 0x28, 0xce, 0xdb, 0x33, 0x33, 0xcf, 0x8c, 0xc6, 0x47, 0x97, - 0xf7, 0xef, 0x67, 0xff, 0x7e, 0x98, 0xb0, 0xc2, 0xad, 0xca, 0x64, 0x4c, 0xbf, 0x59, 0x29, 0xd4, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x95, 0x57, 0x6d, 0x6f, 0xdb, 0x46, + 0x12, 0xfe, 0xce, 0x5f, 0xb1, 0xde, 0x00, 0xa9, 0x04, 0x48, 0xa4, 0xad, 0xb4, 0xbd, 0xd4, 0x16, + 0x99, 0xda, 0xb1, 0x5c, 0x1b, 0xb0, 0x63, 0xc3, 0x52, 0x9a, 0x3b, 0x1c, 0x8a, 0x60, 0x45, 0x0e, + 0xc5, 0xad, 0xa8, 0x5d, 0x76, 0x77, 0x69, 0x45, 0x0d, 0xf2, 0xdf, 0x6f, 0x66, 0x49, 0xca, 0x92, + 0x93, 0x9e, 0x91, 0x0f, 0x71, 0xc4, 0xe5, 0xce, 0xdb, 0x33, 0x33, 0xcf, 0x0c, 0xc7, 0x07, 0xe7, + 0xb7, 0x6f, 0x67, 0xff, 0xb9, 0x9b, 0xb0, 0xc2, 0xad, 0xca, 0x64, 0x4c, 0x7f, 0x59, 0x29, 0xd4, 0x22, 0xe6, 0xa0, 0x38, 0x3e, 0x83, 0xc8, 0x92, 0xf1, 0x0a, 0x9c, 0x60, 0x4a, 0xac, 0x20, 0xe6, - 0x6b, 0x09, 0x9b, 0x4a, 0x1b, 0xc7, 0x59, 0xaa, 0x95, 0x03, 0xe5, 0x62, 0xbe, 0x91, 0x99, 0x2b, - 0xe2, 0xbf, 0x1f, 0x1f, 0xf3, 0x24, 0x68, 0xae, 0x06, 0xcf, 0xde, 0x65, 0xb0, 0x96, 0x29, 0x0c, - 0xfd, 0xc3, 0x40, 0x2a, 0xe9, 0xa4, 0x28, 0x87, 0x36, 0x15, 0x25, 0xc4, 0x27, 0x83, 0x95, 0xf8, - 0x2c, 0x57, 0xf5, 0x6a, 0xf7, 0x5c, 0x5b, 0x30, 0xfe, 0x41, 0xcc, 0xf1, 0x59, 0x69, 0xce, 0x82, - 0x67, 0xa6, 0x5b, 0x87, 0xd2, 0x42, 0x18, 0x0b, 0x68, 0xa4, 0x76, 0xf9, 0xf0, 0x2d, 0x9e, 0x3a, - 0xe9, 0x4a, 0x48, 0xee, 0xa4, 0x4d, 0xd9, 0x14, 0x9c, 0x93, 0x6a, 0x61, 0xc7, 0x51, 0x73, 0x38, - 0xb6, 0xa9, 0x91, 0x95, 0x4b, 0x82, 0xb5, 0x30, 0xcc, 0xc9, 0x15, 0xe8, 0xda, 0x0d, 0xb2, 0x38, - 0xd3, 0x69, 0xbd, 0x42, 0x47, 0xcf, 0xf2, 0x5a, 0xa5, 0x4e, 0x6a, 0xc5, 0xae, 0x7b, 0xfd, 0x2f, - 0x1b, 0xa9, 0x32, 0xbd, 0x09, 0x75, 0x05, 0xaa, 0xc7, 0x0b, 0xe7, 0x2a, 0x7b, 0x1a, 0x45, 0x4b, - 0xa5, 0xc3, 0x4d, 0x09, 0x59, 0xb8, 0x80, 0x28, 0x07, 0xe1, 0x6a, 0x03, 0x36, 0xb2, 0xad, 0x99, - 0xe8, 0x95, 0x85, 0xb4, 0x36, 0xd2, 0x6d, 0x87, 0xdd, 0x11, 0xef, 0x7f, 0xdd, 0x29, 0xbd, 0x78, - 0xae, 0x74, 0x27, 0xc8, 0x07, 0xfc, 0x93, 0x85, 0x32, 0xdf, 0xbf, 0xfd, 0xe1, 0x9b, 0xdb, 0x75, - 0x95, 0x09, 0x07, 0xdf, 0xbb, 0xbb, 0xb8, 0xc9, 0x7a, 0xae, 0xff, 0xc5, 0x00, 0xfa, 0xa3, 0x18, - 0x39, 0xe7, 0x26, 0x25, 0x50, 0x48, 0x17, 0x5b, 0xff, 0xea, 0xe9, 0xaa, 0xb4, 0xf7, 0xf3, 0x3f, - 0x20, 0x75, 0x7b, 0xf7, 0xdd, 0xeb, 0xd7, 0x5c, 0xfb, 0x43, 0x1e, 0xc7, 0x6e, 0x5b, 0x81, 0xce, - 0xe9, 0xec, 0xe8, 0xdc, 0x18, 0xb1, 0x0d, 0xa5, 0xf5, 0x7f, 0x0f, 0x94, 0xd8, 0x42, 0x6f, 0x66, - 0x5a, 0x58, 0xd4, 0x32, 0x80, 0xf8, 0xe8, 0xa4, 0xff, 0x85, 0x00, 0x55, 0x31, 0xf9, 0xc1, 0x1d, - 0xbd, 0xe0, 0xfd, 0x33, 0x15, 0x4a, 0xa5, 0xc0, 0x5c, 0xcf, 0xee, 0x6e, 0x63, 0x37, 0x50, 0x61, - 0x5a, 0x0a, 0x6b, 0x6f, 0xa5, 0x75, 0xa1, 0xc8, 0xb2, 0x1e, 0xbc, 0xe3, 0x60, 0x8c, 0x36, 0xfc, - 0x94, 0x93, 0x36, 0xde, 0x1f, 0xa4, 0x25, 0x08, 0x33, 0x6b, 0x92, 0xd2, 0x6b, 0x93, 0xd3, 0x47, - 0x39, 0xeb, 0xb6, 0x25, 0x84, 0x42, 0xc9, 0x95, 0x20, 0xe3, 0x31, 0x57, 0x5a, 0x21, 0x0a, 0xed, - 0x8d, 0x18, 0x31, 0xec, 0x84, 0x7a, 0x9d, 0x83, 0x08, 0xdd, 0xbe, 0x3d, 0x03, 0x2b, 0xbd, 0x86, - 0x5e, 0x6b, 0xe8, 0x6b, 0x7f, 0x30, 0xfa, 0xe5, 0xf8, 0x78, 0x2f, 0x9c, 0xba, 0x2a, 0xb5, 0xc8, - 0xae, 0x64, 0x09, 0x14, 0x4f, 0x17, 0x8c, 0x82, 0x0d, 0xfb, 0xd7, 0xdd, 0xed, 0x35, 0x66, 0xfe, - 0x11, 0xfe, 0xac, 0xc1, 0x3a, 0x0c, 0x09, 0x5d, 0x9f, 0xac, 0x11, 0x57, 0xd2, 0x0b, 0x18, 0x5d, - 0x8f, 0x93, 0x28, 0x1f, 0xec, 0x9b, 0xde, 0x43, 0xa7, 0x90, 0x16, 0xad, 0xdb, 0x4a, 0x2b, 0x0b, - 0x33, 0xf8, 0xec, 0x06, 0xfe, 0xc4, 0x3a, 0x2c, 0x1c, 0x9b, 0xc4, 0x7f, 0x23, 0x2f, 0xfa, 0x14, - 0xe3, 0xb7, 0x6a, 0x1b, 0x70, 0xf6, 0xf4, 0xba, 0x03, 0xc5, 0xa4, 0x23, 0x5d, 0x0e, 0x8e, 0x3a, - 0x05, 0x4d, 0x89, 0x3c, 0xdc, 0x4f, 0x67, 0x58, 0x1f, 0x51, 0x13, 0x10, 0xe6, 0x80, 0x22, 0xd1, - 0x3e, 0x92, 0x2b, 0x6d, 0x56, 0x97, 0xc2, 0x89, 0xb3, 0x36, 0xe9, 0x3a, 0x14, 0x15, 0xca, 0x60, - 0xbe, 0xb0, 0xa8, 0x04, 0xc2, 0x19, 0xe6, 0x18, 0xbf, 0xfd, 0xcf, 0xf1, 0x7f, 0x11, 0x01, 0x42, - 0x9d, 0xde, 0xe9, 0x3e, 0x9e, 0xaf, 0x45, 0x59, 0x63, 0xdf, 0xf1, 0xc1, 0xd1, 0xc9, 0xd7, 0x60, - 0x1c, 0xb5, 0x2d, 0xd4, 0xb6, 0x12, 0xb3, 0x26, 0x8d, 0x79, 0x57, 0xc7, 0xe1, 0x1f, 0xf6, 0x5d, - 0x15, 0xff, 0x8c, 0x4d, 0xf8, 0x74, 0x8d, 0xb2, 0x97, 0xfc, 0x53, 0xae, 0xa8, 0x67, 0x59, 0x6d, - 0x4a, 0x4c, 0x83, 0x4f, 0x68, 0x6a, 0xb1, 0x39, 0xce, 0x48, 0xa1, 0xbf, 0x31, 0x8e, 0x1a, 0x92, - 0x99, 0xeb, 0x6c, 0xcb, 0xb4, 0x22, 0xff, 0x63, 0xfe, 0x2b, 0xb8, 0xdf, 0x7b, 0x7d, 0x54, 0x97, - 0xa3, 0xf7, 0x4c, 0xe2, 0x09, 0xfd, 0xf3, 0xc9, 0xf2, 0x96, 0x86, 0xa6, 0x39, 0x67, 0x48, 0x02, - 0x85, 0xc6, 0x37, 0x95, 0xc6, 0xaa, 0x43, 0xea, 0xc9, 0xe4, 0x9a, 0xf9, 0xd4, 0xc7, 0x58, 0x89, - 0x95, 0xc1, 0x8c, 0x27, 0xfb, 0x67, 0x05, 0x94, 0xd5, 0x05, 0x1e, 0xcd, 0x6b, 0xe7, 0x30, 0xf5, - 0x54, 0xee, 0x31, 0x6f, 0x1e, 0x38, 0xda, 0x4d, 0x4b, 0x99, 0x2e, 0x63, 0x7e, 0x4d, 0x56, 0xdf, - 0xa1, 0x73, 0xcd, 0x1b, 0xf4, 0x0e, 0x55, 0xbc, 0x24, 0x74, 0x41, 0x42, 0x17, 0x98, 0x96, 0x27, - 0xb1, 0x56, 0x20, 0x68, 0x24, 0x6c, 0x3d, 0x5f, 0x49, 0x74, 0x72, 0x2a, 0xd6, 0xc0, 0x5e, 0xb3, - 0x47, 0x98, 0x6b, 0xed, 0x9e, 0x2e, 0x17, 0xa6, 0xb3, 0x53, 0x8c, 0x92, 0x69, 0xcb, 0x24, 0x78, - 0xef, 0x83, 0xef, 0x7b, 0x86, 0x20, 0xd7, 0x15, 0xc2, 0x34, 0x4a, 0x82, 0x5b, 0x9d, 0x2e, 0xd9, - 0x46, 0x1a, 0xc0, 0x8c, 0x59, 0xd6, 0xbb, 0x9f, 0x9d, 0xf7, 0x99, 0xd5, 0xb9, 0xdb, 0x08, 0x03, - 0xac, 0xa1, 0x89, 0x53, 0x36, 0x96, 0xaa, 0xaa, 0x5d, 0xeb, 0x6c, 0x5a, 0x40, 0xba, 0x9c, 0xeb, - 0xcf, 0x1d, 0x72, 0xbf, 0xdd, 0x13, 0x06, 0x26, 0x09, 0x1e, 0x10, 0x95, 0xaa, 0x30, 0xc2, 0x3e, - 0x97, 0xa8, 0xf0, 0xc5, 0x46, 0x9b, 0xac, 0x93, 0xb8, 0x7f, 0x40, 0xac, 0xc5, 0xe7, 0x12, 0xd4, - 0x02, 0xb9, 0x9c, 0xbf, 0x19, 0xb5, 0x0a, 0x66, 0x9a, 0x81, 0x22, 0x92, 0x66, 0xe8, 0xc6, 0x80, - 0x61, 0x82, 0x58, 0xc7, 0x82, 0xcc, 0x80, 0xb0, 0x58, 0xfa, 0x6c, 0xab, 0x6b, 0xa6, 0x00, 0x32, - 0xe6, 0x34, 0x13, 0xa5, 0x25, 0x09, 0x07, 0xc8, 0xc0, 0x05, 0xe0, 0xfc, 0x30, 0x06, 0x99, 0x87, - 0x75, 0xe6, 0x8e, 0x02, 0xd2, 0x3a, 0xc3, 0x37, 0xdd, 0x09, 0xb1, 0x4d, 0x5d, 0x66, 0x6c, 0x0e, - 0xc4, 0xf5, 0x6a, 0x81, 0x6a, 0x36, 0x05, 0x28, 0x32, 0x87, 0x6c, 0xd6, 0x1a, 0xcf, 0x42, 0x12, - 0x1b, 0xcf, 0x93, 0xe0, 0x52, 0xda, 0xce, 0x9b, 0xe6, 0x9e, 0xd2, 0x8e, 0x49, 0x6c, 0x72, 0x0b, - 0x03, 0xa6, 0xd1, 0xa4, 0xd9, 0x48, 0x0b, 0x4c, 0x28, 0x26, 0x1c, 0xf5, 0x10, 0xfa, 0x91, 0xe2, - 0x83, 0x81, 0x1c, 0x0b, 0xa4, 0x60, 0xcd, 0x90, 0xda, 0xa1, 0x79, 0x44, 0x35, 0xe0, 0x03, 0x1d, - 0xcb, 0xa4, 0x1b, 0x27, 0x8c, 0x6a, 0x00, 0x1b, 0x19, 0x5d, 0x5c, 0xa0, 0x26, 0xc4, 0x1c, 0x0b, - 0x76, 0xdb, 0x78, 0xe7, 0x6d, 0xcb, 0xdc, 0x9b, 0x2f, 0x29, 0x4d, 0x78, 0x2d, 0x6b, 0x5c, 0xca, - 0x8e, 0xc6, 0x91, 0x4c, 0x7c, 0x7c, 0x97, 0xa0, 0xb6, 0x4c, 0xa4, 0x29, 0xa5, 0x0f, 0x31, 0xf9, - 0x28, 0xaf, 0x24, 0xeb, 0x9a, 0x88, 0xa4, 0x49, 0x12, 0xb2, 0x17, 0x72, 0x78, 0xff, 0x91, 0x37, - 0xda, 0xe8, 0xe7, 0x4a, 0xa4, 0x4e, 0x1b, 0x82, 0x1c, 0xf5, 0xbc, 0x20, 0xf8, 0x38, 0x6d, 0x73, - 0x77, 0x5e, 0x96, 0x4f, 0x66, 0x85, 0xca, 0x58, 0xe5, 0xc5, 0x2d, 0xd6, 0x16, 0xbe, 0x41, 0xc0, - 0x81, 0x0a, 0xa3, 0xc3, 0x16, 0x05, 0xae, 0x67, 0xb3, 0x07, 0xe6, 0x8c, 0xc8, 0x73, 0x99, 0x52, - 0x64, 0xb5, 0x02, 0x95, 0x9a, 0x6d, 0xe5, 0xf0, 0x12, 0x3b, 0xdf, 0x83, 0x54, 0x2a, 0x9f, 0x5d, - 0x8b, 0xf6, 0x30, 0xf3, 0x0e, 0xf3, 0xb8, 0xf4, 0x30, 0x4b, 0x4a, 0x7c, 0x0a, 0x48, 0x1c, 0xbe, - 0xa5, 0x89, 0x7b, 0x10, 0x62, 0xaa, 0xfc, 0xe2, 0x4d, 0x32, 0xed, 0x4a, 0xb8, 0xa9, 0x78, 0xac, - 0xf5, 0x37, 0x2f, 0xf5, 0xdc, 0x07, 0xea, 0xb9, 0xe0, 0x4e, 0xa8, 0x5a, 0x94, 0x1e, 0xf3, 0x4e, - 0x74, 0xd7, 0x81, 0x26, 0x99, 0x34, 0xe5, 0x79, 0x6e, 0xb2, 0x5a, 0x2a, 0x8d, 0x97, 0xfe, 0x12, - 0x9e, 0x76, 0xc5, 0x38, 0x6f, 0x9b, 0x83, 0x7c, 0xa2, 0x7e, 0xae, 0x2b, 0xdf, 0xad, 0x16, 0x01, - 0x6e, 0x9d, 0x12, 0x1d, 0x9d, 0xcc, 0x9d, 0x62, 0xa5, 0x5a, 0xa2, 0x68, 0x81, 0x15, 0x14, 0xf3, - 0xa8, 0x45, 0x10, 0x99, 0x50, 0xab, 0x77, 0x38, 0xbc, 0x3d, 0x93, 0x71, 0xe6, 0x84, 0x59, 0xd0, - 0x92, 0xd2, 0x9d, 0x0c, 0x73, 0x83, 0xa6, 0x78, 0xa7, 0xbe, 0x95, 0x1a, 0x47, 0xa2, 0xc1, 0x99, - 0x18, 0x2b, 0x69, 0x2d, 0xee, 0x5e, 0xfa, 0x22, 0xdc, 0xf3, 0x9b, 0x08, 0xbb, 0x4b, 0xa9, 0x27, - 0x71, 0x5f, 0x51, 0x15, 0x5a, 0xf1, 0xd6, 0x79, 0xd2, 0x85, 0x19, 0x1c, 0x82, 0xd7, 0x12, 0xfa, - 0x87, 0x66, 0x48, 0xec, 0xb0, 0xfc, 0x69, 0x6f, 0x0c, 0x66, 0xe1, 0x34, 0x0f, 0x49, 0xe7, 0xe0, - 0x30, 0x22, 0xde, 0xff, 0xa9, 0x2d, 0xb9, 0x96, 0x10, 0xcd, 0xf7, 0xb0, 0x68, 0xa1, 0x48, 0xf3, - 0xc5, 0x73, 0x18, 0x82, 0x17, 0x70, 0xc0, 0x8d, 0x31, 0x97, 0x8b, 0xda, 0xf8, 0x49, 0xdf, 0xa1, - 0x71, 0x00, 0xc6, 0xc1, 0x8d, 0xe0, 0x45, 0x4c, 0x46, 0x7f, 0x09, 0xca, 0x21, 0x26, 0xc1, 0x8f, - 0x80, 0x32, 0x1a, 0x3c, 0x05, 0x47, 0x88, 0xec, 0x01, 0x42, 0x93, 0x26, 0xf0, 0x13, 0x0d, 0xeb, - 0x4a, 0x97, 0xda, 0x9c, 0xbe, 0xca, 0x05, 0xad, 0xc4, 0xaf, 0x5f, 0xfd, 0xf2, 0xf6, 0xed, 0xdb, - 0xb3, 0xb6, 0x8c, 0xb0, 0xe1, 0xba, 0xb4, 0x46, 0x07, 0x11, 0x35, 0x9d, 0x77, 0xff, 0xfb, 0xe4, - 0xf1, 0xe3, 0xe3, 0xcd, 0x6c, 0x42, 0xcc, 0x89, 0xfc, 0x54, 0x23, 0x47, 0x2a, 0xf7, 0x7d, 0x89, - 0xd0, 0x83, 0x10, 0xdc, 0xa8, 0x8e, 0x49, 0x0f, 0xf5, 0xad, 0x04, 0x71, 0xc2, 0x9f, 0x35, 0x0e, - 0x0b, 0x26, 0x58, 0xbe, 0xcf, 0x12, 0x0c, 0xa9, 0xda, 0xc0, 0xd0, 0xf3, 0x1e, 0x39, 0x84, 0x6b, - 0x9f, 0x37, 0x37, 0x99, 0x3e, 0xa0, 0x52, 0x1f, 0xcf, 0xd5, 0x77, 0xd8, 0x7c, 0xb0, 0x63, 0x66, - 0xeb, 0xb9, 0x8f, 0xf8, 0x75, 0x4e, 0x5d, 0x9f, 0xe1, 0xe8, 0x09, 0xa9, 0x67, 0xce, 0xe7, 0xb8, - 0x8d, 0x75, 0x8d, 0xd2, 0x36, 0x46, 0xb7, 0x40, 0x2f, 0xa4, 0x2b, 0xea, 0x79, 0x98, 0xea, 0x55, - 0x74, 0x2e, 0x4d, 0xaa, 0xb5, 0x5e, 0x4a, 0x88, 0x3e, 0xde, 0x4e, 0x2e, 0xa3, 0xa7, 0x2e, 0xf9, - 0x34, 0xc7, 0x8f, 0x8f, 0x25, 0x4f, 0xe8, 0x98, 0xaa, 0x20, 0x60, 0x6b, 0x30, 0x96, 0xc2, 0x39, - 0x0e, 0x4f, 0xde, 0x84, 0x27, 0xc3, 0x79, 0xf9, 0x8f, 0x8e, 0x93, 0x7e, 0xc8, 0xc4, 0x46, 0x2e, - 0x65, 0xf4, 0x1e, 0x3f, 0x4b, 0x8c, 0xc4, 0xcc, 0x6b, 0x63, 0x87, 0xc8, 0x7a, 0xc3, 0xd4, 0x40, - 0x26, 0x9d, 0xdd, 0x2b, 0xcf, 0xce, 0x81, 0xfd, 0xab, 0x03, 0x9c, 0x0d, 0xb4, 0x31, 0x21, 0xe3, - 0x49, 0x68, 0xe8, 0xd2, 0x56, 0x90, 0xe2, 0x47, 0x0c, 0x52, 0x1d, 0xde, 0x7e, 0xea, 0xde, 0x73, - 0x56, 0xd4, 0x38, 0x18, 0xfc, 0xa9, 0x9f, 0x7d, 0x48, 0xf1, 0x80, 0x11, 0x6c, 0x71, 0x71, 0xc5, - 0x99, 0xa4, 0x19, 0x2d, 0x21, 0x08, 0x17, 0x72, 0x23, 0x9a, 0xa6, 0xd9, 0x4e, 0xce, 0x1d, 0xed, - 0x58, 0xb6, 0x97, 0xf6, 0xd9, 0xe8, 0xf8, 0xe4, 0xe7, 0xe1, 0xe8, 0x78, 0x34, 0x62, 0xef, 0x0b, - 0x83, 0x5b, 0xa1, 0x44, 0xf2, 0x9c, 0xa6, 0xc5, 0x86, 0x76, 0xea, 0x76, 0x1c, 0xdd, 0xe2, 0xa0, - 0xc2, 0xbd, 0x12, 0x61, 0x47, 0xa7, 0x9a, 0x69, 0xfa, 0x43, 0x60, 0xcc, 0x4b, 0x3d, 0x8f, 0x56, - 0xb8, 0x4e, 0x82, 0x89, 0x6e, 0x6f, 0xde, 0x4f, 0x7e, 0x9b, 0x4e, 0xbe, 0x4d, 0x41, 0x70, 0x77, - 0x33, 0x63, 0x65, 0x63, 0xc9, 0x07, 0x88, 0x23, 0xac, 0x73, 0x74, 0x0a, 0x06, 0xa3, 0xc2, 0x30, - 0xac, 0xc5, 0x41, 0x88, 0xac, 0x6a, 0x2b, 0xf4, 0xb2, 0x65, 0x03, 0x2b, 0x2b, 0x4e, 0x5d, 0xeb, - 0x77, 0x5f, 0xe6, 0xd7, 0x59, 0x1a, 0xa6, 0x74, 0xa5, 0x59, 0x75, 0xa8, 0x55, 0x68, 0xa5, 0x6b, - 0xbe, 0x17, 0x7e, 0x70, 0xc5, 0x0a, 0xbe, 0xd9, 0xb1, 0xfe, 0xaf, 0x15, 0x2b, 0xa2, 0xa9, 0x83, - 0xd8, 0x79, 0xd6, 0xe9, 0xe8, 0xfe, 0x19, 0x17, 0xb1, 0xb6, 0x7d, 0x71, 0x6a, 0x57, 0xa5, 0xd8, - 0x9e, 0xfa, 0xcf, 0x0d, 0x8a, 0xdb, 0xbf, 0xc6, 0x7f, 0x68, 0x45, 0xa5, 0x7d, 0x95, 0x3e, 0x95, - 0xff, 0x07, 0x8f, 0xc3, 0x5d, 0xed, 0x3a, 0x0f, 0x00, 0x00 + 0x0f, 0x12, 0xd6, 0x95, 0x36, 0x8e, 0xb3, 0x54, 0x2b, 0x07, 0xca, 0xc5, 0x7c, 0x2d, 0x33, 0x57, + 0xc4, 0x3f, 0x1d, 0x1e, 0xf2, 0x24, 0x68, 0xae, 0x06, 0x4f, 0xde, 0x65, 0xf0, 0x20, 0x53, 0x18, + 0xfa, 0x87, 0x81, 0x54, 0xd2, 0x49, 0x51, 0x0e, 0x6d, 0x2a, 0x4a, 0x88, 0x8f, 0x06, 0x2b, 0xf1, + 0x49, 0xae, 0xea, 0xd5, 0xf6, 0xb9, 0xb6, 0x60, 0xfc, 0x83, 0x98, 0xe3, 0xb3, 0xd2, 0x9c, 0x05, + 0x4f, 0x4c, 0xb7, 0x0e, 0xa5, 0x85, 0x30, 0x16, 0xd0, 0x48, 0xed, 0xf2, 0xe1, 0x6b, 0x3c, 0x75, + 0xd2, 0x95, 0x90, 0xdc, 0x48, 0x9b, 0xb2, 0x29, 0x38, 0x27, 0xd5, 0xc2, 0x8e, 0xa3, 0xe6, 0x70, + 0x6c, 0x53, 0x23, 0x2b, 0x97, 0x04, 0x0f, 0xc2, 0x30, 0x27, 0x57, 0xa0, 0x6b, 0x37, 0xc8, 0xe2, + 0x4c, 0xa7, 0xf5, 0x0a, 0x1d, 0x3d, 0xc9, 0x6b, 0x95, 0x3a, 0xa9, 0x15, 0xbb, 0xec, 0xf5, 0x3f, + 0xaf, 0xa5, 0xca, 0xf4, 0x3a, 0xd4, 0x15, 0xa8, 0x1e, 0x2f, 0x9c, 0xab, 0xec, 0x71, 0x14, 0x2d, + 0x95, 0x0e, 0xd7, 0x25, 0x64, 0xe1, 0x02, 0xa2, 0x1c, 0x84, 0xab, 0x0d, 0xd8, 0xc8, 0xb6, 0x66, + 0xa2, 0x17, 0x16, 0xd2, 0xda, 0x48, 0xb7, 0x19, 0x76, 0x47, 0xbc, 0xff, 0x65, 0xab, 0xf4, 0xec, + 0xa9, 0xd2, 0xad, 0x20, 0x1f, 0xf0, 0x8f, 0x16, 0xca, 0x7c, 0xf7, 0xf6, 0xfb, 0xaf, 0x6e, 0xd7, + 0x55, 0x26, 0x1c, 0x7c, 0xeb, 0xee, 0xe2, 0x2a, 0xeb, 0xb9, 0xfe, 0x67, 0x03, 0xe8, 0x8f, 0x62, + 0xe4, 0x9c, 0x9b, 0x94, 0x40, 0x21, 0x9d, 0x6d, 0xfc, 0xab, 0xc7, 0xab, 0xd2, 0xde, 0xce, 0xff, + 0x84, 0xd4, 0xed, 0xdc, 0x77, 0x2f, 0x5f, 0x72, 0xed, 0x0f, 0x79, 0x1c, 0xbb, 0x4d, 0x05, 0x3a, + 0xa7, 0xb3, 0x83, 0x53, 0x63, 0xc4, 0x26, 0x94, 0xd6, 0xff, 0xbf, 0xa7, 0xc4, 0x16, 0x7a, 0x3d, + 0xd3, 0xc2, 0xa2, 0x96, 0x01, 0xc4, 0x07, 0x47, 0xfd, 0xcf, 0x04, 0xa8, 0x8a, 0xc9, 0x0f, 0xee, + 0xe8, 0x05, 0xef, 0x9f, 0xa8, 0x50, 0x2a, 0x05, 0xe6, 0x72, 0x76, 0x73, 0x1d, 0xbb, 0x81, 0x0a, + 0xd3, 0x52, 0x58, 0x7b, 0x2d, 0xad, 0x0b, 0x45, 0x96, 0xf5, 0xe0, 0x0d, 0x07, 0x63, 0xb4, 0xe1, + 0xc7, 0x9c, 0xb4, 0xf1, 0xfe, 0x20, 0x2d, 0x41, 0x98, 0x59, 0x93, 0x94, 0x5e, 0x9b, 0x9c, 0x3e, + 0xca, 0x59, 0xb7, 0x29, 0x21, 0x14, 0x4a, 0xae, 0x04, 0x19, 0x8f, 0xb9, 0xd2, 0x0a, 0x51, 0x68, + 0x6f, 0xc4, 0x88, 0x61, 0x27, 0xd4, 0xeb, 0x1c, 0x44, 0xe8, 0x76, 0xed, 0x19, 0x58, 0xe9, 0x07, + 0xe8, 0xb5, 0x86, 0xbe, 0xf4, 0x07, 0xa3, 0x5f, 0x0e, 0x0f, 0x77, 0xc2, 0xa9, 0xab, 0x52, 0x8b, + 0xec, 0x42, 0x96, 0x40, 0xf1, 0x74, 0xc1, 0x28, 0x58, 0xb3, 0x7f, 0xdf, 0x5c, 0x5f, 0x62, 0xe6, + 0xef, 0xe1, 0xaf, 0x1a, 0xac, 0xc3, 0x90, 0xd0, 0xf5, 0xc9, 0x03, 0xe2, 0x4a, 0x7a, 0x01, 0xa3, + 0xeb, 0x71, 0x12, 0xe5, 0x83, 0x5d, 0xd3, 0x3b, 0xe8, 0x14, 0xd2, 0xa2, 0x75, 0x5b, 0x69, 0x65, + 0x61, 0x06, 0x9f, 0xdc, 0xc0, 0x9f, 0x58, 0x87, 0x85, 0x63, 0x93, 0xf8, 0x47, 0xf2, 0xa2, 0x4f, + 0x31, 0x7e, 0xad, 0xb6, 0x01, 0x67, 0x47, 0xaf, 0xdb, 0x53, 0x4c, 0x3a, 0xd2, 0xe5, 0xe0, 0xa0, + 0x53, 0xd0, 0x94, 0xc8, 0xdd, 0xed, 0x74, 0x86, 0xf5, 0x11, 0x35, 0x01, 0x61, 0x0e, 0x28, 0x12, + 0xed, 0x23, 0xb9, 0xd0, 0x66, 0x75, 0x2e, 0x9c, 0x38, 0x69, 0x93, 0xae, 0x43, 0x51, 0xa1, 0x0c, + 0xe6, 0x0b, 0x8b, 0x4a, 0x20, 0x9c, 0x61, 0x8e, 0xf1, 0xdb, 0xff, 0x1e, 0xfe, 0x81, 0x08, 0x10, + 0xea, 0xf4, 0x4e, 0xf7, 0xf1, 0xfc, 0x41, 0x94, 0x35, 0xf6, 0x1d, 0x1f, 0x1c, 0x1c, 0x7d, 0x09, + 0xc6, 0x51, 0xdb, 0x42, 0x6d, 0x2b, 0x31, 0x6b, 0xd2, 0x98, 0x77, 0x75, 0x1c, 0xfe, 0x69, 0xdf, + 0x54, 0xf1, 0xcf, 0xd8, 0x84, 0x8f, 0xd7, 0x28, 0x7b, 0xc9, 0xaf, 0x72, 0x45, 0x3d, 0xcb, 0x6a, + 0x53, 0x62, 0x1a, 0x7c, 0x42, 0x53, 0x8b, 0xcd, 0x71, 0x42, 0x0a, 0xfd, 0x8d, 0x71, 0xd4, 0x90, + 0xcc, 0x5c, 0x67, 0x1b, 0xa6, 0x15, 0xf9, 0x1f, 0xf3, 0xdf, 0xc0, 0xfd, 0xde, 0xeb, 0xa3, 0xba, + 0x1c, 0xbd, 0x67, 0x12, 0x4f, 0xe8, 0xc7, 0x47, 0xcb, 0x5b, 0x1a, 0x9a, 0xe6, 0x9c, 0x21, 0x09, + 0x14, 0x1a, 0xdf, 0x54, 0x1a, 0xab, 0x0e, 0xa9, 0x27, 0x93, 0x0f, 0xcc, 0xa7, 0x3e, 0xc6, 0x4a, + 0xac, 0x0c, 0x66, 0x3c, 0xd9, 0x3d, 0x2b, 0xa0, 0xac, 0xce, 0xf0, 0x68, 0x5e, 0x3b, 0x87, 0xa9, + 0xa7, 0x72, 0x8f, 0x79, 0xf3, 0xc0, 0xd1, 0x6e, 0x5a, 0xca, 0x74, 0x19, 0xf3, 0x4b, 0xb2, 0xfa, + 0x06, 0x9d, 0x6b, 0xde, 0xa0, 0x77, 0xa8, 0xe2, 0x39, 0xa1, 0x33, 0x12, 0x3a, 0xc3, 0xb4, 0x3c, + 0x8a, 0xb5, 0x02, 0x41, 0x23, 0x61, 0xeb, 0xf9, 0x4a, 0xa2, 0x93, 0x53, 0xf1, 0x00, 0x8f, 0x77, + 0x0a, 0xd3, 0xa9, 0x2f, 0x46, 0xc9, 0xb4, 0x25, 0x10, 0xf6, 0x92, 0xbd, 0xf7, 0xed, 0xce, 0x10, + 0xdb, 0xba, 0x42, 0x74, 0x46, 0x49, 0xd0, 0xd1, 0x19, 0xbb, 0xbb, 0x7a, 0x77, 0xcc, 0xc6, 0x52, + 0x55, 0xb5, 0x6b, 0x9d, 0x51, 0xf5, 0x6a, 0x0e, 0xa6, 0xc3, 0x05, 0xdf, 0x73, 0x66, 0xe5, 0xdf, + 0xf8, 0xf3, 0x47, 0x44, 0x48, 0x7c, 0x2a, 0x41, 0x2d, 0x90, 0x81, 0xe9, 0x29, 0x58, 0x49, 0xf5, + 0xf8, 0x88, 0x2e, 0x9a, 0xe4, 0x5a, 0xa7, 0x4b, 0xb6, 0x96, 0x06, 0xb0, 0x00, 0x2c, 0xeb, 0xdd, + 0xce, 0x4e, 0xfb, 0xcc, 0xea, 0xdc, 0xad, 0x85, 0x01, 0xd6, 0xb0, 0xce, 0x13, 0x73, 0x69, 0x01, + 0xe9, 0x72, 0xae, 0x3f, 0x6d, 0x59, 0xf9, 0xdd, 0x6d, 0xa3, 0xea, 0x0e, 0x41, 0xae, 0x0a, 0x23, + 0xec, 0x53, 0x89, 0x0a, 0x5f, 0xac, 0xb5, 0xc9, 0x3a, 0x17, 0x6f, 0xef, 0xf6, 0x1c, 0x7b, 0x35, + 0x6a, 0xe4, 0x83, 0x99, 0x66, 0xa0, 0x88, 0xf3, 0x19, 0xba, 0x31, 0x60, 0x98, 0x6f, 0xd6, 0x91, + 0x2a, 0x33, 0x20, 0x2c, 0x76, 0x12, 0xdb, 0xe8, 0x9a, 0x29, 0x80, 0x8c, 0x39, 0xcd, 0x44, 0x69, + 0x49, 0xc2, 0x01, 0x12, 0x7a, 0x01, 0x38, 0x8e, 0x8c, 0x41, 0x22, 0x63, 0x9d, 0xb9, 0x83, 0x80, + 0xb4, 0xce, 0xf0, 0x4d, 0x77, 0x42, 0xe4, 0x55, 0x97, 0x19, 0x9b, 0x03, 0x8d, 0x0e, 0xb5, 0x40, + 0x35, 0xeb, 0x02, 0x14, 0x99, 0x43, 0x72, 0x6c, 0x8d, 0x67, 0x21, 0x89, 0x8d, 0xe7, 0x49, 0x70, + 0x2e, 0x6d, 0xe7, 0x4d, 0x73, 0x4f, 0x69, 0xc7, 0x24, 0x72, 0x86, 0x85, 0x01, 0xd3, 0x68, 0xd2, + 0xac, 0xa5, 0x05, 0x26, 0x14, 0x13, 0x8e, 0x5a, 0x12, 0xfd, 0x48, 0xf1, 0xc1, 0x40, 0x8e, 0xf5, + 0x56, 0xb0, 0x66, 0xe6, 0x6d, 0xd1, 0x3c, 0xa0, 0x92, 0xf2, 0x81, 0x8e, 0x65, 0xb2, 0x4d, 0x27, + 0x95, 0x14, 0xf2, 0x02, 0xba, 0xb8, 0x40, 0x4d, 0x88, 0x39, 0xd6, 0xff, 0xa6, 0xf1, 0xce, 0xdb, + 0x96, 0xb9, 0x37, 0x5f, 0x52, 0x9a, 0xf0, 0x5a, 0xd6, 0xb8, 0x94, 0x1d, 0x8c, 0x23, 0x99, 0xf8, + 0xf8, 0xce, 0x41, 0x6d, 0x98, 0x48, 0x53, 0x4a, 0x1f, 0x62, 0xf2, 0x41, 0x5e, 0x48, 0xd6, 0xf5, + 0x24, 0x49, 0x93, 0x24, 0x64, 0xff, 0x98, 0xc3, 0x36, 0x23, 0x1f, 0x78, 0xa3, 0x8d, 0xfe, 0x5d, + 0x88, 0xd4, 0x69, 0x43, 0x90, 0xa3, 0x9e, 0x67, 0x04, 0xef, 0xa7, 0x6d, 0xee, 0x4e, 0xcb, 0xf2, + 0xd1, 0xac, 0x50, 0x19, 0xab, 0xbc, 0xb8, 0xc5, 0xda, 0xc2, 0x37, 0x08, 0x38, 0x50, 0x61, 0x74, + 0xd8, 0xa2, 0xc0, 0xe5, 0x6c, 0x76, 0xc7, 0x9c, 0x11, 0x79, 0x2e, 0x53, 0x8a, 0xac, 0x56, 0xa0, + 0x52, 0xb3, 0xa9, 0x1c, 0x5e, 0x62, 0xa7, 0x3b, 0x90, 0x4a, 0xe5, 0xb3, 0x6b, 0xd1, 0x1e, 0x66, + 0xde, 0x61, 0x1e, 0x97, 0x1e, 0x66, 0x49, 0x89, 0x4f, 0x01, 0x79, 0xc8, 0x33, 0x04, 0x51, 0x19, + 0x42, 0x4c, 0x1d, 0x55, 0xbc, 0x4a, 0xa6, 0x5d, 0x09, 0x37, 0x9d, 0x84, 0x3d, 0xf4, 0xea, 0xb9, + 0x16, 0x7e, 0x4f, 0x2d, 0x1c, 0xdc, 0x08, 0x55, 0x8b, 0xd2, 0x63, 0xde, 0x89, 0x6e, 0x1b, 0xda, + 0x24, 0x93, 0xa6, 0x3c, 0x4f, 0x4d, 0x56, 0x4b, 0xa5, 0xf1, 0xd2, 0x73, 0xbd, 0x71, 0x4a, 0xbd, + 0xd1, 0xfa, 0x44, 0xf4, 0x50, 0x57, 0xd8, 0xdd, 0xf7, 0x38, 0x4f, 0xb4, 0x69, 0x9d, 0x12, 0x1d, + 0x3b, 0xcd, 0x9d, 0x62, 0xa5, 0x5a, 0xa2, 0x68, 0x81, 0x15, 0x14, 0xf3, 0xa8, 0x45, 0x10, 0x89, + 0x55, 0xab, 0x37, 0xb8, 0x0b, 0x78, 0x62, 0xe4, 0xcc, 0x09, 0xb3, 0xa0, 0x9d, 0xa7, 0x3b, 0x19, + 0xe6, 0x06, 0x4d, 0xf1, 0x4e, 0x7d, 0x2b, 0x35, 0x8e, 0x44, 0x83, 0x33, 0x11, 0x60, 0xd2, 0x5a, + 0xdc, 0xbe, 0xf4, 0x45, 0xb8, 0xe3, 0x37, 0xf1, 0x7f, 0x97, 0x52, 0x3f, 0x13, 0x7c, 0x45, 0x55, + 0x68, 0xc5, 0x5b, 0xe7, 0x49, 0x17, 0x66, 0xb0, 0x0f, 0x5e, 0x3b, 0x1f, 0xde, 0x37, 0x33, 0x67, + 0x8b, 0xe5, 0x0f, 0x3b, 0x53, 0x35, 0x0b, 0xa7, 0x79, 0x48, 0x3a, 0x07, 0xfb, 0x11, 0xf1, 0xfe, + 0x0f, 0x6d, 0xc9, 0xb5, 0xfc, 0x6a, 0xbe, 0x85, 0x45, 0x0b, 0x45, 0x9a, 0x2f, 0x9e, 0xc2, 0x10, + 0x3c, 0x83, 0x03, 0x2e, 0xa0, 0xb9, 0x5c, 0xd4, 0xc6, 0x2f, 0x0e, 0x1d, 0x1a, 0x7b, 0x60, 0xec, + 0xdd, 0x08, 0x9e, 0xc5, 0x64, 0xf4, 0x8f, 0xa0, 0xec, 0x63, 0x12, 0x7c, 0x0f, 0x28, 0xa3, 0xc1, + 0x63, 0x70, 0x84, 0xc8, 0x0e, 0x20, 0x34, 0xb8, 0x02, 0x3f, 0x20, 0xb1, 0xae, 0x74, 0xa9, 0xcd, + 0xf1, 0x8b, 0x5c, 0xd0, 0x86, 0xfd, 0xf2, 0xc5, 0x2f, 0xaf, 0x5f, 0xbf, 0x3e, 0x69, 0xcb, 0x08, + 0x1b, 0xae, 0x4b, 0x6b, 0xb4, 0x17, 0x51, 0xd3, 0x79, 0xb7, 0xbf, 0x4f, 0xee, 0x3f, 0xdc, 0x5f, + 0xcd, 0x26, 0xc4, 0x9c, 0xc8, 0x4f, 0x35, 0x72, 0xa4, 0x72, 0xdf, 0x96, 0x08, 0x3d, 0x08, 0xc1, + 0x95, 0xea, 0x98, 0x74, 0x5f, 0xdf, 0x4a, 0x10, 0x27, 0xfc, 0x55, 0xe3, 0xb0, 0x60, 0x82, 0xe5, + 0xbb, 0x2c, 0xc1, 0x90, 0xaa, 0x0d, 0x0c, 0x3d, 0xef, 0x91, 0x43, 0xb8, 0x45, 0x7a, 0x73, 0x93, + 0xe9, 0x1d, 0x2a, 0xf5, 0xf1, 0x5c, 0x7c, 0x83, 0xcd, 0x07, 0x5b, 0x66, 0xb6, 0x9e, 0xfb, 0x88, + 0x5f, 0xe7, 0xd4, 0xf5, 0x19, 0x8e, 0x9e, 0xb0, 0xeb, 0x9b, 0xd3, 0x39, 0x2e, 0x78, 0x5d, 0xb3, + 0xb4, 0xcd, 0xd1, 0xed, 0xe4, 0x0b, 0xe9, 0x8a, 0x7a, 0x1e, 0xa6, 0x7a, 0x15, 0x9d, 0x4a, 0x93, + 0x6a, 0xad, 0x97, 0x12, 0xa2, 0x0f, 0xd7, 0x93, 0xf3, 0xe8, 0xb1, 0x53, 0x3e, 0xce, 0xf1, 0x7b, + 0x66, 0xc9, 0x13, 0x3a, 0xa6, 0x4a, 0x08, 0xd8, 0x03, 0x18, 0x4b, 0x21, 0x1d, 0x86, 0x47, 0xaf, + 0xc2, 0xa3, 0xe1, 0xbc, 0xfc, 0x57, 0xc7, 0x4b, 0xdf, 0x65, 0x62, 0x2d, 0x97, 0x32, 0x7a, 0x8b, + 0x5f, 0x3a, 0x46, 0x62, 0xf6, 0xb5, 0xb1, 0x43, 0x64, 0xbe, 0x61, 0x6a, 0x20, 0x93, 0xce, 0xee, + 0x94, 0x68, 0xe7, 0xc0, 0xee, 0xd5, 0x01, 0xce, 0x07, 0x5a, 0xc2, 0x90, 0xf5, 0x24, 0x34, 0x94, + 0x69, 0x2b, 0x48, 0xf1, 0xbb, 0x08, 0xe9, 0x0e, 0x6f, 0x3f, 0x76, 0xf0, 0x29, 0x2b, 0x6a, 0x1c, + 0x0e, 0xfe, 0xd4, 0xcf, 0x3f, 0xa4, 0x79, 0xc0, 0x08, 0x36, 0xb8, 0x0b, 0xe3, 0x5c, 0xd2, 0x8c, + 0xf6, 0x1a, 0x84, 0x0c, 0xf9, 0x11, 0x4d, 0xd3, 0xde, 0x40, 0xce, 0x1d, 0x6c, 0x99, 0xb6, 0x97, + 0xf6, 0xd9, 0xe8, 0xf0, 0xe8, 0xe7, 0xe1, 0xe8, 0x70, 0x34, 0x62, 0x6f, 0x0b, 0x83, 0x8b, 0xa6, + 0x44, 0x02, 0x9d, 0xa6, 0xc5, 0x9a, 0xd6, 0xf4, 0x76, 0x24, 0x5d, 0xe3, 0xb0, 0xc2, 0x55, 0x15, + 0xa1, 0x47, 0xa7, 0x9a, 0x89, 0xfa, 0x5d, 0x60, 0xcc, 0x4b, 0x3d, 0x8f, 0x56, 0xb8, 0xa1, 0x82, + 0x89, 0xae, 0xaf, 0xde, 0x4e, 0xde, 0x4d, 0x27, 0x5f, 0xa7, 0x20, 0xb8, 0xb9, 0x9a, 0xb1, 0xb2, + 0xb1, 0xe4, 0x03, 0xc4, 0x31, 0xd6, 0x39, 0x3a, 0x05, 0x83, 0x51, 0x61, 0x18, 0xd6, 0xe2, 0x30, + 0x44, 0x66, 0xb5, 0x15, 0x7a, 0xd9, 0x32, 0x82, 0x95, 0x15, 0xa7, 0xce, 0xf5, 0xeb, 0x34, 0xf3, + 0x1b, 0x32, 0x0d, 0x54, 0xba, 0xd2, 0x10, 0x2c, 0xb5, 0x0b, 0x6d, 0x89, 0xcd, 0x27, 0xc8, 0x77, + 0x6e, 0x6d, 0xc1, 0x57, 0x6b, 0xdb, 0xff, 0xdb, 0xda, 0x22, 0x1a, 0x38, 0x08, 0x99, 0x27, 0x9c, + 0x8e, 0xe9, 0x9f, 0xd0, 0x10, 0x6b, 0x3b, 0x17, 0x07, 0x76, 0x55, 0x8a, 0xcd, 0xb1, 0xff, 0x70, + 0xa1, 0x70, 0xfd, 0x6b, 0xfc, 0x41, 0xcb, 0x2e, 0x6d, 0xbe, 0xf4, 0xd1, 0xfd, 0x3f, 0x92, 0x88, + 0x74, 0xbb, 0x84, 0x0f, 0x00, 0x00 }; @@ -1509,3 +1511,44 @@ const uint8_t PAGE_settings_um[] PROGMEM = { 0x6b, 0x43, 0x12, 0x90, 0x0e, 0x00, 0x00 }; + +// Autogenerated from wled00/data/settings_pin.htm, do not edit!! +const uint16_t PAGE_settings_pin_length = 549; +const uint8_t PAGE_settings_pin[] PROGMEM = { + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x95, 0x53, 0x5d, 0x6f, 0xd3, 0x30, + 0x14, 0x7d, 0xcf, 0xaf, 0xf0, 0x8c, 0x34, 0xb5, 0x52, 0xdb, 0x8c, 0x09, 0x24, 0xc4, 0x92, 0x00, + 0x85, 0x49, 0xec, 0x01, 0x56, 0xa9, 0xbc, 0xf0, 0x34, 0xb9, 0xf6, 0x4d, 0xe3, 0xd5, 0xb1, 0x23, + 0xfb, 0xa6, 0xa1, 0x9b, 0xf8, 0xef, 0x5c, 0x27, 0xfd, 0xd8, 0x26, 0x21, 0xc1, 0x4b, 0x9c, 0x73, + 0xee, 0xb9, 0xdf, 0x76, 0x76, 0xf6, 0xe5, 0xf6, 0xf3, 0x8f, 0x9f, 0x8b, 0x6b, 0x56, 0x61, 0x6d, + 0x8a, 0x2c, 0x7e, 0x99, 0x11, 0x76, 0x9d, 0x73, 0xb0, 0x9c, 0x30, 0x08, 0x55, 0x64, 0x35, 0xa0, + 0x60, 0x56, 0xd4, 0x90, 0xf3, 0xad, 0x86, 0xae, 0x71, 0x1e, 0x39, 0x93, 0xce, 0x22, 0x58, 0xcc, + 0x79, 0xa7, 0x15, 0x56, 0xf9, 0xdb, 0x8b, 0x0b, 0x5e, 0x24, 0x83, 0x34, 0x79, 0x61, 0x53, 0xb0, + 0xd5, 0x12, 0xa6, 0x3d, 0x98, 0x68, 0xab, 0x51, 0x0b, 0x33, 0x0d, 0x52, 0x18, 0xc8, 0x5f, 0x4f, + 0x6a, 0xf1, 0x4b, 0xd7, 0x6d, 0x7d, 0xc4, 0x6d, 0x00, 0xdf, 0x03, 0xb1, 0x22, 0x6c, 0x1d, 0x67, + 0xc9, 0x8b, 0xd4, 0xfb, 0x82, 0x64, 0x25, 0x7c, 0x00, 0x4a, 0xd2, 0x62, 0x39, 0x7d, 0x47, 0x2c, + 0x6a, 0x34, 0x50, 0x7c, 0xd3, 0x41, 0xb2, 0x25, 0x20, 0x6a, 0xbb, 0x0e, 0x59, 0x3a, 0x90, 0x59, + 0x90, 0x5e, 0x37, 0x58, 0x24, 0x5b, 0xe1, 0x99, 0xca, 0x95, 0x93, 0x6d, 0x4d, 0x05, 0x5e, 0x95, + 0xad, 0x95, 0xa8, 0x9d, 0x65, 0x5f, 0x47, 0xe3, 0xc7, 0x4e, 0x5b, 0xe5, 0xba, 0x99, 0x6b, 0xc0, + 0x8e, 0x78, 0x85, 0xd8, 0x84, 0xf7, 0x69, 0xba, 0xb1, 0x6e, 0xd6, 0x19, 0x50, 0xb3, 0x35, 0xa4, + 0x25, 0x08, 0x6c, 0x3d, 0x84, 0x34, 0xec, 0xc3, 0xa7, 0xaf, 0x02, 0xc8, 0xd6, 0x6b, 0xdc, 0x4d, + 0x0f, 0x14, 0x1f, 0xff, 0x3e, 0x06, 0x9d, 0xbf, 0x0c, 0x7a, 0x74, 0xe4, 0x13, 0x7e, 0x17, 0xc0, + 0x94, 0x4f, 0xd5, 0xeb, 0x1b, 0x35, 0xc2, 0xf1, 0xa3, 0x07, 0xca, 0x61, 0x59, 0x4c, 0x88, 0xd7, + 0x06, 0x62, 0x99, 0xf3, 0x5d, 0x6f, 0x3a, 0x49, 0x75, 0xb8, 0x5d, 0xdd, 0x3f, 0x11, 0xe3, 0xf9, + 0x39, 0x77, 0xab, 0x7b, 0x90, 0xc8, 0xf3, 0x1c, 0x77, 0x0d, 0xb8, 0x32, 0x72, 0x67, 0x9f, 0xbc, + 0x17, 0xbb, 0x99, 0x0e, 0xfd, 0x19, 0x23, 0x24, 0x59, 0xba, 0x9f, 0x44, 0x16, 0x70, 0x47, 0x83, + 0xf9, 0xa8, 0xeb, 0x38, 0x53, 0xd6, 0x7a, 0x33, 0xe2, 0x3d, 0x35, 0x93, 0x81, 0x9a, 0xb8, 0x22, + 0x61, 0x2f, 0xc8, 0xd2, 0xe1, 0x0e, 0xac, 0x9c, 0xda, 0x15, 0x59, 0xe9, 0x7c, 0xcd, 0xb4, 0xca, + 0x79, 0xfc, 0xb9, 0x0b, 0xc7, 0xdd, 0x2c, 0x4b, 0xce, 0x68, 0x29, 0x95, 0x23, 0x53, 0xe3, 0x42, + 0xdc, 0x91, 0xd2, 0x5b, 0x26, 0x8d, 0x08, 0x21, 0xe7, 0xe8, 0x1a, 0xef, 0xba, 0xe7, 0x5c, 0x05, + 0xa6, 0x99, 0x13, 0xb5, 0x6a, 0x11, 0xa9, 0xa3, 0x24, 0x56, 0x9d, 0xf3, 0x01, 0x71, 0xe6, 0xac, + 0x34, 0x5a, 0x6e, 0x72, 0x4e, 0x7b, 0xe1, 0xc5, 0x87, 0x2c, 0x1d, 0x0c, 0x54, 0x0d, 0x85, 0x38, + 0x3a, 0xfd, 0xc5, 0x67, 0x1e, 0x7d, 0x92, 0xb9, 0x90, 0x9b, 0x93, 0xdf, 0x33, 0x8f, 0xd0, 0xae, + 0x6a, 0x4d, 0x35, 0x2e, 0xfb, 0xf3, 0x24, 0xaa, 0xfc, 0x21, 0x41, 0x75, 0x59, 0x24, 0x0b, 0x03, + 0x22, 0x00, 0xa3, 0xf9, 0x83, 0x67, 0x87, 0xc5, 0xb1, 0xc5, 0xcd, 0x77, 0xba, 0xfa, 0x0a, 0x68, + 0x2e, 0x97, 0x45, 0xa6, 0x6d, 0xd3, 0xe2, 0x3e, 0x6a, 0x43, 0x7d, 0x75, 0xce, 0x2b, 0xbe, 0x7f, + 0x2a, 0xa4, 0xe4, 0x2c, 0xe8, 0x07, 0xfa, 0x7d, 0x43, 0x83, 0xa2, 0x7b, 0x6e, 0xc0, 0xae, 0xe9, + 0x39, 0x44, 0x58, 0x6b, 0x7b, 0x42, 0x54, 0x9e, 0x1f, 0xb2, 0xff, 0x43, 0x63, 0xb1, 0xaf, 0xe4, + 0x3f, 0x1b, 0x4b, 0xe3, 0xba, 0xe8, 0x18, 0x96, 0x98, 0xf6, 0x6f, 0xfd, 0x0f, 0x3e, 0x51, 0x03, + 0x3c, 0xfb, 0x03, 0x00, 0x00 +}; + diff --git a/wled00/set.cpp b/wled00/set.cpp index 7ff7f74c..303a2859 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -7,10 +7,19 @@ //called upon POST settings form submit void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) { + // PIN code request + if (subPage == 252) + { + correctPIN = (strlen(settingsPIN)==0 || strncmp(settingsPIN, request->arg(F("PIN")).c_str(), 4)==0); + lastEditTime = millis(); + return; + } //0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 7: DMX 8: usermods if (subPage <1 || subPage >8) return; + if (correctPIN) lastEditTime = millis(); + //WIFI SETTINGS if (subPage == 1) { @@ -393,6 +402,14 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) doReboot = true; } + if (request->hasArg(F("PIN"))) { + const char *pin = request->arg(F("PIN")).c_str(); + if (strlen(pin) == 4 || strlen(pin) == 0) { + strlcpy(settingsPIN, pin, 5); + settingsPIN[4] = 0; + } + } + bool pwdCorrect = !otaLock; //always allow access if ota not locked if (request->hasArg(F("OP"))) { @@ -408,11 +425,14 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) if (pwdCorrect) //allow changes if correct pwd or no ota active { + bool oldOTALock = otaLock; otaLock = request->hasArg(F("NO")); wifiLock = request->hasArg(F("OW")); aOtaEnabled = request->hasArg(F("AO")); + doReboot = (otaLock ^ oldOTALock); } } + #ifdef WLED_ENABLE_DMX // include only if DMX is enabled if (subPage == 7) { @@ -526,7 +546,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) releaseJSONBufferLock(); } - + if (subPage != 2 && (subPage != 6 || !doReboot)) serializeConfig(); //do not save if factory reset or LED settings (which are saved after LED re-init) if (subPage == 4) alexaInit(); } diff --git a/wled00/wled.cpp b/wled00/wled.cpp index afc56db2..46aaee12 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -139,6 +139,13 @@ void WLED::loop() yield(); } + // 15min PIN time-out + if (strlen(settingsPIN)>0 && millis() - lastEditTime > 900000) { + correctPIN = false; + server.removeHandler(editHandler); + createEditHandler(correctPIN); + } + //LED settings have been saved, re-init busses //This code block causes severe FPS drop on ESP32 with the original "if (busConfigs[0] != nullptr)" conditional. Investigate! if (doInitBusses) { @@ -723,9 +730,6 @@ void WLED::handleStatusLED() { #if defined(STATUSLED) uint32_t c = 0; - static unsigned long ledStatusLastMillis = 0; - static unsigned short ledStatusType = 0; // current status type - corresponds to number of blinks per second - static bool ledStatusState = false; // the current LED state #if STATUSLED>=0 if (pinManager.isPinAllocated(STATUSLED)) { diff --git a/wled00/wled.h b/wled00/wled.h index 403c27ba..bc7d9350 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2202281 +#define VERSION 2203011 //uncomment this if you have a "my_config.h" file you'd like to use //#define WLED_USE_MY_CONFIG @@ -417,6 +417,9 @@ WLED_GLOBAL byte macroDoublePress[WLED_MAX_BUTTONS] _INIT({0}); 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 char settingsPIN[5] _INIT(""); // PIN for settings pages +WLED_GLOBAL bool correctPIN _INIT(true); +WLED_GLOBAL unsigned long lastEditTime _INIT(0); WLED_GLOBAL uint16_t userVar0 _INIT(0), userVar1 _INIT(0); //available for use in usermod @@ -603,6 +606,13 @@ WLED_GLOBAL byte optionType; WLED_GLOBAL bool doReboot _INIT(false); // flag to initiate reboot from async handlers WLED_GLOBAL bool doPublishMqtt _INIT(false); +// status led +#if defined(STATUSLED) +WLED_GLOBAL unsigned long ledStatusLastMillis _INIT(0); +WLED_GLOBAL uint8_t ledStatusType _INIT(0); // current status type - corresponds to number of blinks per second +WLED_GLOBAL bool ledStatusState _INIT(false); // the current LED state +#endif + // server library objects WLED_GLOBAL AsyncWebServer server _INIT_N(((80))); #ifdef WLED_ENABLE_WEBSOCKETS @@ -610,6 +620,7 @@ WLED_GLOBAL AsyncWebSocket ws _INIT_N((("/ws"))); #endif WLED_GLOBAL AsyncClient* hueClient _INIT(NULL); WLED_GLOBAL AsyncMqttClient* mqtt _INIT(NULL); +WLED_GLOBAL AsyncWebHandler *editHandler _INIT(nullptr); // udp interface objects WLED_GLOBAL WiFiUDP notifierUdp, rgbUdp, notifier2Udp; diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index 02a5fd4c..d92eb2f3 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -18,8 +18,8 @@ bool isIp(String str) { return true; } -void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){ - if (otaLock) { +void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) { + if (otaLock || !correctPIN) { if (final) request->send(500, "text/plain", F("Please unlock OTA in security settings!")); return; } @@ -27,18 +27,42 @@ void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t request->_tempFile = WLED_FS.open(filename, "w"); DEBUG_PRINT("Uploading "); DEBUG_PRINTLN(filename); - if (filename == "/presets.json") presetsModifiedTime = toki.second(); + if (filename == F("/presets.json")) presetsModifiedTime = toki.second(); } if (len) { request->_tempFile.write(data,len); } if (final) { request->_tempFile.close(); - request->send(200, "text/plain", F("File Uploaded!")); + if (filename == F("/cfg.json")) { + doReboot = true; + request->send(200, "text/plain", F("Configuration restore successful.\nRebooting...")); + } else + request->send(200, "text/plain", F("File Uploaded!")); cacheInvalidate++; } } +void createEditHandler(bool enable) { + if (enable) { + #ifdef WLED_ENABLE_FS_EDITOR + #ifdef ARDUINO_ARCH_ESP32 + editHandler = &server.addHandler(new SPIFFSEditor(WLED_FS));//http_username,http_password)); + #else + editHandler = &server.addHandler(new SPIFFSEditor("","",WLED_FS));//http_username,http_password)); + #endif + #else + editHandler = server.on("/edit", HTTP_GET, [](AsyncWebServerRequest *request){ + serveMessage(request, 501, "Not implemented", F("The FS editor is disabled in this build."), 254); + }); + #endif + } else { + editHandler = &server.on("/edit", HTTP_GET, [](AsyncWebServerRequest *request){ + serveMessage(request, 500, "Access Denied", F("Please unlock settings page!"), 254); + }); + } +} + bool captivePortal(AsyncWebServerRequest *request) { if (ON_STA_FILTER(request)) return false; //only serve captive in AP mode @@ -88,6 +112,14 @@ void initServer() serveSettings(request); }); + server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){ + if (handleIfNoneMatchCacheHeader(request)) return; + AsyncWebServerResponse *response = request->beginResponse_P(200, "text/css", PAGE_settingsCss, PAGE_settingsCss_length); + response->addHeader(F("Content-Encoding"),"gzip"); + setStaticContentCacheHeaders(response); + request->send(response); + }); + server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){ if(!handleFileRead(request, "/favicon.ico")) { @@ -212,37 +244,30 @@ void initServer() request->send(response); }); + createEditHandler(correctPIN); + +#ifndef WLED_DISABLE_OTA //if OTA is allowed - if (!otaLock){ - #ifdef WLED_ENABLE_FS_EDITOR - #ifdef ARDUINO_ARCH_ESP32 - server.addHandler(new SPIFFSEditor(WLED_FS));//http_username,http_password)); - #else - server.addHandler(new SPIFFSEditor("","",WLED_FS));//http_username,http_password)); - #endif - #else - server.on("/edit", HTTP_GET, [](AsyncWebServerRequest *request){ - serveMessage(request, 501, "Not implemented", F("The FS editor is disabled in this build."), 254); - }); - #endif + if (!otaLock) { //init ota page - #ifndef WLED_DISABLE_OTA server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){ - AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", PAGE_update, PAGE_update_length); + AsyncWebServerResponse *response; + if (correctPIN) response = request->beginResponse_P(200, "text/html", PAGE_update, PAGE_update_length); + else response = request->beginResponse_P(200, "text/html", PAGE_settings_pin, PAGE_settings_pin_length); response->addHeader(F("Content-Encoding"),"gzip"); setStaticContentCacheHeaders(response); request->send(response); - //request->send_P(200, "text/html", PAGE_update); }); server.on("/update", HTTP_POST, [](AsyncWebServerRequest *request){ - if (Update.hasError()) - { - serveMessage(request, 500, F("Update failed!"), F("Please check your file and retry!"), 254); return; + if (Update.hasError() || !correctPIN) { + serveMessage(request, 500, F("Update failed!"), F("Please check your file and retry!"), 254); + } else { + serveMessage(request, 200, F("Update successful!"), F("Rebooting..."), 131); + doReboot = true; } - serveMessage(request, 200, F("Update successful!"), F("Rebooting..."), 131); - doReboot = true; },[](AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){ + if (!correctPIN) return; if(!index){ DEBUG_PRINTLN(F("OTA Update Start")); #ifdef ESP8266 @@ -259,21 +284,16 @@ void initServer() } } }); - - #else - server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){ - serveMessage(request, 501, "Not implemented", F("OTA updating is disabled in this build."), 254); - }); - #endif - } else - { - server.on("/edit", HTTP_GET, [](AsyncWebServerRequest *request){ - serveMessage(request, 500, "Access Denied", F("Please unlock OTA in security settings!"), 254); - }); + } else { server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){ serveMessage(request, 500, "Access Denied", F("Please unlock OTA in security settings!"), 254); }); } +#else + server.on("/update", HTTP_GET, [](AsyncWebServerRequest *request){ + serveMessage(request, 501, "Not implemented", F("OTA updating is disabled in this build."), 254); + }); +#endif #ifdef WLED_ENABLE_DMX @@ -479,6 +499,10 @@ void serveSettings(AsyncWebServerRequest* request, bool post) else if (url.indexOf("um") > 0) subPage = 8; } else subPage = 255; //welcome page + if (subPage > 0 && subPage < 9 && strlen(settingsPIN)>0 && !correctPIN) { + subPage = 252; // require PIN + } + if (subPage == 1 && wifiLock && otaLock) { serveMessage(request, 500, "Access Denied", F("Please unlock OTA in security settings!"), 254); return; @@ -496,16 +520,21 @@ void serveSettings(AsyncWebServerRequest* request, bool post) case 3: strcpy_P(s, PSTR("UI")); break; case 4: strcpy_P(s, PSTR("Sync")); break; case 5: strcpy_P(s, PSTR("Time")); break; - case 6: strcpy_P(s, PSTR("Security")); strcpy_P(s2, PSTR("Rebooting, please wait ~10 seconds...")); break; + case 6: strcpy_P(s, PSTR("Security")); if (doReboot) strcpy_P(s2, PSTR("Rebooting, please wait ~10 seconds...")); break; case 7: strcpy_P(s, PSTR("DMX")); break; case 8: strcpy_P(s, PSTR("Usermods")); break; + case 252: strcpy_P(s, correctPIN ? PSTR("PIN accepted") : PSTR("PIN rejected")); } - strcat_P(s, PSTR(" settings saved.")); + if (subPage != 252) strcat_P(s, PSTR(" settings saved.")); + else { + server.removeHandler(editHandler); + createEditHandler(correctPIN); + } if (!s2[0]) strcpy_P(s2, PSTR("Redirecting...")); - if (!doReboot) serveMessage(request, 200, s, s2, (subPage == 1 || subPage == 6) ? 129 : 1); - if (subPage == 6) doReboot = true; + serveMessage(request, 200, s, s2, (subPage == 1 || (subPage == 6 && doReboot)) ? 129 : (correctPIN ? 1 : 10)); + //if (subPage == 6) doReboot = true; return; } @@ -527,6 +556,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) case 6: response = request->beginResponse_P(200, "text/html", PAGE_settings_sec, PAGE_settings_sec_length); break; case 7: response = request->beginResponse_P(200, "text/html", PAGE_settings_dmx, PAGE_settings_dmx_length); break; case 8: response = request->beginResponse_P(200, "text/html", PAGE_settings_um, PAGE_settings_um_length); break; + case 252: response = request->beginResponse_P(200, "text/html", PAGE_settings_pin, PAGE_settings_pin_length); break; case 253: response = request->beginResponse_P(200, "text/css", PAGE_settingsCss, PAGE_settingsCss_length); break; case 254: serveSettingsJS(request); return; case 255: response = request->beginResponse_P(200, "text/html", PAGE_welcome, PAGE_welcome_length); break; diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 5c6837d5..723d7d2e 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -1,632 +1,633 @@ -#include "wled.h" -#include "wled_ethernet.h" - -/* - * Sending XML status files to client - */ - -//build XML response to HTTP /win API request -void XML_response(AsyncWebServerRequest *request, char* dest) -{ - char sbuf[(dest == nullptr)?1024:1]; //allocate local buffer if none passed - obuf = (dest == nullptr)? sbuf:dest; - - olen = 0; - oappend(SET_F("")); - oappendi((nightlightActive && nightlightMode > NL_MODE_SET) ? briT : bri); - oappend(SET_F("")); - - for (int i = 0; i < 3; i++) - { - oappend(""); - oappendi(col[i]); - oappend(""); - } - for (int i = 0; i < 3; i++) - { - oappend(""); - oappendi(colSec[i]); - oappend(""); - } - oappend(SET_F("")); - oappendi(notifyDirect); - oappend(SET_F("")); - oappendi(receiveNotifications); - oappend(SET_F("")); - oappendi(nightlightActive); - oappend(SET_F("")); - oappendi(nightlightMode > NL_MODE_SET); - oappend(SET_F("")); - oappendi(nightlightDelayMins); - oappend(SET_F("")); - oappendi(nightlightTargetBri); - oappend(SET_F("")); - oappendi(effectCurrent); - oappend(SET_F("")); - oappendi(effectSpeed); - oappend(SET_F("")); - oappendi(effectIntensity); - oappend(SET_F("")); - oappendi(effectPalette); - oappend(SET_F("")); - if (strip.hasWhiteChannel()) { - oappendi(col[3]); - } else { - oappend("-1"); - } - oappend(SET_F("")); - oappendi(colSec[3]); - oappend(SET_F("")); - oappendi(currentPreset); - oappend(SET_F("")); - oappendi(currentPlaylist >= 0); - oappend(SET_F("")); - oappend(serverDescription); - if (realtimeMode) - { - oappend(SET_F(" (live)")); - } - oappend(SET_F("")); - oappendi(strip.getFirstSelectedSegId()); - oappend(SET_F("")); - if (request != nullptr) request->send(200, "text/xml", obuf); -} - -//Deprecated, use of /json/state and presets recommended instead -void URL_response(AsyncWebServerRequest *request) -{ - char sbuf[256]; - char s2buf[100]; - obuf = s2buf; - olen = 0; - - char s[16]; - oappend(SET_F("http://")); - IPAddress localIP = Network.localIP(); - sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]); - oappend(s); - - oappend(SET_F("/win&A=")); - oappendi(bri); - oappend(SET_F("&CL=h")); - for (int i = 0; i < 3; i++) - { - sprintf(s,"%02X", col[i]); - oappend(s); - } - oappend(SET_F("&C2=h")); - for (int i = 0; i < 3; i++) - { - sprintf(s,"%02X", colSec[i]); - oappend(s); - } - oappend(SET_F("&FX=")); - oappendi(effectCurrent); - oappend(SET_F("&SX=")); - oappendi(effectSpeed); - oappend(SET_F("&IX=")); - oappendi(effectIntensity); - oappend(SET_F("&FP=")); - oappendi(effectPalette); - - obuf = sbuf; - olen = 0; - - oappend(SET_F("")); - oappend(s2buf); - oappend(SET_F("")); - - if (request != nullptr) request->send(200, "text/html", obuf); -} - -void extractPin(JsonObject &obj, const char *key) { - if (obj[key].is()) { - JsonArray pins = obj[key].as(); - for (JsonVariant pv : pins) { - if (pv.as() > -1) { oappend(","); oappendi(pv.as()); } - } - } else { - if (obj[key].as() > -1) { oappend(","); oappendi(obj[key].as()); } - } -} - -// oappend used pins by scanning JsonObject (1 level deep) -void fillUMPins(JsonObject &mods) -{ - for (JsonPair kv : mods) { - // kv.key() is usermod name or subobject key - // kv.value() is object itself - JsonObject obj = kv.value(); - if (!obj.isNull()) { - // element is an JsonObject - if (!obj["pin"].isNull()) { - extractPin(obj, "pin"); - } else { - // scan keys (just one level deep as is possible with usermods) - for (JsonPair so : obj) { - const char *key = so.key().c_str(); - if (strstr(key, "pin")) { - // we found a key containing "pin" substring - if (strlen(strstr(key, "pin")) == 3) { - // and it is at the end, we found another pin - extractPin(obj, key); - continue; - } - } - if (!obj[so.key()].is()) continue; - JsonObject subObj = obj[so.key()]; - if (!subObj["pin"].isNull()) { - // get pins from subobject - extractPin(subObj, "pin"); - } - } - } - } - } -} - - -//get values for settings form in javascript -void getSettingsJS(byte subPage, char* dest) -{ - //0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec - DEBUG_PRINT(F("settings resp")); - DEBUG_PRINTLN(subPage); - obuf = dest; - olen = 0; - - if (subPage <0 || subPage >8) return; - - if (subPage == 0) - { - #ifdef WLED_ENABLE_DMX // include only if DMX is enabled - oappend(PSTR("gId('dmxbtn').style.display='';")); - #endif - } - - if (subPage == 1) - { - sappends('s',SET_F("CS"),clientSSID); - - byte l = strlen(clientPass); - char fpass[l+1]; //fill password field with *** - fpass[l] = 0; - memset(fpass,'*',l); - sappends('s',SET_F("CP"),fpass); - - char k[3]; k[2] = 0; //IP addresses - for (int i = 0; i<4; i++) - { - k[1] = 48+i; //ascii 0,1,2,3 - k[0] = 'I'; sappend('v',k,staticIP[i]); - k[0] = 'G'; sappend('v',k,staticGateway[i]); - k[0] = 'S'; sappend('v',k,staticSubnet[i]); - } - - sappends('s',SET_F("CM"),cmDNS); - sappend('i',SET_F("AB"),apBehavior); - sappends('s',SET_F("AS"),apSSID); - sappend('c',SET_F("AH"),apHide); - - l = strlen(apPass); - char fapass[l+1]; //fill password field with *** - fapass[l] = 0; - memset(fapass,'*',l); - sappends('s',SET_F("AP"),fapass); - - sappend('v',SET_F("AC"),apChannel); - sappend('c',SET_F("WS"),noWifiSleep); - - #ifdef WLED_USE_ETHERNET - sappend('v',SET_F("ETH"),ethernetType); - #else - //hide ethernet setting if not compiled in - oappend(SET_F("document.getElementById('ethd').style.display='none';")); - #endif - - if (Network.isConnected()) //is connected - { - char s[32]; - IPAddress localIP = Network.localIP(); - sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]); - - #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET) - if (Network.isEthernet()) strcat_P(s ,SET_F(" (Ethernet)")); - #endif - sappends('m',SET_F("(\"sip\")[0]"),s); - } else - { - sappends('m',SET_F("(\"sip\")[0]"),(char*)F("Not connected")); - } - - if (WiFi.softAPIP()[0] != 0) //is active - { - char s[16]; - IPAddress apIP = WiFi.softAPIP(); - sprintf(s, "%d.%d.%d.%d", apIP[0], apIP[1], apIP[2], apIP[3]); - sappends('m',SET_F("(\"sip\")[1]"),s); - } else - { - sappends('m',SET_F("(\"sip\")[1]"),(char*)F("Not active")); - } - } - - if (subPage == 2) - { - char nS[8]; - - - // Pin reservations will become unnecessary when settings pages will read cfg.json directly - // add reserved and usermod pins as d.um_p array - oappend(SET_F("d.um_p=[6,7,8,9,10,11")); - - if (requestJSONBufferLock(6)) { - // if we can't allocate JSON buffer ignore usermod pins - JsonObject mods = doc.createNestedObject(F("um")); - usermods.addToConfig(mods); - if (!mods.isNull()) fillUMPins(mods); - releaseJSONBufferLock(); - } - - #ifdef WLED_ENABLE_DMX - oappend(SET_F(",2")); // DMX hardcoded pin - #endif - - #ifdef WLED_ENABLE_ADALIGHT - // inform settings page that pin 3 is used by ADALights if not aleready used by strip (previous setup) - // NOTE: this will prohibit pin 3 use on new installs - /* - { - bool pin3used = false; - for (uint8_t s=0; s < busses.getNumBusses(); s++) { - Bus* bus = busses.getBus(s); - uint8_t pins[5]; - uint8_t nPins = bus->getPins(pins); - for (uint8_t i = 0; i < nPins; i++) { - if (pins[i] == 3) { - pin3used = true; - break; - } - } - if (pin3used) break; - } - if (!pin3used && pinManager.isPinAllocated(3)) oappend(SET_F(",3")); // ADALight (RX) pin - } - */ - #endif - - #ifdef WLED_DEBUG - oappend(SET_F(",1")); // debug output (TX) pin - #endif - - #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM) - if (psramFound()) oappend(SET_F(",16,17")); // GPIO16 & GPIO17 reserved for SPI RAM - #endif - - #ifdef WLED_USE_ETHERNET - if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) { - for (uint8_t p=0; p=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_power,nS,10)); } - if (ethernetBoards[ethernetType].eth_mdc>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdc,nS,10)); } - if (ethernetBoards[ethernetType].eth_mdio>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdio,nS,10)); } - switch (ethernetBoards[ethernetType].eth_clk_mode) { - case ETH_CLOCK_GPIO0_IN: - case ETH_CLOCK_GPIO0_OUT: - oappend(SET_F(",0")); - break; - case ETH_CLOCK_GPIO16_OUT: - oappend(SET_F(",16")); - break; - case ETH_CLOCK_GPIO17_OUT: - oappend(SET_F(",17")); - break; - } - } - #endif - - oappend(SET_F("];")); - - // set limits - oappend(SET_F("bLimits(")); - oappend(itoa(WLED_MAX_BUSSES,nS,10)); oappend(","); - oappend(itoa(MAX_LEDS_PER_BUS,nS,10)); oappend(","); - oappend(itoa(MAX_LED_MEMORY,nS,10)); oappend(","); - oappend(itoa(MAX_LEDS,nS,10)); - oappend(SET_F(");")); - - sappend('c',SET_F("MS"),autoSegments); - sappend('c',SET_F("CCT"),correctWB); - sappend('c',SET_F("CR"),cctFromRgb); - sappend('v',SET_F("CB"),strip.cctBlending); - sappend('v',SET_F("FR"),strip.getTargetFps()); - sappend('v',SET_F("AW"),Bus::getAutoWhiteMode()); - - for (uint8_t s=0; s < busses.getNumBusses(); s++) { - Bus* bus = busses.getBus(s); - if (bus == nullptr) continue; - char lp[4] = "L0"; lp[2] = 48+s; lp[3] = 0; //ascii 0-9 //strip data pin - char lc[4] = "LC"; lc[2] = 48+s; lc[3] = 0; //strip length - char co[4] = "CO"; co[2] = 48+s; co[3] = 0; //strip color order - char lt[4] = "LT"; lt[2] = 48+s; lt[3] = 0; //strip type - char ls[4] = "LS"; ls[2] = 48+s; ls[3] = 0; //strip start LED - char cv[4] = "CV"; cv[2] = 48+s; cv[3] = 0; //strip reverse - char sl[4] = "SL"; sl[2] = 48+s; sl[3] = 0; //skip 1st LED - char rf[4] = "RF"; rf[2] = 48+s; rf[3] = 0; //off refresh - oappend(SET_F("addLEDs(1);")); - uint8_t pins[5]; - uint8_t nPins = bus->getPins(pins); - for (uint8_t i = 0; i < nPins; i++) { - lp[1] = 48+i; - if (pinManager.isPinOk(pins[i]) || bus->getType()>=TYPE_NET_DDP_RGB) sappend('v',lp,pins[i]); - } - sappend('v',lc,bus->getLength()); - sappend('v',lt,bus->getType()); - sappend('v',co,bus->getColorOrder()); - sappend('v',ls,bus->getStart()); - sappend('c',cv,bus->reversed); - sappend('c',sl,bus->skippedLeds()); - sappend('c',rf,bus->isOffRefreshRequired()); - } - sappend('v',SET_F("MA"),strip.ablMilliampsMax); - sappend('v',SET_F("LA"),strip.milliampsPerLed); - if (strip.currentMilliamps) - { - sappends('m',SET_F("(\"pow\")[0]"),(char*)""); - olen -= 2; //delete "; - oappendi(strip.currentMilliamps); - oappend(SET_F("mA\";")); - } - - oappend(SET_F("resetCOM(")); - oappend(itoa(WLED_MAX_COLOR_ORDER_MAPPINGS,nS,10)); - oappend(SET_F(");")); - const ColorOrderMap& com = busses.getColorOrderMap(); - for (uint8_t s=0; s < com.count(); s++) { - const ColorOrderMapEntry* entry = com.get(s); - if (entry == nullptr) break; - oappend(SET_F("addCOM(")); - oappend(itoa(entry->start,nS,10)); oappend(","); - oappend(itoa(entry->len,nS,10)); oappend(","); - oappend(itoa(entry->colorOrder,nS,10)); oappend(");"); - } - - sappend('v',SET_F("CA"),briS); - - sappend('c',SET_F("BO"),turnOnAtBoot); - sappend('v',SET_F("BP"),bootPreset); - - sappend('c',SET_F("GB"),strip.gammaCorrectBri); - sappend('c',SET_F("GC"),strip.gammaCorrectCol); - sappend('c',SET_F("TF"),fadeTransition); - sappend('v',SET_F("TD"),transitionDelayDefault); - sappend('c',SET_F("PF"),strip.paletteFade); - sappend('v',SET_F("BF"),briMultiplier); - sappend('v',SET_F("TB"),nightlightTargetBri); - sappend('v',SET_F("TL"),nightlightDelayMinsDefault); - sappend('v',SET_F("TW"),nightlightMode); - sappend('i',SET_F("PB"),strip.paletteBlend); - sappend('v',SET_F("RL"),rlyPin); - sappend('c',SET_F("RM"),rlyMde); - for (uint8_t i=0; i> 4) & 0x0F); - k[0] = 'P'; sappend('v',k,timerMonth[i] & 0x0F); - k[0] = 'D'; sappend('v',k,timerDay[i]); - k[0] = 'E'; sappend('v',k,timerDayEnd[i]); - } - } - } - - if (subPage == 6) - { - sappend('c',SET_F("NO"),otaLock); - sappend('c',SET_F("OW"),wifiLock); - sappend('c',SET_F("AO"),aOtaEnabled); - sappends('m',SET_F("(\"sip\")[0]"),(char*)F("WLED ")); - olen -= 2; //delete "; - oappend(versionString); - oappend(SET_F(" (build ")); - oappendi(VERSION); - oappend(SET_F(")\";")); - } - - #ifdef WLED_ENABLE_DMX // include only if DMX is enabled - if (subPage == 7) - { - sappend('v',SET_F("PU"),e131ProxyUniverse); - - sappend('v',SET_F("CN"),DMXChannels); - sappend('v',SET_F("CG"),DMXGap); - sappend('v',SET_F("CS"),DMXStart); - sappend('v',SET_F("SL"),DMXStartLED); - - sappend('i',SET_F("CH1"),DMXFixtureMap[0]); - sappend('i',SET_F("CH2"),DMXFixtureMap[1]); - sappend('i',SET_F("CH3"),DMXFixtureMap[2]); - sappend('i',SET_F("CH4"),DMXFixtureMap[3]); - sappend('i',SET_F("CH5"),DMXFixtureMap[4]); - sappend('i',SET_F("CH6"),DMXFixtureMap[5]); - sappend('i',SET_F("CH7"),DMXFixtureMap[6]); - sappend('i',SET_F("CH8"),DMXFixtureMap[7]); - sappend('i',SET_F("CH9"),DMXFixtureMap[8]); - sappend('i',SET_F("CH10"),DMXFixtureMap[9]); - sappend('i',SET_F("CH11"),DMXFixtureMap[10]); - sappend('i',SET_F("CH12"),DMXFixtureMap[11]); - sappend('i',SET_F("CH13"),DMXFixtureMap[12]); - sappend('i',SET_F("CH14"),DMXFixtureMap[13]); - sappend('i',SET_F("CH15"),DMXFixtureMap[14]); - } - #endif - - if (subPage == 8) //usermods - { - oappend(SET_F("numM=")); - oappendi(usermods.getModCount()); - oappend(";"); - } -} +#include "wled.h" +#include "wled_ethernet.h" + +/* + * Sending XML status files to client + */ + +//build XML response to HTTP /win API request +void XML_response(AsyncWebServerRequest *request, char* dest) +{ + char sbuf[(dest == nullptr)?1024:1]; //allocate local buffer if none passed + obuf = (dest == nullptr)? sbuf:dest; + + olen = 0; + oappend(SET_F("")); + oappendi((nightlightActive && nightlightMode > NL_MODE_SET) ? briT : bri); + oappend(SET_F("")); + + for (int i = 0; i < 3; i++) + { + oappend(""); + oappendi(col[i]); + oappend(""); + } + for (int i = 0; i < 3; i++) + { + oappend(""); + oappendi(colSec[i]); + oappend(""); + } + oappend(SET_F("")); + oappendi(notifyDirect); + oappend(SET_F("")); + oappendi(receiveNotifications); + oappend(SET_F("")); + oappendi(nightlightActive); + oappend(SET_F("")); + oappendi(nightlightMode > NL_MODE_SET); + oappend(SET_F("")); + oappendi(nightlightDelayMins); + oappend(SET_F("")); + oappendi(nightlightTargetBri); + oappend(SET_F("")); + oappendi(effectCurrent); + oappend(SET_F("")); + oappendi(effectSpeed); + oappend(SET_F("")); + oappendi(effectIntensity); + oappend(SET_F("")); + oappendi(effectPalette); + oappend(SET_F("")); + if (strip.hasWhiteChannel()) { + oappendi(col[3]); + } else { + oappend("-1"); + } + oappend(SET_F("")); + oappendi(colSec[3]); + oappend(SET_F("")); + oappendi(currentPreset); + oappend(SET_F("")); + oappendi(currentPlaylist >= 0); + oappend(SET_F("")); + oappend(serverDescription); + if (realtimeMode) + { + oappend(SET_F(" (live)")); + } + oappend(SET_F("")); + oappendi(strip.getFirstSelectedSegId()); + oappend(SET_F("")); + if (request != nullptr) request->send(200, "text/xml", obuf); +} + +//Deprecated, use of /json/state and presets recommended instead +void URL_response(AsyncWebServerRequest *request) +{ + char sbuf[256]; + char s2buf[100]; + obuf = s2buf; + olen = 0; + + char s[16]; + oappend(SET_F("http://")); + IPAddress localIP = Network.localIP(); + sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]); + oappend(s); + + oappend(SET_F("/win&A=")); + oappendi(bri); + oappend(SET_F("&CL=h")); + for (int i = 0; i < 3; i++) + { + sprintf(s,"%02X", col[i]); + oappend(s); + } + oappend(SET_F("&C2=h")); + for (int i = 0; i < 3; i++) + { + sprintf(s,"%02X", colSec[i]); + oappend(s); + } + oappend(SET_F("&FX=")); + oappendi(effectCurrent); + oappend(SET_F("&SX=")); + oappendi(effectSpeed); + oappend(SET_F("&IX=")); + oappendi(effectIntensity); + oappend(SET_F("&FP=")); + oappendi(effectPalette); + + obuf = sbuf; + olen = 0; + + oappend(SET_F("")); + oappend(s2buf); + oappend(SET_F("")); + + if (request != nullptr) request->send(200, "text/html", obuf); +} + +void extractPin(JsonObject &obj, const char *key) { + if (obj[key].is()) { + JsonArray pins = obj[key].as(); + for (JsonVariant pv : pins) { + if (pv.as() > -1) { oappend(","); oappendi(pv.as()); } + } + } else { + if (obj[key].as() > -1) { oappend(","); oappendi(obj[key].as()); } + } +} + +// oappend used pins by scanning JsonObject (1 level deep) +void fillUMPins(JsonObject &mods) +{ + for (JsonPair kv : mods) { + // kv.key() is usermod name or subobject key + // kv.value() is object itself + JsonObject obj = kv.value(); + if (!obj.isNull()) { + // element is an JsonObject + if (!obj["pin"].isNull()) { + extractPin(obj, "pin"); + } else { + // scan keys (just one level deep as is possible with usermods) + for (JsonPair so : obj) { + const char *key = so.key().c_str(); + if (strstr(key, "pin")) { + // we found a key containing "pin" substring + if (strlen(strstr(key, "pin")) == 3) { + // and it is at the end, we found another pin + extractPin(obj, key); + continue; + } + } + if (!obj[so.key()].is()) continue; + JsonObject subObj = obj[so.key()]; + if (!subObj["pin"].isNull()) { + // get pins from subobject + extractPin(subObj, "pin"); + } + } + } + } + } +} + + +//get values for settings form in javascript +void getSettingsJS(byte subPage, char* dest) +{ + //0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec + DEBUG_PRINT(F("settings resp")); + DEBUG_PRINTLN(subPage); + obuf = dest; + olen = 0; + + if (subPage <0 || subPage >8) return; + + if (subPage == 0) + { + #ifdef WLED_ENABLE_DMX // include only if DMX is enabled + oappend(PSTR("gId('dmxbtn').style.display='';")); + #endif + } + + if (subPage == 1) + { + sappends('s',SET_F("CS"),clientSSID); + + byte l = strlen(clientPass); + char fpass[l+1]; //fill password field with *** + fpass[l] = 0; + memset(fpass,'*',l); + sappends('s',SET_F("CP"),fpass); + + char k[3]; k[2] = 0; //IP addresses + for (int i = 0; i<4; i++) + { + k[1] = 48+i; //ascii 0,1,2,3 + k[0] = 'I'; sappend('v',k,staticIP[i]); + k[0] = 'G'; sappend('v',k,staticGateway[i]); + k[0] = 'S'; sappend('v',k,staticSubnet[i]); + } + + sappends('s',SET_F("CM"),cmDNS); + sappend('i',SET_F("AB"),apBehavior); + sappends('s',SET_F("AS"),apSSID); + sappend('c',SET_F("AH"),apHide); + + l = strlen(apPass); + char fapass[l+1]; //fill password field with *** + fapass[l] = 0; + memset(fapass,'*',l); + sappends('s',SET_F("AP"),fapass); + + sappend('v',SET_F("AC"),apChannel); + sappend('c',SET_F("WS"),noWifiSleep); + + #ifdef WLED_USE_ETHERNET + sappend('v',SET_F("ETH"),ethernetType); + #else + //hide ethernet setting if not compiled in + oappend(SET_F("document.getElementById('ethd').style.display='none';")); + #endif + + if (Network.isConnected()) //is connected + { + char s[32]; + IPAddress localIP = Network.localIP(); + sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]); + + #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_ETHERNET) + if (Network.isEthernet()) strcat_P(s ,SET_F(" (Ethernet)")); + #endif + sappends('m',SET_F("(\"sip\")[0]"),s); + } else + { + sappends('m',SET_F("(\"sip\")[0]"),(char*)F("Not connected")); + } + + if (WiFi.softAPIP()[0] != 0) //is active + { + char s[16]; + IPAddress apIP = WiFi.softAPIP(); + sprintf(s, "%d.%d.%d.%d", apIP[0], apIP[1], apIP[2], apIP[3]); + sappends('m',SET_F("(\"sip\")[1]"),s); + } else + { + sappends('m',SET_F("(\"sip\")[1]"),(char*)F("Not active")); + } + } + + if (subPage == 2) + { + char nS[8]; + + + // Pin reservations will become unnecessary when settings pages will read cfg.json directly + // add reserved and usermod pins as d.um_p array + oappend(SET_F("d.um_p=[6,7,8,9,10,11")); + + if (requestJSONBufferLock(6)) { + // if we can't allocate JSON buffer ignore usermod pins + JsonObject mods = doc.createNestedObject(F("um")); + usermods.addToConfig(mods); + if (!mods.isNull()) fillUMPins(mods); + releaseJSONBufferLock(); + } + + #ifdef WLED_ENABLE_DMX + oappend(SET_F(",2")); // DMX hardcoded pin + #endif + + #ifdef WLED_ENABLE_ADALIGHT + // inform settings page that pin 3 is used by ADALights if not aleready used by strip (previous setup) + // NOTE: this will prohibit pin 3 use on new installs + /* + { + bool pin3used = false; + for (uint8_t s=0; s < busses.getNumBusses(); s++) { + Bus* bus = busses.getBus(s); + uint8_t pins[5]; + uint8_t nPins = bus->getPins(pins); + for (uint8_t i = 0; i < nPins; i++) { + if (pins[i] == 3) { + pin3used = true; + break; + } + } + if (pin3used) break; + } + if (!pin3used && pinManager.isPinAllocated(3)) oappend(SET_F(",3")); // ADALight (RX) pin + } + */ + #endif + + #ifdef WLED_DEBUG + oappend(SET_F(",1")); // debug output (TX) pin + #endif + + #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM) + if (psramFound()) oappend(SET_F(",16,17")); // GPIO16 & GPIO17 reserved for SPI RAM + #endif + + #ifdef WLED_USE_ETHERNET + if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) { + for (uint8_t p=0; p=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_power,nS,10)); } + if (ethernetBoards[ethernetType].eth_mdc>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdc,nS,10)); } + if (ethernetBoards[ethernetType].eth_mdio>=0) { oappend(","); oappend(itoa(ethernetBoards[ethernetType].eth_mdio,nS,10)); } + switch (ethernetBoards[ethernetType].eth_clk_mode) { + case ETH_CLOCK_GPIO0_IN: + case ETH_CLOCK_GPIO0_OUT: + oappend(SET_F(",0")); + break; + case ETH_CLOCK_GPIO16_OUT: + oappend(SET_F(",16")); + break; + case ETH_CLOCK_GPIO17_OUT: + oappend(SET_F(",17")); + break; + } + } + #endif + + oappend(SET_F("];")); + + // set limits + oappend(SET_F("bLimits(")); + oappend(itoa(WLED_MAX_BUSSES,nS,10)); oappend(","); + oappend(itoa(MAX_LEDS_PER_BUS,nS,10)); oappend(","); + oappend(itoa(MAX_LED_MEMORY,nS,10)); oappend(","); + oappend(itoa(MAX_LEDS,nS,10)); + oappend(SET_F(");")); + + sappend('c',SET_F("MS"),autoSegments); + sappend('c',SET_F("CCT"),correctWB); + sappend('c',SET_F("CR"),cctFromRgb); + sappend('v',SET_F("CB"),strip.cctBlending); + sappend('v',SET_F("FR"),strip.getTargetFps()); + sappend('v',SET_F("AW"),Bus::getAutoWhiteMode()); + + for (uint8_t s=0; s < busses.getNumBusses(); s++) { + Bus* bus = busses.getBus(s); + if (bus == nullptr) continue; + char lp[4] = "L0"; lp[2] = 48+s; lp[3] = 0; //ascii 0-9 //strip data pin + char lc[4] = "LC"; lc[2] = 48+s; lc[3] = 0; //strip length + char co[4] = "CO"; co[2] = 48+s; co[3] = 0; //strip color order + char lt[4] = "LT"; lt[2] = 48+s; lt[3] = 0; //strip type + char ls[4] = "LS"; ls[2] = 48+s; ls[3] = 0; //strip start LED + char cv[4] = "CV"; cv[2] = 48+s; cv[3] = 0; //strip reverse + char sl[4] = "SL"; sl[2] = 48+s; sl[3] = 0; //skip 1st LED + char rf[4] = "RF"; rf[2] = 48+s; rf[3] = 0; //off refresh + oappend(SET_F("addLEDs(1);")); + uint8_t pins[5]; + uint8_t nPins = bus->getPins(pins); + for (uint8_t i = 0; i < nPins; i++) { + lp[1] = 48+i; + if (pinManager.isPinOk(pins[i]) || bus->getType()>=TYPE_NET_DDP_RGB) sappend('v',lp,pins[i]); + } + sappend('v',lc,bus->getLength()); + sappend('v',lt,bus->getType()); + sappend('v',co,bus->getColorOrder()); + sappend('v',ls,bus->getStart()); + sappend('c',cv,bus->reversed); + sappend('c',sl,bus->skippedLeds()); + sappend('c',rf,bus->isOffRefreshRequired()); + } + sappend('v',SET_F("MA"),strip.ablMilliampsMax); + sappend('v',SET_F("LA"),strip.milliampsPerLed); + if (strip.currentMilliamps) + { + sappends('m',SET_F("(\"pow\")[0]"),(char*)""); + olen -= 2; //delete "; + oappendi(strip.currentMilliamps); + oappend(SET_F("mA\";")); + } + + oappend(SET_F("resetCOM(")); + oappend(itoa(WLED_MAX_COLOR_ORDER_MAPPINGS,nS,10)); + oappend(SET_F(");")); + const ColorOrderMap& com = busses.getColorOrderMap(); + for (uint8_t s=0; s < com.count(); s++) { + const ColorOrderMapEntry* entry = com.get(s); + if (entry == nullptr) break; + oappend(SET_F("addCOM(")); + oappend(itoa(entry->start,nS,10)); oappend(","); + oappend(itoa(entry->len,nS,10)); oappend(","); + oappend(itoa(entry->colorOrder,nS,10)); oappend(");"); + } + + sappend('v',SET_F("CA"),briS); + + sappend('c',SET_F("BO"),turnOnAtBoot); + sappend('v',SET_F("BP"),bootPreset); + + sappend('c',SET_F("GB"),strip.gammaCorrectBri); + sappend('c',SET_F("GC"),strip.gammaCorrectCol); + sappend('c',SET_F("TF"),fadeTransition); + sappend('v',SET_F("TD"),transitionDelayDefault); + sappend('c',SET_F("PF"),strip.paletteFade); + sappend('v',SET_F("BF"),briMultiplier); + sappend('v',SET_F("TB"),nightlightTargetBri); + sappend('v',SET_F("TL"),nightlightDelayMinsDefault); + sappend('v',SET_F("TW"),nightlightMode); + sappend('i',SET_F("PB"),strip.paletteBlend); + sappend('v',SET_F("RL"),rlyPin); + sappend('c',SET_F("RM"),rlyMde); + for (uint8_t i=0; i> 4) & 0x0F); + k[0] = 'P'; sappend('v',k,timerMonth[i] & 0x0F); + k[0] = 'D'; sappend('v',k,timerDay[i]); + k[0] = 'E'; sappend('v',k,timerDayEnd[i]); + } + } + } + + if (subPage == 6) + { + sappends('s',SET_F("PIN"),settingsPIN); + sappend('c',SET_F("NO"),otaLock); + sappend('c',SET_F("OW"),wifiLock); + sappend('c',SET_F("AO"),aOtaEnabled); + sappends('m',SET_F("(\"sip\")[0]"),(char*)F("WLED ")); + olen -= 2; //delete "; + oappend(versionString); + oappend(SET_F(" (build ")); + oappendi(VERSION); + oappend(SET_F(")\";")); + } + + #ifdef WLED_ENABLE_DMX // include only if DMX is enabled + if (subPage == 7) + { + sappend('v',SET_F("PU"),e131ProxyUniverse); + + sappend('v',SET_F("CN"),DMXChannels); + sappend('v',SET_F("CG"),DMXGap); + sappend('v',SET_F("CS"),DMXStart); + sappend('v',SET_F("SL"),DMXStartLED); + + sappend('i',SET_F("CH1"),DMXFixtureMap[0]); + sappend('i',SET_F("CH2"),DMXFixtureMap[1]); + sappend('i',SET_F("CH3"),DMXFixtureMap[2]); + sappend('i',SET_F("CH4"),DMXFixtureMap[3]); + sappend('i',SET_F("CH5"),DMXFixtureMap[4]); + sappend('i',SET_F("CH6"),DMXFixtureMap[5]); + sappend('i',SET_F("CH7"),DMXFixtureMap[6]); + sappend('i',SET_F("CH8"),DMXFixtureMap[7]); + sappend('i',SET_F("CH9"),DMXFixtureMap[8]); + sappend('i',SET_F("CH10"),DMXFixtureMap[9]); + sappend('i',SET_F("CH11"),DMXFixtureMap[10]); + sappend('i',SET_F("CH12"),DMXFixtureMap[11]); + sappend('i',SET_F("CH13"),DMXFixtureMap[12]); + sappend('i',SET_F("CH14"),DMXFixtureMap[13]); + sappend('i',SET_F("CH15"),DMXFixtureMap[14]); + } + #endif + + if (subPage == 8) //usermods + { + oappend(SET_F("numM=")); + oappendi(usermods.getModCount()); + oappend(";"); + } +}