From 4b73c308decc19a3c7056cc573e660195cccded1 Mon Sep 17 00:00:00 2001 From: Ewoud Date: Thu, 9 Jan 2025 15:17:49 +0100 Subject: [PATCH] Remove webserver code - remove Svelte pio.ini - remove webserver libs LedModFixture - replace AsyncWebSocketMessageBuffer by buffer - don't call web and ws functions for preview SysModPins - replace AsyncWebSocketMessageBuffer by buffer - don't call web and ws functions for board SysModSystem: don't show TCPStack SysModWeb - remove wsEvent, sendDataWs, sendBuffer, serve*, jsonHandler, captivePortal, clientsToJson, sendResponseObjectm printClient - comment clients table --- data/svelte/build_interface.py | 168 ---- data/svelte/index.html | 33 - data/svelte/main.ts | 8 - data/svelte/package-lock.json | 1274 ----------------------------- data/svelte/package.json | 16 - data/svelte/src/App.svelte | 27 - data/svelte/src/AppCounter.svelte | 26 - data/svelte/src/Counter.svelte | 11 - data/svelte/src/Menu.svelte | 40 - data/svelte/vite.config.js | 7 - platformio.ini | 97 --- src/App/LedModFixture.cpp | 52 +- src/App/LedModFixture.h | 2 +- src/Sys/SysModPins.cpp | 17 +- src/Sys/SysModPrint.cpp | 2 +- src/Sys/SysModSystem.cpp | 14 +- src/Sys/SysModWeb.cpp | 727 ++-------------- src/Sys/SysModWeb.h | 65 +- src/User/UserModLive.cpp | 2 +- 19 files changed, 123 insertions(+), 2465 deletions(-) delete mode 100644 data/svelte/build_interface.py delete mode 100644 data/svelte/index.html delete mode 100644 data/svelte/main.ts delete mode 100644 data/svelte/package-lock.json delete mode 100644 data/svelte/package.json delete mode 100644 data/svelte/src/App.svelte delete mode 100644 data/svelte/src/AppCounter.svelte delete mode 100644 data/svelte/src/Counter.svelte delete mode 100644 data/svelte/src/Menu.svelte delete mode 100644 data/svelte/vite.config.js diff --git a/data/svelte/build_interface.py b/data/svelte/build_interface.py deleted file mode 100644 index 7571ede5..00000000 --- a/data/svelte/build_interface.py +++ /dev/null @@ -1,168 +0,0 @@ -# StarBase modified version from https://github.com/theelims/ESP32-sveltekit/blob/main/scripts/build_interface.py - -# ESP32 SvelteKit -- -# -# A simple, secure and extensible framework for IoT projects for ESP32 platforms -# with responsive Sveltekit front-end built with TailwindCSS and DaisyUI. -# https://github.com/theelims/ESP32-sveltekit -# -# Copyright (C) 2018 - 2023 rjwats -# Copyright (C) 2023 - 2024 theelims -# Copyright (C) 2023 Maxtrium B.V. [ code available under dual license ] -# Copyright (C) 2024 runeharlyk -# -# All Rights Reserved. This software may be modified and distributed under -# the terms of the LGPL v3 license. See the LICENSE file for details. - -from pathlib import Path -from shutil import copytree, rmtree, copyfileobj -from os.path import exists, getmtime -import os -import gzip -import mimetypes -import glob -from datetime import datetime - -Import("env") - -project_dir = env["PROJECT_DIR"] -buildFlags = env.ParseFlags(env["BUILD_FLAGS"]) - -interface_dir = project_dir + "/data/svelte" -output_file = project_dir + "/src/WWWData.h" -source_www_dir = interface_dir + "/src" -build_dir = interface_dir + "/dist" -filesystem_dir = project_dir + "/data/www" - - -def find_latest_timestamp_for_app(): - return max( - (getmtime(f) for f in glob.glob(f"{source_www_dir}/**/*", recursive=True)) - ) - - -def should_regenerate_output_file(): - if not flag_exists("EMBED_WWW") or not exists(output_file): - return True - last_source_change = find_latest_timestamp_for_app() - last_build = getmtime(output_file) - - print( - f"Newest file: {datetime.fromtimestamp(last_source_change)}, output file: {datetime.fromtimestamp(last_build)}" - ) - - return last_build < last_source_change - - -def gzip_file(file): - with open(file, 'rb') as f_in: - with gzip.open(file + '.gz', 'wb') as f_out: - copyfileobj(f_in, f_out) - os.remove(file) - - -def flag_exists(flag): - for define in buildFlags.get("CPPDEFINES"): - if (define == flag or (isinstance(define, list) and define[0] == flag)): - return True - return False - - -def get_package_manager(): - if exists(os.path.join(interface_dir, "pnpm-lock.yaml")): - return "pnpm" - if exists(os.path.join(interface_dir, "yarn.lock")): - return "yarn" - if exists(os.path.join(interface_dir, "package-lock.json")): - return "npm" - - -def build_webapp(): - if package_manager := get_package_manager(): - print(f"Building interface with {package_manager}") - os.chdir(interface_dir) - env.Execute(f"{package_manager} install") - env.Execute(f"{package_manager} run build") - os.chdir("..") - else: - raise Exception( - "No lock-file found. Please install dependencies for interface (eg. npm install)" - ) - - -def embed_webapp(): - if flag_exists("EMBED_WWW"): - print("Converting interface to PROGMEM") - build_progmem() - return - add_app_to_filesystem() - - -def build_progmem(): - mimetypes.init() - with open(output_file, "w") as progmem: - progmem.write("#include \n") - progmem.write("#include \n") - - assetMap = {} - - for idx, path in enumerate(Path(build_dir).rglob("*.*")): - asset_path = path.relative_to(build_dir).as_posix() - asset_mime = ( - mimetypes.guess_type(asset_path)[0] or "application/octet-stream" - ) - print(f"Converting {asset_path}") - - asset_var = f"ESP_SVELTEKIT_DATA_{idx}" - progmem.write(f"// {asset_path}\n") - progmem.write(f"const uint8_t {asset_var}[] = {{\n\t") - file_data = gzip.compress(path.read_bytes()) - - for i, byte in enumerate(file_data): - if i and not (i % 16): - progmem.write("\n\t") - progmem.write(f"0x{byte:02X},") - - progmem.write("\n};\n\n") - assetMap[asset_path] = { - "name": asset_var, - "mime": asset_mime, - "size": len(file_data), - } - - progmem.write( - "typedef std::function RouteRegistrationHandler;\n\n" - ) - progmem.write("class WWWData {\n") - progmem.write("\tpublic:\n") - progmem.write( - "\t\tstatic void registerRoutes(RouteRegistrationHandler handler) {\n" - ) - - for asset_path, asset in assetMap.items(): - progmem.write( - f'\t\t\thandler("/{asset_path}", "{asset["mime"]}", {asset["name"]}, {asset["size"]});\n' - ) - - progmem.write("\t\t}\n") - progmem.write("};\n\n") - - -def add_app_to_filesystem(): - build_path = Path(build_dir) - www_path = Path(filesystem_dir) - if www_path.exists() and www_path.is_dir(): - rmtree(www_path) - print("Copying and compress interface to data directory") - copytree(build_path, www_path) - for current_path, _, files in os.walk(www_path): - for file in files: - gzip_file(os.path.join(current_path, file)) - print("Build LittleFS file system image and upload to ESP32") - env.Execute("pio run --target uploadfs") - - -print("running: build_interface.py") -if should_regenerate_output_file(): - build_webapp() - embed_webapp() diff --git a/data/svelte/index.html b/data/svelte/index.html deleted file mode 100644 index 3c941432..00000000 --- a/data/svelte/index.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - Star + Vite + Svelte - - -
- - - diff --git a/data/svelte/main.ts b/data/svelte/main.ts deleted file mode 100644 index 8fe1989f..00000000 --- a/data/svelte/main.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { mount } from 'svelte' -import App from './src/App.svelte' - -const app = mount(App, { - target: document.getElementById('app')!, -}) - -export default app diff --git a/data/svelte/package-lock.json b/data/svelte/package-lock.json deleted file mode 100644 index 9c50b535..00000000 --- a/data/svelte/package-lock.json +++ /dev/null @@ -1,1274 +0,0 @@ -{ - "name": "starbase-svelte", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "starbase-svelte", - "version": "0.0.0", - "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^5.0.3", - "svelte-hamburgers": "latest", - "vite": "^6.0.5" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", - "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", - "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", - "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", - "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", - "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", - "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", - "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", - "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", - "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", - "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", - "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", - "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", - "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", - "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", - "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", - "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", - "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", - "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", - "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", - "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", - "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", - "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", - "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", - "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", - "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.1.tgz", - "integrity": "sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.1.tgz", - "integrity": "sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.1.tgz", - "integrity": "sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.1.tgz", - "integrity": "sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.1.tgz", - "integrity": "sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.1.tgz", - "integrity": "sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.1.tgz", - "integrity": "sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.1.tgz", - "integrity": "sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.1.tgz", - "integrity": "sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.1.tgz", - "integrity": "sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.1.tgz", - "integrity": "sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.1.tgz", - "integrity": "sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.1.tgz", - "integrity": "sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.1.tgz", - "integrity": "sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.1.tgz", - "integrity": "sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz", - "integrity": "sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.1.tgz", - "integrity": "sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.1.tgz", - "integrity": "sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.1.tgz", - "integrity": "sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-5.0.3.tgz", - "integrity": "sha512-MCFS6CrQDu1yGwspm4qtli0e63vaPCehf6V7pIMP15AsWgMKrqDGCPFF/0kn4SP0ii4aySu4Pa62+fIRGFMjgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1", - "debug": "^4.4.0", - "deepmerge": "^4.3.1", - "kleur": "^4.1.5", - "magic-string": "^0.30.15", - "vitefu": "^1.0.4" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22" - }, - "peerDependencies": { - "svelte": "^5.0.0", - "vite": "^6.0.0" - } - }, - "node_modules/@sveltejs/vite-plugin-svelte-inspector": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-4.0.1.tgz", - "integrity": "sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.7" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22" - }, - "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^5.0.0", - "svelte": "^5.0.0", - "vite": "^6.0.0" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-typescript": { - "version": "1.4.13", - "resolved": "https://registry.npmjs.org/acorn-typescript/-/acorn-typescript-1.4.13.tgz", - "integrity": "sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==", - "dev": true, - "license": "MIT", - "peer": true, - "peerDependencies": { - "acorn": ">=8.9.0" - } - }, - "node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/esbuild": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", - "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.2", - "@esbuild/android-arm": "0.24.2", - "@esbuild/android-arm64": "0.24.2", - "@esbuild/android-x64": "0.24.2", - "@esbuild/darwin-arm64": "0.24.2", - "@esbuild/darwin-x64": "0.24.2", - "@esbuild/freebsd-arm64": "0.24.2", - "@esbuild/freebsd-x64": "0.24.2", - "@esbuild/linux-arm": "0.24.2", - "@esbuild/linux-arm64": "0.24.2", - "@esbuild/linux-ia32": "0.24.2", - "@esbuild/linux-loong64": "0.24.2", - "@esbuild/linux-mips64el": "0.24.2", - "@esbuild/linux-ppc64": "0.24.2", - "@esbuild/linux-riscv64": "0.24.2", - "@esbuild/linux-s390x": "0.24.2", - "@esbuild/linux-x64": "0.24.2", - "@esbuild/netbsd-arm64": "0.24.2", - "@esbuild/netbsd-x64": "0.24.2", - "@esbuild/openbsd-arm64": "0.24.2", - "@esbuild/openbsd-x64": "0.24.2", - "@esbuild/sunos-x64": "0.24.2", - "@esbuild/win32-arm64": "0.24.2", - "@esbuild/win32-ia32": "0.24.2", - "@esbuild/win32-x64": "0.24.2" - } - }, - "node_modules/esm-env": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.1.tgz", - "integrity": "sha512-U9JedYYjCnadUlXk7e1Kr+aENQhtUaoaV9+gZm1T8LC/YBAPJx3NSPIAurFOC0U5vrdSevnUJS2/wUVxGwPhng==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/esrap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.3.2.tgz", - "integrity": "sha512-C4PXusxYhFT98GjLSmb20k9PREuUdporer50dhzGuJu9IJXktbMddVCMLAERl5dAHyAi73GWWCE4FVHGP1794g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/is-reference": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", - "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/estree": "^1.0.6" - } - }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/locate-character": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", - "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/rollup": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.29.1.tgz", - "integrity": "sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.29.1", - "@rollup/rollup-android-arm64": "4.29.1", - "@rollup/rollup-darwin-arm64": "4.29.1", - "@rollup/rollup-darwin-x64": "4.29.1", - "@rollup/rollup-freebsd-arm64": "4.29.1", - "@rollup/rollup-freebsd-x64": "4.29.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.29.1", - "@rollup/rollup-linux-arm-musleabihf": "4.29.1", - "@rollup/rollup-linux-arm64-gnu": "4.29.1", - "@rollup/rollup-linux-arm64-musl": "4.29.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.29.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.29.1", - "@rollup/rollup-linux-riscv64-gnu": "4.29.1", - "@rollup/rollup-linux-s390x-gnu": "4.29.1", - "@rollup/rollup-linux-x64-gnu": "4.29.1", - "@rollup/rollup-linux-x64-musl": "4.29.1", - "@rollup/rollup-win32-arm64-msvc": "4.29.1", - "@rollup/rollup-win32-ia32-msvc": "4.29.1", - "@rollup/rollup-win32-x64-msvc": "4.29.1", - "fsevents": "~2.3.2" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/svelte": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.16.0.tgz", - "integrity": "sha512-Ygqsiac6UogVED2ruKclU+pOeMThxWtp9LG+li7BXeDKC2paVIsRTMkNmcON4Zejerd1s5sZHWx6ZtU85xklVg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@ampproject/remapping": "^2.3.0", - "@jridgewell/sourcemap-codec": "^1.5.0", - "@types/estree": "^1.0.5", - "acorn": "^8.12.1", - "acorn-typescript": "^1.4.13", - "aria-query": "^5.3.1", - "axobject-query": "^4.1.0", - "clsx": "^2.1.1", - "esm-env": "^1.2.1", - "esrap": "^1.3.2", - "is-reference": "^3.0.3", - "locate-character": "^3.0.0", - "magic-string": "^0.30.11", - "zimmerframe": "^1.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/svelte-hamburgers": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/svelte-hamburgers/-/svelte-hamburgers-5.0.0.tgz", - "integrity": "sha512-MMb47VCozKDgn/jtmeqw+CbI3cZmkDXd/FG3VCkReMdw2YCSOaWYLsqsXiWTWoQE/oSmw1vH/Tm5mChqlsldHQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "svelte": "^5.0.0" - } - }, - "node_modules/vite": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.6.tgz", - "integrity": "sha512-NSjmUuckPmDU18bHz7QZ+bTYhRR0iA72cs2QAxCqDpafJ0S6qetco0LB3WW2OxlMHS0JmAv+yZ/R3uPmMyGTjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.24.2", - "postcss": "^8.4.49", - "rollup": "^4.23.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vitefu": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.4.tgz", - "integrity": "sha512-y6zEE3PQf6uu/Mt6DTJ9ih+kyJLr4XcSgHR2zUkM8SWDhuixEJxfJ6CZGMHh1Ec3vPLoEA0IHU5oWzVqw8ulow==", - "dev": true, - "license": "MIT", - "workspaces": [ - "tests/deps/*", - "tests/projects/*" - ], - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } - } - }, - "node_modules/zimmerframe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz", - "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==", - "dev": true, - "license": "MIT", - "peer": true - } - } -} diff --git a/data/svelte/package.json b/data/svelte/package.json deleted file mode 100644 index 7ed3978c..00000000 --- a/data/svelte/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "starbase-svelte", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview" - }, - "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^5.0.3", - "vite": "^6.0.5", - "svelte-hamburgers": "latest" - } -} diff --git a/data/svelte/src/App.svelte b/data/svelte/src/App.svelte deleted file mode 100644 index fcdea3ad..00000000 --- a/data/svelte/src/App.svelte +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - diff --git a/data/svelte/src/AppCounter.svelte b/data/svelte/src/AppCounter.svelte deleted file mode 100644 index bb4b68a2..00000000 --- a/data/svelte/src/AppCounter.svelte +++ /dev/null @@ -1,26 +0,0 @@ - - -
-

Star + Vite + Svelte

- -
- -
- -

- Check out SvelteKit, the official Svelte app framework powered by Vite! -

- -

- Click on the Vite and Svelte logos to learn more (ewowi) -

-
- - - \ No newline at end of file diff --git a/data/svelte/src/Counter.svelte b/data/svelte/src/Counter.svelte deleted file mode 100644 index da25338b..00000000 --- a/data/svelte/src/Counter.svelte +++ /dev/null @@ -1,11 +0,0 @@ - - - - \ No newline at end of file diff --git a/data/svelte/src/Menu.svelte b/data/svelte/src/Menu.svelte deleted file mode 100644 index 117cfc75..00000000 --- a/data/svelte/src/Menu.svelte +++ /dev/null @@ -1,40 +0,0 @@ - - -{#if open} -
- {#each ['Home', 'Example', 'About', 'Contact'] as link, i} -

- {link} -

- {/each} -
- -
-{/if} - - diff --git a/data/svelte/vite.config.js b/data/svelte/vite.config.js deleted file mode 100644 index d32eba1d..00000000 --- a/data/svelte/vite.config.js +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from 'vite' -import { svelte } from '@sveltejs/vite-plugin-svelte' - -// https://vite.dev/config/ -export default defineConfig({ - plugins: [svelte()], -}) diff --git a/platformio.ini b/platformio.ini index 2338016b..07304c95 100644 --- a/platformio.ini +++ b/platformio.ini @@ -8,43 +8,6 @@ ; @license For non GPL-v3 usage, commercial licenses must be purchased. Contact moonmodules@icloud.com -; ESPAsyncWebServer ESPHome version -[ESPAsyncWebServer] -build_flags = - -D CONFIG_ASYNC_TCP_USE_WDT=0 ;why? tbd: experiment without - -D WS_MAX_QUEUED_MESSAGES=64 - -D CONFIG_ASYNC_TCP_RUNNING_CORE=1 ;tbd experiment without - ;-D CONFIG_ASYNC_TCP_TASK_STACK_SIZE ; 8192*2 here as default !!! -lib_deps = - https://github.com/MoonModules/ESPAsyncWebServer.git @ 3.2.2 ; + queueLen(gth) (see https://github.com/esphome/ESPAsyncWebServer/pull/38) - ; https://github.com/mathieucarbou/ESPAsyncWebServer.git @ 3.3.5 ; WIP... - -; ESPAsyncWebServer AirCoookie v2.0.7 version (2.2.1 is latest) -; [ESPAsyncWebServer] -; build_flags = -; -D CONFIG_ASYNC_TCP_USE_WDT=0 ;why? tbd: experiment without -; ; -D WS_MAX_QUEUED_MESSAGES=64 ;not supported to set here in AirCoookie version -; -D CONFIG_ASYNC_TCP_STACK_SIZE=CONFIG_ASYNC_TCP_TASK_STACK_SIZE ; ESPHome uses CONFIG_ASYNC_TCP_STACK_SIZE (used in SysModSystem) -; lib_deps = -; ; https://github.com/lost-hope/ESPAsyncWebServer.git#master ;aircoookie + artifx on /edit -; ; https://github.com/ewowi/ESPAsyncWebServer.git ;me-no-dev + 64 + queueLength - alternative -; https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 ; WLEDMM this must be first in the list, otherwise Aircoookie/ESPAsyncWebServer pulls in an older version of AsyncTCP !! -; https://github.com/ewoudwijma/ESPAsyncWebServer.git#v2.0.7 ;aircoookie + getClients + 64 -; ; https://github.com/ewoudwijma/ESPAsyncWebServer.git#v2.2.1 ;crashes on ws refererence in sendDataWs !! - -; see also: -; https://github.com/esphome/ESPAsyncWebServer/issues/34 ; Decide which ESPAsyncWebServer fork should be canonical? -; https://github.com/mathieucarbou/ESPAsyncWebServer/discussions/38 ; Should we try to establish this as the de facto successor fork of ESPAsyncWebServer? -; https://github.com/mathieucarbou/ESPAsyncWebServer ; Important recommendations - -;Work in progress - not compiling yet -[PsychicHttp] -build_flags = - -D STARBASE_USE_Psychic -lib_deps = - ; hoeken/PsychicHttp - https://github.com/hoeken/PsychicHttp - [STARBASE_USERMOD_E131] build_flags = @@ -125,8 +88,6 @@ build_flags = -D STARBASE_DEVMODE -mtext-section-literals ;otherwise [UserModLive::setup()]+0xa17): dangerous relocation: l32r: literal target out of range (try using text-section-literals) ;for StarLight, first only for s2, now for all due to something in UserModLive.Setup... - ${ESPAsyncWebServer.build_flags} ;alternatively PsychicHttp - -D EMBED_WWW ;embed the svelte web interface in the firmware ;optional: -D STARBASE_ETHERNET ; +41.876 bytes (2.2%) ${STARBASE_USERMOD_E131.build_flags} ;+11.416 bytes 0.6% @@ -135,7 +96,6 @@ build_flags = ; ${STARBASE_USERMOD_HA.build_flags} ${STARBASE_USERMOD_LIVE.build_flags} ;+222.204 bytes 11.7% lib_deps = - ${ESPAsyncWebServer.lib_deps} ;alternatively PsychicHttp https://github.com/bblanchon/ArduinoJson.git @ 7.3.0 ;force latest ; https://github.com/Jason2866/ESP32_Show_Info.git ;optional: @@ -197,7 +157,6 @@ lib_deps = ${STARLIGHT.lib_deps} extra_scripts = pre:tools/webbundle.py - pre:data/svelte/build_interface.py post:tools/post_build.py @@ -483,59 +442,3 @@ lib_deps = ; friend class HANumeric; - - - -;AsyncJson.h - - -; In file included from src/Sys/SysModWeb.cpp:22: -; .pio/libdeps/lolin_d32/ESPAsyncWebServerAircoookie/src/AsyncJson.h:86:25: warning: 'DynamicJsonDocument' is deprecated: use JsonDocument instead [-Wdeprecated-declarations] -; DynamicJsonDocument _jsonBuffer; -; ^~~~~~~~~~~ -; In file included from .pio/libdeps/lolin_d32/ArduinoJson/src/ArduinoJson.hpp:53, -; from .pio/libdeps/lolin_d32/ArduinoJson/src/ArduinoJson.h:9, -; from src/SysModule.h:23, -; from src/Sys/SysModWeb.h:13, -; from src/Sys/SysModWeb.cpp:12: -; .pio/libdeps/lolin_d32/ArduinoJson/src/ArduinoJson/compatibility.hpp:125:58: note: declared here -; class ARDUINOJSON_DEPRECATED("use JsonDocument instead") DynamicJsonDocument -; ^~~~~~~~~~~~~~~~~~~ -; In file included from src/Sys/SysModWeb.cpp:22: -; .pio/libdeps/lolin_d32/ESPAsyncWebServerAircoookie/src/AsyncJson.h: In constructor 'AsyncJsonResponse::AsyncJsonResponse(bool, size_t)': -; .pio/libdeps/lolin_d32/ESPAsyncWebServerAircoookie/src/AsyncJson.h:108:47: warning: 'ArduinoJson::V703PB2::JsonArray ArduinoJson::V703PB2::JsonDocument::createNestedArray()' is deprecated: use add() instead [-Wdeprecated-declarations] -; _root = _jsonBuffer.createNestedArray(); -; ^ -; In file included from .pio/libdeps/lolin_d32/ArduinoJson/src/ArduinoJson.hpp:33, -; from .pio/libdeps/lolin_d32/ArduinoJson/src/ArduinoJson.h:9, -; from src/SysModule.h:23, -; from src/Sys/SysModWeb.h:13, -; from src/Sys/SysModWeb.cpp:12: -; .pio/libdeps/lolin_d32/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp:298:13: note: declared here -; JsonArray createNestedArray() { -; ^~~~~~~~~~~~~~~~~ -; In file included from src/Sys/SysModWeb.cpp:22: -; .pio/libdeps/lolin_d32/ESPAsyncWebServerAircoookie/src/AsyncJson.h:110:48: warning: 'ArduinoJson::V703PB2::JsonObject ArduinoJson::V703PB2::JsonDocument::createNestedObject()' is deprecated: use add() instead [-Wdeprecated-declarations] -; _root = _jsonBuffer.createNestedObject(); -; ^ -; In file included from .pio/libdeps/lolin_d32/ArduinoJson/src/ArduinoJson.hpp:33, -; from .pio/libdeps/lolin_d32/ArduinoJson/src/ArduinoJson.h:9, -; from src/SysModule.h:23, -; from src/Sys/SysModWeb.h:13, -; from src/Sys/SysModWeb.cpp:12: -; .pio/libdeps/lolin_d32/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp:318:14: note: declared here -; JsonObject createNestedObject() { -; ^~~~~~~~~~~~~~~~~~ -; In file included from src/Sys/SysModWeb.cpp:22: -; .pio/libdeps/lolin_d32/ESPAsyncWebServerAircoookie/src/AsyncJson.h: In member function 'virtual void AsyncCallbackJsonWebHandler::handleRequest(AsyncWebServerRequest*)': -; .pio/libdeps/lolin_d32/ESPAsyncWebServerAircoookie/src/AsyncJson.h:218:39: warning: 'DynamicJsonDocument' is deprecated: use JsonDocument instead [-Wdeprecated-declarations] -; DynamicJsonDocument jsonBuffer(this->maxJsonBufferSize); -; ^ -; In file included from .pio/libdeps/lolin_d32/ArduinoJson/src/ArduinoJson.hpp:53, -; from .pio/libdeps/lolin_d32/ArduinoJson/src/ArduinoJson.h:9, -; from src/SysModule.h:23, -; from src/Sys/SysModWeb.h:13, -; from src/Sys/SysModWeb.cpp:12: -; .pio/libdeps/lolin_d32/ArduinoJson/src/ArduinoJson/compatibility.hpp:125:58: note: declared here -; class ARDUINOJSON_DEPRECATED("use JsonDocument instead") DynamicJsonDocument -; ^~~~~~~~~~~~~~~~~~~ diff --git a/src/App/LedModFixture.cpp b/src/App/LedModFixture.cpp index 55a8fe70..9fd69843 100644 --- a/src/App/LedModFixture.cpp +++ b/src/App/LedModFixture.cpp @@ -113,21 +113,21 @@ case onUI: if (bytesPerPixel) { mappingStatus = 1; //rebuild the fixture - so it is send to ui - if (web->ws.getClients().length()) + // if (web->ws.getClients().length()) doSendFixtureDefinition = true; //send fixture definition to ui } return true; case onLoop: { - if (!web->isBusy && mappingStatus == 0 && bytesPerPixel && !doSendFixtureDefinition && web->ws.getClients().length()) { //not remapping and clients exists - variable.var["interval"] = max(nrOfLeds * web->ws.count()/200, 16U)*10; //interval in ms * 10, not too fast //from cs to ms + if (!web->isBusy && mappingStatus == 0 && bytesPerPixel && !doSendFixtureDefinition) { //} && web->ws.getClients().length()) { //not remapping and clients exists + variable.var["interval"] = max(nrOfLeds/200, 16)*10; //interval in ms * 10, not too fast //from cs to ms web->ws.count() #define headerBytesPreview 5 // ppf("(%d %d %d,%d,%d)", len, headerBytesPreview + nrOfLeds * bytesPerPixel, fixSize.x, fixSize.y, fixSize.z); size_t len = min(headerBytesPreview + nrOfLeds * bytesPerPixel, PACKAGE_SIZE); - AsyncWebSocketMessageBuffer *wsBuf= web->ws.makeBuffer(len); //global wsBuf causes crash in audio sync module!!! - if (wsBuf) { - wsBuf->lock(); - byte* buffer = wsBuf->get(); + // AsyncWebSocketMessageBuffer *wsBuf= web->ws.makeBuffer(len); //global wsBuf causes crash in audio sync module!!! + byte* buffer = (byte*)malloc(len); // wsBuf->get(); + if (buffer) { + // wsBuf->lock(); //new values buffer[0] = 2; //userFun id //rotations @@ -160,7 +160,7 @@ if (previewBufferIndex + bytesPerPixel > PACKAGE_SIZE) { //send the buffer and create a new one - web->sendBuffer(wsBuf, true); + // web->sendBuffer(wsBuf, true); delay(10); buffer[0] = 2; //userFun id buffer[1] = UINT8_MAX; //indicates follow up package @@ -194,10 +194,11 @@ } } //loop - web->sendBuffer(wsBuf, true); + // web->sendBuffer(wsBuf, true); - wsBuf->unlock(); - web->ws._cleanBuffers(); + // wsBuf->unlock(); + // web->ws._cleanBuffers(); + free(buffer); } } @@ -248,7 +249,7 @@ if (sys->safeMode) return true; //do not process fixture in safeMode do this if the fixture crashes at boot, then change fixture to working fixture and reboot doAllocPins = true; - if (web->ws.getClients().length()) + // if (web->ws.getClients().length()) doSendFixtureDefinition = true; //remap all leds @@ -555,12 +556,12 @@ void LedModFixture::addPixelsPre() { prevIndexP = 0; //for allocPins if (bytesPerPixel && doSendFixtureDefinition) { - for (auto &client:web->ws.getClients()) while (client->queueLen() > 3) delay(10); //ui refresh, wait a bit + // for (auto &client:web->ws.getClients()) while (client->queueLen() > 3) delay(10); //ui refresh, wait a bit size_t len = min(nrOfLeds * 6 + headerBytesFixture, PACKAGE_SIZE); - wsBuf = web->ws.makeBuffer(len); - if (wsBuf) { - wsBuf->lock(); - byte* buffer = wsBuf->get(); + // wsBuf = web->ws.makeBuffer(len); + byte* buffer = (byte*)malloc(len);// wsBuf->get(); + if (buffer) { + // wsBuf->lock(); buffer[0] = 1; //userfun 1 buffer[1] = fixSize.x/256; buffer[2] = fixSize.x%256; @@ -591,14 +592,14 @@ void LedModFixture::addPixel(Coord3D pixel) { if (bytesPerPixel && doSendFixtureDefinition) { //send pixel to ui ... - if (wsBuf && indexP < nrOfLeds ) { //max index to process && indexP * 6 + headerBytesFixture + 5 < 2 * 8192 - byte* buffer = wsBuf->get(); + if (buffer && indexP < nrOfLeds ) { //max index to process && indexP * 6 + headerBytesFixture + 5 < 2 * 8192 wsBuf && + // byte* buffer = wsBuf->get(); if (previewBufferIndex + ((fixSize.x > 1)?2:0 + (fixSize.y > 1)?2:0 + (fixSize.z > 1)?2:0) > PACKAGE_SIZE) { //2, 4, or 6 bytes (1D, 2D, 3D) //add previewBufferIndex to package buffer[12] = previewBufferIndex/256; //first empty slot buffer[13] = previewBufferIndex%256; //send the buffer and create a new one - web->sendBuffer(wsBuf, true, nullptr, false); + // web->sendBuffer(wsBuf, true, nullptr, false); delay(50); ppf("buffer sent i:%d p:%d r:%d r6:%d (1:%d m:%u)\n", indexP, previewBufferIndex, (nrOfLeds - indexP), (nrOfLeds - indexP) * 6, buffer[1], millis()); @@ -684,18 +685,19 @@ void LedModFixture::addPixelsPost() { } else if (nrOfLeds <= STARLIGHT_MAXLEDS) { if (bytesPerPixel && doSendFixtureDefinition) { - if (wsBuf) { - byte* buffer = wsBuf->get(); + if (buffer) { + // byte* buffer = wsBuf->get(); buffer[12] = previewBufferIndex/256; //last slot filled buffer[13] = previewBufferIndex%256; //last slot filled - web->sendBuffer(wsBuf, true, nullptr, false); + // web->sendBuffer(wsBuf, true, nullptr, false); ppf("last buffer sent i:%d p:%d r:%d r6:%d (1:%d m:%u)\n", indexP, previewBufferIndex, (nrOfLeds - indexP), (nrOfLeds - indexP) * 6, buffer[1], millis()); // ppf("addPixelsPost before unlock and clean:%d\n", indexP); - wsBuf->unlock(); - web->ws._cleanBuffers(); + // wsBuf->unlock(); + // web->ws._cleanBuffers(); // delay(50); + free(buffer); } // ppf("addPixelsPost after unlock and clean:%d\n", indexP); diff --git a/src/App/LedModFixture.h b/src/App/LedModFixture.h index 928db990..9837cd68 100644 --- a/src/App/LedModFixture.h +++ b/src/App/LedModFixture.h @@ -162,7 +162,7 @@ class LedModFixture: public SysModule { uint16_t previewBufferIndex = 0; unsigned long start = millis(); uint8_t pass = 0; //'class global' so addPixel/Pin functions know which pass it is in - AsyncWebSocketMessageBuffer * wsBuf; //buffer for preview create fixture + byte* buffer; // AsyncWebSocketMessageBuffer * wsBuf; //buffer for preview create fixture void addPixelsPre(); void addPixel(Coord3D pixel); void addPin(uint8_t pin); diff --git a/src/Sys/SysModPins.cpp b/src/Sys/SysModPins.cpp index c4cf1c5d..75b7ca73 100644 --- a/src/Sys/SysModPins.cpp +++ b/src/Sys/SysModPins.cpp @@ -68,14 +68,14 @@ void SysModPins::setup() { variable.setComment("Pin viewer 🚧"); return true; case onLoop: - if (!web->isBusy && web->ws.getClients().length()) { + if (!web->isBusy) {//} && web->ws.getClients().length()) { variable.var["interval"] = 100; //every 100 ms size_t len = NUM_DIGITAL_PINS + 5; - AsyncWebSocketMessageBuffer *wsBuf= web->ws.makeBuffer(len); //global wsBuf causes crash in audio sync module!!! - if (wsBuf) { - wsBuf->lock(); - byte* buffer = wsBuf->get(); + // AsyncWebSocketMessageBuffer *wsBuf= web->ws.makeBuffer(len); //global wsBuf causes crash in audio sync module!!! + byte* buffer = (byte*)malloc(len);// wsBuf->get(); + if (buffer) { + // wsBuf->lock(); // send pins to clients for (size_t pin = 0; pin < NUM_DIGITAL_PINS; pin++) { @@ -85,10 +85,11 @@ void SysModPins::setup() { //new values buffer[0] = 0; //userFun id - web->sendBuffer(wsBuf, true); + // web->sendBuffer(wsBuf, true); - wsBuf->unlock(); - web->ws._cleanBuffers(); + // wsBuf->unlock(); + // web->ws._cleanBuffers(); + free(buffer); } } return true; diff --git a/src/Sys/SysModPrint.cpp b/src/Sys/SysModPrint.cpp index 2eaf012f..b6f7e1f5 100644 --- a/src/Sys/SysModPrint.cpp +++ b/src/Sys/SysModPrint.cpp @@ -66,7 +66,7 @@ void SysModPrint::setup() { options.add("Serial"); options.add("UI"); - web->clientsToJson(options, true); //ip only + // web->clientsToJson(options, true); //ip only return true; } default: return false; diff --git a/src/Sys/SysModSystem.cpp b/src/Sys/SysModSystem.cpp index ce632660..dcc9dfc2 100644 --- a/src/Sys/SysModSystem.cpp +++ b/src/Sys/SysModSystem.cpp @@ -39,7 +39,7 @@ SysModSystem::SysModSystem() :SysModule("System") {}; void SysModSystem::setup() { SysModule::setup(); - ppf("Stack %d of %d B (async %d of %d B) %d\n", sysTools_get_arduino_maxStackUsage(), getArduinoLoopTaskStackSize(), sysTools_get_webserver_maxStackUsage(), CONFIG_ASYNC_TCP_STACK_SIZE, uxTaskGetStackHighWaterMark(xTaskGetCurrentTaskHandle())); + ppf("Stack %d of %d B (async %d B) %d\n", sysTools_get_arduino_maxStackUsage(), getArduinoLoopTaskStackSize(), sysTools_get_webserver_maxStackUsage(), uxTaskGetStackHighWaterMark(xTaskGetCurrentTaskHandle())); const Variable parentVar = ui->initSysMod(Variable(), name, 2000); parentVar.var["s"] = true; //setup @@ -90,7 +90,7 @@ void SysModSystem::setup() { ui->initButton(parentVar, "reboot", false, [](EventArguments) { switch (eventType) { case onChange: - web->ws.closeAll(1012); + // web->ws.closeAll(1012); // mdls->reboot(); //not working yet // long dly = millis(); @@ -154,16 +154,6 @@ void SysModSystem::setup() { default: return false; }}); - ui->initProgress(parentVar, "TCPStack", 0, 0, CONFIG_ASYNC_TCP_STACK_SIZE, true, [this](EventArguments) { switch (eventType) { - case onChange: - web->addResponse(variable.var, "comment", "%d of %d B", sysTools_get_webserver_maxStackUsage(), CONFIG_ASYNC_TCP_STACK_SIZE); - return true; - case onLoop1s: - variable.setValue(sysTools_get_webserver_maxStackUsage()); - return true; - default: return false; - }}); - ui->initSelect(parentVar, "reset 0", (int)rtc_get_reset_reason(0), true, [this](EventArguments) { switch (eventType) { case onUI: variable.setComment("Reason Core 0"); diff --git a/src/Sys/SysModWeb.cpp b/src/Sys/SysModWeb.cpp index 4c05c6e7..9bbfa3e4 100644 --- a/src/Sys/SysModWeb.cpp +++ b/src/Sys/SysModWeb.cpp @@ -27,18 +27,16 @@ #include "html_newui.h" #include "WWWData.h" -#include "AsyncJson.h" - #include //https://techtutorialsx.com/2018/08/24/esp32-web-server-serving-html-from-file-system/ //https://randomnerdtutorials.com/esp32-async-web-server-espasyncwebserver-library/ SysModWeb::SysModWeb() :SysModule("Web") { - //CORS compatiblity - DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), "*"); - DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Methods"), "*"); - DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), "*"); + // //CORS compatiblity + // DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Origin"), "*"); + // DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Methods"), "*"); + // DefaultHeaders::Instance().addHeader(F("Access-Control-Allow-Headers"), "*"); responseDocLoopTask = new JsonDocument; responseDocLoopTask->to(); responseDocAsyncTCP = new JsonDocument; responseDocAsyncTCP->to(); @@ -48,64 +46,64 @@ void SysModWeb::setup() { SysModule::setup(); const Variable parentVar = ui->initSysMod(Variable(), name, 3101); - Variable tableVar = ui->initTable(parentVar, "clients", nullptr, true, [](EventArguments) { switch (eventType) { - case onLoop1s: - for (JsonObject childVar: variable.children()) - Variable(childVar).triggerEvent(onSetValue); //set the value (WIP) - default: return false; - }}); - - ui->initNumber(tableVar, "nr", UINT16_MAX, 0, 999, true, [this](EventArguments) { switch (eventType) { - case onSetValue: { - uint8_t rowNr = 0; for (auto &client:ws.getClients()) - variable.setValue(client->id(), rowNr++); - return true; } - default: return false; - }}); - - ui->initText(tableVar, "ip", nullptr, 16, true, [this](EventArguments) { switch (eventType) { - case onSetValue: { - uint8_t rowNr = 0; for (auto &client:ws.getClients()) - variable.setValue(JsonString(client->remoteIP().toString().c_str()), rowNr++); - return true; } - default: return false; - }}); - - //UINT8_MAX: tri state boolean: not true not false - ui->initCheckBox(tableVar, "full", UINT8_MAX, true, [this](EventArguments) { switch (eventType) { - case onSetValue: { - uint8_t rowNr = 0; for (auto &client:ws.getClients()) - variable.setValue(client->queueIsFull(), rowNr++); - return true; } - default: return false; - }}); - - ui->initSelect(tableVar, "status", UINT8_MAX, true, [this](EventArguments) { switch (eventType) { - case onSetValue: { - uint8_t rowNr = 0; for (auto &client:ws.getClients()) - variable.setValue(client->status(), rowNr++); - return true; } - case onUI: - { - //tbd: not working yet in ui - JsonArray options = variable.setOptions(); - options.add("Disconnected"); //0 - options.add("Connected"); //1 - options.add("Disconnecting"); //2 - return true; - } - default: return false; - }}); - - ui->initNumber(tableVar, "length", UINT16_MAX, 0, WS_MAX_QUEUED_MESSAGES, true, [this](EventArguments) { switch (eventType) { - case onSetValue: { - uint8_t rowNr = 0; for (auto &client:ws.getClients()) - variable.setValue(client->queueLen(), rowNr++); - return true; } - default: return false; - }}); - - ui->initNumber(parentVar, "maxQueue", WS_MAX_QUEUED_MESSAGES, 0, WS_MAX_QUEUED_MESSAGES, true); + // Variable tableVar = ui->initTable(parentVar, "clients", nullptr, true, [](EventArguments) { switch (eventType) { + // case onLoop1s: + // for (JsonObject childVar: variable.children()) + // Variable(childVar).triggerEvent(onSetValue); //set the value (WIP) + // default: return false; + // }}); + + // ui->initNumber(tableVar, "nr", UINT16_MAX, 0, 999, true, [this](EventArguments) { switch (eventType) { + // case onSetValue: { + // uint8_t rowNr = 0; for (auto &client:ws.getClients()) + // variable.setValue(client->id(), rowNr++); + // return true; } + // default: return false; + // }}); + + // ui->initText(tableVar, "ip", nullptr, 16, true, [this](EventArguments) { switch (eventType) { + // case onSetValue: { + // uint8_t rowNr = 0; for (auto &client:ws.getClients()) + // variable.setValue(JsonString(client->remoteIP().toString().c_str()), rowNr++); + // return true; } + // default: return false; + // }}); + + // //UINT8_MAX: tri state boolean: not true not false + // ui->initCheckBox(tableVar, "full", UINT8_MAX, true, [this](EventArguments) { switch (eventType) { + // case onSetValue: { + // uint8_t rowNr = 0; for (auto &client:ws.getClients()) + // variable.setValue(client->queueIsFull(), rowNr++); + // return true; } + // default: return false; + // }}); + + // ui->initSelect(tableVar, "status", UINT8_MAX, true, [this](EventArguments) { switch (eventType) { + // case onSetValue: { + // uint8_t rowNr = 0; for (auto &client:ws.getClients()) + // variable.setValue(client->status(), rowNr++); + // return true; } + // case onUI: + // { + // //tbd: not working yet in ui + // JsonArray options = variable.setOptions(); + // options.add("Disconnected"); //0 + // options.add("Connected"); //1 + // options.add("Disconnecting"); //2 + // return true; + // } + // default: return false; + // }}); + + // ui->initNumber(tableVar, "length", UINT16_MAX, 0, WS_MAX_QUEUED_MESSAGES, true, [this](EventArguments) { switch (eventType) { + // case onSetValue: { + // uint8_t rowNr = 0; for (auto &client:ws.getClients()) + // variable.setValue(client->queueLen(), rowNr++); + // return true; } + // default: return false; + // }}); + + // ui->initNumber(parentVar, "maxQueue", WS_MAX_QUEUED_MESSAGES, 0, WS_MAX_QUEUED_MESSAGES, true); ui->initText(parentVar, "WSSend", nullptr, 16, true, [this](EventArguments) { switch (eventType) { case onLoop1s: @@ -148,7 +146,7 @@ void SysModWeb::loop20ms() { //currently not used as each variable is send individually if (this->modelUpdated) { - sendDataWs(*mdl->model); //send new data, all clients, no def + // sendDataWs(*mdl->model); //send new data, all clients, no def this->modelUpdated = false; } @@ -165,523 +163,39 @@ void SysModWeb::loop20ms() { } void SysModWeb::loop1s() { - sendResponseObject(); //this sends all the loopTask responses once per second !!! + // sendResponseObject(); //this sends all the loopTask responses once per second !!! } void SysModWeb::reboot() { ppf("SysModWeb reboot\n"); - ws.closeAll(1012); + // ws.closeAll(1012); } void SysModWeb::connectedChanged() { if (mdls->isConnected) { - #ifdef STARBASE_USE_Psychic - - server.listen(80); - - ws.onOpen(wsEventOpen); - ws.onFrame(wsEventFrame); - ws.onClose(wsEventClose); - - server.on("/ws")->setHandler(&ws); - - #else - ws.onEvent( [this](WebSocket * server, WebClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) {wsEvent(server, client, type, arg, data, len);}); - server.addHandler(&ws); - server.begin(); - #endif - - server.on("/", HTTP_GET, [this](WebRequest *request) {serveIndex(request);}); - server.on("/newui", HTTP_GET, [this](WebRequest *request) {serveNewUI(request);}); - - //StarBase modified version from https://github.com/theelims/ESP32-sveltekit/blob/main/lib/framework/ESP32SvelteKit.cpp - - #ifdef EMBED_WWW - // Serve static resources from PROGMEM - ESP_LOGV("ESP32SvelteKit", "Registering routes from PROGMEM static resources"); - WWWData::registerRoutes( - [this](const String &uri, const String &contentType, const uint8_t *content, size_t len) - { - server.on(uri.c_str(), HTTP_GET, [this, content, len, contentType](WebRequest *request) { - WebResponse *response; - response = request->beginResponse_P(200, contentType.c_str(), content, len); - response->addHeader("Content-Encoding","gzip"); - // response.addHeader("Cache-Control", "public, immutable, max-age=31536000"); //from svelte - // setStaticContentCacheHeaders(response); - request->send(response); - }); - - // Set default end-point for all non matching requests - // this is easier than using webServer.onNotFound() - // if (uri.equals("/index.html")) - // { - // _server->defaultEndpoint->setHandler(handler); - // } - }); - - #endif - - //serve json calls - server.on("/json", HTTP_GET, [this](WebRequest *request) {serveJson(request);}); - - server.addHandler(new AsyncCallbackJsonWebHandler("/json", [this](WebRequest *request, JsonVariant &json){jsonHandler(request, json);})); - - server.on("/update", HTTP_POST, [](WebRequest *) {}, [this](WebRequest *request, const String& fileName, size_t index, byte *data, size_t len, bool final) {serveUpdate(request, fileName, index, data, len, final);}); - server.on("/file", HTTP_GET, [this](WebRequest *request) {serveFiles(request);}); - server.on("/upload", HTTP_POST, [](WebRequest *) {}, [this](WebRequest *request, const String& fileName, size_t index, byte *data, size_t len, bool final) {serveUpload(request, fileName, index, data, len, final);}); - - server.onNotFound([this](AsyncWebServerRequest *request) { - ppf("Not-Found HTTP call: URI: %s\n", request->url().c_str()); ///hotspot-detect.html - if (this->captivePortal(request)) return; - }); - - // ppf("%s server (re)started\n", name); //causes crash for some reason... ppf("connectedChanged: web server (re)started %s \n", name); } //else remove handlers... } -//WebSocket connection to 'ws://192.168.1.152/ws' failed: The operation couldn’t be completed. Protocol error -//WS error 192.168.1.126 9 (2) -//WS event data 0.0.0.0 (1) 0 0 0=0? 34 0 -//WS pong 0.0.0.0 9 (1) -//wsEvent deserializeJson failed with code EmptyInput - -// https://github.com/me-no-dev/ESPAsyncWebServer/blob/master/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino -void SysModWeb::wsEvent(WebSocket * ws, WebClient * client, AwsEventType type, void * arg, byte *data, size_t len){ - - if (type == WS_EVT_CONNECT) { - printClient("WS client connected", client); - - //send system constants - getResponseObject()["sysInfo"]["board"] = CONFIG_IDF_TARGET; - getResponseObject()["sysInfo"]["nrOfPins"] = NUM_DIGITAL_PINS; - getResponseObject()["sysInfo"]["pinTypes"].to(); - JsonArray pinTypes = getResponseObject()["sysInfo"]["pinTypes"]; - for (int i=0; igetPinType(i)); - } - - sendResponseObject(client); - - JsonArray model = mdl->model->as(); - - //inspired by https://github.com/bblanchon/ArduinoJson/issues/1280 - //store arrayindex and sort order in vector - std::vector aisvs; - size_t index = 0; - for (JsonObject moduleVar: model) { - ArrayIndexSortValue aisv; - aisv.index = index++; - aisv.value = Variable(moduleVar).order(); - aisvs.push_back(aisv); - } - //sort the vector by the order - std::sort(aisvs.begin(), aisvs.end(), [](const ArrayIndexSortValue &a, const ArrayIndexSortValue &b) {return a.value < b.value;}); - - //send model per module to stay under websocket size limit of 8192 - for (const ArrayIndexSortValue &aisv : aisvs) { - sendDataWs(model[aisv.index], client); //send definition to client - } - - clientsChanged = true; - } else if (type == WS_EVT_DISCONNECT) { - printClient("WS Client disconnected", client); - clientsChanged = true; - } else if (type == WS_EVT_DATA) { - AwsFrameInfo * info = (AwsFrameInfo*)arg; - String msg = ""; - // ppf(" info %d %d %d=%d? %d %d\n", info->final, info->index, info->len, len, info->opcode, data[0]); - if (info->final && info->index == 0 && info->len == len) { //not multipart - recvWsCounter++; - recvWsBytes+=len; - // printClient("WS event data", client); - // the whole message is in a single frame and we got all of its data (max. 1450 bytes) - if (info->opcode == WS_TEXT) - { - if (len > 0 && len < 10 && data[0] == 'p') { - // application layer ping/pong heartbeat. - // client-side socket layer ping packets are unresponded (investigate) - // printClient("WS client pong", client); //crash? - ppf("pong\n"); - client->text("pong"); - } else { - JsonDocument *responseDoc = getResponseDoc(); //we need the doc for deserializeJson - JsonObject responseObject = getResponseObject(); - - DeserializationError error = deserializeJson(*responseDoc, data, len); //data to responseDoc - - if (error || responseObject.isNull()) { - ppf("wsEvent deserializeJson failed with code %s\n", error.c_str()); - client->text("{\"success\":true}"); // we have to send something back otherwise WS connection closes - } else { - bool isOnUI = !responseObject["onUI"].isNull(); - ui->processJson(responseObject); //adds to responseDoc / responseObject - - if (responseObject.size()) { - sendResponseObject(isOnUI?client:nullptr); //onUI only send to requesting client async response - } - else { - if (!isOnUI) //for onui we know json.remove(key) is done - ppf("wsEvent no responseDoc ui:%d\n", isOnUI); - client->text("{\"success\":true}"); // we have to send something back otherwise WS connection closes - } - } - } - } - } else { - //message is comprised of multiple frames or the frame is split into multiple packets - if(info->index == 0){ - // if(info->num == 0) - // ppf("ws[%s][%u] %s-message start\n", ws.url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); - // ppf("ws[%s][%u] frame[%u] start[%llu]\n", ws.url(), client->id(), info->num, info->len); - ppf("💀"); - } - - // ppf("ws[%s][%u] frame[%u] %s[%llu - %llu]: ", ws.url(), client->id(), info->num, (info->message_opcode == WS_TEXT)?"text":"binary", info->index, info->index + len); - ppf("💀"); - - if(info->opcode == WS_TEXT){ - for (size_t i=0; i < len; i++) { - msg += (char) data[i]; - } - } - // else { - // char buff[3]; - // for (size_t i=0; i < len; i++) { - // snprintf(buff, sizeof(buf), "%02x ", (uint8_t) data[i]); - // msg += buff ; - // } - // } - ppf("%s\n",msg.c_str()); - - if ((info->index + len) == info->len) { - // ppf("ws[%s][%u] frame[%u] end[%llu]\n", ws.url(), client->id(), info->num, info->len); - ppf("👻"); - if(info->final){ - // ppf("ws[%s][%u] %s-message end\n", ws.url(), client->id(), (info->message_opcode == WS_TEXT)?"text":"binary"); - ppf("☠️"); - if(info->message_opcode == WS_TEXT) - client->text("I got your text message"); - else - client->binary("I got your binary message"); - } - } - - //message is comprised of multiple frames or the frame is split into multiple packets - //if(info->index == 0){ - //if (!wsFrameBuffer && len < 4096) wsFrameBuffer = new uint8_t[4096]; - //} - - //if (wsFrameBuffer && len < 4096 && info->index + info->) - //{ - - //} - - // if((info->index + len) == info->len){ - // if(info->final){ - // if(info->message_opcode == WS_TEXT) { - // client->text("{\"error\":9}"); //we do not handle split packets right now - // ppf("WS multipart message: we do not handle split packets right now\n"); - // } - // } - // } - // ppf("WS multipart message f:%d i:%d len:%d == %d\n", info->final, info->index, info->len, len); - } - } else if (type == WS_EVT_ERROR){ - //error was received from the other end - // printClient("WS error", client); //crashes - // ppf("WS error\n"); - ppf("ws[%s][%u] error(): \n", ws->url(), client->id());//, *((uint16_t*)arg));//, (char*)data); - } else if (type == WS_EVT_PONG){ - //pong message was received (in response to a ping request maybe) - // printClient("WS pong", client); //crashes! - // ppf("WS pong\n"); - // ppf("ws[%s][%u] pong[%u]: %s\n", ws.url(), client->id(), len, (len)?(char*)data:""); - ppf("ws[%s][%u] pong[%u]: \n", ws->url(), client->id(), len);//, (len)?(char*)data:""); - } -} - -void SysModWeb::sendDataWs(JsonVariant json, WebClient * client) { - - size_t len = measureJson(json); - sendDataWs([json, len](AsyncWebSocketMessageBuffer * wsBuf) { - serializeJson(json, wsBuf->get(), len); - }, len, false, client); //false -> text -} - -//https://kcwong-joe.medium.com/passing-a-function-as-a-parameter-in-c-a132e69669f6 -void SysModWeb::sendDataWs(std::function fill, size_t len, bool isBinary, WebClient * client) { - - xSemaphoreTake(wsMutex, portMAX_DELAY); - - ws.cleanupClients(); //only if above threshold - - if (ws.count()) { - if (len > 8192) - ppf("dev sendDataWs BufferLen too high !!!%d\n", len); - AsyncWebSocketMessageBuffer * wsBuf = ws.makeBuffer(len); //assert failed: block_trim_free heap_tlsf.c:371 (block_is_free(block) && "block must be free"), AsyncWebSocket::makeBuffer(unsigned int) - - if (wsBuf) { - wsBuf->lock(); - - fill(wsBuf); //function parameter - - sendBuffer(wsBuf, isBinary, client); - - wsBuf->unlock(); - ws._cleanBuffers(); - } - else { - ppf("sendDataWs WS buffer allocation failed\n"); - ws.closeAll(1013); //code 1013 = temporary overload, try again later - ws.cleanupClients(0); //disconnect ALL clients to release memory - ws._cleanBuffers(); - } - } - - xSemaphoreGive(wsMutex); -} - -void SysModWeb::sendBuffer(AsyncWebSocketMessageBuffer * wsBuf, bool isBinary, WebClient * client, bool lossless) { - for (auto &loopClient:ws.getClients()) { - if (!client || client == loopClient) { - if (loopClient->status() == WS_CONNECTED && !loopClient->queueIsFull()) { //WS_MAX_QUEUED_MESSAGES / ws.count() / 2)) { //binary is lossy - if (!isBinary || !lossless || loopClient->queueLen() <= 3) { - isBinary?loopClient->binary(wsBuf): loopClient->text(wsBuf); - sendWsCounter++; - if (isBinary) - sendWsBBytes+=wsBuf->length(); - else - sendWsTBytes+=wsBuf->length(); - } - else if (!lossless) ppf("sendBuffer not successful l:%d b:%d q:%d", wsBuf->length(), isBinary, loopClient->queueLen()); - } - else { - printClient("sendDataWs client full or not connected", loopClient); - // ppf("sendDataWs client full or not connected\n"); - ws.cleanupClients(); //only if above threshold - ws._cleanBuffers(); - } - } - } -} - -//add an url to the webserver to listen to -void SysModWeb::serveIndex(WebRequest *request) { - - ppf("Webserver: server.on serveIndex csdata %d-%d (%s)", PAGE_index, PAGE_index_L, request->url().c_str()); - - if (captivePortal(request)) return; - - // if (handleIfNoneMatchCacheHeader(request)) return; - - WebResponse *response; - response = request->beginResponse_P(200, "text/html", PAGE_index, PAGE_index_L); - response->addHeader("Content-Encoding","gzip"); - // setStaticContentCacheHeaders(response); - request->send(response); - - ppf("!\n"); -} -void SysModWeb::serveNewUI(WebRequest *request) { - - ppf("Webserver: server.on serveNewUI csdata %d-%d (%s)", PAGE_newui, PAGE_newui_L, request->url().c_str()); - - if (captivePortal(request)) return; - - // if (handleIfNoneMatchCacheHeader(request)) return; - - WebResponse *response; - response = request->beginResponse_P(200, "text/html", PAGE_newui, PAGE_newui_L); - response->addHeader("Content-Encoding","gzip"); - // setStaticContentCacheHeaders(response); - request->send(response); - - ppf("!\n"); -} - -void SysModWeb::serveUpload(WebRequest *request, const String& fileName, size_t index, byte *data, size_t len, bool final) { - // curl -F 'data=@fixture1.json' 192.168.1.213/upload - // ppf("serveUpload i:%d l:%d f:%d\n", index, len, final); - mdl->setValue("Files", "upload", index/50000); - sendResponseObject(); //otherwise not send in asyn_tcp thread - - if (!index) { - isBusy = true; - ppf("File upload %s %s start\n", request->url().c_str(), fileName.c_str()); - String finalname = fileName; - if (finalname.charAt(0) != '/') { - finalname = '/' + finalname; // prepend slash if missing - } - - request->_tempFile = files->open(finalname.c_str(), FILE_WRITE); - // DEBUG_PRINT("Uploading "); - // DEBUG_PRINTLN(finalname); - // if (finalname.equals("/presets.json")) presetsModifiedTime = toki.second(); - } - if (len) { - request->_tempFile.write(data,len); - } - if (final) { - request->_tempFile.close(); - - mdl->setValue("Files", "upload", UINT16_MAX - 10); //success - sendResponseObject(); //otherwise not send in asyn_tcp thread - - request->send(200, "text/plain", F("File Uploaded!")); - - files->filesChanged = true; - - ppf("File upload %s %s finished\n", request->url().c_str(), fileName.c_str()); - - //if sc files send command to live - #ifdef STARBASE_USERMOD_LIVE - - if (fileName.indexOf(".sc") > 0) { - ppf("sc file added %s\n", fileName.c_str()); - size_t seqNr = UINT8_MAX; - files->nameToSeqNr((fileName).c_str(), &seqNr, ".sc"); - - if (seqNr != UINT8_MAX) { - //now only working for rowNr 0 !!! TBD! - mdl->setValue("effect", "script", 0, 0); //kill the old - mdl->setValue("effect", "script", seqNr + 1, 0); //+1 as None is in dropdown - } - } - - // got multiple definition error here ??? - // if (filename.indexOf(".sc") > 0) - // liveM->run(filename.c_str()); - #endif - - isBusy = false; - } -} - -void SysModWeb::serveUpdate(WebRequest *request, const String& fileName, size_t index, byte *data, size_t len, bool final) { - - // curl -F 'data=@fixture1.json' 192.168.1.213/upload - // ppf("serveUpdate r:%s f:%s i:%d l:%d f:%d\n", index, len, final); - - mdl->setValue("System", "update", index/50000); //therefore about once per second - sendResponseObject(); //otherwise not send in asyn_tcp thread - - if (!index) { - isBusy = true; - - ppf("OTA Update %s %s start\n", request->url().c_str(), fileName.c_str()); - // WLED::instance().disableWatchdog(); - // usermods.onUpdateBegin(true); // notify usermods that update is about to begin (some may require task de-init) - // lastEditTime = millis(); // make sure PIN does not lock during update - Update.begin((ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000); - } - - if (!Update.hasError()) - Update.write(data, len); - else { - mdl->setValue("System", "update", UINT16_MAX - 20); //fail - sendResponseObject(); //otherwise not send in asyn_tcp thread - } - - if (final) { - bool success = Update.end(true); - mdl->setValue("System", "update", success?UINT16_MAX - 10:UINT16_MAX - 20); - sendResponseObject(); //otherwise not send in asyn_tcp thread - - char message[64]; - const char * name = mdl->getValue("System", "name"); - - print->fFormat(message, sizeof(message), "Update of %s (...%d) %s", name, net->localIP()[3], success?"Successful":"Failed"); - - ppf("%s\n", message); - request->send(200, "text/plain", message); - - // usermods.onUpdateBegin(false); // notify usermods that update has failed (some may require task init) - // WLED::instance().enableWatchdog(); - - isBusy = false; - } -} - -void SysModWeb::serveFiles(WebRequest *request) { - - const char * urlString = request->url().c_str(); - const char * path = urlString + strnlen("/file", 6); //remove the uri from the path (skip their positions) - ppf("fileServer request %s\n", path); - if(LittleFS.exists(path)) { - isBusy = true; - request->send(LittleFS, path, "text/plain");//"application/json"); - isBusy = false; - } -} - -void SysModWeb::jsonHandler(WebRequest *request, JsonVariant json) { - - print->printJson("jsonHandler", json); - - JsonObject responseObject = getResponseObject(); - - ui->processJson(json); - - //WLED compatibility - if (json["v"]) { //WLED compatibility: verbose response - serveJson (request); //includes values just updated by processJson e.g. Bri - } - else { - - if (responseObject.size()) { //responseObject set by processJson e.g. onUI - - char resStr[200]; - serializeJson(responseObject, resStr, sizeof(resStr)); - ppf("processJsonUrl response %s\n", resStr); - request->send(200, "application/json", resStr); - - } - else - // request->send(200, "text/plain", "OK"); - request->send(200, "application/json", F("{\"success\":true}")); - } - - sendResponseObject(); -} - -void SysModWeb::clientsToJson(JsonArray array, bool nameOnly, const char * filter) { - for (auto &client:ws.getClients()) { - if (nameOnly) { - array.add(JsonString(client->remoteIP().toString().c_str())); - } else { - // ppf("Client %d %d ...%d\n", client->id(), client->queueIsFull(), client->remoteIP()[3]); - JsonArray row = array.add(); - row.add(client->id()); - array.add(JsonString(client->remoteIP().toString().c_str())); - row.add(client->queueIsFull()); - row.add(client->status()); - row.add(client->queueLen()); - } - } -} - -bool SysModWeb::captivePortal(WebRequest *request) -{ - - if (ON_STA_FILTER(request)) return false; //only serve captive in AP mode - String hostH; - if (!request->hasHeader("Host")) return false; - hostH = request->getHeader("Host")->value(); - - if (!isIp(hostH) && hostH.indexOf(mdns->cmDNS) < 0) { //&& hostH.indexOf("wled.me") < 0 - ppf("captivePortal %d %d\n", net->localIP()[3], request->client()->localIP()[3]); - WebResponse *response = request->beginResponse(302); - response->addHeader(F("Location"), F("http://4.3.2.1")); - request->send(response); - return true; - } - return false; -} +// void SysModWeb::clientsToJson(JsonArray array, bool nameOnly, const char * filter) { +// for (auto &client:ws.getClients()) { +// if (nameOnly) { +// array.add(JsonString(client->remoteIP().toString().c_str())); +// } else { +// // ppf("Client %d %d ...%d\n", client->id(), client->queueIsFull(), client->remoteIP()[3]); +// JsonArray row = array.add(); +// row.add(client->id()); +// array.add(JsonString(client->remoteIP().toString().c_str())); +// row.add(client->queueIsFull()); +// row.add(client->status()); +// row.add(client->queueLen()); +// } +// } +// } JsonDocument * SysModWeb::getResponseDoc() { // ppf("response wsevent core %d %s\n", xPortGetCoreID(), pcTaskGetTaskName(nullptr)); @@ -694,51 +208,6 @@ JsonObject SysModWeb::getResponseObject() { return getResponseDoc()->as(); } -void SysModWeb::sendResponseObject(WebClient * client) { - JsonObject responseObject = getResponseObject(); - if (responseObject.size()) { - // if (strncmp(pcTaskGetTaskName(nullptr), "loopTask", 8) != 0) { - // ppf("send "); - // char sep[3] = ""; - // for (JsonPair pair: responseObject) { - // ppf("%s%s", sep, pair.key().c_str()); - // strlcpy(sep, ", ", sizeof(sep)); - // if (pair.value().is()) { - // char sep[3] = ""; - // ppf("{"); - // for (JsonPair pair: pair.value().as()) { - // ppf("%s%s", sep, pair.key().c_str()); - // strlcpy(sep, ", ", sizeof(sep)); - // } - // ppf("}"); - // } - // } - // ppf("\n"); - // } - - size_t len = measureJson(responseObject); - AsyncWebSocketMessageBuffer * wsBuf = ws.makeBuffer(len); //assert failed: block_trim_free heap_tlsf.c:371 (block_is_free(block) && "block must be free"), AsyncWebSocket::makeBuffer(unsigned int) - if (wsBuf) { - wsBuf->lock(); - - serializeJson(responseObject, wsBuf->get(), len); - - sendBuffer(wsBuf, false, client); //text - - wsBuf->unlock(); - ws._cleanBuffers(); - } - else { - ppf("sendDataWs WS buffer allocation failed\n"); - ws.closeAll(1013); //code 1013 = temporary overload, try again later - ws.cleanupClients(0); //disconnect ALL clients to release memory - ws._cleanBuffers(); - } - - getResponseDoc()->to(); //recreate! - } -} - void SysModWeb::serializeState(JsonVariant root) { const char* jsonState;// = "{\"transition\":7,\"ps\":9,\"pl\":-1,\"nl\":{\"on\":false,\"dur\":60,\"mode\":1,\"tbri\":0,\"rem\":-1},\"udpn\":{\"send\":false,\"recv\":true},\"lor\":0,\"mainseg\":0,\"seg\":[{\"id\":0,\"start\":0,\"stop\":144,\"len\":144,\"grp\":1,\"spc\":0,\"of\":0,\"on\":true,\"frz\":false,\"bri\":255,\"cct\":127,\"col\":[[182,15,98,0],[0,0,0,0],[255,224,160,0]],\"fx\":0,\"sx\":128,\"ix\":128,\"pal\":11,\"c1\":8,\"c2\":20,\"c3\":31,\"sel\":true,\"rev\":false,\"mi\":false,\"o1\":false,\"o2\":false,\"o3\":false,\"ssim\":0,\"mp12\":1}]}"; jsonState = "{\"on\":true,\"bri\":60,\"transition\":7,\"ps\":1,\"pl\":-1,\"AudioReactive\":{\"on\":true},\"nl\":{\"on\":false,\"dur\":60,\"mode\":1,\"tbri\":0,\"rem\":-1},\"udpn\":{\"send\":false,\"recv\":true,\"sgrp\":1,\"rgrp\":1},\"lor\":0,\"mainseg\":0,\"seg\":[{\"id\":0,\"start\":0,\"stop\":16,\"startY\":0,\"stopY\":16,\"len\":16,\"grp\":1,\"spc\":0,\"of\":0,\"on\":true,\"frz\":false,\"bri\":255,\"cct\":127,\"set\":0,\"col\":[[255,160,0],[0,0,0],[0,255,200]],\"fx\":139,\"sx\":240,\"ix\":236,\"pal\":11,\"c1\":255,\"c2\":64,\"c3\":16,\"sel\":true,\"rev\":false,\"mi\":false,\"rY\":false,\"mY\":false,\"tp\":false,\"o1\":false,\"o2\":true,\"o3\":false,\"si\":0,\"m12\":0}],\"ledmap\":0}"; @@ -772,39 +241,3 @@ void SysModWeb::serializeInfo(JsonVariant root) { // print->printJson("serveJson", root); } -void SysModWeb::serveJson(WebRequest *request) { - - AsyncJsonResponse * response; - - // return model.json - if (request->url().indexOf("mdl") > 0) { - JsonArray model = mdl->model->as(); - ppf("serveJson model ...%d, %s %d %d\n", request->client()->remoteIP()[3], request->url().c_str(), model.size(), measureJson(model)); - - response = new AsyncJsonResponse(true); //array, removed size as ArduinoJson v7 doesnt care (tbd: here copy is mode, see WLED for using reference) - JsonArray root = response->getRoot(); - - root.set(model); - } else { //WLED compatible - ppf("serveJson ...%d, %s\n", request->client()->remoteIP()[3], request->url().c_str()); - response = new AsyncJsonResponse(false); //object. removed size as ArduinoJson v7 doesnt care - JsonVariant root = response->getRoot(); - - //temporary set all WLED variables (as otherwise WLED-native does not show the instance): tbd: clean up (state still needed, info not) - - if (request->url().indexOf("state") > 0) { - serializeState(root); - } - else if (request->url().indexOf("info") > 0) { - serializeInfo(root); - } - else { - root["state"] = ""; root["info"] = ""; //init otherwise result is {} - serializeState(root["state"]); - serializeInfo(root["info"]); - } - } - - response->setLength(); - request->send(response); -} //serveJson \ No newline at end of file diff --git a/src/Sys/SysModWeb.h b/src/Sys/SysModWeb.h index efd51be1..3cb7b9d4 100644 --- a/src/Sys/SysModWeb.h +++ b/src/Sys/SysModWeb.h @@ -13,37 +13,10 @@ #include "SysModule.h" #include "SysModPrint.h" -#ifdef STARBASE_USE_Psychic - #include -#else - #include -#endif - - -#ifdef STARBASE_USE_Psychic - #define WebRequest PsychicRequest - #define WebClient PsychicWebSocketClient - #define WebServer PsychicHttpServer - #define WebSocket PsychicWebSocketHandler - #define WebResponse PsychicResponse -#else - #define WebRequest AsyncWebServerRequest - #define WebClient AsyncWebSocketClient - #define WebServer AsyncWebServer - #define WebSocket AsyncWebSocket - #define WebResponse AsyncWebServerResponse -#endif class SysModWeb:public SysModule { public: - #ifdef STARBASE_USE_Psychic - WebSocket ws = WebSocket(); - WebServer server = WebServer(); - #else - WebSocket ws = WebSocket("/ws"); - WebServer server = WebServer(80); - #endif SemaphoreHandle_t wsMutex = xSemaphoreCreateMutex(); @@ -73,38 +46,12 @@ class SysModWeb:public SysModule { void connectedChanged() override; - void wsEvent(WebSocket * ws, WebClient * client, AwsEventType type, void * arg, byte *data, size_t len); - //send json to client or all clients - void sendDataWs(JsonVariant json = JsonVariant(), WebClient * client = nullptr); - void sendDataWs(std::function fill, size_t len, bool isBinary, WebClient * client = nullptr); - void sendBuffer(AsyncWebSocketMessageBuffer * wsBuf, bool isBinary, WebClient * client = nullptr, bool lossless = true); - + //add an url to the webserver to listen to - void serveIndex(WebRequest *request); - void serveNewUI(WebRequest *request); //mdl and WLED style state and info void serializeState(JsonVariant root); void serializeInfo(JsonVariant root); - void serveJson(WebRequest *request); - - - // curl -F 'data=@fixture1.json' 192.168.1.213/upload - void serveUpload(WebRequest *request, const String& fileName, size_t index, byte *data, size_t len, bool final); - // curl -s -F "update=@/Users/ewoudwijma/Developer/GitHub/ewowi/StarBase/.pio/build/esp32dev/firmware.bin" 192.168.1.102/update /dev/null & - // curl -s -F "update=@/Users/ewoudwijma/Downloads/StarLight_24110513_esp32devICVLD.bin" 192.168.1.245/update /dev/null & - void serveUpdate(WebRequest *request, const String& fileName, size_t index, byte *data, size_t len, bool final); - void serveFiles(WebRequest *request); - - //processJsonUrl handles requests send in javascript using fetch and from a browser or curl - //try this !!!: - //curl -X POST "http://4.3.2.1/json" -d '{"Pins.pin19":false}' -H "Content-Type: application/json" - //curl -X POST "http://4.3.2.1/json" -d '{"Fixture.brightness":20, "v":true}' -H "Content-Type: application/json" - //curl -X POST "http://192.168.1.125/json" -d '{"leyers.effect":2}' -H "Content-Type: application/json" - //curl -X POST "http://192.168.1.152/json" -d '{"nrOfLeds":2000}' -H "Content-Type: application/json" - - //handle "v" and processJson (on /json) - void jsonHandler(WebRequest *request, JsonVariant json); //Is this an IP? bool isIp(const String& str) { @@ -117,8 +64,6 @@ class SysModWeb:public SysModule { return true; } - bool captivePortal(WebRequest *request); - template void addResponse(const JsonObject var, const char * key, Type value, const uint8_t rowNr = UINT8_MAX) { JsonObject responseObject = getResponseObject(); @@ -146,17 +91,11 @@ class SysModWeb:public SysModule { addResponse(var, key, JsonString(value)); } - void clientsToJson(JsonArray array, bool nameOnly = false, const char * filter = nullptr); + // void clientsToJson(JsonArray array, bool nameOnly = false, const char * filter = nullptr); //gets the right responseDoc, depending on which task you are in, alternative for requestJSONBufferLock JsonDocument * getResponseDoc(); JsonObject getResponseObject(); - void sendResponseObject(WebClient * client = nullptr); - - void printClient(const char * text, WebClient * client) { - ppf("%s client: %d ip:%s q:%d l:%d s:%d (#:%d)\n", text, client?client->id():-1, client?client->remoteIP().toString().c_str():"", client->queueIsFull(), client->queueLen(), client->status(), client->server()->count()); - //status: { WS_DISCONNECTED, WS_CONNECTED, WS_DISCONNECTING } - } private: bool modelUpdated = false; diff --git a/src/User/UserModLive.cpp b/src/User/UserModLive.cpp index e9f4902a..b90a0e2a 100644 --- a/src/User/UserModLive.cpp +++ b/src/User/UserModLive.cpp @@ -394,7 +394,7 @@ static float _time(float j) { ppf("Before parsing of %s\n", fileName); ppf("Heap %s:%d f:%d / t:%d (l:%d) B [%d %d]\n", __FUNCTION__, __LINE__, ESP.getFreeHeap(), ESP.getHeapSize(), ESP.getMaxAllocHeap(), esp_get_free_heap_size(), esp_get_free_internal_heap_size()); - ppf("Stack %d of %d B (async %d of %d B) %d\n", sys->sysTools_get_arduino_maxStackUsage(), getArduinoLoopTaskStackSize(), sys->sysTools_get_webserver_maxStackUsage(), CONFIG_ASYNC_TCP_STACK_SIZE, uxTaskGetStackHighWaterMark(xTaskGetCurrentTaskHandle())); + ppf("Stack %d of %d B (async %d B) %d\n", sys->sysTools_get_arduino_maxStackUsage(), getArduinoLoopTaskStackSize(), sys->sysTools_get_webserver_maxStackUsage(), uxTaskGetStackHighWaterMark(xTaskGetCurrentTaskHandle())); Executable executable = parser.parseScript(&scScript); executable.name = string(fileName);