From ff075a4f5611dfdace394f115db19992e2d0daca Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 16:18:56 +0200 Subject: [PATCH 01/15] use m for mask instead of x --- mock-api/server.js | 186 ++++++++++++++++++++++----------------------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/mock-api/server.js b/mock-api/server.js index e8aa0ee4d..22b414d00 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -302,7 +302,7 @@ const EMSESP_BOARDPROFILE_ENDPOINT = REST_ENDPOINT_ROOT + 'boardProfile' const EMSESP_WRITE_VALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeValue' const EMSESP_WRITE_SENSOR_ENDPOINT = REST_ENDPOINT_ROOT + 'writeSensor' const EMSESP_WRITE_ANALOG_ENDPOINT = REST_ENDPOINT_ROOT + 'writeAnalog' -const EMSESP_EXCLUDE_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'excludeEntities' +const EMSESP_MASKED_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'maskedEntities' const EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'resetCustomizations' settings = { @@ -574,21 +574,21 @@ const emsesp_devicedata_4 = { u: 1, n: 'hc2 selected room temperature', c: 'hc2/seltemp', - x: false, + m: 0, }, { v: 18.6, u: 1, n: 'hc2 current room temperature', c: '', - x: true, + m: 7, }, { v: 'off', u: 0, n: 'hc2 mode', c: 'hc2/mode', - x: true, + m: 7, }, ], } @@ -598,119 +598,119 @@ const emsesp_deviceentities_1 = [ v: '(0)', n: 'error code', s: 'errorcode', - x: false, + m: 0, i: 1, }, { v: '14:54:39 06/06/2021', n: 'date/time', s: 'datetime', - x: false, + m: 0, i: 2, }, { v: 18.22, n: 'hc1 selected room temperature', s: 'hc1/seltemp', - x: false, + m: 0, i: 3, }, { v: 22.6, n: 'hc1 current room temperature', s: 'hc1/curtemp', - x: false, + m: 0, i: 4, }, { v: 'auto', n: 'hc1 mode', s: 'hc1/mode', - x: false, + m: 0, i: 5, }, ] const emsesp_deviceentities_2 = [ - { v: false, n: 'heating active', s: 'heatingactive', x: false, i: 1 }, - { v: false, n: 'tapwater active', s: 'tapwateractive', x: false, i: 2 }, - { v: 5, n: 'selected flow temperature', s: 'selflowtemp', x: false, i: 3 }, - { v: 0, n: 'burner selected max power', s: 'selburnpow', x: false, i: 4 }, - { v: 0, n: 'heating pump modulation', s: 'heatingpumpmod', x: false, i: 5 }, - { n: 'heating pump 2 modulation', s: 'heatingpump2mod', x: true, i: 6 }, - { n: 'outside temperature', s: 'outdoortemp', x: true, i: 7 }, - { v: 53, n: 'current flow temperature', s: 'curflowtemp', x: false, i: 8 }, - { v: 51.8, n: 'return temperature', s: 'rettemp', x: false, i: 9 }, - { n: 'mixing switch temperature', s: 'switchtemp', x: true, i: 10 }, - { v: 1.3, n: 'system pressure', s: 'syspress', x: false, i: 11 }, - { v: 54.6, n: 'actual boiler temperature', s: 'boiltemp', x: false, i: 12 }, - { n: 'exhaust temperature', s: 'exhausttemp', x: true, i: 13 }, - { v: false, n: 'gas', s: 'burngas', x: false, i: 14 }, - { v: false, n: 'gas stage 2', s: 'burngas2', x: false, i: 15 }, - { v: 0, n: 'flame current', s: 'flamecurr', x: false, i: 16 }, - { v: false, n: 'heating pump', s: 'heatingpump', x: false, i: 17 }, - { v: false, n: 'fan', s: 'fanwork', x: false, i: 18 }, - { v: false, n: 'ignition', s: 'ignwork', x: false, i: 19 }, - { v: false, n: 'oil preheating', s: 'oilpreheat', x: false, i: 20 }, - { v: true, n: 'heating activated', s: 'heatingactivated', x: false, i: 21 }, - { v: 80, n: 'heating temperature', s: 'heatingtemp', x: false, i: 22 }, - { v: 70, n: 'burner pump max power', s: 'pumpmodmax', x: false, i: 23 }, - { v: 30, n: 'burner pump min power', s: 'pumpmodmin', x: false, i: 24 }, - { v: 1, n: 'pump delay', s: 'pumpdelay', x: false, i: 25 }, - { v: 10, n: 'burner min period', s: 'burnminperiod', x: false, i: 26 }, - { v: 0, n: 'burner min power', s: 'burnminpower', x: false, i: 27 }, - { v: 50, n: 'burner max power', s: 'burnmaxpower', x: false, i: 28 }, - { v: -6, n: 'hysteresis on temperature', s: 'boilhyston', x: false, i: 29 }, - { v: 6, n: 'hysteresis off temperature', s: 'boilhystoff', x: false, i: 30 }, - { v: 0, n: 'set flow temperature', s: 'setflowtemp', x: false, i: 31 }, - { v: 0, n: 'burner set power', s: 'setburnpow', x: false, i: 32 }, - { v: 0, n: 'burner current power', s: 'curburnpow', x: false, i: 33 }, - { v: 326323, n: 'burner starts', s: 'burnstarts', x: false, i: 34 }, - { v: 553437, n: 'total burner operating time', s: 'burnworkmin', x: false, i: 35 }, - { v: 451286, n: 'total heat operating time', s: 'heatworkmin', x: false, i: 36 }, - { v: 4672175, n: 'total UBA operating time', s: 'ubauptime', x: false, i: 37 }, - { v: '1C(210) 06.06.2020 12:07 (0 min)', n: 'last error code', s: 'lastcode', x: false, i: 38 }, - { v: '0H', n: 'service code', s: 'servicecode', x: false, i: 39 }, - { v: 203, n: 'service code number', s: 'servicecodenumber', x: false, i: 40 }, - { v: 'H00', n: 'maintenance message', s: 'maintenancemessage', x: false, i: 41 }, - { v: 'manual', n: 'maintenance scheduled', s: 'maintenance', x: false, i: 42 }, - { v: 6000, n: 'time to next maintenance', s: 'maintenancetime', x: false, i: 43 }, - { v: '01.01.2012', n: 'next maintenance date', s: 'maintenancedate', x: false, i: 44 }, - { v: true, n: 'dhw turn on/off', s: 'wwtapactivated', x: false, i: 45 }, - { v: 62, n: 'dhw set temperature', s: 'wwsettemp', x: false, i: 46 }, - { v: 60, n: 'dhw selected temperature', s: 'wwseltemp', x: false, i: 47 }, - { n: 'dhw selected lower temperature', s: 'wwseltemplow', x: true, i: 48 }, - { n: 'dhw selected temperature for off', s: 'wwseltempoff', x: true, i: 49 }, - { n: 'dhw single charge temperature', s: 'wwseltempsingle', x: true, i: 50 }, - { v: 'flow', n: 'dhw type', s: 'wwtype', x: false, i: 51 }, - { v: 'hot', n: 'dhw comfort', s: 'wwcomfort', x: false, i: 52 }, - { v: 40, n: 'dhw flow temperature offset', s: 'wwflowtempoffset', x: false, i: 53 }, - { v: 100, n: 'dhw max power', s: 'wwmaxpower', x: false, i: 54 }, - { v: false, n: 'dhw circulation pump available', s: 'wwcircpump', x: false, i: 55 }, - { v: '3-way valve', n: 'dhw charging type', s: 'wwchargetype', x: false, i: 56 }, - { v: -5, n: 'dhw hysteresis on temperature', s: 'wwhyston', x: false, i: 57 }, - { v: 0, n: 'dhw hysteresis off temperature', s: 'wwhystoff', x: false, i: 58 }, - { v: 70, n: 'dhw disinfection temperature', s: 'wwdisinfectiontemp', x: false, i: 59 }, - { v: 'off', n: 'dhw circulation pump mode', s: 'wwcircmode', x: false, i: 60 }, - { v: false, n: 'dhw circulation active', s: 'wwcirc', x: false, i: 61 }, - { v: 46.4, n: 'dhw current intern temperature', s: 'wwcurtemp', x: false, i: 62 }, - { n: 'dhw current extern temperature', s: 'wwcurtemp2', x: true, i: 63 }, - { v: 0, n: 'dhw current tap water flow', s: 'wwcurflow', x: false, i: 64 }, - { v: 46.3, n: 'dhw storage intern temperature', s: 'wwstoragetemp1', x: false, i: 65 }, - { n: 'dhw storage extern temperature', s: 'wwstoragetemp2', x: true, i: 66 }, - { v: true, n: 'dhw activated', s: 'wwactivated', x: false, i: 67 }, - { v: false, n: 'dhw one time charging', s: 'wwonetime', x: false, i: 68 }, - { v: false, n: 'dhw disinfecting', s: 'wwdisinfecting', x: false, i: 69 }, - { v: false, n: 'dhw charging', s: 'wwcharging', x: false, i: 70 }, - { v: false, n: 'dhw recharging', s: 'wwrecharging', x: false, i: 71 }, - { v: true, n: 'dhw temperature ok', s: 'wwtempok', x: false, i: 72 }, - { v: false, n: 'dhw active', s: 'wwactive', x: false, i: 73 }, - { v: true, n: 'dhw 3way valve active', s: 'ww3wayvalve', x: false, i: 74 }, - { v: 0, n: 'dhw set pump power', s: 'wwsetpumppower', x: false, i: 75 }, - { n: 'dhw mixer temperature', s: 'wwmixertemp', x: true, i: 76 }, - { n: 'dhw cylinder middle temperature (TS3)', s: 'wwcylmiddletemp', x: true, i: 77 }, - { v: 288768, n: 'dhw starts', s: 'wwstarts', x: false, i: 78 }, - { v: 102151, n: 'dhw active time', s: 'wwworkm', x: false, i: 79 }, + { v: false, n: 'heating active', s: 'heatingactive', m: 0, i: 1 }, + { v: false, n: 'tapwater active', s: 'tapwateractive', m: 0, i: 2 }, + { v: 5, n: 'selected flow temperature', s: 'selflowtemp', m: 0, i: 3 }, + { v: 0, n: 'burner selected max power', s: 'selburnpow', m: 0, i: 4 }, + { v: 0, n: 'heating pump modulation', s: 'heatingpumpmod', m: 0, i: 5 }, + { n: 'heating pump 2 modulation', s: 'heatingpump2mod', m: 7, i: 6 }, + { n: 'outside temperature', s: 'outdoortemp', m: 7, i: 7 }, + { v: 53, n: 'current flow temperature', s: 'curflowtemp', m: 0, i: 8 }, + { v: 51.8, n: 'return temperature', s: 'rettemp', m: 0, i: 9 }, + { n: 'mixing switch temperature', s: 'switchtemp', m: 7, i: 10 }, + { v: 1.3, n: 'system pressure', s: 'syspress', m: 0, i: 11 }, + { v: 54.6, n: 'actual boiler temperature', s: 'boiltemp', m: 0, i: 12 }, + { n: 'exhaust temperature', s: 'exhausttemp', m: 7, i: 13 }, + { v: false, n: 'gas', s: 'burngas', m: 0, i: 14 }, + { v: false, n: 'gas stage 2', s: 'burngas2', m: 0, i: 15 }, + { v: 0, n: 'flame current', s: 'flamecurr', m: 0, i: 16 }, + { v: false, n: 'heating pump', s: 'heatingpump', m: 0, i: 17 }, + { v: false, n: 'fan', s: 'fanwork', m: 0, i: 18 }, + { v: false, n: 'ignition', s: 'ignwork', m: 0, i: 19 }, + { v: false, n: 'oil preheating', s: 'oilpreheat', m: 0, i: 20 }, + { v: true, n: 'heating activated', s: 'heatingactivated', m: 0, i: 21 }, + { v: 80, n: 'heating temperature', s: 'heatingtemp', m: 0, i: 22 }, + { v: 70, n: 'burner pump max power', s: 'pumpmodmax', m: 0, i: 23 }, + { v: 30, n: 'burner pump min power', s: 'pumpmodmin', m: 0, i: 24 }, + { v: 1, n: 'pump delay', s: 'pumpdelay', m: 0, i: 25 }, + { v: 10, n: 'burner min period', s: 'burnminperiod', m: 0, i: 26 }, + { v: 0, n: 'burner min power', s: 'burnminpower', m: 0, i: 27 }, + { v: 50, n: 'burner max power', s: 'burnmaxpower', m: 0, i: 28 }, + { v: -6, n: 'hysteresis on temperature', s: 'boilhyston', m: 0, i: 29 }, + { v: 6, n: 'hysteresis off temperature', s: 'boilhystoff', m: 0, i: 30 }, + { v: 0, n: 'set flow temperature', s: 'setflowtemp', m: 0, i: 31 }, + { v: 0, n: 'burner set power', s: 'setburnpow', m: 0, i: 32 }, + { v: 0, n: 'burner current power', s: 'curburnpow', m: 0, i: 33 }, + { v: 326323, n: 'burner starts', s: 'burnstarts', m: 0, i: 34 }, + { v: 553437, n: 'total burner operating time', s: 'burnworkmin', m: 0, i: 35 }, + { v: 451286, n: 'total heat operating time', s: 'heatworkmin', m: 0, i: 36 }, + { v: 4672175, n: 'total UBA operating time', s: 'ubauptime', m: 0, i: 37 }, + { v: '1C(210) 06.06.2020 12:07 (0 min)', n: 'last error code', s: 'lastcode', m: 0, i: 38 }, + { v: '0H', n: 'service code', s: 'servicecode', m: 0, i: 39 }, + { v: 203, n: 'service code number', s: 'servicecodenumber', m: 0, i: 40 }, + { v: 'H00', n: 'maintenance message', s: 'maintenancemessage', m: 0, i: 41 }, + { v: 'manual', n: 'maintenance scheduled', s: 'maintenance', m: 0, i: 42 }, + { v: 6000, n: 'time to next maintenance', s: 'maintenancetime', m: 0, i: 43 }, + { v: '01.01.2012', n: 'next maintenance date', s: 'maintenancedate', m: 0, i: 44 }, + { v: true, n: 'dhw turn on/off', s: 'wwtapactivated', m: 0, i: 45 }, + { v: 62, n: 'dhw set temperature', s: 'wwsettemp', m: 0, i: 46 }, + { v: 60, n: 'dhw selected temperature', s: 'wwseltemp', m: 0, i: 47 }, + { n: 'dhw selected lower temperature', s: 'wwseltemplow', m: 7, i: 48 }, + { n: 'dhw selected temperature for off', s: 'wwseltempoff', m: 7, i: 49 }, + { n: 'dhw single charge temperature', s: 'wwseltempsingle', m: 7, i: 50 }, + { v: 'flow', n: 'dhw type', s: 'wwtype', m: 0, i: 51 }, + { v: 'hot', n: 'dhw comfort', s: 'wwcomfort', m: 0, i: 52 }, + { v: 40, n: 'dhw flow temperature offset', s: 'wwflowtempoffset', m: 0, i: 53 }, + { v: 100, n: 'dhw max power', s: 'wwmaxpower', m: 0, i: 54 }, + { v: false, n: 'dhw circulation pump available', s: 'wwcircpump', m: 0, i: 55 }, + { v: '3-way valve', n: 'dhw charging type', s: 'wwchargetype', m: 0, i: 56 }, + { v: -5, n: 'dhw hysteresis on temperature', s: 'wwhyston', m: 0, i: 57 }, + { v: 0, n: 'dhw hysteresis off temperature', s: 'wwhystoff', m: 0, i: 58 }, + { v: 70, n: 'dhw disinfection temperature', s: 'wwdisinfectiontemp', m: 0, i: 59 }, + { v: 'off', n: 'dhw circulation pump mode', s: 'wwcircmode', m: 0, i: 60 }, + { v: false, n: 'dhw circulation active', s: 'wwcirc', m: 0, i: 61 }, + { v: 46.4, n: 'dhw current intern temperature', s: 'wwcurtemp', m: 0, i: 62 }, + { n: 'dhw current extern temperature', s: 'wwcurtemp2', m: 7, i: 63 }, + { v: 0, n: 'dhw current tap water flow', s: 'wwcurflow', m: 0, i: 64 }, + { v: 46.3, n: 'dhw storage intern temperature', s: 'wwstoragetemp1', m: 0, i: 65 }, + { n: 'dhw storage extern temperature', s: 'wwstoragetemp2', m: 7, i: 66 }, + { v: true, n: 'dhw activated', s: 'wwactivated', m: 0, i: 67 }, + { v: false, n: 'dhw one time charging', s: 'wwonetime', m: 0, i: 68 }, + { v: false, n: 'dhw disinfecting', s: 'wwdisinfecting', m: 0, i: 69 }, + { v: false, n: 'dhw charging', s: 'wwcharging', m: 0, i: 70 }, + { v: false, n: 'dhw recharging', s: 'wwrecharging', m: 0, i: 71 }, + { v: true, n: 'dhw temperature ok', s: 'wwtempok', m: 0, i: 72 }, + { v: false, n: 'dhw active', s: 'wwactive', m: 0, i: 73 }, + { v: true, n: 'dhw 3way valve active', s: 'ww3wayvalve', m: 0, i: 74 }, + { v: 0, n: 'dhw set pump power', s: 'wwsetpumppower', m: 0, i: 75 }, + { n: 'dhw mixer temperature', s: 'wwmixertemp', m: 7, i: 76 }, + { n: 'dhw cylinder middle temperature (TS3)', s: 'wwcylmiddletemp', m: 7, i: 77 }, + { v: 288768, n: 'dhw starts', s: 'wwstarts', m: 0, i: 78 }, + { v: 102151, n: 'dhw active time', s: 'wwworkm', m: 0, i: 79 }, ] const emsesp_deviceentities_4 = [ @@ -718,20 +718,20 @@ const emsesp_deviceentities_4 = [ v: 16, n: 'hc2 selected room temperature', s: 'hc2/seltemp', - x: false, + m: 0, i: 1, }, { n: 'hc2 current room temperature', s: 'hc2/curtemp', - x: true, + m: 7, i: 2, }, { v: 'off', n: 'hc2 mode', s: 'hc2/mode', - x: true, + m: 7, i: 3, }, ] @@ -925,8 +925,8 @@ rest_server.post(EMSESP_DEVICEENTITIES_ENDPOINT, (req, res) => { } }) -rest_server.post(EMSESP_EXCLUDE_ENTITIES_ENDPOINT, (req, res) => { - console.log('exclude list for unique id ' + req.body.id + ' and entities:') +rest_server.post(EMSESP_MASKED_ENTITIES_ENDPOINT, (req, res) => { + console.log('list for unique id ' + req.body.id + ' and entities:') console.log(req.body.entity_ids) res.sendStatus(200) }) From 079f4e5ac0d2e9e0ca5aa76469065d275ba202bf Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 16:19:55 +0200 Subject: [PATCH 02/15] replace exclude_entities with masked_entities --- interface/src/project/api.ts | 6 +-- interface/src/project/types.ts | 4 +- src/system.cpp | 3 +- src/test/test.cpp | 4 +- src/test/test.h | 6 +-- src/web/WebCustomizationService.cpp | 57 +++++++++++++++-------------- src/web/WebCustomizationService.h | 15 ++++---- 7 files changed, 48 insertions(+), 47 deletions(-) diff --git a/interface/src/project/api.ts b/interface/src/project/api.ts index f3a29a6bc..e605332fb 100644 --- a/interface/src/project/api.ts +++ b/interface/src/project/api.ts @@ -12,7 +12,7 @@ import { DeviceData, DeviceEntity, UniqueID, - ExcludeEntities, + MaskedEntities, WriteValue, WriteSensor, WriteAnalog, @@ -63,8 +63,8 @@ export function readDeviceEntities(unique_id: UniqueID): AxiosPromise { - return AXIOS.post('/excludeEntities', excludeEntities); +export function writeMaskedEntities(maskedEntities: MaskedEntities): AxiosPromise { + return AXIOS.post('/maskedEntities', maskedEntities); } export function writeValue(writevalue: WriteValue): AxiosPromise { diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts index 226873bdd..5bcf45dad 100644 --- a/interface/src/project/types.ts +++ b/interface/src/project/types.ts @@ -146,11 +146,11 @@ export interface DeviceEntity { v?: any; // value, in any format n: string; // name s: string; // shortname - x: boolean; // excluded flag + m: number; // mask i: number; // unique id } -export interface ExcludeEntities { +export interface MaskedEntities { id: number; entity_ids: string[]; } diff --git a/src/system.cpp b/src/system.cpp index ab29b4a68..bf8f9ec26 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -1018,7 +1018,6 @@ bool System::command_customizations(const char * value, const int8_t id, JsonObj JsonObject node = output.createNestedObject("Customizations"); - // hide ssid from this list EMSESP::webCustomizationService.read([&](WebCustomization & settings) { // sensors JsonArray sensorsJson = node.createNestedArray("sensors"); @@ -1053,7 +1052,7 @@ bool System::command_customizations(const char * value, const int8_t id, JsonObj } } - // exclude entities + // masked entities JsonArray mask_entitiesJson = node.createNestedArray("masked_entities"); for (const auto & entityCustomization : settings.entityCustomizations) { JsonObject entityJson = mask_entitiesJson.createNestedObject(); diff --git a/src/test/test.cpp b/src/test/test.cpp index ee4635ee5..960332c58 100644 --- a/src/test/test.cpp +++ b/src/test/test.cpp @@ -595,8 +595,8 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const EMSESP::system_.healthcheck(n); } - if (command == "exclude") { - shell.printfln(F("Testing exclude entities")); + if (command == "masked") { + shell.printfln(F("Testing masked entities")); Mqtt::ha_enabled(true); Mqtt::send_response(false); diff --git a/src/test/test.h b/src/test/test.h index 9ca31dd36..65021652e 100644 --- a/src/test/test.h +++ b/src/test/test.h @@ -31,12 +31,12 @@ namespace emsesp { // #define EMSESP_DEBUG_DEFAULT "mixer" // #define EMSESP_DEBUG_DEFAULT "web" // #define EMSESP_DEBUG_DEFAULT "mqtt" -// #define EMSESP_DEBUG_DEFAULT "general" +#define EMSESP_DEBUG_DEFAULT "general" // #define EMSESP_DEBUG_DEFAULT "boiler" // #define EMSESP_DEBUG_DEFAULT "mqtt2" // #define EMSESP_DEBUG_DEFAULT "mqtt_nested" -#define EMSESP_DEBUG_DEFAULT "ha" -// #define EMSESP_DEBUG_DEFAULT "exclude" +// #define EMSESP_DEBUG_DEFAULT "ha" +// #define EMSESP_DEBUG_DEFAULT "masked" // #define EMSESP_DEBUG_DEFAULT "board_profile" // #define EMSESP_DEBUG_DEFAULT "shower_alert" // #define EMSESP_DEBUG_DEFAULT "310" diff --git a/src/web/WebCustomizationService.cpp b/src/web/WebCustomizationService.cpp index 44301e2a6..21bc198ba 100644 --- a/src/web/WebCustomizationService.cpp +++ b/src/web/WebCustomizationService.cpp @@ -31,9 +31,9 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f securityManager, AuthenticationPredicates::IS_AUTHENTICATED) , _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE) - , _exclude_entities_handler(EXCLUDE_ENTITIES_PATH, - securityManager->wrapCallback(std::bind(&WebCustomizationService::exclude_entities, this, _1, _2), - AuthenticationPredicates::IS_AUTHENTICATED)) + , _masked_entities_handler(MASKED_ENTITIES_PATH, + securityManager->wrapCallback(std::bind(&WebCustomizationService::masked_entities, this, _1, _2), + AuthenticationPredicates::IS_AUTHENTICATED)) , _device_entities_handler(DEVICE_ENTITIES_PATH, securityManager->wrapCallback(std::bind(&WebCustomizationService::device_entities, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED)) { @@ -45,17 +45,17 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f HTTP_POST, securityManager->wrapRequest(std::bind(&WebCustomizationService::reset_customization, this, _1), AuthenticationPredicates::IS_ADMIN)); - _exclude_entities_handler.setMethod(HTTP_POST); - _exclude_entities_handler.setMaxContentLength(2048); - _exclude_entities_handler.setMaxJsonBufferSize(2048); - server->addHandler(&_exclude_entities_handler); + _masked_entities_handler.setMethod(HTTP_POST); + _masked_entities_handler.setMaxContentLength(2048); + _masked_entities_handler.setMaxJsonBufferSize(2048); + server->addHandler(&_masked_entities_handler); _device_entities_handler.setMethod(HTTP_POST); _device_entities_handler.setMaxContentLength(256); server->addHandler(&_device_entities_handler); } -// this creates the customization file, saving to the FS +// this creates the customization file, saving it to the FS void WebCustomization::read(WebCustomization & settings, JsonObject & root) { // Dallas Sensor customization JsonArray sensorsJson = root.createNestedArray("sensors"); @@ -78,21 +78,21 @@ void WebCustomization::read(WebCustomization & settings, JsonObject & root) { sensorJson["type"] = sensor.type; // t } - // Exclude entities customization - JsonArray exclude_entitiesJson = root.createNestedArray("exclude_entities"); + // Masked entities customization + JsonArray masked_entitiesJson = root.createNestedArray("masked_entities"); for (const EntityCustomization & entityCustomization : settings.entityCustomizations) { - JsonObject entityJson = exclude_entitiesJson.createNestedObject(); + JsonObject entityJson = masked_entitiesJson.createNestedObject(); entityJson["product_id"] = entityCustomization.product_id; entityJson["device_id"] = entityCustomization.device_id; - JsonArray exclude_entityJson = entityJson.createNestedArray("entity_ids"); + JsonArray masked_entityJson = entityJson.createNestedArray("entity_ids"); for (std::string entity_id : entityCustomization.entity_ids) { - exclude_entityJson.add(entity_id); + masked_entityJson.add(entity_id); } } } -// call on initialization and also when the page is saved via web +// call on initialization and also when the page is saved via web UI // this loads the data into the internal class StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & settings) { // Dallas Sensor customization @@ -124,17 +124,20 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & } } - // load array of entities id's to exclude, building up the object class + // load array of entities id's with masks, building up the object class settings.entityCustomizations.clear(); - if (root["exclude_entities"].is()) { - for (const JsonObject exclude_entities : root["exclude_entities"].as()) { + if (root["masked_entities"].is()) { + for (const JsonObject masked_entities : root["masked_entities"].as()) { auto new_entry = EntityCustomization(); - new_entry.product_id = exclude_entities["product_id"]; - new_entry.device_id = exclude_entities["device_id"]; + new_entry.product_id = masked_entities["product_id"]; + new_entry.device_id = masked_entities["device_id"]; - for (const JsonVariant exclude_entity_id : exclude_entities["entity_ids"].as()) { - new_entry.entity_ids.push_back(exclude_entity_id.as()); // add entity list + for (const JsonVariant masked_entity_id : masked_entities["entity_ids"].as()) { + if (masked_entity_id.is()) { + new_entry.entity_ids.push_back(masked_entity_id.as()); // add entity list + } } + settings.entityCustomizations.push_back(new_entry); // save the new object } } @@ -157,7 +160,7 @@ void WebCustomizationService::reset_customization(AsyncWebServerRequest * reques #endif } -// send back a short list devices used in the customization page +// send back a list of devices used to the customization web page void WebCustomizationService::devices(AsyncWebServerRequest * request) { auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_LARGE_DYN); JsonObject root = response->getRoot(); @@ -183,10 +186,10 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) { request->send(response); } -// send back list device entities +// send back list of device entities void WebCustomizationService::device_entities(AsyncWebServerRequest * request, JsonVariant & json) { if (json.is()) { - auto * response = new MsgpackAsyncJsonResponse(true, EMSESP_JSON_SIZE_XXLARGE_DYN); + auto * response = new MsgpackAsyncJsonResponse(true, EMSESP_JSON_SIZE_XXXLARGE_DYN); for (const auto & emsdevice : EMSESP::emsdevices) { if (emsdevice->unique_id() == json["id"]) { #ifndef EMSESP_STANDALONE @@ -205,10 +208,10 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request, J request->send(response); } -// takes a list of excluded ids send from the webUI +// takes a list of masked ids send from the webUI // saves it in the customization service // and updates the entity list real-time -void WebCustomizationService::exclude_entities(AsyncWebServerRequest * request, JsonVariant & json) { +void WebCustomizationService::masked_entities(AsyncWebServerRequest * request, JsonVariant & json) { if (json.is()) { // find the device using the unique_id for (const auto & emsdevice : EMSESP::emsdevices) { @@ -218,7 +221,7 @@ void WebCustomizationService::exclude_entities(AsyncWebServerRequest * request, // first reset all the entity ids emsdevice->reset_entity_masks(); - // build a list of entities to exclude and then set the flag to non-visible + // build a list of entities JsonArray entity_ids_json = json["entity_ids"]; std::vector entity_ids; for (JsonVariant id : entity_ids_json) { diff --git a/src/web/WebCustomizationService.h b/src/web/WebCustomizationService.h index 1c34ac80d..526259dbe 100644 --- a/src/web/WebCustomizationService.h +++ b/src/web/WebCustomizationService.h @@ -27,7 +27,7 @@ // POST #define DEVICE_ENTITIES_PATH "/rest/deviceEntities" -#define EXCLUDE_ENTITIES_PATH "/rest/excludeEntities" +#define MASKED_ENTITIES_PATH "/rest/maskedEntities" #define RESET_CUSTOMIZATION_SERVICE_PATH "/rest/resetCustomizations" namespace emsesp { @@ -63,17 +63,16 @@ class EntityCustomization { public: uint8_t product_id; // device's product id uint8_t device_id; // device's device id - std::vector entity_ids; // array of entity ids to exclude + std::vector entity_ids; // array of entity ids with masks }; class WebCustomization { public: std::list sensorCustomizations; // for sensor names and offsets std::list analogCustomizations; // for analog sensors - std::list entityCustomizations; // for a list of entities that should be excluded from the device list - - static void read(WebCustomization & settings, JsonObject & root); - static StateUpdateResult update(JsonObject & root, WebCustomization & settings); + std::list entityCustomizations; // for a list of entities that have a special mask set + static void read(WebCustomization & settings, JsonObject & root); + static StateUpdateResult update(JsonObject & root, WebCustomization & settings); }; class WebCustomizationService : public StatefulService { @@ -94,11 +93,11 @@ class WebCustomizationService : public StatefulService { void devices(AsyncWebServerRequest * request); // POST - void exclude_entities(AsyncWebServerRequest * request, JsonVariant & json); + void masked_entities(AsyncWebServerRequest * request, JsonVariant & json); void device_entities(AsyncWebServerRequest * request, JsonVariant & json); void reset_customization(AsyncWebServerRequest * request); - AsyncCallbackJsonWebHandler _exclude_entities_handler, _device_entities_handler; + AsyncCallbackJsonWebHandler _masked_entities_handler, _device_entities_handler; }; } // namespace emsesp From 03af305761e38d5b80f291973000ffb2485bdb38 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 16:20:19 +0200 Subject: [PATCH 03/15] send state to WebUI (only the high nibble mask bits) --- src/emsdevice.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index 715484bb0..a3810236b 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -861,8 +861,8 @@ void EMSdevice::generate_values_web_all(JsonArray & output) { obj["s"] = dv.short_name; } - // is it marked as excluded? - obj["x"] = dv.has_state(DeviceValueState::DV_WEB_EXCLUDE); + // send back the mask state. We're only interested in the high nibble + obj["m"] = dv.state >> 4; // add the unique ID obj["i"] = dv.id; From b4cc300190985516758c5b342ba60d42aaefb3c1 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 16:20:32 +0200 Subject: [PATCH 04/15] fix lint warning --- src/devices/thermostat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/devices/thermostat.cpp b/src/devices/thermostat.cpp index 1e3b5744c..d4de33b66 100644 --- a/src/devices/thermostat.cpp +++ b/src/devices/thermostat.cpp @@ -1251,13 +1251,13 @@ void Thermostat::process_RCTime(std::shared_ptr telegram) { LOG_INFO(F("thermostat time correction from ntp")); } } +#ifndef EMSESP_STANDALONE if (!ntp_ && tm_->tm_year > 110) { // emsesp clock not set, but thermostat clock struct timeval newnow = {.tv_sec = ttime}; -#ifndef EMSESP_STANDALONE settimeofday(&newnow, nullptr); -#endif LOG_INFO(F("ems-esp time set from thermostat")); } +#endif } // process_RCError - type 0xA2 - error message - 14 bytes long From afd55c52e5745a60c834d35d88c4c99157be6595 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 16:20:42 +0200 Subject: [PATCH 05/15] formatting --- src/emsdevicevalue.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/emsdevicevalue.h b/src/emsdevicevalue.h index 526490789..9571218aa 100644 --- a/src/emsdevicevalue.h +++ b/src/emsdevicevalue.h @@ -110,15 +110,17 @@ class DeviceValue { // states of a device value enum DeviceValueState : uint8_t { + // low nibble active state of the device value DV_DEFAULT = 0, // 0 - does not yet have a value DV_ACTIVE = (1 << 0), // 1 - has a validated real value DV_HA_CONFIG_CREATED = (1 << 1), // 2 - set if the HA config topic has been created DV_HA_CLIMATE_NO_RT = (1 << 2), // 3 - climate created without roomTemp - // high nibble as mask for exclusions - DV_WEB_EXCLUDE = (1 << 4), // 16 - not shown on web - DV_API_MQTT_EXCLUDE = (1 << 5), // 32 - not shown on mqtt, API - DV_READONLY = (1 << 6), // 64 - read only - DV_FAVORITE = (1 << 7) // 128 - sort to front + + // high nibble as mask for exclusions & special functions + DV_WEB_EXCLUDE = (1 << 4), // 16 - not shown on web + DV_API_MQTT_EXCLUDE = (1 << 5), // 32 - not shown on mqtt, API + DV_READONLY = (1 << 6), // 64 - read only + DV_FAVORITE = (1 << 7) // 128 - sort to front }; uint8_t device_type; // EMSdevice::DeviceType From f80d7963334178136340c1d75fe38a2e5cdeb213 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 16:21:12 +0200 Subject: [PATCH 06/15] use mask flags --- .../src/project/SettingsCustomization.tsx | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/interface/src/project/SettingsCustomization.tsx b/interface/src/project/SettingsCustomization.tsx index 7e4daf26d..1bf5a5464 100644 --- a/interface/src/project/SettingsCustomization.tsx +++ b/interface/src/project/SettingsCustomization.tsx @@ -110,7 +110,7 @@ const SettingsCustomization: FC = () => { <> - Customize which entities to exclude from all all services (MQTT, API). This will have immediate effect. + Customize which entities to exclude. This will have immediate effect on all services including MQTT and API. { const saveCustomization = async () => { if (deviceEntities && selectedDevice) { - const exclude_entities = deviceEntities.filter((de) => de.x).map((new_de) => "07" + new_de.s); + const masked_entities = deviceEntities + .filter((de) => de.m) + .map((new_de) => new_de.m.toString(16).padStart(2, '0') + new_de.s); try { - const response = await EMSESP.writeExcludeEntities({ + const response = await EMSESP.writeMaskedEntities({ id: selectedDevice, - entity_ids: exclude_entities + entity_ids: masked_entities }); if (response.status === 200) { enqueueSnackbar('Customization saved', { variant: 'success' }); @@ -160,11 +162,11 @@ const SettingsCustomization: FC = () => { return; } - const toggleDeviceEntity = (id: number) => { + const toggleDeviceEntity = (id: number, mask: number) => { setDeviceEntities( deviceEntities.map((o) => { if (o.i === id) { - return { ...o, x: !o.x }; + return { ...o, m: mask ^ o.m }; } return o; }) @@ -177,7 +179,7 @@ const SettingsCustomization: FC = () => { - ({deviceEntities.reduce((a, v) => (v.x ? a + 1 : a), 0)}/{deviceEntities.length}) + ({deviceEntities.reduce((a, de) => (de.m === 7 ? a + 1 : a), 0)}/{deviceEntities.length}) ENTITY NAME CODE @@ -188,10 +190,10 @@ const SettingsCustomization: FC = () => { {deviceEntities.map((de) => ( toggleDeviceEntity(de.i)} - sx={de.x ? { backgroundColor: '#f8696b' } : { backgroundColor: 'black' }} + onClick={() => toggleDeviceEntity(de.i, 7)} + sx={de.m === 7 ? { backgroundColor: '#f8696b' } : { backgroundColor: 'black' }} > - {de.x && } + {de.m === 7 && } {de.n} From f5bf566e66a91cfc3648d9df06ff3c3ac065f325 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 19:56:35 +0200 Subject: [PATCH 07/15] remove aria-label --- interface/src/framework/security/UserForm.tsx | 2 +- interface/src/project/DashboardData.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/framework/security/UserForm.tsx b/interface/src/framework/security/UserForm.tsx index 380e13652..4a82f08a9 100644 --- a/interface/src/framework/security/UserForm.tsx +++ b/interface/src/framework/security/UserForm.tsx @@ -46,7 +46,7 @@ const UserForm: FC = ({ creating, validator, user, setUser, onDon }; return ( - + {user && ( <> {creating ? 'Add' : 'Modify'} User diff --git a/interface/src/project/DashboardData.tsx b/interface/src/project/DashboardData.tsx index d53ebe68e..8d7b043b5 100644 --- a/interface/src/project/DashboardData.tsx +++ b/interface/src/project/DashboardData.tsx @@ -524,7 +524,7 @@ const DashboardData: FC = () => { sendCommand(dv)}> {dv.c && me.admin && ( - + )} @@ -569,7 +569,7 @@ const DashboardData: FC = () => { updateSensor(sensor_data)}> {me.admin && ( - + )} @@ -605,7 +605,7 @@ const DashboardData: FC = () => { updateAnalog(analog_data)}> {me.admin && ( - + )} From b331a07b69cd4339cfce3f6590119f260fdb0970 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 19:56:54 +0200 Subject: [PATCH 08/15] add masks to customize screen --- .../src/project/SettingsCustomization.tsx | 123 ++++++++++++------ mock-api/server.js | 29 ++--- 2 files changed, 97 insertions(+), 55 deletions(-) diff --git a/interface/src/project/SettingsCustomization.tsx b/interface/src/project/SettingsCustomization.tsx index 1bf5a5464..2705dfbad 100644 --- a/interface/src/project/SettingsCustomization.tsx +++ b/interface/src/project/SettingsCustomization.tsx @@ -12,7 +12,9 @@ import { Dialog, DialogActions, DialogContent, - DialogTitle + DialogTitle, + ToggleButton, + ToggleButtonGroup } from '@mui/material'; import TableCell, { tableCellClasses } from '@mui/material/TableCell'; @@ -22,8 +24,12 @@ import { styled } from '@mui/material/styles'; import { useSnackbar } from 'notistack'; import SaveIcon from '@mui/icons-material/Save'; -import CloseIcon from '@mui/icons-material/Close'; import CancelIcon from '@mui/icons-material/Cancel'; +import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined'; +import FavoriteBorderOutlinedIcon from '@mui/icons-material/FavoriteBorderOutlined'; +import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined'; +import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined'; + import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore'; import { ButtonRow, FormLoader, ValidatedTextField, SectionContent } from '../components'; @@ -53,6 +59,7 @@ const SettingsCustomization: FC = () => { const [errorMessage, setErrorMessage] = useState(); const [selectedDevice, setSelectedDevice] = useState(0); const [confirmReset, setConfirmReset] = useState(false); + const [masks, setMasks] = useState(() => ['fav', 'readonly', 'exclude_mqtt', 'exclude_web']); const fetchDevices = useCallback(async () => { try { @@ -162,48 +169,86 @@ const SettingsCustomization: FC = () => { return; } - const toggleDeviceEntity = (id: number, mask: number) => { - setDeviceEntities( - deviceEntities.map((o) => { - if (o.i === id) { - return { ...o, m: mask ^ o.m }; - } - return o; - }) - ); + const setMask = (de: DeviceEntity, newMask: string[]) => { + var new_mask = 0; + if (newMask.includes('exclude_web')) { + new_mask |= 1; + } + if (newMask.includes('exclude_mqtt')) { + new_mask |= 2; + } + if (newMask.includes('readonly')) { + new_mask |= 4; + } + if (newMask.includes('fav')) { + new_mask |= 8; + } + + de.m = new_mask; + setMasks(newMask); + }; + + const getValue = (de: DeviceEntity) => { + var new_masks = []; + if ((de.m & 1) === 1) { + new_masks.push('exclude_web'); + } + if ((de.m & 2) === 2) { + new_masks.push('exclude_mqtt'); + } + if ((de.m & 4) === 4) { + new_masks.push('readonly'); + } + if ((de.m & 8) === 8) { + new_masks.push('fav'); + } + + return new_masks; }; return ( - <> - - - - - ({deviceEntities.reduce((a, de) => (de.m === 7 ? a + 1 : a), 0)}/{deviceEntities.length}) +
+ + + OPTIONS + ENTITY NAME (CODE) + VALUE + + + + {deviceEntities.map((de) => ( + + + { + setMask(de, mask); + }} + > + + + + + + + + + + + + + - ENTITY NAME - CODE - VALUE + + {de.n} ({de.s}) + + {formatValue(de.v)} - - - {deviceEntities.map((de) => ( - toggleDeviceEntity(de.i, 7)} - sx={de.m === 7 ? { backgroundColor: '#f8696b' } : { backgroundColor: 'black' }} - > - {de.m === 7 && } - - {de.n} - - {de.s} - {formatValue(de.v)} - - ))} - -
- + ))} + + ); }; diff --git a/mock-api/server.js b/mock-api/server.js index 22b414d00..5942773dd 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -574,21 +574,18 @@ const emsesp_devicedata_4 = { u: 1, n: 'hc2 selected room temperature', c: 'hc2/seltemp', - m: 0, }, { v: 18.6, u: 1, n: 'hc2 current room temperature', c: '', - m: 7, }, { v: 'off', u: 0, n: 'hc2 mode', c: 'hc2/mode', - m: 7, }, ], } @@ -637,14 +634,14 @@ const emsesp_deviceentities_2 = [ { v: 5, n: 'selected flow temperature', s: 'selflowtemp', m: 0, i: 3 }, { v: 0, n: 'burner selected max power', s: 'selburnpow', m: 0, i: 4 }, { v: 0, n: 'heating pump modulation', s: 'heatingpumpmod', m: 0, i: 5 }, - { n: 'heating pump 2 modulation', s: 'heatingpump2mod', m: 7, i: 6 }, - { n: 'outside temperature', s: 'outdoortemp', m: 7, i: 7 }, + { n: 'heating pump 2 modulation', s: 'heatingpump2mod', m: 2, i: 6 }, + { n: 'outside temperature', s: 'outdoortemp', m: 2, i: 7 }, { v: 53, n: 'current flow temperature', s: 'curflowtemp', m: 0, i: 8 }, { v: 51.8, n: 'return temperature', s: 'rettemp', m: 0, i: 9 }, - { n: 'mixing switch temperature', s: 'switchtemp', m: 7, i: 10 }, + { n: 'mixing switch temperature', s: 'switchtemp', m: 2, i: 10 }, { v: 1.3, n: 'system pressure', s: 'syspress', m: 0, i: 11 }, { v: 54.6, n: 'actual boiler temperature', s: 'boiltemp', m: 0, i: 12 }, - { n: 'exhaust temperature', s: 'exhausttemp', m: 7, i: 13 }, + { n: 'exhaust temperature', s: 'exhausttemp', m: 2, i: 13 }, { v: false, n: 'gas', s: 'burngas', m: 0, i: 14 }, { v: false, n: 'gas stage 2', s: 'burngas2', m: 0, i: 15 }, { v: 0, n: 'flame current', s: 'flamecurr', m: 0, i: 16 }, @@ -679,9 +676,9 @@ const emsesp_deviceentities_2 = [ { v: true, n: 'dhw turn on/off', s: 'wwtapactivated', m: 0, i: 45 }, { v: 62, n: 'dhw set temperature', s: 'wwsettemp', m: 0, i: 46 }, { v: 60, n: 'dhw selected temperature', s: 'wwseltemp', m: 0, i: 47 }, - { n: 'dhw selected lower temperature', s: 'wwseltemplow', m: 7, i: 48 }, - { n: 'dhw selected temperature for off', s: 'wwseltempoff', m: 7, i: 49 }, - { n: 'dhw single charge temperature', s: 'wwseltempsingle', m: 7, i: 50 }, + { n: 'dhw selected lower temperature', s: 'wwseltemplow', m: 2, i: 48 }, + { n: 'dhw selected temperature for off', s: 'wwseltempoff', m: 2, i: 49 }, + { n: 'dhw single charge temperature', s: 'wwseltempsingle', m: 2, i: 50 }, { v: 'flow', n: 'dhw type', s: 'wwtype', m: 0, i: 51 }, { v: 'hot', n: 'dhw comfort', s: 'wwcomfort', m: 0, i: 52 }, { v: 40, n: 'dhw flow temperature offset', s: 'wwflowtempoffset', m: 0, i: 53 }, @@ -694,10 +691,10 @@ const emsesp_deviceentities_2 = [ { v: 'off', n: 'dhw circulation pump mode', s: 'wwcircmode', m: 0, i: 60 }, { v: false, n: 'dhw circulation active', s: 'wwcirc', m: 0, i: 61 }, { v: 46.4, n: 'dhw current intern temperature', s: 'wwcurtemp', m: 0, i: 62 }, - { n: 'dhw current extern temperature', s: 'wwcurtemp2', m: 7, i: 63 }, + { n: 'dhw current extern temperature', s: 'wwcurtemp2', m: 2, i: 63 }, { v: 0, n: 'dhw current tap water flow', s: 'wwcurflow', m: 0, i: 64 }, { v: 46.3, n: 'dhw storage intern temperature', s: 'wwstoragetemp1', m: 0, i: 65 }, - { n: 'dhw storage extern temperature', s: 'wwstoragetemp2', m: 7, i: 66 }, + { n: 'dhw storage extern temperature', s: 'wwstoragetemp2', m: 2, i: 66 }, { v: true, n: 'dhw activated', s: 'wwactivated', m: 0, i: 67 }, { v: false, n: 'dhw one time charging', s: 'wwonetime', m: 0, i: 68 }, { v: false, n: 'dhw disinfecting', s: 'wwdisinfecting', m: 0, i: 69 }, @@ -707,8 +704,8 @@ const emsesp_deviceentities_2 = [ { v: false, n: 'dhw active', s: 'wwactive', m: 0, i: 73 }, { v: true, n: 'dhw 3way valve active', s: 'ww3wayvalve', m: 0, i: 74 }, { v: 0, n: 'dhw set pump power', s: 'wwsetpumppower', m: 0, i: 75 }, - { n: 'dhw mixer temperature', s: 'wwmixertemp', m: 7, i: 76 }, - { n: 'dhw cylinder middle temperature (TS3)', s: 'wwcylmiddletemp', m: 7, i: 77 }, + { n: 'dhw mixer temperature', s: 'wwmixertemp', m: 2, i: 76 }, + { n: 'dhw cylinder middle temperature (TS3)', s: 'wwcylmiddletemp', m: 2, i: 77 }, { v: 288768, n: 'dhw starts', s: 'wwstarts', m: 0, i: 78 }, { v: 102151, n: 'dhw active time', s: 'wwworkm', m: 0, i: 79 }, ] @@ -724,14 +721,14 @@ const emsesp_deviceentities_4 = [ { n: 'hc2 current room temperature', s: 'hc2/curtemp', - m: 7, + m: 3, i: 2, }, { v: 'off', n: 'hc2 mode', s: 'hc2/mode', - m: 7, + m: 3, i: 3, }, ] From fdfc5e0e68c5c822e18c2e94b40b8d4982a3f2db Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 19:57:11 +0200 Subject: [PATCH 09/15] include name of device in options --- src/web/WebCustomizationService.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/web/WebCustomizationService.cpp b/src/web/WebCustomizationService.cpp index 21bc198ba..78a0616b5 100644 --- a/src/web/WebCustomizationService.cpp +++ b/src/web/WebCustomizationService.cpp @@ -175,9 +175,9 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) { uint8_t device_index = EMSESP::device_index(emsdevice->device_type(), emsdevice->unique_id()); if (device_index) { char s[10]; - obj["s"] = emsdevice->device_type_name() + Helpers::smallitoa(s, device_index); + obj["s"] = emsdevice->device_type_name() + Helpers::smallitoa(s, device_index) + " (" + emsdevice->name() + ")"; } else { - obj["s"] = emsdevice->device_type_name(); + obj["s"] = emsdevice->device_type_name() + " (" + emsdevice->name() + ")"; } } } From f7709e19fd3907f7810f1f0da48d69fc3441c08e Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 22:12:11 +0200 Subject: [PATCH 10/15] added w (Writable) to generate_values_web and sort by favorite --- src/emsdevice.cpp | 65 +++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index a3810236b..3e0b4348c 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -632,11 +632,16 @@ std::string EMSdevice::get_value_uom(const char * key) const { // prepare array of device values used for the WebUI // this is loosely based of the function generate_values used for the MQTT and Console // except additional data is stored in the JSON document needed for the Web UI like the UOM and command -// v = value, u=uom, n=name, c=cmd +// v=value, u=uom, n=name, c=cmd, h=help string, s=step, m=min, x=max void EMSdevice::generate_values_web(JsonObject & output) { output["label"] = to_string_short(); JsonArray data = output.createNestedArray("data"); + // sort the device values + std::sort(devicevalues_.begin(), devicevalues_.end(), [](const emsesp::DeviceValue & a, const emsesp::DeviceValue & b) { + return a.has_state(DeviceValueState::DV_FAVORITE); + }); + for (auto & dv : devicevalues_) { // check conditions: // 1. full_name cannot be empty @@ -752,32 +757,8 @@ void EMSdevice::generate_values_web(JsonObject & output) { } } -// reset all entities to being visible -// this is called before loading in the exclude entities list from the customization service -void EMSdevice::reset_entity_masks() { - for (auto & dv : devicevalues_) { - dv.state &= 0x0F; - } -} - -// disable/exclude/mask_out a device entity based on the id -void EMSdevice::mask_entity(std::string entity_id) { - // first character contains mask flags - uint8_t flag = Helpers::hextoint(entity_id.substr(0, 2).c_str()); - for (auto & dv : devicevalues_) { - std::string entity = dv.tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(dv.short_name) : tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name); - if (entity == entity_id.substr(2)) { -#if defined(EMSESP_USE_SERIAL) - Serial.print("mask_entity() Removing Visible for device value: "); - Serial.println(read_flash_string(dv.full_name).c_str()); -#endif - dv.state = (dv.state & 0x0F) | (flag << 4); // set state high bits to flag, turn off active and ha flags - return; - } - } -} - // 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_all(JsonArray & output) { for (auto & dv : devicevalues_) { // also show commands and entities that have an empty full name @@ -854,6 +835,7 @@ void EMSdevice::generate_values_web_all(JsonArray & output) { } else { obj["n"] = "(hidden)"; } + // shortname if (dv.tag >= DeviceValueTAG::TAG_HC1) { obj["s"] = tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name); @@ -861,11 +843,34 @@ void EMSdevice::generate_values_web_all(JsonArray & output) { obj["s"] = dv.short_name; } - // send back the mask state. We're only interested in the high nibble - obj["m"] = dv.state >> 4; + obj["m"] = dv.state >> 4; // send back the mask state. We're only interested in the high nibble + obj["w"] = dv.has_cmd; // if writable + obj["i"] = dv.id; // add the unique ID + } +} - // add the unique ID - obj["i"] = dv.id; +// reset all entities to being visible +// this is called before loading in the exclude entities list from the customization service +void EMSdevice::reset_entity_masks() { + for (auto & dv : devicevalues_) { + dv.state &= 0x0F; + } +} + +// disable/exclude/mask_out a device entity based on the id +void EMSdevice::mask_entity(std::string entity_id) { + // first character contains mask flags + uint8_t flag = Helpers::hextoint(entity_id.substr(0, 2).c_str()); + for (auto & dv : devicevalues_) { + std::string entity = dv.tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(dv.short_name) : tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name); + if (entity == entity_id.substr(2)) { +#if defined(EMSESP_USE_SERIAL) + Serial.print("mask_entity() Removing Visible for device value: "); + Serial.println(read_flash_string(dv.full_name).c_str()); +#endif + dv.state = (dv.state & 0x0F) | (flag << 4); // set state high bits to flag, turn off active and ha flags + return; + } } } From 821d7845f0da5ab3b69fcb070da616de40a64a88 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 22:12:21 +0200 Subject: [PATCH 11/15] updated b10 --- CHANGELOG_LATEST.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md index a9088aebd..186abadbf 100644 --- a/CHANGELOG_LATEST.md +++ b/CHANGELOG_LATEST.md @@ -30,6 +30,7 @@ - sync time with thermostat [#386](https://github.com/emsesp/EMS-ESP32/issues/386), [#408](https://github.com/emsesp/EMS-ESP32/issues/408) - set mode has immediate effect [#395](https://github.com/emsesp/EMS-ESP32/issues/395) - min/max in web value setting +- Extend customization to select if an entity is to be shown in the WebUI or forced as read-only [#317](https://github.com/emsesp/EMS-ESP32/issues/317) ### Fixed From fe3e02cb2e232ba34dce3c39d0d2796aacfdb813 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 22:12:49 +0200 Subject: [PATCH 12/15] added tooltip --- .../src/project/SettingsCustomization.tsx | 53 +++++++++++-------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/interface/src/project/SettingsCustomization.tsx b/interface/src/project/SettingsCustomization.tsx index 2705dfbad..bc245fe5b 100644 --- a/interface/src/project/SettingsCustomization.tsx +++ b/interface/src/project/SettingsCustomization.tsx @@ -14,7 +14,8 @@ import { DialogContent, DialogTitle, ToggleButton, - ToggleButtonGroup + ToggleButtonGroup, + Tooltip } from '@mui/material'; import TableCell, { tableCellClasses } from '@mui/material/TableCell'; @@ -29,7 +30,6 @@ import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined'; import FavoriteBorderOutlinedIcon from '@mui/icons-material/FavoriteBorderOutlined'; import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined'; import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined'; - import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore'; import { ButtonRow, FormLoader, ValidatedTextField, SectionContent } from '../components'; @@ -59,7 +59,7 @@ const SettingsCustomization: FC = () => { const [errorMessage, setErrorMessage] = useState(); const [selectedDevice, setSelectedDevice] = useState(0); const [confirmReset, setConfirmReset] = useState(false); - const [masks, setMasks] = useState(() => ['fav', 'readonly', 'exclude_mqtt', 'exclude_web']); + const [masks, setMasks] = useState(() => ['1']); const fetchDevices = useCallback(async () => { try { @@ -117,7 +117,8 @@ const SettingsCustomization: FC = () => { <> - Customize which entities to exclude. This will have immediate effect on all services including MQTT and API. + You can mark an entity as a favorite to be listed first in the Web Dashboard, or remove it from the + Dashboard, or disable it's write operation or exclude it from the MQTT and API outputs. { const setMask = (de: DeviceEntity, newMask: string[]) => { var new_mask = 0; - if (newMask.includes('exclude_web')) { + if (newMask.includes('1')) { new_mask |= 1; } - if (newMask.includes('exclude_mqtt')) { + if (newMask.includes('2')) { new_mask |= 2; } - if (newMask.includes('readonly')) { + if (newMask.includes('4')) { new_mask |= 4; } - if (newMask.includes('fav')) { + if (newMask.includes('8')) { new_mask |= 8; } @@ -188,19 +189,19 @@ const SettingsCustomization: FC = () => { setMasks(newMask); }; - const getValue = (de: DeviceEntity) => { + const getMask = (de: DeviceEntity) => { var new_masks = []; if ((de.m & 1) === 1) { - new_masks.push('exclude_web'); + new_masks.push('1'); } if ((de.m & 2) === 2) { - new_masks.push('exclude_mqtt'); + new_masks.push('2'); } if ((de.m & 4) === 4) { - new_masks.push('readonly'); + new_masks.push('4'); } if ((de.m & 8) === 8) { - new_masks.push('fav'); + new_masks.push('8'); } return new_masks; @@ -222,22 +223,30 @@ const SettingsCustomization: FC = () => { { setMask(de, mask); }} > - - + + + + - - + + + + - - + + + + - - + + + +
From 7a67577aa19a3c4482a2ada240d813c283e5ed09 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 22:13:04 +0200 Subject: [PATCH 13/15] added w (writeable) --- interface/src/project/types.ts | 1 + mock-api/server.js | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts index 5bcf45dad..f9537f1d1 100644 --- a/interface/src/project/types.ts +++ b/interface/src/project/types.ts @@ -147,6 +147,7 @@ export interface DeviceEntity { n: string; // name s: string; // shortname m: number; // mask + w?: boolean; // writeable i: number; // unique id } diff --git a/mock-api/server.js b/mock-api/server.js index 5942773dd..2539f9a54 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -344,19 +344,19 @@ const emsesp_devices = { i: 1, d: 23, p: 77, - s: 'Thermostat1', + s: 'Thermostat1 (RC20/Moduline 300)', }, { i: 2, d: 8, p: 123, - s: 'Boiler', + s: 'Boiler (Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i)', }, { i: 4, d: 16, p: 165, - s: 'Thermostat2', + s: 'Thermostat2 (RC100/Moduline 1000/1010)', }, ], } @@ -450,7 +450,7 @@ const status = { // Dashboard data const emsesp_devicedata_1 = { - label: 'RC20/Moduline 300', + label: 'Thermostat: RC20/Moduline 300', data: [ { v: '(0)', @@ -567,7 +567,7 @@ const emsesp_devicedata_2 = { } const emsesp_devicedata_4 = { - label: 'RC100/Moduline 1000/1010', + label: 'Thermostat: RC100/Moduline 1000/1010', data: [ { v: 16, @@ -610,6 +610,7 @@ const emsesp_deviceentities_1 = [ n: 'hc1 selected room temperature', s: 'hc1/seltemp', m: 0, + w: true, i: 3, }, { @@ -624,6 +625,7 @@ const emsesp_deviceentities_1 = [ n: 'hc1 mode', s: 'hc1/mode', m: 0, + w: true, i: 5, }, ] From f3b7d33372a0210c7006b83b60358b694d3906c8 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 22:13:13 +0200 Subject: [PATCH 14/15] bump b10 --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index d5f57b3ce..bf2f94b81 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.4.0b9" +#define EMSESP_APP_VERSION "3.4.0b10" From 3853c6ca188d24c684e42e2edaa1f0ea6d2bbd1c Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 27 Mar 2022 22:14:20 +0200 Subject: [PATCH 15/15] added tooltip back to be consistent with other table actions --- interface/src/project/DashboardData.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/project/DashboardData.tsx b/interface/src/project/DashboardData.tsx index 8d7b043b5..eccda938c 100644 --- a/interface/src/project/DashboardData.tsx +++ b/interface/src/project/DashboardData.tsx @@ -20,7 +20,8 @@ import { ListItem, ListItemText, Grid, - useMediaQuery + useMediaQuery, + Tooltip } from '@mui/material'; import TableCell, { tableCellClasses } from '@mui/material/TableCell'; @@ -525,7 +526,9 @@ const DashboardData: FC = () => { {dv.c && me.admin && ( - + + + )}