diff --git a/package-lock.json b/package-lock.json index ce2e7a46..415d8815 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,9 +54,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", @@ -67,15 +67,10 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "bin": { "acorn": "bin/acorn" }, @@ -190,9 +185,9 @@ } }, "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==" }, "node_modules/balanced-match": { "version": "1.0.2", @@ -233,11 +228,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -701,9 +696,9 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1281,17 +1276,6 @@ "node": ">=0.10.0" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -1375,9 +1359,9 @@ } }, "node_modules/nodemon": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.0.tgz", - "integrity": "sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.7.tgz", + "integrity": "sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==", "dependencies": { "chokidar": "^3.5.2", "debug": "^4", @@ -1402,11 +1386,11 @@ } }, "node_modules/nodemon/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -1418,9 +1402,9 @@ } }, "node_modules/nodemon/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/nodemon/node_modules/supports-color": { "version": "5.5.0", @@ -1433,20 +1417,6 @@ "node": ">=4" } }, - "node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "*" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -1507,6 +1477,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "deprecated": "This package is no longer supported.", "dependencies": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" @@ -1620,6 +1591,7 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", "engines": { "node": ">=0.6.0", "teleport": ">=0.2.0" @@ -1826,12 +1798,9 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "bin": { "semver": "bin/semver.js" }, @@ -1993,9 +1962,9 @@ } }, "node_modules/terser": { - "version": "5.29.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.2.tgz", - "integrity": "sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==", + "version": "5.34.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.34.0.tgz", + "integrity": "sha512-y5NUX+U9HhVsK/zihZwoq4r9dICLyV2jXGOriDAVOeKhq3LKVjgJbGO90FisozXLlJfvjHqgckGmJFBb9KYoWQ==", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -2042,12 +2011,9 @@ } }, "node_modules/touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dependencies": { - "nopt": "~1.0.10" - }, + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", "bin": { "nodetouch": "bin/nodetouch.js" } @@ -2065,9 +2031,9 @@ } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, "node_modules/tunnel-agent": { "version": "0.6.0", @@ -2229,11 +2195,6 @@ "node": ">=0.10.0" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/yargs": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", diff --git a/package.json b/package.json index e47a46b2..721455bf 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,6 @@ "clean-css": "^5.3.3", "html-minifier-terser": "^7.2.0", "inliner": "^1.13.1", - "nodemon": "^3.0.2" + "nodemon": "^3.1.7" } } diff --git a/platformio.ini b/platformio.ini index 4d30be32..3005ba22 100644 --- a/platformio.ini +++ b/platformio.ini @@ -430,7 +430,26 @@ lib_deps = ${esp32_idf_V4.lib_deps} ${esp32.AR_lib_deps} monitor_filters = esp32_exception_decoder board_build.partitions = ${esp32.large_partitions} +board_upload.flash_size = 8MB +board_upload.maximum_size = 8388608 ; board_build.f_flash = 80000000L +; board_build.flash_mode = qio + +[env:esp32dev_16M] +board = esp32dev +platform = ${esp32_idf_V4.platform} +platform_packages = ${esp32_idf_V4.platform_packages} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags} ${esp32_idf_V4.build_flags} -D WLED_RELEASE_NAME=ESP32_16M #-D WLED_DISABLE_BROWNOUT_DET + ${esp32.AR_build_flags} +lib_deps = ${esp32_idf_V4.lib_deps} + ${esp32.AR_lib_deps} +monitor_filters = esp32_exception_decoder +board_build.partitions = ${esp32.extreme_partitions} +board_upload.flash_size = 16MB +board_upload.maximum_size = 16777216 +board_build.f_flash = 80000000L +board_build.flash_mode = dio ;[env:esp32dev_audioreactive] ;board = esp32dev @@ -508,6 +527,8 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -D WLED_RELEASE_NAME= lib_deps = ${esp32s3.lib_deps} ${esp32.AR_lib_deps} board_build.partitions = ${esp32.extreme_partitions} +board_upload.flash_size = 16MB +board_upload.maximum_size = 16777216 board_build.f_flash = 80000000L board_build.flash_mode = qio monitor_filters = esp32_exception_decoder diff --git a/platformio_override.sample.ini b/platformio_override.sample.ini index cf2ee024..861d198b 100644 --- a/platformio_override.sample.ini +++ b/platformio_override.sample.ini @@ -359,6 +359,8 @@ upload_speed = 115200 lib_deps = ${esp32c3.lib_deps} board_build.partitions = tools/WLED_ESP32_2MB_noOTA.csv board_build.flash_mode = dio +board_upload.flash_size = 2MB +board_upload.maximum_size = 2097152 [env:wemos_shield_esp32] board = esp32dev diff --git a/requirements.txt b/requirements.txt index c4ce9445..666122aa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,19 +4,17 @@ # # pip-compile # -aiofiles==22.1.0 - # via platformio ajsonrpc==1.2.0 # via platformio -anyio==3.6.2 +anyio==4.6.0 # via starlette -bottle==0.12.25 +bottle==0.13.1 # via platformio -certifi==2023.7.22 +certifi==2024.8.30 # via requests -charset-normalizer==3.1.0 +charset-normalizer==3.3.2 # via requests -click==8.1.3 +click==8.1.7 # via # platformio # uvicorn @@ -28,35 +26,33 @@ h11==0.14.0 # via # uvicorn # wsproto -idna==3.7 +idna==3.10 # via # anyio # requests -marshmallow==3.19.0 +marshmallow==3.22.0 # via platformio -packaging==23.1 +packaging==24.1 # via marshmallow -platformio==6.1.14 +platformio==6.1.16 # via -r requirements.in -pyelftools==0.29 +pyelftools==0.31 # via platformio pyserial==3.5 # via platformio -requests==2.32.0 +requests==2.32.3 # via platformio semantic-version==2.10.0 # via platformio -sniffio==1.3.0 +sniffio==1.3.1 # via anyio -starlette==0.23.1 +starlette==0.39.1 # via platformio tabulate==0.9.0 # via platformio -typing-extensions==4.11.0 - # via starlette -urllib3==1.26.19 +urllib3==2.2.3 # via requests -uvicorn==0.20.0 +uvicorn==0.30.6 # via platformio wsproto==1.2.0 # via platformio diff --git a/tools/WLED_ESP32_4MB_512KB_FS.csv b/tools/WLED_ESP32_4MB_512KB_FS.csv new file mode 100644 index 00000000..5281a612 --- /dev/null +++ b/tools/WLED_ESP32_4MB_512KB_FS.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x1B0000, +app1, app, ota_1, 0x1C0000,0x1B0000, +spiffs, data, spiffs, 0x370000,0x80000, +coredump, data, coredump,,64K \ No newline at end of file diff --git a/tools/all_xml.sh b/tools/all_xml.sh new file mode 100644 index 00000000..68ed07bb --- /dev/null +++ b/tools/all_xml.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Pull all settings pages for comparison +HOST=$1 +TGT_PATH=$2 +CURL_ARGS="--compressed" + +# Replicate one target many times +function replicate() { + for i in {0..10} + do + echo -n " http://${HOST}/settings.js?p=$i -o ${TGT_PATH}/$i.xml" + done +} +read -a TARGETS <<< $(replicate) + +mkdir -p ${TGT_PATH} +curl ${CURL_ARGS} ${TARGETS[@]} diff --git a/wled00/FX.cpp b/wled00/FX.cpp index ad843f0f..f3e82275 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4931,8 +4931,8 @@ uint16_t mode_2DColoredBursts() { // By: ldirko https://editor.so SEGMENT.fadeToBlackBy(40); for (size_t i = 0; i < numLines; i++) { byte x1 = beatsin8(2 + SEGMENT.speed/16, 0, (cols - 1)); - byte x2 = beatsin8(1 + SEGMENT.speed/16, 0, (cols - 1)); - byte y1 = beatsin8(5 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 24); + byte x2 = beatsin8(1 + SEGMENT.speed/16, 0, (rows - 1)); + byte y1 = beatsin8(5 + SEGMENT.speed/16, 0, (cols - 1), 0, i * 24); byte y2 = beatsin8(3 + SEGMENT.speed/16, 0, (rows - 1), 0, i * 48 + 64); CRGB color = ColorFromPalette(SEGPALETTE, i * 255 / numLines + (SEGENV.aux0&0xFF), 255, LINEARBLEND); @@ -5010,9 +5010,11 @@ uint16_t mode_2DDNASpiral() { // By: ldirko https://editor.soulma // draw a gradient line between x and x1 x = x / 2; x1 = x1 / 2; unsigned steps = abs8(x - x1) + 1; + bool positive = (x1 >= x); // direction of drawing for (size_t k = 1; k <= steps; k++) { unsigned rate = k * 255 / steps; - unsigned dx = lerp8by8(x, x1, rate); + //unsigned dx = lerp8by8(x, x1, rate); + unsigned dx = positive? (x + k-1) : (x - k+1); // behaves the same as "lerp8by8" but does not create holes //SEGMENT.setPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND).nscale8_video(rate)); SEGMENT.addPixelColorXY(dx, i, ColorFromPalette(SEGPALETTE, hue, 255, LINEARBLEND)); // use setPixelColorXY for different look SEGMENT.fadePixelColorXY(dx, i, rate); @@ -7528,8 +7530,9 @@ uint16_t mode_2DAkemi(void) { //add geq left and right if (um_data && fftResult) { - for (int x=0; x < cols/8; x++) { - unsigned band = x * cols/8; + int xMax = cols/8; + for (int x=0; x < xMax; x++) { + unsigned band = map(x, 0, max(xMax,4), 0, 15); // map 0..cols/8 to 16 GEQ bands band = constrain(band, 0, 15); int barHeight = map(fftResult[band], 0, 255, 0, 17*rows/32); CRGB color = CRGB(SEGMENT.color_from_palette((band * 35), false, PALETTE_SOLID_WRAP, 0)); diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 26ec1d60..0f669054 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -704,11 +704,14 @@ void Segment::wu_pixel(uint32_t x, uint32_t y, CRGB c) { //awesome wu_pixel WU_WEIGHT(ix, yy), WU_WEIGHT(xx, yy)}; // multiply the intensities by the colour, and saturating-add them to the pixels for (int i = 0; i < 4; i++) { - CRGB led = getPixelColorXY((x >> 8) + (i & 1), (y >> 8) + ((i >> 1) & 1)); + int wu_x = (x >> 8) + (i & 1); // precalculate x + int wu_y = (y >> 8) + ((i >> 1) & 1); // precalculate y + CRGB led = getPixelColorXY(wu_x, wu_y); + CRGB oldLed = led; led.r = qadd8(led.r, c.r * wu[i] >> 8); led.g = qadd8(led.g, c.g * wu[i] >> 8); led.b = qadd8(led.b, c.b * wu[i] >> 8); - setPixelColorXY(int((x >> 8) + (i & 1)), int((y >> 8) + ((i >> 1) & 1)), led); + if (led != oldLed) setPixelColorXY(wu_x, wu_y, led); // don't repaint if same color } } #undef WU_WEIGHT diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 737d5f7a..1bbfa365 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -1290,7 +1290,7 @@ void WS2812FX::finalizeInit() { // if we have less counts than pins and they do not align, use last known count to set current count unsigned count = defCounts[(i < defNumCounts) ? i : defNumCounts -1]; // analog always has length 1 - if (Bus::isPWM(dataType)) count = 1; + if (Bus::isPWM(dataType) || Bus::isOnOff(dataType)) count = 1; prevLen += count; BusConfig defCfg = BusConfig(dataType, defPin, start, count, DEFAULT_LED_COLOR_ORDER, false, 0, RGBW_MODE_MANUAL_ONLY, 0, useGlobalLedBuffer); if (BusManager::add(defCfg) == -1) break; diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index bf2d30c0..84c32f46 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -766,47 +766,47 @@ class PolyBus { #endif #ifdef ARDUINO_ARCH_ESP32 // RMT buses - case I_32_RN_NEO_3: (static_cast(busPtr))->CanShow(); break; - case I_32_RN_NEO_4: (static_cast(busPtr))->CanShow(); break; - case I_32_RN_400_3: (static_cast(busPtr))->CanShow(); break; - case I_32_RN_TM1_4: (static_cast(busPtr))->CanShow(); break; - case I_32_RN_TM2_3: (static_cast(busPtr))->CanShow(); break; - case I_32_RN_UCS_3: (static_cast(busPtr))->CanShow(); break; - case I_32_RN_UCS_4: (static_cast(busPtr))->CanShow(); break; - case I_32_RN_APA106_3: (static_cast(busPtr))->CanShow(); break; - case I_32_RN_FW6_5: (static_cast(busPtr))->CanShow(); break; - case I_32_RN_2805_5: (static_cast(busPtr))->CanShow(); break; - case I_32_RN_TM1914_3: (static_cast(busPtr))->CanShow(); break; - case I_32_RN_SM16825_5: (static_cast(busPtr))->CanShow(); break; + case I_32_RN_NEO_3: return (static_cast(busPtr))->CanShow(); break; + case I_32_RN_NEO_4: return (static_cast(busPtr))->CanShow(); break; + case I_32_RN_400_3: return (static_cast(busPtr))->CanShow(); break; + case I_32_RN_TM1_4: return (static_cast(busPtr))->CanShow(); break; + case I_32_RN_TM2_3: return (static_cast(busPtr))->CanShow(); break; + case I_32_RN_UCS_3: return (static_cast(busPtr))->CanShow(); break; + case I_32_RN_UCS_4: return (static_cast(busPtr))->CanShow(); break; + case I_32_RN_APA106_3: return (static_cast(busPtr))->CanShow(); break; + case I_32_RN_FW6_5: return (static_cast(busPtr))->CanShow(); break; + case I_32_RN_2805_5: return (static_cast(busPtr))->CanShow(); break; + case I_32_RN_TM1914_3: return (static_cast(busPtr))->CanShow(); break; + case I_32_RN_SM16825_5: return (static_cast(busPtr))->CanShow(); break; // I2S1 bus or paralell buses #ifndef WLED_NO_I2S1_PIXELBUS - case I_32_I1_NEO_3: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break; - case I_32_I1_NEO_4: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break; - case I_32_I1_400_3: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break; - case I_32_I1_TM1_4: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break; - case I_32_I1_TM2_3: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break; - case I_32_I1_UCS_3: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break; - case I_32_I1_UCS_4: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break; - case I_32_I1_APA106_3: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break; - case I_32_I1_FW6_5: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break; - case I_32_I1_2805_5: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break; - case I_32_I1_TM1914_3: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break; - case I_32_I1_SM16825_5: if (useParallelI2S) (static_cast(busPtr))->CanShow(); else (static_cast(busPtr))->CanShow(); break; + case I_32_I1_NEO_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; + case I_32_I1_NEO_4: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; + case I_32_I1_400_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; + case I_32_I1_TM1_4: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; + case I_32_I1_TM2_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; + case I_32_I1_UCS_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; + case I_32_I1_UCS_4: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; + case I_32_I1_APA106_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; + case I_32_I1_FW6_5: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; + case I_32_I1_2805_5: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; + case I_32_I1_TM1914_3: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; + case I_32_I1_SM16825_5: if (useParallelI2S) return (static_cast(busPtr))->CanShow(); else return (static_cast(busPtr))->CanShow(); break; #endif // I2S0 bus #ifndef WLED_NO_I2S0_PIXELBUS - case I_32_I0_NEO_3: (static_cast(busPtr))->CanShow(); break; - case I_32_I0_NEO_4: (static_cast(busPtr))->CanShow(); break; - case I_32_I0_400_3: (static_cast(busPtr))->CanShow(); break; - case I_32_I0_TM1_4: (static_cast(busPtr))->CanShow(); break; - case I_32_I0_TM2_3: (static_cast(busPtr))->CanShow(); break; - case I_32_I0_UCS_3: (static_cast(busPtr))->CanShow(); break; - case I_32_I0_UCS_4: (static_cast(busPtr))->CanShow(); break; - case I_32_I0_APA106_3: (static_cast(busPtr))->CanShow(); break; - case I_32_I0_FW6_5: (static_cast(busPtr))->CanShow(); break; - case I_32_I0_2805_5: (static_cast(busPtr))->CanShow(); break; - case I_32_I0_TM1914_3: (static_cast(busPtr))->CanShow(); break; - case I_32_I0_SM16825_5: (static_cast(busPtr))->CanShow(); break; + case I_32_I0_NEO_3: return (static_cast(busPtr))->CanShow(); break; + case I_32_I0_NEO_4: return (static_cast(busPtr))->CanShow(); break; + case I_32_I0_400_3: return (static_cast(busPtr))->CanShow(); break; + case I_32_I0_TM1_4: return (static_cast(busPtr))->CanShow(); break; + case I_32_I0_TM2_3: return (static_cast(busPtr))->CanShow(); break; + case I_32_I0_UCS_3: return (static_cast(busPtr))->CanShow(); break; + case I_32_I0_UCS_4: return (static_cast(busPtr))->CanShow(); break; + case I_32_I0_APA106_3: return (static_cast(busPtr))->CanShow(); break; + case I_32_I0_FW6_5: return (static_cast(busPtr))->CanShow(); break; + case I_32_I0_2805_5: return (static_cast(busPtr))->CanShow(); break; + case I_32_I0_TM1914_3: return (static_cast(busPtr))->CanShow(); break; + case I_32_I0_SM16825_5: return (static_cast(busPtr))->CanShow(); break; #endif #endif case I_HS_DOT_3: return (static_cast(busPtr))->CanShow(); break; diff --git a/wled00/data/index.css b/wled00/data/index.css index 0952cca2..c4e85f73 100644 --- a/wled00/data/index.css +++ b/wled00/data/index.css @@ -35,6 +35,7 @@ --sgp: "block"; --bmt: 0; --sti: 42px; + --stp: 42px; } html { @@ -468,7 +469,7 @@ button { padding: 4px 2px; position: relative; opacity: 1; - transition: opacity .5s linear, height .25s, transform .25s; + transition: opacity .25s linear, height .2s, transform .2s; } .filter { @@ -1335,10 +1336,12 @@ TD .checkmark, TD .radiomark { top: 42px; } -#fxlist .lstI.selected, -#pallist .lstI.selected { +#fxlist .lstI.selected { top: calc(var(--sti) + 42px); } +#pallist .lstI.selected { + top: calc(var(--stp) + 42px); +} dialog::backdrop { backdrop-filter: blur(10px); @@ -1353,10 +1356,12 @@ dialog { color: var(--c-f); } -#fxlist .lstI.sticky, -#pallist .lstI.sticky { +#fxlist .lstI.sticky { top: var(--sti); } +#pallist .lstI.sticky { + top: var(--stp); +} /* list item content */ .lstIcontent { diff --git a/wled00/data/index.js b/wled00/data/index.js index 25ade116..d9c64bdf 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -2828,7 +2828,12 @@ function search(field, listId = null) { // restore default preset sorting if no search term is entered if (!search) { if (listId === 'pcont') { populatePresets(); return; } - if (listId === 'pallist') { populatePalettes(); return; } + if (listId === 'pallist') { + let id = parseInt(d.querySelector('#pallist input[name="palette"]:checked').value); // preserve selected palette + populatePalettes(); + updateSelectedPalette(id); + return; + } } // clear filter if searching in fxlist @@ -2887,18 +2892,25 @@ function initFilters() { function filterFocus(e) { const f = gId("filters"); - if (e.type === "focus") f.classList.remove('fade'); // immediately show (still has transition) - // compute sticky top (with delay for transition) - setTimeout(() => { - const sti = parseInt(getComputedStyle(d.documentElement).getPropertyValue('--sti')) + (e.type === "focus" ? 1 : -1) * f.offsetHeight; - sCol('--sti', sti + "px"); - }, 252); + const c = !!f.querySelectorAll("input[type=checkbox]:checked").length; + const h = f.offsetHeight; + const sti = parseInt(getComputedStyle(d.documentElement).getPropertyValue('--sti')); + if (e.type === "focus") { + // compute sticky top (with delay for transition) + if (!h) setTimeout(() => { + sCol('--sti', (sti+f.offsetHeight) + "px"); // has an unpleasant consequence on palette offset + }, 255); + f.classList.remove('fade'); // immediately show (still has transition) + } if (e.type === "blur") { setTimeout(() => { if (e.target === document.activeElement && document.hasFocus()) return; // do not hide if filter is active - if (gId("filters").querySelectorAll("input[type=checkbox]:checked").length) return; - f.classList.add('fade'); + if (!c) { + // compute sticky top + sCol('--sti', (sti-h) + "px"); // has an unpleasant consequence on palette offset + f.classList.add('fade'); + } }, 255); // wait with hiding } } @@ -2911,7 +2923,7 @@ function filterFx() { gId("fxlist").querySelectorAll('.lstI').forEach((listItem,i) => { const listItemName = listItem.querySelector('.lstIname').innerText; let hide = false; - gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = true; }); + gId("filters").querySelectorAll("input[type=checkbox]").forEach((e) => { if (e.checked && !listItemName.includes(e.dataset.flt)) hide = i>0 /*true*/; }); listItem.style.display = hide ? 'none' : ''; }); } diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 8903d1f2..71b00599 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -302,7 +302,7 @@ class Usermod { virtual bool handleButton(uint8_t b) { return false; } // button overrides are possible here virtual bool getUMData(um_data_t **data) { if (data) *data = nullptr; return false; }; // usermod data exchange [see examples for audio effects] virtual void connected() {} // called when WiFi is (re)connected - virtual void appendConfigData() {} // helper function called from usermod settings page to add metadata for entry fields + virtual void appendConfigData(Print& settingsScript); // helper function called from usermod settings page to add metadata for entry fields virtual void addToJsonState(JsonObject& obj) {} // add JSON objects for WLED state virtual void addToJsonInfo(JsonObject& obj) {} // add JSON objects for UI Info page virtual void readFromJsonState(JsonObject& obj) {} // process JSON messages received from web server @@ -314,6 +314,16 @@ class Usermod { virtual void onUpdateBegin(bool) {} // fired prior to and after unsuccessful firmware update virtual void onStateChange(uint8_t mode) {} // fired upon WLED state change virtual uint16_t getId() {return USERMOD_ID_UNSPECIFIED;} + + // API shims + private: + static Print* oappend_shim; + // old form of appendConfigData; called by default appendConfigData(Print&) with oappend_shim set up + // private so it is not accidentally invoked except via Usermod::appendConfigData(Print&) + virtual void appendConfigData() {} + protected: + // Shim for oappend(), which used to exist in utils.cpp + template static inline void oappend(const T& t) { oappend_shim->print(t); }; }; class UsermodManager { @@ -328,7 +338,7 @@ class UsermodManager { static bool getUMData(um_data_t **um_data, uint8_t mod_id = USERMOD_ID_RESERVED); // USERMOD_ID_RESERVED will poll all usermods static void setup(); static void connected(); - static void appendConfigData(); + static void appendConfigData(Print&); static void addToJsonState(JsonObject& obj); static void addToJsonInfo(JsonObject& obj); static void readFromJsonState(JsonObject& obj); @@ -362,10 +372,11 @@ void parseNumber(const char* str, byte* val, byte minv=0, byte maxv=255); bool getVal(JsonVariant elem, byte* val, byte minv=0, byte maxv=255); bool getBoolVal(JsonVariant elem, bool dflt); bool updateVal(const char* req, const char* key, byte* val, byte minv=0, byte maxv=255); -bool oappend(const char* txt); // append new c string to temp buffer efficiently -bool oappendi(int i); // append new number to temp buffer efficiently -void sappend(char stype, const char* key, int val); -void sappends(char stype, const char* key, char* val); +size_t printSetFormCheckbox(Print& settingsScript, const char* key, int val); +size_t printSetFormValue(Print& settingsScript, const char* key, int val); +size_t printSetFormValue(Print& settingsScript, const char* key, const char* val); +size_t printSetFormIndex(Print& settingsScript, const char* key, int index); +size_t printSetClassElementHTML(Print& settingsScript, const char* key, const int index, const char* val); void prepareHostname(char* hostname); bool isAsterisksOnly(const char* str, byte maxLen); bool requestJSONBufferLock(uint8_t module=255); @@ -444,7 +455,7 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp void sendDataWs(AsyncWebSocketClient * client = nullptr); //xml.cpp -void XML_response(AsyncWebServerRequest *request, char* dest = nullptr); -void getSettingsJS(byte subPage, char* dest); +void XML_response(Print& dest); +void getSettingsJS(byte subPage, Print& dest); #endif diff --git a/wled00/file.cpp b/wled00/file.cpp index 69e1e692..bc346720 100644 --- a/wled00/file.cpp +++ b/wled00/file.cpp @@ -433,7 +433,7 @@ bool handleFileRead(AsyncWebServerRequest* request, String path){ } #endif if(WLED_FS.exists(path) || WLED_FS.exists(path + ".gz")) { - request->send(WLED_FS, path, String(), request->hasArg(F("download"))); + request->send(request->beginResponse(WLED_FS, path, {}, request->hasArg(F("download")), {})); return true; } return false; diff --git a/wled00/improv.cpp b/wled00/improv.cpp index abfd463c..31547f86 100644 --- a/wled00/improv.cpp +++ b/wled00/improv.cpp @@ -123,6 +123,7 @@ void handleImprovPacket() { } checksum += next; + checksum &= 0xFF; packetByte++; } } diff --git a/wled00/mqtt.cpp b/wled00/mqtt.cpp index 6c523c3e..a476db87 100644 --- a/wled00/mqtt.cpp +++ b/wled00/mqtt.cpp @@ -124,6 +124,32 @@ static void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProp payloadStr = nullptr; } +// Print adapter for flat buffers +namespace { +class bufferPrint : public Print { + char* _buf; + size_t _size, _offset; + public: + + bufferPrint(char* buf, size_t size) : _buf(buf), _size(size), _offset(0) {}; + + size_t write(const uint8_t *buffer, size_t size) { + size = std::min(size, _size - _offset); + memcpy(_buf + _offset, buffer, size); + _offset += size; + return size; + } + + size_t write(uint8_t c) { + return this->write(&c, 1); + } + + char* data() const { return _buf; } + size_t size() const { return _offset; } + size_t capacity() const { return _size; } +}; +}; // anonymous namespace + void publishMqtt() { @@ -148,11 +174,13 @@ void publishMqtt() strcat_P(subuf, PSTR("/status")); mqtt->publish(subuf, 0, true, "online"); // retain message for a LWT - char apires[1024]; // allocating 1024 bytes from stack can be risky - XML_response(nullptr, apires); + // TODO: use a DynamicBufferList. Requires a list-read-capable MQTT client API. + DynamicBuffer buf(1024); + bufferPrint pbuf(buf.data(), buf.size()); + XML_response(pbuf); strlcpy(subuf, mqttDeviceTopic, 33); strcat_P(subuf, PSTR("/v")); - mqtt->publish(subuf, 0, retainMqttMsg, apires); // optionally retain message (#2263) + mqtt->publish(subuf, 0, retainMqttMsg, buf.data(), pbuf.size()); // optionally retain message (#2263) #endif } diff --git a/wled00/set.cpp b/wled00/set.cpp index 47bb6482..69f48735 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -1191,7 +1191,11 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply) // internal call, does not send XML response pos = req.indexOf(F("IN")); - if (pos < 1) XML_response(request); + if (pos < 1) { + auto response = request->beginResponseStream("text/xml"); + XML_response(*response); + request->send(response); + } return true; } diff --git a/wled00/udp.cpp b/wled00/udp.cpp index 09e1440e..60774d70 100644 --- a/wled00/udp.cpp +++ b/wled00/udp.cpp @@ -974,10 +974,8 @@ void espNowReceiveCB(uint8_t* address, uint8_t* data, uint8_t len, signed int rs DEBUG_PRINTLN(); #endif -#ifndef WLED_DISABLE_ESPNOW // usermods hook can override processing if (UsermodManager::onEspNowMessage(address, data, len)) return; -#endif // handle WiZ Mote data if (data[0] == 0x91 || data[0] == 0x81 || data[0] == 0x80) { diff --git a/wled00/um_manager.cpp b/wled00/um_manager.cpp index d4ed8135..46fdf5b3 100644 --- a/wled00/um_manager.cpp +++ b/wled00/um_manager.cpp @@ -8,7 +8,7 @@ void UsermodManager::setup() { for (unsigned i = 0; i < numMods; i++ void UsermodManager::connected() { for (unsigned i = 0; i < numMods; i++) ums[i]->connected(); } void UsermodManager::loop() { for (unsigned i = 0; i < numMods; i++) ums[i]->loop(); } void UsermodManager::handleOverlayDraw() { for (unsigned i = 0; i < numMods; i++) ums[i]->handleOverlayDraw(); } -void UsermodManager::appendConfigData() { for (unsigned i = 0; i < numMods; i++) ums[i]->appendConfigData(); } +void UsermodManager::appendConfigData(Print& dest) { for (unsigned i = 0; i < numMods; i++) ums[i]->appendConfigData(dest); } bool UsermodManager::handleButton(uint8_t b) { bool overrideIO = false; for (unsigned i = 0; i < numMods; i++) { @@ -71,3 +71,13 @@ bool UsermodManager::add(Usermod* um) Usermod* UsermodManager::ums[WLED_MAX_USERMODS] = {nullptr}; byte UsermodManager::numMods = 0; + +/* Usermod v2 interface shim for oappend */ +Print* Usermod::oappend_shim = nullptr; + +void Usermod::appendConfigData(Print& settingsScript) { + assert(!oappend_shim); + oappend_shim = &settingsScript; + this->appendConfigData(); + oappend_shim = nullptr; +} diff --git a/wled00/util.cpp b/wled00/util.cpp index 99a75bdd..0b78a464 100644 --- a/wled00/util.cpp +++ b/wled00/util.cpp @@ -87,90 +87,30 @@ bool updateVal(const char* req, const char* key, byte* val, byte minv, byte maxv return true; } - -//append a numeric setting to string buffer -void sappend(char stype, const char* key, int val) -{ - char ds[] = "d.Sf."; - - switch(stype) - { - case 'c': //checkbox - oappend(ds); - oappend(key); - oappend(".checked="); - oappendi(val); - oappend(";"); - break; - case 'v': //numeric - oappend(ds); - oappend(key); - oappend(".value="); - oappendi(val); - oappend(";"); - break; - case 'i': //selectedIndex - oappend(ds); - oappend(key); - oappend(SET_F(".selectedIndex=")); - oappendi(val); - oappend(";"); - break; - } +static size_t printSetFormInput(Print& settingsScript, const char* key, const char* selector, int value) { + return settingsScript.printf_P(PSTR("d.Sf.%s.%s=%d;"), key, selector, value); } - -//append a string setting to buffer -void sappends(char stype, const char* key, char* val) -{ - switch(stype) - { - case 's': {//string (we can interpret val as char*) - String buf = val; - //convert "%" to "%%" to make EspAsyncWebServer happy - //buf.replace("%","%%"); - oappend("d.Sf."); - oappend(key); - oappend(".value=\""); - oappend(buf.c_str()); - oappend("\";"); - break;} - case 'm': //message - oappend(SET_F("d.getElementsByClassName")); - oappend(key); - oappend(SET_F(".innerHTML=\"")); - oappend(val); - oappend("\";"); - break; - } +size_t printSetFormCheckbox(Print& settingsScript, const char* key, int val) { + return printSetFormInput(settingsScript, key, PSTR("checked"), val); +} +size_t printSetFormValue(Print& settingsScript, const char* key, int val) { + return printSetFormInput(settingsScript, key, PSTR("value"), val); +} +size_t printSetFormIndex(Print& settingsScript, const char* key, int index) { + return printSetFormInput(settingsScript, key, PSTR("selectedIndex"), index); } - -bool oappendi(int i) -{ - char s[12]; // 32bit signed number can have 10 digits plus - sign - sprintf(s, "%d", i); - return oappend(s); +size_t printSetFormValue(Print& settingsScript, const char* key, const char* val) { + return settingsScript.printf_P(PSTR("d.Sf.%s.value=\"%s\";"),key,val); } - -bool oappend(const char* txt) -{ - unsigned len = strlen(txt); - if ((obuf == nullptr) || (olen + len >= SETTINGS_STACK_BUF_SIZE)) { // sanity checks -#ifdef WLED_DEBUG - DEBUG_PRINT(F("oappend() buffer overflow. Cannot append ")); - DEBUG_PRINT(len); DEBUG_PRINT(F(" bytes \t\"")); - DEBUG_PRINT(txt); DEBUG_PRINTLN(F("\"")); -#endif - return false; // buffer full - } - strcpy(obuf + olen, txt); - olen += len; - return true; +size_t printSetClassElementHTML(Print& settingsScript, const char* key, const int index, const char* val) { + return settingsScript.printf_P(PSTR("d.getElementsByClassName(\"%s\")[%d].innerHTML=\"%s\";"), key, index, val); } + void prepareHostname(char* hostname) { sprintf_P(hostname, PSTR("wled-%*s"), 6, escapedMac.c_str() + 6); diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 39e0d250..13d43218 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -219,6 +219,7 @@ void WLED::loop() busConfigs[i] = nullptr; } strip.finalizeInit(); // also loads default ledmap if present + BusManager::setBrightness(bri); // fix re-initialised bus' brightness #4005 if (aligned) strip.makeAutoSegments(); else strip.fixInvalidSegments(); doSerializeConfig = true; diff --git a/wled00/wled.h b/wled00/wled.h index 31a61285..052f29b2 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -839,10 +839,6 @@ WLED_GLOBAL time_t sunrise _INIT(0); WLED_GLOBAL time_t sunset _INIT(0); WLED_GLOBAL Toki toki _INIT(Toki()); -// Temp buffer -WLED_GLOBAL char* obuf; -WLED_GLOBAL uint16_t olen _INIT(0); - // General filesystem WLED_GLOBAL size_t fsBytesUsed _INIT(0); WLED_GLOBAL size_t fsBytesTotal _INIT(0); diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index 7d6fecd8..958b5133 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -520,27 +520,23 @@ void serveSettingsJS(AsyncWebServerRequest* request) handleStaticContent(request, FPSTR(_common_js), 200, FPSTR(CONTENT_TYPE_JAVASCRIPT), JS_common, JS_common_length); return; } - char buf[SETTINGS_STACK_BUF_SIZE+37]; - buf[0] = 0; byte subPage = request->arg(F("p")).toInt(); if (subPage > 10) { - strcpy_P(buf, PSTR("alert('Settings for this request are not implemented.');")); - request->send(501, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf); + request->send_P(501, FPSTR(CONTENT_TYPE_JAVASCRIPT), PSTR("alert('Settings for this request are not implemented.');")); return; } if (subPage > 0 && !correctPIN && strlen(settingsPIN)>0) { - strcpy_P(buf, PSTR("alert('PIN incorrect.');")); - request->send(401, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf); + request->send_P(401, FPSTR(CONTENT_TYPE_JAVASCRIPT), PSTR("alert('PIN incorrect.');")); return; } - strcat_P(buf,PSTR("function GetV(){var d=document;")); - getSettingsJS(subPage, buf+strlen(buf)); // this may overflow by 35bytes!!! - strcat_P(buf,PSTR("}")); - AsyncWebServerResponse *response; - response = request->beginResponse(200, FPSTR(CONTENT_TYPE_JAVASCRIPT), buf); + AsyncResponseStream *response = request->beginResponseStream(FPSTR(CONTENT_TYPE_JAVASCRIPT)); response->addHeader(F("Cache-Control"), F("no-store")); response->addHeader(F("Expires"), F("0")); + + response->print(F("function GetV(){var d=document;")); + getSettingsJS(subPage, *response); + response->print(F("}")); request->send(response); } diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 27c6b4ac..b1349fb6 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -6,85 +6,39 @@ */ //build XML response to HTTP /win API request -void XML_response(AsyncWebServerRequest *request, char* dest) +void XML_response(Print& 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("")); - + dest.printf_P(PSTR("%d"), (nightlightActive && nightlightMode > NL_MODE_SET) ? briT : bri); for (int i = 0; i < 3; i++) { - oappend(""); - oappendi(col[i]); - oappend(""); + dest.printf_P(PSTR("%d"), col[i]); } for (int i = 0; i < 3; i++) { - oappend(""); - oappendi(colSec[i]); - oappend(""); + dest.printf_P(PSTR("%d"), colSec[i]); } - oappend(SET_F("")); - oappendi(notifyDirect); - oappend(SET_F("")); - oappendi(receiveGroups!=0); - 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); + dest.printf_P(PSTR("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%s%s%d"), + notifyDirect, receiveGroups!=0, nightlightActive, nightlightMode > NL_MODE_SET, nightlightDelayMins, + nightlightTargetBri, effectCurrent, effectSpeed, effectIntensity, effectPalette, + strip.hasWhiteChannel() ? col[3] : -1, colSec[3], currentPreset, currentPlaylist >= 0, + serverDescription, realtimeMode ? PSTR(" (live)") : "", + strip.getFirstSelectedSegId() + ); } -void extractPin(JsonObject &obj, const char *key) { +static void extractPin(Print& settingsScript, 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()); } + if (pv.as() > -1) { settingsScript.print(","); settingsScript.print(pv.as()); } } } else { - if (obj[key].as() > -1) { oappend(","); oappendi(obj[key].as()); } + if (obj[key].as() > -1) { settingsScript.print(","); settingsScript.print(obj[key].as()); } } } -// oappend used pins by scanning JsonObject (1 level deep) -void fillUMPins(JsonObject &mods) +// print used pins by scanning JsonObject (1 level deep) +static void fillUMPins(Print& settingsScript, JsonObject &mods) { for (JsonPair kv : mods) { // kv.key() is usermod name or subobject key @@ -93,7 +47,7 @@ void fillUMPins(JsonObject &mods) if (!obj.isNull()) { // element is an JsonObject if (!obj["pin"].isNull()) { - extractPin(obj, "pin"); + extractPin(settingsScript, obj, "pin"); } else { // scan keys (just one level deep as is possible with usermods) for (JsonPair so : obj) { @@ -102,7 +56,7 @@ void fillUMPins(JsonObject &mods) // 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); + extractPin(settingsScript, obj, key); continue; } } @@ -110,7 +64,7 @@ void fillUMPins(JsonObject &mods) JsonObject subObj = obj[so.key()]; if (!subObj["pin"].isNull()) { // get pins from subobject - extractPin(subObj, "pin"); + extractPin(settingsScript, subObj, "pin"); } } } @@ -118,167 +72,152 @@ void fillUMPins(JsonObject &mods) } } -void appendGPIOinfo() { - char nS[8]; - - // add usermod pins as d.um_p array - oappend(SET_F("d.um_p=[-1")); // has to have 1 element +void appendGPIOinfo(Print& settingsScript) { + settingsScript.print(F("d.um_p=[-1")); // has to have 1 element if (i2c_sda > -1 && i2c_scl > -1) { - oappend(","); oappend(itoa(i2c_sda,nS,10)); - oappend(","); oappend(itoa(i2c_scl,nS,10)); + settingsScript.printf_P(PSTR(",%d,%d"), i2c_sda, i2c_scl); } if (spi_mosi > -1 && spi_sclk > -1) { - oappend(","); oappend(itoa(spi_mosi,nS,10)); - oappend(","); oappend(itoa(spi_sclk,nS,10)); + settingsScript.printf_P(PSTR(",%d,%d"), spi_mosi, spi_sclk); } // usermod pin reservations will become unnecessary when settings pages will read cfg.json directly if (requestJSONBufferLock(6)) { // if we can't allocate JSON buffer ignore usermod pins JsonObject mods = pDoc->createNestedObject(F("um")); UsermodManager::addToConfig(mods); - if (!mods.isNull()) fillUMPins(mods); + if (!mods.isNull()) fillUMPins(settingsScript, mods); releaseJSONBufferLock(); } - oappend(SET_F("];")); + settingsScript.print(F("];")); // add reserved (unusable) pins - oappend(SET_F("d.rsvd=[")); + settingsScript.print(F("d.rsvd=[")); for (unsigned i = 0; i < WLED_NUM_PINS; i++) { if (!PinManager::isPinOk(i, false)) { // include readonly pins - oappendi(i); oappend(","); + settingsScript.print(i); settingsScript.print(","); } } #ifdef WLED_ENABLE_DMX - oappend(SET_F("2,")); // DMX hardcoded pin + settingsScript.print(F("2,")); // DMX hardcoded pin #endif #if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST) - oappend(itoa(hardwareTX,nS,10)); oappend(","); // debug output (TX) pin + settingsScript.printf_P(PSTR(",%d"),hardwareTX); // debug output (TX) pin #endif //Note: Using pin 3 (RX) disables Adalight / Serial JSON #ifdef WLED_USE_ETHERNET if (ethernetType != WLED_ETH_NONE && ethernetType < WLED_NUM_ETH_TYPES) { - for (unsigned p=0; p=0) { oappend(itoa(ethernetBoards[ethernetType].eth_power,nS,10)); oappend(","); } - if (ethernetBoards[ethernetType].eth_mdc>=0) { oappend(itoa(ethernetBoards[ethernetType].eth_mdc,nS,10)); oappend(","); } - if (ethernetBoards[ethernetType].eth_mdio>=0) { oappend(itoa(ethernetBoards[ethernetType].eth_mdio,nS,10)); oappend(","); } - switch (ethernetBoards[ethernetType].eth_clk_mode) { + for (unsigned p=0; p=0) { settingsScript.printf(",%d", ethernetBoards[ethernetType].eth_power); } + if (ethernetBoards[ethernetType].eth_mdc>=0) { settingsScript.printf(",%d", ethernetBoards[ethernetType].eth_mdc); } + if (ethernetBoards[ethernetType].eth_mdio>=0) { settingsScript.printf(",%d", ethernetBoards[ethernetType].eth_mdio); } + switch (ethernetBoards[ethernetType].eth_clk_mode) { case ETH_CLOCK_GPIO0_IN: case ETH_CLOCK_GPIO0_OUT: - oappend(SET_F("0")); + settingsScript.print(F("0")); break; case ETH_CLOCK_GPIO16_OUT: - oappend(SET_F("16")); + settingsScript.print(F("16")); break; case ETH_CLOCK_GPIO17_OUT: - oappend(SET_F("17")); + settingsScript.print(F("17")); break; } } #endif - oappend(SET_F("];")); // rsvd + settingsScript.print(F("];")); // rsvd // add info for read-only GPIO - oappend(SET_F("d.ro_gpio=[")); + settingsScript.print(F("d.ro_gpio=[")); bool firstPin = true; for (unsigned i = 0; i < WLED_NUM_PINS; i++) { if (PinManager::isReadOnlyPin(i)) { // No comma before the first pin - if (!firstPin) oappend(SET_F(",")); - oappendi(i); + if (!firstPin) settingsScript.print(F(",")); + settingsScript.print(i); firstPin = false; } } - oappend(SET_F("];")); + settingsScript.print(F("];")); // add info about max. # of pins - oappend(SET_F("d.max_gpio=")); - oappendi(WLED_NUM_PINS); - oappend(SET_F(";")); + settingsScript.print(F("d.max_gpio=")); + settingsScript.print(WLED_NUM_PINS); + settingsScript.print(F(";")); } //get values for settings form in javascript -void getSettingsJS(byte subPage, char* dest) +void getSettingsJS(byte subPage, Print& settingsScript) { //0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec DEBUG_PRINTF_P(PSTR("settings resp %u\n"), (unsigned)subPage); - obuf = dest; - olen = 0; if (subPage <0 || subPage >10) return; if (subPage == SUBPAGE_MENU) { #ifdef WLED_DISABLE_2D // include only if 2D is not compiled in - oappend(PSTR("gId('2dbtn').style.display='none';")); + settingsScript.print(F("gId('2dbtn').style.display='none';")); #endif #ifdef WLED_ENABLE_DMX // include only if DMX is enabled - oappend(PSTR("gId('dmxbtn').style.display='';")); + settingsScript.print(F("gId('dmxbtn').style.display='';")); #endif } if (subPage == SUBPAGE_WIFI) { - char nS[10]; size_t l; - oappend(SET_F("resetWiFi(")); - oappend(itoa(WLED_MAX_WIFI_COUNT,nS,10)); - oappend(SET_F(");")); + settingsScript.printf_P(PSTR("resetWiFi(%d);"), WLED_MAX_WIFI_COUNT); for (size_t n = 0; n < multiWiFi.size(); n++) { l = strlen(multiWiFi[n].clientPass); char fpass[l+1]; //fill password field with *** fpass[l] = 0; memset(fpass,'*',l); - oappend(SET_F("addWiFi(\"")); - oappend(multiWiFi[n].clientSSID); - oappend(SET_F("\",\"")); - oappend(fpass); - oappend(SET_F("\",0x")); - oappend(itoa(multiWiFi[n].staticIP,nS,16)); - oappend(SET_F(",0x")); - oappend(itoa(multiWiFi[n].staticGW,nS,16)); - oappend(SET_F(",0x")); - oappend(itoa(multiWiFi[n].staticSN,nS,16)); - oappend(SET_F(");")); + settingsScript.printf_P(PSTR("addWiFi(\"%s\",\",%s\",0x%X,0x%X,0x%X);"), + multiWiFi[n].clientSSID, + fpass, + (uint32_t) multiWiFi[n].staticIP, // explicit cast required as this is a struct + (uint32_t) multiWiFi[n].staticGW, + (uint32_t) multiWiFi[n].staticSN); } - sappend('v',SET_F("D0"),dnsAddress[0]); - sappend('v',SET_F("D1"),dnsAddress[1]); - sappend('v',SET_F("D2"),dnsAddress[2]); - sappend('v',SET_F("D3"),dnsAddress[3]); + printSetFormValue(settingsScript,PSTR("D0"),dnsAddress[0]); + printSetFormValue(settingsScript,PSTR("D1"),dnsAddress[1]); + printSetFormValue(settingsScript,PSTR("D2"),dnsAddress[2]); + printSetFormValue(settingsScript,PSTR("D3"),dnsAddress[3]); - sappends('s',SET_F("CM"),cmDNS); - sappend('i',SET_F("AB"),apBehavior); - sappends('s',SET_F("AS"),apSSID); - sappend('c',SET_F("AH"),apHide); + printSetFormValue(settingsScript,PSTR("CM"),cmDNS); + printSetFormIndex(settingsScript,PSTR("AB"),apBehavior); + printSetFormValue(settingsScript,PSTR("AS"),apSSID); + printSetFormCheckbox(settingsScript,PSTR("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); + printSetFormValue(settingsScript,PSTR("AP"),fapass); - sappend('v',SET_F("AC"),apChannel); + printSetFormValue(settingsScript,PSTR("AC"),apChannel); #ifdef ARDUINO_ARCH_ESP32 - sappend('v',SET_F("TX"),txPower); + printSetFormValue(settingsScript,PSTR("TX"),txPower); #else - oappend(SET_F("gId('tx').style.display='none';")); + settingsScript.print(F("gId('tx').style.display='none';")); #endif - sappend('c',SET_F("FG"),force802_3g); - sappend('c',SET_F("WS"),noWifiSleep); + printSetFormCheckbox(settingsScript,PSTR("FG"),force802_3g); + printSetFormCheckbox(settingsScript,PSTR("WS"),noWifiSleep); #ifndef WLED_DISABLE_ESPNOW - sappend('c',SET_F("RE"),enableESPNow); - sappends('s',SET_F("RMAC"),linked_remote); + printSetFormCheckbox(settingsScript,PSTR("RE"),enableESPNow); + printSetFormValue(settingsScript,PSTR("RMAC"),linked_remote); #else //hide remote settings if not compiled - oappend(SET_F("toggle('ESPNOW');")); // hide ESP-NOW setting + settingsScript.print(F("toggle('ESPNOW');")); // hide ESP-NOW setting #endif #ifdef WLED_USE_ETHERNET - sappend('v',SET_F("ETH"),ethernetType); + printSetFormValue(settingsScript,PSTR("ETH"),ethernetType); #else //hide ethernet setting if not compiled in - oappend(SET_F("gId('ethd').style.display='none';")); + settingsScript.print(F("gId('ethd').style.display='none';")); #endif if (Network.isConnected()) //is connected @@ -290,10 +229,10 @@ void getSettingsJS(byte subPage, char* dest) #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); + printSetClassElementHTML(settingsScript,PSTR("sip"),0,s); } else { - sappends('m',SET_F("(\"sip\")[0]"),(char*)F("Not connected")); + printSetClassElementHTML(settingsScript,PSTR("sip"),0,(char*)F("Not connected")); } if (WiFi.softAPIP()[0] != 0) //is active @@ -301,19 +240,19 @@ void getSettingsJS(byte subPage, char* dest) 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); + printSetClassElementHTML(settingsScript,PSTR("sip"),1,s); } else { - sappends('m',SET_F("(\"sip\")[1]"),(char*)F("Not active")); + printSetClassElementHTML(settingsScript,PSTR("sip"),1,(char*)F("Not active")); } #ifndef WLED_DISABLE_ESPNOW if (strlen(last_signal_src) > 0) { //Have seen an ESP-NOW Remote - sappends('m',SET_F("(\"rlid\")[0]"),last_signal_src); + printSetClassElementHTML(settingsScript,PSTR("rlid"),0,last_signal_src); } else if (!enableESPNow) { - sappends('m',SET_F("(\"rlid\")[0]"),(char*)F("(Enable ESP-NOW to listen)")); + printSetClassElementHTML(settingsScript,PSTR("rlid"),0,(char*)F("(Enable ESP-NOW to listen)")); } else { - sappends('m',SET_F("(\"rlid\")[0]"),(char*)F("None")); + printSetClassElementHTML(settingsScript,PSTR("rlid"),0,(char*)F("None")); } #endif } @@ -322,30 +261,30 @@ void getSettingsJS(byte subPage, char* dest) { char nS[32]; - appendGPIOinfo(); + appendGPIOinfo(settingsScript); - oappend(SET_F("d.ledTypes=")); oappend(BusManager::getLEDTypesJSONString().c_str()); oappend(";"); + settingsScript.print(F("d.ledTypes=")); settingsScript.print(BusManager::getLEDTypesJSONString().c_str()); settingsScript.print(";"); // set limits - oappend(SET_F("bLimits(")); - oappend(itoa(WLED_MAX_BUSSES,nS,10)); oappend(","); - oappend(itoa(WLED_MIN_VIRTUAL_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(","); - oappend(itoa(WLED_MAX_COLOR_ORDER_MAPPINGS,nS,10)); oappend(","); - oappend(itoa(WLED_MAX_DIGITAL_CHANNELS,nS,10)); oappend(","); - oappend(itoa(WLED_MAX_ANALOG_CHANNELS,nS,10)); - oappend(SET_F(");")); + settingsScript.printf_P(PSTR("bLimits(%d,%d,%d,%d,%d,%d,%d,%d);"), + WLED_MAX_BUSSES, + WLED_MIN_VIRTUAL_BUSSES, + MAX_LEDS_PER_BUS, + MAX_LED_MEMORY, + MAX_LEDS, + WLED_MAX_COLOR_ORDER_MAPPINGS, + WLED_MAX_DIGITAL_CHANNELS, + WLED_MAX_ANALOG_CHANNELS + ); - sappend('c',SET_F("MS"),strip.autoSegments); - sappend('c',SET_F("CCT"),strip.correctWB); - sappend('c',SET_F("IC"),cctICused); - sappend('c',SET_F("CR"),strip.cctFromRgb); - sappend('v',SET_F("CB"),strip.cctBlending); - sappend('v',SET_F("FR"),strip.getTargetFps()); - sappend('v',SET_F("AW"),Bus::getGlobalAWMode()); - sappend('c',SET_F("LD"),useGlobalLedBuffer); + printSetFormCheckbox(settingsScript,PSTR("MS"),strip.autoSegments); + printSetFormCheckbox(settingsScript,PSTR("CCT"),strip.correctWB); + printSetFormCheckbox(settingsScript,PSTR("IC"),cctICused); + printSetFormCheckbox(settingsScript,PSTR("CR"),strip.cctFromRgb); + printSetFormValue(settingsScript,PSTR("CB"),strip.cctBlending); + printSetFormValue(settingsScript,PSTR("FR"),strip.getTargetFps()); + printSetFormValue(settingsScript,PSTR("AW"),Bus::getGlobalAWMode()); + printSetFormCheckbox(settingsScript,PSTR("LD"),useGlobalLedBuffer); unsigned sumMa = 0; for (int s = 0; s < BusManager::getNumBusses(); s++) { @@ -365,22 +304,22 @@ void getSettingsJS(byte subPage, char* dest) char sp[4] = "SP"; sp[2] = offset+s; sp[3] = 0; //bus clock speed char la[4] = "LA"; la[2] = offset+s; la[3] = 0; //LED current char ma[4] = "MA"; ma[2] = offset+s; ma[3] = 0; //max per-port PSU current - oappend(SET_F("addLEDs(1);")); + settingsScript.print(F("addLEDs(1);")); uint8_t pins[OUTPUT_MAX_PINS]; int nPins = bus->getPins(pins); for (int i = 0; i < nPins; i++) { lp[1] = offset+i; - if (PinManager::isPinOk(pins[i]) || bus->isVirtual() || bus->isHub75()) sappend('v',lp,pins[i]); + if (PinManager::isPinOk(pins[i]) || bus->isVirtual() || bus->isHub75()) printSetFormValue(settingsScript,lp,pins[i]); } - sappend('v',lc,bus->getLength()); - sappend('v',lt,bus->getType()); - sappend('v',co,bus->getColorOrder() & 0x0F); - sappend('v',ls,bus->getStart()); - sappend('c',cv,bus->isReversed()); - sappend('v',sl,bus->skippedLeds()); - sappend('c',rf,bus->isOffRefreshRequired()); - sappend('v',aw,bus->getAutoWhiteMode()); - sappend('v',wo,bus->getColorOrder() >> 4); + printSetFormValue(settingsScript,lc,bus->getLength()); + printSetFormValue(settingsScript,lt,bus->getType()); + printSetFormValue(settingsScript,co,bus->getColorOrder() & 0x0F); + printSetFormValue(settingsScript,ls,bus->getStart()); + printSetFormCheckbox(settingsScript,cv,bus->isReversed()); + printSetFormValue(settingsScript,sl,bus->skippedLeds()); + printSetFormCheckbox(settingsScript,rf,bus->isOffRefreshRequired()); + printSetFormValue(settingsScript,aw,bus->getAutoWhiteMode()); + printSetFormValue(settingsScript,wo,bus->getColorOrder() >> 4); unsigned speed = bus->getFrequency(); if (bus->isPWM()) { switch (speed) { @@ -401,158 +340,148 @@ void getSettingsJS(byte subPage, char* dest) case 20000 : speed = 4; break; } } - sappend('v',sp,speed); - sappend('v',la,bus->getLEDCurrent()); - sappend('v',ma,bus->getMaxCurrent()); + printSetFormValue(settingsScript,sp,speed); + printSetFormValue(settingsScript,la,bus->getLEDCurrent()); + printSetFormValue(settingsScript,ma,bus->getMaxCurrent()); sumMa += bus->getMaxCurrent(); } - sappend('v',SET_F("MA"),BusManager::ablMilliampsMax() ? BusManager::ablMilliampsMax() : sumMa); - sappend('c',SET_F("ABL"),BusManager::ablMilliampsMax() || sumMa > 0); - sappend('c',SET_F("PPL"),!BusManager::ablMilliampsMax() && sumMa > 0); + printSetFormValue(settingsScript,PSTR("MA"),BusManager::ablMilliampsMax() ? BusManager::ablMilliampsMax() : sumMa); + printSetFormCheckbox(settingsScript,PSTR("ABL"),BusManager::ablMilliampsMax() || sumMa > 0); + printSetFormCheckbox(settingsScript,PSTR("PPL"),!BusManager::ablMilliampsMax() && sumMa > 0); - oappend(SET_F("resetCOM(")); - oappend(itoa(WLED_MAX_COLOR_ORDER_MAPPINGS,nS,10)); - oappend(SET_F(");")); + settingsScript.printf_P(PSTR("resetCOM(%d);"), WLED_MAX_COLOR_ORDER_MAPPINGS); const ColorOrderMap& com = BusManager::getColorOrderMap(); for (int 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(");"); + settingsScript.printf_P(PSTR("addCOM(%d,%d,%d);"), entry->start, entry->len, entry->colorOrder); } - sappend('v',SET_F("CA"),briS); + printSetFormValue(settingsScript,PSTR("CA"),briS); - sappend('c',SET_F("BO"),turnOnAtBoot); - sappend('v',SET_F("BP"),bootPreset); + printSetFormCheckbox(settingsScript,PSTR("BO"),turnOnAtBoot); + printSetFormValue(settingsScript,PSTR("BP"),bootPreset); - sappend('c',SET_F("GB"),gammaCorrectBri); - sappend('c',SET_F("GC"),gammaCorrectCol); - dtostrf(gammaCorrectVal,3,1,nS); sappends('s',SET_F("GV"),nS); - sappend('c',SET_F("TF"),fadeTransition); - sappend('c',SET_F("EB"),modeBlending); - sappend('v',SET_F("TD"),transitionDelayDefault); - sappend('c',SET_F("PF"),strip.paletteFade); - sappend('v',SET_F("TP"),randomPaletteChangeTime); - sappend('c',SET_F("TH"),useHarmonicRandomPalette); - 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); - sappend('c',SET_F("RO"),rlyOpenDrain); + printSetFormCheckbox(settingsScript,PSTR("GB"),gammaCorrectBri); + printSetFormCheckbox(settingsScript,PSTR("GC"),gammaCorrectCol); + dtostrf(gammaCorrectVal,3,1,nS); printSetFormValue(settingsScript,PSTR("GV"),nS); + printSetFormCheckbox(settingsScript,PSTR("TF"),fadeTransition); + printSetFormCheckbox(settingsScript,PSTR("EB"),modeBlending); + printSetFormValue(settingsScript,PSTR("TD"),transitionDelayDefault); + printSetFormCheckbox(settingsScript,PSTR("PF"),strip.paletteFade); + printSetFormValue(settingsScript,PSTR("TP"),randomPaletteChangeTime); + printSetFormCheckbox(settingsScript,PSTR("TH"),useHarmonicRandomPalette); + printSetFormValue(settingsScript,PSTR("BF"),briMultiplier); + printSetFormValue(settingsScript,PSTR("TB"),nightlightTargetBri); + printSetFormValue(settingsScript,PSTR("TL"),nightlightDelayMinsDefault); + printSetFormValue(settingsScript,PSTR("TW"),nightlightMode); + printSetFormIndex(settingsScript,PSTR("PB"),strip.paletteBlend); + printSetFormValue(settingsScript,PSTR("RL"),rlyPin); + printSetFormCheckbox(settingsScript,PSTR("RM"),rlyMde); + printSetFormCheckbox(settingsScript,PSTR("RO"),rlyOpenDrain); for (int i = 0; i < WLED_MAX_BUTTONS; i++) { - oappend(SET_F("addBtn(")); - oappend(itoa(i,nS,10)); oappend(","); - oappend(itoa(btnPin[i],nS,10)); oappend(","); - oappend(itoa(buttonType[i],nS,10)); - oappend(SET_F(");")); + settingsScript.printf_P(PSTR("addBtn(%d,%d,%d);"), i, btnPin[i], buttonType[i]); } - sappend('c',SET_F("IP"),disablePullUp); - sappend('v',SET_F("TT"),touchThreshold); + printSetFormCheckbox(settingsScript,PSTR("IP"),disablePullUp); + printSetFormValue(settingsScript,PSTR("TT"),touchThreshold); #ifndef WLED_DISABLE_INFRARED - sappend('v',SET_F("IR"),irPin); - sappend('v',SET_F("IT"),irEnabled); + printSetFormValue(settingsScript,PSTR("IR"),irPin); + printSetFormValue(settingsScript,PSTR("IT"),irEnabled); #endif - sappend('c',SET_F("MSO"),!irApplyToAllSelected); + printSetFormCheckbox(settingsScript,PSTR("MSO"),!irApplyToAllSelected); } if (subPage == SUBPAGE_UI) { - sappends('s',SET_F("DS"),serverDescription); - sappend('c',SET_F("SU"),simplifiedUI); + printSetFormValue(settingsScript,PSTR("DS"),serverDescription); + printSetFormCheckbox(settingsScript,PSTR("SU"),simplifiedUI); } if (subPage == SUBPAGE_SYNC) { [[maybe_unused]] char nS[32]; - sappend('v',SET_F("UP"),udpPort); - sappend('v',SET_F("U2"),udpPort2); + printSetFormValue(settingsScript,PSTR("UP"),udpPort); + printSetFormValue(settingsScript,PSTR("U2"),udpPort2); #ifndef WLED_DISABLE_ESPNOW - if (enableESPNow) sappend('c',SET_F("EN"),useESPNowSync); - else oappend(SET_F("toggle('ESPNOW');")); // hide ESP-NOW setting + if (enableESPNow) printSetFormCheckbox(settingsScript,PSTR("EN"),useESPNowSync); + else settingsScript.print(F("toggle('ESPNOW');")); // hide ESP-NOW setting #else - oappend(SET_F("toggle('ESPNOW');")); // hide ESP-NOW setting + settingsScript.print(F("toggle('ESPNOW');")); // hide ESP-NOW setting #endif - sappend('v',SET_F("GS"),syncGroups); - sappend('v',SET_F("GR"),receiveGroups); + printSetFormValue(settingsScript,PSTR("GS"),syncGroups); + printSetFormValue(settingsScript,PSTR("GR"),receiveGroups); - sappend('c',SET_F("RB"),receiveNotificationBrightness); - sappend('c',SET_F("RC"),receiveNotificationColor); - sappend('c',SET_F("RX"),receiveNotificationEffects); - sappend('c',SET_F("RP"),receiveNotificationPalette); - sappend('c',SET_F("SO"),receiveSegmentOptions); - sappend('c',SET_F("SG"),receiveSegmentBounds); - sappend('c',SET_F("SS"),sendNotifications); - sappend('c',SET_F("SD"),notifyDirect); - sappend('c',SET_F("SB"),notifyButton); - sappend('c',SET_F("SH"),notifyHue); - sappend('v',SET_F("UR"),udpNumRetries); + printSetFormCheckbox(settingsScript,PSTR("RB"),receiveNotificationBrightness); + printSetFormCheckbox(settingsScript,PSTR("RC"),receiveNotificationColor); + printSetFormCheckbox(settingsScript,PSTR("RX"),receiveNotificationEffects); + printSetFormCheckbox(settingsScript,PSTR("RP"),receiveNotificationPalette); + printSetFormCheckbox(settingsScript,PSTR("SO"),receiveSegmentOptions); + printSetFormCheckbox(settingsScript,PSTR("SG"),receiveSegmentBounds); + printSetFormCheckbox(settingsScript,PSTR("SS"),sendNotifications); + printSetFormCheckbox(settingsScript,PSTR("SD"),notifyDirect); + printSetFormCheckbox(settingsScript,PSTR("SB"),notifyButton); + printSetFormCheckbox(settingsScript,PSTR("SH"),notifyHue); + printSetFormValue(settingsScript,PSTR("UR"),udpNumRetries); - sappend('c',SET_F("NL"),nodeListEnabled); - sappend('c',SET_F("NB"),nodeBroadcastEnabled); + printSetFormCheckbox(settingsScript,PSTR("NL"),nodeListEnabled); + printSetFormCheckbox(settingsScript,PSTR("NB"),nodeBroadcastEnabled); - sappend('c',SET_F("RD"),receiveDirect); - sappend('c',SET_F("MO"),useMainSegmentOnly); - sappend('c',SET_F("RLM"),realtimeRespectLedMaps); - sappend('v',SET_F("EP"),e131Port); - sappend('c',SET_F("ES"),e131SkipOutOfSequence); - sappend('c',SET_F("EM"),e131Multicast); - sappend('v',SET_F("EU"),e131Universe); - sappend('v',SET_F("DA"),DMXAddress); - sappend('v',SET_F("XX"),DMXSegmentSpacing); - sappend('v',SET_F("PY"),e131Priority); - sappend('v',SET_F("DM"),DMXMode); - sappend('v',SET_F("ET"),realtimeTimeoutMs); - sappend('c',SET_F("FB"),arlsForceMaxBri); - sappend('c',SET_F("RG"),arlsDisableGammaCorrection); - sappend('v',SET_F("WO"),arlsOffset); + printSetFormCheckbox(settingsScript,PSTR("RD"),receiveDirect); + printSetFormCheckbox(settingsScript,PSTR("MO"),useMainSegmentOnly); + printSetFormCheckbox(settingsScript,PSTR("RLM"),realtimeRespectLedMaps); + printSetFormValue(settingsScript,PSTR("EP"),e131Port); + printSetFormCheckbox(settingsScript,PSTR("ES"),e131SkipOutOfSequence); + printSetFormCheckbox(settingsScript,PSTR("EM"),e131Multicast); + printSetFormValue(settingsScript,PSTR("EU"),e131Universe); + printSetFormValue(settingsScript,PSTR("DA"),DMXAddress); + printSetFormValue(settingsScript,PSTR("XX"),DMXSegmentSpacing); + printSetFormValue(settingsScript,PSTR("PY"),e131Priority); + printSetFormValue(settingsScript,PSTR("DM"),DMXMode); + printSetFormValue(settingsScript,PSTR("ET"),realtimeTimeoutMs); + printSetFormCheckbox(settingsScript,PSTR("FB"),arlsForceMaxBri); + printSetFormCheckbox(settingsScript,PSTR("RG"),arlsDisableGammaCorrection); + printSetFormValue(settingsScript,PSTR("WO"),arlsOffset); #ifndef WLED_DISABLE_ALEXA - sappend('c',SET_F("AL"),alexaEnabled); - sappends('s',SET_F("AI"),alexaInvocationName); - sappend('c',SET_F("SA"),notifyAlexa); - sappend('v',SET_F("AP"),alexaNumPresets); + printSetFormCheckbox(settingsScript,PSTR("AL"),alexaEnabled); + printSetFormValue(settingsScript,PSTR("AI"),alexaInvocationName); + printSetFormCheckbox(settingsScript,PSTR("SA"),notifyAlexa); + printSetFormValue(settingsScript,PSTR("AP"),alexaNumPresets); #else - oappend(SET_F("toggle('Alexa');")); // hide Alexa settings + settingsScript.print(F("toggle('Alexa');")); // hide Alexa settings #endif #ifndef WLED_DISABLE_MQTT - sappend('c',SET_F("MQ"),mqttEnabled); - sappends('s',SET_F("MS"),mqttServer); - sappend('v',SET_F("MQPORT"),mqttPort); - sappends('s',SET_F("MQUSER"),mqttUser); + printSetFormCheckbox(settingsScript,PSTR("MQ"),mqttEnabled); + printSetFormValue(settingsScript,PSTR("MS"),mqttServer); + printSetFormValue(settingsScript,PSTR("MQPORT"),mqttPort); + printSetFormValue(settingsScript,PSTR("MQUSER"),mqttUser); byte l = strlen(mqttPass); char fpass[l+1]; //fill password field with *** fpass[l] = 0; memset(fpass,'*',l); - sappends('s',SET_F("MQPASS"),fpass); - sappends('s',SET_F("MQCID"),mqttClientID); - sappends('s',"MD",mqttDeviceTopic); - sappends('s',SET_F("MG"),mqttGroupTopic); - sappend('c',SET_F("BM"),buttonPublishMqtt); - sappend('c',SET_F("RT"),retainMqttMsg); - oappend(SET_F("d.Sf.MD.maxlength=")); oappend(itoa(MQTT_MAX_TOPIC_LEN,nS,10)); oappend(SET_F(";")); - oappend(SET_F("d.Sf.MG.maxlength=")); oappend(itoa(MQTT_MAX_TOPIC_LEN,nS,10)); oappend(SET_F(";")); - oappend(SET_F("d.Sf.MS.maxlength=")); oappend(itoa(MQTT_MAX_SERVER_LEN,nS,10)); oappend(SET_F(";")); + printSetFormValue(settingsScript,PSTR("MQPASS"),fpass); + printSetFormValue(settingsScript,PSTR("MQCID"),mqttClientID); + printSetFormValue(settingsScript,PSTR("MD"),mqttDeviceTopic); + printSetFormValue(settingsScript,PSTR("MG"),mqttGroupTopic); + printSetFormCheckbox(settingsScript,PSTR("BM"),buttonPublishMqtt); + printSetFormCheckbox(settingsScript,PSTR("RT"),retainMqttMsg); + settingsScript.printf_P(PSTR("d.Sf.MD.maxlength=%d;d.Sf.MG.maxlength=%d;d.Sf.MS.maxlength=%d;"), + MQTT_MAX_TOPIC_LEN, MQTT_MAX_TOPIC_LEN, MQTT_MAX_SERVER_LEN); #else - oappend(SET_F("toggle('MQTT');")); // hide MQTT settings + settingsScript.print(F("toggle('MQTT');")); // hide MQTT settings #endif #ifndef WLED_DISABLE_HUESYNC - sappend('v',SET_F("H0"),hueIP[0]); - sappend('v',SET_F("H1"),hueIP[1]); - sappend('v',SET_F("H2"),hueIP[2]); - sappend('v',SET_F("H3"),hueIP[3]); - sappend('v',SET_F("HL"),huePollLightId); - sappend('v',SET_F("HI"),huePollIntervalMs); - sappend('c',SET_F("HP"),huePollingEnabled); - sappend('c',SET_F("HO"),hueApplyOnOff); - sappend('c',SET_F("HB"),hueApplyBri); - sappend('c',SET_F("HC"),hueApplyColor); + printSetFormValue(settingsScript,PSTR("H0"),hueIP[0]); + printSetFormValue(settingsScript,PSTR("H1"),hueIP[1]); + printSetFormValue(settingsScript,PSTR("H2"),hueIP[2]); + printSetFormValue(settingsScript,PSTR("H3"),hueIP[3]); + printSetFormValue(settingsScript,PSTR("HL"),huePollLightId); + printSetFormValue(settingsScript,PSTR("HI"),huePollIntervalMs); + printSetFormCheckbox(settingsScript,PSTR("HP"),huePollingEnabled); + printSetFormCheckbox(settingsScript,PSTR("HO"),hueApplyOnOff); + printSetFormCheckbox(settingsScript,PSTR("HB"),hueApplyBri); + printSetFormCheckbox(settingsScript,PSTR("HC"),hueApplyColor); char hueErrorString[25]; switch (hueError) { @@ -566,61 +495,56 @@ void getSettingsJS(byte subPage, char* dest) default: sprintf_P(hueErrorString,PSTR("Bridge Error %i"),hueError); } - sappends('m',SET_F("(\"sip\")[0]"),hueErrorString); + printSetClassElementHTML(settingsScript,PSTR("sip"),0,hueErrorString); #else - oappend(SET_F("toggle('Hue');")); // hide Hue Sync settings + settingsScript.print(F("toggle('Hue');")); // hide Hue Sync settings #endif - sappend('v',SET_F("BD"),serialBaud); + printSetFormValue(settingsScript,PSTR("BD"),serialBaud); #ifndef WLED_ENABLE_ADALIGHT - oappend(SET_F("toggle('Serial);")); + settingsScript.print(F("toggle('Serial);")); #endif } if (subPage == SUBPAGE_TIME) { - sappend('c',SET_F("NT"),ntpEnabled); - sappends('s',SET_F("NS"),ntpServerName); - sappend('c',SET_F("CF"),!useAMPM); - sappend('i',SET_F("TZ"),currentTimezone); - sappend('v',SET_F("UO"),utcOffsetSecs); + printSetFormCheckbox(settingsScript,PSTR("NT"),ntpEnabled); + printSetFormValue(settingsScript,PSTR("NS"),ntpServerName); + printSetFormCheckbox(settingsScript,PSTR("CF"),!useAMPM); + printSetFormIndex(settingsScript,PSTR("TZ"),currentTimezone); + printSetFormValue(settingsScript,PSTR("UO"),utcOffsetSecs); char tm[32]; dtostrf(longitude,4,2,tm); - sappends('s',SET_F("LN"),tm); + printSetFormValue(settingsScript,PSTR("LN"),tm); dtostrf(latitude,4,2,tm); - sappends('s',SET_F("LT"),tm); + printSetFormValue(settingsScript,PSTR("LT"),tm); getTimeString(tm); - sappends('m',SET_F("(\"times\")[0]"),tm); + printSetClassElementHTML(settingsScript,PSTR("times"),0,tm); if ((int)(longitude*10.0f) || (int)(latitude*10.0f)) { sprintf_P(tm, PSTR("Sunrise: %02d:%02d Sunset: %02d:%02d"), hour(sunrise), minute(sunrise), hour(sunset), minute(sunset)); - sappends('m',SET_F("(\"times\")[1]"),tm); + printSetClassElementHTML(settingsScript,PSTR("times"),1,tm); } - sappend('c',SET_F("OL"),overlayCurrent); - sappend('v',SET_F("O1"),overlayMin); - sappend('v',SET_F("O2"),overlayMax); - sappend('v',SET_F("OM"),analogClock12pixel); - sappend('c',SET_F("OS"),analogClockSecondsTrail); - sappend('c',SET_F("O5"),analogClock5MinuteMarks); - sappend('c',SET_F("OB"),analogClockSolidBlack); + printSetFormCheckbox(settingsScript,PSTR("OL"),overlayCurrent); + printSetFormValue(settingsScript,PSTR("O1"),overlayMin); + printSetFormValue(settingsScript,PSTR("O2"),overlayMax); + printSetFormValue(settingsScript,PSTR("OM"),analogClock12pixel); + printSetFormCheckbox(settingsScript,PSTR("OS"),analogClockSecondsTrail); + printSetFormCheckbox(settingsScript,PSTR("O5"),analogClock5MinuteMarks); + printSetFormCheckbox(settingsScript,PSTR("OB"),analogClockSolidBlack); - sappend('c',SET_F("CE"),countdownMode); - sappend('v',SET_F("CY"),countdownYear); - sappend('v',SET_F("CI"),countdownMonth); - sappend('v',SET_F("CD"),countdownDay); - sappend('v',SET_F("CH"),countdownHour); - sappend('v',SET_F("CM"),countdownMin); - sappend('v',SET_F("CS"),countdownSec); + printSetFormCheckbox(settingsScript,PSTR("CE"),countdownMode); + printSetFormValue(settingsScript,PSTR("CY"),countdownYear); + printSetFormValue(settingsScript,PSTR("CI"),countdownMonth); + printSetFormValue(settingsScript,PSTR("CD"),countdownDay); + printSetFormValue(settingsScript,PSTR("CH"),countdownHour); + printSetFormValue(settingsScript,PSTR("CM"),countdownMin); + printSetFormValue(settingsScript,PSTR("CS"),countdownSec); - sappend('v',SET_F("A0"),macroAlexaOn); - sappend('v',SET_F("A1"),macroAlexaOff); - sappend('v',SET_F("MC"),macroCountdown); - sappend('v',SET_F("MN"),macroNl); + printSetFormValue(settingsScript,PSTR("A0"),macroAlexaOn); + printSetFormValue(settingsScript,PSTR("A1"),macroAlexaOff); + printSetFormValue(settingsScript,PSTR("MC"),macroCountdown); + printSetFormValue(settingsScript,PSTR("MN"),macroNl); for (unsigned 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]); + k[0] = 'M'; printSetFormValue(settingsScript,k,(timerMonth[i] >> 4) & 0x0F); + k[0] = 'P'; printSetFormValue(settingsScript,k,timerMonth[i] & 0x0F); + k[0] = 'D'; printSetFormValue(settingsScript,k,timerDay[i]); + k[0] = 'E'; printSetFormValue(settingsScript,k,timerDayEnd[i]); } } } @@ -647,121 +571,114 @@ void getSettingsJS(byte subPage, char* dest) char fpass[l+1]; //fill PIN field with 0000 fpass[l] = 0; memset(fpass,'0',l); - sappends('s',SET_F("PIN"),fpass); - 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(")\";")); - oappend(SET_F("sd=\"")); - oappend(serverDescription); - oappend(SET_F("\";")); + printSetFormValue(settingsScript,PSTR("PIN"),fpass); + printSetFormCheckbox(settingsScript,PSTR("NO"),otaLock); + printSetFormCheckbox(settingsScript,PSTR("OW"),wifiLock); + printSetFormCheckbox(settingsScript,PSTR("AO"),aOtaEnabled); + char tmp_buf[128]; + snprintf_P(tmp_buf,sizeof(tmp_buf),PSTR("WLED %s (build %d)"),versionString,VERSION); + printSetClassElementHTML(settingsScript,PSTR("sip"),0,tmp_buf); + settingsScript.printf_P(PSTR("sd=\"%s\";"), serverDescription); } #ifdef WLED_ENABLE_DMX // include only if DMX is enabled if (subPage == SUBPAGE_DMX) { - sappend('v',SET_F("PU"),e131ProxyUniverse); + printSetFormValue(settingsScript,PSTR("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); + printSetFormValue(settingsScript,PSTR("CN"),DMXChannels); + printSetFormValue(settingsScript,PSTR("CG"),DMXGap); + printSetFormValue(settingsScript,PSTR("CS"),DMXStart); + printSetFormValue(settingsScript,PSTR("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]); + printSetFormIndex(settingsScript,PSTR("CH1"),DMXFixtureMap[0]); + printSetFormIndex(settingsScript,PSTR("CH2"),DMXFixtureMap[1]); + printSetFormIndex(settingsScript,PSTR("CH3"),DMXFixtureMap[2]); + printSetFormIndex(settingsScript,PSTR("CH4"),DMXFixtureMap[3]); + printSetFormIndex(settingsScript,PSTR("CH5"),DMXFixtureMap[4]); + printSetFormIndex(settingsScript,PSTR("CH6"),DMXFixtureMap[5]); + printSetFormIndex(settingsScript,PSTR("CH7"),DMXFixtureMap[6]); + printSetFormIndex(settingsScript,PSTR("CH8"),DMXFixtureMap[7]); + printSetFormIndex(settingsScript,PSTR("CH9"),DMXFixtureMap[8]); + printSetFormIndex(settingsScript,PSTR("CH10"),DMXFixtureMap[9]); + printSetFormIndex(settingsScript,PSTR("CH11"),DMXFixtureMap[10]); + printSetFormIndex(settingsScript,PSTR("CH12"),DMXFixtureMap[11]); + printSetFormIndex(settingsScript,PSTR("CH13"),DMXFixtureMap[12]); + printSetFormIndex(settingsScript,PSTR("CH14"),DMXFixtureMap[13]); + printSetFormIndex(settingsScript,PSTR("CH15"),DMXFixtureMap[14]); } #endif if (subPage == SUBPAGE_UM) //usermods { - appendGPIOinfo(); - oappend(SET_F("numM=")); - oappendi(UsermodManager::getModCount()); - oappend(";"); - sappend('v',SET_F("SDA"),i2c_sda); - sappend('v',SET_F("SCL"),i2c_scl); - sappend('v',SET_F("MOSI"),spi_mosi); - sappend('v',SET_F("MISO"),spi_miso); - sappend('v',SET_F("SCLK"),spi_sclk); - oappend(SET_F("addInfo('SDA','")); oappendi(HW_PIN_SDA); oappend(SET_F("');")); - oappend(SET_F("addInfo('SCL','")); oappendi(HW_PIN_SCL); oappend(SET_F("');")); - oappend(SET_F("addInfo('MOSI','")); oappendi(HW_PIN_DATASPI); oappend(SET_F("');")); - oappend(SET_F("addInfo('MISO','")); oappendi(HW_PIN_MISOSPI); oappend(SET_F("');")); - oappend(SET_F("addInfo('SCLK','")); oappendi(HW_PIN_CLOCKSPI); oappend(SET_F("');")); - UsermodManager::appendConfigData(); + appendGPIOinfo(settingsScript); + settingsScript.printf_P(PSTR("numM=%d;"), UsermodManager::getModCount()); + printSetFormValue(settingsScript,PSTR("SDA"),i2c_sda); + printSetFormValue(settingsScript,PSTR("SCL"),i2c_scl); + printSetFormValue(settingsScript,PSTR("MOSI"),spi_mosi); + printSetFormValue(settingsScript,PSTR("MISO"),spi_miso); + printSetFormValue(settingsScript,PSTR("SCLK"),spi_sclk); + settingsScript.printf_P(PSTR("addInfo('SDA','%d');" + "addInfo('SCL','%d');" + "addInfo('MOSI','%d');" + "addInfo('MISO','%d');" + "addInfo('SCLK','%d');"), + HW_PIN_SDA, HW_PIN_SCL, HW_PIN_DATASPI, HW_PIN_MISOSPI, HW_PIN_CLOCKSPI + ); + UsermodManager::appendConfigData(settingsScript); } if (subPage == SUBPAGE_UPDATE) // update { - sappends('m',SET_F("(\"sip\")[0]"),(char*)F("WLED ")); - olen -= 2; //delete "; - oappend(versionString); - oappend(SET_F("
")); - oappend(releaseString); - oappend(SET_F("
(")); + char tmp_buf[128]; + snprintf_P(tmp_buf,sizeof(tmp_buf),PSTR("WLED %s
%s
(%s build %d)"), + versionString, + releaseString, #if defined(ARDUINO_ARCH_ESP32) - oappend(ESP.getChipModel()); + ESP.getChipModel(), #else - oappend("esp8266"); + F("esp8266"), #endif - oappend(SET_F(" build ")); - oappendi(VERSION); - oappend(SET_F(")\";")); + VERSION); + + printSetClassElementHTML(settingsScript,PSTR("sip"),0,tmp_buf); } if (subPage == SUBPAGE_2D) // 2D matrices { - sappend('v',SET_F("SOMP"),strip.isMatrix); + printSetFormValue(settingsScript,PSTR("SOMP"),strip.isMatrix); #ifndef WLED_DISABLE_2D - oappend(SET_F("maxPanels=")); oappendi(WLED_MAX_PANELS); oappend(SET_F(";")); - oappend(SET_F("resetPanels();")); + settingsScript.printf_P(PSTR("maxPanels=%d;"),WLED_MAX_PANELS); + settingsScript.print(F("resetPanels();")); if (strip.isMatrix) { if(strip.panels>0){ - sappend('v',SET_F("PW"),strip.panel[0].width); //Set generator Width and Height to first panel size for convenience - sappend('v',SET_F("PH"),strip.panel[0].height); + printSetFormValue(settingsScript,PSTR("PW"),strip.panel[0].width); //Set generator Width and Height to first panel size for convenience + printSetFormValue(settingsScript,PSTR("PH"),strip.panel[0].height); } - sappend('v',SET_F("MPC"),strip.panels); + printSetFormValue(settingsScript,PSTR("MPC"),strip.panels); // panels for (unsigned i=0; i