diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 023cfb286..c85e5572e 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -18,6 +18,9 @@ - Show network hostname in Web UI under Network Status - Improved HA Discovery so each section (EMS device, Scheduler, Analog, Temperature, Custom, Shower) have their own section - 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) ## Fixed @@ -27,9 +30,10 @@ - changed HA name and grouping to be consistent [#1528](https://github.com/emsesp/EMS-ESP32/issues/1528) - MQTT autodiscovery in Domoticz not working [#1360](https://github.com/emsesp/EMS-ESP32/issues/1528) - dhw comfort for new ems+, [#1495](https://github.com/emsesp/EMS-ESP32/issues/1495) +- added writeable icon to Web's Custom Entity page for each entity shown in the table ## Changed - use flag for BC400 compatible thermostats, manage different mode settings - 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 +- upgraded ArduinoJson to 7.0.0 #1538 and then 7.0.2 diff --git a/interface/package.json b/interface/package.json index 72a2d9a3b..d3908e499 100644 --- a/interface/package.json +++ b/interface/package.json @@ -20,20 +20,20 @@ "lint": "eslint . --cache --fix" }, "dependencies": { - "@alova/adapter-xhr": "^1.0.2", + "@alova/adapter-xhr": "^1.0.3", "@babel/core": "^7.23.7", "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", - "@mui/icons-material": "^5.15.3", - "@mui/material": "^5.15.3", + "@mui/icons-material": "^5.15.5", + "@mui/material": "^5.15.5", "@table-library/react-table-library": "4.1.7", "@types/imagemin": "^8.0.5", "@types/lodash-es": "^4.17.12", - "@types/node": "^20.10.6", - "@types/react": "^18.2.47", + "@types/node": "^20.11.5", + "@types/react": "^18.2.48", "@types/react-dom": "^18.2.18", "@types/react-router-dom": "^5.3.3", - "alova": "^2.16.2", + "alova": "^2.17.0", "async-validator": "^4.2.5", "history": "^5.3.0", "jwt-decode": "^4.0.0", @@ -42,9 +42,9 @@ "react": "latest", "react-dom": "latest", "react-dropzone": "^14.2.3", - "react-icons": "^4.12.0", - "react-router-dom": "^6.21.1", - "react-toastify": "^9.1.3", + "react-icons": "^5.0.1", + "react-router-dom": "^6.21.3", + "react-toastify": "^10.0.3", "sockette": "^2.0.6", "typesafe-i18n": "^5.26.2", "typescript": "^5.3.3" @@ -52,8 +52,8 @@ "devDependencies": { "@preact/compat": "^17.1.2", "@preact/preset-vite": "^2.8.1", - "@typescript-eslint/eslint-plugin": "^6.18.0", - "@typescript-eslint/parser": "^6.18.0", + "@typescript-eslint/eslint-plugin": "^6.19.0", + "@typescript-eslint/parser": "^6.19.0", "concurrently": "^8.2.2", "eslint": "^8.56.0", "eslint-config-airbnb": "^19.0.4", @@ -67,12 +67,12 @@ "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "preact": "^10.19.3", - "prettier": "^3.1.1", + "prettier": "^3.2.4", "rollup-plugin-visualizer": "^5.12.0", - "terser": "^5.26.0", - "vite": "^5.0.11", + "terser": "^5.27.0", + "vite": "^5.0.12", "vite-plugin-imagemin": "^0.6.1", - "vite-tsconfig-paths": "^4.2.3" + "vite-tsconfig-paths": "^4.3.1" }, "packageManager": "yarn@4.0.2" } diff --git a/interface/src/components/upload/SingleUpload.tsx b/interface/src/components/upload/SingleUpload.tsx index 498e4b913..bbd3e9ce3 100644 --- a/interface/src/components/upload/SingleUpload.tsx +++ b/interface/src/components/upload/SingleUpload.tsx @@ -50,8 +50,10 @@ const SingleUpload: FC = ({ onDrop, onCancel, isUploading, pr const progressText = () => { if (uploading) { - if (progress.total) { - return LL.UPLOADING() + ': ' + Math.round((progress.loaded * 100) / progress.total) + '%'; + if (progress.total && progress.loaded) { + return progress.loaded <= progress.total + ? LL.UPLOADING() + ': ' + Math.round((progress.loaded * 100) / progress.total) + '%' + : LL.UPLOADING() + ': ' + Math.round((progress.total * 100) / progress.loaded) + '%'; } } return LL.UPLOAD_DROP_TEXT(); @@ -83,7 +85,13 @@ const SingleUpload: FC = ({ onDrop, onCancel, isUploading, pr + @@ -284,4 +298,4 @@ const SettingsEntities: FC = () => { ); }; -export default SettingsEntities; +export default SettingsCustomEntities; diff --git a/interface/src/project/SettingsEntitiesDialog.tsx b/interface/src/project/SettingsCustomEntitiesDialog.tsx similarity index 50% rename from interface/src/project/SettingsEntitiesDialog.tsx rename to interface/src/project/SettingsCustomEntitiesDialog.tsx index 061eab8c5..691f23b25 100644 --- a/interface/src/project/SettingsEntitiesDialog.tsx +++ b/interface/src/project/SettingsCustomEntitiesDialog.tsx @@ -30,7 +30,7 @@ import { useI18nContext } from 'i18n/i18n-react'; import { updateValue } from 'utils'; import { validate } from 'validators'; -type SettingsEntitiesDialogProps = { +type SettingsCustomEntitiesDialogProps = { open: boolean; creating: boolean; onClose: () => void; @@ -39,14 +39,14 @@ type SettingsEntitiesDialogProps = { validator: Schema; }; -const SettingsEntitiesDialog = ({ +const SettingsCustomEntitiesDialog = ({ open, creating, onClose, onSave, selectedItem, validator -}: SettingsEntitiesDialogProps) => { +}: SettingsCustomEntitiesDialogProps) => { const { LL } = useI18nContext(); const [editItem, setEditItem] = useState(selectedItem); const [fieldErrors, setFieldErrors] = useState(); @@ -100,7 +100,7 @@ const SettingsEntitiesDialog = ({ - + - - } - label={LL.WRITEABLE()} - /> - - - 0x }} - /> - - - 0x }} - /> - - - - - BOOL - INT - UINT - SHORT - USHORT - ULONG - TIME - RAW + EMS-{LL.VALUE(1)} + RAM-{LL.VALUE(1)} - - {editItem.value_type !== DeviceValueType.BOOL && editItem.value_type !== DeviceValueType.STRING && ( - <> - - - - - - {DeviceValueUOM_s.map((val, i) => ( - - {val} - - ))} - - - - )} - {editItem.value_type === DeviceValueType.STRING && ( + {editItem.ram === 1 && ( )} + {editItem.ram === 0 && ( + <> + + } + label={LL.WRITEABLE()} + /> + + + 0x }} + /> + + + 0x }} + /> + + + + + + + BOOL + INT + UINT + SHORT + USHORT + ULONG + TIME + RAW + + + + {editItem.value_type !== DeviceValueType.BOOL && editItem.value_type !== DeviceValueType.STRING && ( + <> + + + + + + {DeviceValueUOM_s.map((val, i) => ( + + {val} + + ))} + + + + )} + {editItem.value_type === DeviceValueType.STRING && editItem.device_id !== '0' && ( + + + + )} + + )} @@ -249,4 +281,4 @@ const SettingsEntitiesDialog = ({ ); }; -export default SettingsEntitiesDialog; +export default SettingsCustomEntitiesDialog; diff --git a/interface/src/project/api.ts b/interface/src/project/api.ts index 509e238e1..96b317203 100644 --- a/interface/src/project/api.ts +++ b/interface/src/project/api.ts @@ -88,7 +88,7 @@ export const writeSchedule = (data: any) => alovaInstance.Post('/rest/schedule', // SettingsEntities export const readCustomEntities = () => - alovaInstance.Get('/rest/customentities', { + alovaInstance.Get('/rest/customEntities', { name: 'entities', transformData(data: any) { return data.entities.map((ei: EntityItem) => ({ @@ -106,4 +106,4 @@ export const readCustomEntities = () => })); } }); -export const writeCustomEntities = (data: any) => alovaInstance.Post('/rest/customentities', data); +export const writeCustomEntities = (data: any) => alovaInstance.Post('/rest/customEntities', data); diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts index 73a0643c2..e2943a246 100644 --- a/interface/src/project/types.ts +++ b/interface/src/project/types.ts @@ -177,7 +177,8 @@ export enum DeviceValueUOM { L, KMIN, K, - VOLTS + VOLTS, + MBAR } export const DeviceValueUOM_s = [ @@ -204,7 +205,8 @@ export const DeviceValueUOM_s = [ 'l', 'K*min', 'K', - 'V' + 'V', + 'mbar' ]; export enum AnalogType { @@ -323,6 +325,7 @@ export enum ScheduleFlag { export interface EntityItem { id: number; // unique number + ram: number; name: string; device_id: number | string; type_id: number | string; @@ -334,6 +337,7 @@ export interface EntityItem { writeable: boolean; deleted?: boolean; o_id?: number; + o_ram?: number; o_name?: string; o_device_id?: number | string; o_type_id?: number | string; @@ -343,6 +347,7 @@ export interface EntityItem { o_value_type?: number; o_deleted?: boolean; o_writeable?: boolean; + o_value?: any; } export interface Entities { @@ -398,6 +403,6 @@ export const DeviceValueTypeNames = [ 'ULONG', 'TIME', 'ENUM', - 'STRING', + 'RAW', 'CMD' ]; diff --git a/interface/src/types/ntp.ts b/interface/src/types/ntp.ts index e22a9fa59..b783cfb80 100644 --- a/interface/src/types/ntp.ts +++ b/interface/src/types/ntp.ts @@ -9,7 +9,6 @@ export interface NTPStatus { utc_time: string; local_time: string; server: string; - uptime: number; } export interface NTPSettings { diff --git a/interface/yarn.lock b/interface/yarn.lock index 2422f54df..95918a750 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -12,10 +12,10 @@ __metadata: languageName: node linkType: hard -"@alova/adapter-xhr@npm:^1.0.2": - version: 1.0.2 - resolution: "@alova/adapter-xhr@npm:1.0.2" - checksum: a57d178e89e3b655191bebccbc34d22760813b97b430e16f77b6ad561e3bb4ad8a34948aa2d724f5833d675f21a337ab769a3e5f73878430c3139374c6afb6ea +"@alova/adapter-xhr@npm:^1.0.3": + version: 1.0.3 + resolution: "@alova/adapter-xhr@npm:1.0.3" + checksum: 53923b0b7f833bbbda662ad28f29bb8226d2126ab7dcc57c9aa5486212cb02f0cfa19760d33ab63334688458138fc3c4713084c2f6a558c969d83efda7828601 languageName: node linkType: hard @@ -401,12 +401,12 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.23.6": - version: 7.23.6 - resolution: "@babel/runtime@npm:7.23.6" +"@babel/runtime@npm:^7.23.8": + version: 7.23.8 + resolution: "@babel/runtime@npm:7.23.8" dependencies: regenerator-runtime: "npm:^0.14.0" - checksum: 4c4ab16f0361c59fb23956e4d0a29935f1f8a64aa8dd37876ce38355b6f4d8f0e54237aacb89c73b1532def60539ddde2d651523c8fa887b30b19a8cf0c465b0 + checksum: ec8f1967a36164da6cac868533ffdff97badd76d23d7d820cc84f0818864accef972f22f9c6a710185db1e3810e353fc18c3da721e5bb3ee8bc61bdbabce03ff languageName: node linkType: hard @@ -841,41 +841,41 @@ __metadata: languageName: node linkType: hard -"@floating-ui/core@npm:^1.4.2": - version: 1.5.0 - resolution: "@floating-ui/core@npm:1.5.0" - dependencies: - "@floating-ui/utils": "npm:^0.1.3" - checksum: 3182715a30493f44a32158f4d77ab5b6c212064b160cb84b5b8405ec2845bd8a9167c25292709e841cad9e70c6b9efdc30f876044e3b0909139fea8eca00c631 - languageName: node - linkType: hard - -"@floating-ui/dom@npm:^1.5.1": +"@floating-ui/core@npm:^1.5.3": version: 1.5.3 - resolution: "@floating-ui/dom@npm:1.5.3" + resolution: "@floating-ui/core@npm:1.5.3" dependencies: - "@floating-ui/core": "npm:^1.4.2" - "@floating-ui/utils": "npm:^0.1.3" - checksum: d2d5ae7a0949c0ebf7fbf97a21612bf94dbd29cb6c847e00588b8e2a5575ade27c47cb19f5d230fc21a571d99aa0c714b301c9221d33921047408c0ed9d91a30 + "@floating-ui/utils": "npm:^0.2.0" + checksum: 7d9feaca2565a2a71bf03d23cd292c03def63097d7fde7d62909cdb8ddb84664781f3922086bcf10443f3310cb92381a0ecf745b2774edb917fa74fe61015c56 languageName: node linkType: hard -"@floating-ui/react-dom@npm:^2.0.4": - version: 2.0.4 - resolution: "@floating-ui/react-dom@npm:2.0.4" +"@floating-ui/dom@npm:^1.5.4": + version: 1.5.4 + resolution: "@floating-ui/dom@npm:1.5.4" dependencies: - "@floating-ui/dom": "npm:^1.5.1" + "@floating-ui/core": "npm:^1.5.3" + "@floating-ui/utils": "npm:^0.2.0" + checksum: 3ba02ba2b4227c1e18df6ccdd029a1c100058db2e76ca1dac60a593ec72b2d4d995fa5c2d1639a5c38adb17e12398fbfe4f6cf5fd45f2ee6170ed0cf64acea06 + 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" + dependencies: + "@floating-ui/dom": "npm:^1.5.4" peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: 4240a718502c797fd2e174cd06dcd7321a6eda9c8966dbaf61864b9e16445e95649a59bfe7c19ee13f68c11f3693724d7970c7e618089a3d3915bd343639cfae + checksum: b4fc008c725149b9565949184d844c914a8fa2687636c3c1166a1d52ca58537b3ba9b0a0e2945cf424662c846e60b173df0d325af7e700a31550e5e0b346070a languageName: node linkType: hard -"@floating-ui/utils@npm:^0.1.3": - version: 0.1.6 - resolution: "@floating-ui/utils@npm:0.1.6" - checksum: 450ec4ecc1dd8161b1904d4e1e9d95e653cc06f79af6c3b538b79efb10541d90bcc88646ab3cdffc5b92e00c4804ca727b025d153ad285f42dbbb39aec219ec9 +"@floating-ui/utils@npm:^0.2.0": + version: 0.2.1 + resolution: "@floating-ui/utils@npm:0.2.1" + checksum: 33c9ab346e7b05c5a1e6a95bc902aafcfc2c9d513a147e2491468843bd5607531b06d0b9aa56aa491cbf22a6c2495c18ccfc4c0344baec54a689a7bb8e4898d6 languageName: node linkType: hard @@ -970,16 +970,16 @@ __metadata: languageName: node linkType: hard -"@mui/base@npm:5.0.0-beta.30": - version: 5.0.0-beta.30 - resolution: "@mui/base@npm:5.0.0-beta.30" +"@mui/base@npm:5.0.0-beta.32": + version: 5.0.0-beta.32 + resolution: "@mui/base@npm:5.0.0-beta.32" dependencies: - "@babel/runtime": "npm:^7.23.6" - "@floating-ui/react-dom": "npm:^2.0.4" - "@mui/types": "npm:^7.2.12" - "@mui/utils": "npm:^5.15.3" + "@babel/runtime": "npm:^7.23.8" + "@floating-ui/react-dom": "npm:^2.0.5" + "@mui/types": "npm:^7.2.13" + "@mui/utils": "npm:^5.15.5" "@popperjs/core": "npm:^2.11.8" - clsx: "npm:^2.0.0" + clsx: "npm:^2.1.0" prop-types: "npm:^15.8.1" peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 @@ -988,22 +988,22 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 55e18d59ac96f5bbfbfdadd907751f5e6a4f74f611b5e99fe5f8002c76fa117b62c159f52ea0f12574a66460d62734082438cff19cb73e3fca9dc22f82f6eaf2 + checksum: c88cd8a412ecaeaf0040e20708b2a607b9594a4462449ad06b90e96465aad0dada23295f801ed72851025fd023ababc410b6a48fcb69d7cdef90b55e62aa9a11 languageName: node linkType: hard -"@mui/core-downloads-tracker@npm:^5.15.3": - version: 5.15.3 - resolution: "@mui/core-downloads-tracker@npm:5.15.3" - checksum: 002451af1aa555c0163c0ffacde5c15062e0ae0f30b81945e1a0befe7b6c5d14924a2b068b7b5f713c177ee3eecca4fc250d590d11206a6b5465700c399a34d1 +"@mui/core-downloads-tracker@npm:^5.15.5": + version: 5.15.5 + resolution: "@mui/core-downloads-tracker@npm:5.15.5" + checksum: 4c9b1281ebe8d17d402e22f7f50c347c0b3918b1ed17af721f4de5ce282d90bc6d90fe9730595998b2bbb2f7ebe57fc55d4c858f31754fccdb606af472a59dc8 languageName: node linkType: hard -"@mui/icons-material@npm:^5.15.3": - version: 5.15.3 - resolution: "@mui/icons-material@npm:5.15.3" +"@mui/icons-material@npm:^5.15.5": + version: 5.15.5 + resolution: "@mui/icons-material@npm:5.15.5" dependencies: - "@babel/runtime": "npm:^7.23.6" + "@babel/runtime": "npm:^7.23.8" peerDependencies: "@mui/material": ^5.0.0 "@types/react": ^17.0.0 || ^18.0.0 @@ -1011,22 +1011,22 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 2393a9dcd0834cdda728b8ebca5d8f6acbfc34316346aaea257e32961abf7cf578419df196b50223b89b3e2556098aea283786ca4eeedaf58be3d204f499f6bc + checksum: 25feb86a76ce83c81391c95d0c1c867e988cc7bc1b5a05c5698b71cb3cd1005fd148b07c2fa8908cda9fc4e44ea8b6e0fd2197bc0abafac0ee4880b477852eea languageName: node linkType: hard -"@mui/material@npm:^5.15.3": - version: 5.15.3 - resolution: "@mui/material@npm:5.15.3" +"@mui/material@npm:^5.15.5": + version: 5.15.5 + resolution: "@mui/material@npm:5.15.5" dependencies: - "@babel/runtime": "npm:^7.23.6" - "@mui/base": "npm:5.0.0-beta.30" - "@mui/core-downloads-tracker": "npm:^5.15.3" - "@mui/system": "npm:^5.15.3" - "@mui/types": "npm:^7.2.12" - "@mui/utils": "npm:^5.15.3" + "@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/types": "npm:^7.2.13" + "@mui/utils": "npm:^5.15.5" "@types/react-transition-group": "npm:^4.4.10" - clsx: "npm:^2.0.0" + clsx: "npm:^2.1.0" csstype: "npm:^3.1.2" prop-types: "npm:^15.8.1" react-is: "npm:^18.2.0" @@ -1044,16 +1044,16 @@ __metadata: optional: true "@types/react": optional: true - checksum: fe8d318aed036b649a82e4833254f833ece028b6a25cec001991e6864d9e520752df6a746b6ca856c0310cc9aae16697aa77ddf53a85c889bb5d04c5aa5c1dcb + checksum: 2a094d94acfc8f945b6cc73b295799f3174d7292707230e9b9486d810990561778f5f228f2fdc13a064ae234d528fb28c9b53f6c487ca43e65dc17460886165c languageName: node linkType: hard -"@mui/private-theming@npm:^5.15.3": - version: 5.15.3 - resolution: "@mui/private-theming@npm:5.15.3" +"@mui/private-theming@npm:^5.15.5": + version: 5.15.5 + resolution: "@mui/private-theming@npm:5.15.5" dependencies: - "@babel/runtime": "npm:^7.23.6" - "@mui/utils": "npm:^5.15.3" + "@babel/runtime": "npm:^7.23.8" + "@mui/utils": "npm:^5.15.5" prop-types: "npm:^15.8.1" peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 @@ -1061,15 +1061,15 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 4404a7d9545974631b329f391df72fa54edb5aefa6d32d9656b200284613e8ea1bdd3d0add2abe7278f1343dd5cf7552c7e4d2aaf5593f292c7db3cd63ddff21 + checksum: 1b26bc897417dcd91bbc65af3584c3cdf6704e9beb707c97bb7977962536213d7c7bf8e1004cbe86a19625ed5feba82d3ad2997e943138ed36114a8a36bf0fed languageName: node linkType: hard -"@mui/styled-engine@npm:^5.15.3": - version: 5.15.3 - resolution: "@mui/styled-engine@npm:5.15.3" +"@mui/styled-engine@npm:^5.15.5": + version: 5.15.5 + resolution: "@mui/styled-engine@npm:5.15.5" dependencies: - "@babel/runtime": "npm:^7.23.6" + "@babel/runtime": "npm:^7.23.8" "@emotion/cache": "npm:^11.11.0" csstype: "npm:^3.1.2" prop-types: "npm:^15.8.1" @@ -1082,20 +1082,20 @@ __metadata: optional: true "@emotion/styled": optional: true - checksum: 6775f92cda9f17428baf5b95e5849f31eead92485e332902ff29bd49bd03fbe2f5e762ebcdd122f7f31e102ec42cda29cbb5fdef79f5d03f416705d119b69e75 + checksum: 10e38ed39f7defc26d7e14e9634afcd9d540eaa1b9aeb957a6d1154a14a3cca2843e9aa7ead126604728bbf2125203c1f157059c06b397ed0278fc4b7cfae5c5 languageName: node linkType: hard -"@mui/system@npm:^5.15.3": - version: 5.15.3 - resolution: "@mui/system@npm:5.15.3" +"@mui/system@npm:^5.15.5": + version: 5.15.5 + resolution: "@mui/system@npm:5.15.5" dependencies: - "@babel/runtime": "npm:^7.23.6" - "@mui/private-theming": "npm:^5.15.3" - "@mui/styled-engine": "npm:^5.15.3" - "@mui/types": "npm:^7.2.12" - "@mui/utils": "npm:^5.15.3" - clsx: "npm:^2.0.0" + "@babel/runtime": "npm:^7.23.8" + "@mui/private-theming": "npm:^5.15.5" + "@mui/styled-engine": "npm:^5.15.5" + "@mui/types": "npm:^7.2.13" + "@mui/utils": "npm:^5.15.5" + clsx: "npm:^2.1.0" csstype: "npm:^3.1.2" prop-types: "npm:^15.8.1" peerDependencies: @@ -1110,27 +1110,27 @@ __metadata: optional: true "@types/react": optional: true - checksum: 7b71cad3c3b4f8136cf51a9e7040440073201618eaa5d0fcbd8830e3c3f35eb8a38303bb2bc9da84e0c95844193fdb4238af50e1f1d74a8e9fa79500a49c31db + checksum: bc40858eff92efe1424b4de5782ca48ec0bccfe2de244b00af8f8607a7f47b5ec7006a0e369d1c52ddb3fe01d7666d1f7ed6d9a9070bee28dfa4ab2cecc4d015 languageName: node linkType: hard -"@mui/types@npm:^7.2.12": - version: 7.2.12 - resolution: "@mui/types@npm:7.2.12" +"@mui/types@npm:^7.2.13": + version: 7.2.13 + resolution: "@mui/types@npm:7.2.13" peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: 7d3ef53fee7eddc063d2083dc129f7d6d38b472a9196c3522fc5a75e66849fbf2b824be3f6aee11dc02c4475864e544026e6051ffb9d33f5dc1fc2a2279a8b72 + checksum: a35bff025f715073329bd7cbe11ef4ce331ea377adffc0c5cd264bea47283590ce928d1fdbbc27506d1d462151325c81e71f2378ac4335feef3042010bbf3fcd languageName: node linkType: hard -"@mui/utils@npm:^5.15.3": - version: 5.15.3 - resolution: "@mui/utils@npm:5.15.3" +"@mui/utils@npm:^5.15.5": + version: 5.15.5 + resolution: "@mui/utils@npm:5.15.5" dependencies: - "@babel/runtime": "npm:^7.23.6" + "@babel/runtime": "npm:^7.23.8" "@types/prop-types": "npm:^15.7.11" prop-types: "npm:^15.8.1" react-is: "npm:^18.2.0" @@ -1140,7 +1140,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: c4d66e34332f448527c6dea66a7011f95dc230ccaf5a3ee898a6fd69b77a3584af1fd644d095dc7edb2d480e5c050db06f9b9ec9dea3bc5091a80cf8b676f709 + checksum: c8ff39a23ec540c6fd6495e44df6dc5531afca535cbb605f81cd5ef66af946e6c6415290caade8cfa0f61ecfb55703d8065c4968530c0b54c52d44f23a04cbfe languageName: node linkType: hard @@ -1277,10 +1277,10 @@ __metadata: languageName: node linkType: hard -"@remix-run/router@npm:1.14.1": - version: 1.14.1 - resolution: "@remix-run/router@npm:1.14.1" - checksum: caed61639006444a66ca832f1e500bac2fcf02695183e967ff1452d3172f888f2bb40591b239c85f9003b9628383cfd4c8ef55cde800d14276905c7031c9f0b9 +"@remix-run/router@npm:1.14.2": + version: 1.14.2 + resolution: "@remix-run/router@npm:1.14.2" + checksum: 422844e88b985f1e287301b302c6cf8169c9eea792f80d40464f97b25393bb2e697228ebd7a7b61444d5a51c5873c4a637aad20acde5886a5caf62e833c5ceee languageName: node linkType: hard @@ -1568,12 +1568,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^20.10.6": - version: 20.10.6 - resolution: "@types/node@npm:20.10.6" +"@types/node@npm:^20.11.5": + version: 20.11.5 + resolution: "@types/node@npm:20.11.5" dependencies: undici-types: "npm:~5.26.4" - checksum: 08471220d3cbbb6669835c4b78541edf5eface8f2c2e36c550cfa4ff73da73071c90e200a06359fac25d6564127597c23e178128058fb676824ec23d5178a017 + checksum: 9f31c471047d7b3e240ce7b77ff29b0d15e83be7e3feafb3d0b0d0931122b438b1eefa302a5a2e1e9849914ff3fd76aafbd8ccb372efb1331ba048da63bce6f8 languageName: node linkType: hard @@ -1648,14 +1648,14 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:^18.2.47": - version: 18.2.47 - resolution: "@types/react@npm:18.2.47" +"@types/react@npm:^18.2.48": + version: 18.2.48 + resolution: "@types/react@npm:18.2.48" dependencies: "@types/prop-types": "npm:*" "@types/scheduler": "npm:*" csstype: "npm:^3.0.2" - checksum: 0a98c2ef8303909f78c973ac9731cb671f3a0b96bc5213b538d1a50cbaae6e51b6befd64845a9cb95af8528767315d5bd99a85608eb716c020393c7d33a9b477 + checksum: 2e56ea6bd821ae96bd943f727a59d85384eaf5f8a3e6fce4fa1d34453e32d8eedda742432b3857fa0de7a4214bf84ce4239757eb52918e76452c00384731e585 languageName: node linkType: hard @@ -1691,15 +1691,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.18.0" +"@typescript-eslint/eslint-plugin@npm:^6.19.0": + version: 6.19.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.19.0" dependencies: "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:6.18.0" - "@typescript-eslint/type-utils": "npm:6.18.0" - "@typescript-eslint/utils": "npm:6.18.0" - "@typescript-eslint/visitor-keys": "npm:6.18.0" + "@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" 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: 7810a84f6d9cb735f6848aa4a7ef64c77740812afc0248fda63ec182910a1d045cd9a32d8e49b0e5323266db6da12a2fe50171147927b3186815a56f12c16ee7 + checksum: 5ed8483d792c4bc6ed697159c84a47ba5c35cd124949883813f2053b972537de3900a7ae26d4d6f370194f2cc7929baa2d09268e0b90118f20ed961cf6c176b9 languageName: node linkType: hard -"@typescript-eslint/parser@npm:^6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/parser@npm:6.18.0" +"@typescript-eslint/parser@npm:^6.19.0": + version: 6.19.0 + resolution: "@typescript-eslint/parser@npm:6.19.0" dependencies: - "@typescript-eslint/scope-manager": "npm:6.18.0" - "@typescript-eslint/types": "npm:6.18.0" - "@typescript-eslint/typescript-estree": "npm:6.18.0" - "@typescript-eslint/visitor-keys": "npm:6.18.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/visitor-keys": "npm:6.19.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 6798332819f839454a8405e31cfaa0fe908d5966be929bef55e78ac51a0ff3868feb42b38e7772cedf88277f6b2841b3d91f6c573eacb945e2741ecae94047c7 + checksum: 0c6280a69127cf521b3403be9877775eecda2b2e4e44a67874b0d9cf82ed95a7971dac2db633e55ec22f8026da2681137110b2924313421a22b7c03eba8cda67 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/scope-manager@npm:6.18.0" +"@typescript-eslint/scope-manager@npm:6.19.0": + version: 6.19.0 + resolution: "@typescript-eslint/scope-manager@npm:6.19.0" dependencies: - "@typescript-eslint/types": "npm:6.18.0" - "@typescript-eslint/visitor-keys": "npm:6.18.0" - checksum: c2c465e6803f78d3300142167a8a79dd2613c64cf464a40a9cf6b13a2c10c3d82ca30bb9c2d26aba7f054b8740b38e1d25f377fcdf917aba489d5b5ea2550858 + "@typescript-eslint/types": "npm:6.19.0" + "@typescript-eslint/visitor-keys": "npm:6.19.0" + checksum: d36c51c05e14c51ce13181120eeea46d1edd59ed1ff16dc4ec1f5532a975b5faec5c10a373aaa90545f82a12330c6cba18ecedc734e18288f5874855c48ba808 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/type-utils@npm:6.18.0" +"@typescript-eslint/type-utils@npm:6.19.0": + version: 6.19.0 + resolution: "@typescript-eslint/type-utils@npm:6.19.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:6.18.0" - "@typescript-eslint/utils": "npm:6.18.0" + "@typescript-eslint/typescript-estree": "npm:6.19.0" + "@typescript-eslint/utils": "npm:6.19.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.0.1" peerDependencies: @@ -1757,23 +1757,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 9f4a392fe7b7f6b1fb02acbdaa331e764775f6404c29ca66774419e39552523d878227020526ca9c438d997555a99600f8d711496e9a435fb14a779e25ed094e + checksum: f1f20ac28c03dd18546050b63ec0b0fd8c67780265ccb9ef566f16441c3de5deb2607a6046fefdebe8a43ac11fecdf0b009f8e5f70a3d15916d855be74b0f3bb languageName: node linkType: hard -"@typescript-eslint/types@npm:6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/types@npm:6.18.0" - checksum: fc507ca7a1bfec04467087165ff6722f7b9aa9a089ecf0c17656824a951b92ca014766e480122de850057c63a3066628985eb0681c5bbb80ab41d94e7bb52288 +"@typescript-eslint/types@npm:6.19.0": + version: 6.19.0 + resolution: "@typescript-eslint/types@npm:6.19.0" + checksum: 396ad2ad9f2d759dd87bc880a1ffc9d11fda04db8af9402abb4e8eccd58c01fa2d26e38b186526d0b457012f7c912e7afdab2a3798a73aa0ae34abaf50d617ae languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.18.0" +"@typescript-eslint/typescript-estree@npm:6.19.0": + version: 6.19.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.19.0" dependencies: - "@typescript-eslint/types": "npm:6.18.0" - "@typescript-eslint/visitor-keys": "npm:6.18.0" + "@typescript-eslint/types": "npm:6.19.0" + "@typescript-eslint/visitor-keys": "npm:6.19.0" 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: b65392e944baba97ed98e99a1e7122b7b05fa0d9a082b48d0190b377ae9e2ae4ed72d505a2f0f05f2ca78908f0e4b0f1acd44d345c7f4f4415fcec6bb2c57791 + checksum: 06e24bb145a302299a6cf86b36652bd4d7080c4e88517ebc24bdc137c57425a68db256ba628ce16b568bfec8020ae2a748ccee93e304efeded329cb3292b17bf languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/utils@npm:6.18.0" +"@typescript-eslint/utils@npm:6.19.0": + version: 6.19.0 + resolution: "@typescript-eslint/utils@npm:6.19.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.18.0" - "@typescript-eslint/types": "npm:6.18.0" - "@typescript-eslint/typescript-estree": "npm:6.18.0" + "@typescript-eslint/scope-manager": "npm:6.19.0" + "@typescript-eslint/types": "npm:6.19.0" + "@typescript-eslint/typescript-estree": "npm:6.19.0" semver: "npm:^7.5.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: f91798069e337ed42b7e415aabded833d540dab9adf66ae88183003428892584946f20a5496aae2dc65fc0f65b66496baed785a3470ee782b6e2dd25b9200c6c + checksum: 4080c36331204ffef9f218e29f43da767f17551fa4d3877c3d3b49194f7c7382dd9ae2124e7b5ebd47d5556946bb6ad195b47d7d215553efabacdebf81b9e74d languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.18.0": - version: 6.18.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.18.0" +"@typescript-eslint/visitor-keys@npm:6.19.0": + version: 6.19.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.19.0" dependencies: - "@typescript-eslint/types": "npm:6.18.0" + "@typescript-eslint/types": "npm:6.19.0" eslint-visitor-keys: "npm:^3.4.1" - checksum: bf34a357549d515607c761f385b7c7c82aaa07795cada0be2e1e3860c5103fbf731408ac07eaeb0517b51426d77ef9b194dfb94f205c776107a46e0d0027b452 + checksum: 8d51c0b8d94c5df044fde958f62741cef55be97c6a3a16c47e4df9af7b2ff13aa1ee03ca5240777481dca53f3b7a9b00b329e50aff5e3ad829d96bc5f63ca2c3 languageName: node linkType: hard @@ -1825,24 +1825,24 @@ __metadata: version: 0.0.0-use.local resolution: "EMS-ESP@workspace:." dependencies: - "@alova/adapter-xhr": "npm:^1.0.2" + "@alova/adapter-xhr": "npm:^1.0.3" "@babel/core": "npm:^7.23.7" "@emotion/react": "npm:^11.11.3" "@emotion/styled": "npm:^11.11.0" - "@mui/icons-material": "npm:^5.15.3" - "@mui/material": "npm:^5.15.3" + "@mui/icons-material": "npm:^5.15.5" + "@mui/material": "npm:^5.15.5" "@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.10.6" - "@types/react": "npm:^18.2.47" + "@types/node": "npm:^20.11.5" + "@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.18.0" - "@typescript-eslint/parser": "npm:^6.18.0" - alova: "npm:^2.16.2" + "@typescript-eslint/eslint-plugin": "npm:^6.19.0" + "@typescript-eslint/parser": "npm:^6.19.0" + alova: "npm:^2.17.0" async-validator: "npm:^4.2.5" concurrently: "npm:^8.2.2" eslint: "npm:^8.56.0" @@ -1861,21 +1861,21 @@ __metadata: lodash-es: "npm:^4.17.21" mime-types: "npm:^2.1.35" preact: "npm:^10.19.3" - prettier: "npm:^3.1.1" + prettier: "npm:^3.2.4" react: "npm:latest" react-dom: "npm:latest" react-dropzone: "npm:^14.2.3" - react-icons: "npm:^4.12.0" - react-router-dom: "npm:^6.21.1" - react-toastify: "npm:^9.1.3" + react-icons: "npm:^5.0.1" + react-router-dom: "npm:^6.21.3" + react-toastify: "npm:^10.0.3" rollup-plugin-visualizer: "npm:^5.12.0" sockette: "npm:^2.0.6" - terser: "npm:^5.26.0" + terser: "npm:^5.27.0" typesafe-i18n: "npm:^5.26.2" typescript: "npm:^5.3.3" - vite: "npm:^5.0.11" + vite: "npm:^5.0.12" vite-plugin-imagemin: "npm:^0.6.1" - vite-tsconfig-paths: "npm:^4.2.3" + vite-tsconfig-paths: "npm:^4.3.1" languageName: unknown linkType: soft @@ -1944,10 +1944,10 @@ __metadata: languageName: node linkType: hard -"alova@npm:^2.16.2": - version: 2.16.2 - resolution: "alova@npm:2.16.2" - checksum: 06fafddf380d4d8e8e5dd172ebcaa0bc229c76c11b2675cfb2c0ab884a36d4818159267adb14ec7a3cbe681464793085b0386d7741e6a6a732c764b14c8783a8 +"alova@npm:^2.17.0": + version: 2.17.0 + resolution: "alova@npm:2.17.0" + checksum: ff3bda492ac7dc8665403293644736ab90d7989a8479cfb2fa7fcab8fdb6e92b755851e5bcae07f55f5a5170c66c6486f047d19efb8ca39b6b3298717c3f50d7 languageName: node linkType: hard @@ -2617,17 +2617,10 @@ __metadata: languageName: node linkType: hard -"clsx@npm:^1.1.1": - version: 1.2.1 - resolution: "clsx@npm:1.2.1" - checksum: 5ded6f61f15f1fa0350e691ccec43a28b12fb8e64c8e94715f2a937bc3722d4c3ed41d6e945c971fc4dcc2a7213a43323beaf2e1c28654af63ba70c9968a8643 - languageName: node - linkType: hard - -"clsx@npm:^2.0.0": - version: 2.0.0 - resolution: "clsx@npm:2.0.0" - checksum: 943766d1b02fee3538c871e56638d87f973fbc2d6291ce221215ea436fdecb9be97ad323f411839c2d52c45640c449b1a53fbfe7e8b3d529b4e263308b630c9a +"clsx@npm:^2.1.0": + version: 2.1.0 + resolution: "clsx@npm:2.1.0" + checksum: 2e0ce7c3b6803d74fc8147c408f88e79245583202ac14abd9691e2aebb9f312de44270b79154320d10bb7804a9197869635d1291741084826cff20820f31542b languageName: node linkType: hard @@ -7091,12 +7084,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^3.1.1": - version: 3.1.1 - resolution: "prettier@npm:3.1.1" +"prettier@npm:^3.2.4": + version: 3.2.4 + resolution: "prettier@npm:3.2.4" bin: prettier: bin/prettier.cjs - checksum: 26a249f321b97d26c04483f1bf2eeb22e082a76f4222a2c922bebdc60111691aad4ec3979610e83942e0b956058ec361d9e9c81c185172264eb6db9aa678082b + checksum: e2b735d0552501b3a7ac8bd3ba3b6de2920bb35bd4cd02d08cb9057ebe3e96d83b9a7e4b903d987b7530a50223b12c74d107c154337236ae2c68156ba1e65cd2 languageName: node linkType: hard @@ -7202,12 +7195,12 @@ __metadata: languageName: node linkType: hard -"react-icons@npm:^4.12.0": - version: 4.12.0 - resolution: "react-icons@npm:4.12.0" +"react-icons@npm:^5.0.1": + version: 5.0.1 + resolution: "react-icons@npm:5.0.1" peerDependencies: react: "*" - checksum: 5cc20509ca0b182f1e7bf42c271846c48f688c8922e2439f48728805adc93ba18476a13588cbe91ee43a2d03b2787e0dc0b5cc4b9c4e4ae3426f4464b3c1b734 + checksum: c4458c643ae32a793ddebc5fa1235c7ec051be1b131205510e8199d15a4c89221a501f95a71fa21c2da93e8dd225290e2e24bb80abd3fb85801e43009e692098 languageName: node linkType: hard @@ -7225,39 +7218,39 @@ __metadata: languageName: node linkType: hard -"react-router-dom@npm:^6.21.1": - version: 6.21.1 - resolution: "react-router-dom@npm:6.21.1" +"react-router-dom@npm:^6.21.3": + version: 6.21.3 + resolution: "react-router-dom@npm:6.21.3" dependencies: - "@remix-run/router": "npm:1.14.1" - react-router: "npm:6.21.1" + "@remix-run/router": "npm:1.14.2" + react-router: "npm:6.21.3" peerDependencies: react: ">=16.8" react-dom: ">=16.8" - checksum: 2d75bd889828fa5516ad076b44506656d826c365645e7079138cd0ef899db28a1b212f708a6c6e3b543ae11b96b2031f01201cc2fe1733dd4d9c5cbdd4d734ef + checksum: 6e23e35d02e5c83847c8e47d7912d1f6c2c42a35f2317802031bdd993a8205468138a045ff34f67fe807fe9f7dc9d0995ee05bab25aedc0bf978e620ac132815 languageName: node linkType: hard -"react-router@npm:6.21.1": - version: 6.21.1 - resolution: "react-router@npm:6.21.1" +"react-router@npm:6.21.3": + version: 6.21.3 + resolution: "react-router@npm:6.21.3" dependencies: - "@remix-run/router": "npm:1.14.1" + "@remix-run/router": "npm:1.14.2" peerDependencies: react: ">=16.8" - checksum: 1220cc75e0c915a26dde9dbb6509a8f0b0163d96e5ad591af91d9bb5a92a18401718f8d872a03d1cb366e7a6216c165a5cadd12375adf97943f37d7f5c487a90 + checksum: 3d5107cfdb440519d84e6ad6d95454e3bf41ec97677b95f7b2a7f281f8ddf191b765cf1b599ead951f3cd33ed4429f140590d74a01cfdf835dc2f812023a978a languageName: node linkType: hard -"react-toastify@npm:^9.1.3": - version: 9.1.3 - resolution: "react-toastify@npm:9.1.3" +"react-toastify@npm:^10.0.3": + version: 10.0.3 + resolution: "react-toastify@npm:10.0.3" dependencies: - clsx: "npm:^1.1.1" + clsx: "npm:^2.1.0" peerDependencies: react: ">=16" react-dom: ">=16" - checksum: 12667aa10e6cf3f74be2e3c704c2d5570dd7de66fff89ae38fbfab1122e9a9f632de1cb712fe44a9a60b8ecca7590578157cb4ca6c4e8105a8cf80936a94e181 + checksum: 3c9e9cebef41cff7ea60528d1ca01f03feed98a9bba10bd0749a17d7627fa5e4719b2f1d28dee22c9f9a66df2d9ddf906e180f3f9771607e16d96c889f1bf484 languageName: node linkType: hard @@ -8345,9 +8338,9 @@ __metadata: languageName: node linkType: hard -"terser@npm:^5.26.0": - version: 5.26.0 - resolution: "terser@npm:5.26.0" +"terser@npm:^5.27.0": + version: 5.27.0 + resolution: "terser@npm:5.27.0" dependencies: "@jridgewell/source-map": "npm:^0.3.3" acorn: "npm:^8.8.2" @@ -8355,7 +8348,7 @@ __metadata: source-map-support: "npm:~0.5.20" bin: terser: bin/terser - checksum: 0282c5c065cbfa1e725d5609b99579252bc20b83cd1d75e8ab8b46d5da2c9d0fcfc453a12624f2d2d4c1240bfa0017a90fcf1e3b88258e5842fca1b0b82be8d8 + checksum: 9b2c5cb00747dea5994034ca064fb3cc7efc1be6b79a35247662d51ab43bdbe9cbf002bbf29170b5f3bd068c811d0212e22d94acd2cf0d8562687b96f1bffc9f languageName: node linkType: hard @@ -8444,17 +8437,17 @@ __metadata: languageName: node linkType: hard -"tsconfck@npm:^2.1.0": - version: 2.1.2 - resolution: "tsconfck@npm:2.1.2" +"tsconfck@npm:^3.0.1": + version: 3.0.1 + resolution: "tsconfck@npm:3.0.1" peerDependencies: - typescript: ^4.3.5 || ^5.0.0 + typescript: ^5.0.0 peerDependenciesMeta: typescript: optional: true bin: tsconfck: bin/tsconfck.js - checksum: 61df3b03b334a25eabb0a52e67a0c8d85770c631f2739db7703af8fdd102a2ebd598f1c851cc5fc6d6a59f2497a26c845be71c934ea16d838a3ff95a885034fb + checksum: c5317404e2a809af31ad093f82365518a5856b2f342371991f729f42cab0def1b87dca8d22df3fb8c82acda7248710d4fb5030270db024c8000bc8272a3e6d58 languageName: node linkType: hard @@ -8755,25 +8748,25 @@ __metadata: languageName: node linkType: hard -"vite-tsconfig-paths@npm:^4.2.3": - version: 4.2.3 - resolution: "vite-tsconfig-paths@npm:4.2.3" +"vite-tsconfig-paths@npm:^4.3.1": + version: 4.3.1 + resolution: "vite-tsconfig-paths@npm:4.3.1" dependencies: debug: "npm:^4.1.1" globrex: "npm:^0.1.2" - tsconfck: "npm:^2.1.0" + tsconfck: "npm:^3.0.1" peerDependencies: vite: "*" peerDependenciesMeta: vite: optional: true - checksum: ba6abe5d18fc1c1e494e1f1d8a7db56445c2a40e15aadb5d47a9c66cc5372d6f69b94ff0b1e47b67659d6ecaeddebab0a9d11e40b1c3c36c0115800736a6c760 + checksum: 1432f80750f5cbe181c265eb9fc2e9fff8b25a2858f176dc0a02311e3e826333526ee9c16bb0aaaa8555a417ea944d68a2e8225181215cd9502370f913eb3f79 languageName: node linkType: hard -"vite@npm:^5.0.11": - version: 5.0.11 - resolution: "vite@npm:5.0.11" +"vite@npm:^5.0.12": + version: 5.0.12 + resolution: "vite@npm:5.0.12" dependencies: esbuild: "npm:^0.19.3" fsevents: "npm:~2.3.3" @@ -8807,7 +8800,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: f1a8fea35ed9f162d7a10fd13efb2c96637028b0a319d726aeec8b31e20e4d047272bda5df82167618e7774a520236c66f3093ed172802660aec5227814072f4 + checksum: ed0bb26a0d0c8e1dae0b70af9e36adffd7e15d80297443fe4da762596dc81570bad7f0291f590a57c1553f5e435338d8c7ffc483bd9431a95c09d9ac90665fad languageName: node linkType: hard diff --git a/lib/ArduinoJson/.clang-format b/lib/ArduinoJson/.clang-format deleted file mode 100644 index 0853a7826..000000000 --- a/lib/ArduinoJson/.clang-format +++ /dev/null @@ -1,12 +0,0 @@ -# http://clang.llvm.org/docs/ClangFormatStyleOptions.html - -BasedOnStyle: Google -Standard: c++11 -AllowShortFunctionsOnASingleLine: Empty -IncludeBlocks: Preserve -IndentPPDirectives: AfterHash -DerivePointerAlignment: false - -# Always break after if to get accurate coverage -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false diff --git a/lib/ArduinoJson/.prettierignore b/lib/ArduinoJson/.prettierignore deleted file mode 100644 index dd449725e..000000000 --- a/lib/ArduinoJson/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -*.md diff --git a/lib/ArduinoJson/CHANGELOG.md b/lib/ArduinoJson/CHANGELOG.md index 796e21bc6..e82281e20 100644 --- a/lib/ArduinoJson/CHANGELOG.md +++ b/lib/ArduinoJson/CHANGELOG.md @@ -1,6 +1,18 @@ ArduinoJson: change log ======================= +v7.0.2 (2024-01-19) +------ + +* Fix assertion `poolIndex < count_` after `JsonDocument::clear()` (issue #2034) + +v7.0.1 (2024-01-10) +------ + +* Fix "no matching function" with `JsonObjectConst::operator[]` (issue #2019) +* Remove unused files in the PlatformIO package +* Fix `volatile bool` serialized as `1` or `0` instead of `true` or `false` (issue #2029) + v7.0.0 (2024-01-03) ------ diff --git a/lib/ArduinoJson/CMakeLists.txt b/lib/ArduinoJson/CMakeLists.txt new file mode 100644 index 000000000..6efa04b3b --- /dev/null +++ b/lib/ArduinoJson/CMakeLists.txt @@ -0,0 +1,25 @@ +# ArduinoJson - https://arduinojson.org +# Copyright © 2014-2024, Benoit BLANCHON +# MIT License + +cmake_minimum_required(VERSION 3.15) + +if(ESP_PLATFORM) + # Build ArduinoJson as an ESP-IDF component + idf_component_register(INCLUDE_DIRS src) + return() +endif() + +project(ArduinoJson VERSION 7.0.2) + +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + include(CTest) +endif() + +add_subdirectory(src) + +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING) + include(extras/CompileOptions.cmake) + add_subdirectory(extras/tests) + add_subdirectory(extras/fuzzing) +endif() diff --git a/lib/ArduinoJson/CONTRIBUTING.md b/lib/ArduinoJson/CONTRIBUTING.md deleted file mode 100644 index d32a04ff1..000000000 --- a/lib/ArduinoJson/CONTRIBUTING.md +++ /dev/null @@ -1,10 +0,0 @@ -# Contribution to ArduinoJson - -First, thank you for taking the time to contribute to this project. - -You can submit changes via GitHub Pull Requests. - -Please: - -1. Update the test suite for any change of behavior -2. Use clang-format in "file" mode to format the code diff --git a/lib/ArduinoJson/README.md b/lib/ArduinoJson/README.md deleted file mode 100644 index a490af33f..000000000 --- a/lib/ArduinoJson/README.md +++ /dev/null @@ -1,155 +0,0 @@ -

- ArduinoJson -

- ---- - -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/bblanchon/ArduinoJson/ci.yml?branch=7.x&logo=github)](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A7.x) -[![Continuous Integration](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/7.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/7.x) -[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/arduinojson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) -[![Coveralls branch](https://img.shields.io/coveralls/github/bblanchon/ArduinoJson/7.x?logo=coveralls)](https://coveralls.io/github/bblanchon/ArduinoJson?branch=7.x) -[![GitHub stars](https://img.shields.io/github/stars/bblanchon/ArduinoJson?style=flat&logo=github&color=orange)](https://github.com/bblanchon/ArduinoJson/stargazers) -[![GitHub Sponsors](https://img.shields.io/github/sponsors/bblanchon?logo=github&color=orange)](https://github.com/sponsors/bblanchon) - -ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things). - -## Features - -* [JSON deserialization](https://arduinojson.org/v7/api/json/deserializejson/) - * [Optionally decodes UTF-16 escape sequences to UTF-8](https://arduinojson.org/v7/api/config/decode_unicode/) - * [Optionally supports comments in the input](https://arduinojson.org/v7/api/config/enable_comments/) - * [Optionally filters the input to keep only desired values](https://arduinojson.org/v7/api/json/deserializejson/#filtering) - * Supports single quotes as a string delimiter - * Compatible with [NDJSON](http://ndjson.org/) and [JSON Lines](https://jsonlines.org/) -* [JSON serialization](https://arduinojson.org/v7/api/json/serializejson/) - * [Can write to a buffer or a stream](https://arduinojson.org/v7/api/json/serializejson/) - * [Optionally indents the document (prettified JSON)](https://arduinojson.org/v7/api/json/serializejsonpretty/) -* [MessagePack serialization](https://arduinojson.org/v7/api/msgpack/serializemsgpack/) -* [MessagePack deserialization](https://arduinojson.org/v7/api/msgpack/deserializemsgpack/) -* Efficient - * [Twice smaller than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/) - * [Almost 10% faster than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/) - * [Consumes roughly 10% less RAM than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/) - * [Deduplicates strings](https://arduinojson.org/news/2020/08/01/version-6-16-0/) -* Versatile - * Supports [custom allocators (to use external RAM chip, for example)](https://arduinojson.org/v7/how-to/use-external-ram-on-esp32/) - * Supports [`String`](https://arduinojson.org/v7/api/config/enable_arduino_string/), [`std::string`](https://arduinojson.org/v7/api/config/enable_std_string/), and [`std::string_view`](https://arduinojson.org/v7/api/config/enable_string_view/) - * Supports [`Stream`](https://arduinojson.org/v7/api/config/enable_arduino_stream/) and [`std::istream`/`std::ostream`](https://arduinojson.org/v7/api/config/enable_std_stream/) - * Supports [Flash strings](https://arduinojson.org/v7/api/config/enable_progmem/) - * Supports [custom readers](https://arduinojson.org/v7/api/json/deserializejson/#custom-reader) and [custom writers](https://arduinojson.org/v7/api/json/serializejson/#custom-writer) - * Supports [custom converters](https://arduinojson.org/news/2021/05/04/version-6-18-0/) -* Portable - * Usable on any C++ project (not limited to Arduino) - * Compatible with C++11, C++14 and C++17 - * Support for C++98/C++03 available on [ArduinoJson 6.20.x](https://github.com/bblanchon/ArduinoJson/tree/6.20.x) - * Zero warnings with `-Wall -Wextra -pedantic` and `/W4` - * [Header-only library](https://en.wikipedia.org/wiki/Header-only) - * Works with virtually any board - * Arduino boards: [Uno](https://amzn.to/38aL2ik), [Due](https://amzn.to/36YkWi2), [Micro](https://amzn.to/35WkdwG), [Nano](https://amzn.to/2QTvwRX), [Mega](https://amzn.to/36XWhuf), [Yun](https://amzn.to/30odURc), [Leonardo](https://amzn.to/36XWjlR)... - * Espressif chips: [ESP8266](https://amzn.to/36YluV8), [ESP32](https://amzn.to/2G4pRCB) - * Lolin (WeMos) boards: [D1 mini](https://amzn.to/2QUpz7q), [D1 Mini Pro](https://amzn.to/36UsGSs)... - * Teensy boards: [4.0](https://amzn.to/30ljXGq), [3.2](https://amzn.to/2FT0EuC), [2.0](https://amzn.to/2QXUMXj) - * Particle boards: [Argon](https://amzn.to/2FQHa9X), [Boron](https://amzn.to/36WgLUd), [Electron](https://amzn.to/30vEc4k), [Photon](https://amzn.to/387F9Cd)... - * Texas Instruments boards: [MSP430](https://amzn.to/30nJWgg)... - * Soft cores: [Nios II](https://en.wikipedia.org/wiki/Nios_II)... - * Tested on all major development environments - * [Arduino IDE](https://www.arduino.cc/en/Main/Software) - * [Atmel Studio](http://www.atmel.com/microsite/atmel-studio/) - * [Atollic TrueSTUDIO](https://atollic.com/truestudio/) - * [Energia](http://energia.nu/) - * [IAR Embedded Workbench](https://www.iar.com/iar-embedded-workbench/) - * [Keil uVision](http://www.keil.com/) - * [MPLAB X IDE](http://www.microchip.com/mplab/mplab-x-ide) - * [Particle](https://www.particle.io/) - * [PlatformIO](http://platformio.org/) - * [Sloeber plugin for Eclipse](https://eclipse.baeyens.it/) - * [Visual Micro](http://www.visualmicro.com/) - * [Visual Studio](https://www.visualstudio.com/) - * [Even works with online compilers like wandbox.org](https://wandbox.org/permlink/RlZSKy17DjJ6HcdN) - * [CMake friendly](https://arduinojson.org/v7/how-to/use-arduinojson-with-cmake/) -* Well designed - * [Elegant API](http://arduinojson.org/v7/example/) - * [Thread-safe](https://en.wikipedia.org/wiki/Thread_safety) - * Self-contained (no external dependency) - * `const` friendly - * [`for` friendly](https://arduinojson.org/v7/api/jsonobject/begin_end/) - * [TMP friendly](https://en.wikipedia.org/wiki/Template_metaprogramming) - * Handles [integer overflows](https://arduinojson.org/v7/api/jsonvariant/as/#integer-overflows) -* Well tested - * [Unit test coverage close to 100%](https://coveralls.io/github/bblanchon/ArduinoJson?branch=7.x) - * Continuously tested on - * [Visual Studio 2017, 2019, 2022](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/7.x) - * [GCC 5, 6, 7, 8, 9, 10, 11, 12](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22) - * [Clang 3.9, 4.0, 5.0, 6.0, 7, 8, 9, 10, 11, 12, 13, 14, 15](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22) - * [Continuously fuzzed with Google OSS Fuzz](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) - * Passes all default checks of [clang-tidy](https://releases.llvm.org/10.0.0/tools/clang/tools/extra/docs/clang-tidy/) -* Well documented - * [Tutorials](https://arduinojson.org/v7/doc/deserialization/) - * [Examples](https://arduinojson.org/v7/example/) - * [How-tos](https://arduinojson.org/v7/example/) - * [FAQ](https://arduinojson.org/v7/faq/) - * [Troubleshooter](https://arduinojson.org/v7/troubleshooter/) - * [Book](https://arduinojson.org/book/) - * [Changelog](CHANGELOG.md) -* Vibrant user community - * Most popular of all Arduino libraries on [GitHub](https://github.com/search?o=desc&q=arduino+library&s=stars&type=Repositories) - * [Used in hundreds of projects](https://www.hackster.io/search?i=projects&q=arduinojson) - * [Responsive support](https://github.com/bblanchon/ArduinoJson/issues?q=is%3Aissue+is%3Aclosed) - -## Quickstart - -### Deserialization - -Here is a program that parses a JSON document with ArduinoJson. - -```c++ -const char* json = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}"; - -JsonDocument doc; -deserializeJson(doc, json); - -const char* sensor = doc["sensor"]; -long time = doc["time"]; -double latitude = doc["data"][0]; -double longitude = doc["data"][1]; -``` - -See the [tutorial on arduinojson.org](https://arduinojson.org/v7/doc/deserialization/) - -### Serialization - -Here is a program that generates a JSON document with ArduinoJson: - -```c++ -JsonDocument doc; - -doc["sensor"] = "gps"; -doc["time"] = 1351824120; -doc["data"][0] = 48.756080; -doc["data"][1] = 2.302038; - -serializeJson(doc, Serial); -// This prints: -// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]} -``` - -See the [tutorial on arduinojson.org](https://arduinojson.org/v7/doc/serialization/) - -## Sponsors - -ArduinoJson is thankful to its sponsors. Please give them a visit; they deserve it! - -

- - Programming Electronics Academy - -

-

- - 1technophile - -

- -If you run a commercial project that embeds ArduinoJson, think about [sponsoring the library's development](https://github.com/sponsors/bblanchon): it ensures the code that your products rely on stays actively maintained. It can also give your project some exposure to the makers' community. - -If you are an individual user and want to support the development (or give a sign of appreciation), consider purchasing the book [Mastering ArduinoJson](https://arduinojson.org/book/) ❤, or simply [cast a star](https://github.com/bblanchon/ArduinoJson/stargazers) ⭐. diff --git a/lib/ArduinoJson/SUPPORT.md b/lib/ArduinoJson/SUPPORT.md deleted file mode 100644 index c47e1b1ba..000000000 --- a/lib/ArduinoJson/SUPPORT.md +++ /dev/null @@ -1,27 +0,0 @@ -# ArduinoJson Support - -First off, thank you very much for using ArduinoJson. - -We'll be very happy to help you, but first please read the following. - -## Before asking for help - -1. Read the [FAQ](https://arduinojson.org/faq/?utm_source=github&utm_medium=support) -2. Search in the [API Reference](https://arduinojson.org/api/?utm_source=github&utm_medium=support) - -If you did not find the answer, please create a [new issue on GitHub](https://github.com/bblanchon/ArduinoJson/issues/new). - -It is OK to add a comment to a currently opened issue, but please avoid adding comments to a closed issue. - -## Before hitting the Submit button - -Please provide all the relevant information: - -* Good title -* Short description of the problem -* Target platform -* Compiler model and version -* [MVCE](https://stackoverflow.com/help/mcve) -* Compiler output - -Good questions get fast answers! diff --git a/lib/ArduinoJson/idf_component.yml b/lib/ArduinoJson/idf_component.yml new file mode 100644 index 000000000..429d37339 --- /dev/null +++ b/lib/ArduinoJson/idf_component.yml @@ -0,0 +1,13 @@ +version: "7.0.2" +description: >- + A simple and efficient JSON library for embedded C++. + ⭐ 6444 stars on GitHub! + Supports serialization, deserialization, MessagePack, streams, filtering, and more. + Fully tested and documented. +url: https://arduinojson.org/ +files: + exclude: + - "**/.vs/**/*" + - ".devcontainer/**/*" + - "examples/**/*" + - "extras/**/*" diff --git a/lib/ArduinoJson/library.json b/lib/ArduinoJson/library.json new file mode 100644 index 000000000..46f156ac4 --- /dev/null +++ b/lib/ArduinoJson/library.json @@ -0,0 +1,23 @@ +{ + "name": "ArduinoJson", + "keywords": "json, rest, http, web", + "description": "A simple and efficient JSON library for embedded C++. ⭐ 6444 stars on GitHub! Supports serialization, deserialization, MessagePack, streams, filtering, and more. Fully tested and documented.", + "homepage": "https://arduinojson.org/?utm_source=meta&utm_medium=library.json", + "repository": { + "type": "git", + "url": "https://github.com/bblanchon/ArduinoJson.git" + }, + "version": "7.0.2", + "authors": { + "name": "Benoit Blanchon", + "url": "https://blog.benoitblanchon.fr" + }, + "export": { + "include": ["src", "examples", "LICENSE.txt", "ArduinoJson.h"] + }, + "frameworks": "*", + "platforms": "*", + "build": { + "libArchive": false + } +} diff --git a/lib/ArduinoJson/library.properties b/lib/ArduinoJson/library.properties new file mode 100644 index 000000000..e9d9c2c7d --- /dev/null +++ b/lib/ArduinoJson/library.properties @@ -0,0 +1,11 @@ +name=ArduinoJson +version=7.0.2 +author=Benoit Blanchon +maintainer=Benoit Blanchon +sentence=A simple and efficient JSON library for embedded C++. +paragraph=⭐ 6444 stars on GitHub! Supports serialization, deserialization, MessagePack, streams, filtering, and more. Fully tested and documented. +category=Data Processing +url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties +architectures=* +repository=https://github.com/bblanchon/ArduinoJson.git +license=MIT diff --git a/lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayConst.hpp b/lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayConst.hpp index e988e8621..526975a24 100644 --- a/lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayConst.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Array/JsonArrayConst.hpp @@ -51,7 +51,7 @@ class JsonArrayConst : public detail::VariantOperators { } operator JsonVariantConst() const { - return JsonVariantConst(collectionToVariant(data_), resources_); + return JsonVariantConst(getData(), resources_); } // Returns true if the reference is unbound. @@ -69,7 +69,7 @@ class JsonArrayConst : public detail::VariantOperators { // Returns the depth (nesting level) of the array. // https://arduinojson.org/v7/api/jsonarrayconst/nesting/ FORCE_INLINE size_t nesting() const { - return detail::VariantData::nesting(collectionToVariant(data_), resources_); + return detail::VariantData::nesting(getData(), resources_); } // Returns the number of elements in the array. diff --git a/lib/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp b/lib/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp index bc4a226da..d2daf97ad 100644 --- a/lib/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Document/JsonDocument.hpp @@ -65,7 +65,7 @@ class JsonDocument : public detail::VariantOperators { } // Reduces the capacity of the memory pool to match the current usage. - // https://arduinojson.org/v7/api/JsonDocument/shrinktofit/ + // https://arduinojson.org/v7/api/jsondocument/shrinktofit/ void shrinkToFit() { resources_.shrinkToFit(); } diff --git a/lib/ArduinoJson/src/ArduinoJson/Memory/VariantPoolList.hpp b/lib/ArduinoJson/src/ArduinoJson/Memory/VariantPoolList.hpp index 49a05d3b8..8ee5cef68 100644 --- a/lib/ArduinoJson/src/ArduinoJson/Memory/VariantPoolList.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Memory/VariantPoolList.hpp @@ -103,6 +103,7 @@ class VariantPoolList { for (PoolCount i = 0; i < count_; i++) pools_[i].destroy(allocator); count_ = 0; + freeList_ = NULL_SLOT; if (pools_ != preallocatedPools_) { allocator->deallocate(pools_); pools_ = preallocatedPools_; diff --git a/lib/ArduinoJson/src/ArduinoJson/Object/JsonObjectConst.hpp b/lib/ArduinoJson/src/ArduinoJson/Object/JsonObjectConst.hpp index 641db6cf2..8f2c8bb10 100644 --- a/lib/ArduinoJson/src/ArduinoJson/Object/JsonObjectConst.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Object/JsonObjectConst.hpp @@ -27,7 +27,7 @@ class JsonObjectConst : public detail::VariantOperators { : data_(data), resources_(resources) {} operator JsonVariantConst() const { - return JsonVariantConst(collectionToVariant(data_), resources_); + return JsonVariantConst(getData(), resources_); } // Returns true if the reference is unbound. @@ -45,7 +45,7 @@ class JsonObjectConst : public detail::VariantOperators { // Returns the depth (nesting level) of the object. // https://arduinojson.org/v7/api/jsonobjectconst/nesting/ FORCE_INLINE size_t nesting() const { - return detail::VariantData::nesting(collectionToVariant(data_), resources_); + return detail::VariantData::nesting(getData(), resources_); } // Returns the number of members in the object. @@ -101,8 +101,9 @@ class JsonObjectConst : public detail::VariantOperators { FORCE_INLINE typename detail::enable_if::value, JsonVariantConst>::type operator[](TChar* key) const { - return JsonVariantConst( - detail::ObjectData::getMember(data_, detail::adaptString(key))); + return JsonVariantConst(detail::ObjectData::getMember( + data_, detail::adaptString(key), resources_), + resources_); } // DEPRECATED: always returns zero diff --git a/lib/ArduinoJson/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp b/lib/ArduinoJson/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp index b28ede074..89e0edecf 100644 --- a/lib/ArduinoJson/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Variant/VariantRefBaseImpl.hpp @@ -132,7 +132,8 @@ VariantRefBase::operator[](const TString& key) const { template template inline bool VariantRefBase::set(const T& value) const { - Converter::toJson(value, getOrCreateVariant()); + Converter::type>::toJson(value, + getOrCreateVariant()); auto resources = getResourceManager(); return resources && !resources->overflowed(); } diff --git a/lib/ArduinoJson/src/ArduinoJson/version.hpp b/lib/ArduinoJson/src/ArduinoJson/version.hpp index ea3e4f26f..e41890e9f 100644 --- a/lib/ArduinoJson/src/ArduinoJson/version.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/version.hpp @@ -4,8 +4,8 @@ #pragma once -#define ARDUINOJSON_VERSION "7.0.0" +#define ARDUINOJSON_VERSION "7.0.2" #define ARDUINOJSON_VERSION_MAJOR 7 #define ARDUINOJSON_VERSION_MINOR 0 -#define ARDUINOJSON_VERSION_REVISION 0 -#define ARDUINOJSON_VERSION_MACRO V700 +#define ARDUINOJSON_VERSION_REVISION 2 +#define ARDUINOJSON_VERSION_MACRO V702 diff --git a/lib/ESPAsyncWebServer/AsyncJson.h b/lib/ESPAsyncWebServer/AsyncJson.h index 64f9643ef..f005f6ea5 100644 --- a/lib/ESPAsyncWebServer/AsyncJson.h +++ b/lib/ESPAsyncWebServer/AsyncJson.h @@ -70,7 +70,7 @@ class MsgpackAsyncJsonResponse : public AsyncAbstractResponse { ~MsgpackAsyncJsonResponse() { } - JsonVariant & getRoot() { + JsonVariant getRoot() { return _root; } bool _sourceValid() const { @@ -114,7 +114,7 @@ class AsyncJsonResponse : public AsyncAbstractResponse { ~AsyncJsonResponse() { } - JsonVariant & getRoot() { + JsonVariant getRoot() { return _root; } bool _sourceValid() const { @@ -158,7 +158,7 @@ class PrettyAsyncJsonResponse : public AsyncJsonResponse { } }; -typedef std::function ArJsonRequestHandlerFunction; +typedef std::function ArJsonRequestHandlerFunction; class AsyncCallbackJsonWebHandler : public AsyncWebHandler { private: diff --git a/lib/framework/AuthenticationService.cpp b/lib/framework/AuthenticationService.cpp index 005065a94..fd316a87c 100644 --- a/lib/framework/AuthenticationService.cpp +++ b/lib/framework/AuthenticationService.cpp @@ -25,7 +25,7 @@ void AuthenticationService::verifyAuthorization(AsyncWebServerRequest * request) * Signs in a user if the username and password match. Provides a JWT to be used in the Authorization header in * subsequent requests. */ -void AuthenticationService::signIn(AsyncWebServerRequest * request, JsonVariant & json) { +void AuthenticationService::signIn(AsyncWebServerRequest * request, JsonVariant json) { if (json.is()) { String username = json["username"]; String password = json["password"]; diff --git a/lib/framework/AuthenticationService.h b/lib/framework/AuthenticationService.h index 60ed100b6..d8a823485 100644 --- a/lib/framework/AuthenticationService.h +++ b/lib/framework/AuthenticationService.h @@ -21,7 +21,7 @@ class AuthenticationService { AsyncCallbackJsonWebHandler _signInHandler; // endpoint functions - void signIn(AsyncWebServerRequest * request, JsonVariant & json); + void signIn(AsyncWebServerRequest * request, JsonVariant json); void verifyAuthorization(AsyncWebServerRequest * request); }; diff --git a/lib/framework/ESP8266React.cpp b/lib/framework/ESP8266React.cpp index 158e5640d..d182dafa7 100644 --- a/lib/framework/ESP8266React.cpp +++ b/lib/framework/ESP8266React.cpp @@ -54,7 +54,7 @@ void ESP8266React::begin() { DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "Accept, Content-Type, Authorization"); DefaultHeaders::Instance().addHeader("Access-Control-Allow-Credentials", "true"); } - DefaultHeaders::Instance().addHeader("Server", networkSettings.hostname); // TODO use hostname + DefaultHeaders::Instance().addHeader("Server", networkSettings.hostname); }); _apSettingsService.begin(); _ntpSettingsService.begin(); diff --git a/lib/framework/HttpEndpoint.h b/lib/framework/HttpEndpoint.h index 794cbe225..3c1902583 100644 --- a/lib/framework/HttpEndpoint.h +++ b/lib/framework/HttpEndpoint.h @@ -13,77 +13,48 @@ using namespace std::placeholders; // for `_1` etc template -class HttpGetEndpoint { - public: - HttpGetEndpoint(JsonStateReader stateReader, - StatefulService * statefulService, - AsyncWebServer * server, - const String & servicePath, - SecurityManager * securityManager, - AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN) - : _stateReader(stateReader) - , _statefulService(statefulService) { - server->on(servicePath.c_str(), HTTP_GET, securityManager->wrapRequest(std::bind(&HttpGetEndpoint::fetchSettings, this, _1), authenticationPredicate)); - } - - HttpGetEndpoint(JsonStateReader stateReader, StatefulService * statefulService, AsyncWebServer * server, const String & servicePath) - : _stateReader(stateReader) - , _statefulService(statefulService) { - server->on(servicePath.c_str(), HTTP_GET, std::bind(&HttpGetEndpoint::fetchSettings, this, _1)); - } - +class HttpEndpoint { protected: JsonStateReader _stateReader; + JsonStateUpdater _stateUpdater; StatefulService * _statefulService; - void fetchSettings(AsyncWebServerRequest * request) { - AsyncJsonResponse * response = new AsyncJsonResponse(false); - JsonObject jsonObject = response->getRoot().to(); - _statefulService->read(jsonObject, _stateReader); + AsyncCallbackWebHandler * GEThandler; + AsyncCallbackJsonWebHandler * POSThandler; - response->setLength(); - request->send(response); - } -}; - -template -class HttpPostEndpoint { public: - HttpPostEndpoint(JsonStateReader stateReader, - JsonStateUpdater stateUpdater, - StatefulService * statefulService, - AsyncWebServer * server, - const String & servicePath, - SecurityManager * securityManager, - AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN) + HttpEndpoint(JsonStateReader stateReader, + JsonStateUpdater stateUpdater, + StatefulService * statefulService, + AsyncWebServer * server, + const String & servicePath, + SecurityManager * securityManager, + AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN) : _stateReader(stateReader) , _stateUpdater(stateUpdater) - , _statefulService(statefulService) - , _updateHandler(servicePath, securityManager->wrapCallback(std::bind(&HttpPostEndpoint::updateSettings, this, _1, _2), authenticationPredicate)) { - _updateHandler.setMethod(HTTP_POST); - server->addHandler(&_updateHandler); - } + , _statefulService(statefulService) { + // Create the GET and POST endpoints + // We can't use HTTP_ANY and process one a single endpoint due to the way the ESPAsyncWebServer library works + // Could also use server->on() but this is more efficient - HttpPostEndpoint(JsonStateReader stateReader, - JsonStateUpdater stateUpdater, - StatefulService * statefulService, - AsyncWebServer * server, - const String & servicePath) - : _stateReader(stateReader) - , _stateUpdater(stateUpdater) - , _statefulService(statefulService) - , _updateHandler(servicePath, std::bind(&HttpPostEndpoint::updateSettings, this, _1, _2)) { - _updateHandler.setMethod(HTTP_POST); - server->addHandler(&_updateHandler); + // create the GET + GEThandler = new AsyncCallbackWebHandler(); + GEThandler->setUri(servicePath); + GEThandler->setMethod(HTTP_GET); + GEThandler->onRequest(securityManager->wrapRequest(std::bind(&HttpEndpoint::fetchSettings, this, _1), authenticationPredicate)); + server->addHandler(GEThandler); + + // create the POST + POSThandler = + new AsyncCallbackJsonWebHandler(servicePath, + securityManager->wrapCallback(std::bind(&HttpEndpoint::updateSettings, this, _1, _2), authenticationPredicate)); + POSThandler->setMethod(HTTP_POST); + server->addHandler(POSThandler); } protected: - JsonStateReader _stateReader; - JsonStateUpdater _stateUpdater; - StatefulService * _statefulService; - AsyncCallbackJsonWebHandler _updateHandler; - - void updateSettings(AsyncWebServerRequest * request, JsonVariant & json) { + // for POST + void updateSettings(AsyncWebServerRequest * request, JsonVariant json) { if (!json.is()) { request->send(400); return; @@ -105,29 +76,15 @@ class HttpPostEndpoint { response->setLength(); request->send(response); } -}; -template -class HttpEndpoint : public HttpGetEndpoint, public HttpPostEndpoint { - public: - HttpEndpoint(JsonStateReader stateReader, - JsonStateUpdater stateUpdater, - StatefulService * statefulService, - AsyncWebServer * server, - const String & servicePath, - SecurityManager * securityManager, - AuthenticationPredicate authenticationPredicate = AuthenticationPredicates::IS_ADMIN) - : HttpGetEndpoint(stateReader, statefulService, server, servicePath, securityManager, authenticationPredicate) - , HttpPostEndpoint(stateReader, stateUpdater, statefulService, server, servicePath, securityManager, authenticationPredicate) { - } + // for GET + void fetchSettings(AsyncWebServerRequest * request) { + AsyncJsonResponse * response = new AsyncJsonResponse(false); + JsonObject jsonObject = response->getRoot().to(); + _statefulService->read(jsonObject, _stateReader); - HttpEndpoint(JsonStateReader stateReader, - JsonStateUpdater stateUpdater, - StatefulService * statefulService, - AsyncWebServer * server, - const String & servicePath) - : HttpGetEndpoint(stateReader, statefulService, server, servicePath) - , HttpPostEndpoint(stateReader, stateUpdater, statefulService, server, servicePath) { + response->setLength(); + request->send(response); } }; diff --git a/lib/framework/NTPSettingsService.cpp b/lib/framework/NTPSettingsService.cpp index 751de6751..e1a4aa1c5 100644 --- a/lib/framework/NTPSettingsService.cpp +++ b/lib/framework/NTPSettingsService.cpp @@ -61,7 +61,7 @@ void NTPSettingsService::configureNTP() { } } -void NTPSettingsService::configureTime(AsyncWebServerRequest * request, JsonVariant & json) { +void NTPSettingsService::configureTime(AsyncWebServerRequest * request, JsonVariant json) { if (json.is()) { struct tm tm = {0}; String timeLocal = json["local_time"]; diff --git a/lib/framework/NTPSettingsService.h b/lib/framework/NTPSettingsService.h index ab00b36d7..e18800fa1 100644 --- a/lib/framework/NTPSettingsService.h +++ b/lib/framework/NTPSettingsService.h @@ -67,7 +67,7 @@ class NTPSettingsService : public StatefulService { bool connected_ = false; void WiFiEvent(WiFiEvent_t event); void configureNTP(); - void configureTime(AsyncWebServerRequest * request, JsonVariant & json); + void configureTime(AsyncWebServerRequest * request, JsonVariant json); }; #endif diff --git a/lib/framework/SecuritySettingsService.cpp b/lib/framework/SecuritySettingsService.cpp index f17f5f4f1..9b5ab85c6 100644 --- a/lib/framework/SecuritySettingsService.cpp +++ b/lib/framework/SecuritySettingsService.cpp @@ -101,7 +101,7 @@ ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFu } ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate) { - return [this, onRequest, predicate](AsyncWebServerRequest * request, JsonVariant & json) { + return [this, onRequest, predicate](AsyncWebServerRequest * request, JsonVariant json) { Authentication authentication = authenticateRequest(request); if (!predicate(authentication)) { request->send(401); diff --git a/lib_standalone/AsyncJson.h b/lib_standalone/AsyncJson.h index 858b17082..6ab5a5c35 100644 --- a/lib_standalone/AsyncJson.h +++ b/lib_standalone/AsyncJson.h @@ -59,7 +59,7 @@ class PrettyAsyncJsonResponse { ~PrettyAsyncJsonResponse() { } - JsonVariant & getRoot() { + JsonVariant getRoot() { return _root; } @@ -104,7 +104,7 @@ class MsgpackAsyncJsonResponse { ~MsgpackAsyncJsonResponse() { } - JsonVariant & getRoot() { + JsonVariant getRoot() { return _root; } @@ -150,7 +150,7 @@ class AsyncJsonResponse { ~AsyncJsonResponse() { } - JsonVariant & getRoot() { + JsonVariant getRoot() { return _root; } @@ -177,7 +177,7 @@ class AsyncJsonResponse { } }; -typedef std::function ArJsonRequestHandlerFunction; +typedef std::function ArJsonRequestHandlerFunction; class AsyncCallbackJsonWebHandler : public AsyncWebHandler { private: diff --git a/lib_standalone/HttpEndpoint.h b/lib_standalone/HttpEndpoint.h index c1cbaa535..e3fae9ba0 100644 --- a/lib_standalone/HttpEndpoint.h +++ b/lib_standalone/HttpEndpoint.h @@ -67,7 +67,7 @@ class HttpPostEndpoint { JsonStateUpdater _stateUpdater; StatefulService * _statefulService; - void updateSettings(AsyncWebServerRequest * request, JsonVariant & json) { + void updateSettings(AsyncWebServerRequest * request, JsonVariant json) { if (!json.is()) { return; } diff --git a/lib_standalone/SecuritySettingsService.cpp b/lib_standalone/SecuritySettingsService.cpp index dc5f3860c..7cc393418 100644 --- a/lib_standalone/SecuritySettingsService.cpp +++ b/lib_standalone/SecuritySettingsService.cpp @@ -100,7 +100,7 @@ ArRequestHandlerFunction SecuritySettingsService::wrapRequest(ArRequestHandlerFu } ArJsonRequestHandlerFunction SecuritySettingsService::wrapCallback(ArJsonRequestHandlerFunction onRequest, AuthenticationPredicate predicate) { - return [this, onRequest, predicate](AsyncWebServerRequest * request, JsonVariant & json) { + return [this, onRequest, predicate](AsyncWebServerRequest * request, JsonVariant json) { Authentication authentication = authenticateRequest(request); if (!predicate(authentication)) { request->send(401); diff --git a/mock-api/Handler.ts b/mock-api/Handler.ts index caf7b73e1..08d26b876 100644 --- a/mock-api/Handler.ts +++ b/mock-api/Handler.ts @@ -414,28 +414,35 @@ const signin = { }; const generate_token = { token: '1234' }; +// // EMS-ESP Project specific +// const EMSESP_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'settings'; const EMSESP_CORE_DATA_ENDPOINT = REST_ENDPOINT_ROOT + 'coreData'; const EMSESP_SENSOR_DATA_ENDPOINT = REST_ENDPOINT_ROOT + 'sensorData'; const EMSESP_DEVICES_ENDPOINT = REST_ENDPOINT_ROOT + 'devices'; const EMSESP_SCANDEVICES_ENDPOINT = REST_ENDPOINT_ROOT + 'scanDevices'; - // const EMSESP_DEVICEDATA_ENDPOINT = REST_ENDPOINT_ROOT + 'deviceData/:id'; // const EMSESP_DEVICEENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'deviceEntities/:id'; - const EMSESP_DEVICEDATA_ENDPOINT = REST_ENDPOINT_ROOT + 'deviceData'; const EMSESP_DEVICEENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'deviceEntities'; - const EMSESP_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'status'; const EMSESP_BOARDPROFILE_ENDPOINT = REST_ENDPOINT_ROOT + 'boardProfile'; -const EMSESP_WRITE_VALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeDeviceValue'; -const EMSESP_WRITE_SENSOR_ENDPOINT = REST_ENDPOINT_ROOT + 'writeTemperatureSensor'; -const EMSESP_WRITE_ANALOG_ENDPOINT = REST_ENDPOINT_ROOT + 'writeAnalogSensor'; +const EMSESP_WRITE_DEVICEVALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeDeviceValue'; +const EMSESP_WRITE_TEMPSENSOR_ENDPOINT = REST_ENDPOINT_ROOT + 'writeTemperatureSensor'; +const EMSESP_WRITE_ANALOGSENSOR_ENDPOINT = REST_ENDPOINT_ROOT + 'writeAnalogSensor'; const EMSESP_CUSTOMIZATION_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'customizationEntities'; const EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'resetCustomizations'; -const EMSESP_WRITE_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule'; -const EMSESP_WRITE_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'entities'; + +const EMSESP_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule'; +const EMSESP_CUSTOMENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'customEntities'; + +const EMSESP_GET_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'getSettings'; +const EMSESP_GET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'getCustomizations'; +const EMSESP_GET_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'getEntities'; +const EMSESP_GET_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'getSchedule'; + +const EMSESP_SYSTEM_INFO_ENDPOINT = API_ENDPOINT_ROOT + 'system/info'; const emsesp_info = { System: { @@ -566,7 +573,7 @@ const emsesp_allvalues = { 'date/time': '10.12.2023 13:49', 'hc1 how hot lounge should be': 19, 'hc1 current room temp': 19.5, - 'hc1 Discovery current room temperature': 'roomTemp', + 'hc1 mqtt discovery current room temperature': 'roomTemp', 'hc1 mode': 'auto', 'hc1 manual temperature': 21.5, 'hc1 temperature when mode is off': 7, @@ -742,7 +749,7 @@ const emsesp_coredata = { d: 1, p: 1, v: '', - e: 1 + e: 2 } ] }; @@ -788,7 +795,7 @@ const status = { // 1 - RC35 thermo // 2 - RC20 thermo // 3 - Buderus GB125 boiler -// 4 - RC100 themo +// 4 - RC100 thermostat // 5 - Mixer MM10 // 6 - Solar SM10 // 7 - Nefit Trendline boiler @@ -2048,6 +2055,11 @@ const emsesp_devicedata_99 = { u: 1, id: '00boiler_flowtemp', c: 'boiler_flowtemp' + }, + { + v: 0, + u: 0, + id: '00wwExtra1' } ] }; @@ -2058,6 +2070,7 @@ let emsesp_customentities = { entities: [ { id: 0, + ram: 0, device_id: 8, type_id: 24, offset: 0, @@ -2065,7 +2078,21 @@ let emsesp_customentities = { name: 'boiler_flowtemp', uom: 1, value_type: 1, - writeable: true + writeable: true, + value: 30 + }, + { + id: 1, + ram: 0, + device_id: 16, + type_id: 797, + offset: 0, + factor: 1, + name: 'wwExtra1', + uom: 0, + value_type: 0, + writeable: false, + value: 0 } ] }; @@ -2345,6 +2372,7 @@ router // SYSTEM router .get(SYSTEM_STATUS_ENDPOINT, () => new Response(JSON.stringify(system_status), { headers })) + .get(SECURITY_SETTINGS_ENDPOINT, () => new Response(JSON.stringify(security_settings), { headers })) .post(SECURITY_SETTINGS_ENDPOINT, async (request: any) => { security_settings = await request.json(); return new Response('OK', { status: 200 }); @@ -2458,15 +2486,16 @@ router // EMS-ESP Project stuff // router - .post(EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT, async (request: any) => { - return new Response('OK', { status: 200 }); - }) + + // EMS-ESP Settings .get(EMSESP_SETTINGS_ENDPOINT, () => new Response(JSON.stringify(settings), { headers })) .post(EMSESP_SETTINGS_ENDPOINT, async (request: any) => { settings = await request.json(); return new Response('OK', { status: 200 }); // no restart needed // return new Response('OK', { status: 205 }); // restart needed }) + + // Device Dashboard Data .get(EMSESP_CORE_DATA_ENDPOINT, () => new Response(JSON.stringify(emsesp_coredata), { headers })) .get(EMSESP_SENSOR_DATA_ENDPOINT, () => new Response(JSON.stringify(emsesp_sensordata), { headers })) .get(EMSESP_DEVICES_ENDPOINT, () => new Response(JSON.stringify(emsesp_devices), { headers })) @@ -2527,6 +2556,8 @@ router return new Response(encoder.encode(emsesp_deviceentities_7), { headers }); } }) + + // Customization .post(EMSESP_CUSTOMIZATION_ENTITIES_ENDPOINT, async (request: any) => { const content = await request.json(); const id = content.id; @@ -2549,17 +2580,28 @@ router } return new Response('OK', { status: 200 }); }) - .post(EMSESP_WRITE_SCHEDULE_ENDPOINT, async (request: any) => { + .post(EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT, async (request: any) => { + return new Response('OK', { status: 200 }); + }) + + // Scheduler + .post(EMSESP_SCHEDULE_ENDPOINT, async (request: any) => { const content = await request.json(); emsesp_schedule = content; return new Response('OK', { status: 200 }); }) - .post(EMSESP_WRITE_ENTITIES_ENDPOINT, async (request: any) => { + .get(EMSESP_SCHEDULE_ENDPOINT, () => new Response(JSON.stringify(emsesp_schedule), { headers })) + + // Custom Entities + .post(EMSESP_CUSTOMENTITIES_ENDPOINT, async (request: any) => { const content = await request.json(); emsesp_customentities = content; return new Response('OK', { status: 200 }); }) - .post(EMSESP_WRITE_VALUE_ENDPOINT, async (request: any) => { + .get(EMSESP_CUSTOMENTITIES_ENDPOINT, () => new Response(JSON.stringify(emsesp_customentities), { headers })) + + // Device Dashboard + .post(EMSESP_WRITE_DEVICEVALUE_ENDPOINT, async (request: any) => { const content = await request.json(); const command = content.c; const value = content.v; @@ -2603,7 +2645,9 @@ router await delay(1000); // wait to show spinner return new Response('OK', { status: 200 }); // or 400 for bad request }) - .post(EMSESP_WRITE_SENSOR_ENDPOINT, async (request: any) => { + + // Temperature & Analog Sensors + .post(EMSESP_WRITE_TEMPSENSOR_ENDPOINT, async (request: any) => { const ts = await request.json(); var objIndex = emsesp_sensordata.ts.findIndex((obj) => obj.id == ts.id_str); if (objIndex !== -1) { @@ -2612,7 +2656,7 @@ router } return new Response('OK', { status: 200 }); }) - .post(EMSESP_WRITE_ANALOG_ENDPOINT, async (request: any) => { + .post(EMSESP_WRITE_ANALOGSENSOR_ENDPOINT, async (request: any) => { const as = await request.json(); var objIndex = emsesp_sensordata.as.findIndex((obj) => obj.g == as.gpio); if (objIndex === -1) { @@ -2645,6 +2689,8 @@ router return new Response('OK', { status: 200 }); }) + + // Settings - board profile .post(EMSESP_BOARDPROFILE_ENDPOINT, async (request: any) => { const content = await request.json(); const board_profile = content.code; @@ -2774,26 +2820,18 @@ router } return new Response(JSON.stringify(data), { headers }); - }); + }) -// API and calls -const SYSTEM_INFO_ENDPOINT = API_ENDPOINT_ROOT + 'system/info'; -const GET_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'getSettings'; -const GET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'getCustomizations'; -const GET_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'getEntities'; -const GET_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'getSchedule'; -const SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule'; -const ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'customentities'; + // Download Settings + .get(EMSESP_GET_SETTINGS_ENDPOINT, () => new Response(JSON.stringify(emsesp_info), { headers })) + .get(EMSESP_GET_CUSTOMIZATIONS_ENDPOINT, () => new Response(JSON.stringify(emsesp_deviceentities_1), { headers })) + .get(EMSESP_GET_ENTITIES_ENDPOINT, () => new Response(JSON.stringify(emsesp_customentities), { headers })) + .get(EMSESP_GET_SCHEDULE_ENDPOINT, () => new Response(JSON.stringify(emsesp_schedule), { headers })); +// API which are usually POST for security router - .post(SYSTEM_INFO_ENDPOINT, () => new Response(JSON.stringify(emsesp_info), { headers })) - .get(SYSTEM_INFO_ENDPOINT, () => new Response(JSON.stringify(emsesp_info), { headers })) - .get(GET_SETTINGS_ENDPOINT, () => new Response(JSON.stringify(emsesp_info), { headers })) - .get(GET_CUSTOMIZATIONS_ENDPOINT, () => new Response(JSON.stringify(emsesp_deviceentities_1), { headers })) - .get(GET_ENTITIES_ENDPOINT, () => new Response(JSON.stringify(emsesp_customentities), { headers })) - .get(GET_SCHEDULE_ENDPOINT, () => new Response(JSON.stringify(emsesp_schedule), { headers })) - .get(SCHEDULE_ENDPOINT, () => new Response(JSON.stringify(emsesp_schedule), { headers })) - .get(ENTITIES_ENDPOINT, () => new Response(JSON.stringify(emsesp_customentities), { headers })) + .post(EMSESP_SYSTEM_INFO_ENDPOINT, () => new Response(JSON.stringify(emsesp_info), { headers })) + .get(EMSESP_SYSTEM_INFO_ENDPOINT, () => new Response(JSON.stringify(emsesp_info), { headers })) .post(API_ENDPOINT_ROOT, async (request: any) => { const data = await request.json(); if (data.device === 'system') { @@ -2807,7 +2845,9 @@ router return new Response('Not Found', { status: 404 }); }); +// // Event Source // TODO fix event source later +// // const data = { // t: '000+00:00:00.000', diff --git a/mock-api/package.json b/mock-api/package.json index 6b06a70f5..de5e4f285 100644 --- a/mock-api/package.json +++ b/mock-api/package.json @@ -11,7 +11,7 @@ "dependencies": { "@msgpack/msgpack": "^2.8.0", "busboy": "^1.6.0", - "itty-router": "^4.0.26" + "itty-router": "^4.0.27" }, "packageManager": "yarn@4.0.2", "devDependencies": { diff --git a/mock-api/yarn.lock b/mock-api/yarn.lock index 6c2454a51..8d3e1278c 100644 --- a/mock-api/yarn.lock +++ b/mock-api/yarn.lock @@ -129,7 +129,7 @@ __metadata: "@msgpack/msgpack": "npm:^2.8.0" "@types/multer": "npm:^1.4.11" busboy: "npm:^1.6.0" - itty-router: "npm:^4.0.26" + itty-router: "npm:^4.0.27" languageName: unknown linkType: soft @@ -142,10 +142,10 @@ __metadata: languageName: node linkType: hard -"itty-router@npm:^4.0.26": - version: 4.0.26 - resolution: "itty-router@npm:4.0.26" - checksum: 6bd64bdd89a3508e7dd806fafcd86e0887daf306a83149d34c12443de0e518da83f76598f02caff375120aae8e40eae2234c9885e0bb3c3aaa0273a807eb4dd2 +"itty-router@npm:^4.0.27": + version: 4.0.27 + resolution: "itty-router@npm:4.0.27" + checksum: ebb959388b1033f3d80ba2575c2d90fa649c1d5370d977879513cc46e8fd78159b7140d2a66853af6be98f7d740f8609a2c5aa7381506eaa1f1a46268fd2a95f languageName: node linkType: hard diff --git a/pio_local.ini_example b/pio_local.ini_example index 6ac2a6cb1..77c68f171 100644 --- a/pio_local.ini_example +++ b/pio_local.ini_example @@ -20,7 +20,7 @@ ; default_envs = lolin_s3 ; default_envs = standalone ; default_envs = debug -default_envs = custom +; default_envs = custom [env:esp32_4M] ; if using OTA enter your details below @@ -29,16 +29,19 @@ default_envs = custom ; --port=8266 ; --auth=ems-esp-neo ; upload_port = ems-esp.local -; for USB use one of these: +; for USB, here are some examples: ; upload_port = /dev/ttyUSB* ; upload_port = COM5 +extra_scripts = +; pre:scripts/build_interface.py ; comment out if you don't want to re-build the WebUI each time + scripts/rename_fw.py [env:esp32_16M] [env:custom] -; use for ESP-S boards with 4MB flash +; use for baisc ESP boards with 4MB flash ; make sure -D TASMOTA_SDK is also enabled -platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.03/platform-espressif32-2023.10.03.zip +platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.00/platform-espressif32.zip ; use for S3 boards: ; platform = espressif32 framework = arduino @@ -68,13 +71,13 @@ build_flags = -D EMSESP_TEST -D EMSESP_DEBUG -D CONFIG_ETH_ENABLED - ; -D TASMOTA_SDK + -D TASMOTA_SDK '-DEMSESP_DEFAULT_BOARD_PROFILE="Test"' [env:lolin_s3] -upload_port = /dev/ttyACM0 +upload_port = /dev/ttyUSB0 extra_scripts = - pre:scripts/build_interface.py ; comment out if you don't want to re-build the WebUI each time +; pre:scripts/build_interface.py ; comment out if you don't want to re-build the WebUI each time scripts/rename_fw.py ; pio run -e debug diff --git a/platformio.ini b/platformio.ini index be35b8abb..0b38c7e00 100644 --- a/platformio.ini +++ b/platformio.ini @@ -2,8 +2,8 @@ ; override any settings with your own local ones in pio_local.ini [platformio] -; default_envs = esp32_4M -default_envs = lolin_s3 +default_envs = esp32_4M +; default_envs = lolin_s3 ; default_envs = esp32_16M ; default_envs = standalone @@ -50,11 +50,9 @@ extra_scripts = [espressi32_base_tasmota] ; use Tasmota's libary which removes some libs (like mbedtsl) and increases available heap ; platform = https://github.com/tasmota/platform-espressif32.git ; latest development -; latest release with WiFi_secure.h -platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.10.03/platform-espressif32-2023.10.03.zip ; latest stable -; latest arduino 2.xx release: -; platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.11.01/platform-espressif32.zip -; latest arduino 3.0/IDF 5.1.(alpha 3): +; latest release with WiFi_secure.h, Arduino 2.0.14 +platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.00/platform-espressif32.zip +; latest Arduino 3.0/IDF 5.1.(alpha 3): ; platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.12.10/platform-espressif32.zip framework = arduino board_build.filesystem = littlefs diff --git a/scripts/bootloader.bin b/scripts/bootloader.bin new file mode 100644 index 000000000..01419bff9 Binary files /dev/null and b/scripts/bootloader.bin differ diff --git a/scripts/bootloader_dio_40m.bin b/scripts/bootloader_dio_40m.bin deleted file mode 100755 index 3314163fc..000000000 Binary files a/scripts/bootloader_dio_40m.bin and /dev/null differ diff --git a/src/analogsensor.cpp b/src/analogsensor.cpp index fcb051839..fce90371d 100644 --- a/src/analogsensor.cpp +++ b/src/analogsensor.cpp @@ -679,7 +679,7 @@ bool AnalogSensor::get_value_info(JsonObject output, const char * cmd, const int // if we're filtering on an attribute, go find it if (attribute_s) { if (output.containsKey(attribute_s)) { - JsonVariant data = output[attribute_s]; + String data = output[attribute_s].as(); output.clear(); output["api_data"] = data; return true; diff --git a/src/console.cpp b/src/console.cpp index 0947bebef..9d2748d96 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -128,14 +128,16 @@ static void setup_commands(std::shared_ptr & commands) { commands->add_command(ShellContext::MAIN, CommandFlags::USER, string_vector{"test"}, - string_vector{F_(name_optional), F_(data_optional)}, + string_vector{F_(name_optional), F_(data_optional), F_(id_optional)}, [=](Shell & shell, const std::vector & arguments) { if (arguments.empty()) { Test::run_test(shell, "default"); } else if (arguments.size() == 1) { Test::run_test(shell, arguments.front()); - } else { + } else if (arguments.size() == 2) { Test::run_test(shell, arguments[0].c_str(), arguments[1].c_str()); + } else { + Test::run_test(shell, arguments[0].c_str(), arguments[1].c_str(), arguments[2].c_str()); } }); commands->add_command(ShellContext::MAIN, CommandFlags::USER, string_vector{"t"}, [=](Shell & shell, const std::vector & arguments) { @@ -531,15 +533,8 @@ static void setup_commands(std::shared_ptr & commands) { if (return_code == CommandRet::OK && json.size()) { if (json.containsKey("api_data")) { - JsonVariant data = json["api_data"]; - if (data.is()) { - shell.printfln("%d", data.as()); - } else if (data.is()) { - char s[10]; - shell.println(Helpers::render_value(s, data.as(), 1)); - } else { - shell.println(data.as()); - } + String data = json["api_data"].as(); + shell.println(data.c_str()); return; } serializeJsonPretty(doc, shell); @@ -568,9 +563,9 @@ static void setup_commands(std::shared_ptr & commands) { } return devices_list; } else if (current_arguments.size() == 1) { - std::vector command_list; - uint8_t device_type = EMSdevice::device_name_2_device_type(current_arguments[0].c_str()); + uint8_t device_type = EMSdevice::device_name_2_device_type(current_arguments[0].c_str()); if (Command::device_has_commands(device_type)) { + std::vector command_list; for (const auto & cf : Command::commands()) { if (cf.device_type_ == device_type) { command_list.emplace_back(cf.cmd_); diff --git a/src/devices/boiler.cpp b/src/devices/boiler.cpp index 7c7610fbe..b1011bb96 100644 --- a/src/devices/boiler.cpp +++ b/src/devices/boiler.cpp @@ -482,6 +482,15 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const FL_(hpMaxPower), DeviceValueUOM::PERCENT, MAKE_CF_CB(set_hpMaxPower)); + register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, + &hpSetDiffPress_, + DeviceValueType::UINT, + DeviceValueNumOp::DV_NUMOP_MUL50, + FL_(hpSetDiffPress), + DeviceValueUOM::MBAR, + MAKE_CF_CB(set_hpDiffPress), + 150, + 750); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &hpCompOn_, DeviceValueType::BOOL, FL_(hpCompOn), DeviceValueUOM::NONE); register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &hpActivity_, DeviceValueType::ENUM, FL_(enum_hpactivity), FL_(hpActivity), DeviceValueUOM::NONE); // register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &hpHeatingOn_, DeviceValueType::BOOL, FL_(hpHeatingOn), DeviceValueUOM::NONE); @@ -1935,6 +1944,10 @@ void Boiler::process_HpMeters(std::shared_ptr telegram) { has_update(telegram, meterHeat_, 24); } +void Boiler::process_HpPressure(std::shared_ptr telegram) { + has_update(telegram, hpSetDiffPress_, 9); +} + // HIU unit // boiler(0x08) -B-> All(0x00), ?(0x0779), data: 06 05 01 01 AD 02 EF FF FF 00 00 7F FF @@ -2939,6 +2952,15 @@ bool Boiler::set_hpMaxPower(const char * value, const int8_t id) { return false; } +bool Boiler::set_hpDiffPress(const char * value, const int8_t id) { + int v; + if (Helpers::value2number(value, v)) { + write_command(0x2CC, 9, (uint8_t)(v / 50), 0x2CC); + return true; + } + return false; +} + bool Boiler::set_vp_cooling(const char * value, const int8_t id) { bool v; if (Helpers::value2bool(value, v)) { diff --git a/src/devices/boiler.h b/src/devices/boiler.h index 93007917f..106764a72 100644 --- a/src/devices/boiler.h +++ b/src/devices/boiler.h @@ -223,6 +223,7 @@ class Boiler : public EMSdevice { uint32_t meterHeat_; uint8_t hpEA0_; uint8_t hpPumpMode_; + uint8_t hpSetDiffPress_; // Pool unit int8_t poolSetTemp_; @@ -334,6 +335,7 @@ class Boiler : public EMSdevice { void process_HpPool(std::shared_ptr telegram); void process_HpInput(std::shared_ptr telegram); void process_HpInConfig(std::shared_ptr telegram); + void process_HpPressure(std::shared_ptr telegram); void process_HpCooling(std::shared_ptr telegram); void process_HpHeaterConfig(std::shared_ptr telegram); void process_HybridHp(std::shared_ptr telegram); @@ -437,6 +439,7 @@ class Boiler : public EMSdevice { bool set_hpCircPumpWw(const char * value, const int8_t id); bool set_hpPumpMode(const char * value, const int8_t id); bool set_hpMaxPower(const char * value, const int8_t id); + bool set_hpDiffPress(const char * value, const int8_t id); bool set_auxLimit(const char * value, const int8_t id); inline bool set_auxMaxLimit(const char * value, const int8_t id) { diff --git a/src/devices/mixer.cpp b/src/devices/mixer.cpp index a05fa4a2f..5d25e0664 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 + 0x02CD, "MMPLUSSetMessage_HC", false, MAKE_PF_CB(process_MMPLUSSetMessage_HC)); + register_telegram_type((device_id - 0x20) * 2 + 0x02CC, "MMPLUSSetMessage_HC", false, 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); @@ -151,7 +151,7 @@ void Mixer::process_MMConfigMessage(std::shared_ptr telegram) { has_update(telegram, setValveTime_, 1); // valve runtime in 10 sec, max 120 s } -// Mixer Setting 0x2CD +// Mixer Setting 0x2CC void Mixer::process_MMPLUSSetMessage_HC(std::shared_ptr telegram) { has_update(telegram, activated_, 0); // on = 0xFF has_update(telegram, setValveTime_, 1); // valve runtime in 10 sec, max 120 s @@ -241,7 +241,7 @@ bool Mixer::set_activated(const char * value, const int8_t id) { } if (flags() == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { uint8_t hc = device_id() - 0x20; - write_command(0x2CD + hc, 0, b ? 0xFF : 0, 0x2CD + hc); + write_command(0x2CC + hc * 2, 0, b ? 0xFF : 0, 0x2CC + hc * 2); return true; } return false; @@ -260,7 +260,7 @@ bool Mixer::set_setValveTime(const char * value, const int8_t id) { if (flags() == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { v = (v + 5) / 10; uint8_t hc = device_id() - 0x20; - write_command(0x2CD + hc, 1, v, 0x2CD + hc); + write_command(0x2CC + hc * 2, 1, v, 0x2CC + hc * 2); return true; } return false; @@ -273,7 +273,7 @@ bool Mixer::set_flowTempOffset(const char * value, const int8_t id) { } if (flags() == EMSdevice::EMS_DEVICE_FLAG_MMPLUS) { uint8_t hc = device_id() - 0x20; - write_command(0x2CD + hc, 2, v, 0x2CD + hc); + write_command(0x2CC + hc * 2, 2, v, 0x2CC + hc * 2); return true; } return false; diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 3dce345a2..f492d0593 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -583,6 +583,7 @@ void EMSdevice::add_device_value(uint8_t tag, // to b } } }); + if (ignore) { return; } @@ -943,11 +944,10 @@ void EMSdevice::generate_values_web(JsonObject output) { auto mask = Helpers::hextoa((uint8_t)(dv.state >> 4), false); // create mask to a 2-char string // add name, prefixing the tag if it exists. This is the id used in the WebUI table and must be unique - if (dv.has_tag()) { - obj["id"] = mask + tag_to_string(dv.tag) + " " + fullname; - } else { - obj["id"] = mask + fullname; - } + 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 + // obj["id"] = dv.has_tag() ? mask + fullname + " " + tag_to_string(dv.tag) : mask + fullname; // suffix tag // add commands and options if (dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY)) { @@ -1001,7 +1001,7 @@ void EMSdevice::generate_values_web(JsonObject output) { // as generate_values_web() but stripped down to only show all entities and their state // this is used only for WebCustomizationService::device_entities() -void EMSdevice::generate_values_web_customization(JsonArray & output) { +void EMSdevice::generate_values_web_customization(JsonArray output) { for (auto & dv : devicevalues_) { // also show commands and entities that have an empty full name JsonObject obj = output.add(); @@ -1058,13 +1058,10 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) { auto fullname = Helpers::translated_word(dv.fullname); if (dv.type != DeviceValueType::CMD) { if (fullname) { - if (dv.has_tag()) { - char name[50]; - snprintf(name, sizeof(name), "%s %s", tag_to_string(dv.tag), fullname); - obj["n"] = name; - } else { - obj["n"] = 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 + // obj["n"] = (dv.has_tag()) ? fullname + " " + tag_to_string(dv.tag) : fullname; // suffix tag } // add the custom name, is optional @@ -1409,13 +1406,10 @@ bool EMSdevice::get_value_info(JsonObject output, const char * cmd, const int8_t auto fullname = dv.get_fullname(); if (!fullname.empty()) { - if (dv.has_tag()) { - char name[50]; - snprintf(name, sizeof(name), "%s %s", tag_to_string(dv.tag), fullname.c_str()); - json["fullname"] = name; - } else { - json["fullname"] = fullname; - } + 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 + json["fullname"] = dv.has_tag() ? std::string(tag_to_string(dv.tag)) + " " + fullname.c_str() : fullname; // prefix tag } if (dv.tag != DeviceValueTAG::TAG_NONE) { @@ -1549,7 +1543,7 @@ bool EMSdevice::get_value_info(JsonObject output, const char * cmd, const int8_t EMSESP::logger().debug("Attribute '%s'", attribute_s); #endif if (json.containsKey(attribute_s)) { - JsonVariant data = json[attribute_s]; + String data = json[attribute_s].as(); output.clear(); output["api_data"] = data; return true; @@ -1610,16 +1604,20 @@ bool EMSdevice::generate_values(JsonObject output, const uint8_t tag_filter, con char name[80]; if (output_target == OUTPUT_TARGET::API_VERBOSE || output_target == OUTPUT_TARGET::CONSOLE) { - char short_name[20]; - if (output_target == OUTPUT_TARGET::CONSOLE) { - snprintf(short_name, sizeof(short_name), " (%s)", dv.short_name); - } else { - strcpy(short_name, ""); - } + // char short_name[20]; + // if (output_target == OUTPUT_TARGET::CONSOLE) { + // snprintf(short_name, sizeof(short_name), "(%s)", dv.short_name); + // } else { + // strcpy(short_name, ""); + // } + + // add tag if (have_tag) { - snprintf(name, sizeof(name), "%s %s%s", tag_to_string(dv.tag), fullname.c_str(), short_name); // prefix the 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 + // 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(), short_name); + snprintf(name, sizeof(name), "%s (%s)", fullname.c_str(), dv.short_name); } } else { strlcpy(name, (dv.short_name), sizeof(name)); // use short name diff --git a/src/emsdevice.h b/src/emsdevice.h index 06c3edaec..3e881cff5 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -222,7 +222,7 @@ class EMSdevice { enum OUTPUT_TARGET : uint8_t { API_VERBOSE, API_SHORTNAMES, MQTT, CONSOLE }; bool generate_values(JsonObject output, const uint8_t tag_filter, const bool nested, const uint8_t output_target); void generate_values_web(JsonObject output); - void generate_values_web_customization(JsonArray & output); + void generate_values_web_customization(JsonArray output); void add_device_value(uint8_t tag, void * value_p, diff --git a/src/emsdevicevalue.cpp b/src/emsdevicevalue.cpp index a6604c075..867811c34 100644 --- a/src/emsdevicevalue.cpp +++ b/src/emsdevicevalue.cpp @@ -110,7 +110,7 @@ const char * DeviceValue::DeviceValueUOM_s[] = { F_(uom_blank), // 0 F_(uom_degrees), F_(uom_degrees), F_(uom_percent), F_(uom_lmin), F_(uom_kwh), F_(uom_wh), FL_(hours)[0], FL_(minutes)[0], F_(uom_ua), F_(uom_bar), F_(uom_kw), F_(uom_w), F_(uom_kb), FL_(seconds)[0], F_(uom_dbm), F_(uom_fahrenheit), F_(uom_mv), F_(uom_sqm), - F_(uom_m3), F_(uom_l), F_(uom_kmin), F_(uom_k), F_(uom_volts), F_(uom_blank) + F_(uom_m3), F_(uom_l), F_(uom_kmin), F_(uom_k), F_(uom_volts), F_(uom_mbar), F_(uom_blank) }; diff --git a/src/emsdevicevalue.h b/src/emsdevicevalue.h index d99d0dc5b..f7f458b28 100644 --- a/src/emsdevicevalue.h +++ b/src/emsdevicevalue.h @@ -71,7 +71,8 @@ class DeviceValue { KMIN, // 21 - K*min K, // 22 - K VOLTS, // 23 - V - CONNECTIVITY // 24 - used in HA + MBAR, // 24 - mbar + CONNECTIVITY // 25 - used in HA }; // TAG mapping - maps to DeviceValueTAG_s in emsdevice.cpp @@ -143,7 +144,8 @@ class DeviceValue { DV_NUMOP_DIV100 = 100, DV_NUMOP_MUL5 = -5, DV_NUMOP_MUL10 = -10, - DV_NUMOP_MUL15 = -15 + DV_NUMOP_MUL15 = -15, + DV_NUMOP_MUL50 = -50 }; uint8_t device_type; // EMSdevice::DeviceType diff --git a/src/emsesp.cpp b/src/emsesp.cpp index 1dfe1fe79..f8005c79a 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -392,7 +392,6 @@ void EMSESP::show_device_values(uuid::console::Shell & shell) { // extract the shortname from the key, which is in brackets std::size_t first_bracket = key.find_last_of('('); std::size_t last_bracket = key.find_last_of(')'); - std::string shortname = key.substr(first_bracket + 1, last_bracket - first_bracket - 1); std::string uom = emsdevice->get_value_uom(key.substr(first_bracket + 1, last_bracket - first_bracket - 1)); shell.printfln(" %s: %s%s %s%s", key.c_str(), COLOR_BRIGHT_GREEN, p.value().as().c_str(), uom.c_str(), COLOR_RESET); @@ -705,7 +704,7 @@ bool EMSESP::get_device_value_info(JsonObject root, const char * cmd, const int8 // search for recognized device_ids : Me, All, otherwise print hex value std::string EMSESP::device_tostring(const uint8_t device_id) { - if ((device_id & 0x7F) == rxservice_.ems_bus_id()) { + if ((device_id & 0x7F) == EMSbus::ems_bus_id()) { return "Me"; } else if (device_id == 0x00) { return "All"; @@ -734,9 +733,13 @@ std::string EMSESP::pretty_telegram(std::shared_ptr telegram) { } else if (emsdevice->is_device_id(dest)) { dest_name = emsdevice->device_type_name(); } - // get the type name, any match will do + // get the type name if (type_name.empty()) { - type_name = emsdevice->telegram_type_name(telegram); + 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); + } } } } @@ -867,7 +870,7 @@ void EMSESP::process_version(std::shared_ptr telegram) { // returns false if there are none found bool EMSESP::process_telegram(std::shared_ptr telegram) { // if watching or reading... - if ((telegram->type_id == read_id_ || telegram->type_id == response_id_) && (telegram->dest == txservice_.ems_bus_id())) { + if ((telegram->type_id == read_id_ || telegram->type_id == response_id_) && (telegram->dest == EMSbus::ems_bus_id())) { if (telegram->type_id == response_id_) { if (!trace_raw_) { LOG_TRACE("%s", pretty_telegram(telegram).c_str()); @@ -896,7 +899,7 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { } // only process broadcast telegrams or ones sent to us on request - // if ((telegram->dest != 0x00) && (telegram->dest != rxservice_.ems_bus_id())) { + // if ((telegram->dest != 0x00) && (telegram->dest != EMSbus::ems_bus_id())) { if (telegram->operation == Telegram::Operation::RX_READ) { // LOG_DEBUG("read telegram received, not processing"); return false; @@ -924,13 +927,13 @@ 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)) { + 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 == txservice_.ems_bus_id())) { + || (telegram->type_id == publish_id_ && telegram->dest == EMSbus::ems_bus_id())) { if (telegram->type_id == publish_id_) { publish_id_ = 0; } @@ -947,7 +950,7 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { emsdevice->add_handlers_ignored(telegram->type_id); } break; - } else if (emsdevice->is_device_id(telegram->dest)) { + } else if (emsdevice->is_device_id(telegram->dest) && telegram->src != EMSbus::ems_bus_id()) { emsdevice->handle_telegram(telegram); } } @@ -1021,7 +1024,7 @@ void EMSESP::show_devices(uuid::console::Shell & shell) { // if its not in our database, we don't add it bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const char * version, const uint8_t brand) { // don't add ourselves! - if (device_id == rxservice_.ems_bus_id()) { + if (device_id == EMSbus::ems_bus_id()) { return false; } @@ -1062,7 +1065,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const device_p = &device; break; } - if ((device_id >= EMSdevice::EMS_DEVICE_ID_HS1 && device_id <= EMSdevice::EMS_DEVICE_ID_HS16)) { + if (device_id >= EMSdevice::EMS_DEVICE_ID_HS1 && device_id <= EMSdevice::EMS_DEVICE_ID_HS16) { device_p = &device; device_p->device_type = DeviceType::HEATSOURCE; break; @@ -1265,7 +1268,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) { #endif // check first for echo uint8_t first_value = data[0]; - if (((first_value & 0x7F) == txservice_.ems_bus_id()) && (length > 1)) { + if (((first_value & 0x7F) == EMSbus::ems_bus_id()) && (length > 1)) { // if we ask ourself at roomcontrol for version e.g. 0B 98 02 00 20 Roomctrl::check((data[1] ^ 0x80 ^ rxservice_.ems_mask()), data, length); #ifdef EMSESP_UART_DEBUG @@ -1336,7 +1339,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) { wait_km_ = true; connect_time = uuid::get_uptime_sec(); } - if (poll_id == txservice_.ems_bus_id()) { + if (poll_id == EMSbus::ems_bus_id()) { EMSbus::last_bus_activity(uuid::get_uptime()); // set the flag indication the EMS bus is active } if (wait_km_) { diff --git a/src/locale_common.h b/src/locale_common.h index 3dafee51b..c34c30259 100644 --- a/src/locale_common.h +++ b/src/locale_common.h @@ -249,6 +249,7 @@ MAKE_WORD_CUSTOM(uom_l, "l") MAKE_WORD_CUSTOM(uom_kmin, "K*min") MAKE_WORD_CUSTOM(uom_k, "K") MAKE_WORD_CUSTOM(uom_volts, "V") +MAKE_WORD_CUSTOM(uom_mbar, "mbar") // MQTT topics and prefixes MAKE_WORD_CUSTOM(heating_active, "heating_active") diff --git a/src/locale_translations.h b/src/locale_translations.h index 14af7b898..ab982664a 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -286,7 +286,7 @@ MAKE_WORD_TRANSLATION(partymode, "party", "Party", "party", "", "impreza", "", " MAKE_WORD_TRANSLATION(fireplace, "fireplace", "Kamin", "haard", "", "kominek", "", "", "şömine", "camino", "krb") // TODO translate // MQTT Discovery - this is special device entity for 'climate' -MAKE_TRANSLATION(haclimate, "haclimate", "Discovery current room temperature", "Discovery Temperatur", "Discovery huidige kamertemperatuur", "", "termostat w HA", "HA Avlest temp", "", "Güncel osa sıcaklığı", "verifica temperatura ambiente attuale", "Zistiť aktuálnu teplotu v miestnosti") // TODO translate +MAKE_TRANSLATION(haclimate, "haclimate", "mqtt discovery current room temperature", "Discovery Temperatur", "Discovery huidige kamertemperatuur", "", "termostat w HA", "HA Avlest temp", "", "Güncel osa sıcaklığı", "verifica temperatura ambiente attuale", "Zistiť aktuálnu teplotu v miestnosti") // TODO translate // Entity translations: tag, mqtt, en, de, nl, sv, pl, no, fr, tr, it, sk // Boiler @@ -463,6 +463,7 @@ MAKE_TRANSLATION(hpPumpMode, "hppumpmode", "primary heatpump mode", "Modus Haupt MAKE_TRANSLATION(instantstart, "instantstart", "instant start", "Sofortstart", "", "", "natychmiastowy start", "", "", "", "", "") // TODO translate MAKE_TRANSLATION(heatondelay, "heatondelay", "heat-on delay", "Einschaltverzögerung Heizen", "", "", "opóźnienie włączania ogrzewania", "", "", "", "", "") // TODO translate MAKE_TRANSLATION(heatoffdelay, "heatoffdelay", "heat-off delay", "Ausschaltverzögerung Heizen", "", "", "opóźnienie włączania ogrzewania", "", "", "", "", "") // TODO translate +MAKE_TRANSLATION(hpSetDiffPress, "hpsetdiffpress", "set differental pressure", "Pumpensolldruck", "", "", "", "", "", "", "", "") // TODO translate // hybrid heatpump MAKE_TRANSLATION(hybridStrategy, "hybridstrategy", "hybrid control strategy", "Hybrid Strategie", "Hybride strategie", "Hybrid kontrollstrategi", "strategia sterowania hybrydowego", "hybrid kontrollstrategi", "stratégie contrôle hybride", "hibrit kontrol stratejisi", "strategia comtrollo ibrido", "hybridná stratégia riadenia") diff --git a/src/mqtt.cpp b/src/mqtt.cpp index d1ce1f1e0..67cbb54ba 100644 --- a/src/mqtt.cpp +++ b/src/mqtt.cpp @@ -683,12 +683,12 @@ bool Mqtt::queue_publish(const char * topic, const std::string & payload) { return queue_publish_message((topic), payload, mqtt_retain_); } -bool Mqtt::queue_publish(const char * topic, const JsonObjectConst & payload) { +bool Mqtt::queue_publish(const char * topic, const JsonObjectConst payload) { return queue_publish_retain(topic, payload, mqtt_retain_); } // publish json doc, only if its not empty -bool Mqtt::queue_publish(const std::string & topic, const JsonObjectConst & payload) { +bool Mqtt::queue_publish(const std::string & topic, const JsonObjectConst payload) { return queue_publish_retain(topic, payload, mqtt_retain_); } @@ -698,11 +698,11 @@ bool Mqtt::queue_publish_retain(const char * topic, const std::string & payload, } // publish json doc, only if its not empty, using the retain flag -bool Mqtt::queue_publish_retain(const std::string & topic, const JsonObjectConst & payload, const bool retain) { +bool Mqtt::queue_publish_retain(const std::string & topic, const JsonObjectConst payload, const bool retain) { return queue_publish_retain(topic.c_str(), payload, retain); } -bool Mqtt::queue_publish_retain(const char * topic, const JsonObjectConst & payload, const bool retain) { +bool Mqtt::queue_publish_retain(const char * topic, const JsonObjectConst payload, const bool retain) { if (payload.size()) { std::string payload_text; payload_text.reserve(measureJson(payload) + 1); @@ -722,7 +722,7 @@ bool Mqtt::queue_remove_topic(const char * topic) { } // queue a Home Assistant config topic and payload, with retain flag off. -bool Mqtt::queue_ha(const char * topic, const JsonObjectConst & payload) { +bool Mqtt::queue_ha(const char * topic, const JsonObjectConst payload) { if (!enabled()) { return false; } @@ -817,7 +817,7 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSd const int16_t dv_set_min, const uint32_t dv_set_max, const int8_t num_op, - const JsonObjectConst & dev_json) { + const JsonObjectConst dev_json) { // ignore if name (fullname) is empty if (!fullname || !en_name) { return false; diff --git a/src/mqtt.h b/src/mqtt.h index 46b3b1393..ec4ea2d9d 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -68,31 +68,31 @@ class Mqtt { static bool queue_publish(const std::string & topic, const std::string & payload); static bool queue_publish(const char * topic, const char * payload); - static bool queue_publish(const std::string & topic, const JsonObjectConst & payload); - static bool queue_publish(const char * topic, const JsonObjectConst & payload); + static bool queue_publish(const std::string & topic, const JsonObjectConst payload); + static bool queue_publish(const char * topic, const JsonObjectConst payload); static bool queue_publish(const char * topic, const std::string & payload); - static bool queue_publish_retain(const std::string & topic, const JsonObjectConst & payload, const bool retain); + static bool queue_publish_retain(const std::string & topic, const JsonObjectConst payload, const bool retain); static bool queue_publish_retain(const char * topic, const std::string & payload, const bool retain); - static bool queue_publish_retain(const char * topic, const JsonObjectConst & payload, const bool retain); - static bool queue_ha(const char * topic, const JsonObjectConst & payload); + static bool queue_publish_retain(const char * topic, const JsonObjectConst payload, const bool retain); + static bool queue_ha(const char * topic, const JsonObjectConst payload); static bool queue_remove_topic(const char * topic); static bool publish_ha_sensor_config(DeviceValue & dv, const char * model, const char * brand, const bool remove, const bool create_device_config = false); - static bool publish_ha_sensor_config(uint8_t type, - uint8_t tag, - const char * const fullname, - const char * const en_name, - const uint8_t device_type, - const char * const entity, - const uint8_t uom, - const bool remove, - const bool has_cmd, - const char * const ** options, - uint8_t options_size, - const int16_t dv_set_min, - const uint32_t dv_set_max, - const int8_t num_op, - const JsonObjectConst & dev_json); + static bool publish_ha_sensor_config(uint8_t type, + uint8_t tag, + const char * const fullname, + const char * const en_name, + const uint8_t device_type, + const char * const entity, + const uint8_t uom, + const bool remove, + const bool has_cmd, + const char * const ** options, + uint8_t options_size, + const int16_t dv_set_min, + const uint32_t dv_set_max, + const int8_t num_op, + const JsonObjectConst dev_json); static bool publish_system_ha_sensor_config(uint8_t type, const char * name, const char * entity, const uint8_t uom); static bool publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp, const bool remove = false, const int16_t min = 5, const uint32_t max = 30); @@ -168,6 +168,10 @@ class Mqtt { return entity_format_; } + static void entity_format(uint8_t n) { + entity_format_ = n; + } + static uint8_t discovery_type() { return discovery_type_; } diff --git a/src/system.cpp b/src/system.cpp index bf5102a6d..9658b146c 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -632,7 +632,7 @@ void System::send_info_mqtt() { } // create the json for heartbeat -bool System::heartbeat_json(JsonObject output) { +void System::heartbeat_json(JsonObject output) { uint8_t bus_status = EMSESP::bus_status(); if (bus_status == EMSESP::BUS_STATUS_TX_ERRORS) { output["bus_status"] = "txerror"; @@ -684,8 +684,6 @@ bool System::heartbeat_json(JsonObject output) { output["wifistrength"] = wifi_quality(rssi); } #endif - - return true; } // send periodic MQTT message with system information @@ -700,9 +698,8 @@ void System::send_heartbeat() { JsonDocument doc; JsonObject json = doc.to(); - if (heartbeat_json(json)) { - Mqtt::queue_publish(F_(heartbeat), json); // send to MQTT with retain off. This will add to MQTT queue. - } + heartbeat_json(json); + Mqtt::queue_publish(F_(heartbeat), json); // send to MQTT with retain off. This will add to MQTT queue. } // initializes network @@ -1471,7 +1468,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output #if defined(EMSESP_TEST) // run a test, e.g. http://ems-esp/api?device=system&cmd=test&data=boiler bool System::command_test(const char * value, const int8_t id) { - return Test::run_test(value, id); + return Test::test(value, id); } #endif diff --git a/src/system.h b/src/system.h index acfc11b89..ccff2ae71 100644 --- a/src/system.h +++ b/src/system.h @@ -79,7 +79,7 @@ class System { void syslog_init(); bool check_upgrade(bool factory_settings); bool check_restore(); - bool heartbeat_json(JsonObject output); + void heartbeat_json(JsonObject output); void send_heartbeat(); void send_info_mqtt(); diff --git a/src/temperaturesensor.cpp b/src/temperaturesensor.cpp index 359403736..5746885bb 100644 --- a/src/temperaturesensor.cpp +++ b/src/temperaturesensor.cpp @@ -414,8 +414,8 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons if (Helpers::toLower(command_s) == Helpers::toLower(sensor.name().c_str()) || Helpers::toLower(command_s) == Helpers::toLower(sensor.id().c_str())) { output["id"] = sensor.id(); output["name"] = sensor.name(); - char val[10]; 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)); } @@ -426,7 +426,7 @@ bool TemperatureSensor::get_value_info(JsonObject output, const char * cmd, cons // if we're filtering on an attribute, go find it if (attribute_s) { if (output.containsKey(attribute_s)) { - JsonVariant data = output[attribute_s]; + String data = output[attribute_s].as(); output.clear(); output["api_data"] = data; return true; diff --git a/src/test/test.cpp b/src/test/test.cpp index df085ca74..48af75f6f 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -1,7 +1,6 @@ - /* * EMS-ESP - https://github.com/emsesp/EMS-ESP -* Copyright 2020-2023 Paul Derbyshire + * Copyright 2020-2023 Paul Derbyshire * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,12 +24,19 @@ namespace emsesp { // no shell, called via the API or 'call system test' command // or http://ems-esp/api?device=system&cmd=test&data=boiler -bool Test::run_test(const char * command, int8_t id) { - if ((command == nullptr) || (strlen(command) == 0)) { +bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) { + if (cmd.empty()) { return false; } - if (strcmp(command, "memory") == 0) { + if (cmd == "add") { + Mqtt::entity_format(Mqtt::entityFormat::SINGLE_LONG); // SINGLE_LONG, SINGLE_SHORT, MULTI_SHORT + System::test_set_all_active(true); // include all entities and give them fake values + add_device(id1, id2); + return true; + } + + if (cmd == "memory") { EMSESP::logger().notice("Testing memory by adding lots of devices and entities..."); System::test_set_all_active(true); // include all entities and give them fake values @@ -43,7 +49,7 @@ bool Test::run_test(const char * command, int8_t id) { return true; } - if (strcmp(command, "general") == 0) { + if (cmd == "general") { EMSESP::logger().info("Testing general. Adding a Boiler and Thermostat"); // System::test_set_all_active(true); // uncomment if we want to show all entities and give them fake values @@ -77,7 +83,7 @@ bool Test::run_test(const char * command, int8_t id) { // #ifdef EMSESP_STANDALONE - if (strcmp(command, "heat_exchange") == 0) { + if (cmd == "heat_exchange") { EMSESP::logger().info("Testing heating exchange..."); add_device(0x08, 219); // Greenstar HIU/Logamax kompakt WS170 @@ -89,7 +95,7 @@ bool Test::run_test(const char * command, int8_t id) { return true; } - if (strcmp(command, "2thermostats") == 0) { + if (cmd == "2thermostats") { EMSESP::logger().info("Testing with multiple thermostats..."); add_device(0x08, 123); // GB072 @@ -121,7 +127,7 @@ bool Test::run_test(const char * command, int8_t id) { return true; } - if (strcmp(command, "310") == 0) { + if (cmd == "310") { EMSESP::logger().info("Adding a GB072/RC310 combo..."); add_device(0x08, 123); // GB072 @@ -148,7 +154,7 @@ bool Test::run_test(const char * command, int8_t id) { return true; } - if (strcmp(command, "gateway") == 0) { + if (cmd == "gateway") { EMSESP::logger().info("Adding a Gateway..."); // add 0x48 KM200, via a version command @@ -168,7 +174,7 @@ bool Test::run_test(const char * command, int8_t id) { return true; } - if (strcmp(command, "mixer") == 0) { + if (cmd == "mixer") { EMSESP::logger().info("Adding a mixer..."); // add controller @@ -190,7 +196,7 @@ bool Test::run_test(const char * command, int8_t id) { return true; } - if (strcmp(command, "boiler") == 0) { + if (cmd == "boiler") { EMSESP::logger().info("Adding boiler..."); add_device(0x08, 123); // Nefit Trendline @@ -207,7 +213,7 @@ bool Test::run_test(const char * command, int8_t id) { return true; } - if (strcmp(command, "thermostat") == 0) { + if (cmd == "thermostat") { EMSESP::logger().info("Adding thermostat..."); add_device(0x10, 192); // FW120 @@ -220,7 +226,7 @@ bool Test::run_test(const char * command, int8_t id) { return true; } - if (strcmp(command, "solar") == 0) { + if (cmd == "solar") { EMSESP::logger().info("Adding solar..."); add_device(0x30, 163); // SM100 @@ -239,7 +245,7 @@ bool Test::run_test(const char * command, int8_t id) { return true; } - if (strcmp(command, "heatpump") == 0) { + if (cmd == "heatpump") { EMSESP::logger().info("Adding heatpump..."); add_device(0x38, 200); // Enviline module @@ -258,11 +264,13 @@ bool Test::run_test(const char * command, int8_t id) { } // These next tests are run from the Consol via the test command, so inherit the Shell -void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const std::string & data) { +void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const std::string & id1_s, const std::string & id2_s) { shell.add_flags(CommandFlags::ADMIN); // switch to su // init stuff Mqtt::ha_enabled(true); + Mqtt::entity_format(Mqtt::entityFormat::SINGLE_SHORT); // SINGLE_LONG, SINGLE_SHORT, MULTI_SHORT + EMSESP::rxservice_.ems_mask(EMSbus::EMS_MASK_BUDERUS); // EMSESP::watch(EMSESP::Watch::WATCH_RAW); // raw mode @@ -275,11 +283,32 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const command = cmd; } + // extract params + int8_t id1 = -1; + int8_t id2 = -1; + if (!id1_s.empty()) { + if (id1_s[0] == '0' && id1_s[1] == 'x') { + id1 = Helpers::hextoint(id1_s.c_str()); + } else { + id1 = Helpers::atoint(id1_s.c_str()); + } + } + if (!id2_s.empty()) { + id2 = Helpers::atoint(id2_s.c_str()); + } + bool ok = false; + if (command == "add") { + shell.printfln("Testing Adding a device (product_id %d), with all values...", id2); + test("add", id1, id2); // e.g. 8 172 + shell.invoke_command("show values"); + ok = true; + } + if (command == "general") { shell.printfln("Testing adding a boiler, thermostat and sensors..."); - run_test("general"); + test("general"); // add sensors emsesp::EMSESP::analogsensor_.test(); @@ -296,14 +325,14 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // https://github.com/emsesp/EMS-ESP32/issues/869 if (command == "memory") { shell.printfln("Testing memory by adding lots of devices and entities..."); - run_test("memory"); + test("memory"); shell.invoke_command("show values"); ok = true; } if (command == "custom_entities") { shell.printfln("custom entities..."); - run_test("general"); + test("general"); #ifdef EMSESP_STANDALONE AsyncWebServerRequest request; @@ -318,7 +347,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const if (command == "coldshot") { shell.printfln("Testing coldshot..."); - run_test("general"); + test("general"); #ifdef EMSESP_STANDALONE AsyncWebServerRequest request; @@ -370,7 +399,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const if (command == "modes") { shell.printfln("Testing thermostat modes..."); - run_test("general"); + test("general"); shell.invoke_command("call thermostat mode auto"); shell.invoke_command("call thermostat mode Manuell"); // DE shell.invoke_command("call thermostat mode 1"); @@ -506,13 +535,13 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const if (command == "gateway") { shell.printfln("Testing Gateway..."); - run_test("gateway"); + test("gateway"); ok = true; } if (command == "310") { shell.printfln("Testing RC310..."); - run_test("310"); + test("310"); shell.invoke_command("show devices"); shell.invoke_command("show values"); shell.invoke_command("call system publish"); @@ -522,7 +551,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const if (command == "heat_exchange") { shell.printfln("Testing heat exchange..."); - run_test("heat_exchange"); + test("heat_exchange"); shell.invoke_command("show devices"); shell.invoke_command("show values"); ok = true; @@ -530,7 +559,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const if (command == "2thermostats") { shell.printfln("Testing multiple thermostats..."); - run_test("2thermostats"); + test("2thermostats"); shell.invoke_command("show values"); shell.invoke_command("show devices"); ok = true; @@ -542,8 +571,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const Mqtt::enabled(false); // turn off mqtt Mqtt::ha_enabled(false); // turn off ha - run_test("boiler"); - run_test("thermostat"); + test("boiler"); + test("thermostat"); JsonDocument doc; // some absurd high number for (const auto & emsdevice : EMSESP::emsdevices) { @@ -596,7 +625,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const Mqtt::ha_enabled(true); Mqtt::nested_format(1); - run_test("boiler"); + test("boiler"); shell.invoke_command("show devices"); shell.invoke_command("show values"); shell.invoke_command("call boiler info"); @@ -622,7 +651,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const if (command == "shower_alert") { shell.printfln("Testing Shower Alert..."); - run_test("boiler"); + test("boiler"); // device type, command, data Command::call(EMSdevice::DeviceType::BOILER, "wwtapactivated", "false"); @@ -650,10 +679,10 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const Mqtt::nested_format(1); // is nested // Mqtt::nested_format(2); // not nested - run_test("boiler"); - run_test("thermostat"); - run_test("solar"); - run_test("mixer"); + test("boiler"); + test("thermostat"); + test("solar"); + test("mixer"); shell.invoke_command("call system publish"); shell.invoke_command("show mqtt"); @@ -672,8 +701,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const Mqtt::nested_format(1); // Mqtt::send_response(false); - run_test("boiler"); - // run_test("thermostat"); + test("boiler"); + // test("thermostat"); // 0xC2 // [emsesp] Boiler(0x08) -> Me(0x0B), UBAErrorMessage3(0xC2), data: 08 AC 00 10 31 48 30 31 15 80 95 0B 0E 10 38 00 7F FF FF FF 08 AC 00 10 09 41 30 @@ -692,8 +721,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const Mqtt::nested_format(1); // Mqtt::send_response(false); - run_test("boiler"); - run_test("thermostat"); + test("boiler"); + test("thermostat"); shell.invoke_command("call boiler wwseltemp"); shell.invoke_command("call system publish"); @@ -745,15 +774,13 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const } if (command == "healthcheck") { - uint8_t n = 0; - if (!data.empty()) { - n = Helpers::atoint(data.c_str()); - } - // n=1 = EMSESP::system_.HEALTHCHECK_NO_BUS // n=2 = EMSESP::system_.HEALTHCHECK_NO_NETWORK - shell.printfln("Testing healthcheck with %d", n); - EMSESP::system_.healthcheck(n); + if (id1 == -1) { + id1 = 0; + } + shell.printfln("Testing healthcheck with %d", id1); + EMSESP::system_.healthcheck(id1); ok = true; } @@ -763,7 +790,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const Mqtt::ha_enabled(true); // Mqtt::send_response(false); - run_test("thermostat"); + test("thermostat"); // shell.invoke_command("call thermostat seltemp"); // shell.invoke_command("call system publish"); @@ -794,7 +821,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const Mqtt::ha_enabled(true); // Mqtt::send_response(false); - run_test("boiler"); + test("boiler"); shell.invoke_command("call boiler wwseltemp"); shell.invoke_command("call system publish"); @@ -819,7 +846,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const Mqtt::ha_enabled(true); // Mqtt::send_response(false); - run_test("boiler"); + test("boiler"); shell.invoke_command("call boiler wwseltemp"); shell.invoke_command("call system publish"); @@ -842,8 +869,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const // EMSESP::bool_format(BOOL_FORMAT_10); // BOOL_FORMAT_10_STR EMSESP::system_.bool_format(BOOL_FORMAT_TRUEFALSE); // BOOL_FORMAT_TRUEFALSE_STR - run_test("boiler"); - run_test("thermostat"); + test("boiler"); + test("thermostat"); AsyncWebServerRequest request; JsonDocument doc; @@ -875,8 +902,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const EMSESP::system_.bool_format(BOOL_FORMAT_10); // BOOL_FORMAT_10_STR // EMSESP::bool_format(BOOL_FORMAT_TRUEFALSE); // BOOL_FORMAT_TRUEFALSE_STR - run_test("boiler"); - run_test("thermostat"); + test("boiler"); + test("thermostat"); EMSESP::mqtt_.incoming("ems-esp/boiler/wwseltemp", "59"); ok = true; @@ -887,15 +914,15 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const shell.printfln("Testing API wwmode"); Mqtt::ha_enabled(false); Mqtt::nested_format(1); - run_test("310"); + test("310"); AsyncWebServerRequest request; request.method(HTTP_POST); JsonDocument doc; JsonVariant json; - char data[] = "{\"value\":\"off\"}"; - deserializeJson(doc, data); + char odata[] = "{\"value\":\"off\"}"; + deserializeJson(doc, odata); json = doc.as(); request.url("/api/thermostat/wwmode"); EMSESP::webAPIService.webAPIService_post(&request, json); @@ -911,8 +938,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const Mqtt::nested_format(1); // Mqtt::send_response(true); - run_test("boiler"); - run_test("thermostat"); + test("boiler"); + test("thermostat"); AsyncWebServerRequest requestX; JsonDocument docX; @@ -1181,10 +1208,10 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const shell.printfln("Testing nested MQTT"); Mqtt::ha_enabled(false); // turn off HA Discovery to stop the chatter - run_test("boiler"); - run_test("thermostat"); - run_test("solar"); - run_test("mixer"); + test("boiler"); + test("thermostat"); + test("solar"); + test("mixer"); // first with nested Mqtt::nested_format(1); @@ -1201,7 +1228,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const if (command == "thermostat") { shell.printfln("Testing adding a thermostat FW120..."); - run_test("thermostat"); + test("thermostat"); shell.invoke_command("show values"); shell.invoke_command("call system publish"); @@ -1229,7 +1256,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const if (command == "solar") { shell.printfln("Testing Solar"); - run_test("solar"); + test("solar"); uart_telegram("30 00 FF 0A 02 6A 04"); // SM100 pump on (1)sh EMSESP::show_device_values(shell); @@ -1243,7 +1270,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const if (command == "heatpump") { shell.printfln("Testing Heat Pump"); - run_test("heatpump"); + test("heatpump"); shell.invoke_command("call"); shell.invoke_command("call heatpump info"); ok = true; @@ -1698,7 +1725,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const if (command == "mixer") { shell.printfln("Testing Mixer..."); - run_test("mixer"); + test("mixer"); // check for error "No telegram type handler found for ID 0x255 (src 0x20)" uart_telegram({0xA0, 0x00, 0xFF, 0x00, 0x01, 0x55, 0x00, 0x1A}); diff --git a/src/test/test.h b/src/test/test.h index b8091a0e3..83caa6e84 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -22,6 +22,7 @@ #define EMSESP_TEST_H #include "emsesp.h" + #include namespace emsesp { @@ -60,8 +61,8 @@ namespace emsesp { class Test { public: - static void run_test(uuid::console::Shell & shell, const std::string & command, const std::string & data = ""); - static bool run_test(const char * command, int8_t id = 0); + static void run_test(uuid::console::Shell & shell, const std::string & command, const std::string & id1 = "", const std::string & id2 = ""); + static bool test(const std::string & command, int8_t id1 = -1, int8_t id2 = -1); static void dummy_mqtt_commands(const char * message); static void rx_telegram(const std::vector & data); static void uart_telegram(const std::vector & rx_data); diff --git a/src/version.h b/src/version.h index 3e5b71fd4..761b8afef 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.6.5-test.8" +#define EMSESP_APP_VERSION "3.6.5-test.10" diff --git a/src/web/WebAPIService.cpp b/src/web/WebAPIService.cpp index 4dc52fa53..e2e311c01 100644 --- a/src/web/WebAPIService.cpp +++ b/src/web/WebAPIService.cpp @@ -53,7 +53,7 @@ void WebAPIService::webAPIService_get(AsyncWebServerRequest * request) { // For HTTP POSTS with an optional JSON body // HTTP_POST | HTTP_PUT | HTTP_PATCH // POST /{device}[/{hc|id}][/{name}] -void WebAPIService::webAPIService_post(AsyncWebServerRequest * request, JsonVariant & json) { +void WebAPIService::webAPIService_post(AsyncWebServerRequest * request, JsonVariant json) { // if no body then treat it as a secure GET if (!json.is()) { webAPIService_get(request); @@ -134,8 +134,8 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject input) { // if we're returning single values, just sent as plain text // https://github.com/emsesp/EMS-ESP32/issues/462#issuecomment-1093877210 if (output.containsKey("api_data")) { - JsonVariant data = output["api_data"]; - request->send(200, "text/plain; charset=utf-8", data.as()); + String data = output["api_data"].as(); + request->send(200, "text/plain; charset=utf-8", data); api_count_++; delete response; return; diff --git a/src/web/WebAPIService.h b/src/web/WebAPIService.h index a7781102d..aa8dd28cb 100644 --- a/src/web/WebAPIService.h +++ b/src/web/WebAPIService.h @@ -31,8 +31,8 @@ class WebAPIService { public: WebAPIService(AsyncWebServer * server, SecurityManager * securityManager); - void webAPIService_post(AsyncWebServerRequest * request, JsonVariant & json); // for POSTs - void webAPIService_get(AsyncWebServerRequest * request); // for GETs + void webAPIService_post(AsyncWebServerRequest * request, JsonVariant json); // for POSTs + void webAPIService_get(AsyncWebServerRequest * request); // for GETs static uint32_t api_count() { return api_count_; diff --git a/src/web/WebCustomEntityService.cpp b/src/web/WebCustomEntityService.cpp index 065ceb4f3..ea0b5ae55 100644 --- a/src/web/WebCustomEntityService.cpp +++ b/src/web/WebCustomEntityService.cpp @@ -48,6 +48,7 @@ void WebCustomEntity::read(WebCustomEntity & webEntity, JsonObject root) { for (const CustomEntityItem & entityItem : webEntity.customEntityItems) { JsonObject ei = entity.add(); ei["id"] = counter++; // id is only used to render the table and must be unique + ei["ram"] = entityItem.ram; ei["device_id"] = entityItem.device_id; ei["type_id"] = entityItem.type_id; ei["offset"] = entityItem.offset; @@ -73,7 +74,7 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web JsonDocument doc; deserializeJson(doc, json); root = doc.as(); - Serial.println(COLOR_BRIGHT_MAGENTA); + Serial.print(COLOR_BRIGHT_MAGENTA); Serial.print(" Using fake custom entity file: "); serializeJson(root, Serial); Serial.println(COLOR_RESET); @@ -88,6 +89,7 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web if (root["entities"].is()) { for (const JsonObject ei : root["entities"].as()) { auto entityItem = CustomEntityItem(); + entityItem.ram = ei["ram"] | 0; entityItem.device_id = ei["device_id"]; // send as numeric, will be converted to string in web entityItem.type_id = ei["type_id"]; entityItem.offset = ei["offset"]; @@ -96,6 +98,14 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web entityItem.uom = ei["uom"]; entityItem.value_type = ei["value_type"]; entityItem.writeable = ei["writeable"]; + entityItem.data = ei["value"].as(); + if (entityItem.ram == 1) { + entityItem.device_id = 0; + entityItem.type_id = 0; + entityItem.uom = 0; + entityItem.value_type = DeviceValueType::STRING; + entityItem.writeable = true; + } if (entityItem.value_type == DeviceValueType::BOOL) { entityItem.value = EMS_VALUE_DEFAULT_BOOL; @@ -107,7 +117,7 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web entityItem.value = EMS_VALUE_DEFAULT_SHORT; } else if (entityItem.value_type == DeviceValueType::USHORT) { entityItem.value = EMS_VALUE_DEFAULT_USHORT; - } else { // if (entityItem.value_type == DeviceValueType::ULONG || entityItem.value_type == DeviceValueType::TIME) { + } else if (entityItem.value_type == DeviceValueType::ULONG || entityItem.value_type == DeviceValueType::TIME) { entityItem.value = EMS_VALUE_DEFAULT_ULONG; } if (entityItem.factor == 0) { @@ -134,7 +144,9 @@ bool WebCustomEntityService::command_setvalue(const char * value, const std::str EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; }); for (CustomEntityItem & entityItem : *customEntityItems) { if (Helpers::toLower(entityItem.name) == Helpers::toLower(name)) { - if (entityItem.value_type == DeviceValueType::STRING) { + if (entityItem.ram == 1) { + entityItem.data = value; + } else if (entityItem.value_type == DeviceValueType::STRING) { char telegram[84]; strlcpy(telegram, value, sizeof(telegram)); uint8_t data[EMS_MAX_TELEGRAM_LENGTH]; @@ -274,7 +286,7 @@ bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd) for (const CustomEntityItem & entity : *customEntityItems) { render_value(output, entity); } - return (output.size() != 0); + return true; } char command_s[30]; @@ -297,18 +309,20 @@ bool WebCustomEntityService::get_value_info(JsonObject output, const char * cmd) output["readable"] = true; output["writeable"] = entity.writeable; output["visible"] = true; - output["device_id"] = Helpers::hextoa(entity.device_id); - output["type_id"] = Helpers::hextoa(entity.type_id); - output["offset"] = entity.offset; - if (entity.value_type != DeviceValueType::BOOL && entity.value_type != DeviceValueType::STRING) { - output["factor"] = entity.factor; - } else if (entity.value_type == DeviceValueType::STRING) { - output["bytes"] = (uint8_t)entity.factor; + if (entity.ram == 0) { + output["device_id"] = Helpers::hextoa(entity.device_id); + output["type_id"] = Helpers::hextoa(entity.type_id); + output["offset"] = entity.offset; + if (entity.value_type != DeviceValueType::BOOL && entity.value_type != DeviceValueType::STRING) { + output["factor"] = entity.factor; + } else if (entity.value_type == DeviceValueType::STRING) { + output["bytes"] = (uint8_t)entity.factor; + } } render_value(output, entity, true); if (attribute_s) { if (output.containsKey(attribute_s)) { - JsonVariant data = output[attribute_s]; + String data = output[attribute_s].as(); output.clear(); output["api_data"] = data; return true; @@ -547,10 +561,21 @@ 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) { - EMSESP::send_read_request(entity.type_id, - entity.device_id, - entity.offset, - entity.value_type == DeviceValueType::STRING ? (uint8_t)entity.factor : len[entity.value_type]); + if (entity.device_id > 0 && entity.type_id > 0) { // ths excludes also RAM type + bool needFetch = true; + for (const auto & emsdevice : EMSESP::emsdevices) { + if (entity.value_type != DeviceValueType::STRING && emsdevice->is_device_id(entity.device_id) && emsdevice->is_fetch(entity.type_id)) { + needFetch = false; + break; + } + } + if (needFetch) { + EMSESP::send_read_request(entity.type_id, + entity.device_id, + entity.offset, + entity.value_type == DeviceValueType::STRING ? (uint8_t)entity.factor : len[entity.value_type]); + } + } } // EMSESP::logger().debug("fetch custom entities"); } @@ -563,8 +588,8 @@ bool WebCustomEntityService::get_value(std::shared_ptr telegram) const uint8_t len[] = {1, 1, 1, 2, 2, 3, 3}; for (auto & entity : *customEntityItems) { if (entity.value_type == DeviceValueType::STRING && telegram->type_id == entity.type_id && telegram->src == entity.device_id - && telegram->offset == entity.offset) { - auto data = Helpers::data_to_hex(telegram->message_data, telegram->message_length); + && telegram->offset <= entity.offset && (telegram->offset + telegram->message_length) >= (entity.offset + (uint8_t)entity.factor)) { + auto data = Helpers::data_to_hex(telegram->message_data, (uint8_t)entity.factor); if (entity.data != data) { entity.data = data; if (Mqtt::publish_single()) { @@ -573,9 +598,8 @@ bool WebCustomEntityService::get_value(std::shared_ptr telegram) has_change = true; } } - } - if (entity.value_type != DeviceValueType::STRING && telegram->type_id == entity.type_id && telegram->src == entity.device_id - && telegram->offset <= entity.offset && (telegram->offset + telegram->message_length) >= (entity.offset + len[entity.value_type])) { + } else if (entity.value_type != DeviceValueType::STRING && telegram->type_id == entity.type_id && telegram->src == entity.device_id + && telegram->offset <= entity.offset && (telegram->offset + telegram->message_length) >= (entity.offset + len[entity.value_type])) { uint32_t value = 0; for (uint8_t i = 0; i < len[entity.value_type]; i++) { value = (value << 8) + telegram->message_data[i + entity.offset - telegram->offset]; diff --git a/src/web/WebCustomEntityService.h b/src/web/WebCustomEntityService.h index 568261ddc..228cd95c6 100644 --- a/src/web/WebCustomEntityService.h +++ b/src/web/WebCustomEntityService.h @@ -21,7 +21,7 @@ #define WebCustomEntityService_h #define EMSESP_CUSTOMENTITY_FILE "/config/emsespEntity.json" -#define EMSESP_CUSTOMENTITY_SERVICE_PATH "/rest/customentities" // GET and POST +#define EMSESP_CUSTOMENTITY_SERVICE_PATH "/rest/customEntities" // GET and POST namespace emsesp { @@ -38,6 +38,7 @@ class CustomEntityItem { bool writeable; uint32_t value; std::string data; + uint8_t ram; }; class WebCustomEntity { diff --git a/src/web/WebCustomizationService.cpp b/src/web/WebCustomizationService.cpp index 0b0b94200..61e9f18db 100644 --- a/src/web/WebCustomizationService.cpp +++ b/src/web/WebCustomizationService.cpp @@ -25,14 +25,7 @@ using namespace std::placeholders; // for `_1` etc bool WebCustomization::_start = true; WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager) - : _httpEndpoint(WebCustomization::read, - WebCustomization::update, - this, - server, - EMSESP_CUSTOMIZATION_SERVICE_PATH, - securityManager, - AuthenticationPredicates::IS_AUTHENTICATED) - , _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE) + : _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE) , _masked_entities_handler(CUSTOMIZATION_ENTITIES_PATH, securityManager->wrapCallback(std::bind(&WebCustomizationService::customization_entities, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED)) { @@ -85,7 +78,7 @@ void WebCustomization::read(WebCustomization & customizations, JsonObject root) entityJson["product_id"] = entityCustomization.product_id; entityJson["device_id"] = entityCustomization.device_id; - // entries are in the form [|optional customname] e.g "08heatingactive|heating is on" + // entries are in the form [optional customname] e.g "08heatingactive|heating is on" JsonArray masked_entityJson = entityJson["entity_ids"].to(); for (std::string entity_id : entityCustomization.entity_ids) { masked_entityJson.add(entity_id); @@ -103,7 +96,7 @@ StateUpdateResult WebCustomization::update(JsonObject root, WebCustomization & c JsonDocument doc; deserializeJson(doc, json); root = doc.as(); - Serial.println(COLOR_BRIGHT_MAGENTA); + Serial.print(COLOR_BRIGHT_MAGENTA); Serial.print(" Using fake customization file: "); serializeJson(root, Serial); Serial.println(COLOR_RESET); @@ -239,7 +232,7 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request) { // takes a list of updated entities with new masks from the web UI // saves it in the customization service // and updates the entity list real-time -void WebCustomizationService::customization_entities(AsyncWebServerRequest * request, JsonVariant & json) { +void WebCustomizationService::customization_entities(AsyncWebServerRequest * request, JsonVariant json) { bool need_reboot = false; if (json.is()) { // find the device using the unique_id diff --git a/src/web/WebCustomizationService.h b/src/web/WebCustomizationService.h index 40a390428..8ec322b71 100644 --- a/src/web/WebCustomizationService.h +++ b/src/web/WebCustomizationService.h @@ -23,7 +23,6 @@ // GET #define DEVICES_SERVICE_PATH "/rest/devices" -#define EMSESP_CUSTOMIZATION_SERVICE_PATH "/rest/customization" #define DEVICE_ENTITIES_PATH "/rest/deviceEntities" // POST @@ -89,7 +88,6 @@ class WebCustomizationService : public StatefulService { private: #endif - HttpEndpoint _httpEndpoint; FSPersistence _fsPersistence; // GET @@ -97,7 +95,7 @@ class WebCustomizationService : public StatefulService { void device_entities(AsyncWebServerRequest * request); // POST - void customization_entities(AsyncWebServerRequest * request, JsonVariant & json); + void customization_entities(AsyncWebServerRequest * request, JsonVariant json); void reset_customization(AsyncWebServerRequest * request); // command AsyncCallbackJsonWebHandler _masked_entities_handler; diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index 9dd41595d..f1f8ab1b4 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -227,7 +227,7 @@ void WebDataService::device_data(AsyncWebServerRequest * request) { } // assumes the service has been checked for admin authentication -void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVariant & json) { +void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVariant json) { if (json.is()) { uint8_t unique_id = json["id"]; // unique ID const char * cmd = json["c"]; // the command @@ -323,7 +323,7 @@ void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVar // takes a temperaturesensor name and optional offset from the WebUI and update the customization settings // via the temperaturesensor service -void WebDataService::write_temperature_sensor(AsyncWebServerRequest * request, JsonVariant & json) { +void WebDataService::write_temperature_sensor(AsyncWebServerRequest * request, JsonVariant json) { bool ok = false; if (json.is()) { JsonObject sensor = json; @@ -346,7 +346,7 @@ void WebDataService::write_temperature_sensor(AsyncWebServerRequest * request, J } // update the analog record, or create a new one -void WebDataService::write_analog_sensor(AsyncWebServerRequest * request, JsonVariant & json) { +void WebDataService::write_analog_sensor(AsyncWebServerRequest * request, JsonVariant json) { bool ok = false; if (json.is()) { JsonObject analog = json; diff --git a/src/web/WebDataService.h b/src/web/WebDataService.h index 68902e45d..ada443d1f 100644 --- a/src/web/WebDataService.h +++ b/src/web/WebDataService.h @@ -47,9 +47,9 @@ class WebDataService { void device_data(AsyncWebServerRequest * request); // POST - void write_device_value(AsyncWebServerRequest * request, JsonVariant & json); - void write_temperature_sensor(AsyncWebServerRequest * request, JsonVariant & json); - void write_analog_sensor(AsyncWebServerRequest * request, JsonVariant & json); + void write_device_value(AsyncWebServerRequest * request, JsonVariant json); + void write_temperature_sensor(AsyncWebServerRequest * request, JsonVariant json); + void write_analog_sensor(AsyncWebServerRequest * request, JsonVariant json); void scan_devices(AsyncWebServerRequest * request); // command AsyncCallbackJsonWebHandler _write_value_handler, _write_temperature_handler, _write_analog_handler; diff --git a/src/web/WebLogService.cpp b/src/web/WebLogService.cpp index cd8f47266..703b2d9a3 100644 --- a/src/web/WebLogService.cpp +++ b/src/web/WebLogService.cpp @@ -211,7 +211,7 @@ void WebLogService::fetchLog(AsyncWebServerRequest * request) { } // sets the values like level after a POST -void WebLogService::setValues(AsyncWebServerRequest * request, JsonVariant & json) { +void WebLogService::setValues(AsyncWebServerRequest * request, JsonVariant json) { if (!json.is()) { return; } diff --git a/src/web/WebLogService.h b/src/web/WebLogService.h index ce3630e94..083b10fdc 100644 --- a/src/web/WebLogService.h +++ b/src/web/WebLogService.h @@ -64,7 +64,7 @@ class WebLogService : public uuid::log::Handler { char * messagetime(char * out, const uint64_t t, const size_t bufsize); - void setValues(AsyncWebServerRequest * request, JsonVariant & json); + void setValues(AsyncWebServerRequest * request, JsonVariant json); AsyncCallbackJsonWebHandler setValues_; // for POSTs diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index b70612960..b7fd19d74 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -62,7 +62,7 @@ StateUpdateResult WebScheduler::update(JsonObject root, WebScheduler & webSchedu JsonDocument doc; deserializeJson(doc, json); root = doc.as(); - Serial.println(COLOR_BRIGHT_MAGENTA); + Serial.print(COLOR_BRIGHT_MAGENTA); Serial.print(" Using fake scheduler file: "); serializeJson(root, Serial); Serial.println(COLOR_RESET); @@ -177,7 +177,6 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) { attribute_s = breakp + 1; } - JsonVariant data; for (const ScheduleItem & scheduleItem : *scheduleItems) { if (Helpers::toLower(scheduleItem.name) == Helpers::toLower(command_s)) { output["name"] = scheduleItem.name; @@ -199,7 +198,7 @@ bool WebSchedulerService::get_value_info(JsonObject output, const char * cmd) { } if (attribute_s && output.containsKey(attribute_s)) { - data = output[attribute_s]; + String data = output[attribute_s].as(); output.clear(); output["api_data"] = data; }