From c578154b5eab2936bea1deeea04fee2808cf6267 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 14 Jan 2024 15:15:40 +0100 Subject: [PATCH 1/4] tidy up custom entities, add writeable icon (inspired by #1557) --- interface/src/project/Settings.tsx | 4 +- ...ntities.tsx => SettingsCustomEntities.tsx} | 14 ++- ...g.tsx => SettingsCustomEntitiesDialog.tsx} | 8 +- interface/src/project/api.ts | 4 +- mock-api/Handler.ts | 109 ++++++++++++------ 5 files changed, 90 insertions(+), 49 deletions(-) rename interface/src/project/{SettingsEntities.tsx => SettingsCustomEntities.tsx} (94%) rename interface/src/project/{SettingsEntitiesDialog.tsx => SettingsCustomEntitiesDialog.tsx} (97%) diff --git a/interface/src/project/Settings.tsx b/interface/src/project/Settings.tsx index 5a0de5b82..442c9a8f5 100644 --- a/interface/src/project/Settings.tsx +++ b/interface/src/project/Settings.tsx @@ -2,8 +2,8 @@ import { Tab } from '@mui/material'; import { Navigate, Route, Routes } from 'react-router-dom'; import SettingsApplication from './SettingsApplication'; +import SettingsCustomEntities from './SettingsCustomEntities'; import SettingsCustomization from './SettingsCustomization'; -import SettingsEntities from './SettingsEntities'; import SettingsScheduler from './SettingsScheduler'; import type { FC } from 'react'; import { RouterTabs, useRouterTab, useLayoutTitle } from 'components'; @@ -27,7 +27,7 @@ const Settings: FC = () => { } /> } /> } /> - } /> + } /> } /> diff --git a/interface/src/project/SettingsEntities.tsx b/interface/src/project/SettingsCustomEntities.tsx similarity index 94% rename from interface/src/project/SettingsEntities.tsx rename to interface/src/project/SettingsCustomEntities.tsx index 708d86513..ee176d32c 100644 --- a/interface/src/project/SettingsEntities.tsx +++ b/interface/src/project/SettingsCustomEntities.tsx @@ -1,5 +1,6 @@ import AddIcon from '@mui/icons-material/Add'; import CancelIcon from '@mui/icons-material/Cancel'; +import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; import WarningIcon from '@mui/icons-material/Warning'; import { Button, Typography, Box } from '@mui/material'; import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table'; @@ -11,7 +12,7 @@ import { useBlocker } from 'react-router-dom'; import { toast } from 'react-toastify'; -import SettingsEntitiesDialog from './SettingsEntitiesDialog'; +import SettingsCustomEntitiesDialog from './SettingsCustomEntitiesDialog'; import * as EMSESP from './api'; import { DeviceValueTypeNames, DeviceValueUOM_s } from './types'; import { entityItemValidation } from './validators'; @@ -21,7 +22,7 @@ import { ButtonRow, FormLoader, SectionContent, BlockNavigation } from 'componen import { useI18nContext } from 'i18n/i18n-react'; -const SettingsEntities: FC = () => { +const SettingsCustomEntities: FC = () => { const { LL } = useI18nContext(); const [numChanges, setNumChanges] = useState(0); const blocker = useBlocker(numChanges !== 0); @@ -219,7 +220,10 @@ const SettingsEntities: FC = () => { {tableList.map((ei: EntityItem) => ( editEntityItem(ei)}> - {ei.name} + + {ei.name}  + {ei.writeable && } + {showHex(ei.device_id as number, 2)} {showHex(ei.type_id as number, 3)} {ei.offset} @@ -244,7 +248,7 @@ const SettingsEntities: FC = () => { {renderEntity()} {selectedEntityItem && ( - { ); }; -export default SettingsEntities; +export default SettingsCustomEntities; diff --git a/interface/src/project/SettingsEntitiesDialog.tsx b/interface/src/project/SettingsCustomEntitiesDialog.tsx similarity index 97% rename from interface/src/project/SettingsEntitiesDialog.tsx rename to interface/src/project/SettingsCustomEntitiesDialog.tsx index 061eab8c5..f0516f048 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(); @@ -249,4 +249,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/mock-api/Handler.ts b/mock-api/Handler.ts index caf7b73e1..2bd443712 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: { @@ -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' } ] }; @@ -2065,7 +2077,20 @@ let emsesp_customentities = { name: 'boiler_flowtemp', uom: 1, value_type: 1, - writeable: true + writeable: true, + value: 30 + }, + { + id: 1, + device_id: 16, + type_id: 797, + offset: 0, + factor: 1, + name: 'wwExtra1', + uom: 0, + value_type: 0, + writeable: false, + value: 0 } ] }; @@ -2458,15 +2483,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 +2553,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 +2577,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 +2642,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 +2653,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 +2686,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 +2817,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 +2842,9 @@ router return new Response('Not Found', { status: 404 }); }); +// // Event Source // TODO fix event source later +// // const data = { // t: '000+00:00:00.000', From d529cbf269f92433b06d6fce090f4c9ce511c62b Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 14 Jan 2024 15:15:48 +0100 Subject: [PATCH 2/4] package update --- interface/package.json | 2 +- interface/yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/package.json b/interface/package.json index 85ef4d70e..e928aa2af 100644 --- a/interface/package.json +++ b/interface/package.json @@ -67,7 +67,7 @@ "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "preact": "^10.19.3", - "prettier": "^3.2.1", + "prettier": "^3.2.2", "rollup-plugin-visualizer": "^5.12.0", "terser": "^5.26.0", "vite": "^5.0.11", diff --git a/interface/yarn.lock b/interface/yarn.lock index 87cd2c67a..c8271d6f4 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -1861,7 +1861,7 @@ __metadata: lodash-es: "npm:^4.17.21" mime-types: "npm:^2.1.35" preact: "npm:^10.19.3" - prettier: "npm:^3.2.1" + prettier: "npm:^3.2.2" react: "npm:latest" react-dom: "npm:latest" react-dropzone: "npm:^14.2.3" @@ -7091,12 +7091,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^3.2.1": - version: 3.2.1 - resolution: "prettier@npm:3.2.1" +"prettier@npm:^3.2.2": + version: 3.2.2 + resolution: "prettier@npm:3.2.2" bin: prettier: bin/prettier.cjs - checksum: a26d26a74ba5cbf23a9741074ceef4f53a08ced03c42449dc9615ecd08ada9d19d5247ad2b0dfb15b2c8e57ec9f516074627b85b9f03270b08c184c64e7d8f64 + checksum: ab9470ff6cfd19f28bc424f22e58f2fc4a488d148b9384f6c3739235017c8350cae82b3697392c23d9b098b9d8dfaa1cc9ff4ef25fd45f54c97b95f9cc7a1f7d languageName: node linkType: hard From c55e05e7b21f014dfe02ee3e1e0f1a40452e75ca Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 14 Jan 2024 15:16:50 +0100 Subject: [PATCH 3/4] remove redundant rest call to /rest/customization --- src/web/WebCustomEntityService.h | 2 +- src/web/WebCustomizationService.cpp | 11 ++--------- src/web/WebCustomizationService.h | 2 -- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/web/WebCustomEntityService.h b/src/web/WebCustomEntityService.h index 568261ddc..ccb98afd8 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 { diff --git a/src/web/WebCustomizationService.cpp b/src/web/WebCustomizationService.cpp index 3d76626e8..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); diff --git a/src/web/WebCustomizationService.h b/src/web/WebCustomizationService.h index 1b4bc8127..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 From 77607263a9e1c2c60e675e34a735f652d0f7333d Mon Sep 17 00:00:00 2001 From: Proddy Date: Sun, 14 Jan 2024 15:22:07 +0100 Subject: [PATCH 4/4] 3.6.5-dev.9 --- CHANGELOG_LATEST.md | 3 ++- src/version.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index 02cc02507..992863508 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -24,8 +24,9 @@ - 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 - 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.1 diff --git a/src/version.h b/src/version.h index 3b890a031..e6a41a3b6 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.6.5-dev.8" +#define EMSESP_APP_VERSION "3.6.5-dev.9"