diff --git a/interface/src/framework/system/GeneralFileUpload.tsx b/interface/src/framework/system/GeneralFileUpload.tsx index b3a291ca0..d1ef50e66 100644 --- a/interface/src/framework/system/GeneralFileUpload.tsx +++ b/interface/src/framework/system/GeneralFileUpload.tsx @@ -1,21 +1,15 @@ -import { FC } from 'react'; -import { AxiosPromise } from 'axios'; - +import DownloadIcon from '@mui/icons-material/GetApp'; import { Typography, Button, Box } from '@mui/material'; - -import { FileUploadConfig } from 'api/endpoints'; +import { toast } from 'react-toastify'; +import type { FileUploadConfig } from 'api/endpoints'; +import type { AxiosPromise } from 'axios'; +import type { FC } from 'react'; import { SingleUpload, useFileUpload } from 'components'; -import DownloadIcon from '@mui/icons-material/GetApp'; - -import { toast } from 'react-toastify'; - -import { extractErrorMessage } from 'utils'; - -import * as EMSESP from 'project/api'; - import { useI18nContext } from 'i18n/i18n-react'; +import * as EMSESP from 'project/api'; +import { extractErrorMessage } from 'utils'; interface UploadFileProps { uploadGeneralFile: (file: File, config?: FileUploadConfig) => AxiosPromise; @@ -145,7 +139,7 @@ const GeneralFileUpload: FC = ({ uploadGeneralFile }) => { color="primary" onClick={() => downloadEntities()} > - {LL.ENTITIES()} + {LL.CUSTOM_ENTITIES(0)} diff --git a/interface/src/i18n/de/index.ts b/interface/src/i18n/de/index.ts index ac9dcf90e..e00ae0f54 100644 --- a/interface/src/i18n/de/index.ts +++ b/interface/src/i18n/de/index.ts @@ -321,6 +321,7 @@ const de: Translation = { SCHEDULE_TIMER_3: 'jede Stunde', CUSTOM_ENTITIES: 'Individuelle Entitäten', ENTITIES_HELP_1: 'Abfrage von Werten auf dem EMS-Bus', + ENTITIES_SAVED: 'Entities Saved', // TODO translate WRITEABLE: 'Schreibbar' }; diff --git a/interface/src/i18n/en/index.ts b/interface/src/i18n/en/index.ts index ba5a5d8d7..30ec9f2fd 100644 --- a/interface/src/i18n/en/index.ts +++ b/interface/src/i18n/en/index.ts @@ -321,6 +321,7 @@ const en: Translation = { SCHEDULE_TIMER_3: 'every hour', CUSTOM_ENTITIES: 'Custom Entities', ENTITIES_HELP_1: 'Fetch custom entities from the EMS bus', + ENTITIES_SAVED: 'Entities Saved', WRITEABLE: 'Writeable' }; diff --git a/interface/src/i18n/formatters.ts b/interface/src/i18n/formatters.ts index b9d999653..592a53490 100644 --- a/interface/src/i18n/formatters.ts +++ b/interface/src/i18n/formatters.ts @@ -1,5 +1,5 @@ -import type { FormattersInitializer } from 'typesafe-i18n'; import type { Locales, Formatters } from './i18n-types'; +import type { FormattersInitializer } from 'typesafe-i18n'; export const initFormatters: FormattersInitializer = (locale: Locales) => { const formatters: Formatters = { diff --git a/interface/src/i18n/fr/index.ts b/interface/src/i18n/fr/index.ts index bac7958d0..86a8f4d8d 100644 --- a/interface/src/i18n/fr/index.ts +++ b/interface/src/i18n/fr/index.ts @@ -321,6 +321,7 @@ const fr: Translation = { SCHEDULE_TIMER_3: 'every hour', // TODO translate CUSTOM_ENTITIES: 'Custom Entities', // TODO translate ENTITIES_HELP_1: 'Fetch custom entities from the EMS bus', // TODO translate + ENTITIES_SAVED: 'Entities Saved', // TODO translate WRITEABLE: 'Writeable' // TODO translate }; diff --git a/interface/src/i18n/nl/index.ts b/interface/src/i18n/nl/index.ts index a468ba134..2e78472ea 100644 --- a/interface/src/i18n/nl/index.ts +++ b/interface/src/i18n/nl/index.ts @@ -321,6 +321,7 @@ const nl: Translation = { SCHEDULE_TIMER_3: 'every hour', // TODO translate CUSTOM_ENTITIES: 'Custom Entities', // TODO translate ENTITIES_HELP_1: 'Fetch custom entities from the EMS bus', // TODO translate + ENTITIES_SAVED: 'Entities Saved', // TODO translate WRITEABLE: 'Writeable' // TODO translate }; diff --git a/interface/src/i18n/no/index.ts b/interface/src/i18n/no/index.ts index 34081696b..8d62adf01 100644 --- a/interface/src/i18n/no/index.ts +++ b/interface/src/i18n/no/index.ts @@ -321,6 +321,7 @@ const no: Translation = { SCHEDULE_TIMER_3: 'hver time', CUSTOM_ENTITIES: 'Custom Entities', // TODO translate ENTITIES_HELP_1: 'Fetch custom entities from the EMS bus', // TODO translate + ENTITIES_SAVED: 'Entities Saved', // TODO translate WRITEABLE: 'Writeable' // TODO translate }; diff --git a/interface/src/i18n/pl/index.ts b/interface/src/i18n/pl/index.ts index 4a85f60e2..f770bf952 100644 --- a/interface/src/i18n/pl/index.ts +++ b/interface/src/i18n/pl/index.ts @@ -24,7 +24,7 @@ const pl: BaseTranslation = { SECURITY: '{{B|b|}}ezpieczeństw{{o|a|}}', ONOFF_CAP: 'wł./wył.', ONOFF: 'włączono/wyłączono', - TYPE: 'Typ', + TYPE: '{{T|t|}}yp{{|u|}}', DESCRIPTION: 'Opis', ENTITIES: 'Encje', REFRESH: 'Odśwież', @@ -240,7 +240,7 @@ const pl: BaseTranslation = { MQTT_RESPONSE: 'Rezultat wykonania komendy publikuj w temacie "response"', MQTT_PUBLISH_TEXT_1: 'Tematy z pojedynczą wartością publikuj po jej zmianie', MQTT_PUBLISH_TEXT_2: 'Publikuj w tematach "command" (ioBroker)', - MQTT_PUBLISH_TEXT_3: 'Włącz opcję "MQTT discovery', + MQTT_PUBLISH_TEXT_3: 'Włącz opcję "MQTT discovery"', MQTT_PUBLISH_TEXT_4: 'Prefiks dla "MQTT discovery"', MQTT_PUBLISH_TEXT_5: 'Typ "MQTT discovery"', MQTT_PUBLISH_INTERVALS: 'Interwały publikowania', @@ -287,7 +287,7 @@ const pl: BaseTranslation = { NETWORK_BLANK_SSID: 'pozostaw puste aby wyłączyć WiFi', TX_POWER: 'Moc nadawania', HOSTNAME: 'Nazwa w sieci', - NETWORK_DISABLE_SLEEP: 'Wyłącz tryb usypiania WiFi', + NETWORK_DISABLE_SLEEP: 'Wyłącz tryb uśpienia WiFi', NETWORK_LOW_BAND: 'Używaj mniejszej szerokości pasma WiFi (20MHz)', NETWORK_USE_DNS: 'Włącz wsparcie dla mDNS', NETWORK_ENABLE_CORS: 'Włącz wsparcie dla CORS', @@ -300,7 +300,7 @@ const pl: BaseTranslation = { ADDRESS_OF: 'Adres {0}', ADMIN: 'Użytkownik "administrator".', GUEST: 'Użytkownik "gość".', - NEW: 'nowego', + NEW: 'nowe{{go|j|}}', NEW_NAME_OF: 'Nowa nazwa {0}', ENTITY: 'encji', MIN: 'Min.', @@ -319,8 +319,9 @@ const pl: BaseTranslation = { SCHEDULE_TIMER_1: 'przy starcie', SCHEDULE_TIMER_2: 'co minutę', SCHEDULE_TIMER_3: 'co godzinę', - CUSTOM_ENTITIES: 'Custom Entities', // TODO translate - ENTITIES_HELP_1: 'Fetch custom entities from the EMS bus', + CUSTOM_ENTITIES: '{{N|n|}}iestandardowe{{|j|}} encj{{e|i|}}', + ENTITIES_HELP_1: 'Zdefiniuj niestandardowe encje pobierane z magistrali EMS.', + ENTITIES_SAVED: 'Niestandardowe encje zostały uaktualnione.', WRITEABLE: 'Writeable' // TODO translate }; diff --git a/interface/src/i18n/sv/index.ts b/interface/src/i18n/sv/index.ts index 3d6873122..1cf0e7301 100644 --- a/interface/src/i18n/sv/index.ts +++ b/interface/src/i18n/sv/index.ts @@ -321,6 +321,7 @@ const sv: Translation = { SCHEDULE_TIMER_3: 'every hour', // TODO translate CUSTOM_ENTITIES: 'Custom Entities', // TODO translate ENTITIES_HELP_1: 'Fetch custom entities from the EMS bus', // TODO translate + ENTITIES_SAVED: 'Entities Saved', // TODO translate WRITEABLE: 'Writeable' // TODO translate }; diff --git a/interface/src/i18n/tr/index.ts b/interface/src/i18n/tr/index.ts index 61867b860..5ea666083 100644 --- a/interface/src/i18n/tr/index.ts +++ b/interface/src/i18n/tr/index.ts @@ -321,6 +321,7 @@ const tr: Translation = { SCHEDULE_TIMER_3: 'every hour', // TODO translate CUSTOM_ENTITIES: 'Custom Entities', // TODO translate ENTITIES_HELP_1: 'Fetch custom entities from the EMS bus', // TODO translate + ENTITIES_SAVED: 'Entities Saved', // TODO translate WRITEABLE: 'Writeable' // TODO translate }; diff --git a/interface/src/project/DashboardData.tsx b/interface/src/project/DashboardData.tsx index 15ffcc6cf..ce415cd55 100644 --- a/interface/src/project/DashboardData.tsx +++ b/interface/src/project/DashboardData.tsx @@ -1,5 +1,19 @@ -import { FC, useState, useContext, useCallback, useEffect } from 'react'; - +import AddCircleOutlineOutlinedIcon from '@mui/icons-material/AddCircleOutlineOutlined'; +import CancelIcon from '@mui/icons-material/Cancel'; +import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined'; +import EditIcon from '@mui/icons-material/Edit'; +import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined'; +import DownloadIcon from '@mui/icons-material/GetApp'; +import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; +import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined'; +import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined'; +import PlayArrowIcon from '@mui/icons-material/PlayArrow'; +import RefreshIcon from '@mui/icons-material/Refresh'; +import RemoveIcon from '@mui/icons-material/RemoveCircleOutline'; +import StarIcon from '@mui/icons-material/Star'; +import SendIcon from '@mui/icons-material/TrendingFlat'; +import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined'; +import WarningIcon from '@mui/icons-material/Warning'; import { Button, Typography, @@ -19,59 +33,26 @@ import { FormControlLabel, Checkbox } from '@mui/material'; - -import { toast } from 'react-toastify'; - -import { useTheme } from '@table-library/react-table-library/theme'; +import { useRowSelect } from '@table-library/react-table-library/select'; import { useSort, SortToggleType } from '@table-library/react-table-library/sort'; import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table'; -import { useRowSelect } from '@table-library/react-table-library/select'; - -import DownloadIcon from '@mui/icons-material/GetApp'; -import RefreshIcon from '@mui/icons-material/Refresh'; -import EditIcon from '@mui/icons-material/Edit'; -import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; -import AddCircleOutlineOutlinedIcon from '@mui/icons-material/AddCircleOutlineOutlined'; -import CancelIcon from '@mui/icons-material/Cancel'; -import SendIcon from '@mui/icons-material/TrendingFlat'; -import WarningIcon from '@mui/icons-material/Warning'; -import RemoveIcon from '@mui/icons-material/RemoveCircleOutline'; -import PlayArrowIcon from '@mui/icons-material/PlayArrow'; -import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined'; -import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined'; -import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined'; -import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined'; -import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined'; -import StarIcon from '@mui/icons-material/Star'; - -import DeviceIcon from './DeviceIcon'; +import { useTheme } from '@table-library/react-table-library/theme'; +import { useState, useContext, useCallback, useEffect } from 'react'; import { IconContext } from 'react-icons'; - -import { AuthenticatedContext } from 'contexts/authentication'; - -import { ButtonRow, ValidatedTextField, SectionContent, MessageBox } from 'components'; +import { toast } from 'react-toastify'; +import DeviceIcon from './DeviceIcon'; import * as EMSESP from './api'; -import { numberValue, updateValue, extractErrorMessage } from 'utils'; - -import { - SensorData, - Device, - CoreData, - DeviceData, - DeviceValue, - DeviceValueUOM, - DeviceValueUOM_s, - AnalogType, - AnalogTypeNames, - Sensor, - Analog, - DeviceEntityMask -} from './types'; +import { DeviceValueUOM, DeviceValueUOM_s, AnalogType, AnalogTypeNames, DeviceEntityMask } from './types'; +import type { SensorData, Device, CoreData, DeviceData, DeviceValue, Sensor, Analog } from './types'; +import type { FC } from 'react'; +import { ButtonRow, ValidatedTextField, SectionContent, MessageBox } from 'components'; +import { AuthenticatedContext } from 'contexts/authentication'; import { useI18nContext } from 'i18n/i18n-react'; +import { numberValue, updateValue, extractErrorMessage } from 'utils'; const DashboardData: FC = () => { const { me } = useContext(AuthenticatedContext); @@ -301,20 +282,20 @@ const DashboardData: FC = () => { }, [LL]); useEffect(() => { - fetchCoreData(); + void fetchCoreData(); }, [fetchCoreData]); const refreshDataIndex = (selectedDevice: string) => { if (selectedDevice === 'sensor') { - fetchSensorData(); + void fetchSensorData(); return; } setSensorData({ sensors: [], analogs: [] }); if (selectedDevice) { - fetchDeviceData(selectedDevice); + void fetchDeviceData(selectedDevice); } else { - fetchCoreData(); + void fetchCoreData(); } }; @@ -344,11 +325,12 @@ const DashboardData: FC = () => { return sc; }; - const makeCsvData = (columns: any, data: any) => { - return data.reduce((csvString: any, rowItem: any) => { - return csvString + columns.map(({ accessor }: any) => escapeCsvCell(accessor(rowItem))).join(';') + '\r\n'; - }, columns.map(({ name }: any) => escapeCsvCell(name)).join(';') + '\r\n'); - }; + const makeCsvData = (columns: any, data: any) => + data.reduce( + (csvString: any, rowItem: any) => + csvString + columns.map(({ accessor }: any) => escapeCsvCell(accessor(rowItem))).join(';') + '\r\n', + columns.map(({ name }: any) => escapeCsvCell(name)).join(';') + '\r\n' + ); const downloadAsCsv = (columns: any, data: any, filename: string) => { const csvData = makeCsvData(columns, data); @@ -565,7 +547,7 @@ const DashboardData: FC = () => { toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } finally { setSensor(undefined); - fetchSensorData(); + void fetchSensorData(); } } }; @@ -643,7 +625,7 @@ const DashboardData: FC = () => { - + @@ -688,7 +670,7 @@ const DashboardData: FC = () => {
- {LL.TYPE()} + {LL.TYPE(0)} {LL.DESCRIPTION()} {LL.ENTITIES()} @@ -940,7 +922,7 @@ const DashboardData: FC = () => { endIcon={getSortIcon(analog_sort.state, 'TYPE')} onClick={() => analog_sort.fns.onToggleSort({ sortKey: 'TYPE' })} > - {LL.TYPE()} + {LL.TYPE(0)} {LL.VALUE(0)} @@ -993,7 +975,7 @@ const DashboardData: FC = () => { toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } finally { setAnalog(undefined); - fetchSensorData(); + void fetchSensorData(); } } }; @@ -1021,7 +1003,7 @@ const DashboardData: FC = () => { toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } finally { setAnalog(undefined); - fetchSensorData(); + void fetchSensorData(); } } }; @@ -1060,7 +1042,7 @@ const DashboardData: FC = () => { { const { LL } = useI18nContext(); @@ -24,7 +21,7 @@ const Settings: FC = () => { - + } /> diff --git a/src/locale_translations.h b/src/locale_translations.h index 00f918cc3..4639bf451 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -49,7 +49,8 @@ MAKE_WORD_TRANSLATION(pump_device, "Pump Module", "Pumpenmodul", "Pump Module", MAKE_WORD_TRANSLATION(heatsource_device, "Heatsource", "Heizquelle", "Heatsource", "Värmekälla", "Źródło ciepła", "Varmekilde", "", "Isı Kaynağı") // TODO translate MAKE_WORD_TRANSLATION(sensors_device, "Sensors", "Sensoren", "Sensoren", "Sensorer", "Czujniki", "Sensorer", "Capteurs", "Sensör Cihazı") MAKE_WORD_TRANSLATION(unknown_device, "Unknown", "Unbekannt", "Onbekend", "Okänt", "Nieznane urządzenie", "Ukjent", "Inconnu", "") // TODO translate -MAKE_WORD_TRANSLATION(custom_device, "User defined entities", "Nutzer deklarierte Entitäten", "", "", "", "", "", "") // TODO translate +MAKE_WORD_TRANSLATION(custom_device, "Custom", "", "", "", "Niestandardowe", "", "", "") // TODO translate +MAKE_WORD_TRANSLATION(custom_device_name, "User defined entities", "Nutzer deklarierte Entitäten", "", "", "Encje zdefiniowane przez użytkownika", "", "", "") // TODO translate // commands // TODO translate @@ -61,11 +62,11 @@ MAKE_WORD_TRANSLATION(setiovalue_cmd, "set io value", "Setze Wertevorgabe", "", MAKE_WORD_TRANSLATION(changeloglevel_cmd, "change log level", "Ändere Sysloglevel", "", "", "zmień poziom log-u", "endre loggnivå", "", "Kayıt seviyesini değiştir") // TODO translate MAKE_WORD_TRANSLATION(fetch_cmd, "refresh all EMS values", "Lese alle EMS-Werte neu", "", "", "odśwież wszystkie wartości EMS", "oppfrisk alle EMS verdier", "", "Bütün EMS değerlerini yenile") // TODO translate MAKE_WORD_TRANSLATION(restart_cmd, "restart EMS-ESP", "Neustart", "", "", "uruchom ponownie EMS-ESP", "restart EMS-ESP", "", "EMS-ESPyi yeniden başlat") // TODO translate -MAKE_WORD_TRANSLATION(watch_cmd, "watch incoming telegrams", "Watch auf eingehende Telegramme", "", "", "obserwuj przyczodzące telegramy", "se innkommende telegrammer", "", "Gelen telegramları ") // TODO translate +MAKE_WORD_TRANSLATION(watch_cmd, "watch incoming telegrams", "Watch auf eingehende Telegramme", "", "", "obserwuj przychodzące telegramy", "se innkommende telegrammer", "", "Gelen telegramları ") // TODO translate MAKE_WORD_TRANSLATION(publish_cmd, "publish all to MQTT", "Publiziere MQTT", "", "", "opublikuj wszystko na MQTT", "Publiser alt til MQTT", "", "Hepsini MQTTye gönder") // TODO translate MAKE_WORD_TRANSLATION(system_info_cmd, "show system status", "Zeige System-Status", "", "", "pokaż status systemu", "vis system status", "", "Sistem Durumunu Göster") // TODO translate MAKE_WORD_TRANSLATION(schedule_cmd, "enable schedule item", "Aktiviere Zeitplan", "", "", "aktywuj wybrany harmonogram", "", "", "") // TODO translate -MAKE_WORD_TRANSLATION(entity_cmd, "set custom value on ems", "Sende eigene Entitäten zu EMS", "", "", "", "", "", "") // TODO translate +MAKE_WORD_TRANSLATION(entity_cmd, "set custom value on ems", "Sende eigene Entitäten zu EMS", "", "", "wyślij własną wartość na EMS", "", "", "") // TODO translate // tags MAKE_WORD_TRANSLATION(tag_boiler_data_ww, "dhw", "WW", "dhw", "VV", "CWU", "dhw", "ecs", "SKS") diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index 05ecdd447..6364a794f 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -1,7 +1,7 @@ /* * EMS-ESP - https://github.com/emsesp/EMS-ESP * 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 * the Free Software Foundation, either version 3 of the License, or @@ -75,33 +75,32 @@ void WebDataService::core_data(AsyncWebServerRequest * request) { // list is already sorted by device type JsonArray devices = root.createNestedArray("devices"); - char buffer[3]; for (const auto & emsdevice : EMSESP::emsdevices) { // ignore controller if (emsdevice && (emsdevice->device_type() != EMSdevice::DeviceType::CONTROLLER || emsdevice->count_entities() > 0)) { JsonObject obj = devices.createNestedObject(); - obj["id"] = Helpers::smallitoa(buffer, emsdevice->unique_id()); // a unique id as a string - obj["tn"] = emsdevice->device_type_2_device_name_translated(); // translated device type name - obj["t"] = emsdevice->device_type(); // device type number - obj["b"] = emsdevice->brand_to_char(); // brand - obj["n"] = emsdevice->name(); // name - 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["id"] = emsdevice->unique_id(); // a unique id + obj["tn"] = emsdevice->device_type_2_device_name_translated(); // translated device type name + obj["t"] = emsdevice->device_type(); // device type number + obj["b"] = emsdevice->brand_to_char(); // brand + obj["n"] = emsdevice->name(); // name + 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) } } if (EMSESP::webEntityService.count_entities()) { JsonObject obj = devices.createNestedObject(); - obj["id"] = "99"; // the last unique id as a string - obj["tn"] = "Custom"; // translated device type name - obj["t"] = EMSdevice::DeviceType::CUSTOM; // device type number - obj["b"] = 0; // brand - obj["n"] = Helpers::translated_word(FL_(custom_device)); // name - obj["d"] = 0; // deviceid - obj["p"] = 0; // productid - obj["v"] = 0; // version - obj["e"] = EMSESP::webEntityService.count_entities(); // number of entities (device values) + obj["id"] = 99; // the last unique id + obj["tn"] = Helpers::translated_word(FL_(custom_device)); // translated device type name + obj["t"] = EMSdevice::DeviceType::CUSTOM; // device type number + obj["b"] = Helpers::translated_word(FL_(na)); // brand + obj["n"] = Helpers::translated_word(FL_(custom_device_name)); // name + obj["d"] = 0; // deviceid + obj["p"] = 0; // productid + obj["v"] = 0; // version + obj["e"] = EMSESP::webEntityService.count_entities(); // number of entities (device values) } // sensors stuff