From 82e1b069eb9fea2c33df8d798be8879d6b0e45b6 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 21 Jan 2024 11:45:00 +0100 Subject: [PATCH 01/46] rename callback function --- interface/src/framework/system/UploadFileForm.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/framework/system/UploadFileForm.tsx b/interface/src/framework/system/UploadFileForm.tsx index e0df328ed..490734b76 100644 --- a/interface/src/framework/system/UploadFileForm.tsx +++ b/interface/src/framework/system/UploadFileForm.tsx @@ -19,7 +19,7 @@ const UploadFileForm: FC = () => { const { send: getSettings, onSuccess: onSuccessGetSettings } = useRequest(EMSESP.getSettings(), { immediate: false }); - const { send: getCustomizations, onSuccess: onSuccessgetCustomizations } = useRequest(EMSESP.getCustomizations(), { + const { send: getCustomizations, onSuccess: onSuccessGetCustomizations } = useRequest(EMSESP.getCustomizations(), { immediate: false }); const { send: getEntities, onSuccess: onSuccessGetEntities } = useRequest(EMSESP.getEntities(), { @@ -80,7 +80,7 @@ const UploadFileForm: FC = () => { onSuccessGetSettings((event) => { saveFile(event.data, 'settings.json'); }); - onSuccessgetCustomizations((event) => { + onSuccessGetCustomizations((event) => { saveFile(event.data, 'customizations.json'); }); onSuccessGetEntities((event) => { From 9eb617bcb007570a55baba281f59a6ed036a64a8 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 21 Jan 2024 11:45:22 +0100 Subject: [PATCH 02/46] package update --- interface/package.json | 4 +++- interface/yarn.lock | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/interface/package.json b/interface/package.json index d3908e499..f84ec6f40 100644 --- a/interface/package.json +++ b/interface/package.json @@ -13,7 +13,9 @@ "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", + "old_mock-api": "bun --watch ../mock-api/server.js", "standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"npm:mock-api\" \"vite\"", + "old_standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"npm:old_mock-api\" \"vite\"", "typesafe-i18n": "typesafe-i18n --no-watch", "webUI": "node progmem-generator.js", "format": "prettier --write '**/*.{ts,tsx,js,css,json,md}'", @@ -44,7 +46,7 @@ "react-dropzone": "^14.2.3", "react-icons": "^5.0.1", "react-router-dom": "^6.21.3", - "react-toastify": "^10.0.3", + "react-toastify": "^10.0.4", "sockette": "^2.0.6", "typesafe-i18n": "^5.26.2", "typescript": "^5.3.3" diff --git a/interface/yarn.lock b/interface/yarn.lock index 95918a750..27da2bce1 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -1867,7 +1867,7 @@ __metadata: react-dropzone: "npm:^14.2.3" react-icons: "npm:^5.0.1" react-router-dom: "npm:^6.21.3" - react-toastify: "npm:^10.0.3" + react-toastify: "npm:^10.0.4" rollup-plugin-visualizer: "npm:^5.12.0" sockette: "npm:^2.0.6" terser: "npm:^5.27.0" @@ -7242,15 +7242,15 @@ __metadata: languageName: node linkType: hard -"react-toastify@npm:^10.0.3": - version: 10.0.3 - resolution: "react-toastify@npm:10.0.3" +"react-toastify@npm:^10.0.4": + version: 10.0.4 + resolution: "react-toastify@npm:10.0.4" dependencies: clsx: "npm:^2.1.0" peerDependencies: react: ">=16" react-dom: ">=16" - checksum: 3c9e9cebef41cff7ea60528d1ca01f03feed98a9bba10bd0749a17d7627fa5e4719b2f1d28dee22c9f9a66df2d9ddf906e180f3f9771607e16d96c889f1bf484 + checksum: 57f4d0032bf328381bdfeb78ab5efa988d425627a61ffa43b0caa184633a0ea44253a349d6b967247fa3d480ad82a2bbaa9063ce3f89be9550eb9b30398a6837 languageName: node linkType: hard From 603036a5e92a486749942260e0fa80918458c9fa Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 21 Jan 2024 11:45:29 +0100 Subject: [PATCH 03/46] formatting --- interface/src/project/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts index 41e8f6f56..47b1d9a31 100644 --- a/interface/src/project/types.ts +++ b/interface/src/project/types.ts @@ -392,6 +392,7 @@ export const enum DeviceValueType { } export const DeviceValueTypeNames = [ + // 'BOOL', 'INT', 'UINT', From d8671dd114c2a47328c69d079a3c91316c304c8a Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 21 Jan 2024 11:45:40 +0100 Subject: [PATCH 04/46] formatting --- interface/src/project/SettingsCustomEntities.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/project/SettingsCustomEntities.tsx b/interface/src/project/SettingsCustomEntities.tsx index dfda883f0..534ecec07 100644 --- a/interface/src/project/SettingsCustomEntities.tsx +++ b/interface/src/project/SettingsCustomEntities.tsx @@ -1,7 +1,7 @@ import AddIcon from '@mui/icons-material/Add'; import CancelIcon from '@mui/icons-material/Cancel'; -import RefreshIcon from '@mui/icons-material/Refresh'; import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; +import RefreshIcon from '@mui/icons-material/Refresh'; import WarningIcon from '@mui/icons-material/Warning'; import { Button, Typography, Box } from '@mui/material'; import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table'; From fe30b8de8d58cc325c93b3332402cfb62c07e964 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 21 Jan 2024 11:46:13 +0100 Subject: [PATCH 05/46] work on muter/upload testing --- mock-api/package.json | 9 +- mock-api/{server_notused.js => server.js} | 20 +- mock-api/server.ts | 2 +- mock-api/yarn.lock | 772 +++++++++++++++++++++- 4 files changed, 794 insertions(+), 9 deletions(-) rename mock-api/{server_notused.js => server.js} (99%) diff --git a/mock-api/package.json b/mock-api/package.json index de5e4f285..4b0d655df 100644 --- a/mock-api/package.json +++ b/mock-api/package.json @@ -6,12 +6,17 @@ "main": "server.ts", "license": "MIT", "scripts": { - "standalone": "bun --watch server.ts" + "standalone": "bun --watch server.ts", + "old_standalone": "node server.js" }, "dependencies": { "@msgpack/msgpack": "^2.8.0", "busboy": "^1.6.0", - "itty-router": "^4.0.27" + "compression": "^1.7.4", + "express": "^4.18.2", + "express-slow-down": "^2.0.1", + "itty-router": "^4.0.27", + "multer": "^1.4.5-lts.1" }, "packageManager": "yarn@4.0.2", "devDependencies": { diff --git a/mock-api/server_notused.js b/mock-api/server.js similarity index 99% rename from mock-api/server_notused.js rename to mock-api/server.js index 88e478349..3d6523945 100644 --- a/mock-api/server_notused.js +++ b/mock-api/server.js @@ -1,4 +1,5 @@ const express = require('express'); +const rateLimit = require('express-rate-limit'); const compression = require('compression'); const path = require('path'); const msgpack = require('@msgpack/msgpack'); @@ -13,8 +14,16 @@ rest_server.use(express.static(path.join(__dirname, '../interface/build'))); rest_server.use(express.json()); // uploads +const testLimiter = rateLimit({ + windowMs: 20 * 60 * 1000, // 20 minutes + delayAfter: 70, // 70 requests + delayMs: 1000 // adding 500ms delay +}); + const upload = multer({ dest: '../mock-api/uploads' }); + function progress_middleware(req, res, next) { + console.log('Uploading file... '); let progress = 0; const file_size = req.headers['content-length']; @@ -24,7 +33,7 @@ function progress_middleware(req, res, next) { const percentage = (progress / file_size) * 100; console.log(`Progress: ${Math.round(percentage)}%`); // await delay(1000); // slow it down - delay_blocking(200); // slow it down + // delay_blocking(1000); // slow it down }); next(); // invoke next middleware which is multer } @@ -33,7 +42,8 @@ function progress_middleware(req, res, next) { const delay = (ms) => new Promise((res) => setTimeout(res, ms)); function delay_blocking(milliseconds) { var start = new Date().getTime(); - for (var i = 0; i < 1e7; i++) { + // for (var i = 0; i < 1e7; i++) { + while (true) { if (new Date().getTime() - start > milliseconds) { break; } @@ -2202,7 +2212,7 @@ rest_server.post(FACTORY_RESET_ENDPOINT, (req, res) => { res.sendStatus(200); }); -rest_server.post(UPLOAD_FILE_ENDPOINT, progress_middleware, upload.single('file'), (req, res) => { +rest_server.post(UPLOAD_FILE_ENDPOINT, testLimiter, progress_middleware, upload.single('file'), (req, res) => { console.log('command: uploadFile completed.'); if (req.file) { const filename = req.file.originalname; @@ -2758,7 +2768,7 @@ rest_server.get(ENTITIES_ENDPOINT, (req, res) => { // start server const expressServer = rest_server.listen(port, () => - console.log(`EMS-ESP REST API server running on http://localhost:${port}/`) + console.log(`Legacy EMS-ESP REST API server running on http://localhost:${port}/`) ); // event source @@ -2793,5 +2803,5 @@ rest_server.get(ES_LOG_ENDPOINT, function (req, res) { log_index = 0; } fetch_log.events.push(data); // append to buffer - }, 300); + }, 5000); }); diff --git a/mock-api/server.ts b/mock-api/server.ts index 612e7a9ab..7056e5611 100644 --- a/mock-api/server.ts +++ b/mock-api/server.ts @@ -1,4 +1,4 @@ -import { handleRequest } from './Handler'; +import { handleRequest } from './handler'; export default { port: 3080, diff --git a/mock-api/yarn.lock b/mock-api/yarn.lock index 8d3e1278c..80d771471 100644 --- a/mock-api/yarn.lock +++ b/mock-api/yarn.lock @@ -122,6 +122,16 @@ __metadata: languageName: node linkType: hard +"accepts@npm:~1.3.5, accepts@npm:~1.3.8": + version: 1.3.8 + resolution: "accepts@npm:1.3.8" + dependencies: + mime-types: "npm:~2.1.34" + negotiator: "npm:0.6.3" + checksum: 67eaaa90e2917c58418e7a9b89392002d2b1ccd69bcca4799135d0c632f3b082f23f4ae4ddeedbced5aa59bcc7bdf4699c69ebed4593696c922462b7bc5744d6 + languageName: node + linkType: hard + "api@workspace:.": version: 0.0.0-use.local resolution: "api@workspace:." @@ -129,11 +139,56 @@ __metadata: "@msgpack/msgpack": "npm:^2.8.0" "@types/multer": "npm:^1.4.11" busboy: "npm:^1.6.0" + compression: "npm:^1.7.4" + express: "npm:^4.18.2" + express-slow-down: "npm:^2.0.1" itty-router: "npm:^4.0.27" + multer: "npm:^1.4.5-lts.1" languageName: unknown linkType: soft -"busboy@npm:^1.6.0": +"append-field@npm:^1.0.0": + version: 1.0.0 + resolution: "append-field@npm:1.0.0" + checksum: afb50f5ff668af1cb66bc5cfebb55ed9a1d99e24901782ee83d00aed1a499835f9375a149cf27b17f79595ecfcc3d1de0cd5b020b210a5359c43eaf607c217de + languageName: node + linkType: hard + +"array-flatten@npm:1.1.1": + version: 1.1.1 + resolution: "array-flatten@npm:1.1.1" + checksum: e13c9d247241be82f8b4ec71d035ed7204baa82fae820d4db6948d30d3c4a9f2b3905eb2eec2b937d4aa3565200bd3a1c500480114cff649fa748747d2a50feb + languageName: node + linkType: hard + +"body-parser@npm:1.20.1": + version: 1.20.1 + resolution: "body-parser@npm:1.20.1" + dependencies: + bytes: "npm:3.1.2" + content-type: "npm:~1.0.4" + debug: "npm:2.6.9" + depd: "npm:2.0.0" + destroy: "npm:1.2.0" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + on-finished: "npm:2.4.1" + qs: "npm:6.11.0" + raw-body: "npm:2.5.1" + type-is: "npm:~1.6.18" + unpipe: "npm:1.0.0" + checksum: 5f8d128022a2fb8b6e7990d30878a0182f300b70e46b3f9d358a9433ad6275f0de46add6d63206da3637c01c3b38b6111a7480f7e7ac2e9f7b989f6133fe5510 + languageName: node + linkType: hard + +"buffer-from@npm:^1.0.0": + version: 1.1.2 + resolution: "buffer-from@npm:1.1.2" + checksum: 0448524a562b37d4d7ed9efd91685a5b77a50672c556ea254ac9a6d30e3403a517d8981f10e565db24e8339413b43c97ca2951f10e399c6125a0d8911f5679bb + languageName: node + linkType: hard + +"busboy@npm:^1.0.0, busboy@npm:^1.6.0": version: 1.6.0 resolution: "busboy@npm:1.6.0" dependencies: @@ -142,6 +197,357 @@ __metadata: languageName: node linkType: hard +"bytes@npm:3.0.0": + version: 3.0.0 + resolution: "bytes@npm:3.0.0" + checksum: a2b386dd8188849a5325f58eef69c3b73c51801c08ffc6963eddc9be244089ba32d19347caf6d145c86f315ae1b1fc7061a32b0c1aa6379e6a719090287ed101 + languageName: node + linkType: hard + +"bytes@npm:3.1.2": + version: 3.1.2 + resolution: "bytes@npm:3.1.2" + checksum: a10abf2ba70c784471d6b4f58778c0beeb2b5d405148e66affa91f23a9f13d07603d0a0354667310ae1d6dc141474ffd44e2a074be0f6e2254edb8fc21445388 + languageName: node + linkType: hard + +"call-bind@npm:^1.0.0": + version: 1.0.5 + resolution: "call-bind@npm:1.0.5" + dependencies: + function-bind: "npm:^1.1.2" + get-intrinsic: "npm:^1.2.1" + set-function-length: "npm:^1.1.1" + checksum: 246d44db6ef9bbd418828dbd5337f80b46be4398d522eded015f31554cbb2ea33025b0203b75c7ab05a1a255b56ef218880cca1743e4121e306729f9e414da39 + languageName: node + linkType: hard + +"compressible@npm:~2.0.16": + version: 2.0.18 + resolution: "compressible@npm:2.0.18" + dependencies: + mime-db: "npm:>= 1.43.0 < 2" + checksum: 58321a85b375d39230405654721353f709d0c1442129e9a17081771b816302a012471a9b8f4864c7dbe02eef7f2aaac3c614795197092262e94b409c9be108f0 + languageName: node + linkType: hard + +"compression@npm:^1.7.4": + version: 1.7.4 + resolution: "compression@npm:1.7.4" + dependencies: + accepts: "npm:~1.3.5" + bytes: "npm:3.0.0" + compressible: "npm:~2.0.16" + debug: "npm:2.6.9" + on-headers: "npm:~1.0.2" + safe-buffer: "npm:5.1.2" + vary: "npm:~1.1.2" + checksum: 469cd097908fe1d3ff146596d4c24216ad25eabb565c5456660bdcb3a14c82ebc45c23ce56e19fc642746cf407093b55ab9aa1ac30b06883b27c6c736e6383c2 + languageName: node + linkType: hard + +"concat-stream@npm:^1.5.2": + version: 1.6.2 + resolution: "concat-stream@npm:1.6.2" + dependencies: + buffer-from: "npm:^1.0.0" + inherits: "npm:^2.0.3" + readable-stream: "npm:^2.2.2" + typedarray: "npm:^0.0.6" + checksum: 71db903c84fc073ca35a274074e8d26c4330713d299f8623e993c448c1f6bf8b967806dd1d1a7b0f8add6f15ab1af7435df21fe79b4fe7efd78420c89e054e28 + languageName: node + linkType: hard + +"content-disposition@npm:0.5.4": + version: 0.5.4 + resolution: "content-disposition@npm:0.5.4" + dependencies: + safe-buffer: "npm:5.2.1" + checksum: b7f4ce176e324f19324be69b05bf6f6e411160ac94bc523b782248129eb1ef3be006f6cff431aaea5e337fe5d176ce8830b8c2a1b721626ead8933f0cbe78720 + languageName: node + linkType: hard + +"content-type@npm:~1.0.4": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 585847d98dc7fb8035c02ae2cb76c7a9bd7b25f84c447e5ed55c45c2175e83617c8813871b4ee22f368126af6b2b167df655829007b21aa10302873ea9c62662 + languageName: node + linkType: hard + +"cookie-signature@npm:1.0.6": + version: 1.0.6 + resolution: "cookie-signature@npm:1.0.6" + checksum: f4e1b0a98a27a0e6e66fd7ea4e4e9d8e038f624058371bf4499cfcd8f3980be9a121486995202ba3fca74fbed93a407d6d54d43a43f96fd28d0bd7a06761591a + languageName: node + linkType: hard + +"cookie@npm:0.5.0": + version: 0.5.0 + resolution: "cookie@npm:0.5.0" + checksum: aae7911ddc5f444a9025fbd979ad1b5d60191011339bce48e555cb83343d0f98b865ff5c4d71fecdfb8555a5cafdc65632f6fce172f32aaf6936830a883a0380 + languageName: node + linkType: hard + +"core-util-is@npm:~1.0.0": + version: 1.0.3 + resolution: "core-util-is@npm:1.0.3" + checksum: 9de8597363a8e9b9952491ebe18167e3b36e7707569eed0ebf14f8bba773611376466ae34575bca8cfe3c767890c859c74056084738f09d4e4a6f902b2ad7d99 + languageName: node + linkType: hard + +"debug@npm:2.6.9": + version: 2.6.9 + resolution: "debug@npm:2.6.9" + dependencies: + ms: "npm:2.0.0" + checksum: e07005f2b40e04f1bd14a3dd20520e9c4f25f60224cb006ce9d6781732c917964e9ec029fc7f1a151083cd929025ad5133814d4dc624a9aaf020effe4914ed14 + languageName: node + linkType: hard + +"define-data-property@npm:^1.1.1": + version: 1.1.1 + resolution: "define-data-property@npm:1.1.1" + dependencies: + get-intrinsic: "npm:^1.2.1" + gopd: "npm:^1.0.1" + has-property-descriptors: "npm:^1.0.0" + checksum: 5573c8df96b5857408cad64d9b91b69152e305ce4b06218e5f49b59c6cafdbb90a8bd8a0bb83c7bc67a8d479c04aa697063c9bc28d849b7282f9327586d6bc7b + languageName: node + linkType: hard + +"depd@npm:2.0.0": + version: 2.0.0 + resolution: "depd@npm:2.0.0" + checksum: c0c8ff36079ce5ada64f46cc9d6fd47ebcf38241105b6e0c98f412e8ad91f084bcf906ff644cc3a4bd876ca27a62accb8b0fff72ea6ed1a414b89d8506f4a5ca + languageName: node + linkType: hard + +"destroy@npm:1.2.0": + version: 1.2.0 + resolution: "destroy@npm:1.2.0" + checksum: 0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38 + languageName: node + linkType: hard + +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 1b4cac778d64ce3b582a7e26b218afe07e207a0f9bfe13cc7395a6d307849cfe361e65033c3251e00c27dd060cab43014c2d6b2647676135e18b77d2d05b3f4f + languageName: node + linkType: hard + +"encodeurl@npm:~1.0.2": + version: 1.0.2 + resolution: "encodeurl@npm:1.0.2" + checksum: e50e3d508cdd9c4565ba72d2012e65038e5d71bdc9198cb125beb6237b5b1ade6c0d343998da9e170fb2eae52c1bed37d4d6d98a46ea423a0cddbed5ac3f780c + languageName: node + linkType: hard + +"escape-html@npm:~1.0.3": + version: 1.0.3 + resolution: "escape-html@npm:1.0.3" + checksum: 6213ca9ae00d0ab8bccb6d8d4e0a98e76237b2410302cf7df70aaa6591d509a2a37ce8998008cbecae8fc8ffaadf3fb0229535e6a145f3ce0b211d060decbb24 + languageName: node + linkType: hard + +"etag@npm:~1.8.1": + version: 1.8.1 + resolution: "etag@npm:1.8.1" + checksum: 571aeb3dbe0f2bbd4e4fadbdb44f325fc75335cd5f6f6b6a091e6a06a9f25ed5392f0863c5442acb0646787446e816f13cbfc6edce5b07658541dff573cab1ff + languageName: node + linkType: hard + +"express-rate-limit@npm:7": + version: 7.1.5 + resolution: "express-rate-limit@npm:7.1.5" + peerDependencies: + express: 4 || 5 || ^5.0.0-beta.1 + checksum: bced4208de86fc8b99fe9a2dbfd522e0ea9a1875e678a4079102cc77c13c94f40b892ec46dac30cd028e229178ba021778070b86d0741e7258db0adc38cc858a + languageName: node + linkType: hard + +"express-slow-down@npm:^2.0.1": + version: 2.0.1 + resolution: "express-slow-down@npm:2.0.1" + dependencies: + express-rate-limit: "npm:7" + peerDependencies: + express: ">= 4" + checksum: b9b053cf99104a164420df08d6b42768024c9c797e944a7a1f631ebc5741ae31067264c0f05eca3a86eaaa9ab7c7da82d0082f135690b5cb603b687ddd36fdbb + languageName: node + linkType: hard + +"express@npm:^4.18.2": + version: 4.18.2 + resolution: "express@npm:4.18.2" + dependencies: + accepts: "npm:~1.3.8" + array-flatten: "npm:1.1.1" + body-parser: "npm:1.20.1" + content-disposition: "npm:0.5.4" + content-type: "npm:~1.0.4" + cookie: "npm:0.5.0" + cookie-signature: "npm:1.0.6" + debug: "npm:2.6.9" + depd: "npm:2.0.0" + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + etag: "npm:~1.8.1" + finalhandler: "npm:1.2.0" + fresh: "npm:0.5.2" + http-errors: "npm:2.0.0" + merge-descriptors: "npm:1.0.1" + methods: "npm:~1.1.2" + on-finished: "npm:2.4.1" + parseurl: "npm:~1.3.3" + path-to-regexp: "npm:0.1.7" + proxy-addr: "npm:~2.0.7" + qs: "npm:6.11.0" + range-parser: "npm:~1.2.1" + safe-buffer: "npm:5.2.1" + send: "npm:0.18.0" + serve-static: "npm:1.15.0" + setprototypeof: "npm:1.2.0" + statuses: "npm:2.0.1" + type-is: "npm:~1.6.18" + utils-merge: "npm:1.0.1" + vary: "npm:~1.1.2" + checksum: 869ae89ed6ff4bed7b373079dc58e5dddcf2915a2669b36037ff78c99d675ae930e5fe052b35c24f56557d28a023bb1cbe3e2f2fb87eaab96a1cedd7e597809d + languageName: node + linkType: hard + +"finalhandler@npm:1.2.0": + version: 1.2.0 + resolution: "finalhandler@npm:1.2.0" + dependencies: + debug: "npm:2.6.9" + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + on-finished: "npm:2.4.1" + parseurl: "npm:~1.3.3" + statuses: "npm:2.0.1" + unpipe: "npm:~1.0.0" + checksum: 635718cb203c6d18e6b48dfbb6c54ccb08ea470e4f474ddcef38c47edcf3227feec316f886dd701235997d8af35240cae49856721ce18f539ad038665ebbf163 + languageName: node + linkType: hard + +"forwarded@npm:0.2.0": + version: 0.2.0 + resolution: "forwarded@npm:0.2.0" + checksum: 29ba9fd347117144e97cbb8852baae5e8b2acb7d1b591ef85695ed96f5b933b1804a7fac4a15dd09ca7ac7d0cdc104410e8102aae2dd3faa570a797ba07adb81 + languageName: node + linkType: hard + +"fresh@npm:0.5.2": + version: 0.5.2 + resolution: "fresh@npm:0.5.2" + checksum: 64c88e489b5d08e2f29664eb3c79c705ff9a8eb15d3e597198ef76546d4ade295897a44abb0abd2700e7ef784b2e3cbf1161e4fbf16f59129193fd1030d16da1 + languageName: node + linkType: hard + +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 185e20d20f10c8d661d59aac0f3b63b31132d492e1b11fcc2a93cb2c47257ebaee7407c38513efd2b35cafdf972d9beb2ea4593c1e0f3bf8f2744836928d7454 + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2": + version: 1.2.2 + resolution: "get-intrinsic@npm:1.2.2" + dependencies: + function-bind: "npm:^1.1.2" + has-proto: "npm:^1.0.1" + has-symbols: "npm:^1.0.3" + hasown: "npm:^2.0.0" + checksum: aa96db4f809734d26d49b59bc8669d73a0ae792da561514e987735573a1dfaede516cd102f217a078ea2b42d4c4fb1f83d487932cb15d49826b726cc9cd4470b + languageName: node + linkType: hard + +"gopd@npm:^1.0.1": + version: 1.0.1 + resolution: "gopd@npm:1.0.1" + dependencies: + get-intrinsic: "npm:^1.1.3" + checksum: 5fbc7ad57b368ae4cd2f41214bd947b045c1a4be2f194a7be1778d71f8af9dbf4004221f3b6f23e30820eb0d052b4f819fe6ebe8221e2a3c6f0ee4ef173421ca + languageName: node + linkType: hard + +"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.1": + version: 1.0.1 + resolution: "has-property-descriptors@npm:1.0.1" + dependencies: + get-intrinsic: "npm:^1.2.2" + checksum: 21a47bb080a24e79594aef1ce71e1a18a1c5ab4120308e218088f67ebb7f6f408847541e2d96e5bd00e90eef5c5a49e4ebbdc8fc2d5b365a2c379aef071642f0 + languageName: node + linkType: hard + +"has-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "has-proto@npm:1.0.1" + checksum: eab2ab0ed1eae6d058b9bbc4c1d99d2751b29717be80d02fd03ead8b62675488de0c7359bc1fdd4b87ef6fd11e796a9631ad4d7452d9324fdada70158c2e5be7 + languageName: node + linkType: hard + +"has-symbols@npm:^1.0.3": + version: 1.0.3 + resolution: "has-symbols@npm:1.0.3" + checksum: 464f97a8202a7690dadd026e6d73b1ceeddd60fe6acfd06151106f050303eaa75855aaa94969df8015c11ff7c505f196114d22f7386b4a471038da5874cf5e9b + languageName: node + linkType: hard + +"hasown@npm:^2.0.0": + version: 2.0.0 + resolution: "hasown@npm:2.0.0" + dependencies: + function-bind: "npm:^1.1.2" + checksum: c330f8d93f9d23fe632c719d4db3d698ef7d7c367d51548b836069e06a90fa9151e868c8e67353cfe98d67865bf7354855db28fa36eb1b18fa5d4a3f4e7f1c90 + languageName: node + linkType: hard + +"http-errors@npm:2.0.0": + version: 2.0.0 + resolution: "http-errors@npm:2.0.0" + dependencies: + depd: "npm:2.0.0" + inherits: "npm:2.0.4" + setprototypeof: "npm:1.2.0" + statuses: "npm:2.0.1" + toidentifier: "npm:1.0.1" + checksum: 0e7f76ee8ff8a33e58a3281a469815b893c41357378f408be8f6d4aa7d1efafb0da064625518e7078381b6a92325949b119dc38fcb30bdbc4e3a35f78c44c439 + languageName: node + linkType: hard + +"iconv-lite@npm:0.4.24": + version: 0.4.24 + resolution: "iconv-lite@npm:0.4.24" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3" + checksum: 6d3a2dac6e5d1fb126d25645c25c3a1209f70cceecc68b8ef51ae0da3cdc078c151fade7524a30b12a3094926336831fca09c666ef55b37e2c69638b5d6bd2e3 + languageName: node + linkType: hard + +"inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:~2.0.3": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: cd45e923bee15186c07fa4c89db0aace24824c482fb887b528304694b2aa6ff8a898da8657046a5dcf3e46cd6db6c61629551f9215f208d7c3f157cf9b290521 + languageName: node + linkType: hard + +"ipaddr.js@npm:1.9.1": + version: 1.9.1 + resolution: "ipaddr.js@npm:1.9.1" + checksum: 864d0cced0c0832700e9621913a6429ccdc67f37c1bd78fb8c6789fff35c9d167cb329134acad2290497a53336813ab4798d2794fd675d5eb33b5fdf0982b9ca + languageName: node + linkType: hard + +"isarray@npm:~1.0.0": + version: 1.0.0 + resolution: "isarray@npm:1.0.0" + checksum: f032df8e02dce8ec565cf2eb605ea939bdccea528dbcf565cdf92bfa2da9110461159d86a537388ef1acef8815a330642d7885b29010e8f7eac967c9993b65ab + languageName: node + linkType: hard + "itty-router@npm:^4.0.27": version: 4.0.27 resolution: "itty-router@npm:4.0.27" @@ -149,6 +555,302 @@ __metadata: languageName: node linkType: hard +"media-typer@npm:0.3.0": + version: 0.3.0 + resolution: "media-typer@npm:0.3.0" + checksum: 38e0984db39139604756903a01397e29e17dcb04207bb3e081412ce725ab17338ecc47220c1b186b6bbe79a658aad1b0d41142884f5a481f36290cdefbe6aa46 + languageName: node + linkType: hard + +"merge-descriptors@npm:1.0.1": + version: 1.0.1 + resolution: "merge-descriptors@npm:1.0.1" + checksum: 5abc259d2ae25bb06d19ce2b94a21632583c74e2a9109ee1ba7fd147aa7362b380d971e0251069f8b3eb7d48c21ac839e21fa177b335e82c76ec172e30c31a26 + languageName: node + linkType: hard + +"methods@npm:~1.1.2": + version: 1.1.2 + resolution: "methods@npm:1.1.2" + checksum: a385dd974faa34b5dd021b2bbf78c722881bf6f003bfe6d391d7da3ea1ed625d1ff10ddd13c57531f628b3e785be38d3eed10ad03cebd90b76932413df9a1820 + languageName: node + linkType: hard + +"mime-db@npm:1.52.0, mime-db@npm:>= 1.43.0 < 2": + version: 1.52.0 + resolution: "mime-db@npm:1.52.0" + checksum: 54bb60bf39e6f8689f6622784e668a3d7f8bed6b0d886f5c3c446cb3284be28b30bf707ed05d0fe44a036f8469976b2629bbea182684977b084de9da274694d7 + languageName: node + linkType: hard + +"mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": + version: 2.1.35 + resolution: "mime-types@npm:2.1.35" + dependencies: + mime-db: "npm:1.52.0" + checksum: 89aa9651b67644035de2784a6e665fc685d79aba61857e02b9c8758da874a754aed4a9aced9265f5ed1171fd934331e5516b84a7f0218031b6fa0270eca1e51a + languageName: node + linkType: hard + +"mime@npm:1.6.0": + version: 1.6.0 + resolution: "mime@npm:1.6.0" + bin: + mime: cli.js + checksum: b7d98bb1e006c0e63e2c91b590fe1163b872abf8f7ef224d53dd31499c2197278a6d3d0864c45239b1a93d22feaf6f9477e9fc847eef945838150b8c02d03170 + languageName: node + linkType: hard + +"minimist@npm:^1.2.6": + version: 1.2.8 + resolution: "minimist@npm:1.2.8" + checksum: 908491b6cc15a6c440ba5b22780a0ba89b9810e1aea684e253e43c4e3b8d56ec1dcdd7ea96dde119c29df59c936cde16062159eae4225c691e19c70b432b6e6f + languageName: node + linkType: hard + +"mkdirp@npm:^0.5.4": + version: 0.5.6 + resolution: "mkdirp@npm:0.5.6" + dependencies: + minimist: "npm:^1.2.6" + bin: + mkdirp: bin/cmd.js + checksum: 0c91b721bb12c3f9af4b77ebf73604baf350e64d80df91754dc509491ae93bf238581e59c7188360cec7cb62fc4100959245a42cfe01834efedc5e9d068376c2 + languageName: node + linkType: hard + +"ms@npm:2.0.0": + version: 2.0.0 + resolution: "ms@npm:2.0.0" + checksum: 0e6a22b8b746d2e0b65a430519934fefd41b6db0682e3477c10f60c76e947c4c0ad06f63ffdf1d78d335f83edee8c0aa928aa66a36c7cd95b69b26f468d527f4 + languageName: node + linkType: hard + +"ms@npm:2.1.3": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d + languageName: node + linkType: hard + +"multer@npm:^1.4.5-lts.1": + version: 1.4.5-lts.1 + resolution: "multer@npm:1.4.5-lts.1" + dependencies: + append-field: "npm:^1.0.0" + busboy: "npm:^1.0.0" + concat-stream: "npm:^1.5.2" + mkdirp: "npm:^0.5.4" + object-assign: "npm:^4.1.1" + type-is: "npm:^1.6.4" + xtend: "npm:^4.0.0" + checksum: 957c09956f3b7f79d8586cac5e2a50e9a5c3011eb841667b5e4590c5f31d9464f5b46aecd399c83e183a15b88b019cccf0e4fa5620db40bf16b9e3af7fab3ac6 + languageName: node + linkType: hard + +"negotiator@npm:0.6.3": + version: 0.6.3 + resolution: "negotiator@npm:0.6.3" + checksum: 2723fb822a17ad55c93a588a4bc44d53b22855bf4be5499916ca0cab1e7165409d0b288ba2577d7b029f10ce18cf2ed8e703e5af31c984e1e2304277ef979837 + languageName: node + linkType: hard + +"object-assign@npm:^4.1.1": + version: 4.1.1 + resolution: "object-assign@npm:4.1.1" + checksum: fcc6e4ea8c7fe48abfbb552578b1c53e0d194086e2e6bbbf59e0a536381a292f39943c6e9628af05b5528aa5e3318bb30d6b2e53cadaf5b8fe9e12c4b69af23f + languageName: node + linkType: hard + +"object-inspect@npm:^1.9.0": + version: 1.13.1 + resolution: "object-inspect@npm:1.13.1" + checksum: 92f4989ed83422d56431bc39656d4c780348eb15d397ce352ade6b7fec08f973b53744bd41b94af021901e61acaf78fcc19e65bf464ecc0df958586a672700f0 + languageName: node + linkType: hard + +"on-finished@npm:2.4.1": + version: 2.4.1 + resolution: "on-finished@npm:2.4.1" + dependencies: + ee-first: "npm:1.1.1" + checksum: 8e81472c5028125c8c39044ac4ab8ba51a7cdc19a9fbd4710f5d524a74c6d8c9ded4dd0eed83f28d3d33ac1d7a6a439ba948ccb765ac6ce87f30450a26bfe2ea + languageName: node + linkType: hard + +"on-headers@npm:~1.0.2": + version: 1.0.2 + resolution: "on-headers@npm:1.0.2" + checksum: 870766c16345855e2012e9422ba1ab110c7e44ad5891a67790f84610bd70a72b67fdd71baf497295f1d1bf38dd4c92248f825d48729c53c0eae5262fb69fa171 + languageName: node + linkType: hard + +"parseurl@npm:~1.3.3": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2 + languageName: node + linkType: hard + +"path-to-regexp@npm:0.1.7": + version: 0.1.7 + resolution: "path-to-regexp@npm:0.1.7" + checksum: 701c99e1f08e3400bea4d701cf6f03517474bb1b608da71c78b1eb261415b645c5670dfae49808c89e12cea2dccd113b069f040a80de012da0400191c6dbd1c8 + languageName: node + linkType: hard + +"process-nextick-args@npm:~2.0.0": + version: 2.0.1 + resolution: "process-nextick-args@npm:2.0.1" + checksum: 1d38588e520dab7cea67cbbe2efdd86a10cc7a074c09657635e34f035277b59fbb57d09d8638346bf7090f8e8ebc070c96fa5fd183b777fff4f5edff5e9466cf + languageName: node + linkType: hard + +"proxy-addr@npm:~2.0.7": + version: 2.0.7 + resolution: "proxy-addr@npm:2.0.7" + dependencies: + forwarded: "npm:0.2.0" + ipaddr.js: "npm:1.9.1" + checksum: f24a0c80af0e75d31e3451398670d73406ec642914da11a2965b80b1898ca6f66a0e3e091a11a4327079b2b268795f6fa06691923fef91887215c3d0e8ea3f68 + languageName: node + linkType: hard + +"qs@npm:6.11.0": + version: 6.11.0 + resolution: "qs@npm:6.11.0" + dependencies: + side-channel: "npm:^1.0.4" + checksum: 5a3bfea3e2f359ede1bfa5d2f0dbe54001aa55e40e27dc3e60fab814362d83a9b30758db057c2011b6f53a2d4e4e5150194b5bac45372652aecb3e3c0d4b256e + languageName: node + linkType: hard + +"range-parser@npm:~1.2.1": + version: 1.2.1 + resolution: "range-parser@npm:1.2.1" + checksum: ce21ef2a2dd40506893157970dc76e835c78cf56437e26e19189c48d5291e7279314477b06ac38abd6a401b661a6840f7b03bd0b1249da9b691deeaa15872c26 + languageName: node + linkType: hard + +"raw-body@npm:2.5.1": + version: 2.5.1 + resolution: "raw-body@npm:2.5.1" + dependencies: + bytes: "npm:3.1.2" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + unpipe: "npm:1.0.0" + checksum: 280bedc12db3490ecd06f740bdcf66093a07535374b51331242382c0e130bb273ebb611b7bc4cba1b4b4e016cc7b1f4b05a6df885a6af39c2bc3b94c02291c84 + languageName: node + linkType: hard + +"readable-stream@npm:^2.2.2": + version: 2.3.8 + resolution: "readable-stream@npm:2.3.8" + dependencies: + core-util-is: "npm:~1.0.0" + inherits: "npm:~2.0.3" + isarray: "npm:~1.0.0" + process-nextick-args: "npm:~2.0.0" + safe-buffer: "npm:~5.1.1" + string_decoder: "npm:~1.1.1" + util-deprecate: "npm:~1.0.1" + checksum: 8500dd3a90e391d6c5d889256d50ec6026c059fadee98ae9aa9b86757d60ac46fff24fafb7a39fa41d54cb39d8be56cc77be202ebd4cd8ffcf4cb226cbaa40d4 + languageName: node + linkType: hard + +"safe-buffer@npm:5.1.2, safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: 7eb5b48f2ed9a594a4795677d5a150faa7eb54483b2318b568dc0c4fc94092a6cce5be02c7288a0500a156282f5276d5688bce7259299568d1053b2150ef374a + languageName: node + linkType: hard + +"safe-buffer@npm:5.2.1": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 32872cd0ff68a3ddade7a7617b8f4c2ae8764d8b7d884c651b74457967a9e0e886267d3ecc781220629c44a865167b61c375d2da6c720c840ecd73f45d5d9451 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: 7eaf7a0cf37cc27b42fb3ef6a9b1df6e93a1c6d98c6c6702b02fe262d5fcbd89db63320793b99b21cb5348097d0a53de81bd5f4e8b86e20cc9412e3f1cfb4e83 + languageName: node + linkType: hard + +"send@npm:0.18.0": + version: 0.18.0 + resolution: "send@npm:0.18.0" + dependencies: + debug: "npm:2.6.9" + depd: "npm:2.0.0" + destroy: "npm:1.2.0" + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + etag: "npm:~1.8.1" + fresh: "npm:0.5.2" + http-errors: "npm:2.0.0" + mime: "npm:1.6.0" + ms: "npm:2.1.3" + on-finished: "npm:2.4.1" + range-parser: "npm:~1.2.1" + statuses: "npm:2.0.1" + checksum: ec66c0ad109680ad8141d507677cfd8b4e40b9559de23191871803ed241718e99026faa46c398dcfb9250676076573bd6bfe5d0ec347f88f4b7b8533d1d391cb + languageName: node + linkType: hard + +"serve-static@npm:1.15.0": + version: 1.15.0 + resolution: "serve-static@npm:1.15.0" + dependencies: + encodeurl: "npm:~1.0.2" + escape-html: "npm:~1.0.3" + parseurl: "npm:~1.3.3" + send: "npm:0.18.0" + checksum: 699b2d4c29807a51d9b5e0f24955346911437aebb0178b3c4833ad30d3eca93385ff9927254f5c16da345903cad39d9cd4a532198c95a5129cc4ed43911b15a4 + languageName: node + linkType: hard + +"set-function-length@npm:^1.1.1": + version: 1.2.0 + resolution: "set-function-length@npm:1.2.0" + dependencies: + define-data-property: "npm:^1.1.1" + function-bind: "npm:^1.1.2" + get-intrinsic: "npm:^1.2.2" + gopd: "npm:^1.0.1" + has-property-descriptors: "npm:^1.0.1" + checksum: 6d609cd060c488d7d2178a5d4c3689f8a6afa26fa4c48ff4a0516664ff9b84c1c0898915777f5628092dab55c4fcead205525e2edd15c659423bf86f790fdcae + languageName: node + linkType: hard + +"setprototypeof@npm:1.2.0": + version: 1.2.0 + resolution: "setprototypeof@npm:1.2.0" + checksum: fde1630422502fbbc19e6844346778f99d449986b2f9cdcceb8326730d2f3d9964dbcb03c02aaadaefffecd0f2c063315ebea8b3ad895914bf1afc1747fc172e + languageName: node + linkType: hard + +"side-channel@npm:^1.0.4": + version: 1.0.4 + resolution: "side-channel@npm:1.0.4" + dependencies: + call-bind: "npm:^1.0.0" + get-intrinsic: "npm:^1.0.2" + object-inspect: "npm:^1.9.0" + checksum: c4998d9fc530b0e75a7fd791ad868fdc42846f072734f9080ff55cc8dc7d3899abcda24fd896aa6648c3ab7021b4bb478073eb4f44dfd55bce9714bc1a7c5d45 + languageName: node + linkType: hard + +"statuses@npm:2.0.1": + version: 2.0.1 + resolution: "statuses@npm:2.0.1" + checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb + languageName: node + linkType: hard + "streamsearch@npm:^1.1.0": version: 1.1.0 resolution: "streamsearch@npm:1.1.0" @@ -156,9 +858,77 @@ __metadata: languageName: node linkType: hard +"string_decoder@npm:~1.1.1": + version: 1.1.1 + resolution: "string_decoder@npm:1.1.1" + dependencies: + safe-buffer: "npm:~5.1.0" + checksum: 7c41c17ed4dea105231f6df208002ebddd732e8e9e2d619d133cecd8e0087ddfd9587d2feb3c8caf3213cbd841ada6d057f5142cae68a4e62d3540778d9819b4 + languageName: node + linkType: hard + +"toidentifier@npm:1.0.1": + version: 1.0.1 + resolution: "toidentifier@npm:1.0.1" + checksum: 952c29e2a85d7123239b5cfdd889a0dde47ab0497f0913d70588f19c53f7e0b5327c95f4651e413c74b785147f9637b17410ac8c846d5d4a20a5a33eb6dc3a45 + languageName: node + linkType: hard + +"type-is@npm:^1.6.4, type-is@npm:~1.6.18": + version: 1.6.18 + resolution: "type-is@npm:1.6.18" + dependencies: + media-typer: "npm:0.3.0" + mime-types: "npm:~2.1.24" + checksum: 0bd9eeae5efd27d98fd63519f999908c009e148039d8e7179a074f105362d4fcc214c38b24f6cda79c87e563cbd12083a4691381ed28559220d4a10c2047bed4 + languageName: node + linkType: hard + +"typedarray@npm:^0.0.6": + version: 0.0.6 + resolution: "typedarray@npm:0.0.6" + checksum: 2cc1bcf7d8c1237f6a16c04efc06637b2c5f2d74e58e84665445cf87668b85a21ab18dd751fa49eee6ae024b70326635d7b79ad37b1c370ed2fec6aeeeb52714 + languageName: node + linkType: hard + "undici-types@npm:~5.26.4": version: 5.26.5 resolution: "undici-types@npm:5.26.5" checksum: 0097779d94bc0fd26f0418b3a05472410408877279141ded2bd449167be1aed7ea5b76f756562cb3586a07f251b90799bab22d9019ceba49c037c76445f7cddd languageName: node linkType: hard + +"unpipe@npm:1.0.0, unpipe@npm:~1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 4fa18d8d8d977c55cb09715385c203197105e10a6d220087ec819f50cb68870f02942244f1017565484237f1f8c5d3cd413631b1ae104d3096f24fdfde1b4aa2 + languageName: node + linkType: hard + +"util-deprecate@npm:~1.0.1": + version: 1.0.2 + resolution: "util-deprecate@npm:1.0.2" + checksum: 474acf1146cb2701fe3b074892217553dfcf9a031280919ba1b8d651a068c9b15d863b7303cb15bd00a862b498e6cf4ad7b4a08fb134edd5a6f7641681cb54a2 + languageName: node + linkType: hard + +"utils-merge@npm:1.0.1": + version: 1.0.1 + resolution: "utils-merge@npm:1.0.1" + checksum: 5d6949693d58cb2e636a84f3ee1c6e7b2f9c16cb1d42d0ecb386d8c025c69e327205aa1c69e2868cc06a01e5e20681fbba55a4e0ed0cce913d60334024eae798 + languageName: node + linkType: hard + +"vary@npm:~1.1.2": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: 31389debef15a480849b8331b220782230b9815a8e0dbb7b9a8369559aed2e9a7800cd904d4371ea74f4c3527db456dc8e7ac5befce5f0d289014dbdf47b2242 + languageName: node + linkType: hard + +"xtend@npm:^4.0.0": + version: 4.0.2 + resolution: "xtend@npm:4.0.2" + checksum: ac5dfa738b21f6e7f0dd6e65e1b3155036d68104e67e5d5d1bde74892e327d7e5636a076f625599dc394330a731861e87343ff184b0047fef1360a7ec0a5a36a + languageName: node + linkType: hard From a3ccc83cf3d4cc18e2bab4a64c076678817a97be Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 21 Jan 2024 18:26:36 +0100 Subject: [PATCH 06/46] change text for custom entities --- interface/src/i18n/de/index.ts | 2 +- interface/src/i18n/en/index.ts | 2 +- interface/src/i18n/it/index.ts | 2 +- interface/src/i18n/nl/index.ts | 2 +- interface/src/i18n/pl/index.ts | 12 ++++++------ interface/src/i18n/sk/index.ts | 2 +- .../src/project/SettingsCustomEntitiesDialog.tsx | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/interface/src/i18n/de/index.ts b/interface/src/i18n/de/index.ts index 8405362e1..1f03f7fb6 100644 --- a/interface/src/i18n/de/index.ts +++ b/interface/src/i18n/de/index.ts @@ -316,7 +316,7 @@ const de: Translation = { SCHEDULE_TIMER_2: 'jede Minute', SCHEDULE_TIMER_3: 'jede Stunde', CUSTOM_ENTITIES: 'Individuelle Entitäten', - ENTITIES_HELP_1: 'Abfrage von Werten auf dem EMS-Bus', + ENTITIES_HELP_1: 'Abfrage von Werten auf dem EMS-Bus', // TODO translate ENTITIES_UPDATED: 'Entitäten gespeichert', WRITEABLE: 'Schreibbar', SHOWING: 'Anzeigen von', diff --git a/interface/src/i18n/en/index.ts b/interface/src/i18n/en/index.ts index a0df59837..9821d6f0c 100644 --- a/interface/src/i18n/en/index.ts +++ b/interface/src/i18n/en/index.ts @@ -317,7 +317,7 @@ const en: Translation = { SCHEDULE_TIMER_2: 'every minute', SCHEDULE_TIMER_3: 'every hour', CUSTOM_ENTITIES: 'Custom Entities', - ENTITIES_HELP_1: 'Fetch custom entities from the EMS bus', + ENTITIES_HELP_1: 'Define custom EMS entities or dynamic user variables', ENTITIES_UPDATED: 'Entities Updated', WRITEABLE: 'Writeable', SHOWING: 'Showing', diff --git a/interface/src/i18n/it/index.ts b/interface/src/i18n/it/index.ts index 89f07a790..1c36d95b3 100644 --- a/interface/src/i18n/it/index.ts +++ b/interface/src/i18n/it/index.ts @@ -318,7 +318,7 @@ const it: Translation = { SCHEDULE_TIMER_2: 'Ogni minuto', SCHEDULE_TIMER_3: 'Ogni ora', CUSTOM_ENTITIES: 'Entità personalizzate', - ENTITIES_HELP_1: 'Recupera entità personalizzate dal BUS EMS', + ENTITIES_HELP_1: 'Recupera entità personalizzate dal BUS EMS', // TODO translate ENTITIES_UPDATED: 'Entità aggiornate', WRITEABLE: 'Scrivibile', SHOWING: 'Visualizza', diff --git a/interface/src/i18n/nl/index.ts b/interface/src/i18n/nl/index.ts index 9cdb1e6ab..29bcb47bc 100644 --- a/interface/src/i18n/nl/index.ts +++ b/interface/src/i18n/nl/index.ts @@ -316,7 +316,7 @@ const nl: Translation = { SCHEDULE_TIMER_2: 'elke minuut', SCHEDULE_TIMER_3: 'elke huur', CUSTOM_ENTITIES: 'Aangepaste Entiteiten', - ENTITIES_HELP_1: 'Aangepaste entiteiten ophalen uit de EMS-bus', + ENTITIES_HELP_1: 'Aangepaste entiteiten ophalen uit de EMS-bus', // TODO translate ENTITIES_UPDATED: 'Entiteiten bijgewerkt', WRITEABLE: 'Beschrijfbare', SHOWING: 'Tonen', diff --git a/interface/src/i18n/pl/index.ts b/interface/src/i18n/pl/index.ts index 0b68a3728..cd082c455 100644 --- a/interface/src/i18n/pl/index.ts +++ b/interface/src/i18n/pl/index.ts @@ -316,20 +316,20 @@ const pl: BaseTranslation = { SCHEDULE_TIMER_2: 'co minutę', SCHEDULE_TIMER_3: 'co godzinę', CUSTOM_ENTITIES: '{{N|n|}}iestandardowe{{|j|}} encj{{e|i|}}', - ENTITIES_HELP_1: 'Zdefiniuj niestandardowe encje dla magistrali EMS.', + ENTITIES_HELP_1: 'Zdefiniuj niestandardowe encje dla magistrali EMS.', // TODO translate ENTITIES_UPDATED: 'Niestandardowe encje zostały uaktualnione.', WRITEABLE: 'Zapisywalna', SHOWING: 'Wyświetlane', SEARCH: 'Szukaj', CERT: 'Certyfikat główny TLS (pozostaw puste dla TLS-insecure)', ENABLE_TLS: 'Włącz wsparcie dla TLS', - ON: 'włączony', + ON: 'włączony', OFF: 'wyłączony', POLARITY: 'Typ przekaźnika', - ACTIVEHIGH: 'Wyzwalany stanem wysokim', - ACTIVELOW: 'Wyzwalany stanem niskim', - UNCHANGED: 'Zachowaj stan', - ALWAYS: 'Zawsze' + ACTIVEHIGH: 'Wyzwalany stanem wysokim', + ACTIVELOW: 'Wyzwalany stanem niskim', + UNCHANGED: 'Zachowaj stan', + ALWAYS: 'Zawsze' }; export default pl; diff --git a/interface/src/i18n/sk/index.ts b/interface/src/i18n/sk/index.ts index a7339e3c7..e6c405d59 100644 --- a/interface/src/i18n/sk/index.ts +++ b/interface/src/i18n/sk/index.ts @@ -316,7 +316,7 @@ const sk: Translation = { SCHEDULE_TIMER_2: 'každú minútu', SCHEDULE_TIMER_3: 'každú hodinu', CUSTOM_ENTITIES: 'Vlastné entity', - ENTITIES_HELP_1: 'Získavanie vlastných entít zo zbernice EMS', + ENTITIES_HELP_1: 'Získavanie vlastných entít zo zbernice EMS', // TODO translate ENTITIES_UPDATED: 'Aktualizované entity', WRITEABLE: 'Zapísateľný', SHOWING: 'Zobrazenie', diff --git a/interface/src/project/SettingsCustomEntitiesDialog.tsx b/interface/src/project/SettingsCustomEntitiesDialog.tsx index 691f23b25..58998185b 100644 --- a/interface/src/project/SettingsCustomEntitiesDialog.tsx +++ b/interface/src/project/SettingsCustomEntitiesDialog.tsx @@ -130,7 +130,7 @@ const SettingsCustomEntitiesDialog = ({ Date: Sun, 21 Jan 2024 18:26:47 +0100 Subject: [PATCH 07/46] package update --- mock-api/package.json | 2 -- mock-api/yarn.lock | 24 +----------------------- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/mock-api/package.json b/mock-api/package.json index 4b0d655df..0397efbe9 100644 --- a/mock-api/package.json +++ b/mock-api/package.json @@ -11,10 +11,8 @@ }, "dependencies": { "@msgpack/msgpack": "^2.8.0", - "busboy": "^1.6.0", "compression": "^1.7.4", "express": "^4.18.2", - "express-slow-down": "^2.0.1", "itty-router": "^4.0.27", "multer": "^1.4.5-lts.1" }, diff --git a/mock-api/yarn.lock b/mock-api/yarn.lock index 80d771471..7b08cbae3 100644 --- a/mock-api/yarn.lock +++ b/mock-api/yarn.lock @@ -138,10 +138,8 @@ __metadata: dependencies: "@msgpack/msgpack": "npm:^2.8.0" "@types/multer": "npm:^1.4.11" - busboy: "npm:^1.6.0" compression: "npm:^1.7.4" express: "npm:^4.18.2" - express-slow-down: "npm:^2.0.1" itty-router: "npm:^4.0.27" multer: "npm:^1.4.5-lts.1" languageName: unknown @@ -188,7 +186,7 @@ __metadata: languageName: node linkType: hard -"busboy@npm:^1.0.0, busboy@npm:^1.6.0": +"busboy@npm:^1.0.0": version: 1.6.0 resolution: "busboy@npm:1.6.0" dependencies: @@ -357,26 +355,6 @@ __metadata: languageName: node linkType: hard -"express-rate-limit@npm:7": - version: 7.1.5 - resolution: "express-rate-limit@npm:7.1.5" - peerDependencies: - express: 4 || 5 || ^5.0.0-beta.1 - checksum: bced4208de86fc8b99fe9a2dbfd522e0ea9a1875e678a4079102cc77c13c94f40b892ec46dac30cd028e229178ba021778070b86d0741e7258db0adc38cc858a - languageName: node - linkType: hard - -"express-slow-down@npm:^2.0.1": - version: 2.0.1 - resolution: "express-slow-down@npm:2.0.1" - dependencies: - express-rate-limit: "npm:7" - peerDependencies: - express: ">= 4" - checksum: b9b053cf99104a164420df08d6b42768024c9c797e944a7a1f631ebc5741ae31067264c0f05eca3a86eaaa9ab7c7da82d0082f135690b5cb603b687ddd36fdbb - languageName: node - linkType: hard - "express@npm:^4.18.2": version: 4.18.2 resolution: "express@npm:4.18.2" From 2a3838771a3b36e135a54b3d19bd07877cc77d4b Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 21 Jan 2024 18:27:22 +0100 Subject: [PATCH 08/46] cleanup tests --- mock-api/{Handler.ts => handler.ts} | 2 +- mock-api/server.js | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) rename mock-api/{Handler.ts => handler.ts} (99%) diff --git a/mock-api/Handler.ts b/mock-api/handler.ts similarity index 99% rename from mock-api/Handler.ts rename to mock-api/handler.ts index 08d26b876..87e02c773 100644 --- a/mock-api/Handler.ts +++ b/mock-api/handler.ts @@ -1,6 +1,6 @@ import { Router } from 'itty-router'; import { Encoder } from '@msgpack/msgpack'; -import busboy from 'busboy'; +// import busboy from 'busboy'; // import multer from 'multer'; const encoder = new Encoder(); diff --git a/mock-api/server.js b/mock-api/server.js index 3d6523945..ba672486f 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -1,5 +1,4 @@ const express = require('express'); -const rateLimit = require('express-rate-limit'); const compression = require('compression'); const path = require('path'); const msgpack = require('@msgpack/msgpack'); @@ -14,12 +13,6 @@ rest_server.use(express.static(path.join(__dirname, '../interface/build'))); rest_server.use(express.json()); // uploads -const testLimiter = rateLimit({ - windowMs: 20 * 60 * 1000, // 20 minutes - delayAfter: 70, // 70 requests - delayMs: 1000 // adding 500ms delay -}); - const upload = multer({ dest: '../mock-api/uploads' }); function progress_middleware(req, res, next) { @@ -33,7 +26,7 @@ function progress_middleware(req, res, next) { const percentage = (progress / file_size) * 100; console.log(`Progress: ${Math.round(percentage)}%`); // await delay(1000); // slow it down - // delay_blocking(1000); // slow it down + delay_blocking(1000); // slow it down }); next(); // invoke next middleware which is multer } @@ -2212,7 +2205,7 @@ rest_server.post(FACTORY_RESET_ENDPOINT, (req, res) => { res.sendStatus(200); }); -rest_server.post(UPLOAD_FILE_ENDPOINT, testLimiter, progress_middleware, upload.single('file'), (req, res) => { +rest_server.post(UPLOAD_FILE_ENDPOINT, progress_middleware, upload.single('file'), (req, res) => { console.log('command: uploadFile completed.'); if (req.file) { const filename = req.file.originalname; From 79d7142e5f8f0fd3c8158a3439684e900089bfd9 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 21 Jan 2024 18:27:58 +0100 Subject: [PATCH 09/46] add test data --- src/test/test.cpp | 63 +++++++++++++++------ src/test/test.h | 3 +- src/web/WebCustomEntityService.cpp | 90 +++++++++++++++++++++++------- src/web/WebCustomEntityService.h | 6 +- src/web/WebSchedulerService.cpp | 41 +++++++++----- src/web/WebSchedulerService.h | 4 ++ 6 files changed, 155 insertions(+), 52 deletions(-) diff --git a/src/test/test.cpp b/src/test/test.cpp index 48af75f6f..ad7015780 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -307,13 +307,19 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const } if (command == "general") { - shell.printfln("Testing adding a boiler, thermostat and sensors..."); + shell.printfln("Testing adding a boiler, thermostat, all sensors, scheduler and custom entities..."); test("general"); - // add sensors + // add analog and temperatire sensors emsesp::EMSESP::analogsensor_.test(); emsesp::EMSESP::temperaturesensor_.test(); + // scheduler + EMSESP::webSchedulerService.test(); + + // custom entities + EMSESP::webCustomEntityService.test(); + // shell.invoke_command("show devices"); // shell.invoke_command("show values"); shell.invoke_command("call system allvalues"); @@ -331,16 +337,40 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const } if (command == "custom_entities") { - shell.printfln("custom entities..."); - test("general"); + shell.printfln("Adding custom entities..."); + + // add some dummy entities + EMSESP::webCustomEntityService.test(); #ifdef EMSESP_STANDALONE AsyncWebServerRequest request; request.method(HTTP_GET); request.url("/api/custom"); - request.url("/api/custom/boiler_flowtemp"); - request.url("/api/custom/boiler_flowtemp2"); EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/custom/test_custom"); + EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/custom/test_read_only"); + EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/custom/test_ram"); + EMSESP::webAPIService.webAPIService_get(&request); + shell.invoke_command("call custom info"); + +#endif + ok = true; + } + + if (command == "scheduler") { + shell.printfln("Adding Scheduler items..."); + + // add some dummy entities + EMSESP::webSchedulerService.test(); + +#ifdef EMSESP_STANDALONE + AsyncWebServerRequest request; + request.method(HTTP_GET); + request.url("/api/scheduler"); + EMSESP::webAPIService.webAPIService_get(&request); + shell.invoke_command("call scheduler info"); #endif ok = true; } @@ -574,7 +604,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const test("boiler"); test("thermostat"); - JsonDocument doc; // some absurd high number + JsonDocument doc; for (const auto & emsdevice : EMSESP::emsdevices) { if (emsdevice) { doc.clear(); @@ -784,25 +814,26 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const ok = true; } - if (command == "custom") { - shell.printfln("Testing custom entities"); + if (command == "customization") { + shell.printfln("Testing customization renaming entity"); Mqtt::ha_enabled(true); // Mqtt::send_response(false); test("thermostat"); + // before // shell.invoke_command("call thermostat seltemp"); // shell.invoke_command("call system publish"); - // toggle mode + // find thermostat for (const auto & emsdevice : EMSESP::emsdevices) { - Serial.print("Custom: "); - Serial.print(emsdevice->device_type_name()); - Serial.print(" uniqueid="); - Serial.println(emsdevice->unique_id()); - - if (emsdevice->unique_id() == 1) { // thermostat + if (emsdevice->unique_id() == 1) { + Serial.println(); + Serial.print("Custom: "); + Serial.print(emsdevice->device_type_name()); + Serial.print(" uniqueid="); + Serial.println(emsdevice->unique_id()); std::string a = "00hc1/seltemp|new name>5<52"; emsdevice->setCustomizationEntity(a); break; diff --git a/src/test/test.h b/src/test/test.h index 83caa6e84..fbfad38b9 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -52,11 +52,12 @@ namespace emsesp { // #define EMSESP_DEBUG_DEFAULT "api_values" // #define EMSESP_DEBUG_DEFAULT "mqtt_post" // #define EMSESP_DEBUG_DEFAULT "api_wwmode" -// #define EMSESP_DEBUG_DEFAULT "custom" +// #define EMSESP_DEBUG_DEFAULT "customization" // #define EMSESP_DEBUG_DEFAULT "entity_dump" // #define EMSESP_DEBUG_DEFAULT "memory" // #define EMSESP_DEBUG_DEFAULT "coldshot" // #define EMSESP_DEBUG_DEFAULT "custom_entities" +// #define EMSESP_DEBUG_DEFAULT "scheduler" // #define EMSESP_DEBUG_DEFAULT "heat_exchange" class Test { diff --git a/src/web/WebCustomEntityService.cpp b/src/web/WebCustomEntityService.cpp index ea0b5ae55..d488ef435 100644 --- a/src/web/WebCustomEntityService.cpp +++ b/src/web/WebCustomEntityService.cpp @@ -36,7 +36,7 @@ WebCustomEntityService::WebCustomEntityService(AsyncWebServer * server, FS * fs, // load the settings when the service starts void WebCustomEntityService::begin() { _fsPersistence.readFromFS(); - EMSESP::logger().info("Starting Custom entity service"); + EMSESP::logger().info("Starting Custom Entity service"); Mqtt::subscribe(EMSdevice::DeviceType::CUSTOM, "custom/#", nullptr); // use empty function callback } @@ -61,31 +61,17 @@ void WebCustomEntity::read(WebCustomEntity & webEntity, JsonObject root) { } } -// call on initialization and also when the Entity web page is updated +// call on initialization and also when the Entity web page is updated/saved // this loads the data into the internal class StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & webCustomEntity) { -#ifdef EMSESP_STANDALONE - // invoke some fake data for testing - // clang-format off - /* prettier-ignore */ - const char * json = - "{\"entities\": [{\"id\":0,\"device_id\":8,\"type_id\":24,\"offset\":0,\"factor\":1,\"name\":\"boiler_flowtemp\",\"uom\":1,\"value_type\":1,\"writeable\":true}]}"; - // clang-format on - JsonDocument doc; - deserializeJson(doc, json); - root = doc.as(); - Serial.print(COLOR_BRIGHT_MAGENTA); - Serial.print(" Using fake custom entity file: "); - serializeJson(root, Serial); - Serial.println(COLOR_RESET); -#endif - + // reset everything to start fresh for (CustomEntityItem & entityItem : webCustomEntity.customEntityItems) { Command::erase_command(EMSdevice::DeviceType::CUSTOM, entityItem.name.c_str()); } webCustomEntity.customEntityItems.clear(); EMSESP::webCustomEntityService.ha_reset(); + // rebuild the list if (root["entities"].is()) { for (const JsonObject ei : root["entities"].as()) { auto entityItem = CustomEntityItem(); @@ -120,10 +106,13 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web } else if (entityItem.value_type == DeviceValueType::ULONG || entityItem.value_type == DeviceValueType::TIME) { entityItem.value = EMS_VALUE_DEFAULT_ULONG; } + if (entityItem.factor == 0) { entityItem.factor = 1; } + webCustomEntity.customEntityItems.push_back(entityItem); // add to list + if (entityItem.writeable) { Command::add( EMSdevice::DeviceType::CUSTOM, @@ -262,15 +251,16 @@ void WebCustomEntityService::show_values(JsonObject output) { } } - // process json output for info/commands and value_info bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd) { EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; }); + + // if it's commands... if (Helpers::toLower(cmd) == F_(commands)) { output[F_(info)] = Helpers::translated_word(FL_(info_cmd)); output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd)); for (const auto & entity : *customEntityItems) { - output[entity.name] = "custom entitiy"; + output[entity.name] = "custom entity"; } return true; } @@ -281,6 +271,7 @@ bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd) return true; } + // if it's info or values... if (strlen(cmd) == 0 || Helpers::toLower(cmd) == F_(values) || Helpers::toLower(cmd) == F_(info)) { // list all names for (const CustomEntityItem & entity : *customEntityItems) { @@ -350,12 +341,14 @@ void WebCustomEntityService::publish_single(const CustomEntityItem & entity) { if (!Mqtt::enabled() || !Mqtt::publish_single()) { return; } + char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; if (Mqtt::publish_single2cmd()) { snprintf(topic, sizeof(topic), "%s/%s", "custom", entity.name.c_str()); } else { snprintf(topic, sizeof(topic), "%s/%s", "custom_data", entity.name.c_str()); } + JsonDocument doc; JsonObject output = doc.to(); render_value(output, entity, true); @@ -473,6 +466,7 @@ uint8_t WebCustomEntityService::count_entities() { render_value(output, entity); count += (output.containsKey(entity.name) || entity.writeable) ? 1 : 0; } + return count; } @@ -482,6 +476,7 @@ uint8_t WebCustomEntityService::has_commands() { for (const CustomEntityItem & entity : *customEntityItems) { count += entity.writeable ? 1 : 0; } + return count; } @@ -547,6 +542,7 @@ void WebCustomEntityService::generate_value_web(JsonObject output) { default: break; } + // show only entities with value or command if (!obj.containsKey("v") && !obj.containsKey("c")) { data.remove(index); @@ -560,6 +556,7 @@ void WebCustomEntityService::generate_value_web(JsonObject output) { void WebCustomEntityService::fetch() { EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; }); const uint8_t len[] = {1, 1, 1, 2, 2, 3, 3}; + for (auto & entity : *customEntityItems) { if (entity.device_id > 0 && entity.type_id > 0) { // ths excludes also RAM type bool needFetch = true; @@ -615,11 +612,64 @@ bool WebCustomEntityService::get_value(std::shared_ptr telegram) // EMSESP::logger().debug("custom entity %s received with value %d", entity.name.c_str(), (int)entity.val); } } + if (has_change) { publish(); return true; } + return false; } +// hard coded tests +#ifdef EMSESP_TEST +void WebCustomEntityService::test() { + update( + [&](WebCustomEntity & webCustomEntity) { + // test 1 + auto entityItem = CustomEntityItem(); + entityItem.ram = 0; + entityItem.device_id = 8; + entityItem.type_id = 24; + entityItem.offset = 0; + entityItem.factor = 1; + entityItem.name = "test_custom"; + entityItem.uom = 1; + entityItem.value_type = 1; + entityItem.writeable = true; + entityItem.data = "70"; + webCustomEntity.customEntityItems.push_back(entityItem); + + // test 2 + entityItem.ram = 0; + entityItem.device_id = 8; + entityItem.type_id = 18; + entityItem.offset = 0; + entityItem.factor = 1; + entityItem.name = "test_read_only"; + entityItem.uom = 3; + entityItem.value_type = 2; + entityItem.writeable = false; + entityItem.data = "12"; + webCustomEntity.customEntityItems.push_back(entityItem); + + // test 2 + entityItem.ram = 1; + entityItem.device_id = 0; + entityItem.type_id = 0; + entityItem.offset = 0; + entityItem.factor = 1; + entityItem.name = "test_ram"; + entityItem.uom = 0; + entityItem.value_type = 8; + entityItem.writeable = true; + entityItem.data = "14"; + webCustomEntity.customEntityItems.push_back(entityItem); + + return StateUpdateResult::CHANGED; // persist the changes + }, + "local"); +} +#endif + } // namespace emsesp diff --git a/src/web/WebCustomEntityService.h b/src/web/WebCustomEntityService.h index 228cd95c6..ab2cef9ba 100644 --- a/src/web/WebCustomEntityService.h +++ b/src/web/WebCustomEntityService.h @@ -38,7 +38,7 @@ class CustomEntityItem { bool writeable; uint32_t value; std::string data; - uint8_t ram; + uint8_t ram; }; class WebCustomEntity { @@ -70,6 +70,10 @@ class WebCustomEntityService : public StatefulService { ha_registered_ = false; } +#if defined(EMSESP_TEST) + void test(); +#endif + private: HttpEndpoint _httpEndpoint; FSPersistence _fsPersistence; diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index b7fd19d74..80b01d806 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -54,26 +54,15 @@ void WebScheduler::read(WebScheduler & webScheduler, JsonObject root) { // call on initialization and also when the Schedule web page is saved // this loads the data into the internal class StateUpdateResult WebScheduler::update(JsonObject root, WebScheduler & webScheduler) { -#ifdef EMSESP_STANDALONE - // invoke some fake data for testing - const char * json = - "{\"schedule\": [{\"id\":1,\"active\":true,\"flags\":31,\"time\": \"07:30\",\"cmd\": \"hc1mode\",\"value\": \"day\",\"name\": \"turn on " - "central heating\"}]}"; - JsonDocument doc; - deserializeJson(doc, json); - root = doc.as(); - Serial.print(COLOR_BRIGHT_MAGENTA); - Serial.print(" Using fake scheduler file: "); - serializeJson(root, Serial); - Serial.println(COLOR_RESET); -#endif - for (ScheduleItem & scheduleItem : webScheduler.scheduleItems) { Command::erase_command(EMSdevice::DeviceType::SCHEDULER, scheduleItem.name.c_str()); } + + // reset the list webScheduler.scheduleItems.clear(); EMSESP::webSchedulerService.ha_reset(); + // build up the list of schedule items if (root["schedule"].is()) { for (const JsonObject schedule : root["schedule"].as()) { // create each schedule item, overwriting any previous settings @@ -425,4 +414,28 @@ void WebSchedulerService::loop() { } } +// hard coded tests +#if defined(EMSESP_TEST) +void WebSchedulerService::test() { + update( + [&](WebScheduler & webScheduler) { + // test 1 + auto si = ScheduleItem(); + si.active = true; + si.flags = 1; + si.time = "12:00"; + si.cmd = "test"; + si.value = "10"; + si.name = "test_scheduler"; + si.elapsed_min = 0; + si.retry_cnt = 0xFF; // no startup retries + + webScheduler.scheduleItems.push_back(si); + + return StateUpdateResult::CHANGED; // persist the changes + }, + "local"); +} +#endif + } // namespace emsesp diff --git a/src/web/WebSchedulerService.h b/src/web/WebSchedulerService.h index d5496a9e1..cb48c58b4 100644 --- a/src/web/WebSchedulerService.h +++ b/src/web/WebSchedulerService.h @@ -62,6 +62,10 @@ class WebSchedulerService : public StatefulService { ha_registered_ = false; } +#if defined(EMSESP_TEST) + void test(); +#endif + // make all functions public so we can test in the debug and standalone mode #ifndef EMSESP_STANDALONE private: From 2764185132adaf2b00ea7dcd0108d453b9c7b7ed Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 21 Jan 2024 18:28:07 +0100 Subject: [PATCH 10/46] minor text changes --- CHANGELOG.md | 2 +- src/analogsensor.cpp | 1 + src/command.cpp | 7 +++++-- src/emsesp.cpp | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e1da56db..af5bc5c7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -236,7 +236,7 @@ There are breaking changes between 3.5.x and earlier versions of 3.6.0. Please r - fix Table resizing in WebUI [#519](https://github.com/emsesp/EMS-ESP32/issues/519) - allow larger customization files [#570](https://github.com/emsesp/EMS-ESP32/issues/570) -- losing entitiy wwcomfort [#581](https://github.com/emsesp/EMS-ESP32/issues/581) +- losing entity wwcomfort [#581](https://github.com/emsesp/EMS-ESP32/issues/581) ## Changed diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index fce90371d..60cbe4e9c 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -642,6 +642,7 @@ bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int if (sensors_.empty()) { return true; } + // make a copy of the string command for parsing char command_s[30]; strlcpy(command_s, cmd, sizeof(command_s)); diff --git a/src/command.cpp b/src/command.cpp index 2724ff75e..ee16a9bb6 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -302,6 +302,7 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * // check if its a call to an end-point of a device // this is used to fetch the attributes of the device entity, or call a command directly + // for example info, values, commands, etc bool single_command = (!value || !strlen(value)); if (single_command) { // exception 1: anything that is from System @@ -474,7 +475,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo return; } - // create a list of commands, sort them + // create list of command, and sort std::list sorted_cmds; for (const auto & cf : cmdfunctions_) { if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN)) { @@ -483,7 +484,7 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo } sorted_cmds.sort(); - // if not in verbose mode, just print them on a single line + // if not in verbose mode, just print them on a single line and exit if (!verbose) { for (const auto & cl : sorted_cmds) { shell.print(cl); @@ -615,6 +616,7 @@ void Command::show_all(uuid::console::Shell & shell) { shell.print(COLOR_YELLOW); shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::CUSTOM)); shell.println(COLOR_RESET); + // TODO to remove later? shell.printf(" info:\t\t\t\t%slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); shell.println(COLOR_RESET); shell.printf(" commands:\t\t\t%slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); @@ -626,6 +628,7 @@ void Command::show_all(uuid::console::Shell & shell) { shell.print(COLOR_YELLOW); shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SCHEDULER)); shell.println(COLOR_RESET); + // TODO to remove later? shell.printf(" info:\t\t\t\t%slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); shell.println(COLOR_RESET); shell.printf(" commands:\t\t\t%slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 5d79f1790..75ce6a14f 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -685,7 +685,7 @@ bool EMSESP::get_device_value_info(JsonObject root, const char * cmd, const int8 return EMSESP::webSchedulerService.get_value_info(root, cmd); } - // own entities + // custom entities if (devicetype == DeviceType::CUSTOM) { return EMSESP::webCustomEntityService.get_value_info(root, cmd); } From 9e064eb56446a1f7999731c80991f809774734e7 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 21 Jan 2024 21:48:04 +0100 Subject: [PATCH 11/46] remove comments --- lib_standalone/FSPersistence.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib_standalone/FSPersistence.h b/lib_standalone/FSPersistence.h index df37ef67f..1b8a68c49 100644 --- a/lib_standalone/FSPersistence.h +++ b/lib_standalone/FSPersistence.h @@ -18,9 +18,9 @@ class FSPersistence { } void readFromFS() { - Serial.println(); - Serial.print("Fake reading file "); - Serial.println(_filePath); + // Serial.println(); + // Serial.print("Fake reading file "); + // Serial.println(_filePath); applyDefaults(); } From 18d329f3ee7baddd38aa724fcc6132f2a9590c60 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 21 Jan 2024 21:48:24 +0100 Subject: [PATCH 12/46] add analog test --- src/test/test.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/test/test.cpp b/src/test/test.cpp index ad7015780..176e002f5 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -55,7 +55,7 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) { // System::test_set_all_active(true); // uncomment if we want to show all entities and give them fake values add_device(0x08, 123); // Nefit Trendline - add_device(0x18, 157); // Bosch CR100 + add_device(0x18, 157); // RC200/CW100 // add_device(0x10, 158); // RC300 - there's no data here @@ -310,15 +310,11 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const shell.printfln("Testing adding a boiler, thermostat, all sensors, scheduler and custom entities..."); test("general"); - // add analog and temperatire sensors - emsesp::EMSESP::analogsensor_.test(); - emsesp::EMSESP::temperaturesensor_.test(); - - // scheduler - EMSESP::webSchedulerService.test(); - - // custom entities - EMSESP::webCustomEntityService.test(); + // setup fake data + EMSESP::webCustomizationService.test(); // set customizations + EMSESP::temperaturesensor_.test(); // add temperature sensors + EMSESP::webSchedulerService.test(); // add scheduler items + EMSESP::webCustomEntityService.test(); // add custom entities // shell.invoke_command("show devices"); // shell.invoke_command("show values"); @@ -790,15 +786,19 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const Mqtt::nested_format(1); // Mqtt::nested_format(0); - emsesp::EMSESP::analogsensor_.test(); + // load some EMS data + test("general"); + + EMSESP::webCustomizationService.test(); // load the analog sensors + shell.invoke_command("show values"); - // shell.invoke_command("call system publish"); - // shell.invoke_command("show mqtt"); + shell.invoke_command("call analogsensor info"); + shell.invoke_command("call analogsensor values"); - // rename + // test renaming it // bool update(uint8_t id, const std::string & name, int16_t offset, float factor, uint8_t uom, uint8_t type); - EMSESP::analogsensor_.update(36, "analogtest", 2, 0.7, 17, 1); - shell.invoke_command("show values"); + // EMSESP::analogsensor_.update(36, "test_analog1_new", 2, 0.7, 17, 1); + // shell.invoke_command("show values"); // shell.invoke_command("call system publish"); ok = true; } From 27d0ba0526c1ad43f639d6e26beb5595cb0bd95b Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 21 Jan 2024 21:48:36 +0100 Subject: [PATCH 13/46] store custom files for testing --- test/README.txt | 6 + .../emsesp_customizations.json | 27 ++++ .../emsesp_entities.json | 44 ++++++ .../emsesp_schedule.json | 16 +++ .../emsesp_settings.json | 128 ++++++++++++++++++ 5 files changed, 221 insertions(+) create mode 100644 test/README.txt create mode 100644 test/standalone_file_export/emsesp_customizations.json create mode 100644 test/standalone_file_export/emsesp_entities.json create mode 100644 test/standalone_file_export/emsesp_schedule.json create mode 100644 test/standalone_file_export/emsesp_settings.json diff --git a/test/README.txt b/test/README.txt new file mode 100644 index 000000000..7df9ad747 --- /dev/null +++ b/test/README.txt @@ -0,0 +1,6 @@ +This folder contains the default data used when testing in standalone mode. + +It is used for simulation and testing and can be invoked by compiling with -DEMSESP_TEST and from the Console using the command `test general` or via an API call like http://ems-esp.local/api?device=system&cmd=test&data=general + +To run in standalone mode without an ESP32 microcontroller use `make run` or `pio run -e standalone -t exec` + diff --git a/test/standalone_file_export/emsesp_customizations.json b/test/standalone_file_export/emsesp_customizations.json new file mode 100644 index 000000000..1880d6513 --- /dev/null +++ b/test/standalone_file_export/emsesp_customizations.json @@ -0,0 +1,27 @@ +{ + "type": "customizations", + "Customizations": { + "ts": [ + { + "id": "01-0203-0405-0607", + "name": "test_sensor1", + "offset": 0 + }, + { + "id": "0B-0C0D-0E0F-1011", + "name": "test_sensor2", + "offset": 4 + } + ], + "as": [], + "masked_entities": [ + { + "product_id": 123, + "device_id": 8, + "entity_ids": [ + "08heatingactive|is my heating on?" + ] + } + ] + } +} \ No newline at end of file diff --git a/test/standalone_file_export/emsesp_entities.json b/test/standalone_file_export/emsesp_entities.json new file mode 100644 index 000000000..d31abfe07 --- /dev/null +++ b/test/standalone_file_export/emsesp_entities.json @@ -0,0 +1,44 @@ +{ + "type": "entities", + "Entities": { + "entities": [ + { + "id": 0, + "ram": 0, + "device_id": 8, + "type_id": 24, + "offset": 0, + "factor": 1, + "name": "test_custom", + "uom": 1, + "value_type": 1, + "writeable": true + }, + { + "id": 1, + "ram": 0, + "device_id": 24, + "type_id": 677, + "offset": 3, + "factor": 1, + "name": "test_read_only", + "uom": 0, + "value_type": 2, + "writeable": false + }, + { + "id": 2, + "ram": 1, + "device_id": 0, + "type_id": 0, + "offset": 0, + "factor": 1, + "name": "test_ram", + "uom": 0, + "value_type": 8, + "writeable": true, + "value": "14" + } + ] + } +} \ No newline at end of file diff --git a/test/standalone_file_export/emsesp_schedule.json b/test/standalone_file_export/emsesp_schedule.json new file mode 100644 index 000000000..4292ab6a8 --- /dev/null +++ b/test/standalone_file_export/emsesp_schedule.json @@ -0,0 +1,16 @@ +{ + "type": "schedule", + "Schedule": { + "schedule": [ + { + "id": 0, + "active": true, + "flags": 1, + "time": "12:00", + "cmd": "system/fetch", + "value": "10", + "name": "test_scheduler" + } + ] + } +} \ No newline at end of file diff --git a/test/standalone_file_export/emsesp_settings.json b/test/standalone_file_export/emsesp_settings.json new file mode 100644 index 000000000..43eaecc5d --- /dev/null +++ b/test/standalone_file_export/emsesp_settings.json @@ -0,0 +1,128 @@ +{ + "type": "settings", + "System": { + "version": "3.6.5" + }, + "Network": { + "ssid": "fake", + "bssid": "", + "password": "fake", + "hostname": "ems-esp", + "static_ip_config": false, + "enableIPv6": false, + "bandwidth20": false, + "tx_power": 20, + "nosleep": false, + "enableMDNS": true, + "enableCORS": false, + "CORSOrigin": "*" + }, + "AP": { + "provision_mode": 1, + "ssid": "ems-esp", + "password": "ems-esp-neo", + "channel": 1, + "ssid_hidden": false, + "max_clients": 4, + "local_ip": "192.168.4.1", + "gateway_ip": "192.168.4.1", + "subnet_mask": "255.255.255.0" + }, + "MQTT": { + "enabled": true, + "host": "192.168.1.200", + "port": 1883, + "base": "ems-espS", + "username": "fake", + "password": "fake", + "client_id": "ems-esp", + "keep_alive": 60, + "clean_session": false, + "entity_format": 1, + "publish_time_boiler": 10, + "publish_time_thermostat": 10, + "publish_time_solar": 10, + "publish_time_mixer": 10, + "publish_time_other": 10, + "publish_time_sensor": 10, + "publish_time_heartbeat": 60, + "mqtt_qos": 0, + "mqtt_retain": false, + "ha_enabled": true, + "nested_format": 1, + "discovery_prefix": "homeassistant", + "discovery_type": 0, + "publish_single": false, + "publish_single2cmd": false, + "send_response": false + }, + "NTP": { + "enabled": false, + "server": "time.google.com", + "tz_label": "Europe/Amsterdam", + "tz_format": "CET-1CEST,M3.5.0,M10.5.0/3" + }, + "OTA": { + "enabled": false, + "port": 8266, + "password": "ems-esp-neo" + }, + "Security": { + "jwt_secret": "ems-esp-neo", + "users": [ + { + "username": "admin", + "password": "admin", + "admin": true + }, + { + "username": "guest", + "password": "guest", + "admin": false + } + ] + }, + "Settings": { + "version": "3.6.5", + "locale": "en", + "tx_mode": 1, + "ems_bus_id": 11, + "syslog_enabled": false, + "syslog_level": 3, + "trace_raw": false, + "syslog_mark_interval": 0, + "syslog_host": "", + "syslog_port": 514, + "boiler_heatingoff": false, + "shower_timer": false, + "shower_alert": false, + "shower_alert_coldshot": 10, + "shower_alert_trigger": 7, + "rx_gpio": 23, + "tx_gpio": 5, + "dallas_gpio": 18, + "dallas_parasite": false, + "led_gpio": 2, + "hide_led": false, + "low_clock": false, + "telnet_enabled": true, + "notoken_api": false, + "readonly_mode": false, + "analog_enabled": true, + "pbutton_gpio": 0, + "solar_maxflow": 30, + "board_profile": "S32", + "fahrenheit": false, + "bool_format": 1, + "bool_dashboard": 1, + "enum_format": 1, + "weblog_level": 6, + "weblog_buffer": 50, + "weblog_compact": true, + "phy_type": 0, + "eth_power": 0, + "eth_phy_addr": 0, + "eth_clock_mode": 0, + "platform": "ESP32" + } +} From fcffa3df5cc5883713c707dd53426b411f1c7b5e Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 21 Jan 2024 21:49:06 +0100 Subject: [PATCH 14/46] add comment --- src/command.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.cpp b/src/command.cpp index ee16a9bb6..f64deefd4 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -611,7 +611,7 @@ void Command::show_all(uuid::console::Shell & shell) { shell.print(COLOR_RESET); show(shell, EMSdevice::DeviceType::SYSTEM, true); - // show Custom + // show Custom Entities shell.print(COLOR_BOLD_ON); shell.print(COLOR_YELLOW); shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::CUSTOM)); From cc8839ab31b0b2812075a36b0735d6be27dfd144 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 21 Jan 2024 21:49:39 +0100 Subject: [PATCH 15/46] add tests in a consistent way --- src/analogsensor.cpp | 19 ++--- src/analogsensor.h | 5 -- src/temperaturesensor.cpp | 6 +- src/web/WebCustomEntityService.cpp | 11 +-- src/web/WebCustomizationService.cpp | 105 ++++++++++++++++++++-------- src/web/WebCustomizationService.h | 4 ++ src/web/WebSchedulerService.cpp | 3 +- 7 files changed, 96 insertions(+), 57 deletions(-) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 60cbe4e9c..38d4583e2 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -333,10 +333,10 @@ void AnalogSensor::loop() { } // update analog information name and offset -// a type of -1 is used to delete the sensor +// a type value of -1 is used to delete the sensor bool AnalogSensor::update(uint8_t gpio, const std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted) { - boolean found_sensor = false; // see if we can find the sensor in our customization list - + // first see if we can find the sensor in our customization list + bool found_sensor = false; EMSESP::webCustomizationService.update( [&](WebCustomization & settings) { for (auto & AnalogCustomization : settings.analogCustomizations) { @@ -374,7 +374,7 @@ bool AnalogSensor::update(uint8_t gpio, const std::string & name, double offset, remove_ha_topic(type, gpio); // the GPIO } - // we didn't find it, it's new, so create and store it + // we didn't find it, it's new, so create and store it in the customization list if (!found_sensor) { EMSESP::webCustomizationService.update( [&](WebCustomization & settings) { @@ -856,15 +856,4 @@ bool AnalogSensor::command_commands(const char * value, const int8_t id, JsonObj return Command::list(EMSdevice::DeviceType::ANALOGSENSOR, output); } -// hard coded tests -#ifdef EMSESP_TEST -void AnalogSensor::test() { - sensors_.emplace_back(36, "test12", 0, 0.1, 17, AnalogType::ADC); - sensors_.back().set_value(12.4); - - sensors_.emplace_back(37, "test13", 0, 0, 0, AnalogType::DIGITAL_IN); - sensors_.back().set_value(13); -} -#endif - } // namespace emsesp \ No newline at end of file diff --git a/src/analogsensor.h b/src/analogsensor.h index 12615298d..09c470397 100644 --- a/src/analogsensor.h +++ b/src/analogsensor.h @@ -158,11 +158,6 @@ class AnalogSensor { bool command_info(const char * value, const int8_t id, JsonObject output) const; - -#if defined(EMSESP_TEST) - void test(); -#endif - private: static constexpr uint8_t MAX_SENSORS = 20; static constexpr uint32_t MEASURE_ANALOG_INTERVAL = 500; diff --git a/src/temperaturesensor.cpp b/src/temperaturesensor.cpp index 5746885bb..eeaa9bc80 100644 --- a/src/temperaturesensor.cpp +++ b/src/temperaturesensor.cpp @@ -640,16 +640,18 @@ bool TemperatureSensor::Sensor::apply_customization() { #if defined(EMSESP_TEST) void TemperatureSensor::test() { // add 2 temperature sensors + // Sensor ID: 01-0203-0405-0607 uint8_t addr[ADDR_LEN] = {1, 2, 3, 4, 5, 6, 7, 8}; sensors_.emplace_back(addr); - // sensors_.back().apply_customization(); + sensors_.back().apply_customization(); sensors_.back().temperature_c = 123; sensors_.back().read = true; publish_sensor(sensors_.back()); // call publish single + // Sensor ID: 0B-0C0D-0E0F-1011 uint8_t addr2[ADDR_LEN] = {11, 12, 13, 14, 15, 16, 17, 18}; sensors_.emplace_back(addr2); - // sensors_.back().apply_customization(); + sensors_.back().apply_customization(); sensors_.back().temperature_c = 456; sensors_.back().read = true; publish_sensor(sensors_.back()); // call publish single diff --git a/src/web/WebCustomEntityService.cpp b/src/web/WebCustomEntityService.cpp index d488ef435..84881310d 100644 --- a/src/web/WebCustomEntityService.cpp +++ b/src/web/WebCustomEntityService.cpp @@ -626,6 +626,7 @@ bool WebCustomEntityService::get_value(std::shared_ptr telegram) void WebCustomEntityService::test() { update( [&](WebCustomEntity & webCustomEntity) { + webCustomEntity.customEntityItems.clear(); // test 1 auto entityItem = CustomEntityItem(); entityItem.ram = 0; @@ -642,15 +643,15 @@ void WebCustomEntityService::test() { // test 2 entityItem.ram = 0; - entityItem.device_id = 8; - entityItem.type_id = 18; - entityItem.offset = 0; + entityItem.device_id = 24; + entityItem.type_id = 677; + entityItem.offset = 3; entityItem.factor = 1; entityItem.name = "test_read_only"; - entityItem.uom = 3; + entityItem.uom = 0; entityItem.value_type = 2; entityItem.writeable = false; - entityItem.data = "12"; + entityItem.data = "48"; webCustomEntity.customEntityItems.push_back(entityItem); // test 2 diff --git a/src/web/WebCustomizationService.cpp b/src/web/WebCustomizationService.cpp index 61e9f18db..04b6c1b61 100644 --- a/src/web/WebCustomizationService.cpp +++ b/src/web/WebCustomizationService.cpp @@ -89,19 +89,6 @@ void WebCustomization::read(WebCustomization & customizations, JsonObject root) // call on initialization and also when the page is saved via web UI // this loads the data into the internal class StateUpdateResult WebCustomization::update(JsonObject root, WebCustomization & customizations) { -#ifdef EMSESP_STANDALONE - // invoke some fake data for testing - const char * json = "{\"ts\":[],\"as\":[],\"masked_entities\":[{\"product_id\":123,\"device_id\":8,\"entity_ids\":[\"08heatingactive|my custom " - "name for heating active (HS1)\",\"08tapwateractive\"]}]}"; - JsonDocument doc; - deserializeJson(doc, json); - root = doc.as(); - Serial.print(COLOR_BRIGHT_MAGENTA); - Serial.print(" Using fake customization file: "); - serializeJson(root, Serial); - Serial.println(COLOR_RESET); -#endif - // Temperature Sensor customization customizations.sensorCustomizations.clear(); if (root["ts"].is()) { @@ -120,35 +107,36 @@ StateUpdateResult WebCustomization::update(JsonObject root, WebCustomization & c if (root["as"].is()) { for (const JsonObject analogJson : root["as"].as()) { // create each of the sensor, overwriting any previous settings - auto sensor = AnalogCustomization(); - sensor.gpio = analogJson["gpio"]; - sensor.name = analogJson["name"].as(); - sensor.offset = analogJson["offset"]; - sensor.factor = analogJson["factor"]; - sensor.uom = analogJson["uom"]; - sensor.type = analogJson["type"]; - if (_start && sensor.type == EMSESP::analogsensor_.AnalogType::DIGITAL_OUT && sensor.uom > DeviceValue::DeviceValueUOM::NONE) { - sensor.offset = sensor.uom - 1; + auto analog = AnalogCustomization(); + analog.gpio = analogJson["gpio"]; + analog.name = analogJson["name"].as(); + analog.offset = analogJson["offset"]; + analog.factor = analogJson["factor"]; + analog.uom = analogJson["uom"]; + analog.type = analogJson["type"]; + if (_start && analog.type == EMSESP::analogsensor_.AnalogType::DIGITAL_OUT && analog.uom > DeviceValue::DeviceValueUOM::NONE) { + analog.offset = analog.uom - 1; } - customizations.analogCustomizations.push_back(sensor); // add to list + customizations.analogCustomizations.push_back(analog); // add to list } } + _start = false; // load array of entities id's with masks, building up the object class customizations.entityCustomizations.clear(); if (root["masked_entities"].is()) { for (const JsonObject masked_entities : root["masked_entities"].as()) { - auto new_entry = EntityCustomization(); - new_entry.product_id = masked_entities["product_id"]; - new_entry.device_id = masked_entities["device_id"]; + auto emsEntity = EntityCustomization(); + emsEntity.product_id = masked_entities["product_id"]; + emsEntity.device_id = masked_entities["device_id"]; for (const JsonVariant masked_entity_id : masked_entities["entity_ids"].as()) { if (masked_entity_id.is()) { - new_entry.entity_ids.push_back(masked_entity_id.as()); // add entity list + emsEntity.entity_ids.push_back(masked_entity_id.as()); // add entity list } } - customizations.entityCustomizations.push_back(new_entry); // save the new object + customizations.entityCustomizations.push_back(emsEntity); // save the new object } } @@ -256,6 +244,7 @@ void WebCustomizationService::customization_entities(AsyncWebServerRequest * req } // emsesp::EMSESP::logger().info(id.as()); } + // add deleted entities from file read([&](WebCustomization & settings) { for (EntityCustomization entityCustomization : settings.entityCustomizations) { @@ -282,6 +271,7 @@ void WebCustomizationService::customization_entities(AsyncWebServerRequest * req } } }); + // get list of entities that have masks set or a custom fullname emsdevice->getCustomizationEntities(entity_ids); @@ -326,4 +316,61 @@ void WebCustomizationService::begin() { _fsPersistence.readFromFS(); } -} // namespace emsesp \ No newline at end of file + +// hard coded tests +#ifdef EMSESP_TEST +void WebCustomizationService::test() { + update( + [&](WebCustomization & webCustomization) { + // Temperature sensors + webCustomization.sensorCustomizations.clear(); + auto sensor = SensorCustomization(); + sensor.id = "01-0203-0405-0607"; + sensor.name = "test_sensor1"; + sensor.offset = 0; + webCustomization.sensorCustomizations.push_back(sensor); + + sensor = SensorCustomization(); + sensor.id = "0B-0C0D-0E0F-1011"; + sensor.name = "test_sensor2"; + sensor.offset = 4; + webCustomization.sensorCustomizations.push_back(sensor); + + // Analog sensors + // This actually adds the sensors as we use customizations to store them + webCustomization.analogCustomizations.clear(); + auto analog = AnalogCustomization(); + analog.gpio = 36; + analog.name = "test_analog1"; + analog.offset = 0; + analog.factor = 0.1; + analog.uom = 17; + analog.type = 3; + webCustomization.analogCustomizations.push_back(analog); + + analog = AnalogCustomization(); + analog.gpio = 37; + analog.name = "test_analog2"; + analog.offset = 0; + analog.factor = 1; + analog.uom = 0; + analog.type = 1; + webCustomization.analogCustomizations.push_back(analog); + + // EMS entities + webCustomization.entityCustomizations.clear(); + auto emsEntity = EntityCustomization(); + emsEntity.product_id = 123; + emsEntity.device_id = 8; + emsEntity.entity_ids.push_back("08heatingactive|is my heating on?"); + webCustomization.entityCustomizations.push_back(emsEntity); + + return StateUpdateResult::CHANGED; // persist the changes + }, + "local"); + + EMSESP::analogsensor_.reload(); // this is needed to active the analog sensors +} +#endif + +} // namespace emsesp diff --git a/src/web/WebCustomizationService.h b/src/web/WebCustomizationService.h index 8ec322b71..41ceea90c 100644 --- a/src/web/WebCustomizationService.h +++ b/src/web/WebCustomizationService.h @@ -83,6 +83,10 @@ class WebCustomizationService : public StatefulService { void begin(); +#if defined(EMSESP_TEST) + void test(); +#endif + // make all functions public so we can test in the debug and standalone mode #ifndef EMSESP_STANDALONE private: diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index 80b01d806..bd2b6cb9a 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -419,12 +419,13 @@ void WebSchedulerService::loop() { void WebSchedulerService::test() { update( [&](WebScheduler & webScheduler) { + webScheduler.scheduleItems.clear(); // test 1 auto si = ScheduleItem(); si.active = true; si.flags = 1; si.time = "12:00"; - si.cmd = "test"; + si.cmd = "system/fetch"; si.value = "10"; si.name = "test_scheduler"; si.elapsed_min = 0; From 326e7bcc2a280543d839b5a2209e03dfa3e8b827 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 21 Jan 2024 21:51:52 +0100 Subject: [PATCH 16/46] add TODO comments so reminding me what to do next --- src/analogsensor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 38d4583e2..993b964a0 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -638,6 +638,7 @@ void AnalogSensor::publish_values(const bool force) { // called from emsesp.cpp, similar to the emsdevice->get_value_info // searches by name +// TODO see if this can replace the command_info bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) const { if (sensors_.empty()) { return true; @@ -700,6 +701,7 @@ bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int // creates JSON doc from values // returns true if there are no sensors +// TODO see if this can be merged with get_value_info so we can remove the commands (info, commands, etc...) bool AnalogSensor::command_info(const char * value, const int8_t id, JsonObject output) const { if (sensors_.empty()) { return true; From 8a0e037c60dc62f1c243b9d6e714abe42361303e Mon Sep 17 00:00:00 2001 From: Proddy Date: Mon, 22 Jan 2024 10:03:02 +0100 Subject: [PATCH 17/46] change default version for testing --- Makefile | 2 +- platformio.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 1beb818c8..74fb42b02 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ DEFINES += -DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_PROGMEM=1 -DAR DEFINES += -DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_TEST -D__linux__ -DEMC_RX_BUFFER_SIZE=1500 DEFINES += $(ARGS) -DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.6.4-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" +DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.6.5-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" #---------------------------------------------------------------------- # Sources & Files diff --git a/platformio.ini b/platformio.ini index 0b38c7e00..fbb56daed 100644 --- a/platformio.ini +++ b/platformio.ini @@ -171,7 +171,7 @@ platform = native build_flags = -DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_PROGMEM=1 -DARDUINOJSON_ENABLE_ARDUINO_STRING -DARDUINOJSON_USE_DOUBLE=0 -DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_TEST -D__linux__ - -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.6.4-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" + -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.6.5-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" -lpthread -std=gnu++11 -Og -ggdb build_src_flags = From 21de630f8ef58ebe8860f9a8e22aaf8f9efbd202 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Mon, 22 Jan 2024 16:13:23 +0100 Subject: [PATCH 18/46] check telegrams for dest==thermostat --- src/emsesp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 5d79f1790..8c015180d 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -922,7 +922,7 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { bool found = false; bool knowndevice = false; for (const auto & emsdevice : emsdevices) { - if (emsdevice->is_device_id(telegram->src) && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id())) { + if (emsdevice->is_device_id(telegram->src) && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id()|| telegram->dest == 0x10)) { knowndevice = true; found = emsdevice->handle_telegram(telegram); // if we correctly processed the telegram then follow up with sending it via MQTT (if enabled) From 9266454f82a6b262684cc1dd4100b1c50bc81edc Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Tue, 23 Jan 2024 13:47:28 +0100 Subject: [PATCH 19/46] rework process telegram --- interface/package.json | 8 +- interface/yarn.lock | 200 ++++++++++++++++++++--------------------- src/emsesp.cpp | 76 +++++++++------- 3 files changed, 150 insertions(+), 134 deletions(-) diff --git a/interface/package.json b/interface/package.json index 208151e8d..3d5c60ddd 100644 --- a/interface/package.json +++ b/interface/package.json @@ -24,8 +24,8 @@ "@babel/core": "^7.23.7", "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", - "@mui/icons-material": "^5.15.5", - "@mui/material": "^5.15.5", + "@mui/icons-material": "^5.15.6", + "@mui/material": "^5.15.6", "@table-library/react-table-library": "4.1.7", "@types/imagemin": "^8.0.5", "@types/lodash-es": "^4.17.12", @@ -52,8 +52,8 @@ "devDependencies": { "@preact/compat": "^17.1.2", "@preact/preset-vite": "^2.8.1", - "@typescript-eslint/eslint-plugin": "^6.19.0", - "@typescript-eslint/parser": "^6.19.0", + "@typescript-eslint/eslint-plugin": "^6.19.1", + "@typescript-eslint/parser": "^6.19.1", "concurrently": "^8.2.2", "eslint": "^8.56.0", "eslint-config-airbnb": "^19.0.4", diff --git a/interface/yarn.lock b/interface/yarn.lock index 27da2bce1..0efef8813 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -860,15 +860,15 @@ __metadata: languageName: node linkType: hard -"@floating-ui/react-dom@npm:^2.0.5": - version: 2.0.5 - resolution: "@floating-ui/react-dom@npm:2.0.5" +"@floating-ui/react-dom@npm:^2.0.6": + version: 2.0.6 + resolution: "@floating-ui/react-dom@npm:2.0.6" dependencies: "@floating-ui/dom": "npm:^1.5.4" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: b4fc008c725149b9565949184d844c914a8fa2687636c3c1166a1d52ca58537b3ba9b0a0e2945cf424662c846e60b173df0d325af7e700a31550e5e0b346070a + checksum: 4a3f828370c1b14af0e4d24df18de7b2cfd6695c189532d5949daaa43cba13ce7f231c71783b47e8c54baefcc2542650d82a4a6cebcf3d9091673f2a53d3a2cb languageName: node linkType: hard @@ -970,14 +970,14 @@ __metadata: languageName: node linkType: hard -"@mui/base@npm:5.0.0-beta.32": - version: 5.0.0-beta.32 - resolution: "@mui/base@npm:5.0.0-beta.32" +"@mui/base@npm:5.0.0-beta.33": + version: 5.0.0-beta.33 + resolution: "@mui/base@npm:5.0.0-beta.33" dependencies: "@babel/runtime": "npm:^7.23.8" - "@floating-ui/react-dom": "npm:^2.0.5" + "@floating-ui/react-dom": "npm:^2.0.6" "@mui/types": "npm:^7.2.13" - "@mui/utils": "npm:^5.15.5" + "@mui/utils": "npm:^5.15.6" "@popperjs/core": "npm:^2.11.8" clsx: "npm:^2.1.0" prop-types: "npm:^15.8.1" @@ -988,20 +988,20 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: c88cd8a412ecaeaf0040e20708b2a607b9594a4462449ad06b90e96465aad0dada23295f801ed72851025fd023ababc410b6a48fcb69d7cdef90b55e62aa9a11 + checksum: 8898430f4c8f6d9ce2aa46f621e7a84e800ee2a08fd6ce121e999494c77256060376d11e4d05640e8848eca1d8d553e95c2a150ce68d6416a1517136e8253ef8 languageName: node linkType: hard -"@mui/core-downloads-tracker@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/core-downloads-tracker@npm:5.15.5" - checksum: 4c9b1281ebe8d17d402e22f7f50c347c0b3918b1ed17af721f4de5ce282d90bc6d90fe9730595998b2bbb2f7ebe57fc55d4c858f31754fccdb606af472a59dc8 +"@mui/core-downloads-tracker@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/core-downloads-tracker@npm:5.15.6" + checksum: 38833a893c82e6244814be8321819fd08379a872068e06e1511f01ce243e21258b108fe5ddc66a02fddf07bba95b6cb6e9fc59538733c6072cab59b701ccb5c1 languageName: node linkType: hard -"@mui/icons-material@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/icons-material@npm:5.15.5" +"@mui/icons-material@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/icons-material@npm:5.15.6" dependencies: "@babel/runtime": "npm:^7.23.8" peerDependencies: @@ -1011,20 +1011,20 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 25feb86a76ce83c81391c95d0c1c867e988cc7bc1b5a05c5698b71cb3cd1005fd148b07c2fa8908cda9fc4e44ea8b6e0fd2197bc0abafac0ee4880b477852eea + checksum: b7a39bbf86beac98ac0160e6bf4c6130fae16527cbd4e545e2fbcf07105c44c86364a0e03d27120225d30e01ca1a127caf693ba5ee6d0ac34421bc6db14cdb55 languageName: node linkType: hard -"@mui/material@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/material@npm:5.15.5" +"@mui/material@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/material@npm:5.15.6" dependencies: "@babel/runtime": "npm:^7.23.8" - "@mui/base": "npm:5.0.0-beta.32" - "@mui/core-downloads-tracker": "npm:^5.15.5" - "@mui/system": "npm:^5.15.5" + "@mui/base": "npm:5.0.0-beta.33" + "@mui/core-downloads-tracker": "npm:^5.15.6" + "@mui/system": "npm:^5.15.6" "@mui/types": "npm:^7.2.13" - "@mui/utils": "npm:^5.15.5" + "@mui/utils": "npm:^5.15.6" "@types/react-transition-group": "npm:^4.4.10" clsx: "npm:^2.1.0" csstype: "npm:^3.1.2" @@ -1044,16 +1044,16 @@ __metadata: optional: true "@types/react": optional: true - checksum: 2a094d94acfc8f945b6cc73b295799f3174d7292707230e9b9486d810990561778f5f228f2fdc13a064ae234d528fb28c9b53f6c487ca43e65dc17460886165c + checksum: c6aff7dc5b65c68b4a6e1d0b4cc9712b906f0d3d57dcda49d7d4dee15e53872dec292e71bbdb38800849dccb0565aa259635e00332e85c1a8ba372322c8eeab8 languageName: node linkType: hard -"@mui/private-theming@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/private-theming@npm:5.15.5" +"@mui/private-theming@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/private-theming@npm:5.15.6" dependencies: "@babel/runtime": "npm:^7.23.8" - "@mui/utils": "npm:^5.15.5" + "@mui/utils": "npm:^5.15.6" prop-types: "npm:^15.8.1" peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 @@ -1061,13 +1061,13 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 1b26bc897417dcd91bbc65af3584c3cdf6704e9beb707c97bb7977962536213d7c7bf8e1004cbe86a19625ed5feba82d3ad2997e943138ed36114a8a36bf0fed + checksum: f56b4c99c4a634a29ff84e8d75940a6972a270ba896dae8d38ac8dc8663fe5c3c97db847c545302c80e831350b867b87c8cad6afc25eeb97ee6e0291bb274528 languageName: node linkType: hard -"@mui/styled-engine@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/styled-engine@npm:5.15.5" +"@mui/styled-engine@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/styled-engine@npm:5.15.6" dependencies: "@babel/runtime": "npm:^7.23.8" "@emotion/cache": "npm:^11.11.0" @@ -1082,19 +1082,19 @@ __metadata: optional: true "@emotion/styled": optional: true - checksum: 10e38ed39f7defc26d7e14e9634afcd9d540eaa1b9aeb957a6d1154a14a3cca2843e9aa7ead126604728bbf2125203c1f157059c06b397ed0278fc4b7cfae5c5 + checksum: 0c932a6aff4fdacc0f1dcf02768ef3d56dbed4cd58c8040e2ea33d1e0284d18183d759af240fc4a891469e0ace3a32e1b9403951ed996e6e8a736b45ccf20ecc languageName: node linkType: hard -"@mui/system@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/system@npm:5.15.5" +"@mui/system@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/system@npm:5.15.6" dependencies: "@babel/runtime": "npm:^7.23.8" - "@mui/private-theming": "npm:^5.15.5" - "@mui/styled-engine": "npm:^5.15.5" + "@mui/private-theming": "npm:^5.15.6" + "@mui/styled-engine": "npm:^5.15.6" "@mui/types": "npm:^7.2.13" - "@mui/utils": "npm:^5.15.5" + "@mui/utils": "npm:^5.15.6" clsx: "npm:^2.1.0" csstype: "npm:^3.1.2" prop-types: "npm:^15.8.1" @@ -1110,7 +1110,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: bc40858eff92efe1424b4de5782ca48ec0bccfe2de244b00af8f8607a7f47b5ec7006a0e369d1c52ddb3fe01d7666d1f7ed6d9a9070bee28dfa4ab2cecc4d015 + checksum: 742133972a60e2c137be9daf231dee47d296acb98742c6c198db94999119883bd36c24e5392eafa9c99e8fb3225883b5a20a282baf56fb29cf0a0ce51740df51 languageName: node linkType: hard @@ -1126,9 +1126,9 @@ __metadata: languageName: node linkType: hard -"@mui/utils@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/utils@npm:5.15.5" +"@mui/utils@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/utils@npm:5.15.6" dependencies: "@babel/runtime": "npm:^7.23.8" "@types/prop-types": "npm:^15.7.11" @@ -1140,7 +1140,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: c8ff39a23ec540c6fd6495e44df6dc5531afca535cbb605f81cd5ef66af946e6c6415290caade8cfa0f61ecfb55703d8065c4968530c0b54c52d44f23a04cbfe + checksum: 7ed0131bc776f01ad64615cca21b6813d44b792d61bd5a17f8b4aab8387c8c72581322c2d0f4cd9664dfecec13268c2a00b50d8991f93a9abddaf22579d68c45 languageName: node linkType: hard @@ -1691,15 +1691,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.19.0" +"@typescript-eslint/eslint-plugin@npm:^6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/eslint-plugin@npm:6.19.1" dependencies: "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:6.19.0" - "@typescript-eslint/type-utils": "npm:6.19.0" - "@typescript-eslint/utils": "npm:6.19.0" - "@typescript-eslint/visitor-keys": "npm:6.19.0" + "@typescript-eslint/scope-manager": "npm:6.19.1" + "@typescript-eslint/type-utils": "npm:6.19.1" + "@typescript-eslint/utils": "npm:6.19.1" + "@typescript-eslint/visitor-keys": "npm:6.19.1" debug: "npm:^4.3.4" graphemer: "npm:^1.4.0" ignore: "npm:^5.2.4" @@ -1712,44 +1712,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 5ed8483d792c4bc6ed697159c84a47ba5c35cd124949883813f2053b972537de3900a7ae26d4d6f370194f2cc7929baa2d09268e0b90118f20ed961cf6c176b9 + checksum: e88a35527b066a42d0253d153183a360faedc1cd39867c541ce7cb1f7b22f8446bb913b998fcdeba269d5d4217888af42e6d64da5c0592b1f49ed5648d2e3e84 languageName: node linkType: hard -"@typescript-eslint/parser@npm:^6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/parser@npm:6.19.0" +"@typescript-eslint/parser@npm:^6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/parser@npm:6.19.1" dependencies: - "@typescript-eslint/scope-manager": "npm:6.19.0" - "@typescript-eslint/types": "npm:6.19.0" - "@typescript-eslint/typescript-estree": "npm:6.19.0" - "@typescript-eslint/visitor-keys": "npm:6.19.0" + "@typescript-eslint/scope-manager": "npm:6.19.1" + "@typescript-eslint/types": "npm:6.19.1" + "@typescript-eslint/typescript-estree": "npm:6.19.1" + "@typescript-eslint/visitor-keys": "npm:6.19.1" debug: "npm:^4.3.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 0c6280a69127cf521b3403be9877775eecda2b2e4e44a67874b0d9cf82ed95a7971dac2db633e55ec22f8026da2681137110b2924313421a22b7c03eba8cda67 + checksum: 63ff00a56586879a62e40b27b55c94501173fcf2fb5a620d01e7505851b4bb20feb1e7fbad36010af97aefc0a722267d9ce3aa004abab22cb7eb23eebb0102ce languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/scope-manager@npm:6.19.0" +"@typescript-eslint/scope-manager@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/scope-manager@npm:6.19.1" dependencies: - "@typescript-eslint/types": "npm:6.19.0" - "@typescript-eslint/visitor-keys": "npm:6.19.0" - checksum: d36c51c05e14c51ce13181120eeea46d1edd59ed1ff16dc4ec1f5532a975b5faec5c10a373aaa90545f82a12330c6cba18ecedc734e18288f5874855c48ba808 + "@typescript-eslint/types": "npm:6.19.1" + "@typescript-eslint/visitor-keys": "npm:6.19.1" + checksum: 2a17f68d3c41582bfac7ecd192e2c2539cf4d2c9728a7018d842da7a8a23986b8a1f8cfcb59862c909b483140a2d164a4ba44451905e0a141378e5dd0df056cc languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/type-utils@npm:6.19.0" +"@typescript-eslint/type-utils@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/type-utils@npm:6.19.1" dependencies: - "@typescript-eslint/typescript-estree": "npm:6.19.0" - "@typescript-eslint/utils": "npm:6.19.0" + "@typescript-eslint/typescript-estree": "npm:6.19.1" + "@typescript-eslint/utils": "npm:6.19.1" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.0.1" peerDependencies: @@ -1757,23 +1757,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: f1f20ac28c03dd18546050b63ec0b0fd8c67780265ccb9ef566f16441c3de5deb2607a6046fefdebe8a43ac11fecdf0b009f8e5f70a3d15916d855be74b0f3bb + checksum: 5150b897d8b3778c549c6b964b031981da1039dfa0fb89a0eb92702735ca55793d2f840af14b340eccbca81669ba3dd02d7f09fb420fb66b18ec9f1f211b3243 languageName: node linkType: hard -"@typescript-eslint/types@npm:6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/types@npm:6.19.0" - checksum: 396ad2ad9f2d759dd87bc880a1ffc9d11fda04db8af9402abb4e8eccd58c01fa2d26e38b186526d0b457012f7c912e7afdab2a3798a73aa0ae34abaf50d617ae +"@typescript-eslint/types@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/types@npm:6.19.1" + checksum: 93f3ded80b81a1b8686866b93e36ddf9bac04604d09e88d7ed1ec25b6b2f49ff64747d8d194ba1f3215e231fd0790b88fb5ecadcc6ed53ff584f8c0b87423216 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.19.0" +"@typescript-eslint/typescript-estree@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/typescript-estree@npm:6.19.1" dependencies: - "@typescript-eslint/types": "npm:6.19.0" - "@typescript-eslint/visitor-keys": "npm:6.19.0" + "@typescript-eslint/types": "npm:6.19.1" + "@typescript-eslint/visitor-keys": "npm:6.19.1" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" @@ -1783,34 +1783,34 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 06e24bb145a302299a6cf86b36652bd4d7080c4e88517ebc24bdc137c57425a68db256ba628ce16b568bfec8020ae2a748ccee93e304efeded329cb3292b17bf + checksum: 3ce91dd477ccb2cc3cf5d07ac8d23792988f4fad78bfd39783292846f32daea5081d3790ba9cc795d9de89ea2e1d55dc9c3d2aeaa8597093b0f6ac3a206195e9 languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/utils@npm:6.19.0" +"@typescript-eslint/utils@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/utils@npm:6.19.1" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" "@types/json-schema": "npm:^7.0.12" "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:6.19.0" - "@typescript-eslint/types": "npm:6.19.0" - "@typescript-eslint/typescript-estree": "npm:6.19.0" + "@typescript-eslint/scope-manager": "npm:6.19.1" + "@typescript-eslint/types": "npm:6.19.1" + "@typescript-eslint/typescript-estree": "npm:6.19.1" semver: "npm:^7.5.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 4080c36331204ffef9f218e29f43da767f17551fa4d3877c3d3b49194f7c7382dd9ae2124e7b5ebd47d5556946bb6ad195b47d7d215553efabacdebf81b9e74d + checksum: f8931df675defa84af373c81bbb13cc34c2fcf0803c687a38b982e85335dbf2fb8415667fbabaa043df0326ba3e98ed974104bbd21f09ec538304fc3adeed0c3 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.19.0" +"@typescript-eslint/visitor-keys@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/visitor-keys@npm:6.19.1" dependencies: - "@typescript-eslint/types": "npm:6.19.0" + "@typescript-eslint/types": "npm:6.19.1" eslint-visitor-keys: "npm:^3.4.1" - checksum: 8d51c0b8d94c5df044fde958f62741cef55be97c6a3a16c47e4df9af7b2ff13aa1ee03ca5240777481dca53f3b7a9b00b329e50aff5e3ad829d96bc5f63ca2c3 + checksum: b41f3247520e1e4d3e43876843b03f0d887e544d4ac8a9e1f4b25d08568da36fedde883fa226488a595f688198859cd0290d0f1351c2ca6cbc30cca2c90adf21 languageName: node linkType: hard @@ -1829,8 +1829,8 @@ __metadata: "@babel/core": "npm:^7.23.7" "@emotion/react": "npm:^11.11.3" "@emotion/styled": "npm:^11.11.0" - "@mui/icons-material": "npm:^5.15.5" - "@mui/material": "npm:^5.15.5" + "@mui/icons-material": "npm:^5.15.6" + "@mui/material": "npm:^5.15.6" "@preact/compat": "npm:^17.1.2" "@preact/preset-vite": "npm:^2.8.1" "@table-library/react-table-library": "npm:4.1.7" @@ -1840,8 +1840,8 @@ __metadata: "@types/react": "npm:^18.2.48" "@types/react-dom": "npm:^18.2.18" "@types/react-router-dom": "npm:^5.3.3" - "@typescript-eslint/eslint-plugin": "npm:^6.19.0" - "@typescript-eslint/parser": "npm:^6.19.0" + "@typescript-eslint/eslint-plugin": "npm:^6.19.1" + "@typescript-eslint/parser": "npm:^6.19.1" alova: "npm:^2.17.0" async-validator: "npm:^4.2.5" concurrently: "npm:^8.2.2" diff --git a/src/emsesp.cpp b/src/emsesp.cpp index f8005c79a..163f537f3 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -219,9 +219,9 @@ void EMSESP::uart_init() { txservice_.tx_mode(tx_mode); // force a fetch for all new values, unless Tx is set to off - if (tx_mode != 0) { - EMSESP::fetch_device_values(); - } + // if (tx_mode != 0) { + // EMSESP::fetch_device_values(); + // } } // return status of bus: connected (0), connected but Tx is broken (1), disconnected (2) @@ -690,7 +690,7 @@ bool EMSESP::get_device_value_info(JsonObject root, const char * cmd, const int8 return EMSESP::webSchedulerService.get_value_info(root, cmd); } - // own entities + // custom entities if (devicetype == DeviceType::CUSTOM) { return EMSESP::webCustomEntityService.get_value_info(root, cmd); } @@ -924,49 +924,65 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { // calls the associated process function for that EMS device // returns false if the device_id doesn't recognize it // after the telegram has been processed, see if there have been values changed and we need to do a MQTT publish - bool found = false; - bool knowndevice = false; + bool telegram_found = false; + uint8_t device_found = 0; for (const auto & emsdevice : emsdevices) { if (emsdevice->is_device_id(telegram->src) && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id())) { - knowndevice = true; - found = emsdevice->handle_telegram(telegram); - // if we correctly processed the telegram then follow up with sending it via MQTT (if enabled) - if (found && Mqtt::connected()) { - if ((mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update()) - || (telegram->type_id == publish_id_ && telegram->dest == EMSbus::ems_bus_id())) { - if (telegram->type_id == publish_id_) { - publish_id_ = 0; - } - emsdevice->has_update(false); // reset flag - if (!Mqtt::publish_single()) { - publish_device_values(emsdevice->device_type()); // publish to MQTT if we explicitly have too - } - } + telegram_found = emsdevice->handle_telegram(telegram); + device_found = emsdevice->unique_id(); + break; + } + } + if (!telegram_found) { + // check for command to the device + for (const auto & emsdevice : emsdevices) { + if (emsdevice->is_device_id(telegram->dest) && telegram->src != EMSbus::ems_bus_id()) { + telegram_found = emsdevice->handle_telegram(telegram); + device_found = emsdevice->unique_id(); + break; } - if (wait_validate_ == telegram->type_id) { - wait_validate_ = 0; + } + } + if (!telegram_found) { + // check for sends to master thermostat + for (const auto & emsdevice : emsdevices) { + if (emsdevice->is_device_id(telegram->src) && telegram->dest != 0x10) { + telegram_found = emsdevice->handle_telegram(telegram); + device_found = emsdevice->unique_id(); + break; } - if (!found && telegram->message_length > 0) { + } + } + for (const auto & emsdevice : emsdevices) { + if (emsdevice->unique_id() == device_found) { + if (!telegram_found && telegram->message_length > 0) { emsdevice->add_handlers_ignored(telegram->type_id); } + if (Mqtt::connected() && telegram_found && (mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update()) + || (telegram->type_id == publish_id_ && telegram->dest == EMSbus::ems_bus_id())) { + if (telegram->type_id == publish_id_) { + publish_id_ = 0; + } + emsdevice->has_update(false); // reset flag + if (!Mqtt::publish_single()) { + publish_device_values(emsdevice->device_type()); // publish to MQTT if we explicitly have too + } + } break; - } else if (emsdevice->is_device_id(telegram->dest) && telegram->src != EMSbus::ems_bus_id()) { - emsdevice->handle_telegram(telegram); } } - - // handle unknown broadcasted telegrams - if (!found && telegram->dest == 0) { + // handle unknown broadcasted telegrams (or send to us) + if (!telegram_found && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id())) { LOG_DEBUG("No telegram type handler found for ID 0x%02X (src 0x%02X)", telegram->type_id, telegram->src); if (watch() == WATCH_UNKNOWN) { LOG_NOTICE("%s", pretty_telegram(telegram).c_str()); } - if (!wait_km_ && !knowndevice && (telegram->src != EMSbus::ems_bus_id()) && (telegram->message_length > 0)) { + if (!wait_km_ && !device_found && (telegram->src != EMSbus::ems_bus_id()) && (telegram->message_length > 0)) { send_read_request(EMSdevice::EMS_TYPE_VERSION, telegram->src); } } - return found; + return telegram_found; } // return true if we have this device already registered From 6aca61deee8196a31ca25cd38cb95ea399cb2730 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Wed, 24 Jan 2024 07:44:20 +0100 Subject: [PATCH 20/46] typo, telegram name for pretty telegram --- src/emsesp.cpp | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 163f537f3..3ecc78982 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -726,20 +726,25 @@ std::string EMSESP::pretty_telegram(std::shared_ptr telegram) { std::string dest_name(""); std::string type_name(""); for (const auto & emsdevice : emsdevices) { - if (emsdevice) { - // get src & dest - if (emsdevice->is_device_id(src)) { - src_name = emsdevice->device_type_name(); - } else if (emsdevice->is_device_id(dest)) { - dest_name = emsdevice->device_type_name(); + // get src & dest + if (emsdevice->is_device_id(src)) { + src_name = emsdevice->device_type_name(); + } else if (emsdevice->is_device_id(dest)) { + dest_name = emsdevice->device_type_name(); + } + // get the type name + if (type_name.empty()) { + if ((telegram->operation == Telegram::Operation::RX_READ && emsdevice->is_device_id(dest)) + || (telegram->operation != Telegram::Operation::RX_READ && dest == 0 && emsdevice->is_device_id(src)) + || (telegram->operation != Telegram::Operation::RX_READ && src == EMSbus::ems_bus_id() && emsdevice->is_device_id(dest))) { + type_name = emsdevice->telegram_type_name(telegram); } - // get the type name - if (type_name.empty()) { - if ((telegram->operation == Telegram::Operation::RX_READ && emsdevice->is_device_id(dest)) - || (telegram->operation != Telegram::Operation::RX_READ && dest == 0 && emsdevice->is_device_id(src)) - || (telegram->operation != Telegram::Operation::RX_READ && src == EMSbus::ems_bus_id() && emsdevice->is_device_id(dest))) { - type_name = emsdevice->telegram_type_name(telegram); - } + } + } + if (type_name.empty()) { + for (const auto & emsdevice : emsdevices) { + if (telegram->operation != Telegram::Operation::RX_READ && emsdevice->is_device_id(src)) { + type_name = emsdevice->telegram_type_name(telegram); } } } @@ -946,7 +951,7 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { if (!telegram_found) { // check for sends to master thermostat for (const auto & emsdevice : emsdevices) { - if (emsdevice->is_device_id(telegram->src) && telegram->dest != 0x10) { + if (emsdevice->is_device_id(telegram->src) && telegram->dest == 0x10) { telegram_found = emsdevice->handle_telegram(telegram); device_found = emsdevice->unique_id(); break; From 104229854145379a9b5c0afd6343912234f3f6f5 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Wed, 24 Jan 2024 11:10:16 +0100 Subject: [PATCH 21/46] add brackets to make logic clear --- src/emsesp.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 3ecc78982..c2f1bd472 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -963,8 +963,9 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { if (!telegram_found && telegram->message_length > 0) { emsdevice->add_handlers_ignored(telegram->type_id); } - if (Mqtt::connected() && telegram_found && (mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update()) - || (telegram->type_id == publish_id_ && telegram->dest == EMSbus::ems_bus_id())) { + if (Mqtt::connected() && telegram_found + && ((mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update()) + || (telegram->type_id == publish_id_ && telegram->dest == EMSbus::ems_bus_id()))) { if (telegram->type_id == publish_id_) { publish_id_ = 0; } From 541615d405a652684d8a1229fde12838663dcb56 Mon Sep 17 00:00:00 2001 From: Marco H Date: Wed, 24 Jan 2024 20:02:02 +0100 Subject: [PATCH 22/46] Add Buderus MX300 Internet Gateway --- src/device_library.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/device_library.h b/src/device_library.h index 0bbb79ad1..58d6e97cc 100644 --- a/src/device_library.h +++ b/src/device_library.h @@ -179,8 +179,9 @@ // Gateways - 0x48 {189, DeviceType::GATEWAY, "KM200/MB LAN 2", DeviceFlags::EMS_DEVICE_FLAG_NONE}, +{252, DeviceType::GATEWAY, "MX300", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // Generic - 0x40 or other with no product-id and no version {0, DeviceType::GENERIC, "unknown", DeviceFlags::EMS_DEVICE_FLAG_NONE} -// clang-format on \ No newline at end of file +// clang-format on From e319f5e270e22fb7665953548e8f7ffed4c528b4 Mon Sep 17 00:00:00 2001 From: proddy Date: Fri, 26 Jan 2024 23:01:17 +0100 Subject: [PATCH 23/46] package update --- interface/package.json | 12 +- interface/yarn.lock | 312 ++++++++++++++++++++++------------------- 2 files changed, 173 insertions(+), 151 deletions(-) diff --git a/interface/package.json b/interface/package.json index f84ec6f40..b3a3e0cbe 100644 --- a/interface/package.json +++ b/interface/package.json @@ -23,15 +23,15 @@ }, "dependencies": { "@alova/adapter-xhr": "^1.0.3", - "@babel/core": "^7.23.7", + "@babel/core": "^7.23.9", "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", - "@mui/icons-material": "^5.15.5", - "@mui/material": "^5.15.5", + "@mui/icons-material": "^5.15.6", + "@mui/material": "^5.15.6", "@table-library/react-table-library": "4.1.7", "@types/imagemin": "^8.0.5", "@types/lodash-es": "^4.17.12", - "@types/node": "^20.11.5", + "@types/node": "^20.11.7", "@types/react": "^18.2.48", "@types/react-dom": "^18.2.18", "@types/react-router-dom": "^5.3.3", @@ -54,8 +54,8 @@ "devDependencies": { "@preact/compat": "^17.1.2", "@preact/preset-vite": "^2.8.1", - "@typescript-eslint/eslint-plugin": "^6.19.0", - "@typescript-eslint/parser": "^6.19.0", + "@typescript-eslint/eslint-plugin": "^6.19.1", + "@typescript-eslint/parser": "^6.19.1", "concurrently": "^8.2.2", "eslint": "^8.56.0", "eslint-config-airbnb": "^19.0.4", diff --git a/interface/yarn.lock b/interface/yarn.lock index 27da2bce1..c75be5f21 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -86,26 +86,26 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.23.7": - version: 7.23.7 - resolution: "@babel/core@npm:7.23.7" +"@babel/core@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/core@npm:7.23.9" dependencies: "@ampproject/remapping": "npm:^2.2.0" "@babel/code-frame": "npm:^7.23.5" "@babel/generator": "npm:^7.23.6" "@babel/helper-compilation-targets": "npm:^7.23.6" "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helpers": "npm:^7.23.7" - "@babel/parser": "npm:^7.23.6" - "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.7" - "@babel/types": "npm:^7.23.6" + "@babel/helpers": "npm:^7.23.9" + "@babel/parser": "npm:^7.23.9" + "@babel/template": "npm:^7.23.9" + "@babel/traverse": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 956841695ea801c8b4196d01072e6c1062335960715a6fcfd4009831003b526b00627c78b373ed49b1658c3622c71142f7ff04235fe839cac4a1a25ed51b90aa + checksum: 268cdbb86bef1b8ea5b1300f2f325e56a1740a5051360cb228ffeaa0f80282b6674f3a2b4d6466adb0691183759b88d4c37b4a4f77232c84a49ed771c84cdc27 languageName: node linkType: hard @@ -304,14 +304,14 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.23.7": - version: 7.23.7 - resolution: "@babel/helpers@npm:7.23.7" +"@babel/helpers@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/helpers@npm:7.23.9" dependencies: - "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.7" - "@babel/types": "npm:^7.23.6" - checksum: ec07061dc871d406ed82c8757c4d7a510aaf15145799fb0a2c3bd3c72ca101fe82a02dd5f83ca604fbbba5de5408dd731bb1452150562bed4f3b0a2846f81f61 + "@babel/template": "npm:^7.23.9" + "@babel/traverse": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + checksum: dd56daac8bbd7ed174bb00fd185926fd449e591d9a00edaceb7ac6edbdd7a8db57e2cb365b4fafda382201752789ced2f7ae010f667eab0f198a4571cda4d2c5 languageName: node linkType: hard @@ -346,12 +346,12 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.23.6": - version: 7.23.6 - resolution: "@babel/parser@npm:7.23.6" +"@babel/parser@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/parser@npm:7.23.9" bin: parser: ./bin/babel-parser.js - checksum: 6be3a63d3c9d07b035b5a79c022327cb7e16cbd530140ecb731f19a650c794c315a72c699a22413ebeafaff14aa8f53435111898d59e01a393d741b85629fa7d + checksum: 727a7a807100f6a26df859e2f009c4ddbd0d3363287b45daa50bd082ccd0d431d0c4d0e610a91f806e04a1918726cd0f5a0592c9b902a815337feed12e1cafd9 languageName: node linkType: hard @@ -421,6 +421,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/template@npm:7.23.9" + dependencies: + "@babel/code-frame": "npm:^7.23.5" + "@babel/parser": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + checksum: 1b011ba9354dc2e646561d54b6862e0df51760e6179faadd79be05825b0b6da04911e4e192df943f1766748da3037fd8493615b38707f7cadb0cf0c96601c170 + languageName: node + linkType: hard + "@babel/traverse@npm:^7.23.2": version: 7.23.2 resolution: "@babel/traverse@npm:7.23.2" @@ -439,9 +450,9 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.23.7": - version: 7.23.7 - resolution: "@babel/traverse@npm:7.23.7" +"@babel/traverse@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/traverse@npm:7.23.9" dependencies: "@babel/code-frame": "npm:^7.23.5" "@babel/generator": "npm:^7.23.6" @@ -449,11 +460,11 @@ __metadata: "@babel/helper-function-name": "npm:^7.23.0" "@babel/helper-hoist-variables": "npm:^7.22.5" "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.23.6" - "@babel/types": "npm:^7.23.6" + "@babel/parser": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 3215e59429963c8dac85c26933372cdd322952aa9930e4bc5ef2d0e4bd7a1510d1ecf8f8fd860ace5d4d9fe496d23805a1ea019a86410aee4111de5f63ee84f9 + checksum: e2bb845f7f229feb7c338f7e150f5f1abc5395dcd3a6a47f63a25242ec3ec6b165f04a6df7d4849468547faee34eb3cf52487eb0bd867a7d3c42fec2a648266f languageName: node linkType: hard @@ -479,6 +490,17 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/types@npm:7.23.9" + dependencies: + "@babel/helper-string-parser": "npm:^7.23.4" + "@babel/helper-validator-identifier": "npm:^7.22.20" + to-fast-properties: "npm:^2.0.0" + checksum: bed9634e5fd0f9dc63c84cfa83316c4cb617192db9fedfea464fca743affe93736d7bf2ebf418ee8358751a9d388e303af87a0c050cb5d87d5870c1b0154f6cb + languageName: node + linkType: hard + "@emotion/babel-plugin@npm:^11.11.0": version: 11.11.0 resolution: "@emotion/babel-plugin@npm:11.11.0" @@ -841,38 +863,38 @@ __metadata: languageName: node linkType: hard -"@floating-ui/core@npm:^1.5.3": - version: 1.5.3 - resolution: "@floating-ui/core@npm:1.5.3" +"@floating-ui/core@npm:^1.6.0": + version: 1.6.0 + resolution: "@floating-ui/core@npm:1.6.0" dependencies: - "@floating-ui/utils": "npm:^0.2.0" - checksum: 7d9feaca2565a2a71bf03d23cd292c03def63097d7fde7d62909cdb8ddb84664781f3922086bcf10443f3310cb92381a0ecf745b2774edb917fa74fe61015c56 + "@floating-ui/utils": "npm:^0.2.1" + checksum: d6a47cacde193cd8ccb4c268b91ccc4ca254dffaec6242b07fd9bcde526044cc976d27933a7917f9a671de0a0e27f8d358f46400677dbd0c8199de293e9746e1 languageName: node linkType: hard -"@floating-ui/dom@npm:^1.5.4": - version: 1.5.4 - resolution: "@floating-ui/dom@npm:1.5.4" +"@floating-ui/dom@npm:^1.6.0": + version: 1.6.0 + resolution: "@floating-ui/dom@npm:1.6.0" dependencies: - "@floating-ui/core": "npm:^1.5.3" - "@floating-ui/utils": "npm:^0.2.0" - checksum: 3ba02ba2b4227c1e18df6ccdd029a1c100058db2e76ca1dac60a593ec72b2d4d995fa5c2d1639a5c38adb17e12398fbfe4f6cf5fd45f2ee6170ed0cf64acea06 + "@floating-ui/core": "npm:^1.6.0" + "@floating-ui/utils": "npm:^0.2.1" + checksum: fc559385a27feddff31bdb9f4c8bc05e12bda5aac4e44e7b5850a2af3d2960bf58d72034ccc3fc6c1bf5e69a97d6b5958ee73a885b5e7e7594dc4fa2c22ba47d languageName: node linkType: hard -"@floating-ui/react-dom@npm:^2.0.5": - version: 2.0.5 - resolution: "@floating-ui/react-dom@npm:2.0.5" +"@floating-ui/react-dom@npm:^2.0.6": + version: 2.0.7 + resolution: "@floating-ui/react-dom@npm:2.0.7" dependencies: - "@floating-ui/dom": "npm:^1.5.4" + "@floating-ui/dom": "npm:^1.6.0" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: b4fc008c725149b9565949184d844c914a8fa2687636c3c1166a1d52ca58537b3ba9b0a0e2945cf424662c846e60b173df0d325af7e700a31550e5e0b346070a + checksum: 15eb9ec493781253077e7e26c65c56586a1c92c414879c55d779cba5479d46b8897de06d61c831d03d24c24894257817fed9a515a4f2dc955666df5156dd757b languageName: node linkType: hard -"@floating-ui/utils@npm:^0.2.0": +"@floating-ui/utils@npm:^0.2.1": version: 0.2.1 resolution: "@floating-ui/utils@npm:0.2.1" checksum: 33c9ab346e7b05c5a1e6a95bc902aafcfc2c9d513a147e2491468843bd5607531b06d0b9aa56aa491cbf22a6c2495c18ccfc4c0344baec54a689a7bb8e4898d6 @@ -970,14 +992,14 @@ __metadata: languageName: node linkType: hard -"@mui/base@npm:5.0.0-beta.32": - version: 5.0.0-beta.32 - resolution: "@mui/base@npm:5.0.0-beta.32" +"@mui/base@npm:5.0.0-beta.33": + version: 5.0.0-beta.33 + resolution: "@mui/base@npm:5.0.0-beta.33" dependencies: "@babel/runtime": "npm:^7.23.8" - "@floating-ui/react-dom": "npm:^2.0.5" + "@floating-ui/react-dom": "npm:^2.0.6" "@mui/types": "npm:^7.2.13" - "@mui/utils": "npm:^5.15.5" + "@mui/utils": "npm:^5.15.6" "@popperjs/core": "npm:^2.11.8" clsx: "npm:^2.1.0" prop-types: "npm:^15.8.1" @@ -988,20 +1010,20 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: c88cd8a412ecaeaf0040e20708b2a607b9594a4462449ad06b90e96465aad0dada23295f801ed72851025fd023ababc410b6a48fcb69d7cdef90b55e62aa9a11 + checksum: 8898430f4c8f6d9ce2aa46f621e7a84e800ee2a08fd6ce121e999494c77256060376d11e4d05640e8848eca1d8d553e95c2a150ce68d6416a1517136e8253ef8 languageName: node linkType: hard -"@mui/core-downloads-tracker@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/core-downloads-tracker@npm:5.15.5" - checksum: 4c9b1281ebe8d17d402e22f7f50c347c0b3918b1ed17af721f4de5ce282d90bc6d90fe9730595998b2bbb2f7ebe57fc55d4c858f31754fccdb606af472a59dc8 +"@mui/core-downloads-tracker@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/core-downloads-tracker@npm:5.15.6" + checksum: 38833a893c82e6244814be8321819fd08379a872068e06e1511f01ce243e21258b108fe5ddc66a02fddf07bba95b6cb6e9fc59538733c6072cab59b701ccb5c1 languageName: node linkType: hard -"@mui/icons-material@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/icons-material@npm:5.15.5" +"@mui/icons-material@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/icons-material@npm:5.15.6" dependencies: "@babel/runtime": "npm:^7.23.8" peerDependencies: @@ -1011,20 +1033,20 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 25feb86a76ce83c81391c95d0c1c867e988cc7bc1b5a05c5698b71cb3cd1005fd148b07c2fa8908cda9fc4e44ea8b6e0fd2197bc0abafac0ee4880b477852eea + checksum: b7a39bbf86beac98ac0160e6bf4c6130fae16527cbd4e545e2fbcf07105c44c86364a0e03d27120225d30e01ca1a127caf693ba5ee6d0ac34421bc6db14cdb55 languageName: node linkType: hard -"@mui/material@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/material@npm:5.15.5" +"@mui/material@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/material@npm:5.15.6" dependencies: "@babel/runtime": "npm:^7.23.8" - "@mui/base": "npm:5.0.0-beta.32" - "@mui/core-downloads-tracker": "npm:^5.15.5" - "@mui/system": "npm:^5.15.5" + "@mui/base": "npm:5.0.0-beta.33" + "@mui/core-downloads-tracker": "npm:^5.15.6" + "@mui/system": "npm:^5.15.6" "@mui/types": "npm:^7.2.13" - "@mui/utils": "npm:^5.15.5" + "@mui/utils": "npm:^5.15.6" "@types/react-transition-group": "npm:^4.4.10" clsx: "npm:^2.1.0" csstype: "npm:^3.1.2" @@ -1044,16 +1066,16 @@ __metadata: optional: true "@types/react": optional: true - checksum: 2a094d94acfc8f945b6cc73b295799f3174d7292707230e9b9486d810990561778f5f228f2fdc13a064ae234d528fb28c9b53f6c487ca43e65dc17460886165c + checksum: c6aff7dc5b65c68b4a6e1d0b4cc9712b906f0d3d57dcda49d7d4dee15e53872dec292e71bbdb38800849dccb0565aa259635e00332e85c1a8ba372322c8eeab8 languageName: node linkType: hard -"@mui/private-theming@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/private-theming@npm:5.15.5" +"@mui/private-theming@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/private-theming@npm:5.15.6" dependencies: "@babel/runtime": "npm:^7.23.8" - "@mui/utils": "npm:^5.15.5" + "@mui/utils": "npm:^5.15.6" prop-types: "npm:^15.8.1" peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 @@ -1061,13 +1083,13 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 1b26bc897417dcd91bbc65af3584c3cdf6704e9beb707c97bb7977962536213d7c7bf8e1004cbe86a19625ed5feba82d3ad2997e943138ed36114a8a36bf0fed + checksum: f56b4c99c4a634a29ff84e8d75940a6972a270ba896dae8d38ac8dc8663fe5c3c97db847c545302c80e831350b867b87c8cad6afc25eeb97ee6e0291bb274528 languageName: node linkType: hard -"@mui/styled-engine@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/styled-engine@npm:5.15.5" +"@mui/styled-engine@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/styled-engine@npm:5.15.6" dependencies: "@babel/runtime": "npm:^7.23.8" "@emotion/cache": "npm:^11.11.0" @@ -1082,19 +1104,19 @@ __metadata: optional: true "@emotion/styled": optional: true - checksum: 10e38ed39f7defc26d7e14e9634afcd9d540eaa1b9aeb957a6d1154a14a3cca2843e9aa7ead126604728bbf2125203c1f157059c06b397ed0278fc4b7cfae5c5 + checksum: 0c932a6aff4fdacc0f1dcf02768ef3d56dbed4cd58c8040e2ea33d1e0284d18183d759af240fc4a891469e0ace3a32e1b9403951ed996e6e8a736b45ccf20ecc languageName: node linkType: hard -"@mui/system@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/system@npm:5.15.5" +"@mui/system@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/system@npm:5.15.6" dependencies: "@babel/runtime": "npm:^7.23.8" - "@mui/private-theming": "npm:^5.15.5" - "@mui/styled-engine": "npm:^5.15.5" + "@mui/private-theming": "npm:^5.15.6" + "@mui/styled-engine": "npm:^5.15.6" "@mui/types": "npm:^7.2.13" - "@mui/utils": "npm:^5.15.5" + "@mui/utils": "npm:^5.15.6" clsx: "npm:^2.1.0" csstype: "npm:^3.1.2" prop-types: "npm:^15.8.1" @@ -1110,7 +1132,7 @@ __metadata: optional: true "@types/react": optional: true - checksum: bc40858eff92efe1424b4de5782ca48ec0bccfe2de244b00af8f8607a7f47b5ec7006a0e369d1c52ddb3fe01d7666d1f7ed6d9a9070bee28dfa4ab2cecc4d015 + checksum: 742133972a60e2c137be9daf231dee47d296acb98742c6c198db94999119883bd36c24e5392eafa9c99e8fb3225883b5a20a282baf56fb29cf0a0ce51740df51 languageName: node linkType: hard @@ -1126,9 +1148,9 @@ __metadata: languageName: node linkType: hard -"@mui/utils@npm:^5.15.5": - version: 5.15.5 - resolution: "@mui/utils@npm:5.15.5" +"@mui/utils@npm:^5.15.6": + version: 5.15.6 + resolution: "@mui/utils@npm:5.15.6" dependencies: "@babel/runtime": "npm:^7.23.8" "@types/prop-types": "npm:^15.7.11" @@ -1140,7 +1162,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: c8ff39a23ec540c6fd6495e44df6dc5531afca535cbb605f81cd5ef66af946e6c6415290caade8cfa0f61ecfb55703d8065c4968530c0b54c52d44f23a04cbfe + checksum: 7ed0131bc776f01ad64615cca21b6813d44b792d61bd5a17f8b4aab8387c8c72581322c2d0f4cd9664dfecec13268c2a00b50d8991f93a9abddaf22579d68c45 languageName: node linkType: hard @@ -1568,12 +1590,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^20.11.5": - version: 20.11.5 - resolution: "@types/node@npm:20.11.5" +"@types/node@npm:^20.11.7": + version: 20.11.7 + resolution: "@types/node@npm:20.11.7" dependencies: undici-types: "npm:~5.26.4" - checksum: 9f31c471047d7b3e240ce7b77ff29b0d15e83be7e3feafb3d0b0d0931122b438b1eefa302a5a2e1e9849914ff3fd76aafbd8ccb372efb1331ba048da63bce6f8 + checksum: ff0428c093987f1f6e3400b91450077cf006d7f0e4ff316e20636218562c53761565ceb06bd7a161badf46e6884d78b554c7b1c3a7717cf5cb8c97f461ecd754 languageName: node linkType: hard @@ -1691,15 +1713,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.19.0" +"@typescript-eslint/eslint-plugin@npm:^6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/eslint-plugin@npm:6.19.1" dependencies: "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:6.19.0" - "@typescript-eslint/type-utils": "npm:6.19.0" - "@typescript-eslint/utils": "npm:6.19.0" - "@typescript-eslint/visitor-keys": "npm:6.19.0" + "@typescript-eslint/scope-manager": "npm:6.19.1" + "@typescript-eslint/type-utils": "npm:6.19.1" + "@typescript-eslint/utils": "npm:6.19.1" + "@typescript-eslint/visitor-keys": "npm:6.19.1" debug: "npm:^4.3.4" graphemer: "npm:^1.4.0" ignore: "npm:^5.2.4" @@ -1712,44 +1734,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 5ed8483d792c4bc6ed697159c84a47ba5c35cd124949883813f2053b972537de3900a7ae26d4d6f370194f2cc7929baa2d09268e0b90118f20ed961cf6c176b9 + checksum: e88a35527b066a42d0253d153183a360faedc1cd39867c541ce7cb1f7b22f8446bb913b998fcdeba269d5d4217888af42e6d64da5c0592b1f49ed5648d2e3e84 languageName: node linkType: hard -"@typescript-eslint/parser@npm:^6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/parser@npm:6.19.0" +"@typescript-eslint/parser@npm:^6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/parser@npm:6.19.1" dependencies: - "@typescript-eslint/scope-manager": "npm:6.19.0" - "@typescript-eslint/types": "npm:6.19.0" - "@typescript-eslint/typescript-estree": "npm:6.19.0" - "@typescript-eslint/visitor-keys": "npm:6.19.0" + "@typescript-eslint/scope-manager": "npm:6.19.1" + "@typescript-eslint/types": "npm:6.19.1" + "@typescript-eslint/typescript-estree": "npm:6.19.1" + "@typescript-eslint/visitor-keys": "npm:6.19.1" debug: "npm:^4.3.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 0c6280a69127cf521b3403be9877775eecda2b2e4e44a67874b0d9cf82ed95a7971dac2db633e55ec22f8026da2681137110b2924313421a22b7c03eba8cda67 + checksum: 63ff00a56586879a62e40b27b55c94501173fcf2fb5a620d01e7505851b4bb20feb1e7fbad36010af97aefc0a722267d9ce3aa004abab22cb7eb23eebb0102ce languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/scope-manager@npm:6.19.0" +"@typescript-eslint/scope-manager@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/scope-manager@npm:6.19.1" dependencies: - "@typescript-eslint/types": "npm:6.19.0" - "@typescript-eslint/visitor-keys": "npm:6.19.0" - checksum: d36c51c05e14c51ce13181120eeea46d1edd59ed1ff16dc4ec1f5532a975b5faec5c10a373aaa90545f82a12330c6cba18ecedc734e18288f5874855c48ba808 + "@typescript-eslint/types": "npm:6.19.1" + "@typescript-eslint/visitor-keys": "npm:6.19.1" + checksum: 2a17f68d3c41582bfac7ecd192e2c2539cf4d2c9728a7018d842da7a8a23986b8a1f8cfcb59862c909b483140a2d164a4ba44451905e0a141378e5dd0df056cc languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/type-utils@npm:6.19.0" +"@typescript-eslint/type-utils@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/type-utils@npm:6.19.1" dependencies: - "@typescript-eslint/typescript-estree": "npm:6.19.0" - "@typescript-eslint/utils": "npm:6.19.0" + "@typescript-eslint/typescript-estree": "npm:6.19.1" + "@typescript-eslint/utils": "npm:6.19.1" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.0.1" peerDependencies: @@ -1757,23 +1779,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: f1f20ac28c03dd18546050b63ec0b0fd8c67780265ccb9ef566f16441c3de5deb2607a6046fefdebe8a43ac11fecdf0b009f8e5f70a3d15916d855be74b0f3bb + checksum: 5150b897d8b3778c549c6b964b031981da1039dfa0fb89a0eb92702735ca55793d2f840af14b340eccbca81669ba3dd02d7f09fb420fb66b18ec9f1f211b3243 languageName: node linkType: hard -"@typescript-eslint/types@npm:6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/types@npm:6.19.0" - checksum: 396ad2ad9f2d759dd87bc880a1ffc9d11fda04db8af9402abb4e8eccd58c01fa2d26e38b186526d0b457012f7c912e7afdab2a3798a73aa0ae34abaf50d617ae +"@typescript-eslint/types@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/types@npm:6.19.1" + checksum: 93f3ded80b81a1b8686866b93e36ddf9bac04604d09e88d7ed1ec25b6b2f49ff64747d8d194ba1f3215e231fd0790b88fb5ecadcc6ed53ff584f8c0b87423216 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.19.0" +"@typescript-eslint/typescript-estree@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/typescript-estree@npm:6.19.1" dependencies: - "@typescript-eslint/types": "npm:6.19.0" - "@typescript-eslint/visitor-keys": "npm:6.19.0" + "@typescript-eslint/types": "npm:6.19.1" + "@typescript-eslint/visitor-keys": "npm:6.19.1" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" @@ -1783,34 +1805,34 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 06e24bb145a302299a6cf86b36652bd4d7080c4e88517ebc24bdc137c57425a68db256ba628ce16b568bfec8020ae2a748ccee93e304efeded329cb3292b17bf + checksum: 3ce91dd477ccb2cc3cf5d07ac8d23792988f4fad78bfd39783292846f32daea5081d3790ba9cc795d9de89ea2e1d55dc9c3d2aeaa8597093b0f6ac3a206195e9 languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/utils@npm:6.19.0" +"@typescript-eslint/utils@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/utils@npm:6.19.1" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" "@types/json-schema": "npm:^7.0.12" "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:6.19.0" - "@typescript-eslint/types": "npm:6.19.0" - "@typescript-eslint/typescript-estree": "npm:6.19.0" + "@typescript-eslint/scope-manager": "npm:6.19.1" + "@typescript-eslint/types": "npm:6.19.1" + "@typescript-eslint/typescript-estree": "npm:6.19.1" semver: "npm:^7.5.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 4080c36331204ffef9f218e29f43da767f17551fa4d3877c3d3b49194f7c7382dd9ae2124e7b5ebd47d5556946bb6ad195b47d7d215553efabacdebf81b9e74d + checksum: f8931df675defa84af373c81bbb13cc34c2fcf0803c687a38b982e85335dbf2fb8415667fbabaa043df0326ba3e98ed974104bbd21f09ec538304fc3adeed0c3 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.19.0": - version: 6.19.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.19.0" +"@typescript-eslint/visitor-keys@npm:6.19.1": + version: 6.19.1 + resolution: "@typescript-eslint/visitor-keys@npm:6.19.1" dependencies: - "@typescript-eslint/types": "npm:6.19.0" + "@typescript-eslint/types": "npm:6.19.1" eslint-visitor-keys: "npm:^3.4.1" - checksum: 8d51c0b8d94c5df044fde958f62741cef55be97c6a3a16c47e4df9af7b2ff13aa1ee03ca5240777481dca53f3b7a9b00b329e50aff5e3ad829d96bc5f63ca2c3 + checksum: b41f3247520e1e4d3e43876843b03f0d887e544d4ac8a9e1f4b25d08568da36fedde883fa226488a595f688198859cd0290d0f1351c2ca6cbc30cca2c90adf21 languageName: node linkType: hard @@ -1826,22 +1848,22 @@ __metadata: resolution: "EMS-ESP@workspace:." dependencies: "@alova/adapter-xhr": "npm:^1.0.3" - "@babel/core": "npm:^7.23.7" + "@babel/core": "npm:^7.23.9" "@emotion/react": "npm:^11.11.3" "@emotion/styled": "npm:^11.11.0" - "@mui/icons-material": "npm:^5.15.5" - "@mui/material": "npm:^5.15.5" + "@mui/icons-material": "npm:^5.15.6" + "@mui/material": "npm:^5.15.6" "@preact/compat": "npm:^17.1.2" "@preact/preset-vite": "npm:^2.8.1" "@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.5" + "@types/node": "npm:^20.11.7" "@types/react": "npm:^18.2.48" "@types/react-dom": "npm:^18.2.18" "@types/react-router-dom": "npm:^5.3.3" - "@typescript-eslint/eslint-plugin": "npm:^6.19.0" - "@typescript-eslint/parser": "npm:^6.19.0" + "@typescript-eslint/eslint-plugin": "npm:^6.19.1" + "@typescript-eslint/parser": "npm:^6.19.1" alova: "npm:^2.17.0" async-validator: "npm:^4.2.5" concurrently: "npm:^8.2.2" From 34cafe0d4d09a66a7ba72f83b6a4588985c98dbf Mon Sep 17 00:00:00 2001 From: proddy Date: Fri, 26 Jan 2024 23:01:44 +0100 Subject: [PATCH 24/46] minor refactor moving scheduler item list loading once --- src/web/WebSchedulerService.cpp | 50 ++++++++++++++++++++------------- src/web/WebSchedulerService.h | 2 +- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index bd2b6cb9a..d45c31b07 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -17,6 +17,7 @@ */ #include "emsesp.h" +#include "WebSchedulerService.h" namespace emsesp { @@ -30,6 +31,13 @@ WebSchedulerService::WebSchedulerService(AsyncWebServer * server, FS * fs, Secur // load the settings when the service starts void WebSchedulerService::begin() { _fsPersistence.readFromFS(); + + // save a local pointer to the scheduler item list + EMSESP::webSchedulerService.read([&](WebScheduler & webScheduler) { + // + scheduleItems_ = &webScheduler.scheduleItems; + }); + EMSESP::logger().info("Starting Scheduler service"); Mqtt::subscribe(EMSdevice::DeviceType::SCHEDULER, "scheduler/#", nullptr); // use empty function callback } @@ -92,7 +100,9 @@ StateUpdateResult WebScheduler::update(JsonObject root, WebScheduler & webSchedu } } } + EMSESP::webSchedulerService.publish(true); + return StateUpdateResult::CHANGED; } @@ -103,17 +113,19 @@ bool WebSchedulerService::command_setvalue(const char * value, const std::string return false; } - EMSESP::webSchedulerService.read([&](WebScheduler & webScheduler) { scheduleItems = &webScheduler.scheduleItems; }); - for (ScheduleItem & scheduleItem : *scheduleItems) { + for (ScheduleItem & scheduleItem : *scheduleItems_) { if (scheduleItem.name == name) { if (scheduleItem.active == v) { return true; } + scheduleItem.active = v; publish_single(name.c_str(), v); + if (EMSESP::mqtt_.get_publish_onchange(0)) { publish(); } + return true; } } @@ -122,25 +134,26 @@ bool WebSchedulerService::command_setvalue(const char * value, const std::string // process json output for info/commands and value_info bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) { - EMSESP::webSchedulerService.read([&](WebScheduler & webScheduler) { scheduleItems = &webScheduler.scheduleItems; }); if (Helpers::toLower(cmd) == F_(commands)) { output[F_(info)] = Helpers::translated_word(FL_(info_cmd)); output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd)); - for (const ScheduleItem & scheduleItem : *scheduleItems) { + + for (const ScheduleItem & scheduleItem : *scheduleItems_) { if (!scheduleItem.name.empty()) { output[scheduleItem.name] = "activate schedule"; } } + return true; } - if (scheduleItems->size() == 0) { + if (scheduleItems_->size() == 0) { return true; } if (strlen(cmd) == 0 || Helpers::toLower(cmd) == F_(values) || Helpers::toLower(cmd) == F_(info)) { // list all names - for (const ScheduleItem & scheduleItem : *scheduleItems) { + for (const ScheduleItem & scheduleItem : *scheduleItems_) { if (!scheduleItem.name.empty()) { if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) { output[scheduleItem.name] = scheduleItem.active; @@ -152,6 +165,7 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) { } } } + return (output.size() > 0); } @@ -166,7 +180,7 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) { attribute_s = breakp + 1; } - for (const ScheduleItem & scheduleItem : *scheduleItems) { + for (const ScheduleItem & scheduleItem : *scheduleItems_) { if (Helpers::toLower(scheduleItem.name) == Helpers::toLower(command_s)) { output["name"] = scheduleItem.name; output["type"] = "boolean"; @@ -227,20 +241,19 @@ void WebSchedulerService::publish(const bool force) { return; } - EMSESP::webSchedulerService.read([&](WebScheduler & webScheduler) { scheduleItems = &webScheduler.scheduleItems; }); - if (scheduleItems->size() == 0) { + if (scheduleItems_->size() == 0) { return; } if (Mqtt::publish_single() && force) { - for (const ScheduleItem & scheduleItem : *scheduleItems) { + for (const ScheduleItem & scheduleItem : *scheduleItems_) { publish_single(scheduleItem.name.c_str(), scheduleItem.active); } } JsonDocument doc; bool ha_created = ha_registered_; - for (const ScheduleItem & scheduleItem : *scheduleItems) { + for (const ScheduleItem & scheduleItem : *scheduleItems_) { if (!scheduleItem.name.empty() && !doc.containsKey(scheduleItem.name)) { if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) { doc[scheduleItem.name] = scheduleItem.active; @@ -303,16 +316,16 @@ void WebSchedulerService::publish(const bool force) { } bool WebSchedulerService::has_commands() { - EMSESP::webSchedulerService.read([&](WebScheduler & webScheduler) { scheduleItems = &webScheduler.scheduleItems; }); - if (scheduleItems->size() == 0) { + if (scheduleItems_->size() == 0) { return false; } - for (const ScheduleItem & scheduleItem : *scheduleItems) { + for (const ScheduleItem & scheduleItem : *scheduleItems_) { if (!scheduleItem.name.empty()) { return true; } } + return false; } @@ -364,14 +377,13 @@ void WebSchedulerService::loop() { static uint32_t last_uptime_min = 0; // get list of scheduler events and exit if it's empty - EMSESP::webSchedulerService.read([&](WebScheduler & webScheduler) { scheduleItems = &webScheduler.scheduleItems; }); - if (scheduleItems->size() == 0) { + if (scheduleItems_->size() == 0) { return; } // check startup commands if (last_tm_min == -1) { - for (ScheduleItem & scheduleItem : *scheduleItems) { + for (ScheduleItem & scheduleItem : *scheduleItems_) { if (scheduleItem.active && scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_TIMER && scheduleItem.elapsed_min == 0) { scheduleItem.retry_cnt = command(scheduleItem.cmd.c_str(), scheduleItem.value.c_str()) ? 0xFF : 0; } @@ -382,7 +394,7 @@ void WebSchedulerService::loop() { // check timer every minute, sync to EMS-ESP clock uint32_t uptime_min = uuid::get_uptime_sec() / 60; if (last_uptime_min != uptime_min) { - for (ScheduleItem & scheduleItem : *scheduleItems) { + for (ScheduleItem & scheduleItem : *scheduleItems_) { // retry startup commands not yet executed if (scheduleItem.active && scheduleItem.flags == SCHEDULEFLAG_SCHEDULE_TIMER && scheduleItem.elapsed_min == 0 && scheduleItem.retry_cnt < MAX_STARTUP_RETRIES) { @@ -405,7 +417,7 @@ void WebSchedulerService::loop() { uint8_t real_dow = 1 << tm->tm_wday; // 1 is Sunday uint16_t real_min = tm->tm_hour * 60 + tm->tm_min; - for (const ScheduleItem & scheduleItem : *scheduleItems) { + for (const ScheduleItem & scheduleItem : *scheduleItems_) { if (scheduleItem.active && (real_dow & scheduleItem.flags) && real_min == scheduleItem.elapsed_min) { command(scheduleItem.cmd.c_str(), scheduleItem.value.c_str()); } diff --git a/src/web/WebSchedulerService.h b/src/web/WebSchedulerService.h index cb48c58b4..4b7e87897 100644 --- a/src/web/WebSchedulerService.h +++ b/src/web/WebSchedulerService.h @@ -75,7 +75,7 @@ class WebSchedulerService : public StatefulService { HttpEndpoint _httpEndpoint; FSPersistence _fsPersistence; - std::list * scheduleItems; // pointer to the list of schedule events + std::list * scheduleItems_; // pointer to the list of schedule events bool ha_registered_ = false; }; From 5669deeb8074280a4fc85486c596f826e56a8910 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 28 Jan 2024 08:40:38 +0100 Subject: [PATCH 25/46] fix jsonvariant in command --- src/command.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/command.cpp b/src/command.cpp index 2724ff75e..b80fd0ee4 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -173,8 +173,10 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec if (!output.containsKey("api_data")) { return CommandRet::INVALID; } - data = output["api_data"]; + String dat = output["api_data"]; output.clear(); + input["data"] = dat.c_str(); + data = input["data"]; } } } From 31bea94d9c6a43edddaaa90bba87effd932c87ab Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 28 Jan 2024 08:41:02 +0100 Subject: [PATCH 26/46] fetch mixer 0x2CC --- src/devices/mixer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devices/mixer.cpp b/src/devices/mixer.cpp index 5d25e0664..28e97b800 100644 --- a/src/devices/mixer.cpp +++ b/src/devices/mixer.cpp @@ -30,7 +30,7 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c if (flags == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { register_telegram_type(device_id - 0x20 + 0x02D7, "MMPLUSStatusMessage_HC", false, MAKE_PF_CB(process_MMPLUSStatusMessage_HC)); // register_telegram_type(device_id - 0x20 + 0x02E1, "MMPLUSSetMessage_HC", true, MAKE_PF_CB(process_MMPLUSSetMessage_HC)); - register_telegram_type((device_id - 0x20) * 2 + 0x02CC, "MMPLUSSetMessage_HC", false, MAKE_PF_CB(process_MMPLUSSetMessage_HC)); + register_telegram_type((device_id - 0x20) * 2 + 0x02CC, "MMPLUSSetMessage_HC", true, MAKE_PF_CB(process_MMPLUSSetMessage_HC)); hc_ = device_id - 0x20 + 1; uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1; register_device_value(tag, &flowTempHc_, DeviceValueType::USHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(flowTempHc), DeviceValueUOM::DEGREES); From 542246c1420f75f223903df2025ffa2844c59491 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 28 Jan 2024 09:03:22 +0100 Subject: [PATCH 27/46] hpPressure telegram --- src/devices/boiler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index b1011bb96..49bea1edd 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -86,6 +86,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const register_telegram_type(0x49D, "HPSettings3", true, MAKE_PF_CB(process_HpSettings3)); register_telegram_type(0x4AE, "HPEnergy", true, MAKE_PF_CB(process_HpEnergy)); register_telegram_type(0x4AF, "HPMeters", true, MAKE_PF_CB(process_HpMeters)); + register_telegram_type(0x2CC, "HPPressure", true, MAKE_PF_CB(process_HpPressure)); } if (model() == EMSdevice::EMS_DEVICE_FLAG_HIU) { From 24b8e004ecba4a670b005356fa8f4f46f463d971 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 28 Jan 2024 09:07:05 +0100 Subject: [PATCH 28/46] fix jsonvariant in command --- src/command.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/command.cpp b/src/command.cpp index 2724ff75e..b80fd0ee4 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -173,8 +173,10 @@ uint8_t Command::process(const char * path, const bool is_admin, const JsonObjec if (!output.containsKey("api_data")) { return CommandRet::INVALID; } - data = output["api_data"]; + String dat = output["api_data"]; output.clear(); + input["data"] = dat.c_str(); + data = input["data"]; } } } From fbd3ebbd4e8e5d8fc503a42c9f2e12f4b3e26e84 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 28 Jan 2024 09:07:28 +0100 Subject: [PATCH 29/46] fetch mixer 0x2CC --- src/devices/mixer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/devices/mixer.cpp b/src/devices/mixer.cpp index 7c3d3377a..1543e5338 100644 --- a/src/devices/mixer.cpp +++ b/src/devices/mixer.cpp @@ -43,9 +43,9 @@ Mixer::Mixer(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c // EMS+ if (flags == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { if (device_id >= 0x20 && device_id <= 0x27) { - register_telegram_type(device_id - 0x20 + 0x02D7, "MMPLUSStatusMessage_HC", false, MAKE_PF_CB(process_MMPLUSStatusMessage_HC)); - // register_telegram_type(device_id - 0x20 + 0x02E1, "MMPLUSSetMessage_HC", true, MAKE_PF_CB(process_MMPLUSSetMessage_HC)); - register_telegram_type(2 * (device_id - 0x20) + 0x02CC, "MMPLUSSetMessage_HC", false, MAKE_PF_CB(process_MMPLUSSetMessage_HC)); + register_telegram_type(device_id - 0x20 + 0x02D7, "MMPLUSStatusMessage", false, MAKE_PF_CB(process_MMPLUSStatusMessage_HC)); + // register_telegram_type(device_id - 0x20 + 0x02E1, "MMPLUSSetMessage", true, MAKE_PF_CB(process_MMPLUSSetMessage_HC)); + register_telegram_type(2 * (device_id - 0x20) + 0x02CC, "MMPLUSSetMessage", true, MAKE_PF_CB(process_MMPLUSSetMessage_HC)); type_ = Type::HC; hc_ = device_id - 0x20 + 1; uint8_t tag = DeviceValueTAG::TAG_HC1 + hc_ - 1; From 0760e6e021ed9419caada3e4c2551a50a293cc4c Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 28 Jan 2024 09:07:49 +0100 Subject: [PATCH 30/46] hpPressure telegram --- src/devices/boiler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index 74195e884..8a2e5333f 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -86,6 +86,7 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const register_telegram_type(0x49D, "HPSettings3", true, MAKE_PF_CB(process_HpSettings3)); register_telegram_type(0x4AE, "HPEnergy", true, MAKE_PF_CB(process_HpEnergy)); register_telegram_type(0x4AF, "HPMeters", true, MAKE_PF_CB(process_HpMeters)); + register_telegram_type(0x2CC, "HPPressure", true, MAKE_PF_CB(process_HpPressure)); } if (model() == EMSdevice::EMS_DEVICE_FLAG_HIU) { From 6155645436c641ee85de52e68451852facaac0c4 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 28 Jan 2024 11:31:17 +0100 Subject: [PATCH 31/46] process telegram selection of device --- src/emsesp.cpp | 109 ++++++++++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 41 deletions(-) diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 8c015180d..8b6d8e3f5 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -685,7 +685,7 @@ bool EMSESP::get_device_value_info(JsonObject root, const char * cmd, const int8 return EMSESP::webSchedulerService.get_value_info(root, cmd); } - // own entities + // custom entities if (devicetype == DeviceType::CUSTOM) { return EMSESP::webCustomEntityService.get_value_info(root, cmd); } @@ -721,20 +721,26 @@ std::string EMSESP::pretty_telegram(std::shared_ptr telegram) { std::string dest_name(""); std::string type_name(""); for (const auto & emsdevice : emsdevices) { - if (emsdevice) { - // get src & dest - if (emsdevice->is_device_id(src)) { - src_name = emsdevice->device_type_name(); - } else if (emsdevice->is_device_id(dest)) { - dest_name = emsdevice->device_type_name(); + // get src & dest + if (emsdevice->is_device_id(src)) { + src_name = emsdevice->device_type_name(); + } else if (emsdevice->is_device_id(dest)) { + dest_name = emsdevice->device_type_name(); + } + // get the type name + if (type_name.empty()) { + if ((telegram->operation == Telegram::Operation::RX_READ && emsdevice->is_device_id(dest)) + || (telegram->operation != Telegram::Operation::RX_READ && dest == 0 && emsdevice->is_device_id(src)) + || (telegram->operation != Telegram::Operation::RX_READ && src == EMSbus::ems_bus_id() && emsdevice->is_device_id(dest))) { + type_name = emsdevice->telegram_type_name(telegram); } - // get the type name - if (type_name.empty()) { - if ((telegram->operation == Telegram::Operation::RX_READ && emsdevice->is_device_id(dest)) - || (telegram->operation != Telegram::Operation::RX_READ && dest == 0 && emsdevice->is_device_id(src)) - || (telegram->operation != Telegram::Operation::RX_READ && src == EMSbus::ems_bus_id() && emsdevice->is_device_id(dest))) { - type_name = emsdevice->telegram_type_name(telegram); - } + } + } + if (type_name.empty()) { + // fallback, get the type name from src + for (const auto & emsdevice : emsdevices) { + if (telegram->operation != Telegram::Operation::RX_READ && emsdevice->is_device_id(src)) { + type_name = emsdevice->telegram_type_name(telegram); } } } @@ -919,49 +925,70 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { // calls the associated process function for that EMS device // returns false if the device_id doesn't recognize it // after the telegram has been processed, see if there have been values changed and we need to do a MQTT publish - bool found = false; - bool knowndevice = false; + bool telegram_found = false; + uint8_t device_found = 0; + // broadcast or send to us for (const auto & emsdevice : emsdevices) { - if (emsdevice->is_device_id(telegram->src) && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id()|| telegram->dest == 0x10)) { - knowndevice = true; - found = emsdevice->handle_telegram(telegram); - // if we correctly processed the telegram then follow up with sending it via MQTT (if enabled) - if (found && Mqtt::connected()) { - if ((mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update()) - || (telegram->type_id == publish_id_ && telegram->dest == EMSbus::ems_bus_id())) { - if (telegram->type_id == publish_id_) { - publish_id_ = 0; - } - emsdevice->has_update(false); // reset flag - if (!Mqtt::publish_single()) { - publish_device_values(emsdevice->device_type()); // publish to MQTT if we explicitly have too - } - } + if (emsdevice->is_device_id(telegram->src) && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id())) { + telegram_found = emsdevice->handle_telegram(telegram); + device_found = emsdevice->unique_id(); + break; + } + } + if (!telegram_found) { + // check for command to the device + for (const auto & emsdevice : emsdevices) { + if (emsdevice->is_device_id(telegram->dest) && telegram->src != EMSbus::ems_bus_id()) { + telegram_found = emsdevice->handle_telegram(telegram); + device_found = emsdevice->unique_id(); + break; } - if (wait_validate_ == telegram->type_id) { - wait_validate_ = 0; + } + } + if (!telegram_found) { + // check for sends to master thermostat + for (const auto & emsdevice : emsdevices) { + if (emsdevice->is_device_id(telegram->src) && telegram->dest == 0x10) { + telegram_found = emsdevice->handle_telegram(telegram); + device_found = emsdevice->unique_id(); + break; } - if (!found && telegram->message_length > 0) { + } + } + for (const auto & emsdevice : emsdevices) { + if (emsdevice->unique_id() == device_found) { + if (telegram->message_length > 0) { emsdevice->add_handlers_ignored(telegram->type_id); } + if (telegram->dest == 0 && telegram->offset == 0 && telegram->message_length > 0) { + emsdevice->add_handlers_broadcasted(telegram->type_id); + } + if (Mqtt::connected() && telegram_found + && ((mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update()) + || (telegram->type_id == publish_id_ && telegram->dest == EMSbus::ems_bus_id()))) { + if (telegram->type_id == publish_id_) { + publish_id_ = 0; + } + emsdevice->has_update(false); // reset flag + if (!Mqtt::publish_single()) { + publish_device_values(emsdevice->device_type()); // publish to MQTT if we explicitly have too + } + } break; - } else if (emsdevice->is_device_id(telegram->dest) && telegram->src != EMSbus::ems_bus_id()) { - emsdevice->handle_telegram(telegram); } } - - // handle unknown broadcasted telegrams - if (!found && telegram->dest == 0) { + // handle unknown broadcasted telegrams (or send to us) + if (!telegram_found && (telegram->dest == 0 || telegram->dest == EMSbus::ems_bus_id())) { LOG_DEBUG("No telegram type handler found for ID 0x%02X (src 0x%02X)", telegram->type_id, telegram->src); if (watch() == WATCH_UNKNOWN) { LOG_NOTICE("%s", pretty_telegram(telegram).c_str()); } - if (!wait_km_ && !knowndevice && (telegram->src != EMSbus::ems_bus_id()) && (telegram->message_length > 0)) { + if (!wait_km_ && !device_found && (telegram->src != EMSbus::ems_bus_id()) && (telegram->message_length > 0)) { send_read_request(EMSdevice::EMS_TYPE_VERSION, telegram->src); } } - return found; + return telegram_found; } // return true if we have this device already registered From ce6e89338f39d461a7a9b6be31bbf7a8ef6c8bca Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 28 Jan 2024 12:15:16 +0100 Subject: [PATCH 32/46] reset wait_validate --- src/emsesp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/emsesp.cpp b/src/emsesp.cpp index a1595a56d..a576a7f2f 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -965,6 +965,9 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { if (!telegram_found && telegram->message_length > 0) { emsdevice->add_handlers_ignored(telegram->type_id); } + if (wait_validate_ == telegram->type_id) { + wait_validate_ = 0; + } if (Mqtt::connected() && telegram_found && ((mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update()) || (telegram->type_id == publish_id_ && telegram->dest == EMSbus::ems_bus_id()))) { From 2bd66bf4b6af5e82bf787e196837640cf6bdafa8 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Sun, 28 Jan 2024 12:16:35 +0100 Subject: [PATCH 33/46] reset wait_validate, typo --- src/emsesp.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/emsesp.cpp b/src/emsesp.cpp index a47f4352a..90ee6c652 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -957,9 +957,12 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { } for (const auto & emsdevice : emsdevices) { if (emsdevice->unique_id() == device_found) { - if (telegram->message_length > 0) { + if (!telegram_found && telegram->message_length > 0) { emsdevice->add_handlers_ignored(telegram->type_id); } + if (wait_validate_ == telegram->type_id) { + wait_validate_ = 0; + } if (Mqtt::connected() && telegram_found && ((mqtt_.get_publish_onchange(emsdevice->device_type()) && emsdevice->has_update()) || (telegram->type_id == publish_id_ && telegram->dest == EMSbus::ems_bus_id()))) { From 8e9edcb673fb93300beb741aba711549d58e0f8e Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 28 Jan 2024 13:21:45 +0100 Subject: [PATCH 34/46] fixes #1583 --- interface/src/project/SettingsCustomEntitiesDialog.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/project/SettingsCustomEntitiesDialog.tsx b/interface/src/project/SettingsCustomEntitiesDialog.tsx index 58998185b..9c293dcd1 100644 --- a/interface/src/project/SettingsCustomEntitiesDialog.tsx +++ b/interface/src/project/SettingsCustomEntitiesDialog.tsx @@ -27,7 +27,7 @@ import { BlockFormControlLabel, ValidatedTextField } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; -import { updateValue } from 'utils'; +import { numberValue, updateValue } from 'utils'; import { validate } from 'validators'; type SettingsCustomEntitiesDialogProps = { @@ -214,7 +214,7 @@ const SettingsCustomEntitiesDialog = ({ Date: Sun, 28 Jan 2024 13:21:52 +0100 Subject: [PATCH 35/46] package update --- interface/package.json | 2 +- interface/yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/package.json b/interface/package.json index b3a3e0cbe..3546a18cb 100644 --- a/interface/package.json +++ b/interface/package.json @@ -31,7 +31,7 @@ "@table-library/react-table-library": "4.1.7", "@types/imagemin": "^8.0.5", "@types/lodash-es": "^4.17.12", - "@types/node": "^20.11.7", + "@types/node": "^20.11.9", "@types/react": "^18.2.48", "@types/react-dom": "^18.2.18", "@types/react-router-dom": "^5.3.3", diff --git a/interface/yarn.lock b/interface/yarn.lock index c75be5f21..c7f2946b1 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -1590,12 +1590,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^20.11.7": - version: 20.11.7 - resolution: "@types/node@npm:20.11.7" +"@types/node@npm:^20.11.9": + version: 20.11.9 + resolution: "@types/node@npm:20.11.9" dependencies: undici-types: "npm:~5.26.4" - checksum: ff0428c093987f1f6e3400b91450077cf006d7f0e4ff316e20636218562c53761565ceb06bd7a161badf46e6884d78b554c7b1c3a7717cf5cb8c97f461ecd754 + checksum: 5683ec162f7975119b9c9b026f00bfc8e4fcd02d87ba106787685765fe042b8c16b71241baec043b6ac19caa343fe4e0edcb252c74943c36b98fadd72c8924fe languageName: node linkType: hard @@ -1858,7 +1858,7 @@ __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.7" + "@types/node": "npm:^20.11.9" "@types/react": "npm:^18.2.48" "@types/react-dom": "npm:^18.2.18" "@types/react-router-dom": "npm:^5.3.3" From eec0051997109194ec5290df83c8f0b50ea34ce9 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 28 Jan 2024 14:09:42 +0100 Subject: [PATCH 36/46] hide IP addresses --- src/system.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/system.cpp b/src/system.cpp index 14caf9e5f..c72a3cbfc 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -1230,23 +1230,23 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output node["network"] = "Ethernet"; node["hostname"] = ETH.getHostname(); // node["MAC"] = ETH.macAddress(); - node["IPv4 address"] = uuid::printable_to_string(ETH.localIP()) + "/" + uuid::printable_to_string(ETH.subnetMask()); - node["IPv4 gateway"] = uuid::printable_to_string(ETH.gatewayIP()); - node["IPv4 nameserver"] = uuid::printable_to_string(ETH.dnsIP()); - if (ETH.localIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000") { - node["IPv6 address"] = uuid::printable_to_string(ETH.localIPv6()); - } + // node["IPv4 address"] = uuid::printable_to_string(ETH.localIP()) + "/" + uuid::printable_to_string(ETH.subnetMask()); + // node["IPv4 gateway"] = uuid::printable_to_string(ETH.gatewayIP()); + // node["IPv4 nameserver"] = uuid::printable_to_string(ETH.dnsIP()); + // if (ETH.localIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000") { + // node["IPv6 address"] = uuid::printable_to_string(ETH.localIPv6()); + // } } else if (WiFi.status() == WL_CONNECTED) { node["network"] = "WiFi"; node["hostname"] = WiFi.getHostname(); node["RSSI"] = WiFi.RSSI(); // node["MAC"] = WiFi.macAddress(); - node["IPv4 address"] = uuid::printable_to_string(WiFi.localIP()) + "/" + uuid::printable_to_string(WiFi.subnetMask()); - node["IPv4 gateway"] = uuid::printable_to_string(WiFi.gatewayIP()); - node["IPv4 nameserver"] = uuid::printable_to_string(WiFi.dnsIP()); - if (WiFi.localIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000") { - node["IPv6 address"] = uuid::printable_to_string(WiFi.localIPv6()); - } + // node["IPv4 address"] = uuid::printable_to_string(WiFi.localIP()) + "/" + uuid::printable_to_string(WiFi.subnetMask()); + // node["IPv4 gateway"] = uuid::printable_to_string(WiFi.gatewayIP()); + // node["IPv4 nameserver"] = uuid::printable_to_string(WiFi.dnsIP()); + // if (WiFi.localIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000") { + // node["IPv6 address"] = uuid::printable_to_string(WiFi.localIPv6()); + // } } #endif EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & settings) { From 040954bb7084992c4fa8ea18331a0bd48e3e5357 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 28 Jan 2024 16:36:18 +0100 Subject: [PATCH 37/46] tidy up commands for temperature sensor --- src/command.cpp | 88 ++++++++++++++------------------ src/emsesp.cpp | 19 ++++--- src/system.cpp | 3 +- src/temperaturesensor.cpp | 90 +++++++++++++-------------------- src/temperaturesensor.h | 6 +-- src/test/test.cpp | 16 ++++++ src/test/test.h | 4 +- src/version.h | 2 +- src/web/WebAPIService.cpp | 9 ++-- src/web/WebSchedulerService.cpp | 1 + 10 files changed, 112 insertions(+), 126 deletions(-) diff --git a/src/command.cpp b/src/command.cpp index f64deefd4..93e472484 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -364,10 +364,10 @@ uint8_t Command::call(const uint8_t device_type, const char * cmd, const char * // report back. If not OK show output from error, other return the HTTP code if (return_code != CommandRet::OK) { - if (value == nullptr) { + if ((value == nullptr) || (strlen(value) == 0)) { LOG_ERROR("Command '%s' failed with code: %d", cmd, return_code); } else { - LOG_ERROR("Command '%s:%s' failed with code: %d", cmd, value, return_code); + LOG_ERROR("Command '%s/%s' failed with code: %d", cmd, value, return_code); } return message(return_code, "callback function failed", output); } @@ -442,7 +442,7 @@ bool Command::list(const uint8_t device_type, JsonObject output) { return false; } - // create a list of commands, sort them + // create a list of commands we have registered, and sort them std::list sorted_cmds; for (const auto & cf : cmdfunctions_) { if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN)) { @@ -451,6 +451,12 @@ bool Command::list(const uint8_t device_type, JsonObject output) { } sorted_cmds.sort(); + // force add info and commands for those non-EMS devices + if (device_type == EMSdevice::DeviceType::TEMPERATURESENSOR) { + output[F_(info)] = Helpers::translated_word(FL_(info_cmd)); + output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd)); + } + for (const auto & cl : sorted_cmds) { for (const auto & cf : cmdfunctions_) { if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN) && cf.description_ && (cl == std::string(cf.cmd_))) { @@ -475,14 +481,24 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo return; } - // create list of command, and sort + // create list of commands we have registered std::list sorted_cmds; for (const auto & cf : cmdfunctions_) { if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN)) { sorted_cmds.push_back((cf.cmd_)); } } - sorted_cmds.sort(); + + // non EMS devices always have an info and commands command + bool show_info = (device_type == EMSdevice::DeviceType::TEMPERATURESENSOR || device_type == EMSdevice::DeviceType::ANALOGSENSOR + || device_type == EMSdevice::DeviceType::SCHEDULER || device_type == EMSdevice::DeviceType::CUSTOM); + + if (!verbose && show_info) { + sorted_cmds.push_back(F_(info)); + sorted_cmds.push_back(F_(commands)); + } + + sorted_cmds.sort(); // sort them // if not in verbose mode, just print them on a single line and exit if (!verbose) { @@ -495,7 +511,16 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo } // verbose mode - shell.println(); + shell.printfln("\n%s%s %s:%s", COLOR_BOLD_ON, COLOR_YELLOW, EMSdevice::device_type_2_device_name(device_type), COLOR_RESET); + + // we hard code 'info' and 'commmands' commands so print them first + if (show_info) { + shell.printf(" info:\t\t\t\t%slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); + shell.println(COLOR_RESET); + shell.printf(" commands:\t\t\t%slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); + shell.println(COLOR_RESET); + } + for (const auto & cl : sorted_cmds) { // find and print the description for (const auto & cf : cmdfunctions_) { @@ -530,8 +555,6 @@ void Command::show(uuid::console::Shell & shell, uint8_t device_type, bool verbo } shell.println(); } - - shell.println(); } // see if a device_type is active and has associated commands @@ -599,69 +622,32 @@ void Command::show_devices(uuid::console::Shell & shell) { shell.println(); } -// output list of all commands to console +// 'show commmands' : output list of all commands to console // calls show with verbose mode set void Command::show_all(uuid::console::Shell & shell) { shell.printfln("Showing all available commands (%s*%s=authentication not required):", COLOR_BRIGHT_GREEN, COLOR_RESET); - // show system first - shell.print(COLOR_BOLD_ON); - shell.print(COLOR_YELLOW); - shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SYSTEM)); - shell.print(COLOR_RESET); + // show system ones first show(shell, EMSdevice::DeviceType::SYSTEM, true); - - // show Custom Entities - shell.print(COLOR_BOLD_ON); - shell.print(COLOR_YELLOW); - shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::CUSTOM)); - shell.println(COLOR_RESET); - // TODO to remove later? - shell.printf(" info:\t\t\t\t%slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); - shell.println(COLOR_RESET); - shell.printf(" commands:\t\t\t%slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); - shell.print(COLOR_RESET); show(shell, EMSdevice::DeviceType::CUSTOM, true); - - // show scheduler - shell.print(COLOR_BOLD_ON); - shell.print(COLOR_YELLOW); - shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::SCHEDULER)); - shell.println(COLOR_RESET); - // TODO to remove later? - shell.printf(" info:\t\t\t\t%slists all values %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); - shell.println(COLOR_RESET); - shell.printf(" commands:\t\t\t%slists all commands %s*", COLOR_BRIGHT_CYAN, COLOR_BRIGHT_GREEN); - shell.print(COLOR_RESET); show(shell, EMSdevice::DeviceType::SCHEDULER, true); - // show sensors + // then sensors if (EMSESP::sensor_enabled()) { - shell.print(COLOR_BOLD_ON); - shell.print(COLOR_YELLOW); - shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::TEMPERATURESENSOR)); - shell.print(COLOR_RESET); show(shell, EMSdevice::DeviceType::TEMPERATURESENSOR, true); } - if (EMSESP::analog_enabled()) { - shell.print(COLOR_BOLD_ON); - shell.print(COLOR_YELLOW); - shell.printf(" %s: ", EMSdevice::device_type_2_device_name(EMSdevice::DeviceType::ANALOGSENSOR)); - shell.print(COLOR_RESET); show(shell, EMSdevice::DeviceType::ANALOGSENSOR, true); } - // do this in the order of factory classes to keep a consistent order when displaying + // now EMS devices, do this in the order of factory classes to keep a consistent order when displaying for (const auto & device_class : EMSFactory::device_handlers()) { if (Command::device_has_commands(device_class.first)) { - shell.print(COLOR_BOLD_ON); - shell.print(COLOR_YELLOW); - shell.printf(" %s: ", EMSdevice::device_type_2_device_name(device_class.first)); - shell.print(COLOR_RESET); show(shell, device_class.first, true); } } + + shell.println(); } // Extract only the path component from the passed URI and normalized it diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 75ce6a14f..5b1faeb25 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -659,9 +659,10 @@ void EMSESP::publish_response(std::shared_ptr telegram) { buffer = nullptr; } -// builds json with the detail of each value, -// for a specific EMS device type or the sensors, scheduler and custom entities +// builds json with the detail of each value, for an EMS device +// for other types like sensors, scheduler, custom entities it will process single commands like 'info', 'values', 'commands'... bool EMSESP::get_device_value_info(JsonObject root, const char * cmd, const int8_t id, const uint8_t devicetype) { + // check first for EMS devices for (const auto & emsdevice : emsdevices) { if (emsdevice->device_type() == devicetype) { if (emsdevice->get_value_info(root, cmd, id)) { @@ -670,24 +671,24 @@ bool EMSESP::get_device_value_info(JsonObject root, const char * cmd, const int8 } } - // specific for the temperaturesensor + // temperaturesensor if (devicetype == DeviceType::TEMPERATURESENSOR) { - return EMSESP::temperaturesensor_.get_value_info(root, cmd, id); + return temperaturesensor_.get_value_info(root, cmd, id); } // analog sensor if (devicetype == DeviceType::ANALOGSENSOR) { - return EMSESP::analogsensor_.get_value_info(root, cmd, id); + return analogsensor_.get_value_info(root, cmd, id); } // scheduler if (devicetype == DeviceType::SCHEDULER) { - return EMSESP::webSchedulerService.get_value_info(root, cmd); + return webSchedulerService.get_value_info(root, cmd); } // custom entities if (devicetype == DeviceType::CUSTOM) { - return EMSESP::webCustomEntityService.get_value_info(root, cmd); + return webCustomEntityService.get_value_info(root, cmd); } char error[100]; @@ -1165,7 +1166,9 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const // Print to LOG showing we've added a new device LOG_INFO("Recognized new %s with deviceID 0x%02X", EMSdevice::device_type_2_device_name(device_type), device_id); - // add command commands for all devices, except for connect, controller and gateway + // add commands 'info', 'commands', 'values', 'entities' for all EMS devices + // and register the MQTT subscribe topic for this device + // except for connect, controller and gateway if ((device_type == DeviceType::CONNECT) || (device_type == DeviceType::CONTROLLER) || (device_type == DeviceType::GATEWAY)) { return true; } diff --git a/src/system.cpp b/src/system.cpp index c72a3cbfc..fc75fde48 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -125,9 +125,10 @@ bool System::command_allvalues(const char * value, const int8_t id, JsonObject o // Sensors device_output = output["Analog Sensors"].to(); + // TODO fix this also for analogsensor EMSESP::analogsensor_.command_info(nullptr, 0, device_output); device_output = output["Temperature Sensors"].to(); - EMSESP::temperaturesensor_.command_info(nullptr, 0, device_output); + EMSESP::temperaturesensor_.get_value_info(device_output, nullptr); return true; } diff --git a/src/temperaturesensor.cpp b/src/temperaturesensor.cpp index eeaa9bc80..ae77250b5 100644 --- a/src/temperaturesensor.cpp +++ b/src/temperaturesensor.cpp @@ -45,24 +45,6 @@ void TemperatureSensor::start() { LOG_INFO("Starting Temperature sensor service"); #endif - // Add API calls - Command::add( - EMSdevice::DeviceType::TEMPERATURESENSOR, - F_(info), - [&](const char * value, const int8_t id, JsonObject output) { return command_info(value, id, output); }, - FL_(info_cmd)); - Command::add( - EMSdevice::DeviceType::TEMPERATURESENSOR, - F_(values), - [&](const char * value, const int8_t id, JsonObject output) { return command_info(value, 0, output); }, - nullptr, - CommandFlag::HIDDEN); // this command is hidden - Command::add( - EMSdevice::DeviceType::TEMPERATURESENSOR, - F_(commands), - [&](const char * value, const int8_t id, JsonObject output) { return command_commands(value, id, output); }, - FL_(commands_cmd)); - char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; snprintf(topic, sizeof(topic), "%s/#", F_(temperaturesensor)); Mqtt::subscribe(EMSdevice::DeviceType::TEMPERATURESENSOR, topic, nullptr); // use empty function callback @@ -361,57 +343,56 @@ bool TemperatureSensor::updated_values() { return false; } -// list commands -bool TemperatureSensor::command_commands(const char * value, const int8_t id, JsonObject output) { - return Command::list(EMSdevice::DeviceType::TEMPERATURESENSOR, output); -} - -// creates JSON doc from values -// returns true if there are no sensors -bool TemperatureSensor::command_info(const char * value, const int8_t id, JsonObject output) { +// called from emsesp.cpp for commands +bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) { if (sensors_.empty()) { - return true; + return true; // no sensors, return true } - for (const auto & sensor : sensors_) { - char val[10]; - if (id == -1) { // show number and id, info command + bool show_all = true; + if (Helpers::hasValue(cmd)) { + show_all = (strncmp(cmd, F_(info), 4) == 0); + } + + // see if we're showing all sensors + if (show_all) { + for (const auto & sensor : sensors_) { JsonObject dataSensor = output[sensor.name()].to(); dataSensor["id"] = sensor.id(); - dataSensor["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES); - dataSensor["type"] = F_(number); + dataSensor["offset"] = sensor.offset(); if (Helpers::hasValue(sensor.temperature_c)) { - dataSensor["temp"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0)); + char val[10]; + dataSensor["value"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0)); } - } else if (id == 0 && Helpers::hasValue(sensor.temperature_c)) { // values command - output[sensor.name()] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0)); - } else if (Helpers::hasValue(sensor.temperature_c)) { - output[sensor.id()] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0)); + dataSensor["type"] = F_(number); + dataSensor["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES); + dataSensor["writeable"] = false; } + return true; } - return (output.size() > 0); -} - -// called from emsesp.cpp, similar to the emsdevice->get_value_info -bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) { - if (sensors_.empty()) { - return true; + // check of it a 'commmands' command + if (Helpers::toLower(cmd) == F_(commands)) { + return Command::list(EMSdevice::DeviceType::TEMPERATURESENSOR, output); } - // make a copy of the string command for parsing - char command_s[30]; - strlcpy(command_s, cmd, sizeof(command_s)); - char * attribute_s = nullptr; - // check specific attribute to fetch instead of the complete record - char * breakp = strchr(command_s, '/'); + // this is for a specific sensor + // make a copy of the string command for parsing, and lowercase it + char sensor_name[30] = {'\0'}; + char * attribute_s = nullptr; + strlcpy(sensor_name, cmd, sizeof(sensor_name)); + auto sensor_lowercase = Helpers::toLower(sensor_name); + + // check for a specific attribute to fetch instead of the complete record + char * breakp = strchr(sensor_name, '/'); if (breakp) { *breakp = '\0'; attribute_s = breakp + 1; } for (const auto & sensor : sensors_) { - if (Helpers::toLower(command_s) == Helpers::toLower(sensor.name().c_str()) || Helpers::toLower(command_s) == Helpers::toLower(sensor.id().c_str())) { + // match custom name or sensor ID + if (sensor_lowercase == Helpers::toLower(sensor.name().c_str()) || sensor_lowercase == Helpers::toLower(sensor.id().c_str())) { output["id"] = sensor.id(); output["name"] = sensor.name(); if (Helpers::hasValue(sensor.temperature_c)) { @@ -432,16 +413,17 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons return true; } else { char error[100]; - snprintf(error, sizeof(error), "cannot find attribute %s in entity %s", attribute_s, command_s); + snprintf(error, sizeof(error), "cannot find attribute %s in entity %s", attribute_s, sensor_name); output.clear(); output["message"] = error; return false; } } - return true; + return true; // found a match, exit } } - return false; + + return false; // not found } // publish a single sensor to MQTT diff --git a/src/temperaturesensor.h b/src/temperaturesensor.h index 98d10066f..0c354d278 100644 --- a/src/temperaturesensor.h +++ b/src/temperaturesensor.h @@ -83,7 +83,7 @@ class TemperatureSensor { void publish_values(const bool force); void reload(); bool updated_values(); - bool get_value_info(JsonObject output, const char * cmd, const int8_t id); + bool get_value_info(JsonObject output, const char * cmd, const int8_t id = -1); // return back reference to the sensor list, used by other classes std::vector sensors() const { @@ -112,8 +112,6 @@ class TemperatureSensor { bool update(const std::string & id, const std::string & name, int16_t offset); - bool command_info(const char * value, const int8_t id, JsonObject output); - #if defined(EMSESP_TEST) void test(); #endif @@ -155,8 +153,6 @@ class TemperatureSensor { uint64_t get_id(const uint8_t addr[]); void remove_ha_topic(const std::string & id); - bool command_commands(const char * value, const int8_t id, JsonObject output); - std::vector sensors_; // our list of active sensors #ifndef EMSESP_STANDALONE diff --git a/src/test/test.cpp b/src/test/test.cpp index 176e002f5..048424608 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -757,8 +757,24 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const if (command == "temperature") { shell.printfln("Testing adding Temperature sensor"); + shell.invoke_command("show commands"); + emsesp::EMSESP::temperaturesensor_.test(); + + shell.invoke_command("call temperaturesensor"); shell.invoke_command("show values"); + shell.invoke_command("call system allvalues"); + + shell.invoke_command("call temperaturesensor info"); + AsyncWebServerRequest request; + request.method(HTTP_GET); + request.url("/api/temperaturesensor/commands"); + EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/temperaturesensor/info"); + EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/temperaturesensor/01-0203-0405-0607"); + EMSESP::webAPIService.webAPIService_get(&request); + ok = true; } diff --git a/src/test/test.h b/src/test/test.h index fbfad38b9..f36f0adb4 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -27,7 +27,7 @@ namespace emsesp { -#define EMSESP_DEBUG_DEFAULT "general" +// #define EMSESP_DEBUG_DEFAULT "general" // #define EMSESP_DEBUG_DEFAULT "thermostat" // #define EMSESP_DEBUG_DEFAULT "solar" @@ -47,7 +47,7 @@ namespace emsesp { // #define EMSESP_DEBUG_DEFAULT "dv" // #define EMSESP_DEBUG_DEFAULT "lastcode" // #define EMSESP_DEBUG_DEFAULT "2thermostats" -// #define EMSESP_DEBUG_DEFAULT "temperature" +#define EMSESP_DEBUG_DEFAULT "temperature" // #define EMSESP_DEBUG_DEFAULT "analog" // #define EMSESP_DEBUG_DEFAULT "api_values" // #define EMSESP_DEBUG_DEFAULT "mqtt_post" diff --git a/src/version.h b/src/version.h index 9988523a9..b6f8dbe73 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.6.5-dev.10" +#define EMSESP_APP_VERSION "3.6.5-dev.11" diff --git a/src/web/WebAPIService.cpp b/src/web/WebAPIService.cpp index e2e311c01..f997cd5f8 100644 --- a/src/web/WebAPIService.cpp +++ b/src/web/WebAPIService.cpp @@ -152,12 +152,13 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject input) { #if defined(EMSESP_STANDALONE) Serial.print(COLOR_YELLOW); - Serial.print("web response code: "); - Serial.println(ret_codes[return_code]); + Serial.print("data: "); if (output.size()) { - serializeJsonPretty(output, Serial); + serializeJson(output, Serial); } - Serial.println(); + Serial.print(" (response code "); + Serial.print(ret_codes[return_code]); + Serial.println(")"); Serial.print(COLOR_RESET); #endif } diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index d45c31b07..2c56164a0 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -134,6 +134,7 @@ bool WebSchedulerService::command_setvalue(const char * value, const std::string // process json output for info/commands and value_info bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) { + // check of it a 'commmands' command if (Helpers::toLower(cmd) == F_(commands)) { output[F_(info)] = Helpers::translated_word(FL_(info_cmd)); output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd)); From 30e11ad593889fdfb41695e2c382e786b9efbace Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 28 Jan 2024 18:27:51 +0100 Subject: [PATCH 38/46] added comment --- interface/src/project/api.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/project/api.ts b/interface/src/project/api.ts index 96b317203..1475c4779 100644 --- a/interface/src/project/api.ts +++ b/interface/src/project/api.ts @@ -20,7 +20,7 @@ export const readCoreData = () => alovaInstance.Get(`/rest/coreData`); export const readDeviceData = (id: number) => alovaInstance.Get('/rest/deviceData', { // alovaInstance.Get(`/rest/deviceData/${id}`, { - params: { id }, // TODO replace later + params: { id }, // TODO replace later with id responseType: 'arraybuffer' // uses msgpack }); export const writeDeviceValue = (data: any) => alovaInstance.Post('/rest/writeDeviceValue', data); @@ -56,7 +56,7 @@ export const getSchedule = () => alovaInstance.Get('/rest/getSchedule'); export const readDeviceEntities = (id: number) => // alovaInstance.Get(`/rest/deviceEntities/${id}`, { alovaInstance.Get(`/rest/deviceEntities`, { - params: { id }, // TODO replace later + params: { id }, // TODO replace later with id responseType: 'arraybuffer', transformData(data: any) { return data.map((de: DeviceEntity) => ({ ...de, o_m: de.m, o_cn: de.cn, o_mi: de.mi, o_ma: de.ma })); From d11508282f36379804e3d740b574d7f0da1654f0 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 28 Jan 2024 18:28:12 +0100 Subject: [PATCH 39/46] tidied up commands info, values etc --- src/test/test.cpp | 25 ++++++++++++++++++++++++- src/test/test.h | 4 ++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/test/test.cpp b/src/test/test.cpp index 048424608..999f0c7ce 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -744,7 +744,11 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const shell.printfln("Testing device value rendering"); Mqtt::ha_enabled(true); + // Mqtt::ha_enabled(false); + Mqtt::nested_format(1); + // Mqtt::nested_format(0); + // Mqtt::send_response(false); test("boiler"); @@ -759,13 +763,17 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const shell.printfln("Testing adding Temperature sensor"); shell.invoke_command("show commands"); + // load some EMS data + // test("general"); + emsesp::EMSESP::temperaturesensor_.test(); shell.invoke_command("call temperaturesensor"); shell.invoke_command("show values"); shell.invoke_command("call system allvalues"); - shell.invoke_command("call temperaturesensor info"); + shell.invoke_command("call temperaturesensor values"); + AsyncWebServerRequest request; request.method(HTTP_GET); request.url("/api/temperaturesensor/commands"); @@ -799,18 +807,33 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const shell.printfln("Testing adding Analog sensor"); Mqtt::ha_enabled(true); // Mqtt::ha_enabled(false); + Mqtt::nested_format(1); // Mqtt::nested_format(0); + // Mqtt::send_response(false); + // load some EMS data test("general"); EMSESP::webCustomizationService.test(); // load the analog sensors + shell.invoke_command("call analogsensor"); shell.invoke_command("show values"); + shell.invoke_command("call system allvalues"); shell.invoke_command("call analogsensor info"); shell.invoke_command("call analogsensor values"); + AsyncWebServerRequest request; + request.method(HTTP_GET); + request.url("/api/analogsensor/commands"); + EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/analogsensor/info"); + EMSESP::webAPIService.webAPIService_get(&request); + request.url("/api/analogsensor/test_analog1"); + request.url("/api/analogsensor/36"); + EMSESP::webAPIService.webAPIService_get(&request); + // test renaming it // bool update(uint8_t id, const std::string & name, int16_t offset, float factor, uint8_t uom, uint8_t type); // EMSESP::analogsensor_.update(36, "test_analog1_new", 2, 0.7, 17, 1); diff --git a/src/test/test.h b/src/test/test.h index f36f0adb4..5fbbe38c9 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -47,8 +47,8 @@ namespace emsesp { // #define EMSESP_DEBUG_DEFAULT "dv" // #define EMSESP_DEBUG_DEFAULT "lastcode" // #define EMSESP_DEBUG_DEFAULT "2thermostats" -#define EMSESP_DEBUG_DEFAULT "temperature" -// #define EMSESP_DEBUG_DEFAULT "analog" +// #define EMSESP_DEBUG_DEFAULT "temperature" +#define EMSESP_DEBUG_DEFAULT "analog" // #define EMSESP_DEBUG_DEFAULT "api_values" // #define EMSESP_DEBUG_DEFAULT "mqtt_post" // #define EMSESP_DEBUG_DEFAULT "api_wwmode" From 5735ffd22204dd9bba2aa3d231a3d25acb089652 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 28 Jan 2024 18:28:26 +0100 Subject: [PATCH 40/46] tidied up commands --- src/analogsensor.cpp | 169 +++++++++++++++++--------------------- src/analogsensor.h | 6 +- src/emsdevice.cpp | 8 +- src/system.cpp | 7 +- src/temperaturesensor.cpp | 50 ++++++----- src/temperaturesensor.h | 1 + 6 files changed, 114 insertions(+), 127 deletions(-) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 993b964a0..46794b512 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -33,29 +33,13 @@ void AnalogSensor::start() { LOG_INFO("Starting Analog sensor service"); - // Add API call for /info - Command::add( - EMSdevice::DeviceType::ANALOGSENSOR, - F_(info), - [&](const char * value, const int8_t id, JsonObject output) { return command_info(value, id, output); }, - FL_(info_cmd)); - Command::add( - EMSdevice::DeviceType::ANALOGSENSOR, - F_(values), - [&](const char * value, const int8_t id, JsonObject output) { return command_info(value, 0, output); }, - nullptr, - CommandFlag::HIDDEN); // this command is hidden + // Add API calls Command::add( EMSdevice::DeviceType::ANALOGSENSOR, F_(setvalue), [&](const char * value, const int8_t id) { return command_setvalue(value, id); }, FL_(setiovalue_cmd), CommandFlag::ADMIN_ONLY); - Command::add( - EMSdevice::DeviceType::ANALOGSENSOR, - F_(commands), - [&](const char * value, const int8_t id, JsonObject output) { return command_commands(value, id, output); }, - FL_(commands_cmd)); char topic[Mqtt::MQTT_TOPIC_MAX_SIZE]; snprintf(topic, sizeof(topic), "%s/#", F_(analogsensor)); @@ -636,48 +620,64 @@ void AnalogSensor::publish_values(const bool force) { Mqtt::queue_publish(topic, doc.as()); } -// called from emsesp.cpp, similar to the emsdevice->get_value_info -// searches by name -// TODO see if this can replace the command_info -bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) const { +// called from emsesp.cpp for commands +// searches sensor by name +bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) { if (sensors_.empty()) { + return true; // no sensors, return true + } + + uint8_t show_all = 0; + if (Helpers::hasValue(cmd)) { + show_all = (strncmp(cmd, F_(info), 4) == 0) ? 1 : (strncmp(cmd, F_(values), 6) == 0) ? 2 : 0; + } + + // see if we're showing all sensors + if (show_all) { + for (const auto & sensor : sensors_) { + if (show_all == 1) { + // info + JsonObject dataSensor = output[sensor.name()].to(); + addSensorJson(dataSensor, sensor); + } else { + // values, shortname version. Also used in 'system allvalues' + output[sensor.name()] = sensor.value(); + } + } return true; } - // make a copy of the string command for parsing - char command_s[30]; - strlcpy(command_s, cmd, sizeof(command_s)); - char * attribute_s = nullptr; + // check of it a 'commmands' command + if (Helpers::toLower(cmd) == F_(commands)) { + return Command::list(EMSdevice::DeviceType::TEMPERATURESENSOR, output); + } + + // this is for a specific sensor + // make a copy of the string command for parsing, and lowercase it + char sensor_name[30] = {'\0'}; + char * attribute_s = nullptr; + strlcpy(sensor_name, cmd, sizeof(sensor_name)); + auto sensor_lowercase = Helpers::toLower(sensor_name); // check specific attribute to fetch instead of the complete record - char * breakp = strchr(command_s, '/'); + char * breakp = strchr(sensor_name, '/'); if (breakp) { *breakp = '\0'; attribute_s = breakp + 1; } for (const auto & sensor : sensors_) { - if (Helpers::toLower(command_s) == Helpers::toLower(sensor.name().c_str()) || Helpers::atoint(command_s) == sensor.gpio()) { - output["gpio"] = sensor.gpio(); - output["name"] = sensor.name(); - output["type"] = F_(number); - output["analog"] = FL_(list_sensortype)[sensor.type()]; - output["uom"] = EMSdevice::uom_to_string(sensor.uom()); - output["offset"] = sensor.offset(); - output["factor"] = sensor.factor(); - output["value"] = sensor.value(); - output["writeable"] = sensor.type() == AnalogType::COUNTER || (sensor.type() >= AnalogType::DIGITAL_OUT && sensor.type() <= AnalogType::PWM_2); - // min/max for writeable analogs - if (sensor.type() == AnalogType::COUNTER) { - output["min"] = 0; - output["max"] = 4000000; - } else if (sensor.type() == AnalogType::DIGITAL_OUT) { - output["min"] = 0; - output["max"] = sensor.gpio() == 25 || sensor.gpio() == 26 ? 255 : 1; - } else if (sensor.type() >= AnalogType::PWM_0 && sensor.type() <= AnalogType::PWM_2) { - output["min"] = 0; - output["max"] = 100; - } + if (sensor_lowercase == Helpers::toLower(sensor.name().c_str()) || Helpers::atoint(sensor_name) == sensor.gpio()) { + // add the details + addSensorJson(output, sensor); + + /* + // if someone wants gpio numbers + char gpio_str[9]; + snprintf(gpio_str, sizeof(gpio_str), "gpio_%02d", sensor.gpio()); + output[gpio_str] = sensor.value(); + */ + // if we're filtering on an attribute, go find it if (attribute_s) { if (output.containsKey(attribute_s)) { @@ -687,57 +687,45 @@ bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int return true; } else { char error[100]; - snprintf(error, sizeof(error), "cannot find attribute %s in entity %s", attribute_s, command_s); + snprintf(error, sizeof(error), "cannot find attribute %s in entity %s", attribute_s, sensor_name); output.clear(); output["message"] = error; return false; } } - return true; + return true; // found a match, exit } } - return false; + return false; // not found } -// creates JSON doc from values -// returns true if there are no sensors -// TODO see if this can be merged with get_value_info so we can remove the commands (info, commands, etc...) -bool AnalogSensor::command_info(const char * value, const int8_t id, JsonObject output) const { - if (sensors_.empty()) { - return true; +void AnalogSensor::addSensorJson(JsonObject output, const Sensor & sensor) { + output["gpio"] = sensor.gpio(); + output["type"] = F_(number); + output["analog"] = FL_(list_sensortype)[sensor.type()]; + output["value"] = sensor.value(); + output["writeable"] = sensor.type() == AnalogType::COUNTER || (sensor.type() >= AnalogType::DIGITAL_OUT && sensor.type() <= AnalogType::PWM_2); + if (sensor.type() == AnalogType::COUNTER) { + output["min"] = 0; + output["max"] = 4000000; + output["start_value"] = sensor.offset(); + output["factor"] = sensor.factor(); + output["uom"] = EMSdevice::uom_to_string(sensor.uom()); + } else if (sensor.type() == AnalogType::ADC) { + output["offset"] = sensor.offset(); + output["factor"] = sensor.factor(); + output["uom"] = EMSdevice::uom_to_string(sensor.uom()); + } else if (sensor.type() == AnalogType::TIMER || sensor.type() == AnalogType::RATE) { + output["factor"] = sensor.factor(); + } else if (sensor.type() >= AnalogType::PWM_0 && sensor.type() <= AnalogType::PWM_2) { + output["frequency"] = sensor.factor(); + output["min"] = 0; + output["max"] = 100; + output["uom"] = EMSdevice::uom_to_string(sensor.uom()); + } else if (sensor.type() == AnalogType::DIGITAL_OUT) { + output["min"] = 0; + output["max"] = sensor.gpio() == 25 || sensor.gpio() == 26 ? 255 : 1; } - - for (const auto & sensor : sensors_) { - if (id == -1) { // show number and id for info command - JsonObject dataSensor = output[sensor.name()].to(); - dataSensor["gpio"] = sensor.gpio(); - dataSensor["type"] = F_(number); - dataSensor["value"] = sensor.value(); - dataSensor["analog"] = FL_(list_sensortype)[sensor.type()]; - if (sensor.type() == AnalogType::ADC) { - dataSensor["uom"] = EMSdevice::uom_to_string(sensor.uom()); - dataSensor["offset"] = sensor.offset(); - dataSensor["factor"] = sensor.factor(); - } else if (sensor.type() == AnalogType::COUNTER) { - dataSensor["uom"] = EMSdevice::uom_to_string(sensor.uom()); - dataSensor["start_value"] = sensor.offset(); - dataSensor["factor"] = sensor.factor(); - } else if (sensor.type() == AnalogType::TIMER || sensor.type() == AnalogType::RATE) { - dataSensor["factor"] = sensor.factor(); - } else if (sensor.type() >= AnalogType::PWM_0 && sensor.type() <= AnalogType::PWM_2) { - dataSensor["uom"] = EMSdevice::uom_to_string(sensor.uom()); - dataSensor["frequency"] = sensor.factor(); - } - } else if (id == 0) { // output values command - output[sensor.name()] = sensor.value(); - } else { // if someone wants gpio numbers - char gpio_str[9]; - snprintf(gpio_str, sizeof(gpio_str), "gpio_%02d", sensor.gpio()); - output[gpio_str] = sensor.value(); - } - } - - return (output.size() > 0); } // this creates the sensor, initializing everything @@ -853,9 +841,4 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) { return false; } -// list commands -bool AnalogSensor::command_commands(const char * value, const int8_t id, JsonObject output) { - return Command::list(EMSdevice::DeviceType::ANALOGSENSOR, output); -} - } // namespace emsesp \ No newline at end of file diff --git a/src/analogsensor.h b/src/analogsensor.h index 09c470397..8681106a4 100644 --- a/src/analogsensor.h +++ b/src/analogsensor.h @@ -153,11 +153,9 @@ class AnalogSensor { } bool update(uint8_t gpio, const std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted = false); - bool get_value_info(JsonObject output, const char * cmd, const int8_t id) const; + bool get_value_info(JsonObject output, const char * cmd, const int8_t id = -1); void store_counters(); - bool command_info(const char * value, const int8_t id, JsonObject output) const; - private: static constexpr uint8_t MAX_SENSORS = 20; static constexpr uint32_t MEASURE_ANALOG_INTERVAL = 500; @@ -167,7 +165,7 @@ class AnalogSensor { void remove_ha_topic(const int8_t type, const uint8_t id) const; bool command_setvalue(const char * value, const int8_t gpio); void measure(); - bool command_commands(const char * value, const int8_t id, JsonObject output); + void addSensorJson(JsonObject output, const Sensor & sensor); std::vector sensors_; // our list of sensors diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index d548734d4..f33e643ab 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -932,7 +932,7 @@ void EMSdevice::generate_values_web(JsonObject output) { // add name, prefixing the tag if it exists. This is the id used in the WebUI table and must be unique obj["id"] = dv.has_tag() ? mask + tag_to_string(dv.tag) + " " + fullname : mask + fullname; // suffix tag - // TODO check TAG https://github.com/emsesp/EMS-ESP32/issues/1338 + // TAG https://github.com/emsesp/EMS-ESP32/issues/1338 // obj["id"] = dv.has_tag() ? mask + fullname + " " + tag_to_string(dv.tag) : mask + fullname; // suffix tag // add commands and options @@ -1046,7 +1046,7 @@ void EMSdevice::generate_values_web_customization(JsonArray output) { if (fullname) { obj["n"] = dv.has_tag() ? std::string(tag_to_string(dv.tag)) + " " + fullname : fullname; // prefix tag - // TODO check TAG https://github.com/emsesp/EMS-ESP32/issues/1338 + // TAG https://github.com/emsesp/EMS-ESP32/issues/1338 // obj["n"] = (dv.has_tag()) ? fullname + " " + tag_to_string(dv.tag) : fullname; // suffix tag } @@ -1394,7 +1394,7 @@ bool EMSdevice::get_value_info(JsonObject output, const char * cmd, const int8_t if (!fullname.empty()) { json["fullname"] = dv.has_tag() ? fullname + " " + tag_to_string(dv.tag) : fullname; // suffix tag - // TODO check TAG https://github.com/emsesp/EMS-ESP32/issues/1338 + // TAG https://github.com/emsesp/EMS-ESP32/issues/1338 json["fullname"] = dv.has_tag() ? std::string(tag_to_string(dv.tag)) + " " + fullname.c_str() : fullname; // prefix tag } @@ -1600,7 +1600,7 @@ bool EMSdevice::generate_values(JsonObject output, const uint8_t tag_filter, con // add tag if (have_tag) { snprintf(name, sizeof(name), "%s %s (%s)", tag_to_string(dv.tag), fullname.c_str(), dv.short_name); // prefix tag - // TODO check TAG https://github.com/emsesp/EMS-ESP32/issues/1338 + // TAG https://github.com/emsesp/EMS-ESP32/issues/1338 // snprintf(name, sizeof(name), "%s %s (%s)", fullname.c_str(), tag_to_string(dv.tag), dv.short_name); // sufix tag } else { snprintf(name, sizeof(name), "%s (%s)", fullname.c_str(), dv.short_name); diff --git a/src/system.cpp b/src/system.cpp index fc75fde48..a268aec16 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -119,16 +119,15 @@ bool System::command_allvalues(const char * value, const int8_t id, JsonObject o emsdevice->generate_values(device_output, DeviceValueTAG::TAG_NONE, true, EMSdevice::OUTPUT_TARGET::API_VERBOSE); // use nested for id -1 and 0 } - // Custom entities + // Custom Entities device_output = output["Custom Entities"].to(); EMSESP::webCustomEntityService.get_value_info(device_output, ""); // Sensors device_output = output["Analog Sensors"].to(); - // TODO fix this also for analogsensor - EMSESP::analogsensor_.command_info(nullptr, 0, device_output); + EMSESP::analogsensor_.get_value_info(device_output, "values"); device_output = output["Temperature Sensors"].to(); - EMSESP::temperaturesensor_.get_value_info(device_output, nullptr); + EMSESP::temperaturesensor_.get_value_info(device_output, "values"); return true; } diff --git a/src/temperaturesensor.cpp b/src/temperaturesensor.cpp index ae77250b5..096bb6538 100644 --- a/src/temperaturesensor.cpp +++ b/src/temperaturesensor.cpp @@ -349,24 +349,25 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons return true; // no sensors, return true } - bool show_all = true; + uint8_t show_all = 0; if (Helpers::hasValue(cmd)) { - show_all = (strncmp(cmd, F_(info), 4) == 0); + show_all = (strncmp(cmd, F_(info), 4) == 0) ? 1 : (strncmp(cmd, F_(values), 6) == 0) ? 2 : 0; } // see if we're showing all sensors if (show_all) { for (const auto & sensor : sensors_) { - JsonObject dataSensor = output[sensor.name()].to(); - dataSensor["id"] = sensor.id(); - dataSensor["offset"] = sensor.offset(); - if (Helpers::hasValue(sensor.temperature_c)) { - char val[10]; - dataSensor["value"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0)); + if (show_all == 1) { + // info + JsonObject dataSensor = output[sensor.name()].to(); + addSensorJson(dataSensor, sensor); + } else { + // values, shortname version. Also used in 'system allvalues' + if (Helpers::hasValue(sensor.temperature_c)) { + char val[10]; + output[sensor.name()] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0)); + } } - dataSensor["type"] = F_(number); - dataSensor["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES); - dataSensor["writeable"] = false; } return true; } @@ -393,17 +394,8 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons for (const auto & sensor : sensors_) { // match custom name or sensor ID if (sensor_lowercase == Helpers::toLower(sensor.name().c_str()) || sensor_lowercase == Helpers::toLower(sensor.id().c_str())) { - output["id"] = sensor.id(); - output["name"] = sensor.name(); - if (Helpers::hasValue(sensor.temperature_c)) { - char val[10]; - output["value"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0)); - } - - output["type"] = F_(number); - output["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES); - output["writeable"] = false; - + // add values + addSensorJson(output, sensor); // if we're filtering on an attribute, go find it if (attribute_s) { if (output.containsKey(attribute_s)) { @@ -426,6 +418,20 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons return false; // not found } +void TemperatureSensor::addSensorJson(JsonObject output, const Sensor & sensor) { + output["id"] = sensor.id(); + output["name"] = sensor.name(); + if (Helpers::hasValue(sensor.temperature_c)) { + char val[10]; + output["value"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0)); + } + + output["type"] = F_(number); + output["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES); + output["writeable"] = false; +} + + // publish a single sensor to MQTT void TemperatureSensor::publish_sensor(const Sensor & sensor) { if (Mqtt::enabled() && Mqtt::publish_single()) { diff --git a/src/temperaturesensor.h b/src/temperaturesensor.h index 0c354d278..aad999e26 100644 --- a/src/temperaturesensor.h +++ b/src/temperaturesensor.h @@ -152,6 +152,7 @@ class TemperatureSensor { int16_t get_temperature_c(const uint8_t addr[]); uint64_t get_id(const uint8_t addr[]); void remove_ha_topic(const std::string & id); + void addSensorJson(JsonObject output, const Sensor & sensor); std::vector sensors_; // our list of active sensors From c7a35ebc58697fdc91a4e2f732c02b9121b3374c Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 28 Jan 2024 18:29:22 +0100 Subject: [PATCH 41/46] updated with changes to sensor commands --- CHANGELOG_LATEST.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index b6b3d9d48..b324bbaf0 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -17,7 +17,7 @@ - boiler Bosch C1200W, id 12, [#1536](https://github.com/emsesp/EMS-ESP32/issues/1536) - mixer MM100 telegram 0x2CC [#1554](https://github.com/emsesp/EMS-ESP32/issues/1554) - boiler hpSetDiffPressure [#1563](https://github.com/emsesp/EMS-ESP32/issues/1563) -- custom variables [#1423](https://github.com/emsesp/EMS-ESP32/issues/1423) +- custom variables [#1423](https://github.com/emsesp/EMS-ESP32/issues/1423) ## Fixed @@ -33,3 +33,4 @@ - HA don't set entity_category to Diagnostic/Configuration for EMS entities [#1459](https://github.com/emsesp/EMS-ESP32/discussions/1459) - upgraded ArduinoJson to 7.0.0 #1538 and then 7.0.2 +- small changes to the API for analog and temperature sensors From 0f799d5922f3a0d99a94f95ec4645d20071be995 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Tue, 30 Jan 2024 07:15:11 +0100 Subject: [PATCH 42/46] fix broadcast sending --- src/telegram.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/telegram.cpp b/src/telegram.cpp index ac3da27c3..83382a457 100644 --- a/src/telegram.cpp +++ b/src/telegram.cpp @@ -509,8 +509,8 @@ void TxService::add(uint8_t operation, const uint8_t * data, const uint8_t lengt } if (operation == Telegram::Operation::TX_RAW) { - if (src != ems_bus_id()) { - operation = Telegram::Operation::NONE; // do not check reply/ack for other ids + if (src != ems_bus_id() || dest == 0) { + operation = Telegram::Operation::NONE; // do not check reply/ack for other ids and broadcasts } else if (dest & 0x80) { operation = Telegram::Operation::TX_READ; EMSESP::set_response_id(type_id); From 1065c9eec9f773313b864e3dbe023b28f7fa23fa Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Tue, 30 Jan 2024 07:41:17 +0100 Subject: [PATCH 43/46] translations --- interface/src/i18n/de/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/i18n/de/index.ts b/interface/src/i18n/de/index.ts index 907ed4e2e..f0c8d3d05 100644 --- a/interface/src/i18n/de/index.ts +++ b/interface/src/i18n/de/index.ts @@ -191,7 +191,7 @@ const de: Translation = { THE_LATEST: 'Die neueste', OFFICIAL: 'offizielle', DEVELOPMENT: 'Entwicklungs', - RELEASE_IS: 'release ist', // TODO translate + RELEASE_IS: 'Release ist', RELEASE_NOTES: 'Versionshinweise', EMS_ESP_VER: 'EMS-ESP Version', UPTIME: 'System Betriebszeit', @@ -228,7 +228,7 @@ const de: Translation = { BROKER: 'Broker', CLIENT: 'Client', BASE_TOPIC: 'Base', - OPTIONAL: 'Optional', // TODO translate + OPTIONAL: 'Optional', FORMATTING: 'Formattierung', MQTT_FORMAT: 'Topic/Payload Format', MQTT_NEST_1: 'Eingebettet in einem Gesamttopic', @@ -308,7 +308,7 @@ const de: Translation = { LEAVE: 'Verlassen', SCHEDULER: 'Planer', SCHEDULER_HELP_1: 'Fügen Sie eigene, geplante Befehle zur Automatisierung hinzu. Vergeben Sie einen Entitätsnamen um die Aktivierung über API/Mqtt zu steuern', - SCHEDULER_HELP_2: 'Use 00:00 to trigger once on start-up', // TODO translate + SCHEDULER_HELP_2: '00:00 aktiviert einmalige Ausführung am Start', SCHEDULE: 'Zeitplan', TIME: 'Zeit', TIMER: 'Timer', @@ -317,7 +317,7 @@ const de: Translation = { SCHEDULE_TIMER_2: 'jede Minute', SCHEDULE_TIMER_3: 'jede Stunde', CUSTOM_ENTITIES: 'Individuelle Entitäten', - ENTITIES_HELP_1: 'Abfrage von Werten auf dem EMS-Bus', // TODO translate + ENTITIES_HELP_1: 'Definition eigener EMS-Werte oder dynamischer Variablen', ENTITIES_UPDATED: 'Entitäten gespeichert', WRITEABLE: 'Schreibbar', SHOWING: 'Anzeigen von', From 00b35255033a3911cd54e43bb5a1ac542aeeb2fc Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Tue, 30 Jan 2024 07:41:49 +0100 Subject: [PATCH 44/46] show sensor command commands --- src/analogsensor.cpp | 10 +++++----- src/command.cpp | 12 +++++------- src/temperaturesensor.cpp | 10 +++++----- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index 46794b512..e61915a26 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -623,6 +623,11 @@ void AnalogSensor::publish_values(const bool force) { // called from emsesp.cpp for commands // searches sensor by name bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) { + // check of it a 'commmands' command + if (Helpers::toLower(cmd) == F_(commands)) { + return Command::list(EMSdevice::DeviceType::ANALOGSENSOR, output); + } + if (sensors_.empty()) { return true; // no sensors, return true } @@ -647,11 +652,6 @@ bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int return true; } - // check of it a 'commmands' command - if (Helpers::toLower(cmd) == F_(commands)) { - return Command::list(EMSdevice::DeviceType::TEMPERATURESENSOR, output); - } - // this is for a specific sensor // make a copy of the string command for parsing, and lowercase it char sensor_name[30] = {'\0'}; diff --git a/src/command.cpp b/src/command.cpp index 12b4e13a7..3287f02a6 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -439,7 +439,11 @@ void Command::erase_command(const uint8_t device_type, const char * cmd) { // list all commands for a specific device, output as json bool Command::list(const uint8_t device_type, JsonObject output) { - if (cmdfunctions_.empty()) { + // force add info and commands for those non-EMS devices + if (device_type == EMSdevice::DeviceType::TEMPERATURESENSOR || device_type == EMSdevice::DeviceType::ANALOGSENSOR) { + output[F_(info)] = Helpers::translated_word(FL_(info_cmd)); + output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd)); + } else if (cmdfunctions_.empty()) { output["message"] = "no commands available"; return false; } @@ -453,12 +457,6 @@ bool Command::list(const uint8_t device_type, JsonObject output) { } sorted_cmds.sort(); - // force add info and commands for those non-EMS devices - if (device_type == EMSdevice::DeviceType::TEMPERATURESENSOR) { - output[F_(info)] = Helpers::translated_word(FL_(info_cmd)); - output[F_(commands)] = Helpers::translated_word(FL_(commands_cmd)); - } - for (const auto & cl : sorted_cmds) { for (const auto & cf : cmdfunctions_) { if ((cf.device_type_ == device_type) && !cf.has_flags(CommandFlag::HIDDEN) && cf.description_ && (cl == std::string(cf.cmd_))) { diff --git a/src/temperaturesensor.cpp b/src/temperaturesensor.cpp index 096bb6538..841ef633c 100644 --- a/src/temperaturesensor.cpp +++ b/src/temperaturesensor.cpp @@ -345,6 +345,11 @@ bool TemperatureSensor::updated_values() { // called from emsesp.cpp for commands bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, const int8_t id) { + // check of it a 'commmands' command + if (Helpers::toLower(cmd) == F_(commands)) { + return Command::list(EMSdevice::DeviceType::TEMPERATURESENSOR, output); + } + if (sensors_.empty()) { return true; // no sensors, return true } @@ -372,11 +377,6 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons return true; } - // check of it a 'commmands' command - if (Helpers::toLower(cmd) == F_(commands)) { - return Command::list(EMSdevice::DeviceType::TEMPERATURESENSOR, output); - } - // this is for a specific sensor // make a copy of the string command for parsing, and lowercase it char sensor_name[30] = {'\0'}; From b7ce69ee2d765e5d03cf3cc4e7d71bc1cc3c362d Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Tue, 30 Jan 2024 07:42:57 +0100 Subject: [PATCH 45/46] map RFM200/T1RF to connect/extension --- src/device_library.h | 6 ++++-- src/devices/connect.cpp | 24 +++++++++++++++++++++++- src/devices/connect.h | 4 ++++ src/devices/extension.cpp | 5 +++++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/device_library.h b/src/device_library.h index 8cfdf37ac..78f85c94a 100644 --- a/src/device_library.h +++ b/src/device_library.h @@ -70,8 +70,6 @@ {206, DeviceType::CONTROLLER, "Ecomline", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {207, DeviceType::CONTROLLER, "Sense II/CS200", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x10 {209, DeviceType::CONTROLLER, "ErP", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 -{218, DeviceType::CONTROLLER, "M200/RFM200", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x50 -{220, DeviceType::CONTROLLER, "BC30", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x16 {224, DeviceType::CONTROLLER, "9000i", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {229, DeviceType::CONTROLLER, "8700i", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 {230, DeviceType::CONTROLLER, "BC Base", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09 @@ -165,6 +163,7 @@ {206, DeviceType::CONNECT, "Easy Connect", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // Wireless sensor base - 0x50 +{218, DeviceType::CONNECT, "M200/RFM200", DeviceFlags::EMS_DEVICE_FLAG_NONE}, {236, DeviceType::CONNECT, "Wireless sensor base", DeviceFlags::EMS_DEVICE_FLAG_NONE}, {238, DeviceType::CONNECT, "Wireless sensor base", DeviceFlags::EMS_DEVICE_FLAG_NONE}, @@ -174,6 +173,9 @@ // EM10/100 extension module, pump module - 0x15 { 243, DeviceType::EXTENSION, "EM10/EM100", DeviceFlags::EMS_DEVICE_FLAG_NONE}, +// Wireless outdoor sensor T1RF - 0x16 +{ 220, DeviceType::EXTENSION, "T1RF", DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x16 + // EM10 error contact and analog flowtemp control- 0x12 { 74, DeviceType::ALERT, "EM10", DeviceFlags::EMS_DEVICE_FLAG_NONE}, diff --git a/src/devices/connect.cpp b/src/devices/connect.cpp index db5d578e3..8e795c242 100644 --- a/src/devices/connect.cpp +++ b/src/devices/connect.cpp @@ -24,6 +24,28 @@ REGISTER_FACTORY(Connect, EMSdevice::DeviceType::CONNECT); Connect::Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand) : EMSdevice(device_type, device_id, product_id, version, name, flags, brand) { + if (device_id == 0x50) { // RF Base + register_telegram_type(0xD1, "RFOutdoorTemp", false, MAKE_PF_CB(process_OutdoorTemp)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &outdoorTemp_, + DeviceValueType::SHORT, + DeviceValueNumOp::DV_NUMOP_DIV10, + FL_(outdoorTemp), + DeviceValueUOM::DEGREES); + } } +/* + * OutdoorTemp - type 0xD1 - external temperature + */ +void Connect::process_OutdoorTemp(std::shared_ptr telegram) { + has_update(telegram, outdoorTemp_, 0); +} + +/* other values from 0x50 RF base +(0x087F), data: 00 00 +(0x0880), data: 01 04 +(0x0889), data: 00 80 80 01 +*/ + -} // namespace emsesp \ No newline at end of file +} // namespace emsesp diff --git a/src/devices/connect.h b/src/devices/connect.h index 18b75c40f..d868c0872 100644 --- a/src/devices/connect.h +++ b/src/devices/connect.h @@ -26,6 +26,10 @@ namespace emsesp { class Connect : public EMSdevice { public: Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand); + + private: + void process_OutdoorTemp(std::shared_ptr telegram); + int16_t outdoorTemp_; }; } // namespace emsesp diff --git a/src/devices/extension.cpp b/src/devices/extension.cpp index 153d8dfca..181103fa9 100644 --- a/src/devices/extension.cpp +++ b/src/devices/extension.cpp @@ -24,6 +24,11 @@ REGISTER_FACTORY(Extension, EMSdevice::DeviceType::EXTENSION); Extension::Extension(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand) : EMSdevice(device_type, device_id, product_id, version, name, flags, brand) { + if (device_id == 0x16) { + // no entities for T1RF outdoor sensor, values are comming from RFbase 0x50 (connect) + return; + } + // Extension module EM100 device_id 0x12 register_telegram_type(0x935, "EM100SetMessage", true, MAKE_PF_CB(process_EM100SetMessage)); register_telegram_type(0x936, "EM100OutMessage", false, MAKE_PF_CB(process_EM100OutMessage)); register_telegram_type(0x937, "EM100TempMessage", false, MAKE_PF_CB(process_EM100TempMessage)); From 5532d206576f6275be65cd2886f1395248dc6c27 Mon Sep 17 00:00:00 2001 From: MichaelDvP Date: Tue, 30 Jan 2024 07:47:42 +0100 Subject: [PATCH 46/46] update packages --- interface/package.json | 6 +- interface/yarn.lock | 190 +++++++++++++++++++++++------------------ 2 files changed, 109 insertions(+), 87 deletions(-) diff --git a/interface/package.json b/interface/package.json index 3546a18cb..128ff5c98 100644 --- a/interface/package.json +++ b/interface/package.json @@ -31,7 +31,7 @@ "@table-library/react-table-library": "4.1.7", "@types/imagemin": "^8.0.5", "@types/lodash-es": "^4.17.12", - "@types/node": "^20.11.9", + "@types/node": "^20.11.10", "@types/react": "^18.2.48", "@types/react-dom": "^18.2.18", "@types/react-router-dom": "^5.3.3", @@ -54,8 +54,8 @@ "devDependencies": { "@preact/compat": "^17.1.2", "@preact/preset-vite": "^2.8.1", - "@typescript-eslint/eslint-plugin": "^6.19.1", - "@typescript-eslint/parser": "^6.19.1", + "@typescript-eslint/eslint-plugin": "^6.20.0", + "@typescript-eslint/parser": "^6.20.0", "concurrently": "^8.2.2", "eslint": "^8.56.0", "eslint-config-airbnb": "^19.0.4", diff --git a/interface/yarn.lock b/interface/yarn.lock index 0efef8813..12ed905ad 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -86,26 +86,26 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.23.7": - version: 7.23.7 - resolution: "@babel/core@npm:7.23.7" +"@babel/core@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/core@npm:7.23.9" dependencies: "@ampproject/remapping": "npm:^2.2.0" "@babel/code-frame": "npm:^7.23.5" "@babel/generator": "npm:^7.23.6" "@babel/helper-compilation-targets": "npm:^7.23.6" "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helpers": "npm:^7.23.7" - "@babel/parser": "npm:^7.23.6" - "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.7" - "@babel/types": "npm:^7.23.6" + "@babel/helpers": "npm:^7.23.9" + "@babel/parser": "npm:^7.23.9" + "@babel/template": "npm:^7.23.9" + "@babel/traverse": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 956841695ea801c8b4196d01072e6c1062335960715a6fcfd4009831003b526b00627c78b373ed49b1658c3622c71142f7ff04235fe839cac4a1a25ed51b90aa + checksum: 268cdbb86bef1b8ea5b1300f2f325e56a1740a5051360cb228ffeaa0f80282b6674f3a2b4d6466adb0691183759b88d4c37b4a4f77232c84a49ed771c84cdc27 languageName: node linkType: hard @@ -304,14 +304,14 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.23.7": - version: 7.23.7 - resolution: "@babel/helpers@npm:7.23.7" +"@babel/helpers@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/helpers@npm:7.23.9" dependencies: - "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.7" - "@babel/types": "npm:^7.23.6" - checksum: ec07061dc871d406ed82c8757c4d7a510aaf15145799fb0a2c3bd3c72ca101fe82a02dd5f83ca604fbbba5de5408dd731bb1452150562bed4f3b0a2846f81f61 + "@babel/template": "npm:^7.23.9" + "@babel/traverse": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + checksum: dd56daac8bbd7ed174bb00fd185926fd449e591d9a00edaceb7ac6edbdd7a8db57e2cb365b4fafda382201752789ced2f7ae010f667eab0f198a4571cda4d2c5 languageName: node linkType: hard @@ -346,12 +346,12 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.23.6": - version: 7.23.6 - resolution: "@babel/parser@npm:7.23.6" +"@babel/parser@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/parser@npm:7.23.9" bin: parser: ./bin/babel-parser.js - checksum: 6be3a63d3c9d07b035b5a79c022327cb7e16cbd530140ecb731f19a650c794c315a72c699a22413ebeafaff14aa8f53435111898d59e01a393d741b85629fa7d + checksum: 727a7a807100f6a26df859e2f009c4ddbd0d3363287b45daa50bd082ccd0d431d0c4d0e610a91f806e04a1918726cd0f5a0592c9b902a815337feed12e1cafd9 languageName: node linkType: hard @@ -421,6 +421,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/template@npm:7.23.9" + dependencies: + "@babel/code-frame": "npm:^7.23.5" + "@babel/parser": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + checksum: 1b011ba9354dc2e646561d54b6862e0df51760e6179faadd79be05825b0b6da04911e4e192df943f1766748da3037fd8493615b38707f7cadb0cf0c96601c170 + languageName: node + linkType: hard + "@babel/traverse@npm:^7.23.2": version: 7.23.2 resolution: "@babel/traverse@npm:7.23.2" @@ -439,9 +450,9 @@ __metadata: languageName: node linkType: hard -"@babel/traverse@npm:^7.23.7": - version: 7.23.7 - resolution: "@babel/traverse@npm:7.23.7" +"@babel/traverse@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/traverse@npm:7.23.9" dependencies: "@babel/code-frame": "npm:^7.23.5" "@babel/generator": "npm:^7.23.6" @@ -449,11 +460,11 @@ __metadata: "@babel/helper-function-name": "npm:^7.23.0" "@babel/helper-hoist-variables": "npm:^7.22.5" "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.23.6" - "@babel/types": "npm:^7.23.6" + "@babel/parser": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 3215e59429963c8dac85c26933372cdd322952aa9930e4bc5ef2d0e4bd7a1510d1ecf8f8fd860ace5d4d9fe496d23805a1ea019a86410aee4111de5f63ee84f9 + checksum: e2bb845f7f229feb7c338f7e150f5f1abc5395dcd3a6a47f63a25242ec3ec6b165f04a6df7d4849468547faee34eb3cf52487eb0bd867a7d3c42fec2a648266f languageName: node linkType: hard @@ -479,6 +490,17 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/types@npm:7.23.9" + dependencies: + "@babel/helper-string-parser": "npm:^7.23.4" + "@babel/helper-validator-identifier": "npm:^7.22.20" + to-fast-properties: "npm:^2.0.0" + checksum: bed9634e5fd0f9dc63c84cfa83316c4cb617192db9fedfea464fca743affe93736d7bf2ebf418ee8358751a9d388e303af87a0c050cb5d87d5870c1b0154f6cb + languageName: node + linkType: hard + "@emotion/babel-plugin@npm:^11.11.0": version: 11.11.0 resolution: "@emotion/babel-plugin@npm:11.11.0" @@ -1568,12 +1590,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^20.11.5": - version: 20.11.5 - resolution: "@types/node@npm:20.11.5" +"@types/node@npm:^20.11.10": + version: 20.11.10 + resolution: "@types/node@npm:20.11.10" dependencies: undici-types: "npm:~5.26.4" - checksum: 9f31c471047d7b3e240ce7b77ff29b0d15e83be7e3feafb3d0b0d0931122b438b1eefa302a5a2e1e9849914ff3fd76aafbd8ccb372efb1331ba048da63bce6f8 + checksum: 41ca9c7e7c95bf070ad747ab266f267f41950e01f5ddda739d0665c2ed39acc45cce46f78e33ffa2bf2dacd74a8493044b967c86358017dacce12958e49db664 languageName: node linkType: hard @@ -1691,15 +1713,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/eslint-plugin@npm:6.19.1" +"@typescript-eslint/eslint-plugin@npm:^6.20.0": + version: 6.20.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.20.0" dependencies: "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:6.19.1" - "@typescript-eslint/type-utils": "npm:6.19.1" - "@typescript-eslint/utils": "npm:6.19.1" - "@typescript-eslint/visitor-keys": "npm:6.19.1" + "@typescript-eslint/scope-manager": "npm:6.20.0" + "@typescript-eslint/type-utils": "npm:6.20.0" + "@typescript-eslint/utils": "npm:6.20.0" + "@typescript-eslint/visitor-keys": "npm:6.20.0" debug: "npm:^4.3.4" graphemer: "npm:^1.4.0" ignore: "npm:^5.2.4" @@ -1712,44 +1734,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: e88a35527b066a42d0253d153183a360faedc1cd39867c541ce7cb1f7b22f8446bb913b998fcdeba269d5d4217888af42e6d64da5c0592b1f49ed5648d2e3e84 + checksum: dee6a2392c831e6ae69611ecc4de06e66a7b16f6bf6d8e3bfd25091eb14d88c9d0bb9c9cd634efcfa318902341f7a459cf48f713d55cb1d610145ca1f52af4d3 languageName: node linkType: hard -"@typescript-eslint/parser@npm:^6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/parser@npm:6.19.1" +"@typescript-eslint/parser@npm:^6.20.0": + version: 6.20.0 + resolution: "@typescript-eslint/parser@npm:6.20.0" dependencies: - "@typescript-eslint/scope-manager": "npm:6.19.1" - "@typescript-eslint/types": "npm:6.19.1" - "@typescript-eslint/typescript-estree": "npm:6.19.1" - "@typescript-eslint/visitor-keys": "npm:6.19.1" + "@typescript-eslint/scope-manager": "npm:6.20.0" + "@typescript-eslint/types": "npm:6.20.0" + "@typescript-eslint/typescript-estree": "npm:6.20.0" + "@typescript-eslint/visitor-keys": "npm:6.20.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 63ff00a56586879a62e40b27b55c94501173fcf2fb5a620d01e7505851b4bb20feb1e7fbad36010af97aefc0a722267d9ce3aa004abab22cb7eb23eebb0102ce + checksum: 691062d47cae7977604ede848ffff3689162428a53577f298989f585954aa3a3450e7fd5c2b363d024cd5f16022c163cecf0f1f1d138234bbd78048050b4b8bf languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/scope-manager@npm:6.19.1" +"@typescript-eslint/scope-manager@npm:6.20.0": + version: 6.20.0 + resolution: "@typescript-eslint/scope-manager@npm:6.20.0" dependencies: - "@typescript-eslint/types": "npm:6.19.1" - "@typescript-eslint/visitor-keys": "npm:6.19.1" - checksum: 2a17f68d3c41582bfac7ecd192e2c2539cf4d2c9728a7018d842da7a8a23986b8a1f8cfcb59862c909b483140a2d164a4ba44451905e0a141378e5dd0df056cc + "@typescript-eslint/types": "npm:6.20.0" + "@typescript-eslint/visitor-keys": "npm:6.20.0" + checksum: 2c1a644f2931454b34875f2e6dffad52a1fc7b6ac508d7d1ad3cd9da028a7dff9c6191feeea2c9ca691deba199ac9e83cbd0036914be4cd45b6954437f03c09a languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/type-utils@npm:6.19.1" +"@typescript-eslint/type-utils@npm:6.20.0": + version: 6.20.0 + resolution: "@typescript-eslint/type-utils@npm:6.20.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:6.19.1" - "@typescript-eslint/utils": "npm:6.19.1" + "@typescript-eslint/typescript-estree": "npm:6.20.0" + "@typescript-eslint/utils": "npm:6.20.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.0.1" peerDependencies: @@ -1757,23 +1779,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 5150b897d8b3778c549c6b964b031981da1039dfa0fb89a0eb92702735ca55793d2f840af14b340eccbca81669ba3dd02d7f09fb420fb66b18ec9f1f211b3243 + checksum: bc2f2793cfec3463164b5f5ded31b4e169e21c3a1990c1ce4effe70a359c486d92fbbc4cd92758bbf1c30a468ad0839e0fa890bd452c707d0c294cb3a7b14021 languageName: node linkType: hard -"@typescript-eslint/types@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/types@npm:6.19.1" - checksum: 93f3ded80b81a1b8686866b93e36ddf9bac04604d09e88d7ed1ec25b6b2f49ff64747d8d194ba1f3215e231fd0790b88fb5ecadcc6ed53ff584f8c0b87423216 +"@typescript-eslint/types@npm:6.20.0": + version: 6.20.0 + resolution: "@typescript-eslint/types@npm:6.20.0" + checksum: 74ed1761e27c3c1a29fd260fe51096f42cfb1472b20390d6df6ec41de0420208f379e809de416e81cd7c00fdc3d5550b2391872be56bf4a1b0c595f71db0b1ea languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/typescript-estree@npm:6.19.1" +"@typescript-eslint/typescript-estree@npm:6.20.0": + version: 6.20.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.20.0" dependencies: - "@typescript-eslint/types": "npm:6.19.1" - "@typescript-eslint/visitor-keys": "npm:6.19.1" + "@typescript-eslint/types": "npm:6.20.0" + "@typescript-eslint/visitor-keys": "npm:6.20.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" @@ -1783,34 +1805,34 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 3ce91dd477ccb2cc3cf5d07ac8d23792988f4fad78bfd39783292846f32daea5081d3790ba9cc795d9de89ea2e1d55dc9c3d2aeaa8597093b0f6ac3a206195e9 + checksum: 55b280c6e71c79cb009ac80189a7f0e1aa9011bc7206c810bbb52d9703a894aa2817dfd44d947edf64d62f3aa0962e01f3423fcb21d2f39964a4840287d9e196 languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/utils@npm:6.19.1" +"@typescript-eslint/utils@npm:6.20.0": + version: 6.20.0 + resolution: "@typescript-eslint/utils@npm:6.20.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" "@types/json-schema": "npm:^7.0.12" "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:6.19.1" - "@typescript-eslint/types": "npm:6.19.1" - "@typescript-eslint/typescript-estree": "npm:6.19.1" + "@typescript-eslint/scope-manager": "npm:6.20.0" + "@typescript-eslint/types": "npm:6.20.0" + "@typescript-eslint/typescript-estree": "npm:6.20.0" semver: "npm:^7.5.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: f8931df675defa84af373c81bbb13cc34c2fcf0803c687a38b982e85335dbf2fb8415667fbabaa043df0326ba3e98ed974104bbd21f09ec538304fc3adeed0c3 + checksum: 6d4604be6123e0073dd5e7dd357c95b370c678572d2e982478d0d6937d4d65f0cad0ac207b8b724f3bce239e64ba1ddd6bece11e1592734d8bf691177e6971e6 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.19.1": - version: 6.19.1 - resolution: "@typescript-eslint/visitor-keys@npm:6.19.1" +"@typescript-eslint/visitor-keys@npm:6.20.0": + version: 6.20.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.20.0" dependencies: - "@typescript-eslint/types": "npm:6.19.1" + "@typescript-eslint/types": "npm:6.20.0" eslint-visitor-keys: "npm:^3.4.1" - checksum: b41f3247520e1e4d3e43876843b03f0d887e544d4ac8a9e1f4b25d08568da36fedde883fa226488a595f688198859cd0290d0f1351c2ca6cbc30cca2c90adf21 + checksum: df066c73f3880ad78880c442f307e58f026e6047d9caab9d7c356d13276f4fe466fab3e8d19cdb1e6749e87639cb7c4babcfe118f554fcd2d3929ce9f4983216 languageName: node linkType: hard @@ -1826,7 +1848,7 @@ __metadata: resolution: "EMS-ESP@workspace:." dependencies: "@alova/adapter-xhr": "npm:^1.0.3" - "@babel/core": "npm:^7.23.7" + "@babel/core": "npm:^7.23.9" "@emotion/react": "npm:^11.11.3" "@emotion/styled": "npm:^11.11.0" "@mui/icons-material": "npm:^5.15.6" @@ -1836,12 +1858,12 @@ __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.5" + "@types/node": "npm:^20.11.10" "@types/react": "npm:^18.2.48" "@types/react-dom": "npm:^18.2.18" "@types/react-router-dom": "npm:^5.3.3" - "@typescript-eslint/eslint-plugin": "npm:^6.19.1" - "@typescript-eslint/parser": "npm:^6.19.1" + "@typescript-eslint/eslint-plugin": "npm:^6.20.0" + "@typescript-eslint/parser": "npm:^6.20.0" alova: "npm:^2.17.0" async-validator: "npm:^4.2.5" concurrently: "npm:^8.2.2"