diff --git a/.vscode/settings.json b/.vscode/settings.json index 6cd3e6dd1..970fb6b8c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,6 +25,8 @@ "regex": "cpp", "tuple": "cpp", "type_traits": "cpp", - "utility": "cpp" + "utility": "cpp", + "string": "cpp", + "string_view": "cpp" } } diff --git a/interface/src/i18n/de/index.ts b/interface/src/i18n/de/index.ts index 39fa06348..e87be85aa 100644 --- a/interface/src/i18n/de/index.ts +++ b/interface/src/i18n/de/index.ts @@ -37,7 +37,6 @@ const de: Translation = { BRAND: 'Marke', ENTITY_NAME: 'Entitätsname', VALUE: '{{Wert|wert}}', - SHOW_FAV: 'nur Favoriten anzeigen', DEVICE_DATA: 'Gerätedaten', SENSOR_DATA: 'Sensordaten', DEVICES: 'Geräte', diff --git a/interface/src/i18n/en/index.ts b/interface/src/i18n/en/index.ts index 601df0120..9982ada54 100644 --- a/interface/src/i18n/en/index.ts +++ b/interface/src/i18n/en/index.ts @@ -37,7 +37,6 @@ const en: Translation = { BRAND: 'Brand', ENTITY_NAME: 'Entity Name', VALUE: '{{Value|value}}', - SHOW_FAV: 'only show favorites', DEVICE_DATA: 'Device Data', SENSOR_DATA: 'Sensor Data', DEVICES: 'Devices', diff --git a/interface/src/i18n/fr/index.ts b/interface/src/i18n/fr/index.ts index bf269cf24..26b7a1cd1 100644 --- a/interface/src/i18n/fr/index.ts +++ b/interface/src/i18n/fr/index.ts @@ -37,7 +37,6 @@ const fr: Translation = { BRAND: 'Marque', ENTITY_NAME: 'Nom de l\'entité', VALUE: 'Valeur', - SHOW_FAV: 'ne montrer que les favoris', DEVICE_DATA: 'Données des appareils', SENSOR_DATA: 'Données des capteurs', DEVICES: 'Appareils', diff --git a/interface/src/i18n/nl/index.ts b/interface/src/i18n/nl/index.ts index 10bfd83d3..f99466172 100644 --- a/interface/src/i18n/nl/index.ts +++ b/interface/src/i18n/nl/index.ts @@ -37,7 +37,6 @@ const nl: Translation = { BRAND: 'Merk', ENTITY_NAME: 'Entiteit', VALUE: '{{Waarde|waarde}}', - SHOW_FAV: 'alleen favorieten weergeven', SENSOR_DATA: 'Sensor data', DEVICE_DATA: 'Apparaat data', DEVICES: 'Apparaten', diff --git a/interface/src/i18n/no/index.ts b/interface/src/i18n/no/index.ts index 226a67e87..6385064d7 100644 --- a/interface/src/i18n/no/index.ts +++ b/interface/src/i18n/no/index.ts @@ -37,7 +37,6 @@ const no: Translation = { BRAND: 'Fabrikat', ENTITY_NAME: 'Objektsnavn', VALUE: '{{Verdi|verdi}}', - SHOW_FAV: ' Vis kun favoritter', DEVICE_DATA: 'Enheterdata', SENSOR_DATA: 'Sensordata', DEVICES: 'Enheter', diff --git a/interface/src/i18n/pl/index.ts b/interface/src/i18n/pl/index.ts index 881591adf..73b9c8689 100644 --- a/interface/src/i18n/pl/index.ts +++ b/interface/src/i18n/pl/index.ts @@ -37,7 +37,6 @@ const pl: BaseTranslation = { VERSION: 'Wersja', ENTITY_NAME: 'Nazwa encji', VALUE: '{{W|w|}}artość', - SHOW_FAV: 'Pokaż tylko "ulubione"', DEVICE_DATA: 'Dane z urządzeń', SENSOR_DATA: 'Dane z czujników', DEVICES: 'Urządzenia', diff --git a/interface/src/i18n/sv/index.ts b/interface/src/i18n/sv/index.ts index fe9a9c8e1..0fa2a02e6 100644 --- a/interface/src/i18n/sv/index.ts +++ b/interface/src/i18n/sv/index.ts @@ -37,7 +37,6 @@ const sv: Translation = { BRAND: 'Fabrikat', ENTITY_NAME: 'Entitetsnamn', VALUE: '{{Värde|värde}}', - SHOW_FAV: 'Visa enbart favoriter', DEVICE_DATA: 'Enhets data', SENSOR_DATA: 'Sensor data', DEVICES: 'Enheter', diff --git a/interface/src/i18n/tr/index.ts b/interface/src/i18n/tr/index.ts index c4bbc7665..46598d4fd 100644 --- a/interface/src/i18n/tr/index.ts +++ b/interface/src/i18n/tr/index.ts @@ -37,7 +37,6 @@ const tr: Translation = { BRAND: 'Marka', ENTITY_NAME: 'Valık Adı', VALUE: '{{Değer|değer}}', - SHOW_FAV: 'sadece favorileri göster', DEVICE_DATA: 'Cihaz Bilgisi', SENSOR_DATA: 'Sensör Bilgisi', DEVICES: 'Cihazlar', diff --git a/interface/src/project/DashboardDevices.tsx b/interface/src/project/DashboardDevices.tsx index 9cf569e11..f1bf7b881 100644 --- a/interface/src/project/DashboardDevices.tsx +++ b/interface/src/project/DashboardDevices.tsx @@ -9,6 +9,7 @@ import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutl import PlayArrowIcon from '@mui/icons-material/PlayArrow'; import RefreshIcon from '@mui/icons-material/Refresh'; import StarIcon from '@mui/icons-material/Star'; +import StarBorderOutlinedIcon from '@mui/icons-material/StarBorderOutlined'; import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined'; import { @@ -21,8 +22,6 @@ import { List, ListItem, ListItemText, - FormControlLabel, - Checkbox, Box, Grid, Typography @@ -54,13 +53,15 @@ import { extractErrorMessage } from 'utils'; const DashboardDevices: FC = () => { const { me } = useContext(AuthenticatedContext); const { LL } = useI18nContext(); - const [deviceData, setDeviceData] = useState({ label: '', data: [] }); + const [deviceData, setDeviceData] = useState({ data: [] }); const [selectedDeviceValue, setSelectedDeviceValue] = useState(); - const [deviceDetails, setDeviceDetails] = useState(-1); const [onlyFav, setOnlyFav] = useState(false); - const [selectedDevice, setSelectedDevice] = useState(); const [deviceValueDialogOpen, setDeviceValueDialogOpen] = useState(false); + const [showDeviceInfo, setShowDeviceInfo] = useState(false); + + const [selectedDevice, setSelectedDevice] = useState(); + const [coreData, setCoreData] = useState({ connected: true, devices: [] @@ -95,11 +96,6 @@ const DashboardDevices: FC = () => { border-top: 1px solid #177ac9; border-bottom: 1px solid #177ac9; } - `, - Cell: ` - &:last-of-type { - text-align: right; - }, ` }); @@ -107,7 +103,7 @@ const DashboardDevices: FC = () => { common_theme, { Table: ` - --data-table-library_grid-template-columns: 40px 160px repeat(1, minmax(0, 1fr)) 100px 40px; + --data-table-library_grid-template-columns: 40px 160px repeat(1, minmax(0, 1fr)); `, BaseRow: ` .td { @@ -136,7 +132,11 @@ const DashboardDevices: FC = () => { Table: ` --data-table-library_grid-template-columns: 300px 150px 40px; height: auto; - max-height: 92%; + max-height: 96%; + overflow-y: scroll; + ::-webkit-scrollbar { + display:none; + } `, BaseCell: ` &:nth-of-type(2) { @@ -192,6 +192,7 @@ const DashboardDevices: FC = () => { }; function onSelectChange(action: any, state: any) { + setDeviceData({ data: [] }); setSelectedDevice(state.id); if (action.type === 'ADD_BY_ID_EXCLUSIVELY') { void fetchDeviceData(state.id); @@ -205,13 +206,20 @@ const DashboardDevices: FC = () => { } ); - const escFunction = useCallback((event) => { - if (event.keyCode === 27) { - if (device_select) { - device_select.fns.onRemoveAll(); + const resetDeviceSelect = () => { + device_select.fns.onRemoveAll(); + }; + + const escFunction = useCallback( + (event: any) => { + if (event.keyCode === 27) { + if (device_select) { + resetDeviceSelect(); + } } - } - }, []); + }, + [device_select] + ); useEffect(() => { document.addEventListener('keydown', escFunction); @@ -288,10 +296,18 @@ const DashboardDevices: FC = () => { }, { accessor: (dv: any) => DeviceValueUOM_s[dv.u], name: 'UoM' } ]; + + // TODO create filename from selected device + const deviceIndex = coreData.devices.findIndex((d) => d.id === device_select.state.id); + if (deviceIndex === -1) { + return; + } + const filename = coreData.devices[deviceIndex].tn + '_' + coreData.devices[deviceIndex].n; + downloadAsCsv( columns, onlyFav ? deviceData.data.filter((dv) => hasMask(dv.id, DeviceEntityMask.DV_FAVORITE)) : deviceData.data, - 'device_entities' + filename ); }; @@ -326,42 +342,47 @@ const DashboardDevices: FC = () => { }; const renderDeviceDetails = () => { - if (coreData && coreData.devices.length > 0 && deviceDetails !== -1) { - const device = coreData.devices[deviceDetails]; + if (showDeviceInfo) { + // find record based on device_seelct.state.id + const deviceIndex = coreData.devices.findIndex((d) => d.id === device_select.state.id); + if (deviceIndex === -1) { + return; + } + return ( - setDeviceDetails(-1)}> + setShowDeviceInfo(false)}> {LL.DEVICE_DETAILS()} - + - + - {device.t !== DeviceType.CUSTOM && ( + {coreData.devices[deviceIndex].t !== DeviceType.CUSTOM && ( <> - + - + - + )} - @@ -385,24 +406,16 @@ const DashboardDevices: FC = () => { {LL.TYPE(0)} {LL.DESCRIPTION()} - {LL.ENTITIES()} - - {tableList.map((device: Device, index: number) => ( + {tableList.map((device: Device) => ( {device.tn} {device.n} - {device.e} - - setDeviceDetails(index)}> - - - ))} @@ -439,13 +452,28 @@ const DashboardDevices: FC = () => { ); + const shown_data = onlyFav + ? deviceData.data.filter((dv) => hasMask(dv.id, DeviceEntityMask.DV_FAVORITE)) + : deviceData.data; + + function truncate(str, length) { + if (str.length > length) { + return str.slice(0, length) + '...'; + } else return str; + } + + const deviceIndex = coreData.devices.findIndex((d) => d.id === device_select.state.id); + if (deviceIndex === -1) { + return; + } + return ( { > - {deviceData.label} + + {truncate(coreData.devices[deviceIndex].n, 35)} +  ({shown_data.length}) + setShowDeviceInfo(true)}> + + + + + + setOnlyFav(!onlyFav)}> + {onlyFav ? ( + + ) : ( + + )} + + - - hasMask(dv.id, DeviceEntityMask.DV_FAVORITE)) - : deviceData.data - }} + data={{ nodes: shown_data }} theme={data_theme} sort={dv_sort} layout={{ custom: true, fixedHeader: true }} diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts index 5ffffbacb..96d2f76b7 100644 --- a/interface/src/project/types.ts +++ b/interface/src/project/types.ts @@ -68,7 +68,6 @@ export interface Device { d: number; // deviceid p: number; // productid v: string; // version - e: number; // number of entries } export interface TemperatureSensor { @@ -134,7 +133,6 @@ export interface DeviceValue { } export interface DeviceData { - label: string; data: DeviceValue[]; } diff --git a/mock-api/server.js b/mock-api/server.js index 27cbe92eb..2f53de7a0 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -395,8 +395,7 @@ const emsesp_coredata = { n: 'GBx72/Trendline/Cerapur/Greenstar Si/27i', d: 8, p: 123, - v: '06.01', - e: 68 + v: '06.01' }, { id: 3, @@ -406,8 +405,7 @@ const emsesp_coredata = { n: 'GB125/GB135/MC10', d: 8, p: 123, - v: '06.01', - e: 56 + v: '06.01' }, { id: 1, @@ -417,8 +415,7 @@ const emsesp_coredata = { n: 'RC35', d: 24, p: 86, - v: '04.01', - e: 58 + v: '04.01' }, { id: 2, @@ -428,8 +425,7 @@ const emsesp_coredata = { n: 'RC20/Moduline 300', d: 23, p: 77, - v: '03.03', - e: 6 + v: '03.03' }, { id: 4, @@ -439,8 +435,7 @@ const emsesp_coredata = { n: 'RC100/Moduline 1000/1010', d: 16, p: 165, - v: '04.01', - e: 3 + v: '04.01' }, { id: 5, @@ -450,8 +445,7 @@ const emsesp_coredata = { n: 'MM10', d: 32, p: 69, - v: '01.01', - e: 6 + v: '01.01' }, { id: 6, @@ -461,8 +455,7 @@ const emsesp_coredata = { n: 'SM10', d: 48, p: 73, - v: '01.02', - e: 16 + v: '01.02' }, { id: 99, @@ -472,8 +465,7 @@ const emsesp_coredata = { n: 'User defined entities', d: 1, p: 1, - v: '', - e: 1 + v: '' } ] }; @@ -526,7 +518,6 @@ const status = { // 99 - Custom const emsesp_devicedata_7 = { - label: 'Boiler: Nefit GBx72/Trendline/Cerapur/Greenstar Si/27i', data: [ { v: '', u: 0, id: '08reset', c: 'reset', l: ['-', 'maintenance', 'error'] }, { v: 'off', u: 0, id: '08heating active' }, @@ -607,7 +598,6 @@ const emsesp_devicedata_7 = { }; const emsesp_devicedata_1 = { - label: 'Thermostat: RC35', data: [ { v: '22(816) 01.05.2023 13:07 (1 min)', @@ -1040,7 +1030,6 @@ const emsesp_devicedata_1 = { }; const emsesp_devicedata_2 = { - label: 'Thermostat: RC20/Moduline 300', data: [ { v: '(0)', @@ -1084,7 +1073,6 @@ const emsesp_devicedata_2 = { }; const emsesp_devicedata_3 = { - label: 'Boiler: GB125/GB135/MC10', data: [ { v: '', @@ -1557,7 +1545,6 @@ const emsesp_devicedata_3 = { }; const emsesp_devicedata_4 = { - label: 'Thermostat: RC100/Moduline 1000/1010', data: [ { v: 16, @@ -1582,7 +1569,6 @@ const emsesp_devicedata_4 = { }; const emsesp_devicedata_5 = { - label: 'Mixer Module: MM10', data: [ { v: 30, @@ -1630,7 +1616,6 @@ const emsesp_devicedata_5 = { }; const emsesp_devicedata_6 = { - label: 'Solar Module: SM10', data: [ { v: 43.9, @@ -1780,7 +1765,6 @@ const emsesp_devicedata_6 = { }; const emsesp_devicedata_99 = { - label: 'User defined entities', data: [ { v: 5, diff --git a/src/emsdevice.cpp b/src/emsdevice.cpp index ff26bc870..891aca0e0 100644 --- a/src/emsdevice.cpp +++ b/src/emsdevice.cpp @@ -824,8 +824,9 @@ std::string EMSdevice::get_value_uom(const char * key) const { // 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, 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"); + // output["label"] = to_string_short(); + // output["label"] = name_; + JsonArray data = output.createNestedArray("data"); for (auto & dv : devicevalues_) { auto fullname = dv.get_fullname(); diff --git a/src/emsesp.cpp b/src/emsesp.cpp index b298a3c21..e693c627c 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -340,7 +340,7 @@ void EMSESP::dump_all_values(uuid::console::Shell & shell) { if (device.product_id == 160) { // MM100 device_id = 0x28; // wwc } else { - device_id = 0x20; // hc + device_id = 0x20; // hc } } else { device_id = 0x20; // should cover all the other device types @@ -906,7 +906,7 @@ bool EMSESP::process_telegram(std::shared_ptr telegram) { if (telegram->type_id == publish_id_) { publish_id_ = 0; } - emsdevice->has_update(false); // reset flag + emsdevice->has_update(false); // reset flag if (!Mqtt::publish_single()) { publish_device_values(emsdevice->device_type()); // publish to MQTT if we explicitly have too } @@ -1098,7 +1098,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const name = "Modem"; device_type = DeviceType::CONNECT; } else if (device_id == EMSdevice::EMS_DEVICE_ID_CONVERTER) { - name = "Converter"; // generic + name = "Converter"; // generic } else if (device_id == EMSdevice::EMS_DEVICE_ID_CLOCK) { name = "Clock"; // generic device_type = DeviceType::CONTROLLER; @@ -1124,6 +1124,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const emsdevices.push_back(EMSFactory::add(device_type, device_id, product_id, version, name, flags, brand)); // assign a unique ID. Note that this is not actual unique after a restart as it's dependent on the order that devices are found + // can't be 0 otherwise web won't work emsdevices.back()->unique_id(++unique_id_count_); // sort devices based on type @@ -1365,7 +1366,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) { #endif Roomctrl::check((data[1] ^ 0x80 ^ rxservice_.ems_mask()), data); // check if there is a message for the roomcontroller - rxservice_.add(data, length); // add to RxQueue + rxservice_.add(data, length); // add to RxQueue } } @@ -1465,7 +1466,7 @@ void EMSESP::start() { system_.system_restart(); }; - system_.reload_settings(); // ... and store some of the settings locally + system_.reload_settings(); // ... and store some of the settings locally webCustomizationService.begin(); // load the customizations webSchedulerService.begin(); // load the scheduler events @@ -1483,16 +1484,16 @@ void EMSESP::start() { } // start all the EMS-ESP services - mqtt_.start(); // mqtt init + mqtt_.start(); // mqtt init system_.start(); // starts commands, led, adc, button, network, syslog & uart LOG_INFO(("Starting EMS-ESP version %s (hostname: %s)"), EMSESP_APP_VERSION, system_.hostname().c_str()); // welcome message - shower_.start(); // initialize shower timer and shower alert - temperaturesensor_.start(); // Temperature external sensors - analogsensor_.start(); // Analog external sensors - webLogService.start(); // apply settings to weblog service + shower_.start(); // initialize shower timer and shower alert + temperaturesensor_.start(); // Temperature external sensors + analogsensor_.start(); // Analog external sensors + webLogService.start(); // apply settings to weblog service // Load our library of known devices into stack mem. Names are stored in Flash memory device_library_ = { diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index 14aee85ff..054082011 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -88,7 +88,7 @@ void WebDataService::core_data(AsyncWebServerRequest * request) { obj["d"] = emsdevice->device_id(); // deviceid obj["p"] = emsdevice->product_id(); // productid obj["v"] = emsdevice->version(); // version - obj["e"] = emsdevice->count_entities(); // number of entities (device values) + // obj["e"] = emsdevice->count_entities(); // number of entities (device values) } } @@ -103,7 +103,7 @@ void WebDataService::core_data(AsyncWebServerRequest * request) { obj["d"] = 0; // deviceid obj["p"] = 0; // productid obj["v"] = 0; // version - obj["e"] = EMSESP::webEntityService.count_entities(); // number of entities (device values) + // obj["e"] = EMSESP::webEntityService.count_entities(); // number of entities (device values) } root["connected"] = EMSESP::bus_status() != 2;