diff --git a/interface/package.json b/interface/package.json index 0f4402192..1873df3a7 100644 --- a/interface/package.json +++ b/interface/package.json @@ -1,7 +1,7 @@ { "name": "EMS-ESP", "version": "3.7", - "description": "build EMS-ESP WebUI", + "description": "Build the EMS-ESP WebUI", "homepage": "https://emsesp.github.io/docs", "author": "proddy", "license": "MIT", @@ -12,9 +12,10 @@ "preview": "vite preview", "build-hosted": "typesafe-i18n --no-watch && vite build --mode hosted", "preview-standalone": "typesafe-i18n --no-watch && vite build && concurrently -c \"auto\" \"npm:mock-api\" \"vite preview\"", - "mock-api": "bun --watch ../mock-api/server.ts", + "mock-api": "bun --watch ../mock-api/rest_server.ts", + "mock-es": "bun --watch ../mock-api/es_server.ts", "old_mock-api": "bun --watch ../mock-api/server.js", - "standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"npm:mock-api\" \"vite\"", + "standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"npm:mock-api\" \"npm:mock-es\" \"vite\"", "old_standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"npm:old_mock-api\" \"vite\"", "typesafe-i18n": "typesafe-i18n --no-watch", "webUI": "node progmem-generator.js", @@ -25,18 +26,19 @@ "@alova/adapter-xhr": "^1.0.3", "@babel/core": "^7.24.3", "@emotion/react": "^11.11.4", - "@emotion/styled": "^11.11.0", + "@emotion/styled": "^11.11.5", "@mui/icons-material": "^5.15.14", "@mui/material": "^5.15.14", "@table-library/react-table-library": "4.1.7", "@types/imagemin": "^8.0.5", "@types/lodash-es": "^4.17.12", - "@types/node": "^20.11.30", - "@types/react": "^18.2.72", - "@types/react-dom": "^18.2.22", + "@types/node": "^20.12.2", + "@types/react": "^18.2.73", + "@types/react-dom": "^18.2.23", "@types/react-router-dom": "^5.3.3", - "alova": "^2.18.0", + "alova": "^2.18.2", "async-validator": "^4.2.5", + "eslint-plugin-prettier": "^5.1.3", "history": "^5.3.0", "jwt-decode": "^4.0.0", "lodash-es": "^4.17.21", @@ -47,7 +49,6 @@ "react-icons": "^5.0.1", "react-router-dom": "^6.22.3", "react-toastify": "^10.0.5", - "sockette": "^2.0.6", "typesafe-i18n": "^5.26.2", "typescript": "^5.4.3" }, @@ -62,15 +63,13 @@ "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-autofix": "^1.1.0", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.8.0", - "eslint-plugin-prettier": "alpha", "eslint-plugin-react": "^7.34.1", "eslint-plugin-react-hooks": "^4.6.0", "preact": "^10.20.1", "prettier": "^3.2.5", "rollup-plugin-visualizer": "^5.12.0", "terser": "^5.30.0", - "vite": "^5.2.6", + "vite": "^5.2.7", "vite-plugin-imagemin": "^0.6.1", "vite-tsconfig-paths": "^4.3.2" }, diff --git a/interface/vite.config.ts b/interface/vite.config.ts index e55510a06..008df4f7b 100644 --- a/interface/vite.config.ts +++ b/interface/vite.config.ts @@ -20,7 +20,7 @@ export default defineConfig(({ command, mode }) => { secure: false }, '/es': { - target: 'http://localhost:3080', + target: 'http://localhost:3081', changeOrigin: true, secure: false } diff --git a/interface/yarn.lock b/interface/yarn.lock index a22be1cc1..f4a7e2ca9 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -268,7 +268,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.7": +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.7": version: 7.24.1 resolution: "@babel/runtime@npm:7.24.1" dependencies: @@ -356,7 +356,7 @@ __metadata: languageName: node linkType: hard -"@emotion/is-prop-valid@npm:^1.2.1": +"@emotion/is-prop-valid@npm:^1.2.2": version: 1.2.2 resolution: "@emotion/is-prop-valid@npm:1.2.2" dependencies: @@ -406,6 +406,19 @@ __metadata: languageName: node linkType: hard +"@emotion/serialize@npm:^1.1.4": + version: 1.1.4 + resolution: "@emotion/serialize@npm:1.1.4" + dependencies: + "@emotion/hash": "npm:^0.9.1" + "@emotion/memoize": "npm:^0.8.1" + "@emotion/unitless": "npm:^0.8.1" + "@emotion/utils": "npm:^1.2.1" + csstype: "npm:^3.0.2" + checksum: 10/11fc4f960226778e9a5f86310b739703986d13b2de3e89a16d788126ce312b2c8c174a2947c9bfc80cb124b331c36feeac44193f81150616d94b1ba19a92d70a + languageName: node + linkType: hard + "@emotion/sheet@npm:^1.2.2": version: 1.2.2 resolution: "@emotion/sheet@npm:1.2.2" @@ -413,14 +426,14 @@ __metadata: languageName: node linkType: hard -"@emotion/styled@npm:^11.11.0": - version: 11.11.0 - resolution: "@emotion/styled@npm:11.11.0" +"@emotion/styled@npm:^11.11.5": + version: 11.11.5 + resolution: "@emotion/styled@npm:11.11.5" dependencies: "@babel/runtime": "npm:^7.18.3" "@emotion/babel-plugin": "npm:^11.11.0" - "@emotion/is-prop-valid": "npm:^1.2.1" - "@emotion/serialize": "npm:^1.1.2" + "@emotion/is-prop-valid": "npm:^1.2.2" + "@emotion/serialize": "npm:^1.1.4" "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.0.1" "@emotion/utils": "npm:^1.2.1" peerDependencies: @@ -429,7 +442,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 10/ac471a40645ee7bc950378ff9453028078bc2e45a6317f77636e4ed27f7ea61eb549b1efefdc5433640f73246ae5ee212e6c864085dc042b6541b2ffa0e21a49 + checksum: 10/a936787ef80d73066840391522d88280424de0abb56bec83d17e14bdc5a515e77e343dd171f7caae1405462e3f71815b5480dcc4e1eff5e8ff4a020f5c39341e languageName: node linkType: hard @@ -1397,7 +1410,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^20.11.30": +"@types/node@npm:*": version: 20.11.30 resolution: "@types/node@npm:20.11.30" dependencies: @@ -1406,6 +1419,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^20.12.2": + version: 20.12.2 + resolution: "@types/node@npm:20.12.2" + dependencies: + undici-types: "npm:~5.26.4" + checksum: 10/f1f0ebfe475aefa183763b856e0023b81b76554196e8676a45b9fcfd1012cdd20d32adefb3c0330001c0011e074676603c34c24821a4924228250ea13a75da43 + languageName: node + linkType: hard + "@types/parse-json@npm:^4.0.0": version: 4.0.2 resolution: "@types/parse-json@npm:4.0.2" @@ -1420,12 +1442,12 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:^18.2.22": - version: 18.2.22 - resolution: "@types/react-dom@npm:18.2.22" +"@types/react-dom@npm:^18.2.23": + version: 18.2.23 + resolution: "@types/react-dom@npm:18.2.23" dependencies: "@types/react": "npm:*" - checksum: 10/310da22244c1bb65a7f213f8727bda821dd211cfb2dd62d1f9b28dd50ef1c196d59e908494bd5f25c13a3844343f3a6135f39fb830aca6f79646fa56c1b56c08 + checksum: 10/8311c67767b0aafb5cd94176a90f801f0f5f6930731d57caaa04bb0d87fdef6bc6f723a116d9777d2082ec022682acaad7a62d04dc27e330e818cf34f2ef2703 languageName: node linkType: hard @@ -1470,13 +1492,13 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:^18.2.72": - version: 18.2.72 - resolution: "@types/react@npm:18.2.72" +"@types/react@npm:^18.2.73": + version: 18.2.73 + resolution: "@types/react@npm:18.2.73" dependencies: "@types/prop-types": "npm:*" csstype: "npm:^3.0.2" - checksum: 10/0c15461eeb8cd5153b48446d4aae681ae1d4f45fa5828fc53c12aaac9dfe426a64259a284737f6abfc3bea36df9507c129d7065ebb390b21349ad30128385ac1 + checksum: 10/799e30e73464dff40e04f4eb7499ebc31f99b1711a69263b9af340af738e35c9cdf53084e3dacc3b21c031aaa0cba1b51f4ba60490204b7abb75f115b841583f languageName: node linkType: hard @@ -1649,7 +1671,7 @@ __metadata: "@alova/adapter-xhr": "npm:^1.0.3" "@babel/core": "npm:^7.24.3" "@emotion/react": "npm:^11.11.4" - "@emotion/styled": "npm:^11.11.0" + "@emotion/styled": "npm:^11.11.5" "@mui/icons-material": "npm:^5.15.14" "@mui/material": "npm:^5.15.14" "@preact/compat": "npm:^17.1.2" @@ -1657,13 +1679,13 @@ __metadata: "@table-library/react-table-library": "npm:4.1.7" "@types/imagemin": "npm:^8.0.5" "@types/lodash-es": "npm:^4.17.12" - "@types/node": "npm:^20.11.30" - "@types/react": "npm:^18.2.72" - "@types/react-dom": "npm:^18.2.22" + "@types/node": "npm:^20.12.2" + "@types/react": "npm:^18.2.73" + "@types/react-dom": "npm:^18.2.23" "@types/react-router-dom": "npm:^5.3.3" "@typescript-eslint/eslint-plugin": "npm:^7.4.0" "@typescript-eslint/parser": "npm:^7.4.0" - alova: "npm:^2.18.0" + alova: "npm:^2.18.2" async-validator: "npm:^4.2.5" concurrently: "npm:^8.2.2" eslint: "npm:^8.57.0" @@ -1671,8 +1693,7 @@ __metadata: eslint-import-resolver-typescript: "npm:^3.6.1" eslint-plugin-autofix: "npm:^1.1.0" eslint-plugin-import: "npm:^2.29.1" - eslint-plugin-jsx-a11y: "npm:^6.8.0" - eslint-plugin-prettier: "npm:alpha" + eslint-plugin-prettier: "npm:^5.1.3" eslint-plugin-react: "npm:^7.34.1" eslint-plugin-react-hooks: "npm:^4.6.0" history: "npm:^5.3.0" @@ -1688,11 +1709,10 @@ __metadata: react-router-dom: "npm:^6.22.3" react-toastify: "npm:^10.0.5" rollup-plugin-visualizer: "npm:^5.12.0" - sockette: "npm:^2.0.6" terser: "npm:^5.30.0" typesafe-i18n: "npm:^5.26.2" typescript: "npm:^5.4.3" - vite: "npm:^5.2.6" + vite: "npm:^5.2.7" vite-plugin-imagemin: "npm:^0.6.1" vite-tsconfig-paths: "npm:^4.3.2" languageName: unknown @@ -1754,10 +1774,10 @@ __metadata: languageName: node linkType: hard -"alova@npm:^2.18.0": - version: 2.18.0 - resolution: "alova@npm:2.18.0" - checksum: 10/6edf15157f4bce4239ba3461bf71a653fd4e904c80e5e7d4574328bb30d5704d5e4fc9c024b60f886bb010ee3e29e56cfb6ab7fc235a6a2aa4ee879cae35e387 +"alova@npm:^2.18.2": + version: 2.18.2 + resolution: "alova@npm:2.18.2" + checksum: 10/715d97c5b80c2b3541b7b5dd203bb7496d7308a49682df31ed007c12a7d716ee910f3da852accc2398c2283db3808748678074cb87324b5d77bb991018431bf3 languageName: node linkType: hard @@ -1837,15 +1857,6 @@ __metadata: languageName: node linkType: hard -"aria-query@npm:^5.3.0": - version: 5.3.0 - resolution: "aria-query@npm:5.3.0" - dependencies: - dequal: "npm:^2.0.3" - checksum: 10/c3e1ed127cc6886fea4732e97dd6d3c3938e64180803acfb9df8955517c4943760746ffaf4020ce8f7ffaa7556a3b5f85c3769a1f5ca74a1288e02d042f9ae4e - languageName: node - linkType: hard - "array-buffer-byte-length@npm:^1.0.1": version: 1.0.1 resolution: "array-buffer-byte-length@npm:1.0.1" @@ -1977,13 +1988,6 @@ __metadata: languageName: node linkType: hard -"ast-types-flow@npm:^0.0.8": - version: 0.0.8 - resolution: "ast-types-flow@npm:0.0.8" - checksum: 10/85a1c24af4707871c27cfe456bd2ff7fcbe678f3d1c878ac968c9557735a171a17bdcc8c8f903ceab3fc3c49d5b3da2194e6ab0a6be7fec0e133fa028f21ba1b - languageName: node - linkType: hard - "async-validator@npm:^4.2.5": version: 4.2.5 resolution: "async-validator@npm:4.2.5" @@ -2007,22 +2011,6 @@ __metadata: languageName: node linkType: hard -"axe-core@npm:=4.7.0": - version: 4.7.0 - resolution: "axe-core@npm:4.7.0" - checksum: 10/615c0f7722c3c9fcf353dbd70b00e2ceae234d4c17cbc839dd85c01d16797c4e4da45f8d27c6118e9e6b033fb06efd196106e13651a1b2f3a10e0f11c7b2f660 - languageName: node - linkType: hard - -"axobject-query@npm:^3.2.1": - version: 3.2.1 - resolution: "axobject-query@npm:3.2.1" - dependencies: - dequal: "npm:^2.0.3" - checksum: 10/675af2548ed4ece75ad6d50cc0473cfdec7579eac77ec9861e7088d03ffb171aa697b70d2877423bee2ce16460ef62c698c6442a105612cc015719e8ea06b0bd - languageName: node - linkType: hard - "babel-plugin-macros@npm:^3.1.0": version: 3.1.0 resolution: "babel-plugin-macros@npm:3.1.0" @@ -2643,13 +2631,6 @@ __metadata: languageName: node linkType: hard -"damerau-levenshtein@npm:^1.0.8": - version: 1.0.8 - resolution: "damerau-levenshtein@npm:1.0.8" - checksum: 10/f4eba1c90170f96be25d95fa3857141b5f81e254f7e4d530da929217b19990ea9a0390fc53d3c1cafac9152fda78e722ea4894f765cf6216be413b5af1fbf821 - languageName: node - linkType: hard - "data-view-buffer@npm:^1.0.1": version: 1.0.1 resolution: "data-view-buffer@npm:1.0.1" @@ -2835,13 +2816,6 @@ __metadata: languageName: node linkType: hard -"dequal@npm:^2.0.3": - version: 2.0.3 - resolution: "dequal@npm:2.0.3" - checksum: 10/6ff05a7561f33603df87c45e389c9ac0a95e3c056be3da1a0c4702149e3a7f6fe5ffbb294478687ba51a9e95f3a60e8b6b9005993acd79c292c7d15f71964b6b - languageName: node - linkType: hard - "dir-glob@npm:^3.0.1": version: 3.0.1 resolution: "dir-glob@npm:3.0.1" @@ -3157,7 +3131,7 @@ __metadata: languageName: node linkType: hard -"es-iterator-helpers@npm:^1.0.15, es-iterator-helpers@npm:^1.0.17": +"es-iterator-helpers@npm:^1.0.17": version: 1.0.18 resolution: "es-iterator-helpers@npm:1.0.18" dependencies: @@ -3628,48 +3602,23 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-jsx-a11y@npm:^6.8.0": - version: 6.8.0 - resolution: "eslint-plugin-jsx-a11y@npm:6.8.0" - dependencies: - "@babel/runtime": "npm:^7.23.2" - aria-query: "npm:^5.3.0" - array-includes: "npm:^3.1.7" - array.prototype.flatmap: "npm:^1.3.2" - ast-types-flow: "npm:^0.0.8" - axe-core: "npm:=4.7.0" - axobject-query: "npm:^3.2.1" - damerau-levenshtein: "npm:^1.0.8" - emoji-regex: "npm:^9.2.2" - es-iterator-helpers: "npm:^1.0.15" - hasown: "npm:^2.0.0" - jsx-ast-utils: "npm:^3.3.5" - language-tags: "npm:^1.0.9" - minimatch: "npm:^3.1.2" - object.entries: "npm:^1.1.7" - object.fromentries: "npm:^2.0.7" - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: 10/7a8e4498531a43d988ce2f12502a3f5ce96eacfec13f956cf927f24bb041b724fb7fc0f0306ea19d143bfc79e138bf25e25acca0822847206ac6bf5ce095e846 - languageName: node - linkType: hard - -"eslint-plugin-prettier@npm:alpha": - version: 5.0.0-alpha.2 - resolution: "eslint-plugin-prettier@npm:5.0.0-alpha.2" +"eslint-plugin-prettier@npm:^5.1.3": + version: 5.1.3 + resolution: "eslint-plugin-prettier@npm:5.1.3" dependencies: prettier-linter-helpers: "npm:^1.0.0" - synckit: "npm:^0.8.5" + synckit: "npm:^0.8.6" peerDependencies: "@types/eslint": ">=8.0.0" eslint: ">=8.0.0" + eslint-config-prettier: "*" prettier: ">=3.0.0" peerDependenciesMeta: "@types/eslint": optional: true eslint-config-prettier: optional: true - checksum: 10/dc67d0ea0e0dfc0dcda176ddb3297c5616752ab8ba3369b2ff67336cfd5343bbce78c55295f0db07b07a9c8c72ceed41dca8834a4bcaab88dc8b45cf43ce7bc7 + checksum: 10/4f26a30444adc61ed692cdb5a9f7e8d9f5794f0917151051e66755ce032a08c3cc72c8b5d56101412e90f6d77035bd8194ea8731e9c16aacdd5ae345a8dae188 languageName: node linkType: hard @@ -5529,7 +5478,7 @@ __metadata: languageName: node linkType: hard -"jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.5": +"jsx-ast-utils@npm:^2.4.1 || ^3.0.0": version: 3.3.5 resolution: "jsx-ast-utils@npm:3.3.5" dependencies: @@ -5580,22 +5529,6 @@ __metadata: languageName: node linkType: hard -"language-subtag-registry@npm:^0.3.20": - version: 0.3.22 - resolution: "language-subtag-registry@npm:0.3.22" - checksum: 10/5591f4abd775d1ab5945355a5ba894327d2d94c900607bdb69aac1bc5bb921dbeeeb5f616df95e8c0ae875501d19c1cfa0e852ece822121e95048deb34f2b4d2 - languageName: node - linkType: hard - -"language-tags@npm:^1.0.9": - version: 1.0.9 - resolution: "language-tags@npm:1.0.9" - dependencies: - language-subtag-registry: "npm:^0.3.20" - checksum: 10/d3a7c14b694e67f519153d6df6cb200681648d38d623c3bfa9d6a66a5ec5493628acb88e9df5aceef3cf1902ab263a205e7d59ee4cf1d6bb67e707b83538bd6d - languageName: node - linkType: hard - "levn@npm:^0.4.1": version: 0.4.1 resolution: "levn@npm:0.4.1" @@ -6641,7 +6574,7 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.4.36": +"postcss@npm:^8.4.38": version: 8.4.38 resolution: "postcss@npm:8.4.38" dependencies: @@ -7433,13 +7366,6 @@ __metadata: languageName: node linkType: hard -"sockette@npm:^2.0.6": - version: 2.0.6 - resolution: "sockette@npm:2.0.6" - checksum: 10/38a59afc6a61572e25066b8ac0345c3c91a5aac0447392f5d281927c7365b6d1c67de95b667fa7f9ea21cd0928ec854baaa055c264fed1e9223f37996bfd598b - languageName: node - linkType: hard - "socks-proxy-agent@npm:^8.0.1": version: 8.0.2 resolution: "socks-proxy-agent@npm:8.0.2" @@ -7872,7 +7798,7 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.8.5": +"synckit@npm:^0.8.6": version: 0.8.8 resolution: "synckit@npm:0.8.8" dependencies: @@ -8352,13 +8278,13 @@ __metadata: languageName: node linkType: hard -"vite@npm:^5.2.6": - version: 5.2.6 - resolution: "vite@npm:5.2.6" +"vite@npm:^5.2.7": + version: 5.2.7 + resolution: "vite@npm:5.2.7" dependencies: esbuild: "npm:^0.20.1" fsevents: "npm:~2.3.3" - postcss: "npm:^8.4.36" + postcss: "npm:^8.4.38" rollup: "npm:^4.13.0" peerDependencies: "@types/node": ^18.0.0 || >=20.0.0 @@ -8388,7 +8314,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10/0409acd4bbad1bca42b2015ac5d0f710bbc84b86f6b518add9a9c13adf1aab02fd40fcca854dc08ff2a2226c1df77d5d5b4a958c6c4c04ca27a6bfb0b4f60615 + checksum: 10/a00173446c8392069a70a92be78b060f7e5895f28c229eb25198953daa55c16ffbddcd4e8f015f220b2b1113e12d30e7a892221de34be336b222a12cddbb78a4 languageName: node linkType: hard diff --git a/mock-api/es_server.ts b/mock-api/es_server.ts new file mode 100644 index 000000000..c72cdc6a5 --- /dev/null +++ b/mock-api/es_server.ts @@ -0,0 +1,67 @@ +import express from 'express'; + +const rest_server = express(); + +const port = 3081; + +const ES_ENDPOINT_ROOT = '/es/'; +const ES_LOG_ENDPOINT = ES_ENDPOINT_ROOT + 'log'; + +const INTERVAL = 2000; + +function pad(number) { + var r = String(number); + if (r.length === 1) { + r = '0' + r; + } + return r; +} + +// e.g. 2024-03-29 07:02:37.856 +Date.prototype.toISOString = function () { + return ( + this.getUTCFullYear() + + '-' + + pad(this.getUTCMonth() + 1) + + '-' + + pad(this.getUTCDate()) + + ' ' + + pad(this.getUTCHours()) + + ':' + + pad(this.getUTCMinutes()) + + ':' + + pad(this.getUTCSeconds()) + + '.' + + String((this.getUTCMilliseconds() / 1000).toFixed(3)).slice(2, 5) + ); +}; + +rest_server.get(ES_LOG_ENDPOINT, (_req, res) => { + res.writeHead(200, { + Connection: 'keep-alive', + 'Cache-Control': 'no-cache', + 'Content-Type': 'text/event-stream' + }); + + let count = 0; + const interval = setInterval(() => { + const data = { + t: new Date().toISOString(), + l: 3, // error + i: count, + n: 'system', + m: 'message #' + count++ + }; + res.write(`data: ${JSON.stringify(data)}\n\n`); + }, INTERVAL); + + // if client closes connection + res.on('close', () => { + console.log('Closing ES connection'); + clearInterval(interval); + res.end(); + }); +}); + +// start eventsource server +rest_server.listen(port, () => console.log(`EMS-ESP EventSource server running on http://localhost:${port}/`)); diff --git a/mock-api/server.js b/mock-api/old_server.js similarity index 100% rename from mock-api/server.js rename to mock-api/old_server.js diff --git a/mock-api/package.json b/mock-api/package.json index f447cc2b1..0c658d1c4 100644 --- a/mock-api/package.json +++ b/mock-api/package.json @@ -3,17 +3,16 @@ "version": "3.7.0", "description": "mock api for EMS-ESP", "author": "proddy", - "main": "server.ts", "license": "MIT", "scripts": { - "standalone": "bun --watch server.ts", - "old_standalone": "node server.js" + "mock-api": "bun --watch rest_server.ts", + "mock-es": "bun --watch es_server.ts" }, "dependencies": { "@msgpack/msgpack": "^2.8.0", "compression": "^1.7.4", "express": "^4.19.2", - "itty-router": "^4.2.2", + "itty-router": "^5.0.4", "multer": "^1.4.5-lts.1" }, "packageManager": "yarn@4.1.1", diff --git a/mock-api/handler.ts b/mock-api/rest_server.ts similarity index 90% rename from mock-api/handler.ts rename to mock-api/rest_server.ts index e118a88cf..f40e4482f 100644 --- a/mock-api/handler.ts +++ b/mock-api/rest_server.ts @@ -1,19 +1,19 @@ -import { Router } from 'itty-router'; +import { AutoRouter, error, status } from 'itty-router'; import { Encoder } from '@msgpack/msgpack'; + // import busboy from 'busboy'; // import multer from 'multer'; +// const upload = multer({ dest: '../mock-api/uploads' }); const encoder = new Encoder(); -const router = Router(); -// const upload = multer({ dest: '../mock-api/uploads' }); // TODO remove muter + +const router = AutoRouter({ + port: 3080, + missing: () => error(404, 'Error, not found') +}); const REST_ENDPOINT_ROOT = '/rest/'; const API_ENDPOINT_ROOT = '/api/'; -const ES_ENDPOINT_ROOT = '/es/'; - -const restRouter = Router({ base: REST_ENDPOINT_ROOT }); -const apiRouter = Router({ base: API_ENDPOINT_ROOT }); -const esRouter = Router({ base: ES_ENDPOINT_ROOT }); // HTTP HEADERS const headers = { @@ -125,7 +125,7 @@ const LOG_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'logSettings'; let log_settings = { level: 6, max_messages: 50, - compact: false + compact: true }; const FETCH_LOG_ENDPOINT = REST_ENDPOINT_ROOT + 'fetchLog'; @@ -454,7 +454,6 @@ const EMSESP_SCANDEVICES_ENDPOINT = REST_ENDPOINT_ROOT + 'scanDevices'; // const EMSESP_DEVICEENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'deviceEntities/:id'; const EMSESP_DEVICEDATA_ENDPOINT = REST_ENDPOINT_ROOT + 'deviceData'; const EMSESP_DEVICEENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'deviceEntities'; -const EMSESP_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'status'; const EMSESP_BOARDPROFILE_ENDPOINT = REST_ENDPOINT_ROOT + 'boardProfile'; const EMSESP_WRITE_DEVICEVALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeDeviceValue'; const EMSESP_WRITE_TEMPSENSOR_ENDPOINT = REST_ENDPOINT_ROOT + 'writeTemperatureSensor'; @@ -2321,91 +2320,89 @@ const emsesp_deviceentities_4 = [ // LOG router .post(FETCH_LOG_ENDPOINT, () => { - const encoded = encoder.encode(fetch_log); - // TODO check if still need this or just send a 200 since ES will catch up? - return new Response(encoded, { headers }); + return status(200); }) - .get(LOG_SETTINGS_ENDPOINT, () => new Response(JSON.stringify(log_settings), { headers })) + .get(LOG_SETTINGS_ENDPOINT, () => log_settings) .post(LOG_SETTINGS_ENDPOINT, async (request: any) => { log_settings = await request.json(); - return new Response('OK', { status: 200 }); + return status(200); }); // NETWORK router - .get(NETWORK_STATUS_ENDPOINT, () => new Response(JSON.stringify(network_status), { headers })) - .get(NETWORK_SETTINGS_ENDPOINT, () => new Response(JSON.stringify(network_settings), { headers })) + .get(NETWORK_STATUS_ENDPOINT, () => network_status) + .get(NETWORK_SETTINGS_ENDPOINT, () => network_settings) .get(LIST_NETWORKS_ENDPOINT, () => { if (countWifiScanPoll++ === 3) { console.log('done, sending list'); - return new Response(JSON.stringify(list_networks), { headers }); // send list + return list_networks; // send list } else { console.log('...waiting #' + countWifiScanPoll); - return new Response('OK', { status: 200 }); + return status(200); } }) .get(SCAN_NETWORKS_ENDPOINT, () => { console.log('start scan networks'); countWifiScanPoll = 0; // stop the poll - return new Response('OK', { status: 202 }); // always 202, poll for list + return status(202); }) .post(NETWORK_SETTINGS_ENDPOINT, async (request: any) => { network_settings = await request.json(); - return new Response('OK', { status: 200 }); + return status(200); }); // AP router - .get(AP_SETTINGS_ENDPOINT, () => new Response(JSON.stringify(ap_settings), { headers })) - .get(AP_STATUS_ENDPOINT, () => new Response(JSON.stringify(ap_status), { headers })) + .get(AP_SETTINGS_ENDPOINT, () => ap_settings) + .get(AP_STATUS_ENDPOINT, () => ap_status) .post(AP_SETTINGS_ENDPOINT, async (request: any) => { ap_settings = await request.json(); - return new Response('OK', { status: 200 }); + return status(200); }); // OTA router - .get(OTA_SETTINGS_ENDPOINT, () => new Response(JSON.stringify(ota_settings), { headers })) + .get(OTA_SETTINGS_ENDPOINT, () => ota_settings) .post(OTA_SETTINGS_ENDPOINT, async (request: any) => { ota_settings = await request.json(); - return new Response('OK', { status: 200 }); + return status(200); }); // MQTT router - .get(MQTT_SETTINGS_ENDPOINT, () => new Response(JSON.stringify(mqtt_settings), { headers })) - .get(MQTT_STATUS_ENDPOINT, () => new Response(JSON.stringify(mqtt_status), { headers })) + .get(MQTT_SETTINGS_ENDPOINT, () => mqtt_settings) + .get(MQTT_STATUS_ENDPOINT, () => mqtt_status) .post(MQTT_SETTINGS_ENDPOINT, async (request: any) => { mqtt_settings = await request.json(); - return new Response('OK', { status: 200 }); + return status(200); }); // NTP router - .get(NTP_SETTINGS_ENDPOINT, () => new Response(JSON.stringify(ntp_settings), { headers })) - .get(NTP_STATUS_ENDPOINT, () => new Response(JSON.stringify(ntp_status), { headers })) - .post(TIME_ENDPOINT, () => new Response('OK', { status: 200 })) + .get(NTP_SETTINGS_ENDPOINT, () => ntp_settings) + .get(NTP_STATUS_ENDPOINT, () => ntp_status) + .post(TIME_ENDPOINT, () => status(200)) .post(NTP_SETTINGS_ENDPOINT, async (request: any) => { ntp_settings = await request.json(); - return new Response('OK', { status: 200 }); + return status(200); }); // SYSTEM and SETTINGS router - .get(SYSTEM_STATUS_ENDPOINT, () => new Response(JSON.stringify(system_status), { headers })) - .get(ACTIVITY_ENDPOINT, () => new Response(JSON.stringify(activity), { headers })) - .get(ESPSYSTEM_STATUS_ENDPOINT, () => new Response(JSON.stringify(ESPsystem_status), { headers })) - .get(SECURITY_SETTINGS_ENDPOINT, () => new Response(JSON.stringify(security_settings), { headers })) + .get(SYSTEM_STATUS_ENDPOINT, () => system_status) + .get(ACTIVITY_ENDPOINT, () => activity) + .get(ESPSYSTEM_STATUS_ENDPOINT, () => ESPsystem_status) + .get(SECURITY_SETTINGS_ENDPOINT, () => security_settings) .post(SECURITY_SETTINGS_ENDPOINT, async (request: any) => { security_settings = await request.json(); - return new Response('OK', { status: 200 }); + return status(200); }) - .get(VERIFY_AUTHORIZATION_ENDPOINT, () => new Response(JSON.stringify(verify_authentication), { headers })) - .post(RESTART_ENDPOINT, () => new Response('OK', { status: 200 })) - .post(FACTORY_RESET_ENDPOINT, () => new Response('OK', { status: 200 })) - .post(UPLOAD_FILE_ENDPOINT, () => new Response('OK', { status: 404 })) // TODO remove upload when fixed - .post(SIGN_IN_ENDPOINT, () => new Response(JSON.stringify(signin), { headers })) - .get(GENERATE_TOKEN_ENDPOINT, () => new Response(JSON.stringify(generate_token), { headers })); + .get(VERIFY_AUTHORIZATION_ENDPOINT, () => verify_authentication) + .post(RESTART_ENDPOINT, () => status(200)) + .post(FACTORY_RESET_ENDPOINT, () => status(200)) + .post(UPLOAD_FILE_ENDPOINT, () => status(404)) // TODO remove upload when fixed + .post(SIGN_IN_ENDPOINT, () => signin) + .get(GENERATE_TOKEN_ENDPOINT, () => generate_token); // uploads // TODO fix uploading later @@ -2510,19 +2507,18 @@ router router // EMS-ESP Settings - .get(EMSESP_SETTINGS_ENDPOINT, () => new Response(JSON.stringify(settings), { headers })) + .get(EMSESP_SETTINGS_ENDPOINT, () => settings) .post(EMSESP_SETTINGS_ENDPOINT, async (request: any) => { settings = await request.json(); - return new Response('OK', { status: 200 }); // no restart needed - // return new Response('OK', { status: 205 }); // restart needed + status(200); // no restart needed + status(205); // restart needed }) // Device Dashboard Data - .get(EMSESP_CORE_DATA_ENDPOINT, () => new Response(JSON.stringify(emsesp_coredata), { headers })) - .get(EMSESP_SENSOR_DATA_ENDPOINT, () => new Response(JSON.stringify(emsesp_sensordata), { headers })) - .get(EMSESP_DEVICES_ENDPOINT, () => new Response(JSON.stringify(emsesp_devices), { headers })) - .post(EMSESP_SCANDEVICES_ENDPOINT, () => new Response('OK', { status: 200 })) - .get(EMSESP_STATUS_ENDPOINT, () => new Response(JSON.stringify(status), { headers })) + .get(EMSESP_CORE_DATA_ENDPOINT, () => emsesp_coredata) + .get(EMSESP_SENSOR_DATA_ENDPOINT, () => emsesp_sensordata) + .get(EMSESP_DEVICES_ENDPOINT, () => emsesp_devices) + .post(EMSESP_SCANDEVICES_ENDPOINT, () => status(200)) .get(EMSESP_DEVICEDATA_ENDPOINT, (request) => { // const id = Number(request.params.id); // TODO when using :id const id = Number(request.query.id); @@ -2600,27 +2596,27 @@ router updateMask(entity, emsesp_deviceentities_6, emsesp_devicedata_6); } } - return new Response('OK', { status: 200 }); + return status(200); }) .post(EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT, async (request: any) => { - return new Response('OK', { status: 200 }); + return status(200); }) // Scheduler .post(EMSESP_SCHEDULE_ENDPOINT, async (request: any) => { const content = await request.json(); emsesp_schedule = content; - return new Response('OK', { status: 200 }); + return status(200); }) - .get(EMSESP_SCHEDULE_ENDPOINT, () => new Response(JSON.stringify(emsesp_schedule), { headers })) + .get(EMSESP_SCHEDULE_ENDPOINT, () => emsesp_schedule) // Custom Entities .post(EMSESP_CUSTOMENTITIES_ENDPOINT, async (request: any) => { const content = await request.json(); emsesp_customentities = content; - return new Response('OK', { status: 200 }); + return status(200); }) - .get(EMSESP_CUSTOMENTITIES_ENDPOINT, () => new Response(JSON.stringify(emsesp_customentities), { headers })) + .get(EMSESP_CUSTOMENTITIES_ENDPOINT, () => emsesp_customentities) // Device Dashboard .post(EMSESP_WRITE_DEVICEVALUE_ENDPOINT, async (request: any) => { @@ -2665,7 +2661,7 @@ router } await delay(1000); // wait to show spinner - return new Response('OK', { status: 200 }); // or 400 for bad request + return status(200); }) // Temperature & Analog Sensors @@ -2676,7 +2672,7 @@ router emsesp_sensordata.ts[objIndex].n = ts.name; emsesp_sensordata.ts[objIndex].o = ts.offset; } - return new Response('OK', { status: 200 }); + return status(200); }) .post(EMSESP_WRITE_ANALOGSENSOR_ENDPOINT, async (request: any) => { const as = await request.json(); @@ -2709,7 +2705,7 @@ router } } - return new Response('OK', { status: 200 }); + return status(200); }) // Settings - board profile @@ -2841,103 +2837,30 @@ router data.eth_clock_mode = 0; } - return new Response(JSON.stringify(data), { headers }); + return data; }) // Download Settings - .get(EMSESP_GET_SETTINGS_ENDPOINT, () => new Response(JSON.stringify(emsesp_info), { headers })) - .get(EMSESP_GET_CUSTOMIZATIONS_ENDPOINT, () => new Response(JSON.stringify(emsesp_deviceentities_1), { headers })) - .get(EMSESP_GET_ENTITIES_ENDPOINT, () => new Response(JSON.stringify(emsesp_customentities), { headers })) - .get(EMSESP_GET_SCHEDULE_ENDPOINT, () => new Response(JSON.stringify(emsesp_schedule), { headers })); + .get(EMSESP_GET_SETTINGS_ENDPOINT, () => emsesp_info) + .get(EMSESP_GET_CUSTOMIZATIONS_ENDPOINT, () => emsesp_deviceentities_1) + .get(EMSESP_GET_ENTITIES_ENDPOINT, () => emsesp_customentities) + .get(EMSESP_GET_SCHEDULE_ENDPOINT, () => emsesp_schedule); // API which are usually POST for security router - .post(EMSESP_SYSTEM_INFO_ENDPOINT, () => new Response(JSON.stringify(emsesp_info), { headers })) - .get(EMSESP_SYSTEM_INFO_ENDPOINT, () => new Response(JSON.stringify(emsesp_info), { headers })) + .post(EMSESP_SYSTEM_INFO_ENDPOINT, () => emsesp_info) + .get(EMSESP_SYSTEM_INFO_ENDPOINT, () => emsesp_info) .post(API_ENDPOINT_ROOT, async (request: any) => { const data = await request.json(); if (data.device === 'system') { if (data.entity === 'info') { - return new Response(JSON.stringify(emsesp_info), { headers }); + return emsesp_info; } if (data.entity === 'allvalues') { - return new Response(JSON.stringify(emsesp_allvalues), { headers }); + return emsesp_allvalues; } } - return new Response('Not Found', { status: 404 }); + return status(404); // not found }); -// -// Event Source // TODO fix event source later -// - -// const data = { -// t: '000+00:00:00.000', -// l: 3, // error -// i: 1, -// n: 'system', -// m: 'incoming message #1' -// }; -// const sseFormattedResponse = `data: ${JSON.stringify(data)}\n\n`; -// router.get('/es/log', () => new Response(sseFormattedResponse, { headers: ESheaders })); - -var count = 8; -var log_index = 0; -const ES_LOG_ENDPOINT = ES_ENDPOINT_ROOT + 'log'; - -// new Response({ -// headers: { -// 'content-type': 'application/json', -// 'Content-Type': 'text/event-stream', -// 'Cache-Control': 'no-cache', -// 'Access-Control-Allow-Origin': '*', -// 'Connection': 'keep-alive' -// }, -// body: '{"foo":"bar"}' -// }) - -// rest_server.get(ES_LOG_ENDPOINT, function (req, res) { -// res.setHeader('Content-Type', 'text/event-stream'); -// res.setHeader('Cache-Control', 'no-cache'); -// res.setHeader('Access-Control-Allow-Origin', '*'); -// res.setHeader('Connection', 'keep-alive'); -// res.flushHeaders(); - -let sseFormattedResponse = ''; - -// var timer = setInterval(function () { -// count += 1; -// log_index += 1; -// const data = { -// t: '000+00:00:00.000', -// l: 3, // error -// i: count, -// n: 'system', -// m: 'incoming message #' + count + '/' + log_index -// }; -// sseFormattedResponse = `data: ${JSON.stringify(data)}\n\n`; -// console.log('done'); -// // res.write(sseFormattedResponse); -// // res.flush(); // this is important - -// // if buffer is full, start over -// if (log_index > 50) { -// fetch_log.events = []; -// log_index = 0; -// } -// fetch_log.events.push(data); // append to buffer -// }, 300); - -router.get(ES_LOG_ENDPOINT, () => new Response(sseFormattedResponse, { headers: ESheaders })); - -// Tie it all together -const missingHandler = () => new Response('Not found.', { status: 404 }); - -router - .all('/api/*', apiRouter.handle) - .all('/rest/*', restRouter.handle) - .all('/es/*', esRouter.handle) - .all('*', missingHandler); - -const errorHandler = (error: any) => new Response(error.message || 'Server Error', { status: error.status || 500 }); -export const handleRequest = (request: any) => router.handle(request).catch(errorHandler); +export default router; diff --git a/mock-api/server.ts b/mock-api/server.ts deleted file mode 100644 index 7056e5611..000000000 --- a/mock-api/server.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { handleRequest } from './handler'; - -export default { - port: 3080, - fetch: (request) => handleRequest(request) -}; diff --git a/mock-api/yarn.lock b/mock-api/yarn.lock index d97a3862d..489ad4c7b 100644 --- a/mock-api/yarn.lock +++ b/mock-api/yarn.lock @@ -140,7 +140,7 @@ __metadata: "@types/multer": "npm:^1.4.11" compression: "npm:^1.7.4" express: "npm:^4.19.2" - itty-router: "npm:^4.2.2" + itty-router: "npm:^5.0.4" multer: "npm:^1.4.5-lts.1" languageName: unknown linkType: soft @@ -526,10 +526,10 @@ __metadata: languageName: node linkType: hard -"itty-router@npm:^4.2.2": - version: 4.2.2 - resolution: "itty-router@npm:4.2.2" - checksum: 10/ead44fd46ea358776dc2bb120970eff5ab0acb10ad82c384eba9b361c6eba7f5971408f80cbc3655004cb12ae53dd77a85de236bdb215cef896c2589f5096854 +"itty-router@npm:^5.0.4": + version: 5.0.4 + resolution: "itty-router@npm:5.0.4" + checksum: 10/61c5c12b57e592ae9689782ca59d7b77154909eb52fc019c38f34e03fdce3d7fb50aad930bde0b31ef8d9131d2101141517823416886b36b81ba3ec6a0ff819e languageName: node linkType: hard diff --git a/platformio.ini b/platformio.ini index fae3d8823..b1ef043a9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -39,7 +39,7 @@ unbuild_flags = ${common.core_unbuild_flags} [espressi32_base] -platform = espressif32@6.5.0 +platform = espressif32@6.6.0 framework = arduino board_build.filesystem = littlefs build_flags = ${common.build_flags} diff --git a/scripts/api_test.http b/test/api_test.http similarity index 94% rename from scripts/api_test.http rename to test/api_test.http index 5af6d5b9d..e5e9e506d 100755 --- a/scripts/api_test.http +++ b/test/api_test.http @@ -5,6 +5,7 @@ @host = http://ems-esp.local @host_dev = http://10.10.10.20 +@host_standalone = http://localhost:3080 @token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiYWRtaW4iOnRydWV9.2bHpWya2C7Q12WjNUBD6_7N3RCD7CMl-EGhyQVzFdDg @@ -106,3 +107,10 @@ Authorization: Bearer {{token}} ### GET {{host_dev}}/api/thermostat/seltemp + + +#### STANDALONE #### + +GET {{host_standalone}}/api/system/info + +### \ No newline at end of file