mirror of
https://github.com/vincentvdwal/crust-craft.git
synced 2026-08-18 17:26:39 +02:00
add ap mode, modernize ui, split spoof code
This commit is contained in:
Generated
+11
-19
@@ -12,7 +12,8 @@
|
|||||||
"chart.js": "^4.5.0",
|
"chart.js": "^4.5.0",
|
||||||
"chartjs-adapter-date-fns": "^3.0.0",
|
"chartjs-adapter-date-fns": "^3.0.0",
|
||||||
"chartjs-plugin-annotation": "^3.1.0",
|
"chartjs-plugin-annotation": "^3.1.0",
|
||||||
"date-fns": "^4.1.0"
|
"date-fns": "^4.1.0",
|
||||||
|
"lucide-svelte": "^1.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/compat": "^1.2.5",
|
"@eslint/compat": "^1.2.5",
|
||||||
@@ -736,7 +737,6 @@
|
|||||||
"version": "0.3.13",
|
"version": "0.3.13",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
||||||
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
|
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/sourcemap-codec": "^1.5.0",
|
"@jridgewell/sourcemap-codec": "^1.5.0",
|
||||||
@@ -747,7 +747,6 @@
|
|||||||
"version": "2.3.5",
|
"version": "2.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
|
||||||
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
|
"integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/gen-mapping": "^0.3.5",
|
"@jridgewell/gen-mapping": "^0.3.5",
|
||||||
@@ -758,7 +757,6 @@
|
|||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
@@ -768,14 +766,12 @@
|
|||||||
"version": "1.5.5",
|
"version": "1.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
|
||||||
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
|
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@jridgewell/trace-mapping": {
|
"node_modules/@jridgewell/trace-mapping": {
|
||||||
"version": "0.3.30",
|
"version": "0.3.30",
|
||||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
|
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
|
||||||
"integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
|
"integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/resolve-uri": "^3.1.0",
|
"@jridgewell/resolve-uri": "^3.1.0",
|
||||||
@@ -1124,7 +1120,6 @@
|
|||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz",
|
||||||
"integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==",
|
"integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"acorn": "^8.9.0"
|
"acorn": "^8.9.0"
|
||||||
@@ -1535,7 +1530,6 @@
|
|||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||||
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
"integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
@@ -1807,7 +1801,6 @@
|
|||||||
"version": "8.15.0",
|
"version": "8.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
@@ -1870,7 +1863,6 @@
|
|||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
|
||||||
"integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
|
"integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
@@ -1880,7 +1872,6 @@
|
|||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||||
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
|
"integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
@@ -2005,7 +1996,6 @@
|
|||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
@@ -2378,7 +2368,6 @@
|
|||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
|
||||||
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
|
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/espree": {
|
"node_modules/espree": {
|
||||||
@@ -2416,7 +2405,6 @@
|
|||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/esrap/-/esrap-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/esrap/-/esrap-2.1.0.tgz",
|
||||||
"integrity": "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==",
|
"integrity": "sha512-yzmPNpl7TBbMRC5Lj2JlJZNPml0tzqoqP5B1JXycNUwtqma9AKCO0M2wHrdgsHcy1WRW7S9rJknAMtByg3usgA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||||
@@ -2737,7 +2725,6 @@
|
|||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz",
|
||||||
"integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
|
"integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "^1.0.6"
|
"@types/estree": "^1.0.6"
|
||||||
@@ -3088,7 +3075,6 @@
|
|||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
|
||||||
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
|
"integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/locate-path": {
|
"node_modules/locate-path": {
|
||||||
@@ -3128,11 +3114,19 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lucide-svelte": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lucide-svelte/-/lucide-svelte-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-WvzZgk0pqzgda+AErLvgWxHkfg/+GgUwqKMRHvzt0IqyMdmyEDzDCk3Z+Wo/3y753oIgx8u9Q4eUbWkghFa8Jg==",
|
||||||
|
"license": "ISC",
|
||||||
|
"peerDependencies": {
|
||||||
|
"svelte": "^3 || ^4 || ^5.0.0-next.42"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.30.19",
|
"version": "0.30.19",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
|
||||||
"integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==",
|
"integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||||
@@ -3921,7 +3915,6 @@
|
|||||||
"version": "5.38.8",
|
"version": "5.38.8",
|
||||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.38.8.tgz",
|
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.38.8.tgz",
|
||||||
"integrity": "sha512-UDpTbM/iuZ4MaMnn4ODB3rf5JKDyPOi5oJcopP0j7YHQ9BuJtsAqsR71r2N6AnJf7ygbalTJU5y8eSWGAQZjlQ==",
|
"integrity": "sha512-UDpTbM/iuZ4MaMnn4ODB3rf5JKDyPOi5oJcopP0j7YHQ9BuJtsAqsR71r2N6AnJf7ygbalTJU5y8eSWGAQZjlQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/remapping": "^2.3.4",
|
"@jridgewell/remapping": "^2.3.4",
|
||||||
@@ -4372,7 +4365,6 @@
|
|||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz",
|
||||||
"integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==",
|
"integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -47,6 +47,7 @@
|
|||||||
"chart.js": "^4.5.0",
|
"chart.js": "^4.5.0",
|
||||||
"chartjs-adapter-date-fns": "^3.0.0",
|
"chartjs-adapter-date-fns": "^3.0.0",
|
||||||
"chartjs-plugin-annotation": "^3.1.0",
|
"chartjs-plugin-annotation": "^3.1.0",
|
||||||
"date-fns": "^4.1.0"
|
"date-fns": "^4.1.0",
|
||||||
|
"lucide-svelte": "^1.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+178
@@ -7,6 +7,25 @@ settings:
|
|||||||
importers:
|
importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
|
dependencies:
|
||||||
|
'@cubejs-client/core':
|
||||||
|
specifier: ^1.3.67
|
||||||
|
version: 1.6.44
|
||||||
|
chart.js:
|
||||||
|
specifier: ^4.5.0
|
||||||
|
version: 4.5.1
|
||||||
|
chartjs-adapter-date-fns:
|
||||||
|
specifier: ^3.0.0
|
||||||
|
version: 3.0.0(chart.js@4.5.1)(date-fns@4.1.0)
|
||||||
|
chartjs-plugin-annotation:
|
||||||
|
specifier: ^3.1.0
|
||||||
|
version: 3.1.0(chart.js@4.5.1)
|
||||||
|
date-fns:
|
||||||
|
specifier: ^4.1.0
|
||||||
|
version: 4.1.0
|
||||||
|
lucide-svelte:
|
||||||
|
specifier: ^1.0.1
|
||||||
|
version: 1.0.1(svelte@5.38.8)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@eslint/compat':
|
'@eslint/compat':
|
||||||
specifier: ^1.2.5
|
specifier: ^1.2.5
|
||||||
@@ -77,6 +96,9 @@ importers:
|
|||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
|
'@cubejs-client/core@1.6.44':
|
||||||
|
resolution: {integrity: sha512-0J2i2xb4DQMdpZDnOnPUEz28fMgI04dbkePWxsGjCuCNcdr752f+iq9W1DZGzQ0JMdZfnSLmnaBrWWrcNMjATA==}
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.25.9':
|
'@esbuild/aix-ppc64@0.25.9':
|
||||||
resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==}
|
resolution: {integrity: sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -316,6 +338,9 @@ packages:
|
|||||||
'@jridgewell/trace-mapping@0.3.30':
|
'@jridgewell/trace-mapping@0.3.30':
|
||||||
resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==}
|
resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==}
|
||||||
|
|
||||||
|
'@kurkle/color@0.3.4':
|
||||||
|
resolution: {integrity: sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==}
|
||||||
|
|
||||||
'@nodelib/fs.scandir@2.1.5':
|
'@nodelib/fs.scandir@2.1.5':
|
||||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
@@ -694,6 +719,21 @@ packages:
|
|||||||
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
chart.js@4.5.1:
|
||||||
|
resolution: {integrity: sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==}
|
||||||
|
engines: {pnpm: '>=8'}
|
||||||
|
|
||||||
|
chartjs-adapter-date-fns@3.0.0:
|
||||||
|
resolution: {integrity: sha512-Rs3iEB3Q5pJ973J93OBTpnP7qoGwvq3nUnoMdtxO+9aoJof7UFcRbWcIDteXuYd1fgAvct/32T9qaLyLuZVwCg==}
|
||||||
|
peerDependencies:
|
||||||
|
chart.js: '>=2.8.0'
|
||||||
|
date-fns: '>=2.0.0'
|
||||||
|
|
||||||
|
chartjs-plugin-annotation@3.1.0:
|
||||||
|
resolution: {integrity: sha512-EkAed6/ycXD/7n0ShrlT1T2Hm3acnbFhgkIEJLa0X+M6S16x0zwj1Fv4suv/2bwayCT3jGPdAtI9uLcAMToaQQ==}
|
||||||
|
peerDependencies:
|
||||||
|
chart.js: '>=4.0.0'
|
||||||
|
|
||||||
chokidar@4.0.3:
|
chokidar@4.0.3:
|
||||||
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
|
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
|
||||||
engines: {node: '>= 14.16.0'}
|
engines: {node: '>= 14.16.0'}
|
||||||
@@ -720,6 +760,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
|
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
|
core-js@3.49.0:
|
||||||
|
resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==}
|
||||||
|
|
||||||
|
cross-fetch@3.2.0:
|
||||||
|
resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==}
|
||||||
|
|
||||||
cross-spawn@7.0.6:
|
cross-spawn@7.0.6:
|
||||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
@@ -729,6 +775,28 @@ packages:
|
|||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
d3-array@3.2.4:
|
||||||
|
resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
d3-format@3.1.2:
|
||||||
|
resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
d3-time-format@4.1.0:
|
||||||
|
resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
d3-time@3.1.0:
|
||||||
|
resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
date-fns@4.1.0:
|
||||||
|
resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==}
|
||||||
|
|
||||||
|
dayjs@1.11.20:
|
||||||
|
resolution: {integrity: sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==}
|
||||||
|
|
||||||
debug@4.4.1:
|
debug@4.4.1:
|
||||||
resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
|
resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
|
||||||
engines: {node: '>=6.0'}
|
engines: {node: '>=6.0'}
|
||||||
@@ -920,6 +988,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
|
||||||
engines: {node: '>=0.8.19'}
|
engines: {node: '>=0.8.19'}
|
||||||
|
|
||||||
|
internmap@2.0.3:
|
||||||
|
resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
is-extglob@2.1.1:
|
is-extglob@2.1.1:
|
||||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -1053,6 +1125,11 @@ packages:
|
|||||||
lodash.merge@4.6.2:
|
lodash.merge@4.6.2:
|
||||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||||
|
|
||||||
|
lucide-svelte@1.0.1:
|
||||||
|
resolution: {integrity: sha512-WvzZgk0pqzgda+AErLvgWxHkfg/+GgUwqKMRHvzt0IqyMdmyEDzDCk3Z+Wo/3y753oIgx8u9Q4eUbWkghFa8Jg==}
|
||||||
|
peerDependencies:
|
||||||
|
svelte: ^3 || ^4 || ^5.0.0-next.42
|
||||||
|
|
||||||
magic-string@0.30.19:
|
magic-string@0.30.19:
|
||||||
resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==}
|
resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==}
|
||||||
|
|
||||||
@@ -1107,6 +1184,15 @@ packages:
|
|||||||
natural-compare@1.4.0:
|
natural-compare@1.4.0:
|
||||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||||
|
|
||||||
|
node-fetch@2.7.0:
|
||||||
|
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
||||||
|
engines: {node: 4.x || >=6.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
encoding: ^0.1.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
encoding:
|
||||||
|
optional: true
|
||||||
|
|
||||||
optionator@0.9.4:
|
optionator@0.9.4:
|
||||||
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@@ -1261,6 +1347,9 @@ packages:
|
|||||||
queue-microtask@1.2.3:
|
queue-microtask@1.2.3:
|
||||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||||
|
|
||||||
|
ramda@0.27.2:
|
||||||
|
resolution: {integrity: sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==}
|
||||||
|
|
||||||
readdirp@4.1.2:
|
readdirp@4.1.2:
|
||||||
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
|
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
|
||||||
engines: {node: '>= 14.18.0'}
|
engines: {node: '>= 14.18.0'}
|
||||||
@@ -1361,6 +1450,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
|
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
tr46@0.0.3:
|
||||||
|
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||||
|
|
||||||
ts-api-utils@2.1.0:
|
ts-api-utils@2.1.0:
|
||||||
resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==}
|
resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==}
|
||||||
engines: {node: '>=18.12'}
|
engines: {node: '>=18.12'}
|
||||||
@@ -1386,6 +1478,9 @@ packages:
|
|||||||
uri-js@4.4.1:
|
uri-js@4.4.1:
|
||||||
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||||
|
|
||||||
|
url-search-params-polyfill@7.0.1:
|
||||||
|
resolution: {integrity: sha512-bAw7L2E+jn9XHG5P9zrPnHdO0yJub4U+yXJOdpcpkr7OBd9T8oll4lUos0iSGRcDvfZoLUKfx9a6aNmIhJ4+mQ==}
|
||||||
|
|
||||||
util-deprecate@1.0.2:
|
util-deprecate@1.0.2:
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||||
|
|
||||||
@@ -1446,6 +1541,12 @@ packages:
|
|||||||
vite:
|
vite:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
webidl-conversions@3.0.1:
|
||||||
|
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||||
|
|
||||||
|
whatwg-url@5.0.0:
|
||||||
|
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
||||||
|
|
||||||
which@2.0.2:
|
which@2.0.2:
|
||||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
@@ -1472,6 +1573,19 @@ packages:
|
|||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
|
|
||||||
|
'@cubejs-client/core@1.6.44':
|
||||||
|
dependencies:
|
||||||
|
core-js: 3.49.0
|
||||||
|
cross-fetch: 3.2.0
|
||||||
|
d3-format: 3.1.2
|
||||||
|
d3-time-format: 4.1.0
|
||||||
|
dayjs: 1.11.20
|
||||||
|
ramda: 0.27.2
|
||||||
|
url-search-params-polyfill: 7.0.1
|
||||||
|
uuid: 11.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.25.9':
|
'@esbuild/aix-ppc64@0.25.9':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -1632,6 +1746,8 @@ snapshots:
|
|||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
|
'@kurkle/color@0.3.4': {}
|
||||||
|
|
||||||
'@nodelib/fs.scandir@2.1.5':
|
'@nodelib/fs.scandir@2.1.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@nodelib/fs.stat': 2.0.5
|
'@nodelib/fs.stat': 2.0.5
|
||||||
@@ -1987,6 +2103,19 @@ snapshots:
|
|||||||
ansi-styles: 4.3.0
|
ansi-styles: 4.3.0
|
||||||
supports-color: 7.2.0
|
supports-color: 7.2.0
|
||||||
|
|
||||||
|
chart.js@4.5.1:
|
||||||
|
dependencies:
|
||||||
|
'@kurkle/color': 0.3.4
|
||||||
|
|
||||||
|
chartjs-adapter-date-fns@3.0.0(chart.js@4.5.1)(date-fns@4.1.0):
|
||||||
|
dependencies:
|
||||||
|
chart.js: 4.5.1
|
||||||
|
date-fns: 4.1.0
|
||||||
|
|
||||||
|
chartjs-plugin-annotation@3.1.0(chart.js@4.5.1):
|
||||||
|
dependencies:
|
||||||
|
chart.js: 4.5.1
|
||||||
|
|
||||||
chokidar@4.0.3:
|
chokidar@4.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
readdirp: 4.1.2
|
readdirp: 4.1.2
|
||||||
@@ -2005,6 +2134,14 @@ snapshots:
|
|||||||
|
|
||||||
cookie@0.6.0: {}
|
cookie@0.6.0: {}
|
||||||
|
|
||||||
|
core-js@3.49.0: {}
|
||||||
|
|
||||||
|
cross-fetch@3.2.0:
|
||||||
|
dependencies:
|
||||||
|
node-fetch: 2.7.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
|
||||||
cross-spawn@7.0.6:
|
cross-spawn@7.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
path-key: 3.1.1
|
path-key: 3.1.1
|
||||||
@@ -2013,6 +2150,24 @@ snapshots:
|
|||||||
|
|
||||||
cssesc@3.0.0: {}
|
cssesc@3.0.0: {}
|
||||||
|
|
||||||
|
d3-array@3.2.4:
|
||||||
|
dependencies:
|
||||||
|
internmap: 2.0.3
|
||||||
|
|
||||||
|
d3-format@3.1.2: {}
|
||||||
|
|
||||||
|
d3-time-format@4.1.0:
|
||||||
|
dependencies:
|
||||||
|
d3-time: 3.1.0
|
||||||
|
|
||||||
|
d3-time@3.1.0:
|
||||||
|
dependencies:
|
||||||
|
d3-array: 3.2.4
|
||||||
|
|
||||||
|
date-fns@4.1.0: {}
|
||||||
|
|
||||||
|
dayjs@1.11.20: {}
|
||||||
|
|
||||||
debug@4.4.1:
|
debug@4.4.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
@@ -2232,6 +2387,8 @@ snapshots:
|
|||||||
|
|
||||||
imurmurhash@0.1.4: {}
|
imurmurhash@0.1.4: {}
|
||||||
|
|
||||||
|
internmap@2.0.3: {}
|
||||||
|
|
||||||
is-extglob@2.1.1: {}
|
is-extglob@2.1.1: {}
|
||||||
|
|
||||||
is-glob@4.0.3:
|
is-glob@4.0.3:
|
||||||
@@ -2330,6 +2487,10 @@ snapshots:
|
|||||||
|
|
||||||
lodash.merge@4.6.2: {}
|
lodash.merge@4.6.2: {}
|
||||||
|
|
||||||
|
lucide-svelte@1.0.1(svelte@5.38.8):
|
||||||
|
dependencies:
|
||||||
|
svelte: 5.38.8
|
||||||
|
|
||||||
magic-string@0.30.19:
|
magic-string@0.30.19:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
@@ -2369,6 +2530,10 @@ snapshots:
|
|||||||
|
|
||||||
natural-compare@1.4.0: {}
|
natural-compare@1.4.0: {}
|
||||||
|
|
||||||
|
node-fetch@2.7.0:
|
||||||
|
dependencies:
|
||||||
|
whatwg-url: 5.0.0
|
||||||
|
|
||||||
optionator@0.9.4:
|
optionator@0.9.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
deep-is: 0.1.4
|
deep-is: 0.1.4
|
||||||
@@ -2450,6 +2615,8 @@ snapshots:
|
|||||||
|
|
||||||
queue-microtask@1.2.3: {}
|
queue-microtask@1.2.3: {}
|
||||||
|
|
||||||
|
ramda@0.27.2: {}
|
||||||
|
|
||||||
readdirp@4.1.2: {}
|
readdirp@4.1.2: {}
|
||||||
|
|
||||||
resolve-from@4.0.0: {}
|
resolve-from@4.0.0: {}
|
||||||
@@ -2579,6 +2746,8 @@ snapshots:
|
|||||||
|
|
||||||
totalist@3.0.1: {}
|
totalist@3.0.1: {}
|
||||||
|
|
||||||
|
tr46@0.0.3: {}
|
||||||
|
|
||||||
ts-api-utils@2.1.0(typescript@5.9.2):
|
ts-api-utils@2.1.0(typescript@5.9.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
typescript: 5.9.2
|
typescript: 5.9.2
|
||||||
@@ -2604,6 +2773,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode: 2.3.1
|
punycode: 2.3.1
|
||||||
|
|
||||||
|
url-search-params-polyfill@7.0.1: {}
|
||||||
|
|
||||||
util-deprecate@1.0.2: {}
|
util-deprecate@1.0.2: {}
|
||||||
|
|
||||||
uuid@11.1.0: {}
|
uuid@11.1.0: {}
|
||||||
@@ -2630,6 +2801,13 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
vite: 7.1.5(jiti@2.5.1)(lightningcss@1.30.1)
|
vite: 7.1.5(jiti@2.5.1)(lightningcss@1.30.1)
|
||||||
|
|
||||||
|
webidl-conversions@3.0.1: {}
|
||||||
|
|
||||||
|
whatwg-url@5.0.0:
|
||||||
|
dependencies:
|
||||||
|
tr46: 0.0.3
|
||||||
|
webidl-conversions: 3.0.1
|
||||||
|
|
||||||
which@2.0.2:
|
which@2.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
isexe: 2.0.0
|
isexe: 2.0.0
|
||||||
|
|||||||
+365
-122
@@ -2,127 +2,213 @@
|
|||||||
@plugin '@tailwindcss/forms';
|
@plugin '@tailwindcss/forms';
|
||||||
@plugin '@tailwindcss/typography';
|
@plugin '@tailwindcss/typography';
|
||||||
|
|
||||||
|
/* ── Design tokens ─────────────────────────────────────── */
|
||||||
|
:root {
|
||||||
|
--bg: #0f1117;
|
||||||
|
--surface: #1a1d27;
|
||||||
|
--surface-raised: #22263a;
|
||||||
|
--border: rgba(255, 255, 255, 0.07);
|
||||||
|
--text: #e8eaf0;
|
||||||
|
--text-muted: #7a7f96;
|
||||||
|
--accent: #f97316;
|
||||||
|
--accent-dim: rgba(249, 115, 22, 0.15);
|
||||||
|
--green: #22c55e;
|
||||||
|
--red: #ef4444;
|
||||||
|
--radius: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme='light'] {
|
||||||
|
--bg: #f4f5f7;
|
||||||
|
--surface: #ffffff;
|
||||||
|
--surface-raised: #eef0f4;
|
||||||
|
--border: rgba(0, 0, 0, 0.08);
|
||||||
|
--text: #1a1d27;
|
||||||
|
--text-muted: #6b7280;
|
||||||
|
--accent-dim: rgba(249, 115, 22, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Base ──────────────────────────────────────────────── */
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
font-family:
|
font-family:
|
||||||
ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
|
ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji';
|
||||||
'Noto Color Emoji';
|
background: var(--bg);
|
||||||
margin: 0
|
color: var(--text);
|
||||||
|
margin: 0;
|
||||||
|
min-height: 100dvh;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Nav ───────────────────────────────────────────────── */
|
||||||
.nav {
|
.nav {
|
||||||
background-color: black;
|
background: var(--surface);
|
||||||
color: white;
|
border-bottom: 1px solid var(--border);
|
||||||
width: full;
|
padding: 0.75rem 1rem;
|
||||||
text-align: center;
|
display: flex;
|
||||||
padding: 1em;
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-title {
|
.nav-title {
|
||||||
font-size: xx-large;
|
font-size: 1.5rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--accent);
|
||||||
|
letter-spacing: 0.05em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.dark-mode-btn {
|
||||||
max-width: 1000px;
|
position: absolute;
|
||||||
margin: auto;
|
right: 1rem;
|
||||||
}
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
.card-grid {
|
background: var(--surface-raised);
|
||||||
margin-top: 15px;
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.graph {
|
|
||||||
height: 400px;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
padding: 0.4rem;
|
||||||
|
transition:
|
||||||
|
color 0.15s,
|
||||||
|
border-color 0.15s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plot-wrapper {
|
.dark-mode-btn:hover {
|
||||||
height: 400px;
|
color: var(--accent);
|
||||||
|
border-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Layout ────────────────────────────────────────────── */
|
||||||
|
.content {
|
||||||
|
max-width: 960px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 1.5rem 1rem 4rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Status cards ──────────────────────────────────────── */
|
||||||
|
.card-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 540px) {
|
||||||
|
.card-grid {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
||||||
|
.card-grid > :nth-child(3) {
|
||||||
|
grid-column: span 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 1.1rem 1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
min-width: 25%;
|
gap: 0.25rem;
|
||||||
padding: 1em;
|
transition: box-shadow 0.2s;
|
||||||
min-height: 120px;
|
|
||||||
box-shadow: 2px 2px 12px 1px rgba(140, 140, 140, .5);
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.reading {
|
.card-label {
|
||||||
font-weight: bold;
|
font-size: 0.7rem;
|
||||||
margin-top: 18px;
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-value {
|
||||||
@property --ovenColor1 {
|
font-size: 2.2rem;
|
||||||
syntax: '<color>';
|
font-weight: 700;
|
||||||
initial-value: rgba(255, 0, 0, 0);
|
line-height: 1;
|
||||||
inherits: false;
|
color: var(--text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-unit {
|
||||||
@property --ovenColor2 {
|
font-size: 1rem;
|
||||||
syntax: '<color>';
|
font-weight: 400;
|
||||||
initial-value: rgba(255, 0, 0, 0);
|
color: var(--text-muted);
|
||||||
inherits: false;
|
margin-left: 0.1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.oven {
|
.card-sub {
|
||||||
display: flex;
|
font-size: 0.75rem;
|
||||||
justify-content: center;
|
color: var(--text-muted);
|
||||||
margin: auto;
|
margin-top: 0.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.oven-wrapper {
|
.card-target {
|
||||||
background: radial-gradient(var(--ovenColor1), var(--ovenColor2), rgba(255, 0, 0, 0), rgba(255, 0, 0, 0));
|
font-size: 0.9rem;
|
||||||
width: 50%;
|
font-weight: 600;
|
||||||
display: flex;
|
color: var(--accent);
|
||||||
justify-content: center;
|
opacity: 0.8;
|
||||||
overflow: visible;
|
margin-top: 0.25rem;
|
||||||
padding: 30px;
|
letter-spacing: 0.02em;
|
||||||
transition: --ovenColor1 3s, --ovenColor2 3s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.oven.on .oven-wrapper {
|
@keyframes extreme-blink {
|
||||||
--ovenColor1: rgb(255, 60, 0);
|
0%,
|
||||||
--ovenColor2: rgba(255, 60, 0, 0.4);
|
100% {
|
||||||
|
color: #ef4444;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.oven .oven-img-wrapper {
|
.temp-extreme {
|
||||||
width: 65%;
|
animation: extreme-blink 0.6s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
.oven img {
|
/* ── Relay card ────────────────────────────────────────── */
|
||||||
width: 100%;
|
.relay-card {
|
||||||
}
|
|
||||||
|
|
||||||
.relais {
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
background: var(--surface);
|
||||||
|
transition:
|
||||||
|
background 0.3s,
|
||||||
|
box-shadow 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.relay-card:hover {
|
||||||
|
background: var(--surface-raised);
|
||||||
|
}
|
||||||
|
|
||||||
|
.relay-on {
|
||||||
|
box-shadow:
|
||||||
|
0 0 0 2px var(--red),
|
||||||
|
0 0 20px rgba(239, 68, 68, 0.25);
|
||||||
|
}
|
||||||
|
.relay-off {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ON/OFF toggle switch (visual-only inside the relay button) */
|
||||||
.onoffswitch {
|
.onoffswitch {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
margin-top: 10px;
|
margin: 0.5rem 0 0.15rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 90px;
|
width: 90px;
|
||||||
-webkit-user-select: none;
|
user-select: none;
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.onoffswitch-checkbox {
|
.onoffswitch-checkbox {
|
||||||
@@ -134,8 +220,7 @@ p {
|
|||||||
.onoffswitch-label {
|
.onoffswitch-label {
|
||||||
display: block;
|
display: block;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
cursor: pointer;
|
border: 2px solid rgba(255, 255, 255, 0.15);
|
||||||
border: 2px solid #999999;
|
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,88 +228,246 @@ p {
|
|||||||
display: block;
|
display: block;
|
||||||
width: 200%;
|
width: 200%;
|
||||||
margin-left: -100%;
|
margin-left: -100%;
|
||||||
transition: margin 0.3s ease-in 0s;
|
transition: margin 0.25s ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
.onoffswitch-inner:before,
|
.onoffswitch-inner::before,
|
||||||
.onoffswitch-inner:after {
|
.onoffswitch-inner::after {
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
float: left;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
padding: 0;
|
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
font-size: 14px;
|
font-size: 13px;
|
||||||
color: white;
|
font-weight: 700;
|
||||||
font-family: Trebuchet, Arial, sans-serif;
|
|
||||||
font-weight: bold;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.onoffswitch-inner:before {
|
.onoffswitch-inner::before {
|
||||||
content: "ON";
|
content: 'ON';
|
||||||
background-color: #C43535;
|
background-color: #c43535;
|
||||||
color: #FFFFFF;
|
color: #ffffff;
|
||||||
padding-right: 8px;
|
padding-right: 8px;
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.onoffswitch-inner:after {
|
.onoffswitch-inner::after {
|
||||||
content: "OFF";
|
content: 'OFF';
|
||||||
padding-left: 10px;
|
background-color: #444;
|
||||||
|
color: #aaa;
|
||||||
|
padding-left: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
background-color: #EEEEEE;
|
[data-theme='light'] .onoffswitch-inner::after {
|
||||||
color: #999999;
|
background-color: #d1d5db;
|
||||||
text-align: center;
|
color: #6b7280;
|
||||||
}
|
}
|
||||||
|
|
||||||
.onoffswitch-switch {
|
.onoffswitch-switch {
|
||||||
display: block;
|
display: block;
|
||||||
width: 22px;
|
width: 22px;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
margin: 6px;
|
margin: 4px;
|
||||||
background: #FFFFFF;
|
margin-left: 3px;
|
||||||
|
background: #ffffff;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 2px;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 56px;
|
right: 56px;
|
||||||
border: 2px solid #999999;
|
border: 2px solid rgba(255, 255, 255, 0.15);
|
||||||
border-radius: 20px;
|
border-radius: 50%;
|
||||||
transition: all 0.3s ease-in 0s;
|
transition: right 0.25s ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-inner {
|
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-inner {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.onoffswitch-checkbox:checked+.onoffswitch-label .onoffswitch-switch {
|
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-switch {
|
||||||
right: 0px;
|
right: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings {
|
/* ── Oven graphic ──────────────────────────────────────── */
|
||||||
margin-bottom: 200px;
|
@property --ovenColor1 {
|
||||||
margin-top: 50px;
|
syntax: '<color>';
|
||||||
|
initial-value: rgba(255, 0, 0, 0);
|
||||||
|
inherits: false;
|
||||||
|
}
|
||||||
|
@property --ovenColor2 {
|
||||||
|
syntax: '<color>';
|
||||||
|
initial-value: rgba(255, 0, 0, 0);
|
||||||
|
inherits: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings input {
|
.oven {
|
||||||
max-width: 50px;
|
display: flex;
|
||||||
font-size: larger;
|
justify-content: center;
|
||||||
font-weight: bold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.oven-wrapper {
|
||||||
|
background: radial-gradient(
|
||||||
|
circle at center,
|
||||||
|
var(--ovenColor1) 0%,
|
||||||
|
var(--ovenColor2) 30%,
|
||||||
|
transparent 68%
|
||||||
|
);
|
||||||
|
width: 60%;
|
||||||
|
max-width: 480px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 3.5rem;
|
||||||
|
transition:
|
||||||
|
--ovenColor1 2.5s,
|
||||||
|
--ovenColor2 2.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.oven.on .oven-wrapper {
|
||||||
|
--ovenColor1: rgba(255, 110, 0, 0.85);
|
||||||
|
--ovenColor2: rgba(255, 60, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.oven-img-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.oven img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Chart ─────────────────────────────────────────────── */
|
||||||
|
.chart-section {
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
padding: 1rem;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-section canvas {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Controls grid ─────────────────────────────────────── */
|
||||||
|
.controls-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 1rem;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.controls-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-card {
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 1.1rem 1.1rem 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Inputs ────────────────────────────────────────────── */
|
||||||
|
.input-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.num-input {
|
||||||
|
background: var(--surface-raised);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 1.1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 0.35rem 0.5rem;
|
||||||
|
width: 5.5rem;
|
||||||
|
outline: none;
|
||||||
|
transition: border-color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.num-input:focus {
|
||||||
|
border-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-unit {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-select {
|
||||||
|
background: var(--surface-raised);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 0.95rem;
|
||||||
|
padding: 0.4rem 0.6rem;
|
||||||
|
width: 100%;
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: border-color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mode-select:focus {
|
||||||
|
border-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Sub-controls (PWM / PID params) ───────────────────── */
|
||||||
|
.subcontrol-grid {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subcontrol {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sublabel {
|
||||||
|
font-size: 0.68rem;
|
||||||
|
font-weight: 600;
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.subinfo {
|
||||||
|
font-size: 0.78rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Action buttons ────────────────────────────────────── */
|
||||||
|
.action-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.35rem;
|
||||||
|
background: var(--surface-raised);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--text);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 0.45rem 0.9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
|
transition:
|
||||||
|
background 0.15s,
|
||||||
|
border-color 0.15s;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn:hover {
|
||||||
|
background: var(--accent-dim);
|
||||||
|
border-color: var(--accent);
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── Utility ───────────────────────────────────────────── */
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none !important;
|
||||||
}
|
|
||||||
|
|
||||||
#mode_span::first-letter {
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart div {
|
|
||||||
font: 10px sans-serif;
|
|
||||||
background-color: steelblue;
|
|
||||||
text-align: right;
|
|
||||||
padding: 3px;
|
|
||||||
margin: 1px;
|
|
||||||
color: white;
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
/**
|
||||||
|
* SpoofSocket – a fake WebSocket that simulates the ESP32 firmware.
|
||||||
|
* Used in DEV mode only. Cast to WebSocket with `as unknown as WebSocket`.
|
||||||
|
*
|
||||||
|
* Thermal model:
|
||||||
|
* – S-curve heating: rate peaks at ~50% of the target range (fast in the
|
||||||
|
* middle, slow at start/end), matching how a real oven behaves.
|
||||||
|
* – Newton's law of cooling when relay is off.
|
||||||
|
* – Small Gaussian noise on each tick for realism.
|
||||||
|
*
|
||||||
|
* Control modes mirror the firmware: manual, pwm, pid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const TICK_MS = 500; // matches WS_INTERVAL on the firmware
|
||||||
|
const ROOM_TEMP = 22; // °C ambient
|
||||||
|
const MAX_HEAT_RATE = 14; // °C/s at peak of S-curve
|
||||||
|
const NOISE_AMP = 0.35; // °C peak random noise
|
||||||
|
|
||||||
|
/** S-curve heating factor: parabolic 4x(1-x), peaks at x = 0.5. */
|
||||||
|
function heatFactor(temp: number, target: number): number {
|
||||||
|
if (target <= ROOM_TEMP) return 0;
|
||||||
|
const x = Math.max(0, Math.min(1, (temp - ROOM_TEMP) / (target - ROOM_TEMP)));
|
||||||
|
return 4 * x * (1 - x) + 0.02; // +0.02 so the oven starts moving immediately
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Newton's law of cooling – rate proportional to excess over ambient. */
|
||||||
|
function coolingRate(temp: number): number {
|
||||||
|
return (1.4 * Math.max(0, temp - ROOM_TEMP)) / 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
type SensorPayload = {
|
||||||
|
mode: string;
|
||||||
|
temperature: number;
|
||||||
|
relais: number;
|
||||||
|
target_temp: number;
|
||||||
|
pwm_on: number;
|
||||||
|
pwm_off: number;
|
||||||
|
pid: number;
|
||||||
|
kp: number;
|
||||||
|
ki: number;
|
||||||
|
kd: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Command = { cmd: string; value?: number | string };
|
||||||
|
|
||||||
|
export class SpoofSocket {
|
||||||
|
onopen: (() => void) | null = null;
|
||||||
|
onclose: (() => void) | null = null;
|
||||||
|
onmessage: ((e: { data: string }) => void) | null = null;
|
||||||
|
readyState: number = WebSocket.CONNECTING;
|
||||||
|
|
||||||
|
private s: SensorPayload = {
|
||||||
|
mode: 'manual',
|
||||||
|
temperature: ROOM_TEMP,
|
||||||
|
relais: 0,
|
||||||
|
target_temp: 460,
|
||||||
|
pwm_on: 2000,
|
||||||
|
pwm_off: 4000,
|
||||||
|
pid: 0,
|
||||||
|
kp: 0.6,
|
||||||
|
ki: 0.1,
|
||||||
|
kd: 0.0
|
||||||
|
};
|
||||||
|
|
||||||
|
private integral = 0;
|
||||||
|
private lastSwitch = Date.now();
|
||||||
|
private ticker: ReturnType<typeof setInterval> | null = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
// Simulate async connection handshake
|
||||||
|
setTimeout(() => {
|
||||||
|
this.readyState = WebSocket.OPEN;
|
||||||
|
this.onopen?.();
|
||||||
|
this.ticker = setInterval(() => this.tick(), TICK_MS);
|
||||||
|
}, 80);
|
||||||
|
}
|
||||||
|
|
||||||
|
send(raw: string): void {
|
||||||
|
try {
|
||||||
|
const { cmd, value } = JSON.parse(raw) as Command;
|
||||||
|
this.handle(cmd, value);
|
||||||
|
} catch {
|
||||||
|
// ignore malformed messages
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Stop the simulation ticker without triggering onclose (for cleanup). */
|
||||||
|
destroy(): void {
|
||||||
|
if (this.ticker !== null) {
|
||||||
|
clearInterval(this.ticker);
|
||||||
|
this.ticker = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(): void {
|
||||||
|
this.destroy();
|
||||||
|
this.readyState = WebSocket.CLOSED;
|
||||||
|
this.onclose?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
private handle(cmd: string, value?: number | string): void {
|
||||||
|
const s = this.s;
|
||||||
|
switch (cmd) {
|
||||||
|
case 'getReadings':
|
||||||
|
this.emit();
|
||||||
|
break;
|
||||||
|
case 'setTargetTemp':
|
||||||
|
s.target_temp = Number(value);
|
||||||
|
this.integral = 0; // reset integral on setpoint change
|
||||||
|
break;
|
||||||
|
case 'setMode':
|
||||||
|
s.mode = String(value);
|
||||||
|
if (s.mode === 'manual') s.relais = 0;
|
||||||
|
this.integral = 0;
|
||||||
|
break;
|
||||||
|
case 'switchRelais':
|
||||||
|
if (s.mode === 'manual') {
|
||||||
|
s.relais = s.relais ? 0 : 1;
|
||||||
|
this.lastSwitch = Date.now();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'setPWMOn':
|
||||||
|
s.pwm_on = Number(value) * 1000;
|
||||||
|
break;
|
||||||
|
case 'setPWMOff':
|
||||||
|
s.pwm_off = Number(value) * 1000;
|
||||||
|
break;
|
||||||
|
case 'setKp':
|
||||||
|
s.kp = Number(value);
|
||||||
|
break;
|
||||||
|
case 'setKi':
|
||||||
|
s.ki = Number(value);
|
||||||
|
break;
|
||||||
|
case 'setKd':
|
||||||
|
s.kd = Number(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private tick(): void {
|
||||||
|
const dt = TICK_MS / 1000;
|
||||||
|
const s = this.s;
|
||||||
|
const now = Date.now();
|
||||||
|
|
||||||
|
// ── relay control (mirrors firmware regulateRelais) ──────────────────
|
||||||
|
if (s.mode === 'pwm') {
|
||||||
|
const elapsed = now - this.lastSwitch;
|
||||||
|
if (s.relais === 1 && elapsed > s.pwm_on) {
|
||||||
|
s.relais = 0;
|
||||||
|
this.lastSwitch = now;
|
||||||
|
} else if (s.relais === 0 && elapsed > s.pwm_off) {
|
||||||
|
s.relais = 1;
|
||||||
|
this.lastSwitch = now;
|
||||||
|
}
|
||||||
|
} else if (s.mode === 'pid') {
|
||||||
|
const error = s.target_temp - s.temperature;
|
||||||
|
this.integral = Math.max(-100, Math.min(100, this.integral + s.ki * error * dt));
|
||||||
|
const output = Math.max(0, Math.min(100, s.kp * error + this.integral));
|
||||||
|
s.pid = output;
|
||||||
|
|
||||||
|
if (output > 0) {
|
||||||
|
const offDelay = s.pwm_on / (output / 100) - s.pwm_on;
|
||||||
|
const elapsed = now - this.lastSwitch;
|
||||||
|
if (s.relais === 1 && offDelay > 0 && elapsed > s.pwm_on) {
|
||||||
|
s.relais = 0;
|
||||||
|
this.lastSwitch = now;
|
||||||
|
} else if (s.relais === 0 && offDelay > 0 && elapsed > offDelay) {
|
||||||
|
s.relais = 1;
|
||||||
|
this.lastSwitch = now;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s.relais = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── thermal model ────────────────────────────────────────────────────
|
||||||
|
if (s.relais) {
|
||||||
|
s.temperature += MAX_HEAT_RATE * heatFactor(s.temperature, s.target_temp) * dt;
|
||||||
|
} else {
|
||||||
|
s.temperature -= coolingRate(s.temperature) * dt;
|
||||||
|
}
|
||||||
|
s.temperature = Math.max(ROOM_TEMP, s.temperature);
|
||||||
|
s.temperature += (Math.random() - 0.5) * NOISE_AMP;
|
||||||
|
|
||||||
|
this.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private emit(): void {
|
||||||
|
this.onmessage?.({ data: JSON.stringify(this.s) });
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-5
@@ -1,7 +1,3 @@
|
|||||||
export const pad = (n: string | number, amount = 2) => {
|
export const pad = (n: string | number, amount = 2) => {
|
||||||
if (amount === 2) {
|
return String(n).padStart(amount, '0');
|
||||||
return ('0' + n).slice(-2);
|
|
||||||
} else {
|
|
||||||
return ('00' + n).slice(-3);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
+90
-63
@@ -10,53 +10,62 @@
|
|||||||
#include "secrets.h"
|
#include "secrets.h"
|
||||||
#include "pid.h"
|
#include "pid.h"
|
||||||
|
|
||||||
// #define RELAY 21;
|
|
||||||
// #define THERMO_DO 19;
|
|
||||||
// #define THERMO_CS 23;
|
|
||||||
// #define THERMO_CLK 5;
|
|
||||||
|
|
||||||
AsyncWebServer server(80);
|
AsyncWebServer server(80);
|
||||||
AsyncWebSocket ws("/ws");
|
AsyncWebSocket ws("/ws");
|
||||||
|
|
||||||
|
// Pin assignments
|
||||||
|
constexpr int relay = 21;
|
||||||
|
constexpr int thermoDO = 19;
|
||||||
|
constexpr int thermoCS = 23;
|
||||||
|
constexpr int thermoCLK = 5;
|
||||||
|
|
||||||
// Timer variables
|
// Timer variables
|
||||||
unsigned long lastSensor = 0;
|
unsigned long lastSensor = 0;
|
||||||
unsigned long SENSOR_INTERVAL = 100;
|
const unsigned long SENSOR_INTERVAL = 100;
|
||||||
|
|
||||||
unsigned long lastWebSocket = 0;
|
unsigned long lastWebSocket = 0;
|
||||||
unsigned long WS_INTERVAL = 500;
|
const unsigned long WS_INTERVAL = 500;
|
||||||
|
|
||||||
int relay = 21;
|
|
||||||
int thermoDO = 19;
|
|
||||||
int thermoCS = 23;
|
|
||||||
int thermoCLK = 5;
|
|
||||||
|
|
||||||
float temperature = 0;
|
float temperature = 0;
|
||||||
int targetTemp = 300;
|
float targetTemp = 460;
|
||||||
|
|
||||||
unsigned long lastSwitch = 0;
|
unsigned long lastSwitch = 0;
|
||||||
float pwmSwitchDelayOn = 2000; // 2s
|
float pwmSwitchDelayOn = 2000; // 2s
|
||||||
float pwmSwitchDelayOff = 4000; // 4s
|
float pwmSwitchDelayOff = 4000; // 4s
|
||||||
|
|
||||||
float power = 0;
|
float power = 100;
|
||||||
|
|
||||||
float kp = 0.6;
|
float kp = 0.6;
|
||||||
float ki = 0.1;
|
float ki = 0.1;
|
||||||
float kd = 0.0;
|
float kd = 0.0;
|
||||||
|
|
||||||
String mode = "manual";
|
enum class Mode { MANUAL, PWM, PID };
|
||||||
|
Mode mode = Mode::MANUAL;
|
||||||
|
|
||||||
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
|
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);
|
||||||
|
|
||||||
PIDController pid(kp, ki, kd, 100.0, 0.0, 100.0); // Kp, Ki, Kd, max, min, max_integral
|
PIDController pid(kp, ki, kd, 100.0, 0.0, 100.0); // Kp, Ki, Kd, max, min, max_integral
|
||||||
|
|
||||||
|
static const char *modeToStr(Mode m)
|
||||||
|
{
|
||||||
|
switch (m)
|
||||||
|
{
|
||||||
|
case Mode::PWM:
|
||||||
|
return "pwm";
|
||||||
|
case Mode::PID:
|
||||||
|
return "pid";
|
||||||
|
default:
|
||||||
|
return "manual";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get Sensor Readings and return JSON object
|
// Get Sensor Readings and return JSON object
|
||||||
String getSensorReadings()
|
String getSensorReadings()
|
||||||
|
|
||||||
{
|
{
|
||||||
JsonDocument readings;
|
JsonDocument readings;
|
||||||
String jsonString;
|
String jsonString;
|
||||||
|
|
||||||
readings["mode"] = mode;
|
readings["mode"] = modeToStr(mode);
|
||||||
|
|
||||||
temperature = thermocouple.readCelsius();
|
temperature = thermocouple.readCelsius();
|
||||||
readings["temperature"] = temperature;
|
readings["temperature"] = temperature;
|
||||||
@@ -95,8 +104,18 @@ void initWiFi()
|
|||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
WiFi.begin(ssid, password);
|
WiFi.begin(ssid, password);
|
||||||
Serial.print("Connecting to WiFi ..");
|
Serial.print("Connecting to WiFi ..");
|
||||||
|
unsigned long startAttemptTime = millis();
|
||||||
while (WiFi.status() != WL_CONNECTED)
|
while (WiFi.status() != WL_CONNECTED)
|
||||||
{
|
{
|
||||||
|
if (millis() - startAttemptTime > 10000)
|
||||||
|
{
|
||||||
|
Serial.println("Wifi not found, starting AP mode");
|
||||||
|
WiFi.mode(WIFI_AP);
|
||||||
|
WiFi.softAP(ap_ssid, ap_password);
|
||||||
|
Serial.print("AP IP address: ");
|
||||||
|
Serial.println(WiFi.softAPIP());
|
||||||
|
break;
|
||||||
|
}
|
||||||
Serial.print('.');
|
Serial.print('.');
|
||||||
delay(SENSOR_INTERVAL);
|
delay(SENSOR_INTERVAL);
|
||||||
yield();
|
yield();
|
||||||
@@ -115,20 +134,30 @@ void handleWebSocketMessage(void *arg, uint8_t *data, size_t len)
|
|||||||
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT)
|
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT)
|
||||||
{
|
{
|
||||||
data[len] = 0;
|
data[len] = 0;
|
||||||
String message = (char *)data;
|
JsonDocument doc;
|
||||||
if (message.startsWith("getReadings"))
|
DeserializationError err = deserializeJson(doc, (char *)data);
|
||||||
|
if (err)
|
||||||
{
|
{
|
||||||
String sensorReadings = getSensorReadings();
|
Serial.printf("WS JSON parse error: %s\n", err.c_str());
|
||||||
notifyClients(sensorReadings);
|
return;
|
||||||
};
|
}
|
||||||
if (message.startsWith("switchRelais"))
|
|
||||||
|
const char *cmd = doc["cmd"];
|
||||||
|
if (!cmd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (strcmp(cmd, "getReadings") == 0)
|
||||||
|
{
|
||||||
|
notifyClients(getSensorReadings());
|
||||||
|
}
|
||||||
|
else if (strcmp(cmd, "switchRelais") == 0)
|
||||||
{
|
{
|
||||||
Serial.printf("\nSwitch Relais");
|
Serial.printf("\nSwitch Relais");
|
||||||
if (digitalRead(relay) == HIGH)
|
if (digitalRead(relay) == HIGH)
|
||||||
{
|
{
|
||||||
digitalWrite(relay, LOW);
|
digitalWrite(relay, LOW);
|
||||||
lastSwitch = millis();
|
lastSwitch = millis();
|
||||||
mode = "manual";
|
mode = Mode::MANUAL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -136,68 +165,55 @@ void handleWebSocketMessage(void *arg, uint8_t *data, size_t len)
|
|||||||
lastSwitch = millis();
|
lastSwitch = millis();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (message.startsWith("setTargetTemp"))
|
else if (strcmp(cmd, "setTargetTemp") == 0)
|
||||||
{
|
{
|
||||||
String target = message.substring(15, 18);
|
targetTemp = doc["value"].as<float>();
|
||||||
targetTemp = target.toFloat();
|
|
||||||
pid.setSetpoint(targetTemp);
|
pid.setSetpoint(targetTemp);
|
||||||
Serial.printf("\nTarget temp set to ");
|
Serial.printf("\nTarget temp set to %.1f°C", targetTemp);
|
||||||
Serial.print(targetTemp);
|
|
||||||
Serial.printf("°C");
|
|
||||||
}
|
}
|
||||||
if (message.startsWith("setMode"))
|
else if (strcmp(cmd, "setMode") == 0)
|
||||||
{
|
{
|
||||||
if (message.indexOf("pwm") > 0)
|
const char *value = doc["value"];
|
||||||
|
if (value && strcmp(value, "pwm") == 0)
|
||||||
{
|
{
|
||||||
mode = "pwm";
|
mode = Mode::PWM;
|
||||||
}
|
}
|
||||||
else if (message.indexOf("pid") > 0)
|
else if (value && strcmp(value, "pid") == 0)
|
||||||
{
|
{
|
||||||
mode = "pid";
|
mode = Mode::PID;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mode = "manual";
|
mode = Mode::MANUAL;
|
||||||
digitalWrite(relay, LOW);
|
digitalWrite(relay, LOW);
|
||||||
lastSwitch = millis();
|
lastSwitch = millis();
|
||||||
}
|
}
|
||||||
Serial.printf("\nMode set to ");
|
Serial.printf("\nMode set to %s", modeToStr(mode));
|
||||||
Serial.print(mode);
|
|
||||||
}
|
}
|
||||||
if (message.startsWith("setKp"))
|
else if (strcmp(cmd, "setKp") == 0)
|
||||||
{
|
{
|
||||||
String k = message.substring(6, 12);
|
kp = doc["value"].as<float>();
|
||||||
kp = k.toFloat();
|
|
||||||
pid.setSetKp(kp);
|
pid.setSetKp(kp);
|
||||||
}
|
}
|
||||||
if (message.startsWith("setKi"))
|
else if (strcmp(cmd, "setKi") == 0)
|
||||||
{
|
{
|
||||||
String k = message.substring(6, 12);
|
ki = doc["value"].as<float>();
|
||||||
ki = k.toFloat();
|
|
||||||
pid.setSetKi(ki);
|
pid.setSetKi(ki);
|
||||||
}
|
}
|
||||||
if (message.startsWith("setKd"))
|
else if (strcmp(cmd, "setKd") == 0)
|
||||||
{
|
{
|
||||||
String k = message.substring(6, 12);
|
kd = doc["value"].as<float>();
|
||||||
kd = k.toFloat();
|
|
||||||
pid.setSetKd(kd);
|
pid.setSetKd(kd);
|
||||||
}
|
}
|
||||||
if (message.startsWith("setPWMOn"))
|
else if (strcmp(cmd, "setPWMOn") == 0)
|
||||||
{
|
{
|
||||||
String target = message.substring(10, 15);
|
pwmSwitchDelayOn = doc["value"].as<float>() * 1000;
|
||||||
pwmSwitchDelayOn = target.toFloat() * 1000;
|
Serial.printf("\nPWM switch ON set to %.0fms", pwmSwitchDelayOn);
|
||||||
Serial.printf("\nPWM switch ON set to ");
|
|
||||||
Serial.print(pwmSwitchDelayOn);
|
|
||||||
Serial.printf("°C");
|
|
||||||
}
|
}
|
||||||
|
else if (strcmp(cmd, "setPWMOff") == 0)
|
||||||
if (message.startsWith("setPWMOff"))
|
|
||||||
{
|
{
|
||||||
String target = message.substring(11, 16);
|
pwmSwitchDelayOff = doc["value"].as<float>() * 1000;
|
||||||
pwmSwitchDelayOff = target.toFloat() * 1000;
|
Serial.printf("\nPWM switch OFF set to %.0fms", pwmSwitchDelayOff);
|
||||||
Serial.printf("\nPWM switch OFF set to ");
|
|
||||||
Serial.print(pwmSwitchDelayOff);
|
|
||||||
Serial.printf("°C");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -229,7 +245,7 @@ void initWebSocket()
|
|||||||
|
|
||||||
void regulateRelais()
|
void regulateRelais()
|
||||||
{
|
{
|
||||||
if (mode == "pwm")
|
if (mode == Mode::PWM)
|
||||||
{
|
{
|
||||||
if ((millis() - lastSwitch) > pwmSwitchDelayOn)
|
if ((millis() - lastSwitch) > pwmSwitchDelayOn)
|
||||||
{
|
{
|
||||||
@@ -249,11 +265,20 @@ void regulateRelais()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mode == "pid")
|
if (mode == Mode::PID)
|
||||||
{
|
{
|
||||||
// output = Kp×error + Ki×∫error×dt + Kd×(Δerror/Δt)
|
// output = Kp×error + Ki×∫error×dt + Kd×(Δerror/Δt)
|
||||||
power = pid.compute(temperature);
|
power = pid.compute(temperature);
|
||||||
pwmSwitchDelayOff = (pwmSwitchDelayOn / (power / 100)) - pwmSwitchDelayOn;
|
if (power > 0.0f)
|
||||||
|
{
|
||||||
|
pwmSwitchDelayOff = (pwmSwitchDelayOn / (power / 100.0f)) - pwmSwitchDelayOn;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pwmSwitchDelayOff = 0.0f;
|
||||||
|
digitalWrite(relay, LOW);
|
||||||
|
lastSwitch = millis();
|
||||||
|
}
|
||||||
|
|
||||||
if (pwmSwitchDelayOff > 0)
|
if (pwmSwitchDelayOff > 0)
|
||||||
{
|
{
|
||||||
@@ -291,6 +316,8 @@ void setup()
|
|||||||
initLittleFS();
|
initLittleFS();
|
||||||
initWebSocket();
|
initWebSocket();
|
||||||
|
|
||||||
|
digitalWrite(relay, HIGH);
|
||||||
|
|
||||||
// Web Server Root URL
|
// Web Server Root URL
|
||||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
|
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||||
{ request->send(LittleFS, "/index.html", "text/html"); });
|
{ request->send(LittleFS, "/index.html", "text/html"); });
|
||||||
|
|||||||
+397
-490
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,5 @@
|
|||||||
// Replace with your network credentials
|
// Replace with your network credentials
|
||||||
const char *ssid = "WIFI_SSID";
|
const char *ssid = "WIFI_SSID";
|
||||||
const char *password = "WIFI_PWD";
|
const char *password = "WIFI_PWD";
|
||||||
|
const char *ap_ssid = "CrustCraft";
|
||||||
|
const char *ap_password = "crustcr4ft";
|
||||||
Reference in New Issue
Block a user