This commit is contained in:
MichaelDvP
2024-10-22 18:36:13 +02:00
53 changed files with 1091 additions and 841 deletions

View File

@@ -48,6 +48,7 @@ For more details go to [www.emsesp.org](https://www.emsesp.org/).
- internal ESP32 temperature sensor on the S3 [#2077](https://github.com/emsesp/EMS-ESP32/issues/2077) - internal ESP32 temperature sensor on the S3 [#2077](https://github.com/emsesp/EMS-ESP32/issues/2077)
- MQTT status topic (used in connect and last will) set to Retain [#2086](https://github.com/emsesp/EMS-ESP32/discussions/2086) - MQTT status topic (used in connect and last will) set to Retain [#2086](https://github.com/emsesp/EMS-ESP32/discussions/2086)
- Czech language [2096](https://github.com/emsesp/EMS-ESP32/issues/2096) - Czech language [2096](https://github.com/emsesp/EMS-ESP32/issues/2096)
- Developer Mode and send EMS Read Commands from WebUI [#2116](https://github.com/emsesp/EMS-ESP32/issues/2116)
## Fixed ## Fixed

View File

@@ -31,6 +31,8 @@ export default tseslint.config(
'@typescript-eslint/no-unsafe-enum-comparison': 'off', '@typescript-eslint/no-unsafe-enum-comparison': 'off',
'@typescript-eslint/no-unused-expressions': 'off', '@typescript-eslint/no-unused-expressions': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off', '@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-misused-promises': [ '@typescript-eslint/no-misused-promises': [
'error', 'error',
{ {

View File

@@ -24,8 +24,8 @@
"@alova/adapter-xhr": "2.0.8", "@alova/adapter-xhr": "2.0.8",
"@emotion/react": "^11.13.3", "@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0", "@emotion/styled": "^11.13.0",
"@mui/icons-material": "^6.1.4", "@mui/icons-material": "^6.1.5",
"@mui/material": "^6.1.4", "@mui/material": "^6.1.5",
"@table-library/react-table-library": "4.1.7", "@table-library/react-table-library": "4.1.7",
"alova": "3.1.0", "alova": "3.1.0",
"async-validator": "^4.2.5", "async-validator": "^4.2.5",
@@ -41,13 +41,13 @@
"typescript": "^5.6.3" "typescript": "^5.6.3"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.25.8", "@babel/core": "^7.25.9",
"@eslint/js": "^9.13.0", "@eslint/js": "^9.13.0",
"@preact/compat": "^18.3.1", "@preact/compat": "^18.3.1",
"@preact/preset-vite": "^2.9.1", "@preact/preset-vite": "^2.9.1",
"@trivago/prettier-plugin-sort-imports": "^4.3.0", "@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/formidable": "^3", "@types/formidable": "^3",
"@types/node": "^22.7.7", "@types/node": "^22.7.8",
"@types/react": "^18.3.11", "@types/react": "^18.3.11",
"@types/react-dom": "^18.3.1", "@types/react-dom": "^18.3.1",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
@@ -58,7 +58,7 @@
"prettier": "^3.3.3", "prettier": "^3.3.3",
"rollup-plugin-visualizer": "^5.12.0", "rollup-plugin-visualizer": "^5.12.0",
"terser": "^5.36.0", "terser": "^5.36.0",
"typescript-eslint": "8.10.0", "typescript-eslint": "8.11.0",
"vite": "^5.4.9", "vite": "^5.4.9",
"vite-plugin-imagemin": "^0.6.1", "vite-plugin-imagemin": "^0.6.1",
"vite-tsconfig-paths": "^5.0.1" "vite-tsconfig-paths": "^5.0.1"

View File

@@ -15,6 +15,7 @@ import DownloadUpload from 'app/settings/DownloadUpload';
import MqttSettings from 'app/settings/MqttSettings'; import MqttSettings from 'app/settings/MqttSettings';
import NTPSettings from 'app/settings/NTPSettings'; import NTPSettings from 'app/settings/NTPSettings';
import Settings from 'app/settings/Settings'; import Settings from 'app/settings/Settings';
import Version from 'app/settings/Version';
import Network from 'app/settings/network/Network'; import Network from 'app/settings/network/Network';
import Security from 'app/settings/security/Security'; import Security from 'app/settings/security/Security';
import APStatus from 'app/status/APStatus'; import APStatus from 'app/status/APStatus';
@@ -51,6 +52,7 @@ const AuthenticatedRouting = () => {
{me.admin && ( {me.admin && (
<> <>
<Route path="/settings" element={<Settings />} /> <Route path="/settings" element={<Settings />} />
<Route path="/settings/version" element={<Version />} />
<Route path="/settings/application" element={<ApplicationSettings />} /> <Route path="/settings/application" element={<ApplicationSettings />} />
<Route path="/settings/mqtt" element={<MqttSettings />} /> <Route path="/settings/mqtt" element={<MqttSettings />} />
<Route path="/settings/ntp" element={<NTPSettings />} /> <Route path="/settings/ntp" element={<NTPSettings />} />

View File

@@ -102,6 +102,9 @@ const Dashboard = () => {
Row: ` Row: `
cursor: pointer; cursor: pointer;
background-color: #1e1e1e; background-color: #1e1e1e;
&:nth-of-type(odd) .td {
background-color: #303030;
},
&:hover .td { &:hover .td {
background-color: #177ac9; background-color: #177ac9;
} }
@@ -234,7 +237,7 @@ const Dashboard = () => {
<Grid container spacing={0} justifyContent="flex-start"> <Grid container spacing={0} justifyContent="flex-start">
<Grid size={11}> <Grid size={11}>
<Typography mb={2} variant="body1" color="warning"> <Typography mb={2} variant="body1" color="warning">
{LL.DASHBOARD_1()} {LL.DASHBOARD_1()}.
</Typography> </Typography>
</Grid> </Grid>
@@ -274,7 +277,7 @@ const Dashboard = () => {
}} }}
> >
{!loading && data.length === 0 ? ( {!loading && data.length === 0 ? (
<Typography variant="subtitle2" color="warning"> <Typography variant="subtitle2" color="secondary">
{LL.NO_DATA()} {LL.NO_DATA()}
</Typography> </Typography>
) : ( ) : (

View File

@@ -166,11 +166,6 @@ const Devices = () => {
Table: ` Table: `
--data-table-library_grid-template-columns: repeat(1, minmax(0, 1fr)) 130px; --data-table-library_grid-template-columns: repeat(1, minmax(0, 1fr)) 130px;
`, `,
BaseRow: `
// .td {
// height: 42px;
// }
`,
HeaderRow: ` HeaderRow: `
.th { .th {
padding: 8px; padding: 8px;
@@ -268,7 +263,7 @@ const Devices = () => {
), ),
VALUE: (array) => VALUE: (array) =>
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access // eslint-disable-next-line @typescript-eslint/no-unsafe-return
array.sort((a, b) => a.v.toString().localeCompare(b.v.toString())) array.sort((a, b) => a.v.toString().localeCompare(b.v.toString()))
} }
} }
@@ -362,7 +357,9 @@ const Devices = () => {
}, },
{ {
accessor: (dv: DeviceValue) => accessor: (dv: DeviceValue) =>
DeviceValueUOM_s[dv.u].replace(/[^a-zA-Z0-9]/g, ''), dv.u !== undefined && DeviceValueUOM_s[dv.u]
? DeviceValueUOM_s[dv.u].replace(/[^a-zA-Z0-9]/g, '')
: '',
name: 'UoM' name: 'UoM'
}, },
{ {

View File

@@ -51,19 +51,19 @@ const Help = () => {
} }
}); });
const { send: sendExportAllValues } = useRequest( // const { send: sendExportAllValues } = useRequest(
() => callAction({ action: 'export', param: 'allvalues' }), // () => callAction({ action: 'export', param: 'allvalues' }),
{ // {
immediate: false // immediate: false
} // }
) // )
.onSuccess((event) => { // .onSuccess((event) => {
saveFile(event.data, 'allvalues', '.txt'); // saveFile(event.data, 'allvalues', '.txt');
toast.info(LL.DOWNLOAD_SUCCESSFUL()); // toast.info(LL.DOWNLOAD_SUCCESSFUL());
}) // })
.onError((error) => { // .onError((error) => {
toast.error(error.message); // toast.error(error.message);
}); // });
const { send: sendAPI } = useRequest((data: APIcall) => API(data), { const { send: sendAPI } = useRequest((data: APIcall) => API(data), {
immediate: false immediate: false
@@ -103,7 +103,7 @@ const Help = () => {
sx={{ sx={{
maxHeight: { xs: 100, md: 250 } maxHeight: { xs: 100, md: 250 }
}} }}
onError={(e) => setNotFound(true)} onError={() => setNotFound(true)}
src={ src={
notFound notFound
? '' ? ''
@@ -162,11 +162,11 @@ const Help = () => {
color="primary" color="primary"
onClick={() => sendAPI({ device: 'system', cmd: 'info', id: 0 })} onClick={() => sendAPI({ device: 'system', cmd: 'info', id: 0 })}
> >
{LL.DOWNLOAD(1)}&nbsp;{LL.SUPPORT_INFORMATION(0)} {LL.SUPPORT_INFORMATION(0)}
</Button> </Button>
</Box> </Box>
<Button {/* <Button
sx={{ ml: 2 }} sx={{ ml: 2 }}
startIcon={<DownloadIcon />} startIcon={<DownloadIcon />}
variant="outlined" variant="outlined"
@@ -174,7 +174,7 @@ const Help = () => {
onClick={() => sendExportAllValues()} onClick={() => sendExportAllValues()}
> >
{LL.DOWNLOAD(1)}&nbsp;{LL.ALLVALUES()} {LL.DOWNLOAD(1)}&nbsp;{LL.ALLVALUES()}
</Button> </Button> */}
<Divider sx={{ mt: 4 }} /> <Divider sx={{ mt: 4 }} />

View File

@@ -313,7 +313,7 @@ const Scheduler = () => {
<SectionContent> <SectionContent>
{blocker ? <BlockNavigation blocker={blocker} /> : null} {blocker ? <BlockNavigation blocker={blocker} /> : null}
<Box mb={2} color="warning.main"> <Box mb={2} color="warning.main">
<Typography variant="body1">{LL.SCHEDULER_HELP_1()}</Typography> <Typography variant="body1">{LL.SCHEDULER_HELP_1()}.</Typography>
</Box> </Box>
{renderSchedule()} {renderSchedule()}

View File

@@ -219,7 +219,7 @@ const Sensors = () => {
sortToggleType: SortToggleType.AlternateWithReset, sortToggleType: SortToggleType.AlternateWithReset,
sortFns: { sortFns: {
GPIO: (array) => array.sort((a, b) => a.g - b.g), GPIO: (array) => array.sort((a, b) => a.g - b.g),
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access // eslint-disable-next-line @typescript-eslint/no-unsafe-return
NAME: (array) => array.sort((a, b) => a.n.localeCompare(b.n)), NAME: (array) => array.sort((a, b) => a.n.localeCompare(b.n)),
TYPE: (array) => array.sort((a, b) => a.t - b.t), TYPE: (array) => array.sort((a, b) => a.t - b.t),
VALUE: (array) => array.sort((a, b) => a.v - b.v) VALUE: (array) => array.sort((a, b) => a.v - b.v)
@@ -238,7 +238,7 @@ const Sensors = () => {
}, },
sortToggleType: SortToggleType.AlternateWithReset, sortToggleType: SortToggleType.AlternateWithReset,
sortFns: { sortFns: {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access // eslint-disable-next-line @typescript-eslint/no-unsafe-return
NAME: (array) => array.sort((a, b) => a.n.localeCompare(b.n)), NAME: (array) => array.sort((a, b) => a.n.localeCompare(b.n)),
VALUE: (array) => array.sort((a, b) => a.t - b.t) VALUE: (array) => array.sort((a, b) => a.t - b.t)
} }

View File

@@ -42,6 +42,7 @@ export interface Settings {
modbus_port: number; modbus_port: number;
modbus_max_clients: number; modbus_max_clients: number;
modbus_timeout: number; modbus_timeout: number;
developer_mode: boolean;
} }
export enum busConnectionStatus { export enum busConnectionStatus {
@@ -273,6 +274,7 @@ export interface APIcall {
device: string; device: string;
cmd: string; cmd: string;
id: number; id: number;
data?: string; // optional
} }
export interface Action { export interface Action {

View File

@@ -686,6 +686,16 @@ const ApplicationSettings = () => {
<Typography sx={{ pb: 1, pt: 2 }} variant="h6" color="primary"> <Typography sx={{ pb: 1, pt: 2 }} variant="h6" color="primary">
{LL.SPECIAL_FUNCTIONS()} {LL.SPECIAL_FUNCTIONS()}
</Typography> </Typography>
<BlockFormControlLabel
control={
<Checkbox
checked={data.developer_mode}
onChange={updateFormValue}
name="developer_mode"
/>
}
label={LL.DEVELOPER_MODE()}
/>
<BlockFormControlLabel <BlockFormControlLabel
control={ control={
<Checkbox <Checkbox
@@ -696,7 +706,6 @@ const ApplicationSettings = () => {
} }
label={LL.HEATINGOFF()} label={LL.HEATINGOFF()}
/> />
<BlockFormControlLabel <BlockFormControlLabel
control={ control={
<Checkbox <Checkbox

View File

@@ -1,27 +1,13 @@
import { useState } from 'react'; import { useState } from 'react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import CancelIcon from '@mui/icons-material/Cancel';
import DownloadIcon from '@mui/icons-material/GetApp'; import DownloadIcon from '@mui/icons-material/GetApp';
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; import { Box, Button, Typography } from '@mui/material';
import WarningIcon from '@mui/icons-material/Warning';
import {
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Link,
Typography
} from '@mui/material';
import Grid from '@mui/material/Grid2'; import Grid from '@mui/material/Grid2';
import * as SystemApi from 'api/system'; import * as SystemApi from 'api/system';
import { API, callAction } from 'api/app'; import { API, callAction } from 'api/app';
import { getDevVersion, getStableVersion } from 'api/system';
import { dialogStyle } from 'CustomTheme';
import { useRequest } from 'alova/client'; import { useRequest } from 'alova/client';
import type { APIcall } from 'app/main/types'; import type { APIcall } from 'app/main/types';
import RestartMonitor from 'app/status/RestartMonitor'; import RestartMonitor from 'app/status/RestartMonitor';
@@ -38,18 +24,6 @@ const DownloadUpload = () => {
const { LL } = useI18nContext(); const { LL } = useI18nContext();
const [restarting, setRestarting] = useState<boolean>(false); const [restarting, setRestarting] = useState<boolean>(false);
const [openDialog, setOpenDialog] = useState<boolean>(false);
const [useDev, setUseDev] = useState<boolean>(false);
const [upgradeAvailable, setUpgradeAvailable] = useState<boolean>(false);
const { send: sendCheckUpgrade } = useRequest(
(version: string) => callAction({ action: 'checkUpgrade', param: version }),
{
immediate: false
}
).onSuccess((event) => {
setUpgradeAvailable((event.data as { upgradeable: boolean }).upgradeable);
});
const { send: sendExportData } = useRequest( const { send: sendExportData } = useRequest(
(type: string) => callAction({ action: 'export', param: type }), (type: string) => callAction({ action: 'export', param: type }),
@@ -71,13 +45,6 @@ const DownloadUpload = () => {
const { data, send: loadData, error } = useRequest(SystemApi.readSystemStatus); const { data, send: loadData, error } = useRequest(SystemApi.readSystemStatus);
const { send: sendUploadURL } = useRequest(
(url: string) => callAction({ action: 'uploadURL', param: url }),
{
immediate: false
}
);
const doRestart = async () => { const doRestart = async () => {
setRestarting(true); setRestarting(true);
await sendAPI({ device: 'system', cmd: 'restart', id: 0 }).catch( await sendAPI({ device: 'system', cmd: 'restart', id: 0 }).catch(
@@ -87,134 +54,13 @@ const DownloadUpload = () => {
); );
}; };
// called immediately to get the latest version, on page load
const { data: latestVersion } = useRequest(getStableVersion, {
// uncomment next 2 lines for testing, uses https://github.com/emsesp/EMS-ESP32/releases/download/v3.6.5/EMS-ESP-3_6_5-ESP32-16MB+.bin
// immediate: false,
// initialData: '3.6.5'
});
// called immediately to get the latest version, on page load, then check for upgrade
const { data: latestDevVersion } = useRequest(getDevVersion, {
// uncomment next 2 lines for testing, uses https://github.com/emsesp/EMS-ESP32/releases/download/latest/EMS-ESP-3_7_0-dev_31-ESP32-16MB+.bin
// immediate: false,
// initialData: '3.7.0-dev.32'
}).onSuccess((event) => {
void sendCheckUpgrade(event.data);
});
const STABLE_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/';
const STABLE_RELNOTES_URL =
'https://github.com/emsesp/EMS-ESP32/blob/main/CHANGELOG.md';
const DEV_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/latest/';
const DEV_RELNOTES_URL =
'https://github.com/emsesp/EMS-ESP32/blob/dev/CHANGELOG_LATEST.md';
const getBinURL = (useDevVersion: boolean) => {
if (!latestVersion || !latestDevVersion) {
return '';
}
const filename =
'EMS-ESP-' +
(useDevVersion ? latestDevVersion : latestVersion).replaceAll('.', '_') +
'-' +
getPlatform() +
'.bin';
return useDevVersion
? DEV_URL + filename
: STABLE_URL + 'v' + latestVersion + '/' + filename;
};
const getPlatform = () => {
return (
[data.esp_platform, data.flash_chip_size >= 16384 ? '16MB' : '4MB'].join('-') +
(data.psram ? '+' : '')
);
};
const installFirmwareURL = async (url: string) => {
await sendUploadURL(url).catch((error: Error) => {
toast.error(error.message);
});
setRestarting(true);
};
useLayoutTitle(LL.DOWNLOAD_UPLOAD()); useLayoutTitle(LL.DOWNLOAD_UPLOAD());
const internet_live =
latestDevVersion !== undefined && latestVersion !== undefined;
const renderUploadDialog = () => {
if (!internet_live) {
return null;
}
return (
<Dialog
sx={dialogStyle}
open={openDialog}
onClose={() => setOpenDialog(false)}
>
<DialogTitle>
{LL.INSTALL('') +
' ' +
(useDev ? LL.DEVELOPMENT() : LL.STABLE()) +
' Firmware'}
</DialogTitle>
<DialogContent dividers>
<Typography mb={2}>
{LL.INSTALL_VERSION(useDev ? latestDevVersion : latestVersion)}
</Typography>
<Link
target="_blank"
href={useDev ? DEV_RELNOTES_URL : STABLE_RELNOTES_URL}
color="primary"
>
{LL.RELEASE_NOTES()}
</Link>
&nbsp;|&nbsp;
<Link target="_blank" href={getBinURL(useDev)} color="primary">
{LL.DOWNLOAD(1)}
</Link>
</DialogContent>
<DialogActions>
<Button
startIcon={<CancelIcon />}
variant="outlined"
onClick={() => setOpenDialog(false)}
color="secondary"
>
{LL.CANCEL()}
</Button>
<Button
startIcon={<WarningIcon color="warning" />}
variant="outlined"
onClick={() => installFirmwareURL(getBinURL(useDev))}
color="primary"
>
{LL.INSTALL('')}
</Button>
</DialogActions>
</Dialog>
);
};
// useDevVersion = true to force using the dev version
const showFirmwareDialog = (useDevVersion: boolean) => {
if (useDevVersion || data.emsesp_version.includes('dev')) {
setUseDev(true);
}
setOpenDialog(true);
};
const content = () => { const content = () => {
if (!data) { if (!data) {
return <FormLoader onRetry={loadData} errorMessage={error?.message} />; return <FormLoader onRetry={loadData} errorMessage={error?.message} />;
} }
const isDev = data.emsesp_version.includes('dev');
return ( return (
<> <>
<Typography sx={{ pb: 2 }} variant="h6" color="primary"> <Typography sx={{ pb: 2 }} variant="h6" color="primary">
@@ -232,7 +78,7 @@ const DownloadUpload = () => {
color="primary" color="primary"
onClick={() => sendExportData('settings')} onClick={() => sendExportData('settings')}
> >
{LL.DOWNLOAD(1)}&nbsp;{LL.SETTINGS_OF(LL.APPLICATION())} {LL.SETTINGS_OF(LL.APPLICATION())}
</Button> </Button>
<Button <Button
@@ -242,7 +88,7 @@ const DownloadUpload = () => {
color="primary" color="primary"
onClick={() => sendExportData('customizations')} onClick={() => sendExportData('customizations')}
> >
{LL.DOWNLOAD(1)}&nbsp;{LL.CUSTOMIZATIONS()} {LL.CUSTOMIZATIONS()}
</Button> </Button>
<Button <Button
sx={{ ml: 2 }} sx={{ ml: 2 }}
@@ -251,7 +97,7 @@ const DownloadUpload = () => {
color="primary" color="primary"
onClick={() => sendExportData('entities')} onClick={() => sendExportData('entities')}
> >
{LL.DOWNLOAD(1)}&nbsp;{LL.CUSTOM_ENTITIES(0)} {LL.CUSTOM_ENTITIES(0)}
</Button> </Button>
<Button <Button
sx={{ ml: 2 }} sx={{ ml: 2 }}
@@ -260,7 +106,7 @@ const DownloadUpload = () => {
color="primary" color="primary"
onClick={() => sendExportData('schedule')} onClick={() => sendExportData('schedule')}
> >
{LL.DOWNLOAD(1)}&nbsp;{LL.SCHEDULE(0)} {LL.SCHEDULE(0)}
</Button> </Button>
</Grid> </Grid>
@@ -273,68 +119,6 @@ const DownloadUpload = () => {
</Box> </Box>
<SingleUpload doRestart={doRestart} /> <SingleUpload doRestart={doRestart} />
<Typography sx={{ pt: 2 }} variant="h6" color="primary">
{LL.EMS_ESP_VER()}
</Typography>
<Box p={2} mt={2} border="1px solid grey" borderRadius={2}>
<Typography>
<b>{LL.VERSION() + ':'}</b>&nbsp;{data.emsesp_version}
{data.build_flags && (
<Typography variant="caption">
&nbsp; &#40;{data.build_flags}&#41;
</Typography>
)}
</Typography>
<Typography>
<b>Platform:</b>&nbsp;{getPlatform()}
</Typography>
<Typography>
<b>Release:</b>&nbsp;{isDev ? LL.DEVELOPMENT() : LL.STABLE()}
{!isDev && (
<Button
sx={{ ml: 2 }}
size="small"
variant="outlined"
color="primary"
onClick={() => showFirmwareDialog(true)}
>
{LL.SWITCH_DEV()}
</Button>
)}
</Typography>
<Typography mt={2} color="secondary">
<InfoOutlinedIcon color="secondary" sx={{ verticalAlign: 'middle' }} />
&nbsp;&nbsp;
{upgradeAvailable ? LL.UPGRADE_AVAILABLE() : LL.LATEST_VERSION()}
{upgradeAvailable &&
internet_live &&
(data.psram ? (
<Button
sx={{ ml: 2, textTransform: 'none' }}
size="small"
variant="outlined"
color="primary"
onClick={() => showFirmwareDialog(false)}
>
{isDev
? LL.INSTALL('v' + latestDevVersion)
: LL.INSTALL('v' + latestVersion)}
</Button>
) : (
<>
&nbsp;&nbsp;
<Link target="_blank" href={getBinURL(isDev)} color="primary">
{LL.DOWNLOAD(1)}&nbsp;v
{isDev ? latestDevVersion : latestVersion}
</Link>
</>
))}
</Typography>
{renderUploadDialog()}
</Box>
</> </>
); );
}; };

View File

@@ -1,6 +1,7 @@
import { useState } from 'react'; import { useState } from 'react';
import AccessTimeIcon from '@mui/icons-material/AccessTime'; import AccessTimeIcon from '@mui/icons-material/AccessTime';
import BuildIcon from '@mui/icons-material/Build';
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
import DeviceHubIcon from '@mui/icons-material/DeviceHub'; import DeviceHubIcon from '@mui/icons-material/DeviceHub';
import ImportExportIcon from '@mui/icons-material/ImportExport'; import ImportExportIcon from '@mui/icons-material/ImportExport';
@@ -20,7 +21,7 @@ import {
List List
} from '@mui/material'; } from '@mui/material';
import { API } from 'api/app'; import { API, callAction } from 'api/app';
import { dialogStyle } from 'CustomTheme'; import { dialogStyle } from 'CustomTheme';
import { useRequest } from 'alova/client'; import { useRequest } from 'alova/client';
@@ -39,6 +40,11 @@ const Settings = () => {
immediate: false immediate: false
}); });
// call checkUpgrade with no param to fetch EMS-ESP version
const { data } = useRequest(() => callAction({ action: 'checkUpgrade' }), {
initialData: { emsesp_version: '...' }
});
const doFormat = async () => { const doFormat = async () => {
await sendAPI({ device: 'system', cmd: 'format', id: 0 }).then(() => { await sendAPI({ device: 'system', cmd: 'format', id: 0 }).then(() => {
setConfirmFactoryReset(false); setConfirmFactoryReset(false);
@@ -77,10 +83,18 @@ const Settings = () => {
const content = () => ( const content = () => (
<> <>
<List sx={{ borderRadius: 3, border: '2px solid grey' }}> <List sx={{ borderRadius: 3, border: '2px solid grey' }}>
<ListMenuItem
icon={BuildIcon}
bgcolor="#72caf9"
label={LL.EMS_ESP_VER()}
text={data.emsesp_version}
to="version"
/>
<ListMenuItem <ListMenuItem
icon={TuneIcon} icon={TuneIcon}
bgcolor="#134ba2" bgcolor="#134ba2"
label={LL.SETTINGS_OF(LL.APPLICATION())} label={LL.APPLICATION()}
text={LL.APPLICATION_SETTINGS_1()} text={LL.APPLICATION_SETTINGS_1()}
to="application" to="application"
/> />
@@ -88,7 +102,7 @@ const Settings = () => {
<ListMenuItem <ListMenuItem
icon={SettingsEthernetIcon} icon={SettingsEthernetIcon}
bgcolor="#40828f" bgcolor="#40828f"
label={LL.SETTINGS_OF(LL.NETWORK(0))} label={LL.NETWORK(0)}
text={LL.CONFIGURE(LL.SETTINGS_OF(LL.NETWORK(1)))} text={LL.CONFIGURE(LL.SETTINGS_OF(LL.NETWORK(1)))}
to="network" to="network"
/> />
@@ -96,7 +110,7 @@ const Settings = () => {
<ListMenuItem <ListMenuItem
icon={SettingsInputAntennaIcon} icon={SettingsInputAntennaIcon}
bgcolor="#5f9a5f" bgcolor="#5f9a5f"
label={LL.SETTINGS_OF(LL.ACCESS_POINT(0))} label={LL.ACCESS_POINT(0)}
text={LL.CONFIGURE(LL.ACCESS_POINT(1))} text={LL.CONFIGURE(LL.ACCESS_POINT(1))}
to="ap" to="ap"
/> />
@@ -104,7 +118,7 @@ const Settings = () => {
<ListMenuItem <ListMenuItem
icon={AccessTimeIcon} icon={AccessTimeIcon}
bgcolor="#c5572c" bgcolor="#c5572c"
label={LL.SETTINGS_OF('NTP')} label="NTP"
text={LL.CONFIGURE(LL.LOCAL_TIME(1))} text={LL.CONFIGURE(LL.LOCAL_TIME(1))}
to="ntp" to="ntp"
/> />
@@ -112,14 +126,14 @@ const Settings = () => {
<ListMenuItem <ListMenuItem
icon={DeviceHubIcon} icon={DeviceHubIcon}
bgcolor="#68374d" bgcolor="#68374d"
label={LL.SETTINGS_OF('MQTT')} label="MQTT"
text={LL.CONFIGURE('MQTT')} text={LL.CONFIGURE('MQTT')}
to="mqtt" to="mqtt"
/> />
<ListMenuItem <ListMenuItem
icon={LockIcon} icon={LockIcon}
label={LL.SETTINGS_OF(LL.SECURITY(0))} label={LL.SECURITY(0)}
text={LL.SECURITY_1()} text={LL.SECURITY_1()}
to="security" to="security"
/> />

View File

@@ -0,0 +1,262 @@
import { useState } from 'react';
import { toast } from 'react-toastify';
import CancelIcon from '@mui/icons-material/Cancel';
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
import WarningIcon from '@mui/icons-material/Warning';
import {
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Link,
Typography
} from '@mui/material';
import * as SystemApi from 'api/system';
import { callAction } from 'api/app';
import { getDevVersion, getStableVersion } from 'api/system';
import { dialogStyle } from 'CustomTheme';
import { useRequest } from 'alova/client';
import RestartMonitor from 'app/status/RestartMonitor';
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
import { useI18nContext } from 'i18n/i18n-react';
const Version = () => {
const { LL } = useI18nContext();
const [restarting, setRestarting] = useState<boolean>(false);
const [openDialog, setOpenDialog] = useState<boolean>(false);
const [useDev, setUseDev] = useState<boolean>(false);
const [upgradeAvailable, setUpgradeAvailable] = useState<boolean>(false);
const { send: sendCheckUpgrade } = useRequest(
(version: string) => callAction({ action: 'checkUpgrade', param: version }),
{
immediate: false
}
).onSuccess((event) => {
const data = event.data as { emsesp_version: string; upgradeable: boolean };
setUpgradeAvailable(data.upgradeable);
});
const { data, send: loadData, error } = useRequest(SystemApi.readSystemStatus);
const { send: sendUploadURL } = useRequest(
(url: string) => callAction({ action: 'uploadURL', param: url }),
{
immediate: false
}
);
// called immediately to get the latest version, on page load
const { data: latestVersion } = useRequest(getStableVersion, {
// uncomment next 2 lines for testing, uses https://github.com/emsesp/EMS-ESP32/releases/download/v3.6.5/EMS-ESP-3_6_5-ESP32-16MB+.bin
// immediate: false,
// initialData: '3.6.5'
});
// called immediately to get the latest version, on page load, then check for upgrade (works for both dev and stable)
const { data: latestDevVersion } = useRequest(getDevVersion, {
// uncomment next 2 lines for testing, uses https://github.com/emsesp/EMS-ESP32/releases/download/latest/EMS-ESP-3_7_0-dev_31-ESP32-16MB+.bin
// immediate: false,
// initialData: '3.7.0-dev.32'
}).onSuccess((event) => {
void sendCheckUpgrade(event.data);
});
const STABLE_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/';
const STABLE_RELNOTES_URL =
'https://github.com/emsesp/EMS-ESP32/blob/main/CHANGELOG.md';
const DEV_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/latest/';
const DEV_RELNOTES_URL =
'https://github.com/emsesp/EMS-ESP32/blob/dev/CHANGELOG_LATEST.md';
const getBinURL = (useDevVersion: boolean) => {
if (!latestVersion || !latestDevVersion) {
return '';
}
const filename =
'EMS-ESP-' +
(useDevVersion ? latestDevVersion : latestVersion).replaceAll('.', '_') +
'-' +
getPlatform() +
'.bin';
return useDevVersion
? DEV_URL + filename
: STABLE_URL + 'v' + latestVersion + '/' + filename;
};
const getPlatform = () => {
return (
[data.esp_platform, data.flash_chip_size >= 16384 ? '16MB' : '4MB'].join('-') +
(data.psram ? '+' : '')
);
};
const installFirmwareURL = async (url: string) => {
await sendUploadURL(url).catch((error: Error) => {
toast.error(error.message);
});
setRestarting(true);
};
useLayoutTitle(LL.EMS_ESP_VER());
const internet_live =
latestDevVersion !== undefined && latestVersion !== undefined;
const renderUploadDialog = () => {
if (!internet_live) {
return null;
}
return (
<Dialog
sx={dialogStyle}
open={openDialog}
onClose={() => setOpenDialog(false)}
>
<DialogTitle>
{LL.INSTALL('') +
' ' +
(useDev ? LL.DEVELOPMENT() : LL.STABLE()) +
' Firmware'}
</DialogTitle>
<DialogContent dividers>
<Typography mb={2}>
{LL.INSTALL_VERSION(useDev ? latestDevVersion : latestVersion)}
</Typography>
<Link
target="_blank"
href={useDev ? DEV_RELNOTES_URL : STABLE_RELNOTES_URL}
color="primary"
>
changelog
</Link>
&nbsp;|&nbsp;
<Link target="_blank" href={getBinURL(useDev)} color="primary">
{LL.DOWNLOAD(1)}
</Link>
</DialogContent>
<DialogActions>
<Button
startIcon={<CancelIcon />}
variant="outlined"
onClick={() => setOpenDialog(false)}
color="secondary"
>
{LL.CANCEL()}
</Button>
<Button
startIcon={<WarningIcon color="warning" />}
variant="outlined"
onClick={() => installFirmwareURL(getBinURL(useDev))}
color="primary"
>
{LL.INSTALL('')}
</Button>
</DialogActions>
</Dialog>
);
};
// useDevVersion = true to force using the dev version
const showFirmwareDialog = (useDevVersion: boolean) => {
if (useDevVersion || data.emsesp_version.includes('dev')) {
setUseDev(true);
}
setOpenDialog(true);
};
const content = () => {
if (!data) {
return <FormLoader onRetry={loadData} errorMessage={error?.message} />;
}
const isDev = data.emsesp_version.includes('dev');
return (
<>
<Typography variant="h6" color="primary">
Firmware Version Check
</Typography>
<Box p={2} mt={2} border="1px solid grey" borderRadius={2}>
<Typography>
<b>{LL.VERSION() + ':'}</b>&nbsp;{data.emsesp_version}
{data.build_flags && (
<Typography variant="caption">
&nbsp; &#40;{data.build_flags}&#41;
</Typography>
)}
</Typography>
<Typography>
<b>Platform:</b>&nbsp;{getPlatform()}
</Typography>
<Typography>
<b>Release:</b>&nbsp;
<Link
target="_blank"
href={useDev ? DEV_RELNOTES_URL : STABLE_RELNOTES_URL}
color="primary"
>
{isDev ? LL.DEVELOPMENT() : LL.STABLE()}
</Link>
{!isDev && (
<Button
sx={{ ml: 2 }}
variant="outlined"
color="primary"
onClick={() => showFirmwareDialog(true)}
>
{LL.SWITCH_DEV()}
</Button>
)}
</Typography>
<Typography mt={2} color="warning">
<InfoOutlinedIcon color="warning" sx={{ verticalAlign: 'middle' }} />
&nbsp;&nbsp;
{upgradeAvailable ? LL.UPGRADE_AVAILABLE() : LL.LATEST_VERSION()}
{upgradeAvailable &&
internet_live &&
(data.psram ? (
<Button
sx={{ ml: 2, textTransform: 'none' }}
variant="outlined"
color="primary"
onClick={() => showFirmwareDialog(false)}
>
{isDev
? LL.INSTALL('v' + latestDevVersion)
: LL.INSTALL('v' + latestVersion)}
</Button>
) : (
<>
&nbsp;&nbsp;
<Link target="_blank" href={getBinURL(isDev)} color="primary">
{LL.DOWNLOAD(1)}&nbsp;v
{isDev ? latestDevVersion : latestVersion}
</Link>
</>
))}
</Typography>
{renderUploadDialog()}
</Box>
</>
);
};
return (
<SectionContent>{restarting ? <RestartMonitor /> : content()}</SectionContent>
);
};
export default Version;

View File

@@ -1,9 +1,7 @@
import { useContext, useState } from 'react'; import { useContext, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import AccessTimeIcon from '@mui/icons-material/AccessTime'; import AccessTimeIcon from '@mui/icons-material/AccessTime';
import BuildIcon from '@mui/icons-material/Build';
import CancelIcon from '@mui/icons-material/Cancel'; import CancelIcon from '@mui/icons-material/Cancel';
import DeviceHubIcon from '@mui/icons-material/DeviceHub'; import DeviceHubIcon from '@mui/icons-material/DeviceHub';
import DirectionsBusIcon from '@mui/icons-material/DirectionsBus'; import DirectionsBusIcon from '@mui/icons-material/DirectionsBus';
@@ -13,7 +11,6 @@ import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
import RouterIcon from '@mui/icons-material/Router'; import RouterIcon from '@mui/icons-material/Router';
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna'; import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
import TimerIcon from '@mui/icons-material/Timer'; import TimerIcon from '@mui/icons-material/Timer';
import UpgradeIcon from '@mui/icons-material/Upgrade';
import WifiIcon from '@mui/icons-material/Wifi'; import WifiIcon from '@mui/icons-material/Wifi';
import { import {
Avatar, Avatar,
@@ -46,8 +43,6 @@ import RestartMonitor from './RestartMonitor';
const SystemStatus = () => { const SystemStatus = () => {
const { LL } = useI18nContext(); const { LL } = useI18nContext();
const navigate = useNavigate();
useLayoutTitle(LL.STATUS_OF('')); useLayoutTitle(LL.STATUS_OF(''));
const { me } = useContext(AuthenticatedContext); const { me } = useContext(AuthenticatedContext);
@@ -248,28 +243,6 @@ const SystemStatus = () => {
return ( return (
<> <>
<List sx={{ borderRadius: 3, border: '2px solid grey' }}> <List sx={{ borderRadius: 3, border: '2px solid grey' }}>
<ListItem>
<ListItemAvatar>
<Avatar sx={{ bgcolor: '#134ba2', color: 'white' }}>
<BuildIcon />
</Avatar>
</ListItemAvatar>
<ListItemText
primary={LL.EMS_ESP_VER()}
secondary={'' + data.emsesp_version}
/>
{me.admin && (
<Button
startIcon={<UpgradeIcon />}
variant="outlined"
color="primary"
onClick={() => navigate('/settings/upload')}
>
{LL.UPDATE()}
</Button>
)}
</ListItem>
<ListItem> <ListItem>
<ListItemAvatar> <ListItemAvatar>
<Avatar sx={{ bgcolor: '#c5572c', color: 'white' }}> <Avatar sx={{ bgcolor: '#c5572c', color: 'white' }}>
@@ -292,6 +265,15 @@ const SystemStatus = () => {
)} )}
</ListItem> </ListItem>
<ListMenuItem
disabled={!me.admin}
icon={MemoryIcon}
bgcolor="#68374d"
label={LL.HARDWARE()}
text={formatNumber(data.free_heap) + ' KB' + ' ' + LL.FREE_MEMORY()}
to="/status/hardwarestatus"
/>
<ListMenuItem <ListMenuItem
disabled={!me.admin} disabled={!me.admin}
icon={DirectionsBusIcon} icon={DirectionsBusIcon}
@@ -301,15 +283,6 @@ const SystemStatus = () => {
to="/status/activity" to="/status/activity"
/> />
<ListMenuItem
disabled={!me.admin}
icon={MemoryIcon}
bgcolor="#68374d"
label={LL.STATUS_OF(LL.HARDWARE())}
text={formatNumber(data.free_heap) + ' KB' + ' ' + LL.FREE_MEMORY()}
to="/status/hardwarestatus"
/>
<ListMenuItem <ListMenuItem
disabled={!me.admin} disabled={!me.admin}
icon={ icon={
@@ -318,7 +291,7 @@ const SystemStatus = () => {
: RouterIcon : RouterIcon
} }
bgcolor={networkStatusHighlight()} bgcolor={networkStatusHighlight()}
label={LL.STATUS_OF(LL.NETWORK(1))} label={LL.NETWORK(1)}
text={networkStatus()} text={networkStatus()}
to="/status/network" to="/status/network"
/> />
@@ -327,7 +300,7 @@ const SystemStatus = () => {
disabled={!me.admin} disabled={!me.admin}
icon={DeviceHubIcon} icon={DeviceHubIcon}
bgcolor={activeHighlight(data.mqtt_status)} bgcolor={activeHighlight(data.mqtt_status)}
label={LL.STATUS_OF('MQTT')} label="MQTT"
text={data.mqtt_status ? LL.ACTIVE() : LL.INACTIVE(0)} text={data.mqtt_status ? LL.ACTIVE() : LL.INACTIVE(0)}
to="/status/mqtt" to="/status/mqtt"
/> />
@@ -336,7 +309,7 @@ const SystemStatus = () => {
disabled={!me.admin} disabled={!me.admin}
icon={AccessTimeIcon} icon={AccessTimeIcon}
bgcolor={ntpStatusHighlight()} bgcolor={ntpStatusHighlight()}
label={LL.STATUS_OF('NTP')} label="NTP"
text={ntpStatus()} text={ntpStatus()}
to="/status/ntp" to="/status/ntp"
/> />
@@ -345,7 +318,7 @@ const SystemStatus = () => {
disabled={!me.admin} disabled={!me.admin}
icon={SettingsInputAntennaIcon} icon={SettingsInputAntennaIcon}
bgcolor={activeHighlight(data.ap_status)} bgcolor={activeHighlight(data.ap_status)}
label={LL.STATUS_OF(LL.ACCESS_POINT(0))} label={LL.ACCESS_POINT(0)}
text={data.ap_status ? LL.ACTIVE() : LL.INACTIVE(0)} text={data.ap_status ? LL.ACTIVE() : LL.INACTIVE(0)}
to="/status/ap" to="/status/ap"
/> />

View File

@@ -2,13 +2,23 @@ import { useEffect, useRef, useState } from 'react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import DownloadIcon from '@mui/icons-material/GetApp'; import DownloadIcon from '@mui/icons-material/GetApp';
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
import WarningIcon from '@mui/icons-material/Warning'; import WarningIcon from '@mui/icons-material/Warning';
import { Box, Button, Checkbox, MenuItem, TextField, styled } from '@mui/material'; import {
Box,
Button,
Checkbox,
IconButton,
MenuItem,
TextField,
styled
} from '@mui/material';
import Grid from '@mui/material/Grid2'; import Grid from '@mui/material/Grid2';
import { API } from 'api/app';
import { fetchLogES, readLogSettings, updateLogSettings } from 'api/system'; import { fetchLogES, readLogSettings, updateLogSettings } from 'api/system';
import { useSSE } from 'alova/client'; import { useRequest, useSSE } from 'alova/client';
import { import {
BlockFormControlLabel, BlockFormControlLabel,
BlockNavigation, BlockNavigation,
@@ -80,9 +90,20 @@ const SystemLog = () => {
update: updateLogSettings update: updateLogSettings
}); });
const { send } = useRequest(
(data: string) => API({ device: 'system', cmd: 'read', id: 0, data: data }),
{
immediate: false
}
);
const [readValue, setReadValue] = useState('');
const [readOpen, setReadOpen] = useState(false);
const [logEntries, setLogEntries] = useState<LogEntry[]>([]); const [logEntries, setLogEntries] = useState<LogEntry[]>([]);
const [autoscroll, setAutoscroll] = useState(true); const [autoscroll, setAutoscroll] = useState(true);
const ALPHA_NUMERIC_DASH_REGEX = /^[a-fA-F0-9 ]+$/;
const updateFormValue = updateValueDirty( const updateFormValue = updateValueDirty(
origData, origData,
dirtyFlags, dirtyFlags,
@@ -150,6 +171,19 @@ const SystemLog = () => {
} }
}, [logEntries.length]); }, [logEntries.length]);
const sendReadCommand = () => {
if (readValue === '') {
setReadOpen(!readOpen);
return;
}
if (readValue.split(' ').filter((word) => word !== '').length > 1) {
void send(readValue);
setReadOpen(false);
setReadValue('');
}
};
const content = () => { const content = () => {
if (!data) { if (!data) {
return <FormLoader onRetry={loadData} errorMessage={errorMessage} />; return <FormLoader onRetry={loadData} errorMessage={errorMessage} />;
@@ -163,7 +197,7 @@ const SystemLog = () => {
name="level" name="level"
label={LL.LOG_LEVEL()} label={LL.LOG_LEVEL()}
value={data.level} value={data.level}
sx={{ width: '15ch' }} sx={{ width: '10ch' }}
variant="outlined" variant="outlined"
onChange={updateFormValue} onChange={updateFormValue}
margin="normal" margin="normal"
@@ -218,25 +252,71 @@ const SystemLog = () => {
label={LL.AUTO_SCROLL()} label={LL.AUTO_SCROLL()}
/> />
</Grid> </Grid>
<Button <Grid>
startIcon={<DownloadIcon />}
variant="outlined"
color="secondary"
onClick={onDownload}
>
{LL.EXPORT()}
</Button>
{dirtyFlags && dirtyFlags.length !== 0 && (
<Button <Button
startIcon={<WarningIcon color="warning" />} startIcon={<DownloadIcon />}
variant="contained" variant="outlined"
color="info" color="secondary"
onClick={saveSettings} onClick={onDownload}
> >
{LL.APPLY_CHANGES(dirtyFlags.length)} {LL.EXPORT()}
</Button> </Button>
{dirtyFlags && dirtyFlags.length !== 0 && (
<Button
startIcon={<WarningIcon color="warning" />}
variant="contained"
color="info"
onClick={saveSettings}
>
{LL.APPLY_CHANGES(dirtyFlags.length)}
</Button>
)}
</Grid>
{readOpen ? (
<Box
component="form"
sx={{ display: 'flex', alignItems: 'flex-end' }}
onSubmit={(e) => {
e.preventDefault();
sendReadCommand();
}}
>
<IconButton
disableRipple
onClick={() => {
setReadOpen(false);
setReadValue('');
}}
>
<PlayArrowIcon color="primary" sx={{ my: 2.5 }} />
</IconButton>
<TextField
value={readValue}
onChange={(e) => {
const value = e.target.value;
if (value !== '' && !ALPHA_NUMERIC_DASH_REGEX.test(value)) {
return;
}
setReadValue(value);
}}
focused={true}
size="small"
label="Send Read command" // doesn't need translating - developer only
helperText="<deviceID> <typeID> [offset] [len]"
/>
</Box>
) : (
<>
{data.developer_mode && (
<IconButton onClick={sendReadCommand}>
<PlayArrowIcon color="primary" />
</IconButton>
)}
</>
)} )}
</Grid> </Grid>
<Box <Box
sx={{ sx={{
backgroundColor: 'black', backgroundColor: 'black',

View File

@@ -39,7 +39,7 @@ const DragNdrop = ({ onFileSelected }) => {
event.preventDefault(); event.preventDefault();
const droppedFiles = event.dataTransfer.files; const droppedFiles = event.dataTransfer.files;
if (droppedFiles.length > 0) { if (droppedFiles.length > 0) {
checkFileExtension(droppedFiles[0]); checkFileExtension(droppedFiles[0] as File);
} }
}; };

View File

@@ -159,7 +159,7 @@ const cz: Translation = {
HELP_INFORMATION_2: 'Pro živý chat se komunitou se připojte k našemu serveru Discord', HELP_INFORMATION_2: 'Pro živý chat se komunitou se připojte k našemu serveru Discord',
HELP_INFORMATION_3: 'Chcete-li požádat o funkci nebo nahlásit chybu', HELP_INFORMATION_3: 'Chcete-li požádat o funkci nebo nahlásit chybu',
HELP_INFORMATION_4: 'Stáhněte a připojte informace o podpoře pro rychlejší odezvu při hlášení problému', HELP_INFORMATION_4: 'Stáhněte a připojte informace o podpoře pro rychlejší odezvu při hlášení problému',
HELP_INFORMATION_5: 'Pro pomoc a dotazy kontaktujte svého instalatéra.', HELP_INFORMATION_5: 'Pro pomoc a dotazy kontaktujte svého instalatéra',
UPLOAD: 'Nahrát', UPLOAD: 'Nahrát',
DOWNLOAD: '{{S|s|s}}táhnout', DOWNLOAD: '{{S|s|s}}táhnout',
INSTALL: 'Instalovat {0}', INSTALL: 'Instalovat {0}',
@@ -177,7 +177,6 @@ const cz: Translation = {
SYSTEM_FACTORY_TEXT_DIALOG: 'Opravdu chcete resetovat EMS-ESP do továrního nastavení?', SYSTEM_FACTORY_TEXT_DIALOG: 'Opravdu chcete resetovat EMS-ESP do továrního nastavení?',
STABLE: 'Stabilní', STABLE: 'Stabilní',
DEVELOPMENT: 'Vývojová verze', DEVELOPMENT: 'Vývojová verze',
RELEASE_NOTES: 'poznámky k vydání',
EMS_ESP_VER: 'Verze firmwaru', EMS_ESP_VER: 'Verze firmwaru',
UPTIME: 'Doba provozu systému', UPTIME: 'Doba provozu systému',
FREE_MEMORY: 'Volná paměť', FREE_MEMORY: 'Volná paměť',
@@ -287,7 +286,7 @@ const cz: Translation = {
STAY: 'Zůstat', STAY: 'Zůstat',
LEAVE: 'Odejít', LEAVE: 'Odejít',
SCHEDULER: 'Plánovač', SCHEDULER: 'Plánovač',
SCHEDULER_HELP_1: 'Automatizujte příkazy přidáním naplánovaných událostí níže. Nastavte jedinečný název pro povolení/zakázání aktivace přes API/MQTT.', SCHEDULER_HELP_1: 'Automatizujte příkazy přidáním naplánovaných událostí níže. Nastavte jedinečný název pro povolení/zakázání aktivace přes API/MQTT',
SCHEDULER_HELP_2: 'Použijte 00:00 pro spuštění při startu', SCHEDULER_HELP_2: 'Použijte 00:00 pro spuštění při startu',
SCHEDULE: 'Harmonogram', SCHEDULE: 'Harmonogram',
TIME: 'Čas', TIME: 'Čas',
@@ -344,6 +343,7 @@ const cz: Translation = {
DASHBOARD: 'Dashboard', DASHBOARD: 'Dashboard',
NO_DATA: 'Žádná data nejsou k dispozici', NO_DATA: 'Žádná data nejsou k dispozici',
DASHBOARD_1: 'Přizpůsobte si dashboard označením EMS entit jako Oblíbené pomocí modulu Přizpůsobení.', DASHBOARD_1: 'Přizpůsobte si dashboard označením EMS entit jako Oblíbené pomocí modulu Přizpůsobení.',
DEVELOPER_MODE: 'Developer Mode' // TODO translate
}; };
export default cz; export default cz;

View File

@@ -115,7 +115,7 @@ const de: Translation = {
READONLY: 'Nur-Lese-Modus aktivieren (blockiert alle ausgehenden EMS Tx-Schreibbefehle)', READONLY: 'Nur-Lese-Modus aktivieren (blockiert alle ausgehenden EMS Tx-Schreibbefehle)',
UNDERCLOCK_CPU: 'CPU-Geschwindigkeit untertakten', UNDERCLOCK_CPU: 'CPU-Geschwindigkeit untertakten',
REMOTE_TIMEOUT: 'Timeout', REMOTE_TIMEOUT: 'Timeout',
REMOTE_TIMEOUT_EN: 'Deaktiviere Remote bei fehlender Temperatur', REMOTE_TIMEOUT_EN: 'Deaktiviere Remote bei fehlender Raumtemperatur',
HEATINGOFF: 'Heizen ausschalten beim EMS-ESP Start', HEATINGOFF: 'Heizen ausschalten beim EMS-ESP Start',
MIN_DURATION: 'Dauer bis die Dusche erkannt wrid', MIN_DURATION: 'Dauer bis die Dusche erkannt wrid',
ENABLE_SHOWER_TIMER: 'Duschtimer aktivieren', ENABLE_SHOWER_TIMER: 'Duschtimer aktivieren',
@@ -155,11 +155,11 @@ const de: Translation = {
NAME: 'Name', NAME: 'Name',
CUSTOMIZATIONS_RESET: 'Möchten Sie wirklich alle Anpassungen entfernen, einschließlich der benutzerdefinierten Einstellungen der Temperatur- und Analogsensoren?', CUSTOMIZATIONS_RESET: 'Möchten Sie wirklich alle Anpassungen entfernen, einschließlich der benutzerdefinierten Einstellungen der Temperatur- und Analogsensoren?',
SUPPORT_INFORMATION: 'Unterstützende Informationen', SUPPORT_INFORMATION: 'Unterstützende Informationen',
HELP_INFORMATION_1: 'EMS-ESP Konfigurationsanweisungen und mehr finden Sie im Online-Wiki.', HELP_INFORMATION_1: 'EMS-ESP Konfigurationsanweisungen und mehr finden Sie im Online-Wiki',
HELP_INFORMATION_2: 'Für einen Live-Community-Chat besuchen Sie unseren Discord-Server.', HELP_INFORMATION_2: 'Für einen Live-Community-Chat besuchen Sie unseren Discord-Server',
HELP_INFORMATION_3: 'Um neue Funktionen anzufragen oder Fehler zu melden, eröffnen Sie ein Issue auf GitHub.', HELP_INFORMATION_3: 'Um neue Funktionen anzufragen oder Fehler zu melden, eröffnen Sie ein Issue auf GitHub',
HELP_INFORMATION_4: 'Bitte laden Sie die Systemdetails und hängen Sie sie an das Support-Issue an.', HELP_INFORMATION_4: 'Bitte laden Sie die Systemdetails und hängen Sie sie an das Support-Issue an',
HELP_INFORMATION_5: 'Für Hilfe und Fragen wenden Sie sich bitte an Ihren Installateur.', HELP_INFORMATION_5: 'Für Hilfe und Fragen wenden Sie sich bitte an Ihren Installateur',
UPLOAD: 'Hochladen', UPLOAD: 'Hochladen',
DOWNLOAD: '{{H|h|h}}erunterladen', DOWNLOAD: '{{H|h|h}}erunterladen',
INSTALL: 'Installieren {0}', INSTALL: 'Installieren {0}',
@@ -177,7 +177,6 @@ const de: Translation = {
SYSTEM_FACTORY_TEXT_DIALOG: 'Sind Sie sicher, alle Einstellungen auf Werkseinstellung zu setzen?', SYSTEM_FACTORY_TEXT_DIALOG: 'Sind Sie sicher, alle Einstellungen auf Werkseinstellung zu setzen?',
STABLE: 'Stabil', STABLE: 'Stabil',
DEVELOPMENT: 'Entwicklung', DEVELOPMENT: 'Entwicklung',
RELEASE_NOTES: 'Versionshinweise',
EMS_ESP_VER: 'Firmware-Version', EMS_ESP_VER: 'Firmware-Version',
UPTIME: 'Systembetriebszeit', UPTIME: 'Systembetriebszeit',
FREE_MEMORY: 'Freier RAM Speicher', FREE_MEMORY: 'Freier RAM Speicher',
@@ -287,7 +286,7 @@ const de: Translation = {
STAY: 'Bleiben', STAY: 'Bleiben',
LEAVE: 'Verlassen', LEAVE: 'Verlassen',
SCHEDULER: 'Planer', SCHEDULER: 'Planer',
SCHEDULER_HELP_1: 'Fügen Sie eigene geplante Befehle zur Automatisierung hinzu. Vergeben Sie einen Entitätsnamen, um die Aktivierung über API/Mqtt zu steuern.', SCHEDULER_HELP_1: 'Fügen Sie eigene geplante Befehle zur Automatisierung hinzu. Vergeben Sie einen Entitätsnamen, um die Aktivierung über API/Mqtt zu steuern',
SCHEDULER_HELP_2: '00:00 aktiviert einmalige Ausführung beim Start.', SCHEDULER_HELP_2: '00:00 aktiviert einmalige Ausführung beim Start.',
SCHEDULE: 'Zeitplan', SCHEDULE: 'Zeitplan',
TIME: 'Zeit', TIME: 'Zeit',
@@ -343,7 +342,8 @@ const de: Translation = {
AUTO_SCROLL: 'Automatisches Scrollen', AUTO_SCROLL: 'Automatisches Scrollen',
DASHBOARD: 'Dashboard', DASHBOARD: 'Dashboard',
NO_DATA: 'Keine Daten verfügbar', NO_DATA: 'Keine Daten verfügbar',
DASHBOARD_1: 'Passen Sie Ihr Dashboard an, indem Sie EMS-Entitäten mithilfe des Moduls „Anpassungen“ als Favorit markieren.' DASHBOARD_1: 'Passen Sie Ihr Dashboard an, indem Sie EMS-Entitäten mithilfe des Moduls „Anpassungen“ als Favorit markieren.',
DEVELOPER_MODE: 'Entwicklermodus'
}; };
export default de; export default de;

View File

@@ -115,7 +115,7 @@ const en: Translation = {
READONLY: 'Enable read-only mode (blocks all outgoing EMS Tx Write commands)', READONLY: 'Enable read-only mode (blocks all outgoing EMS Tx Write commands)',
UNDERCLOCK_CPU: 'Underclock CPU speed', UNDERCLOCK_CPU: 'Underclock CPU speed',
REMOTE_TIMEOUT: 'Remote timeout', REMOTE_TIMEOUT: 'Remote timeout',
REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', REMOTE_TIMEOUT_EN: 'Disable remote on missing room temperature',
HEATINGOFF: 'Start boiler with forced heating off', HEATINGOFF: 'Start boiler with forced heating off',
MIN_DURATION: 'Wait time', MIN_DURATION: 'Wait time',
ENABLE_SHOWER_TIMER: 'Enable Shower Timer', ENABLE_SHOWER_TIMER: 'Enable Shower Timer',
@@ -159,7 +159,7 @@ const en: Translation = {
HELP_INFORMATION_2: 'For live community chat join our Discord server', HELP_INFORMATION_2: 'For live community chat join our Discord server',
HELP_INFORMATION_3: 'To request a feature or report a bug', HELP_INFORMATION_3: 'To request a feature or report a bug',
HELP_INFORMATION_4: 'Download and attach your support information for a faster response when reporting an issue', HELP_INFORMATION_4: 'Download and attach your support information for a faster response when reporting an issue',
HELP_INFORMATION_5: 'For help and questions please contact your installer.', HELP_INFORMATION_5: 'For help and questions please contact your installer',
UPLOAD: 'Upload', UPLOAD: 'Upload',
DOWNLOAD: '{{D|d|d}}ownload', DOWNLOAD: '{{D|d|d}}ownload',
INSTALL: 'Install {0}', INSTALL: 'Install {0}',
@@ -177,7 +177,6 @@ const en: Translation = {
SYSTEM_FACTORY_TEXT_DIALOG: 'Are you sure you want to reset EMS-ESP to its factory defaults?', SYSTEM_FACTORY_TEXT_DIALOG: 'Are you sure you want to reset EMS-ESP to its factory defaults?',
STABLE: 'Stable', STABLE: 'Stable',
DEVELOPMENT: 'Development', DEVELOPMENT: 'Development',
RELEASE_NOTES: 'release notes',
EMS_ESP_VER: 'Firmware Version', EMS_ESP_VER: 'Firmware Version',
UPTIME: 'System Uptime', UPTIME: 'System Uptime',
FREE_MEMORY: 'Free Memory', FREE_MEMORY: 'Free Memory',
@@ -287,7 +286,7 @@ const en: Translation = {
STAY: 'Stay', STAY: 'Stay',
LEAVE: 'Leave', LEAVE: 'Leave',
SCHEDULER: 'Scheduler', SCHEDULER: 'Scheduler',
SCHEDULER_HELP_1: 'Automate commands by adding scheduled events below. Set a unique Name to enable/disable activation via API/MQTT.', SCHEDULER_HELP_1: 'Automate commands by adding scheduled events below. Set a unique Name to enable/disable activation via API/MQTT',
SCHEDULER_HELP_2: 'Use 00:00 to trigger once on start-up', SCHEDULER_HELP_2: 'Use 00:00 to trigger once on start-up',
SCHEDULE: 'Schedule', SCHEDULE: 'Schedule',
TIME: 'Time', TIME: 'Time',
@@ -343,7 +342,8 @@ const en: Translation = {
AUTO_SCROLL: 'Auto Scroll', AUTO_SCROLL: 'Auto Scroll',
DASHBOARD: 'Dashboard', DASHBOARD: 'Dashboard',
NO_DATA: 'No data available', NO_DATA: 'No data available',
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module.', DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module',
DEVELOPER_MODE: 'Developer Mode'
}; };
export default en; export default en;

View File

@@ -26,7 +26,7 @@ const fr: Translation = {
ENTITIES: 'entités', ENTITIES: 'entités',
REFRESH: 'Rafraîchir', REFRESH: 'Rafraîchir',
EXPORT: 'Exporter', EXPORT: 'Exporter',
FAVORITES: "Favoris", // TODO translate FAVORITES: "Favoris",
DEVICE_DETAILS: "Détails de l'appareil", DEVICE_DETAILS: "Détails de l'appareil",
ID_OF: 'ID {0}', ID_OF: 'ID {0}',
DEVICE: 'Appareil', DEVICE: 'Appareil',
@@ -116,7 +116,7 @@ const fr: Translation = {
UNDERCLOCK_CPU: 'Underclock du CPU', UNDERCLOCK_CPU: 'Underclock du CPU',
HEATINGOFF: 'Start boiler with forced heating off', // TODO translate HEATINGOFF: 'Start boiler with forced heating off', // TODO translate
REMOTE_TIMEOUT: 'Remote timeout', REMOTE_TIMEOUT: 'Remote timeout',
REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', REMOTE_TIMEOUT_EN: 'Disable remote on missing room temperature', // TODO translate
MIN_DURATION: 'Wait time', MIN_DURATION: 'Wait time',
ENABLE_SHOWER_TIMER: 'Activer la minuterie de la douche', ENABLE_SHOWER_TIMER: 'Activer la minuterie de la douche',
ENABLE_SHOWER_ALERT: 'Activer les alertes de durée de douche', ENABLE_SHOWER_ALERT: 'Activer les alertes de durée de douche',
@@ -147,7 +147,7 @@ const fr: Translation = {
CUSTOMIZATIONS_HELP_2: 'marquer comme favori', CUSTOMIZATIONS_HELP_2: 'marquer comme favori',
CUSTOMIZATIONS_HELP_3: "désactiver l'action d'écriture", CUSTOMIZATIONS_HELP_3: "désactiver l'action d'écriture",
CUSTOMIZATIONS_HELP_4: "exclure de MQTT et de l'API", CUSTOMIZATIONS_HELP_4: "exclure de MQTT et de l'API",
CUSTOMIZATIONS_HELP_5: 'cacher des appareils', // TODO translate CUSTOMIZATIONS_HELP_5: 'cacher des appareils',
CUSTOMIZATIONS_HELP_6: 'remove from memory', // TODO translate CUSTOMIZATIONS_HELP_6: 'remove from memory', // TODO translate
SELECT_DEVICE: 'Sélectionnez un appareil', SELECT_DEVICE: 'Sélectionnez un appareil',
SET_ALL: 'tout régler', SET_ALL: 'tout régler',
@@ -155,11 +155,11 @@ const fr: Translation = {
NAME: 'Nom', NAME: 'Nom',
CUSTOMIZATIONS_RESET: 'Êtes-vous sûr de vouloir supprimer toutes les personnalisations, y compris les paramètres personnalisés des capteurs de température et analogiques ?', CUSTOMIZATIONS_RESET: 'Êtes-vous sûr de vouloir supprimer toutes les personnalisations, y compris les paramètres personnalisés des capteurs de température et analogiques ?',
SUPPORT_INFORMATION: 'Information de support', SUPPORT_INFORMATION: 'Information de support',
HELP_INFORMATION_1: 'Visitez le wiki en ligne pour obtenir des instructions sur la façon de configurer EMS-ESP.', HELP_INFORMATION_1: 'Visitez le wiki en ligne pour obtenir des instructions sur la façon de configurer EMS-ESP',
HELP_INFORMATION_2: 'Pour une discussion en direct avec la communauté, rejoignez notre serveur Discord', HELP_INFORMATION_2: 'Pour une discussion en direct avec la communauté, rejoignez notre serveur Discord',
HELP_INFORMATION_3: 'Pour demander une fonctionnalité ou signaler un problème', HELP_INFORMATION_3: 'Pour demander une fonctionnalité ou signaler un problème',
HELP_INFORMATION_4: "N'oubliez pas de télécharger et de joindre les informations relatives à votre système pour obtenir une réponse plus rapide lorsque vous signalez un problème", HELP_INFORMATION_4: "N'oubliez pas de télécharger et de joindre les informations relatives à votre système pour obtenir une réponse plus rapide lorsque vous signalez un problème",
HELP_INFORMATION_5: 'For help and questions please contact your installer.', // TODO translate HELP_INFORMATION_5: 'For help and questions please contact your installer', // TODO translate
UPLOAD: 'Upload', UPLOAD: 'Upload',
DOWNLOAD: '{{D|d|d}}ownload', DOWNLOAD: '{{D|d|d}}ownload',
INSTALL: 'Installer {0}', INSTALL: 'Installer {0}',
@@ -177,7 +177,6 @@ const fr: Translation = {
SYSTEM_FACTORY_TEXT_DIALOG: "Êtes-vous sûr de vouloir réinitialiser l'appareil à ses paramètres d'usine ?", SYSTEM_FACTORY_TEXT_DIALOG: "Êtes-vous sûr de vouloir réinitialiser l'appareil à ses paramètres d'usine ?",
STABLE: 'Stable', // TODO translate STABLE: 'Stable', // TODO translate
DEVELOPMENT: 'Développement', DEVELOPMENT: 'Développement',
RELEASE_NOTES: 'notes de version',
EMS_ESP_VER: 'Firmware Version', // TODO translate EMS_ESP_VER: 'Firmware Version', // TODO translate
UPTIME: 'Durée de fonctionnement du système', UPTIME: 'Durée de fonctionnement du système',
FREE_MEMORY: 'Libre Memory', FREE_MEMORY: 'Libre Memory',
@@ -261,7 +260,7 @@ const fr: Translation = {
SCAN_AGAIN: 'Rescanner', SCAN_AGAIN: 'Rescanner',
NETWORK_SCANNER: 'Scan réseau', NETWORK_SCANNER: 'Scan réseau',
NETWORK_NO_WIFI: 'Pas de réseau WiFi trouvé', NETWORK_NO_WIFI: 'Pas de réseau WiFi trouvé',
NETWORK_BLANK_SSID: 'laisser vide pour désactiver le WiFi', // and enable ETH // TODO translate NETWORK_BLANK_SSID: 'laisser vide pour désactiver le WiFi',
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
TX_POWER: 'Puissance Tx', TX_POWER: 'Puissance Tx',
HOSTNAME: "Nom d'hôte", HOSTNAME: "Nom d'hôte",
@@ -287,7 +286,7 @@ const fr: Translation = {
STAY: 'Stay', // TODO translate STAY: 'Stay', // TODO translate
LEAVE: 'Leave', // TODO translate LEAVE: 'Leave', // TODO translate
SCHEDULER: 'Scheduler', // TODO translate SCHEDULER: 'Scheduler', // TODO translate
SCHEDULER_HELP_1: 'Automate commands by adding scheduled events below. Set a unique Name to enable/disable activation via API/MQTT.', // TODO translate SCHEDULER_HELP_1: 'Automate commands by adding scheduled events below. Set a unique Name to enable/disable activation via API/MQTT', // TODO translate
SCHEDULER_HELP_2: 'Use 00:00 to trigger once on start-up', // TODO translate SCHEDULER_HELP_2: 'Use 00:00 to trigger once on start-up', // TODO translate
SCHEDULE: 'Schedule', // TODO translate SCHEDULE: 'Schedule', // TODO translate
TIME: 'Time', // TODO translate TIME: 'Time', // TODO translate
@@ -321,7 +320,7 @@ const fr: Translation = {
SECURITY_1: 'Add or remove users', // TODO translate SECURITY_1: 'Add or remove users', // TODO translate
DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware', // TODO translate DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware', // TODO translate
MODULES: 'Module', // TODO translate MODULES: 'Module', // TODO translate
MODULES_1: 'Activer ou désactiver les modules externes', // TODO translate MODULES_1: 'Activer ou désactiver les modules externes',
MODULES_UPDATED: 'Modules updated', // TODO translate MODULES_UPDATED: 'Modules updated', // TODO translate
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
MODULES_NONE: 'No external modules detected', // TODO translate MODULES_NONE: 'No external modules detected', // TODO translate
@@ -336,14 +335,15 @@ const fr: Translation = {
INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate INSTALL_VERSION: 'This will install version {0}. Are you sure?', // TODO translate
SWITCH_DEV: 'switch to the development version', // TODO translate SWITCH_DEV: 'switch to the development version', // TODO translate
UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate UPGRADE_AVAILABLE: 'There is a firmware upgrade available!', // TODO translate
LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate // TODO translate LATEST_VERSION: 'You are using the latest firmware version.', // TODO translate
PLEASE_WAIT: 'Please wait', // TODO translate PLEASE_WAIT: 'Please wait', // TODO translate
RESTARTING_PRE: 'Initializing', // TODO translate RESTARTING_PRE: 'Initializing', // TODO translate
RESTARTING_POST: 'Preparing', // TODO translate RESTARTING_POST: 'Preparing', // TODO translate
AUTO_SCROLL: 'Auto Scroll', // TODO translate AUTO_SCROLL: 'Auto Scroll', // TODO translate
DASHBOARD: 'Dashboard', // TODO translate DASHBOARD: 'Dashboard', // TODO translate
NO_DATA: 'No data available', // TODO translate NO_DATA: 'No data available', // TODO translate
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module.' // TODO translate DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module', // TODO translate
DEVELOPER_MODE: 'Developer Mode' // TODO translate
}; };
export default fr; export default fr;

View File

@@ -26,7 +26,7 @@ const it: Translation = {
ENTITIES: 'entità', ENTITIES: 'entità',
REFRESH: 'Ricaricare', REFRESH: 'Ricaricare',
EXPORT: 'Esporta', EXPORT: 'Esporta',
FAVORITES: "Preferiti", // TODO Translate FAVORITES: "Preferiti",
DEVICE_DETAILS: 'Dettagli dispositivo', DEVICE_DETAILS: 'Dettagli dispositivo',
ID_OF: '{0} ID', ID_OF: '{0} ID',
DEVICE: 'Dispositivo', DEVICE: 'Dispositivo',
@@ -115,7 +115,7 @@ const it: Translation = {
READONLY: 'Abilita modalità sola-lettura (blocca tutti i comandi di scrittura EMS Tx in uscita)', READONLY: 'Abilita modalità sola-lettura (blocca tutti i comandi di scrittura EMS Tx in uscita)',
UNDERCLOCK_CPU: 'Abbassa velocità della CPU', UNDERCLOCK_CPU: 'Abbassa velocità della CPU',
REMOTE_TIMEOUT: 'Remote timeout', REMOTE_TIMEOUT: 'Remote timeout',
REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', REMOTE_TIMEOUT_EN: 'Disable remote on missing room temperature', // TODO translate
HEATINGOFF: 'Avviamento caldaia con riscaldamento forzato spento', HEATINGOFF: 'Avviamento caldaia con riscaldamento forzato spento',
MIN_DURATION: 'Wait time', MIN_DURATION: 'Wait time',
ENABLE_SHOWER_TIMER: 'Abilita timer doccia', ENABLE_SHOWER_TIMER: 'Abilita timer doccia',
@@ -147,7 +147,7 @@ const it: Translation = {
CUSTOMIZATIONS_HELP_2: 'seleziona come preferito', CUSTOMIZATIONS_HELP_2: 'seleziona come preferito',
CUSTOMIZATIONS_HELP_3: 'disabilita azione scrittura', CUSTOMIZATIONS_HELP_3: 'disabilita azione scrittura',
CUSTOMIZATIONS_HELP_4: 'esculdi da MQTT e API', CUSTOMIZATIONS_HELP_4: 'esculdi da MQTT e API',
CUSTOMIZATIONS_HELP_5: 'nascondi dai dispositivi', // TODO translate CUSTOMIZATIONS_HELP_5: 'nascondi dai dispositivi',
CUSTOMIZATIONS_HELP_6: 'rimuovi dalla memoria', CUSTOMIZATIONS_HELP_6: 'rimuovi dalla memoria',
SELECT_DEVICE: 'Seleziona un dispositivo', SELECT_DEVICE: 'Seleziona un dispositivo',
SET_ALL: 'imposta tutto', SET_ALL: 'imposta tutto',
@@ -159,7 +159,7 @@ const it: Translation = {
HELP_INFORMATION_2: 'Per la chat della community dal vivo unisciti al nostro server Discord', HELP_INFORMATION_2: 'Per la chat della community dal vivo unisciti al nostro server Discord',
HELP_INFORMATION_3: 'Per richiedere una funzionalità o segnalare un errore', HELP_INFORMATION_3: 'Per richiedere una funzionalità o segnalare un errore',
HELP_INFORMATION_4: 'Ricordati di scaricare e allegare le informazioni del tuo sistema per una risposta più rapida quando segnali un problema', HELP_INFORMATION_4: 'Ricordati di scaricare e allegare le informazioni del tuo sistema per una risposta più rapida quando segnali un problema',
HELP_INFORMATION_5: 'For help and questions please contact your installer.', // TODO translate HELP_INFORMATION_5: 'For help and questions please contact your installer', // TODO translate
UPLOAD: 'Carica', UPLOAD: 'Carica',
DOWNLOAD: 'Scarica', DOWNLOAD: 'Scarica',
INSTALL: 'Installare {0}', INSTALL: 'Installare {0}',
@@ -177,7 +177,6 @@ const it: Translation = {
SYSTEM_FACTORY_TEXT_DIALOG: 'Sei sicuro di voler ripristinare il dispositivo alle impostazioni di fabbrica??', SYSTEM_FACTORY_TEXT_DIALOG: 'Sei sicuro di voler ripristinare il dispositivo alle impostazioni di fabbrica??',
STABLE: 'Stable', // TODO translate STABLE: 'Stable', // TODO translate
DEVELOPMENT: 'Sviluppo', DEVELOPMENT: 'Sviluppo',
RELEASE_NOTES: 'note rilascio',
EMS_ESP_VER: 'Versione Firmware', EMS_ESP_VER: 'Versione Firmware',
UPTIME: 'Tempo di attività del sistema', UPTIME: 'Tempo di attività del sistema',
FREE_MEMORY: 'Free Memory', FREE_MEMORY: 'Free Memory',
@@ -287,20 +286,20 @@ const it: Translation = {
STAY: 'Stai', STAY: 'Stai',
LEAVE: 'Esci', LEAVE: 'Esci',
SCHEDULER: 'Programma eventi', SCHEDULER: 'Programma eventi',
SCHEDULER_HELP_1: "Automatizza i comandi aggiungendo gli eventi programmati di seguito. Imposta un nome univoco per abilitare/disabilitare l'attivazione tramite API/MQTT.", SCHEDULER_HELP_1: "Automatizza i comandi aggiungendo gli eventi programmati di seguito. Imposta un nome univoco per abilitare/disabilitare l'attivazione tramite API/MQTT",
SCHEDULER_HELP_2: "per attivare una volta all'avvio", SCHEDULER_HELP_2: "per attivare una volta all'avvio",
SCHEDULE: 'Programma', SCHEDULE: 'Programma',
TIME: 'Ora', TIME: 'Ora',
TIMER: 'Orologio', TIMER: 'Orologio',
ONCHANGE: 'Sul cambiamento', // TODO translate ONCHANGE: 'Sul cambiamento',
CONDITION: 'Condizione', // TODO translate CONDITION: 'Condizione',
IMMEDIATE: 'Immediata', // TODO translate IMMEDIATE: 'Immediata',
SCHEDULE_UPDATED: 'Calendario aggiornato', SCHEDULE_UPDATED: 'Calendario aggiornato',
SCHEDULE_TIMER_1: 'All avvio', SCHEDULE_TIMER_1: 'All avvio',
SCHEDULE_TIMER_2: 'Ogni minuto', SCHEDULE_TIMER_2: 'Ogni minuto',
SCHEDULE_TIMER_3: 'Ogni ora', SCHEDULE_TIMER_3: 'Ogni ora',
CUSTOM_ENTITIES: 'Entità personalizzate', CUSTOM_ENTITIES: 'Entità personalizzate',
ENTITIES_HELP_1: 'Recupera entità personalizzate dal BUS EMS', // TODO translate ENTITIES_HELP_1: 'Recupera entità personalizzate dal BUS EMS',
ENTITIES_UPDATED: 'Entità aggiornate', ENTITIES_UPDATED: 'Entità aggiornate',
WRITEABLE: 'Scrivibile', WRITEABLE: 'Scrivibile',
SHOWING: 'Visualizza', SHOWING: 'Visualizza',
@@ -343,7 +342,8 @@ const it: Translation = {
AUTO_SCROLL: 'Auto Scroll', // TODO translate AUTO_SCROLL: 'Auto Scroll', // TODO translate
DASHBOARD: 'Dashboard', // TODO translate DASHBOARD: 'Dashboard', // TODO translate
NO_DATA: 'No data available', // TODO translate NO_DATA: 'No data available', // TODO translate
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module.' // TODO translate DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module', // TODO translate
DEVELOPER_MODE: 'Developer Mode' // TODO translate
}; };
export default it; export default it;

View File

@@ -26,7 +26,7 @@ const nl: Translation = {
ENTITIES: 'entiteiten', ENTITIES: 'entiteiten',
REFRESH: 'Ververs', REFRESH: 'Ververs',
EXPORT: 'Export', EXPORT: 'Export',
FAVORITES: "Favorieten", // TODO Translate FAVORITES: "Favorieten",
DEVICE_DETAILS: 'Device Gegevens', DEVICE_DETAILS: 'Device Gegevens',
ID_OF: '{0} ID', ID_OF: '{0} ID',
DEVICE: 'Apparaat', DEVICE: 'Apparaat',
@@ -115,7 +115,7 @@ const nl: Translation = {
READONLY: 'Activeer read-only modus (blokkeert alle outgaande EMS Tx schrijf commandos)', READONLY: 'Activeer read-only modus (blokkeert alle outgaande EMS Tx schrijf commandos)',
UNDERCLOCK_CPU: 'Underclock CPU snelheid', UNDERCLOCK_CPU: 'Underclock CPU snelheid',
REMOTE_TIMEOUT: 'Remote timeout', REMOTE_TIMEOUT: 'Remote timeout',
REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', REMOTE_TIMEOUT_EN: 'Disable remote on missing room temperature', // TODO translate
HEATINGOFF: 'Start ketel met geforceerde verwarming uit', HEATINGOFF: 'Start ketel met geforceerde verwarming uit',
MIN_DURATION: 'Wait time', MIN_DURATION: 'Wait time',
ENABLE_SHOWER_TIMER: 'Activeer Douche Timer (tijdmeting)', ENABLE_SHOWER_TIMER: 'Activeer Douche Timer (tijdmeting)',
@@ -147,7 +147,7 @@ const nl: Translation = {
CUSTOMIZATIONS_HELP_2: 'Markeer as favoriet', CUSTOMIZATIONS_HELP_2: 'Markeer as favoriet',
CUSTOMIZATIONS_HELP_3: 'Zet schrijfacties uit', CUSTOMIZATIONS_HELP_3: 'Zet schrijfacties uit',
CUSTOMIZATIONS_HELP_4: 'Uitsluiten van MQTT en API', CUSTOMIZATIONS_HELP_4: 'Uitsluiten van MQTT en API',
CUSTOMIZATIONS_HELP_5: 'verbergen voor apparaten', // TODO translate CUSTOMIZATIONS_HELP_5: 'verbergen voor apparaten',
CUSTOMIZATIONS_HELP_6: 'verwijderen van memory', CUSTOMIZATIONS_HELP_6: 'verwijderen van memory',
SELECT_DEVICE: 'Selecteer een apparaat', SELECT_DEVICE: 'Selecteer een apparaat',
SET_ALL: 'Alles aanzetten', SET_ALL: 'Alles aanzetten',
@@ -159,7 +159,7 @@ const nl: Translation = {
HELP_INFORMATION_2: 'Voor de live community ga naar de Discord server', HELP_INFORMATION_2: 'Voor de live community ga naar de Discord server',
HELP_INFORMATION_3: 'Om een nieuwe feature te vragen of een bug te rapporteren', HELP_INFORMATION_3: 'Om een nieuwe feature te vragen of een bug te rapporteren',
HELP_INFORMATION_4: 'Zorg dat je ook je systeem details zijn toevoeged voor een sneller antwoord', HELP_INFORMATION_4: 'Zorg dat je ook je systeem details zijn toevoeged voor een sneller antwoord',
HELP_INFORMATION_5: 'For help and questions please contact your installer.', // TODO translate HELP_INFORMATION_5: 'For help and questions please contact your installer', // TODO translate
UPLOAD: 'Upload', UPLOAD: 'Upload',
DOWNLOAD: '{{D|d|d}}ownload', DOWNLOAD: '{{D|d|d}}ownload',
INSTALL: 'Installeren {0}', INSTALL: 'Installeren {0}',
@@ -177,7 +177,6 @@ const nl: Translation = {
SYSTEM_FACTORY_TEXT_DIALOG: 'Weet je zeker dat je een reset naar fabrieksinstellingen uit wilt voeren?', SYSTEM_FACTORY_TEXT_DIALOG: 'Weet je zeker dat je een reset naar fabrieksinstellingen uit wilt voeren?',
STABLE: 'Stable', STABLE: 'Stable',
DEVELOPMENT: 'Development', DEVELOPMENT: 'Development',
RELEASE_NOTES: 'release notes',
EMS_ESP_VER: 'Firmware Versie', EMS_ESP_VER: 'Firmware Versie',
UPTIME: 'Systeem Uptime', UPTIME: 'Systeem Uptime',
FREE_MEMORY: 'Free Memory', FREE_MEMORY: 'Free Memory',
@@ -287,14 +286,14 @@ const nl: Translation = {
STAY: 'Blijven', STAY: 'Blijven',
LEAVE: 'Verlaten', LEAVE: 'Verlaten',
SCHEDULER: 'Scheduler', SCHEDULER: 'Scheduler',
SCHEDULER_HELP_1: 'Automatiseer opdrachten door hieronder geplande gebeurtenissen toe te voegen. Stel een unieke naam in om activering via API/MQTT in/uit te schakelen.', SCHEDULER_HELP_1: 'Automatiseer opdrachten door hieronder geplande gebeurtenissen toe te voegen. Stel een unieke naam in om activering via API/MQTT in/uit te schakelen',
SCHEDULER_HELP_2: 'Gebruik 00:00 om eenmaal te activeren bij het opstarten', SCHEDULER_HELP_2: 'Gebruik 00:00 om eenmaal te activeren bij het opstarten',
SCHEDULE: 'Schedule', SCHEDULE: 'Schedule',
TIME: 'Tijd', TIME: 'Tijd',
TIMER: 'Timer', TIMER: 'Timer',
ONCHANGE: 'Op verandering', // TODO translate ONCHANGE: 'Op verandering',
CONDITION: 'Voorwaarde', // TODO translate CONDITION: 'Voorwaarde',
IMMEDIATE: 'Onmiddellijk', // TODO translate IMMEDIATE: 'Onmiddellijk',
SCHEDULE_UPDATED: 'Schema bijgewerkt', SCHEDULE_UPDATED: 'Schema bijgewerkt',
SCHEDULE_TIMER_1: 'bij het opstarten', SCHEDULE_TIMER_1: 'bij het opstarten',
SCHEDULE_TIMER_2: 'elke minuut', SCHEDULE_TIMER_2: 'elke minuut',
@@ -343,7 +342,8 @@ const nl: Translation = {
AUTO_SCROLL: 'Auto Scroll', // TODO translate AUTO_SCROLL: 'Auto Scroll', // TODO translate
DASHBOARD: 'Dashboard', // TODO translate DASHBOARD: 'Dashboard', // TODO translate
NO_DATA: 'No data available', // TODO translate NO_DATA: 'No data available', // TODO translate
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module.' // TODO translate DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module', // TODO translate
DEVELOPER_MODE: 'Developer Mode' // TODO translate
}; };
export default nl; export default nl;

View File

@@ -26,7 +26,7 @@ const no: Translation = {
ENTITIES: 'Ojekter', ENTITIES: 'Ojekter',
REFRESH: 'Oppdater', REFRESH: 'Oppdater',
EXPORT: 'Eksport', EXPORT: 'Eksport',
FAVORITES: "Favoritter", // TODO translate FAVORITES: "Favoritter",
DEVICE_DETAILS: 'Enhetsdetaljer', DEVICE_DETAILS: 'Enhetsdetaljer',
ID_OF: '{0}-ID', ID_OF: '{0}-ID',
DEVICE: 'Enhets', DEVICE: 'Enhets',
@@ -115,7 +115,7 @@ const no: Translation = {
READONLY: 'Aktiver read-only modus (blokker all EMS Tx Skriving)', READONLY: 'Aktiver read-only modus (blokker all EMS Tx Skriving)',
UNDERCLOCK_CPU: 'Underklokking av prosessorhastighet', UNDERCLOCK_CPU: 'Underklokking av prosessorhastighet',
REMOTE_TIMEOUT: 'Remote timeout', REMOTE_TIMEOUT: 'Remote timeout',
REMOTE_TIMEOUT_EN: 'Disable remote control on missing roomtemperature', REMOTE_TIMEOUT_EN: 'Disable remote control on missing room temperature', // TODO translate
HEATINGOFF: 'Start boiler with forced heating off', // TODO translate HEATINGOFF: 'Start boiler with forced heating off', // TODO translate
MIN_DURATION: 'Wait time', MIN_DURATION: 'Wait time',
ENABLE_SHOWER_TIMER: 'Aktiver Dusjtimer', ENABLE_SHOWER_TIMER: 'Aktiver Dusjtimer',
@@ -147,7 +147,7 @@ const no: Translation = {
CUSTOMIZATIONS_HELP_2: 'merk som favoritt', CUSTOMIZATIONS_HELP_2: 'merk som favoritt',
CUSTOMIZATIONS_HELP_3: 'inaktiviser skriving', CUSTOMIZATIONS_HELP_3: 'inaktiviser skriving',
CUSTOMIZATIONS_HELP_4: 'ekskludere fra MQTT og API', CUSTOMIZATIONS_HELP_4: 'ekskludere fra MQTT og API',
CUSTOMIZATIONS_HELP_5: 'skjul fra enheter', // TODO translate CUSTOMIZATIONS_HELP_5: 'skjul fra enheter',
CUSTOMIZATIONS_HELP_6: 'fjern fra minnet', CUSTOMIZATIONS_HELP_6: 'fjern fra minnet',
SELECT_DEVICE: 'Velg en enhet', SELECT_DEVICE: 'Velg en enhet',
SET_ALL: 'sett alle', SET_ALL: 'sett alle',
@@ -159,7 +159,7 @@ const no: Translation = {
HELP_INFORMATION_2: 'For community-support besøk vår Discord-server', HELP_INFORMATION_2: 'For community-support besøk vår Discord-server',
HELP_INFORMATION_3: 'For å be om en ny funksjon eller melde feil', HELP_INFORMATION_3: 'For å be om en ny funksjon eller melde feil',
HELP_INFORMATION_4: 'Husk å laste ned og legg ved din systeminformasjon for en raskere respons når du rapporterer et problem', HELP_INFORMATION_4: 'Husk å laste ned og legg ved din systeminformasjon for en raskere respons når du rapporterer et problem',
HELP_INFORMATION_5: 'For help and questions please contact your installer.', // TODO translate HELP_INFORMATION_5: 'For help and questions please contact your installer', // TODO translate
UPLOAD: 'Opplasning', UPLOAD: 'Opplasning',
DOWNLOAD: '{{N|n|n}}edlasting', DOWNLOAD: '{{N|n|n}}edlasting',
INSTALL: 'Installer {0}', INSTALL: 'Installer {0}',
@@ -177,7 +177,6 @@ const no: Translation = {
SYSTEM_FACTORY_TEXT_DIALOG: 'Er du sikker på at du vil resette enheten til fabrikkinstillinger?', SYSTEM_FACTORY_TEXT_DIALOG: 'Er du sikker på at du vil resette enheten til fabrikkinstillinger?',
STABLE: 'Stable', // TODO translate STABLE: 'Stable', // TODO translate
DEVELOPMENT: 'Development', DEVELOPMENT: 'Development',
RELEASE_NOTES: 'release notes',
EMS_ESP_VER: 'Firmware Version', // TODO translate EMS_ESP_VER: 'Firmware Version', // TODO translate
UPTIME: 'System Oppetid', UPTIME: 'System Oppetid',
FREE_MEMORY: 'Ledig Memory', FREE_MEMORY: 'Ledig Memory',
@@ -261,7 +260,7 @@ const no: Translation = {
SCAN_AGAIN: 'Søk igjen', SCAN_AGAIN: 'Søk igjen',
NETWORK_SCANNER: 'Nettverk Scanner', NETWORK_SCANNER: 'Nettverk Scanner',
NETWORK_NO_WIFI: 'Ingen trådløse nett funnet', NETWORK_NO_WIFI: 'Ingen trådløse nett funnet',
NETWORK_BLANK_SSID: 'la feltet være blankt for å deaktivisere trådløst nettverk', // TODO translate NETWORK_BLANK_SSID: 'la feltet være blankt for å deaktivisere trådløst nettverk',
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
TX_POWER: 'Tx Effekt', TX_POWER: 'Tx Effekt',
HOSTNAME: 'Hostname', HOSTNAME: 'Hostname',
@@ -287,14 +286,14 @@ const no: Translation = {
STAY: 'Bli her', STAY: 'Bli her',
LEAVE: 'Forlat', LEAVE: 'Forlat',
SCHEDULER: 'Planlegger', SCHEDULER: 'Planlegger',
SCHEDULER_HELP_1: 'Automatiser kommandoer ved å legge til skedulerte hendelser nedenfor. Sett et unikt navn for å slå på/av aktivering via API/MQTT.', SCHEDULER_HELP_1: 'Automatiser kommandoer ved å legge til skedulerte hendelser nedenfor. Sett et unikt navn for å slå på/av aktivering via API/MQTT',
SCHEDULER_HELP_2: 'Bruk 00:00 for å kjøre en gang ved oppstart', SCHEDULER_HELP_2: 'Bruk 00:00 for å kjøre en gang ved oppstart',
SCHEDULE: 'Planlegg', SCHEDULE: 'Planlegg',
TIME: 'Tid', TIME: 'Tid',
TIMER: 'Timer', TIMER: 'Timer',
ONCHANGE: 'På endring', // TODO translate ONCHANGE: 'På endring',
CONDITION: 'Betingelse', // TODO translate CONDITION: 'Betingelse',
IMMEDIATE: 'Umiddelbar', // TODO translate IMMEDIATE: 'Umiddelbar',
SCHEDULE_UPDATED: 'Planlegger er oppdatert', SCHEDULE_UPDATED: 'Planlegger er oppdatert',
SCHEDULE_TIMER_1: 'ved oppstart', SCHEDULE_TIMER_1: 'ved oppstart',
SCHEDULE_TIMER_2: 'hvert minutt', SCHEDULE_TIMER_2: 'hvert minutt',
@@ -321,7 +320,7 @@ const no: Translation = {
SECURITY_1: 'Add or remove users', // TODO translate SECURITY_1: 'Add or remove users', // TODO translate
DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware', // TODO translate DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware', // TODO translate
MODULES: 'Module', // TODO translate MODULES: 'Module', // TODO translate
MODULES_1: 'Aktiver eller deaktiver eksterne moduler', // TODO translate MODULES_1: 'Aktiver eller deaktiver eksterne moduler',
MODULES_UPDATED: 'Modules updated', // TODO translate MODULES_UPDATED: 'Modules updated', // TODO translate
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
MODULES_NONE: 'No external modules detected', // TODO translate MODULES_NONE: 'No external modules detected', // TODO translate
@@ -343,7 +342,8 @@ const no: Translation = {
AUTO_SCROLL: 'Auto Scroll', // TODO translate AUTO_SCROLL: 'Auto Scroll', // TODO translate
DASHBOARD: 'Dashboard', // TODO translate DASHBOARD: 'Dashboard', // TODO translate
NO_DATA: 'No data available', // TODO translate NO_DATA: 'No data available', // TODO translate
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module.' // TODO translate DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module', // TODO translate
DEVELOPER_MODE: 'Developer Mode' // TODO translate
}; };
export default no; export default no;

View File

@@ -26,7 +26,7 @@ const pl: BaseTranslation = {
ENTITIES: 'encj{{i|a|e|e|i}}', ENTITIES: 'encj{{i|a|e|e|i}}',
REFRESH: 'Odśwież', REFRESH: 'Odśwież',
EXPORT: 'Eksportuj', EXPORT: 'Eksportuj',
FAVORITES: "Ulubione", // TODO Translate FAVORITES: "Ulubione",
DEVICE_DETAILS: 'Szczegóły urządzenia', DEVICE_DETAILS: 'Szczegóły urządzenia',
ID_OF: 'ID {0}', ID_OF: 'ID {0}',
DEVICE: 'urządzenia', DEVICE: 'urządzenia',
@@ -115,7 +115,7 @@ const pl: BaseTranslation = {
READONLY: 'Tryb pracy "tylko do odczytu" (blokuje wszystkie komendy zapisu na magistralę EMS)', READONLY: 'Tryb pracy "tylko do odczytu" (blokuje wszystkie komendy zapisu na magistralę EMS)',
UNDERCLOCK_CPU: 'Obniż taktowanie CPU', UNDERCLOCK_CPU: 'Obniż taktowanie CPU',
REMOTE_TIMEOUT: 'Remote timeout', REMOTE_TIMEOUT: 'Remote timeout',
REMOTE_TIMEOUT_EN: 'Disable remote control on missing roomtemperature', REMOTE_TIMEOUT_EN: 'Disable remote control on missing room temperature', // TODO translate
HEATINGOFF: 'Uruchom kocioł z wymuszonym wyłączonym grzaniem', HEATINGOFF: 'Uruchom kocioł z wymuszonym wyłączonym grzaniem',
MIN_DURATION: 'Wait time', MIN_DURATION: 'Wait time',
ENABLE_SHOWER_TIMER: 'Aktywuj minutnik prysznica', ENABLE_SHOWER_TIMER: 'Aktywuj minutnik prysznica',
@@ -147,7 +147,7 @@ const pl: BaseTranslation = {
CUSTOMIZATIONS_HELP_2: 'oznacz jako ulubioną', CUSTOMIZATIONS_HELP_2: 'oznacz jako ulubioną',
CUSTOMIZATIONS_HELP_3: 'zablokuj akcje zapisu', CUSTOMIZATIONS_HELP_3: 'zablokuj akcje zapisu',
CUSTOMIZATIONS_HELP_4: 'wyklucz z MQTT i API', CUSTOMIZATIONS_HELP_4: 'wyklucz z MQTT i API',
CUSTOMIZATIONS_HELP_5: 'ukryć przed urządzeniami', // TODO translate CUSTOMIZATIONS_HELP_5: 'ukryć przed urządzeniami',
CUSTOMIZATIONS_HELP_6: 'usuń z pamięci', CUSTOMIZATIONS_HELP_6: 'usuń z pamięci',
SELECT_DEVICE: 'wybierz urządzenie', SELECT_DEVICE: 'wybierz urządzenie',
SET_ALL: 'Ustaw wszystko jako', SET_ALL: 'Ustaw wszystko jako',
@@ -155,11 +155,11 @@ const pl: BaseTranslation = {
NAME: '{{Nazwa|nazwa|}}', NAME: '{{Nazwa|nazwa|}}',
CUSTOMIZATIONS_RESET: 'Na pewno chcesz usunąć wszystkie personalizacje łącznie z ustawieniami dla czujników temperatury 1-Wire® i urządzeń podłączonych do EMS-ESP?', CUSTOMIZATIONS_RESET: 'Na pewno chcesz usunąć wszystkie personalizacje łącznie z ustawieniami dla czujników temperatury 1-Wire® i urządzeń podłączonych do EMS-ESP?',
SUPPORT_INFORMATION: '{{I|i|}}nformacj{{e|i|}} o systemie', SUPPORT_INFORMATION: '{{I|i|}}nformacj{{e|i|}} o systemie',
HELP_INFORMATION_1: 'Skorzystaj z wiki w internecie aby uzyskać instrukcje dotyczące konfiguracji EMS-ESP.', HELP_INFORMATION_1: 'Skorzystaj z wiki w internecie aby uzyskać instrukcje dotyczące konfiguracji EMS-ESP',
HELP_INFORMATION_2: 'Dołącz do naszego serwera Discord by komunikować się na żywo ze społecznością.', HELP_INFORMATION_2: 'Dołącz do naszego serwera Discord by komunikować się na żywo ze społecznością',
HELP_INFORMATION_3: 'Zaproponuj nową funkcjonalność lub zgłoś problem.', HELP_INFORMATION_3: 'Zaproponuj nową funkcjonalność lub zgłoś problem',
HELP_INFORMATION_4: 'Zgłaszając problem, nie zapomnij pobrać i dołączyć informacji o swoim systemie!', HELP_INFORMATION_4: 'Zgłaszając problem, nie zapomnij pobrać i dołączyć informacji o swoim systemie!',
HELP_INFORMATION_5: 'For help and questions please contact your installer.', // TODO translate HELP_INFORMATION_5: 'For help and questions please contact your installer', // TODO translate
UPLOAD: 'Wysyłanie', UPLOAD: 'Wysyłanie',
DOWNLOAD: '{{P|p||P}}obier{{anie|z||z}}', DOWNLOAD: '{{P|p||P}}obier{{anie|z||z}}',
INSTALL: 'Zainstalować {0}', INSTALL: 'Zainstalować {0}',
@@ -177,10 +177,9 @@ const pl: BaseTranslation = {
SYSTEM_FACTORY_TEXT_DIALOG: 'Na pewno chcesz przywrócić ustawienia fabryczne interfejsu EMS-ESP? ', SYSTEM_FACTORY_TEXT_DIALOG: 'Na pewno chcesz przywrócić ustawienia fabryczne interfejsu EMS-ESP? ',
STABLE: 'Stable', // TODO translate STABLE: 'Stable', // TODO translate
DEVELOPMENT: 'Testowe', DEVELOPMENT: 'Testowe',
RELEASE_NOTES: 'lista zmian',
EMS_ESP_VER: 'Wersja Firmware', EMS_ESP_VER: 'Wersja Firmware',
UPTIME: 'Czas działania systemu', UPTIME: 'Czas działania systemu',
FREE_MEMORY: 'Wolne Memory', // TODO translate FREE_MEMORY: 'Wolne Memory',
PSRAM: 'PSRAM (rozmiar / wolne)', PSRAM: 'PSRAM (rozmiar / wolne)',
FLASH: 'FLASH (rozmiar , taktowanie)', FLASH: 'FLASH (rozmiar , taktowanie)',
APPSIZE: 'Aplikacja (partycja: wykorzystane / wolne)', APPSIZE: 'Aplikacja (partycja: wykorzystane / wolne)',
@@ -287,14 +286,14 @@ const pl: BaseTranslation = {
STAY: 'Pozostań', STAY: 'Pozostań',
LEAVE: 'Opuść', LEAVE: 'Opuść',
SCHEDULER: 'Harmonogram', SCHEDULER: 'Harmonogram',
SCHEDULER_HELP_1: 'Zautomatyzuj wykonywanie komend, dodając poniżej harmonogram zdarzeń. Nadaj mu unikalną nazwę, aby móc go aktywować/dezaktywować przez API/MQTT.', SCHEDULER_HELP_1: 'Zautomatyzuj wykonywanie komend, dodając poniżej harmonogram zdarzeń. Nadaj mu unikalną nazwę, aby móc go aktywować/dezaktywować przez API/MQTT',
SCHEDULER_HELP_2: 'Wpisz 00:00 aby wykonywać jednorazowo przy starcie.', SCHEDULER_HELP_2: 'Wpisz 00:00 aby wykonywać jednorazowo przy starcie.',
SCHEDULE: '{{H|h|}}armonogram{{|u|}}', SCHEDULE: '{{H|h|}}armonogram{{|u|}}',
TIME: '{{Czas|Godzina|}}', TIME: '{{Czas|Godzina|}}',
TIMER: '{{m|M|}}inutnik', TIMER: '{{m|M|}}inutnik',
ONCHANGE: 'O zmianie', // TODO translate ONCHANGE: 'O zmianie',
CONDITION: 'Stan', // TODO translate CONDITION: 'Stan',
IMMEDIATE: 'Natychmiastowy', // TODO translate IMMEDIATE: 'Natychmiastowy',
SCHEDULE_UPDATED: 'Harmonogram został uaktualniony.', SCHEDULE_UPDATED: 'Harmonogram został uaktualniony.',
SCHEDULE_TIMER_1: 'przy starcie', SCHEDULE_TIMER_1: 'przy starcie',
SCHEDULE_TIMER_2: 'co minutę', SCHEDULE_TIMER_2: 'co minutę',
@@ -321,7 +320,7 @@ const pl: BaseTranslation = {
SECURITY_1: 'Dodawanie i usuwanie użytkowników', SECURITY_1: 'Dodawanie i usuwanie użytkowników',
DOWNLOAD_UPLOAD_1: 'Pobieranie/wysyłanie ustawień i firmware', DOWNLOAD_UPLOAD_1: 'Pobieranie/wysyłanie ustawień i firmware',
MODULES: 'Module', // TODO translate MODULES: 'Module', // TODO translate
MODULES_1: 'Aktywuj lub dezaktywuj moduły zewnętrzne', // TODO translate MODULES_1: 'Aktywuj lub dezaktywuj moduły zewnętrzne',
MODULES_UPDATED: 'Modules updated', // TODO translate MODULES_UPDATED: 'Modules updated', // TODO translate
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
MODULES_NONE: 'No external modules detected', // TODO translate MODULES_NONE: 'No external modules detected', // TODO translate
@@ -343,7 +342,8 @@ const pl: BaseTranslation = {
AUTO_SCROLL: 'Auto Scroll', // TODO translate AUTO_SCROLL: 'Auto Scroll', // TODO translate
DASHBOARD: 'Dashboard', // TODO translate DASHBOARD: 'Dashboard', // TODO translate
NO_DATA: 'No data available', // TODO translate NO_DATA: 'No data available', // TODO translate
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module.' // TODO translate DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module', // TODO translate
DEVELOPER_MODE: 'Developer Mode' // TODO translate
}; };
export default pl; export default pl;

View File

@@ -26,7 +26,7 @@ const sk: Translation = {
ENTITIES: 'entity', ENTITIES: 'entity',
REFRESH: 'Obnoviť', REFRESH: 'Obnoviť',
EXPORT: 'Export', EXPORT: 'Export',
FAVORITES: "Obľúbené", // TODO translate FAVORITES: "Obľúbené",
DEVICE_DETAILS: 'Detaily zariadenia', DEVICE_DETAILS: 'Detaily zariadenia',
ID_OF: '{0} ID', ID_OF: '{0} ID',
DEVICE: 'Zariadenie', DEVICE: 'Zariadenie',
@@ -115,7 +115,7 @@ const sk: Translation = {
READONLY: 'Povoliť režim len na čítanie (blokuje všetky odchádzajúce príkazy EMS Tx Write)', READONLY: 'Povoliť režim len na čítanie (blokuje všetky odchádzajúce príkazy EMS Tx Write)',
UNDERCLOCK_CPU: 'Podtaktovanie rýchlosti procesora', UNDERCLOCK_CPU: 'Podtaktovanie rýchlosti procesora',
REMOTE_TIMEOUT: 'Remote timeout', REMOTE_TIMEOUT: 'Remote timeout',
REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', REMOTE_TIMEOUT_EN: 'Disable remote on missing room temperature', // TODO translate
HEATINGOFF: 'Spustiť kotol s vynúteným vykurovaním', HEATINGOFF: 'Spustiť kotol s vynúteným vykurovaním',
MIN_DURATION: 'Wait time', MIN_DURATION: 'Wait time',
ENABLE_SHOWER_TIMER: 'Povoliť časovač sprchovania', ENABLE_SHOWER_TIMER: 'Povoliť časovač sprchovania',
@@ -147,7 +147,7 @@ const sk: Translation = {
CUSTOMIZATIONS_HELP_2: 'označiť ako obľúbené', CUSTOMIZATIONS_HELP_2: 'označiť ako obľúbené',
CUSTOMIZATIONS_HELP_3: 'zakázať akciu zápisu', CUSTOMIZATIONS_HELP_3: 'zakázať akciu zápisu',
CUSTOMIZATIONS_HELP_4: 'vylúčiť z MQTT a API', CUSTOMIZATIONS_HELP_4: 'vylúčiť z MQTT a API',
CUSTOMIZATIONS_HELP_5: 'skryť zo Zariadení', // TODO translate CUSTOMIZATIONS_HELP_5: 'skryť zo Zariadení',
CUSTOMIZATIONS_HELP_6: 'odstrániť z pamäte', CUSTOMIZATIONS_HELP_6: 'odstrániť z pamäte',
SELECT_DEVICE: 'Zvoliť zariadenie', SELECT_DEVICE: 'Zvoliť zariadenie',
SET_ALL: 'nastaviť všetko', SET_ALL: 'nastaviť všetko',
@@ -159,7 +159,7 @@ const sk: Translation = {
HELP_INFORMATION_2: 'Pre živý komunitný chat sa pripojte na náš Discord server', HELP_INFORMATION_2: 'Pre živý komunitný chat sa pripojte na náš Discord server',
HELP_INFORMATION_3: 'Ak chcete požiadať o funkciu alebo nahlásiť chybu', HELP_INFORMATION_3: 'Ak chcete požiadať o funkciu alebo nahlásiť chybu',
HELP_INFORMATION_4: 'nezabudnite si stiahnuť a pripojiť informácie o vašom systéme, aby ste mohli rýchlejšie reagovať pri nahlasovaní problému', HELP_INFORMATION_4: 'nezabudnite si stiahnuť a pripojiť informácie o vašom systéme, aby ste mohli rýchlejšie reagovať pri nahlasovaní problému',
HELP_INFORMATION_5: 'Pre pomoc a otázky, kontaktujte svojho inštalatéra.', HELP_INFORMATION_5: 'Pre pomoc a otázky, kontaktujte svojho inštalatéra',
UPLOAD: 'Nahrať', UPLOAD: 'Nahrať',
DOWNLOAD: '{{S|s|s}}tiahnuť', DOWNLOAD: '{{S|s|s}}tiahnuť',
INSTALL: 'Inštalovať {0}', INSTALL: 'Inštalovať {0}',
@@ -177,7 +177,6 @@ const sk: Translation = {
SYSTEM_FACTORY_TEXT_DIALOG: 'Naozaj chcete resetovať EMS-ESP na predvolené výrobné nastavenia?', SYSTEM_FACTORY_TEXT_DIALOG: 'Naozaj chcete resetovať EMS-ESP na predvolené výrobné nastavenia?',
STABLE: 'Stabilná', STABLE: 'Stabilná',
DEVELOPMENT: 'Vývojárska', DEVELOPMENT: 'Vývojárska',
RELEASE_NOTES: 'poznámky k verzii',
EMS_ESP_VER: 'Firmware verzia', EMS_ESP_VER: 'Firmware verzia',
UPTIME: 'Beh systému', UPTIME: 'Beh systému',
FREE_MEMORY: 'Voľné Memory', FREE_MEMORY: 'Voľné Memory',
@@ -287,7 +286,7 @@ const sk: Translation = {
STAY: 'Zostať', STAY: 'Zostať',
LEAVE: 'Opustiť', LEAVE: 'Opustiť',
SCHEDULER: 'Plánovač', SCHEDULER: 'Plánovač',
SCHEDULER_HELP_1: 'Automatizujte príkazy pridaním naplánovaných udalostí nižšie. Nastavte jedinečné meno na aktiváciu/deaktiváciu cez API/MQTT.', SCHEDULER_HELP_1: 'Automatizujte príkazy pridaním naplánovaných udalostí nižšie. Nastavte jedinečné meno na aktiváciu/deaktiváciu cez API/MQTT',
SCHEDULER_HELP_2: 'Použite 00:00 na jednorazové spustenie pri štarte', SCHEDULER_HELP_2: 'Použite 00:00 na jednorazové spustenie pri štarte',
SCHEDULE: 'Plánovač', SCHEDULE: 'Plánovač',
TIME: 'Čas', TIME: 'Čas',
@@ -343,7 +342,8 @@ const sk: Translation = {
AUTO_SCROLL: 'Automatické rolovanie', AUTO_SCROLL: 'Automatické rolovanie',
DASHBOARD: 'Panel', DASHBOARD: 'Panel',
NO_DATA: 'Nie sú k dispozícii žiadne údaje', NO_DATA: 'Nie sú k dispozícii žiadne údaje',
DASHBOARD_1: 'Prispôsobte si svoj informačný panel tak, že označíte entity EMS ako Obľúbené pomocou modulu Prispôsobenia.' DASHBOARD_1: 'Prispôsobte si svoj informačný panel tak, že označíte entity EMS ako Obľúbené pomocou modulu Prispôsobenia.',
DEVELOPER_MODE: 'Developer Mode' // TODO translate
}; };
export default sk; export default sk;

View File

@@ -26,7 +26,7 @@ const sv: Translation = {
ENTITIES: 'entiteter', ENTITIES: 'entiteter',
REFRESH: 'Uppdatera', REFRESH: 'Uppdatera',
EXPORT: 'Exportera', EXPORT: 'Exportera',
FAVORITES: "Favoriter", // TODO translate FAVORITES: "Favoriter",
DEVICE_DETAILS: 'Enhetsdetaljer', DEVICE_DETAILS: 'Enhetsdetaljer',
ID_OF: '{0}-ID', ID_OF: '{0}-ID',
DEVICE: 'Enhets', DEVICE: 'Enhets',
@@ -115,7 +115,7 @@ const sv: Translation = {
READONLY: 'Aktivera read-only (blockerar alla utgående skrivkommandon mot EMS-bussen)', READONLY: 'Aktivera read-only (blockerar alla utgående skrivkommandon mot EMS-bussen)',
UNDERCLOCK_CPU: 'Nedklocka Processorhastighet', UNDERCLOCK_CPU: 'Nedklocka Processorhastighet',
REMOTE_TIMEOUT: 'Remote timeout', REMOTE_TIMEOUT: 'Remote timeout',
REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', REMOTE_TIMEOUT_EN: 'Disable remote on missing room temperature', // TODO translate
HEATINGOFF: 'Start boiler with forced heating off', // TODO translate HEATINGOFF: 'Start boiler with forced heating off', // TODO translate
MIN_DURATION: 'Wait time', MIN_DURATION: 'Wait time',
ENABLE_SHOWER_TIMER: 'Aktivera Dusch-timer', ENABLE_SHOWER_TIMER: 'Aktivera Dusch-timer',
@@ -147,8 +147,8 @@ const sv: Translation = {
CUSTOMIZATIONS_HELP_2: 'Favorit', CUSTOMIZATIONS_HELP_2: 'Favorit',
CUSTOMIZATIONS_HELP_3: 'Inaktivera skrivningar', CUSTOMIZATIONS_HELP_3: 'Inaktivera skrivningar',
CUSTOMIZATIONS_HELP_4: 'Exkludera från MQTT & API', CUSTOMIZATIONS_HELP_4: 'Exkludera från MQTT & API',
CUSTOMIZATIONS_HELP_5: 'dölj från enheter', // TODO translate CUSTOMIZATIONS_HELP_5: 'dölj från enheter',
CUSTOMIZATIONS_HELP_6: 'remove from memory', // TODO translate CUSTOMIZATIONS_HELP_6: 'remove from memory',
SELECT_DEVICE: 'Välj en enhet', SELECT_DEVICE: 'Välj en enhet',
SET_ALL: 'ställ in alla', SET_ALL: 'ställ in alla',
OPTIONS: 'Alternativ', OPTIONS: 'Alternativ',
@@ -159,7 +159,7 @@ const sv: Translation = {
HELP_INFORMATION_2: 'För community-support besök vår Discord-server', HELP_INFORMATION_2: 'För community-support besök vår Discord-server',
HELP_INFORMATION_3: 'Önska en ny funktion eller rapportera en bugg', HELP_INFORMATION_3: 'Önska en ny funktion eller rapportera en bugg',
HELP_INFORMATION_4: 'Bifoga din systeminformation för snabbare hantering när du rapporterar ett problem', HELP_INFORMATION_4: 'Bifoga din systeminformation för snabbare hantering när du rapporterar ett problem',
HELP_INFORMATION_5: 'For help and questions please contact your installer.', // TODO translate HELP_INFORMATION_5: 'For help and questions please contact your installer', // TODO translate
UPLOAD: 'Uppladdning', UPLOAD: 'Uppladdning',
DOWNLOAD: '{{N|n|n}}edladdning', DOWNLOAD: '{{N|n|n}}edladdning',
INSTALL: 'Installera {0}', INSTALL: 'Installera {0}',
@@ -177,7 +177,6 @@ const sv: Translation = {
SYSTEM_FACTORY_TEXT_DIALOG: 'Är du säker att du vill fabriksåterställa enheten?', SYSTEM_FACTORY_TEXT_DIALOG: 'Är du säker att du vill fabriksåterställa enheten?',
STABLE: 'Stable', // TODO translate STABLE: 'Stable', // TODO translate
DEVELOPMENT: 'Utveckling', DEVELOPMENT: 'Utveckling',
RELEASE_NOTES: 'release-logg',
EMS_ESP_VER: 'Firmware Version', // TODO translate EMS_ESP_VER: 'Firmware Version', // TODO translate
UPTIME: 'Systemets Upptid', UPTIME: 'Systemets Upptid',
FREE_MEMORY: 'Ledigt Memory', FREE_MEMORY: 'Ledigt Memory',
@@ -261,7 +260,7 @@ const sv: Translation = {
SCAN_AGAIN: 'Sök igen', SCAN_AGAIN: 'Sök igen',
NETWORK_SCANNER: 'Hittade nätverk', NETWORK_SCANNER: 'Hittade nätverk',
NETWORK_NO_WIFI: 'Inga WiFi-nätverk hittades', NETWORK_NO_WIFI: 'Inga WiFi-nätverk hittades',
NETWORK_BLANK_SSID: 'lämna blankt för att inaktivera WiFi', // and enable ETH // TODO translate NETWORK_BLANK_SSID: 'lämna blankt för att inaktivera WiFi',
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
TX_POWER: 'Tx Effekt', TX_POWER: 'Tx Effekt',
HOSTNAME: 'Värdnamn', HOSTNAME: 'Värdnamn',
@@ -287,14 +286,14 @@ const sv: Translation = {
STAY: 'Stay', // TODO translate STAY: 'Stay', // TODO translate
LEAVE: 'Leave', // TODO translate LEAVE: 'Leave', // TODO translate
SCHEDULER: 'Scheduler', // TODO translate SCHEDULER: 'Scheduler', // TODO translate
SCHEDULER_HELP_1: 'Automate commands by adding scheduled events below. Set a unique Name to enable/disable activation via API/MQTT.', // TODO translate SCHEDULER_HELP_1: 'Automate commands by adding scheduled events below. Set a unique Name to enable/disable activation via API/MQTT', // TODO translate
SCHEDULER_HELP_2: 'Use 00:00 to trigger once on start-up', // TODO translate SCHEDULER_HELP_2: 'Use 00:00 to trigger once on start-up', // TODO translate
SCHEDULE: 'Schedule', // TODO translate SCHEDULE: 'Schedule', // TODO translate
TIME: 'Time', // TODO translate TIME: 'Time', // TODO translate
TIMER: 'Timer', // TODO translate TIMER: 'Timer', // TODO translate
ONCHANGE: 'På förändring', // TODO translate ONCHANGE: 'På förändring',
CONDITION: 'Skick', // TODO translate CONDITION: 'Skick',
IMMEDIATE: 'Omedelbar', // TODO translate IMMEDIATE: 'Omedelbar',
SCHEDULE_UPDATED: 'Schedule updated', // TODO translate SCHEDULE_UPDATED: 'Schedule updated', // TODO translate
SCHEDULE_TIMER_1: 'on startup', // TODO translate SCHEDULE_TIMER_1: 'on startup', // TODO translate
SCHEDULE_TIMER_2: 'every minute', // TODO translate SCHEDULE_TIMER_2: 'every minute', // TODO translate
@@ -321,7 +320,7 @@ const sv: Translation = {
SECURITY_1: 'Add or remove users', // TODO translate SECURITY_1: 'Add or remove users', // TODO translate
DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware', // TODO translate DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware', // TODO translate
MODULES: 'Module', // TODO translate MODULES: 'Module', // TODO translate
MODULES_1: 'Aktivera eller avaktivera externa moduler', // TODO translate MODULES_1: 'Aktivera eller avaktivera externa moduler',
MODULES_UPDATED: 'Modules updated', // TODO translate MODULES_UPDATED: 'Modules updated', // TODO translate
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
MODULES_NONE: 'No external modules detected', // TODO translate MODULES_NONE: 'No external modules detected', // TODO translate
@@ -343,7 +342,8 @@ const sv: Translation = {
AUTO_SCROLL: 'Auto Scroll', // TODO translate AUTO_SCROLL: 'Auto Scroll', // TODO translate
DASHBOARD: 'Dashboard', // TODO translate DASHBOARD: 'Dashboard', // TODO translate
NO_DATA: 'No data available', // TODO translate NO_DATA: 'No data available', // TODO translate
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module.' // TODO translate DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module', // TODO translate
DEVELOPER_MODE: 'Developer Mode' // TODO translate
}; };
export default sv; export default sv;

View File

@@ -26,7 +26,7 @@ const tr: Translation = {
ENTITIES: 'varlıklar', ENTITIES: 'varlıklar',
REFRESH: 'Yenile', REFRESH: 'Yenile',
EXPORT: 'Dışarı al', EXPORT: 'Dışarı al',
FAVORITES: "Favoriler", // TODO translate FAVORITES: "Favoriler",
DEVICE_DETAILS: 'Cihaz Ayrıntıları', DEVICE_DETAILS: 'Cihaz Ayrıntıları',
ID_OF: 'Kimlik {0}', ID_OF: 'Kimlik {0}',
DEVICE: 'Cihaz', DEVICE: 'Cihaz',
@@ -115,7 +115,7 @@ const tr: Translation = {
READONLY: 'Salt okunur modu devreye al (bütün giden EMS Tx Yazma komutlarını engeller)', READONLY: 'Salt okunur modu devreye al (bütün giden EMS Tx Yazma komutlarını engeller)',
UNDERCLOCK_CPU: 'İşlemci hızını düşür', UNDERCLOCK_CPU: 'İşlemci hızını düşür',
REMOTE_TIMEOUT: 'Remote timeout', REMOTE_TIMEOUT: 'Remote timeout',
REMOTE_TIMEOUT_EN: 'Disable remote on missing roomtemperature', REMOTE_TIMEOUT_EN: 'Disable remote on missing room temperature', // TODO translate
HEATINGOFF: 'Start boiler with forced heating off', // TODO translate HEATINGOFF: 'Start boiler with forced heating off', // TODO translate
MIN_DURATION: 'Wait time', MIN_DURATION: 'Wait time',
ENABLE_SHOWER_TIMER: 'Duş Sayacını Devreye Al', ENABLE_SHOWER_TIMER: 'Duş Sayacını Devreye Al',
@@ -147,7 +147,7 @@ const tr: Translation = {
CUSTOMIZATIONS_HELP_2: 'favori olarak işaretle', CUSTOMIZATIONS_HELP_2: 'favori olarak işaretle',
CUSTOMIZATIONS_HELP_3: 'yazma işlemini devre dışı bırak', CUSTOMIZATIONS_HELP_3: 'yazma işlemini devre dışı bırak',
CUSTOMIZATIONS_HELP_4: 'MQTT ve APInin dışında bırak', CUSTOMIZATIONS_HELP_4: 'MQTT ve APInin dışında bırak',
CUSTOMIZATIONS_HELP_5: 'Cihazlardan gizle', // TODO translate CUSTOMIZATIONS_HELP_5: 'Cihazlardan gizle',
CUSTOMIZATIONS_HELP_6: 'remove from memory', CUSTOMIZATIONS_HELP_6: 'remove from memory',
SELECT_DEVICE: 'Bir cihaz seç', SELECT_DEVICE: 'Bir cihaz seç',
SET_ALL: 'hepsini ayarla', SET_ALL: 'hepsini ayarla',
@@ -159,7 +159,7 @@ const tr: Translation = {
HELP_INFORMATION_2: 'Canlı topluluk sohbeti için Discord sunucumuza katılın', HELP_INFORMATION_2: 'Canlı topluluk sohbeti için Discord sunucumuza katılın',
HELP_INFORMATION_3: 'Yeni bir özellik talep etmek yada hata bildirmek için', HELP_INFORMATION_3: 'Yeni bir özellik talep etmek yada hata bildirmek için',
HELP_INFORMATION_4: 'Bir sorun bildirirken daha hızlı bir dönüş için sistem bilginizi indirip eklemeyi unutmayın', HELP_INFORMATION_4: 'Bir sorun bildirirken daha hızlı bir dönüş için sistem bilginizi indirip eklemeyi unutmayın',
HELP_INFORMATION_5: 'For help and questions please contact your installer.', // TODO translate HELP_INFORMATION_5: 'For help and questions please contact your installer', // TODO translate
UPLOAD: 'Yükleme', UPLOAD: 'Yükleme',
DOWNLOAD: '{{İ|i|i}}İndirme', DOWNLOAD: '{{İ|i|i}}İndirme',
INSTALL: 'Düzenlemek {0}', INSTALL: 'Düzenlemek {0}',
@@ -177,7 +177,6 @@ const tr: Translation = {
SYSTEM_FACTORY_TEXT_DIALOG: 'Cihazı fabrika ayarlarına döndürmek istediğinize emin misiniz?', SYSTEM_FACTORY_TEXT_DIALOG: 'Cihazı fabrika ayarlarına döndürmek istediğinize emin misiniz?',
STABLE: 'Stable', // TODO translate STABLE: 'Stable', // TODO translate
DEVELOPMENT: 'Geliştirme', DEVELOPMENT: 'Geliştirme',
RELEASE_NOTES: 'yayınlanma notları',
EMS_ESP_VER: 'Firmware Sürümü', EMS_ESP_VER: 'Firmware Sürümü',
UPTIME: 'Sistem Çalışma Süresi', UPTIME: 'Sistem Çalışma Süresi',
FREE_MEMORY: 'Yığın Memory', FREE_MEMORY: 'Yığın Memory',
@@ -261,7 +260,7 @@ const tr: Translation = {
SCAN_AGAIN: 'Tekrar tara', SCAN_AGAIN: 'Tekrar tara',
NETWORK_SCANNER: 'Ağ Tarayıcısı', NETWORK_SCANNER: 'Ağ Tarayıcısı',
NETWORK_NO_WIFI: 'Hiçbir Kablosuz Ağ bulunamadı', NETWORK_NO_WIFI: 'Hiçbir Kablosuz Ağ bulunamadı',
NETWORK_BLANK_SSID: 'Kablosuz ağı devre dışı bırakmak için boş bırakın', // TODO translate NETWORK_BLANK_SSID: 'Kablosuz ağı devre dışı bırakmak için boş bırakın',
NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate NETWORK_BLANK_BSSID: 'leave blank to use only SSID', // TODO translate
TX_POWER: 'Aktarım gücü', TX_POWER: 'Aktarım gücü',
HOSTNAME: 'Ana Makine Adı', HOSTNAME: 'Ana Makine Adı',
@@ -287,12 +286,12 @@ const tr: Translation = {
STAY: 'Stay', // TODO translate STAY: 'Stay', // TODO translate
LEAVE: 'Leave', // TODO translate LEAVE: 'Leave', // TODO translate
SCHEDULER: 'Scheduler', // TODO translate SCHEDULER: 'Scheduler', // TODO translate
SCHEDULER_HELP_1: 'Automate commands by adding scheduled events below. Set a unique Name to enable/disable activation via API/MQTT.', // TODO translate SCHEDULER_HELP_1: 'Automate commands by adding scheduled events below. Set a unique Name to enable/disable activation via API/MQTT', // TODO translate
SCHEDULER_HELP_2: 'Use 00:00 to trigger once on start-up', // TODO translate SCHEDULER_HELP_2: 'Use 00:00 to trigger once on start-up', // TODO translate
SCHEDULE: 'Schedule', // TODO translate SCHEDULE: 'Schedule', // TODO translate
TIME: 'Time', // TODO translate TIME: 'Time', // TODO translate
TIMER: 'Timer', // TODO translate TIMER: 'Timer', // TODO translate
ONCHANGE: 'Değişimde', // TODO translate ONCHANGE: 'Değişimde',
CONDITION: 'Durum', // TODO translate CONDITION: 'Durum', // TODO translate
IMMEDIATE: 'hemen', // TODO translate IMMEDIATE: 'hemen', // TODO translate
SCHEDULE_UPDATED: 'Schedule updated', // TODO translate SCHEDULE_UPDATED: 'Schedule updated', // TODO translate
@@ -321,7 +320,7 @@ const tr: Translation = {
SECURITY_1: 'Add or remove users', // TODO translate SECURITY_1: 'Add or remove users', // TODO translate
DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware', // TODO translate DOWNLOAD_UPLOAD_1: 'Download and Upload Settings and Firmware', // TODO translate
MODULES: 'Module', // TODO translate MODULES: 'Module', // TODO translate
MODULES_1: 'Harici modülleri etkinleştirin veya devre dışı bırakın', // TODO translate MODULES_1: 'Harici modülleri etkinleştirin veya devre dışı bırakın',
MODULES_UPDATED: 'Modules updated', // TODO translate MODULES_UPDATED: 'Modules updated', // TODO translate
MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate MODULES_DESCRIPTION: 'Click on the Module to activate or de-activate EMS-ESP library modules', // TODO translate
MODULES_NONE: 'No external modules detected', // TODO translate MODULES_NONE: 'No external modules detected', // TODO translate
@@ -343,7 +342,8 @@ const tr: Translation = {
AUTO_SCROLL: 'Auto Scroll', // TODO translate AUTO_SCROLL: 'Auto Scroll', // TODO translate
DASHBOARD: 'Dashboard', // TODO translate DASHBOARD: 'Dashboard', // TODO translate
NO_DATA: 'No data available', // TODO translate NO_DATA: 'No data available', // TODO translate
DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module.' // TODO translate DASHBOARD_1: 'Customize your dashboard by marking EMS entities as Favorite using the Customizations module', // TODO translate
DEVELOPER_MODE: 'Developer Mode' // TODO translate
}; };
export default tr; export default tr;

View File

@@ -67,4 +67,5 @@ export interface LogSettings {
max_messages: number; max_messages: number;
compact: boolean; compact: boolean;
psram: boolean; psram: boolean;
developer_mode: boolean;
} }

View File

@@ -43,13 +43,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/code-frame@npm:^7.25.7": "@babel/code-frame@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/code-frame@npm:7.25.7" resolution: "@babel/code-frame@npm:7.25.9"
dependencies: dependencies:
"@babel/highlight": "npm:^7.25.7" "@babel/highlight": "npm:^7.25.9"
picocolors: "npm:^1.0.0" picocolors: "npm:^1.0.0"
checksum: 10c0/14825c298bdec914caf3d24d1383b6d4cd6b030714686004992f4fc251831ecf432236652896f99d5d341f17170ae9a07b58d8d7b15aa0df8cfa1c5a7d5474bc checksum: 10c0/88562eba0eeb5960b7004e108790aa00183d90cbbe70ce10dad01c2c48141d2ef54d6dcd0c678cc1e456de770ffeb68e28559f4d222c01a110c79aea8733074b
languageName: node languageName: node
linkType: hard linkType: hard
@@ -60,10 +60,10 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/compat-data@npm:^7.25.7": "@babel/compat-data@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/compat-data@npm:7.25.7" resolution: "@babel/compat-data@npm:7.25.9"
checksum: 10c0/e5cc915abdd18d021236474a96606b2d4a915c4fb620c1ad776b8a08d91111e788cb3b7e9bad43593d4e0bfa4f06894357bcb0984102de1861b9e7322b6bc9f8 checksum: 10c0/8d9fc2074311ce61aaf5bccf740a808644d19d4859caf5fa46d8a7186a1ee0b0d8cbbc23f9371f8b397e84a885bdeab58d5f22d6799ddde55973252aac351a27
languageName: node languageName: node
linkType: hard linkType: hard
@@ -90,26 +90,26 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/core@npm:^7.25.8": "@babel/core@npm:^7.25.9":
version: 7.25.8 version: 7.25.9
resolution: "@babel/core@npm:7.25.8" resolution: "@babel/core@npm:7.25.9"
dependencies: dependencies:
"@ampproject/remapping": "npm:^2.2.0" "@ampproject/remapping": "npm:^2.2.0"
"@babel/code-frame": "npm:^7.25.7" "@babel/code-frame": "npm:^7.25.9"
"@babel/generator": "npm:^7.25.7" "@babel/generator": "npm:^7.25.9"
"@babel/helper-compilation-targets": "npm:^7.25.7" "@babel/helper-compilation-targets": "npm:^7.25.9"
"@babel/helper-module-transforms": "npm:^7.25.7" "@babel/helper-module-transforms": "npm:^7.25.9"
"@babel/helpers": "npm:^7.25.7" "@babel/helpers": "npm:^7.25.9"
"@babel/parser": "npm:^7.25.8" "@babel/parser": "npm:^7.25.9"
"@babel/template": "npm:^7.25.7" "@babel/template": "npm:^7.25.9"
"@babel/traverse": "npm:^7.25.7" "@babel/traverse": "npm:^7.25.9"
"@babel/types": "npm:^7.25.8" "@babel/types": "npm:^7.25.9"
convert-source-map: "npm:^2.0.0" convert-source-map: "npm:^2.0.0"
debug: "npm:^4.1.0" debug: "npm:^4.1.0"
gensync: "npm:^1.0.0-beta.2" gensync: "npm:^1.0.0-beta.2"
json5: "npm:^2.2.3" json5: "npm:^2.2.3"
semver: "npm:^6.3.1" semver: "npm:^6.3.1"
checksum: 10c0/8411ea506e6f7c8a39ab5c1524b00589fa3b087edb47389708f7fe07170929192171734666e3ea10b95a951643a531a6d09eedfe071572c9ea28516646265086 checksum: 10c0/40d3064ebe906f65ed4153a0f4d75c679a19e4d71e425035b7bbe2d292a9167274f1a0d908d4d6c8f484fcddeb10bd91e0c7878fdb3dfad1bb00f6a319ce431d
languageName: node languageName: node
linkType: hard linkType: hard
@@ -136,15 +136,15 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/generator@npm:^7.25.7": "@babel/generator@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/generator@npm:7.25.7" resolution: "@babel/generator@npm:7.25.9"
dependencies: dependencies:
"@babel/types": "npm:^7.25.7" "@babel/types": "npm:^7.25.9"
"@jridgewell/gen-mapping": "npm:^0.3.5" "@jridgewell/gen-mapping": "npm:^0.3.5"
"@jridgewell/trace-mapping": "npm:^0.3.25" "@jridgewell/trace-mapping": "npm:^0.3.25"
jsesc: "npm:^3.0.2" jsesc: "npm:^3.0.2"
checksum: 10c0/c03a26c79864d60d04ce36b649c3fa0d6fd7b2bf6a22e22854a0457aa09206508392dd73ee40e7bc8d50b3602f9ff068afa47770cda091d332e7db1ca382ee96 checksum: 10c0/fca49a1440ac550bb835a73c0e8314849cd493a468a5431ca7f9dbb3d3443e3a1a6dcba2426752e8a97cc2feed4a3b7a0c639e1c45871c4a9dd0c994f08dd25a
languageName: node languageName: node
linkType: hard linkType: hard
@@ -170,16 +170,16 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/helper-compilation-targets@npm:^7.25.7": "@babel/helper-compilation-targets@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/helper-compilation-targets@npm:7.25.7" resolution: "@babel/helper-compilation-targets@npm:7.25.9"
dependencies: dependencies:
"@babel/compat-data": "npm:^7.25.7" "@babel/compat-data": "npm:^7.25.9"
"@babel/helper-validator-option": "npm:^7.25.7" "@babel/helper-validator-option": "npm:^7.25.9"
browserslist: "npm:^4.24.0" browserslist: "npm:^4.24.0"
lru-cache: "npm:^5.1.1" lru-cache: "npm:^5.1.1"
semver: "npm:^6.3.1" semver: "npm:^6.3.1"
checksum: 10c0/705be7e5274a3fdade68e3e2cf42e2b600316ab52794e13b91299a16f16c926f15886b6e9d6df20eb943ccc1cdba5a363d4766f8d01e47b8e6f4e01175f5e66c checksum: 10c0/a6b26a1e4222e69ef8e62ee19374308f060b007828bc11c65025ecc9e814aba21ff2175d6d3f8bf53c863edd728ee8f94ba7870f8f90a37d39552ad9933a8aaa
languageName: node languageName: node
linkType: hard linkType: hard
@@ -221,13 +221,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/helper-module-imports@npm:^7.25.7": "@babel/helper-module-imports@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/helper-module-imports@npm:7.25.7" resolution: "@babel/helper-module-imports@npm:7.25.9"
dependencies: dependencies:
"@babel/traverse": "npm:^7.25.7" "@babel/traverse": "npm:^7.25.9"
"@babel/types": "npm:^7.25.7" "@babel/types": "npm:^7.25.9"
checksum: 10c0/0fd0c3673835e5bf75558e184bcadc47c1f6dd2fe2016d53ebe1e5a6ae931a44e093015c2f9a6651c1a89f25c76d9246710c2b0b460b95ee069c464f2837fa2c checksum: 10c0/078d3c2b45d1f97ffe6bb47f61961be4785d2342a4156d8b42c92ee4e1b7b9e365655dd6cb25329e8fe1a675c91eeac7e3d04f0c518b67e417e29d6e27b6aa70
languageName: node languageName: node
linkType: hard linkType: hard
@@ -245,17 +245,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/helper-module-transforms@npm:^7.25.7": "@babel/helper-module-transforms@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/helper-module-transforms@npm:7.25.7" resolution: "@babel/helper-module-transforms@npm:7.25.9"
dependencies: dependencies:
"@babel/helper-module-imports": "npm:^7.25.7" "@babel/helper-module-imports": "npm:^7.25.9"
"@babel/helper-simple-access": "npm:^7.25.7" "@babel/helper-simple-access": "npm:^7.25.9"
"@babel/helper-validator-identifier": "npm:^7.25.7" "@babel/helper-validator-identifier": "npm:^7.25.9"
"@babel/traverse": "npm:^7.25.7" "@babel/traverse": "npm:^7.25.9"
peerDependencies: peerDependencies:
"@babel/core": ^7.0.0 "@babel/core": ^7.0.0
checksum: 10c0/f37fa7d1d4df21690535b278468cbd5faf0133a3080f282000cfa4f3ffc9462a1458f866b04b6a2f2d1eec4691236cba9a867da61270dab3ab19846e62f05090 checksum: 10c0/cd005e7585806845d79c5c0ca9e8926f186b430b0a558dad08a3611365eaad3ac587672b0d903530117dec454f48b6bdc3d164b19ea1b71ca1b4eb3be7b452ef
languageName: node languageName: node
linkType: hard linkType: hard
@@ -276,13 +276,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/helper-simple-access@npm:^7.25.7": "@babel/helper-simple-access@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/helper-simple-access@npm:7.25.7" resolution: "@babel/helper-simple-access@npm:7.25.9"
dependencies: dependencies:
"@babel/traverse": "npm:^7.25.7" "@babel/traverse": "npm:^7.25.9"
"@babel/types": "npm:^7.25.7" "@babel/types": "npm:^7.25.9"
checksum: 10c0/eed1b499bfb4f613c18debd61517e3de77b6da2727ca025aa05ac81599e0269f1dddb5237db04e8bb598115d015874752e0a7f11ff38672d74a4976097417059 checksum: 10c0/3f1bcdb88ee3883ccf86959869a867f6bbf8c4737cd44fb9f799c38e54f67474590bc66802500ae9fe18161792875b2cfb7ec15673f48ed6c8663f6d09686ca8
languageName: node languageName: node
linkType: hard linkType: hard
@@ -302,10 +302,10 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/helper-string-parser@npm:^7.25.7": "@babel/helper-string-parser@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/helper-string-parser@npm:7.25.7" resolution: "@babel/helper-string-parser@npm:7.25.9"
checksum: 10c0/73ef2ceb81f8294678a0afe8ab0103729c0370cac2e830e0d5128b03be5f6a2635838af31d391d763e3c5a4460ed96f42fd7c9b552130670d525be665913bc4c checksum: 10c0/7244b45d8e65f6b4338a6a68a8556f2cb161b782343e97281a5f2b9b93e420cad0d9f5773a59d79f61d0c448913d06f6a2358a87f2e203cf112e3c5b53522ee6
languageName: node languageName: node
linkType: hard linkType: hard
@@ -316,10 +316,10 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/helper-validator-identifier@npm:^7.25.7": "@babel/helper-validator-identifier@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/helper-validator-identifier@npm:7.25.7" resolution: "@babel/helper-validator-identifier@npm:7.25.9"
checksum: 10c0/07438e5bf01ab2882a15027fdf39ac3b0ba1b251774a5130917907014684e2f70fef8fd620137ca062c4c4eedc388508d2ea7a3a7d9936a32785f4fe116c68c0 checksum: 10c0/4fc6f830177b7b7e887ad3277ddb3b91d81e6c4a24151540d9d1023e8dc6b1c0505f0f0628ae653601eb4388a8db45c1c14b2c07a9173837aef7e4116456259d
languageName: node languageName: node
linkType: hard linkType: hard
@@ -330,10 +330,10 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/helper-validator-option@npm:^7.25.7": "@babel/helper-validator-option@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/helper-validator-option@npm:7.25.7" resolution: "@babel/helper-validator-option@npm:7.25.9"
checksum: 10c0/12ed418c8e3ed9ed44c8c80d823f4e42d399b5eb2e423adccb975e31a31a008cd3b5d8eab688b31f740caff4a1bb28fe06ea2fa7d635aee34cc0ad6995d50f0a checksum: 10c0/27fb195d14c7dcb07f14e58fe77c44eea19a6a40a74472ec05c441478fa0bb49fa1c32b2d64be7a38870ee48ef6601bdebe98d512f0253aea0b39756c4014f3e
languageName: node languageName: node
linkType: hard linkType: hard
@@ -347,13 +347,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/helpers@npm:^7.25.7": "@babel/helpers@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/helpers@npm:7.25.7" resolution: "@babel/helpers@npm:7.25.9"
dependencies: dependencies:
"@babel/template": "npm:^7.25.7" "@babel/template": "npm:^7.25.9"
"@babel/types": "npm:^7.25.7" "@babel/types": "npm:^7.25.9"
checksum: 10c0/3b3ae9e373bd785414195ef8f59976a69d5a6ebe0ef2165fdcc5165e5c3ee09e0fcee94bb457df2ddb8c0532e4146d0a9b7a96b3497399a4bff4ffe196b30228 checksum: 10c0/4354fbf050291937d0f127f6f927a0c471b604524e0767516fefb91dc36427f25904dd0d2b2b3bbc66bce1894c680cc37eac9ab46970d70f24bf3e53375612de
languageName: node languageName: node
linkType: hard linkType: hard
@@ -369,15 +369,15 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/highlight@npm:^7.25.7": "@babel/highlight@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/highlight@npm:7.25.7" resolution: "@babel/highlight@npm:7.25.9"
dependencies: dependencies:
"@babel/helper-validator-identifier": "npm:^7.25.7" "@babel/helper-validator-identifier": "npm:^7.25.9"
chalk: "npm:^2.4.2" chalk: "npm:^2.4.2"
js-tokens: "npm:^4.0.0" js-tokens: "npm:^4.0.0"
picocolors: "npm:^1.0.0" picocolors: "npm:^1.0.0"
checksum: 10c0/1f5894fdb0a0af6101fb2822369b2eeeae32cbeae2ef73ff73fc6a0a4a20471565cd9cfa589f54ed69df66adeca7c57266031ca9134b7bd244d023a488d419aa checksum: 10c0/ae0ed93c151b85a07df42936117fa593ce91563a22dfc8944a90ae7088c9679645c33e00dcd20b081c1979665d65f986241172dae1fc9e5922692fc3ff685a49
languageName: node languageName: node
linkType: hard linkType: hard
@@ -392,25 +392,14 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/parser@npm:^7.25.7": "@babel/parser@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/parser@npm:7.25.7" resolution: "@babel/parser@npm:7.25.9"
dependencies: dependencies:
"@babel/types": "npm:^7.25.7" "@babel/types": "npm:^7.25.9"
bin: bin:
parser: ./bin/babel-parser.js parser: ./bin/babel-parser.js
checksum: 10c0/b771469bb6b636c18a8d642b9df3c73913c3860a979591e1a29a98659efd38b81d3e393047b5251fe382d4c82c681c12da9ce91c98d69316d2604d155a214bcf checksum: 10c0/143faff8a72331be5ed94080e0f4645cbeea814fb488cd9210154083735f67cb66fde32f6a4a80efd6c4cdf12c6f8b50995a465846093c7f65c5da8d7829627c
languageName: node
linkType: hard
"@babel/parser@npm:^7.25.8":
version: 7.25.8
resolution: "@babel/parser@npm:7.25.8"
dependencies:
"@babel/types": "npm:^7.25.8"
bin:
parser: ./bin/babel-parser.js
checksum: 10c0/a1a13845b7e8dda4c970791814a4bbf60004969882f18f470e260ad822d2e1f8941948f851e9335895563610f240fa6c98481ce8019865e469502bbf21daafa4
languageName: node languageName: node
linkType: hard linkType: hard
@@ -480,14 +469,14 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/template@npm:^7.25.7": "@babel/template@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/template@npm:7.25.7" resolution: "@babel/template@npm:7.25.9"
dependencies: dependencies:
"@babel/code-frame": "npm:^7.25.7" "@babel/code-frame": "npm:^7.25.9"
"@babel/parser": "npm:^7.25.7" "@babel/parser": "npm:^7.25.9"
"@babel/types": "npm:^7.25.7" "@babel/types": "npm:^7.25.9"
checksum: 10c0/8ae9e36e4330ee83d4832531d1d9bec7dc2ef6a2a8afa1ef1229506fd60667abcb17f306d1c3d7e582251270597022990c845d5d69e7add70a5aea66720decb9 checksum: 10c0/ebe677273f96a36c92cc15b7aa7b11cc8bc8a3bb7a01d55b2125baca8f19cae94ff3ce15f1b1880fb8437f3a690d9f89d4e91f16fc1dc4d3eb66226d128983ab
languageName: node languageName: node
linkType: hard linkType: hard
@@ -524,18 +513,18 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/traverse@npm:^7.25.7": "@babel/traverse@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/traverse@npm:7.25.7" resolution: "@babel/traverse@npm:7.25.9"
dependencies: dependencies:
"@babel/code-frame": "npm:^7.25.7" "@babel/code-frame": "npm:^7.25.9"
"@babel/generator": "npm:^7.25.7" "@babel/generator": "npm:^7.25.9"
"@babel/parser": "npm:^7.25.7" "@babel/parser": "npm:^7.25.9"
"@babel/template": "npm:^7.25.7" "@babel/template": "npm:^7.25.9"
"@babel/types": "npm:^7.25.7" "@babel/types": "npm:^7.25.9"
debug: "npm:^4.3.1" debug: "npm:^4.3.1"
globals: "npm:^11.1.0" globals: "npm:^11.1.0"
checksum: 10c0/75d73e52c507a7a7a4c7971d6bf4f8f26fdd094e0d3a0193d77edf6a5efa36fc3db91ec5cc48e8b94e6eb5d5ad21af0a1040e71309172851209415fd105efb1a checksum: 10c0/e90be586a714da4adb80e6cb6a3c5cfcaa9b28148abdafb065e34cc109676fc3db22cf98cd2b2fff66ffb9b50c0ef882cab0f466b6844be0f6c637b82719bba1
languageName: node languageName: node
linkType: hard linkType: hard
@@ -560,25 +549,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@babel/types@npm:^7.25.7": "@babel/types@npm:^7.25.9":
version: 7.25.7 version: 7.25.9
resolution: "@babel/types@npm:7.25.7" resolution: "@babel/types@npm:7.25.9"
dependencies: dependencies:
"@babel/helper-string-parser": "npm:^7.25.7" "@babel/helper-string-parser": "npm:^7.25.9"
"@babel/helper-validator-identifier": "npm:^7.25.7" "@babel/helper-validator-identifier": "npm:^7.25.9"
to-fast-properties: "npm:^2.0.0" checksum: 10c0/33890d08bcb06b26a3a60e4c6c996cbdf2b8d8a3c212664de659c2775f80b002c5f2bceedaa309c384ff5e99bd579794fe6a7e41de07df70246f43c55016d349
checksum: 10c0/e03e1e2e08600fa1e8eb90632ac9c253dd748176c8d670d85f85b0dc83a0573b26ae748a1cbcb81f401903a3d95f43c3f4f8d516a5ed779929db27de56289633
languageName: node
linkType: hard
"@babel/types@npm:^7.25.8":
version: 7.25.8
resolution: "@babel/types@npm:7.25.8"
dependencies:
"@babel/helper-string-parser": "npm:^7.25.7"
"@babel/helper-validator-identifier": "npm:^7.25.7"
to-fast-properties: "npm:^2.0.0"
checksum: 10c0/55ca2d6df6426c98db2769ce884ce5e9de83a512ea2dd7bcf56c811984dc14351cacf42932a723630c5afcff2455809323decd645820762182f10b7b5252b59f
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1076,38 +1053,38 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/core-downloads-tracker@npm:^6.1.4": "@mui/core-downloads-tracker@npm:^6.1.5":
version: 6.1.4 version: 6.1.5
resolution: "@mui/core-downloads-tracker@npm:6.1.4" resolution: "@mui/core-downloads-tracker@npm:6.1.5"
checksum: 10c0/bfd84a726c883dd681b2cda13b977eb6646c1da66ea59905dbe7b857ec4ac86576a318eb116d54633e7c479aecb52fe0c75fb957f1b6081a6c8857dd5ce4c5b9 checksum: 10c0/c8767b7a8046e669ea687108dd2c62352e48c61379657a1b88798c12ec47cc3f99eedf30758294a17a81f2dcef22aeb08f992aecdf6e0876f312d345ba1d5f3d
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/icons-material@npm:^6.1.4": "@mui/icons-material@npm:^6.1.5":
version: 6.1.4 version: 6.1.5
resolution: "@mui/icons-material@npm:6.1.4" resolution: "@mui/icons-material@npm:6.1.5"
dependencies: dependencies:
"@babel/runtime": "npm:^7.25.7" "@babel/runtime": "npm:^7.25.7"
peerDependencies: peerDependencies:
"@mui/material": ^6.1.4 "@mui/material": ^6.1.5
"@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0
react: ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0
peerDependenciesMeta: peerDependenciesMeta:
"@types/react": "@types/react":
optional: true optional: true
checksum: 10c0/8e4e8a20c7183fae76f1e013669212404696e9e146aa413afbc705ee56f0a32cfef6143a16f9ec24aeb1e8dfb567d50f9b04b9bdf381ad8bd7a2c9b09d25186c checksum: 10c0/112f7570b8d27019a16b619a3a5b9f01cb7d8a244d50014596e17f06ed5f569888aeac2223c058da37567b5a358c99a53ee2afdf8958bc4a34b964a02f796787
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/material@npm:^6.1.4": "@mui/material@npm:^6.1.5":
version: 6.1.4 version: 6.1.5
resolution: "@mui/material@npm:6.1.4" resolution: "@mui/material@npm:6.1.5"
dependencies: dependencies:
"@babel/runtime": "npm:^7.25.7" "@babel/runtime": "npm:^7.25.7"
"@mui/core-downloads-tracker": "npm:^6.1.4" "@mui/core-downloads-tracker": "npm:^6.1.5"
"@mui/system": "npm:^6.1.4" "@mui/system": "npm:^6.1.5"
"@mui/types": "npm:^7.2.18" "@mui/types": "npm:^7.2.18"
"@mui/utils": "npm:^6.1.4" "@mui/utils": "npm:^6.1.5"
"@popperjs/core": "npm:^2.11.8" "@popperjs/core": "npm:^2.11.8"
"@types/react-transition-group": "npm:^4.4.11" "@types/react-transition-group": "npm:^4.4.11"
clsx: "npm:^2.1.1" clsx: "npm:^2.1.1"
@@ -1118,7 +1095,7 @@ __metadata:
peerDependencies: peerDependencies:
"@emotion/react": ^11.5.0 "@emotion/react": ^11.5.0
"@emotion/styled": ^11.3.0 "@emotion/styled": ^11.3.0
"@mui/material-pigment-css": ^6.1.4 "@mui/material-pigment-css": ^6.1.5
"@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0
react: ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0
@@ -1131,16 +1108,16 @@ __metadata:
optional: true optional: true
"@types/react": "@types/react":
optional: true optional: true
checksum: 10c0/3729e56129b27706ebfab67428035dc7f0136dfd745281b467c7da07e78248cc8e2f36939cd6c33967fd565c5b5eff336629e3f7a2d877e9b176d24df67c9c81 checksum: 10c0/982a2446fd511a952627aa8567e302528ad3a2ad8b3125574a38facaef2a5a076a723c67076682f95b09f9fe4dbf3445213fe6655658d23419b49440ae11873e
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/private-theming@npm:^6.1.4": "@mui/private-theming@npm:^6.1.5":
version: 6.1.4 version: 6.1.5
resolution: "@mui/private-theming@npm:6.1.4" resolution: "@mui/private-theming@npm:6.1.5"
dependencies: dependencies:
"@babel/runtime": "npm:^7.25.7" "@babel/runtime": "npm:^7.25.7"
"@mui/utils": "npm:^6.1.4" "@mui/utils": "npm:^6.1.5"
prop-types: "npm:^15.8.1" prop-types: "npm:^15.8.1"
peerDependencies: peerDependencies:
"@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0
@@ -1148,13 +1125,13 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
"@types/react": "@types/react":
optional: true optional: true
checksum: 10c0/37c81ca4529afbec2a4710d4dfa1597a5f9a33ff3ae775fa68474f86b223ed4ab953526e49883d77638ad62f0c944716c2b0dc58a105624ca91fe60a633e3b4a checksum: 10c0/3a5a470c78daa60fa3c9346a15617ab4d6ad3c544b564fe4b2fe6f3155cb4955b0c670395a9074e91956b1cb50bca96fc07d03cad92759147bebadcacd00f36c
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/styled-engine@npm:^6.1.4": "@mui/styled-engine@npm:^6.1.5":
version: 6.1.4 version: 6.1.5
resolution: "@mui/styled-engine@npm:6.1.4" resolution: "@mui/styled-engine@npm:6.1.5"
dependencies: dependencies:
"@babel/runtime": "npm:^7.25.7" "@babel/runtime": "npm:^7.25.7"
"@emotion/cache": "npm:^11.13.1" "@emotion/cache": "npm:^11.13.1"
@@ -1171,19 +1148,19 @@ __metadata:
optional: true optional: true
"@emotion/styled": "@emotion/styled":
optional: true optional: true
checksum: 10c0/ce8f53a704aa607152ef5ef25d95bdd5c4399f7dbf240acd6e4057c24d84536bb3c884fcb13c5e88d87dbfff42935c82af2e63800ba033ad481847b1967ccf52 checksum: 10c0/7a4830a7f1736d399c06d414cd6762ff4a830e976946da4a58b77e864b6d6abb4385800e644367e57c670397bf1f12690e82ffe05f185c85c8dafd132a67ca2a
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/system@npm:^6.1.4": "@mui/system@npm:^6.1.5":
version: 6.1.4 version: 6.1.5
resolution: "@mui/system@npm:6.1.4" resolution: "@mui/system@npm:6.1.5"
dependencies: dependencies:
"@babel/runtime": "npm:^7.25.7" "@babel/runtime": "npm:^7.25.7"
"@mui/private-theming": "npm:^6.1.4" "@mui/private-theming": "npm:^6.1.5"
"@mui/styled-engine": "npm:^6.1.4" "@mui/styled-engine": "npm:^6.1.5"
"@mui/types": "npm:^7.2.18" "@mui/types": "npm:^7.2.18"
"@mui/utils": "npm:^6.1.4" "@mui/utils": "npm:^6.1.5"
clsx: "npm:^2.1.1" clsx: "npm:^2.1.1"
csstype: "npm:^3.1.3" csstype: "npm:^3.1.3"
prop-types: "npm:^15.8.1" prop-types: "npm:^15.8.1"
@@ -1199,7 +1176,7 @@ __metadata:
optional: true optional: true
"@types/react": "@types/react":
optional: true optional: true
checksum: 10c0/766f1c695254df54b06de1af231cdf30752f71a79181edd4c24044405144b7a72c4c23248155f4041999993aa4f568878eccd130c100b4b332e7dd6b322dfd75 checksum: 10c0/7e8ce81b7e6a5810c0856427dbd7f89f62a23ab151e0199813e7cd7e9d47e4719004f6b576c5cad0121735cfb0c984ea022c494796202e2c0c054c6a60995c40
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1215,9 +1192,9 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@mui/utils@npm:^6.1.4": "@mui/utils@npm:^6.1.5":
version: 6.1.4 version: 6.1.5
resolution: "@mui/utils@npm:6.1.4" resolution: "@mui/utils@npm:6.1.5"
dependencies: dependencies:
"@babel/runtime": "npm:^7.25.7" "@babel/runtime": "npm:^7.25.7"
"@mui/types": "npm:^7.2.18" "@mui/types": "npm:^7.2.18"
@@ -1231,7 +1208,7 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
"@types/react": "@types/react":
optional: true optional: true
checksum: 10c0/cac4f05904897c28444e7ef2a6891678d36c0a8fae921ccacebcd7b53da99e4c6cab05669328fdabff624313de68f1b5bcd427cba36024b6c3505b5ee945eb05 checksum: 10c0/899191334f321aedf993e6a79cd63ac511e8ef23a84c1e156ca4a82c407e97f86f9f3d4250765f5c9e71d9af963bdc738e6d63fc62f9088fc5ad9c055fc3b111
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1685,12 +1662,12 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@types/node@npm:^22.7.7": "@types/node@npm:^22.7.8":
version: 22.7.7 version: 22.7.8
resolution: "@types/node@npm:22.7.7" resolution: "@types/node@npm:22.7.8"
dependencies: dependencies:
undici-types: "npm:~6.19.2" undici-types: "npm:~6.19.2"
checksum: 10c0/07268a1e990ad9d9b1865092881317ea679a46eb6706d83a8874eec75fdddae6cfd6452e4e68b651561183e2a8f8548276f3155744bc402c2545978c19b70d65 checksum: 10c0/3d3b3a2ec5a57ca4fd37b34dce415620993ca5f87cea2c728ffe73aa31446dbfe19c53171c478447bd7d78011ef4845a46ab2f0dc38e699cc75b3d100a60c690
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1785,15 +1762,15 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/eslint-plugin@npm:8.10.0": "@typescript-eslint/eslint-plugin@npm:8.11.0":
version: 8.10.0 version: 8.11.0
resolution: "@typescript-eslint/eslint-plugin@npm:8.10.0" resolution: "@typescript-eslint/eslint-plugin@npm:8.11.0"
dependencies: dependencies:
"@eslint-community/regexpp": "npm:^4.10.0" "@eslint-community/regexpp": "npm:^4.10.0"
"@typescript-eslint/scope-manager": "npm:8.10.0" "@typescript-eslint/scope-manager": "npm:8.11.0"
"@typescript-eslint/type-utils": "npm:8.10.0" "@typescript-eslint/type-utils": "npm:8.11.0"
"@typescript-eslint/utils": "npm:8.10.0" "@typescript-eslint/utils": "npm:8.11.0"
"@typescript-eslint/visitor-keys": "npm:8.10.0" "@typescript-eslint/visitor-keys": "npm:8.11.0"
graphemer: "npm:^1.4.0" graphemer: "npm:^1.4.0"
ignore: "npm:^5.3.1" ignore: "npm:^5.3.1"
natural-compare: "npm:^1.4.0" natural-compare: "npm:^1.4.0"
@@ -1804,66 +1781,66 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: 10c0/4b77ba9c865a2a14e238cd330b5901f0274b8ce1c13324fccd0339b8eea82a50a4709394c903fd8cd5bd0d3aebace0761ff9a4a19fa20b00bb61349b7671c035 checksum: 10c0/be509f7bb0c0c596801059b06995a81a1c326cc6ac31d96a32f7b6b7d7b495f9bad4dc442aa6e923d22515e62c668d3c14695c68bd6e0be1d4bf72158b7fd2d6
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/parser@npm:8.10.0": "@typescript-eslint/parser@npm:8.11.0":
version: 8.10.0 version: 8.11.0
resolution: "@typescript-eslint/parser@npm:8.10.0" resolution: "@typescript-eslint/parser@npm:8.11.0"
dependencies: dependencies:
"@typescript-eslint/scope-manager": "npm:8.10.0" "@typescript-eslint/scope-manager": "npm:8.11.0"
"@typescript-eslint/types": "npm:8.10.0" "@typescript-eslint/types": "npm:8.11.0"
"@typescript-eslint/typescript-estree": "npm:8.10.0" "@typescript-eslint/typescript-estree": "npm:8.11.0"
"@typescript-eslint/visitor-keys": "npm:8.10.0" "@typescript-eslint/visitor-keys": "npm:8.11.0"
debug: "npm:^4.3.4" debug: "npm:^4.3.4"
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: 10c0/7becb2457c085c239838d301796074b790f46dd38c9fbc14ec1dec8e993c7115cd8a66cdc07983c3a68a2dd92e24e8acc49d69a4ebcc29e9869957eb52d1cb74 checksum: 10c0/e83f239fec60697083e5dcb1c8948340e783ea6e043fe9a65d557faef8882963b09d69aacd736eb8ab18a768769a7bbfc3de0f1251d4bba080613541acb0741c
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/scope-manager@npm:8.10.0": "@typescript-eslint/scope-manager@npm:8.11.0":
version: 8.10.0 version: 8.11.0
resolution: "@typescript-eslint/scope-manager@npm:8.10.0" resolution: "@typescript-eslint/scope-manager@npm:8.11.0"
dependencies: dependencies:
"@typescript-eslint/types": "npm:8.10.0" "@typescript-eslint/types": "npm:8.11.0"
"@typescript-eslint/visitor-keys": "npm:8.10.0" "@typescript-eslint/visitor-keys": "npm:8.11.0"
checksum: 10c0/b8bb8635c4d6c00a3578d6265e3ee0f5d96d0c9dee534ed588aa411c3f4497fd71cce730c3ae7571e52453d955b191bc9edcc47c9af21a20c90e9a20f2371108 checksum: 10c0/0910da62d8ae261711dd9f89d5c7d8e96ff13c50054436256e5a661309229cb49e3b8189c9468d36b6c4d3f7cddd121519ea78f9b18c9b869a808834b079b2ea
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/type-utils@npm:8.10.0": "@typescript-eslint/type-utils@npm:8.11.0":
version: 8.10.0 version: 8.11.0
resolution: "@typescript-eslint/type-utils@npm:8.10.0" resolution: "@typescript-eslint/type-utils@npm:8.11.0"
dependencies: dependencies:
"@typescript-eslint/typescript-estree": "npm:8.10.0" "@typescript-eslint/typescript-estree": "npm:8.11.0"
"@typescript-eslint/utils": "npm:8.10.0" "@typescript-eslint/utils": "npm:8.11.0"
debug: "npm:^4.3.4" debug: "npm:^4.3.4"
ts-api-utils: "npm:^1.3.0" ts-api-utils: "npm:^1.3.0"
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: 10c0/1af8fce8394279e6ac7bcef449a132072ee36e374c8d557564246ffe7150230844901ca0305e29525bf37c87010e03bf8bedec76fccbfe1e41931cb4f274e208 checksum: 10c0/b69e31c1599ceeb20c29052a4ddb33a554174a3a4c55ee37d90c9b8250af6ef978a0b9ddbeefef4e83d62c4caea1bfa2d8088527f397bde69fb4ab9b360d794a
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/types@npm:8.10.0": "@typescript-eslint/types@npm:8.11.0":
version: 8.10.0 version: 8.11.0
resolution: "@typescript-eslint/types@npm:8.10.0" resolution: "@typescript-eslint/types@npm:8.11.0"
checksum: 10c0/f27dd43c8383e02e914a254257627e393dfc0f08b0f74a253c106813ae361f090271b2f3f2ef588fa3ca1329897d873da595bb5641fe8e3091b25eddca24b5d2 checksum: 10c0/5ccdd3eeee077a6fc8e7f4bc0e0cbc9327b1205a845253ec5c0c6c49ff915e853161df00c24a0ffb4b8ec745d3f153dd0e066400a021c844c026e31121f46699
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/typescript-estree@npm:8.10.0": "@typescript-eslint/typescript-estree@npm:8.11.0":
version: 8.10.0 version: 8.11.0
resolution: "@typescript-eslint/typescript-estree@npm:8.10.0" resolution: "@typescript-eslint/typescript-estree@npm:8.11.0"
dependencies: dependencies:
"@typescript-eslint/types": "npm:8.10.0" "@typescript-eslint/types": "npm:8.11.0"
"@typescript-eslint/visitor-keys": "npm:8.10.0" "@typescript-eslint/visitor-keys": "npm:8.11.0"
debug: "npm:^4.3.4" debug: "npm:^4.3.4"
fast-glob: "npm:^3.3.2" fast-glob: "npm:^3.3.2"
is-glob: "npm:^4.0.3" is-glob: "npm:^4.0.3"
@@ -1873,31 +1850,31 @@ __metadata:
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: 10c0/535a740fe25be0e28fe68c41e3264273d1e5169c9f938e08cc0e3415c357726f43efa44621960108c318fc3305c425d29f3223b6e731d44d67f84058a8947304 checksum: 10c0/b629ad3cd32b005d5c1d67c36958a418f8672efebea869399834f4f201ebf90b942165eebb5c9d9799dcabdc2cc26e5fabb00629f76b158847f42e1a491a75a6
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/utils@npm:8.10.0": "@typescript-eslint/utils@npm:8.11.0":
version: 8.10.0 version: 8.11.0
resolution: "@typescript-eslint/utils@npm:8.10.0" resolution: "@typescript-eslint/utils@npm:8.11.0"
dependencies: dependencies:
"@eslint-community/eslint-utils": "npm:^4.4.0" "@eslint-community/eslint-utils": "npm:^4.4.0"
"@typescript-eslint/scope-manager": "npm:8.10.0" "@typescript-eslint/scope-manager": "npm:8.11.0"
"@typescript-eslint/types": "npm:8.10.0" "@typescript-eslint/types": "npm:8.11.0"
"@typescript-eslint/typescript-estree": "npm:8.10.0" "@typescript-eslint/typescript-estree": "npm:8.11.0"
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
checksum: 10c0/a21a2933517176abd00fcd5d8d80023e35dc3d89d5746bbac43790b4e984ab1f371117db08048bce7f42d54c64f4e0e35161149f8f34fd25a27bff9d1110fd16 checksum: 10c0/bb5bcc8d928a55b22298e76f834ea6a9fe125a9ffeb6ac23bee0258b3ed32f41e281888a3d0be226a05e1011bb3b70e42a71a40366acdefea6779131c46bc522
languageName: node languageName: node
linkType: hard linkType: hard
"@typescript-eslint/visitor-keys@npm:8.10.0": "@typescript-eslint/visitor-keys@npm:8.11.0":
version: 8.10.0 version: 8.11.0
resolution: "@typescript-eslint/visitor-keys@npm:8.10.0" resolution: "@typescript-eslint/visitor-keys@npm:8.11.0"
dependencies: dependencies:
"@typescript-eslint/types": "npm:8.10.0" "@typescript-eslint/types": "npm:8.11.0"
eslint-visitor-keys: "npm:^3.4.3" eslint-visitor-keys: "npm:^3.4.3"
checksum: 10c0/14721c4ac939640d5fd1ee1b6eeb07604b11a6017e319e21dcc71e7aac2992341fc7ae1992d977bad4433b6a1d0d1c0c279e6927316b26245f6e333f922fa458 checksum: 10c0/7a5a49609fdc47e114fe59eee56393c90b122ec8e9520f90b0c5e189635ae1ccfa8e00108f641342c2c8f4637fe9d40c77927cf7c8248a3a660812cb4b7d0c08
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1906,18 +1883,18 @@ __metadata:
resolution: "EMS-ESP@workspace:." resolution: "EMS-ESP@workspace:."
dependencies: dependencies:
"@alova/adapter-xhr": "npm:2.0.8" "@alova/adapter-xhr": "npm:2.0.8"
"@babel/core": "npm:^7.25.8" "@babel/core": "npm:^7.25.9"
"@emotion/react": "npm:^11.13.3" "@emotion/react": "npm:^11.13.3"
"@emotion/styled": "npm:^11.13.0" "@emotion/styled": "npm:^11.13.0"
"@eslint/js": "npm:^9.13.0" "@eslint/js": "npm:^9.13.0"
"@mui/icons-material": "npm:^6.1.4" "@mui/icons-material": "npm:^6.1.5"
"@mui/material": "npm:^6.1.4" "@mui/material": "npm:^6.1.5"
"@preact/compat": "npm:^18.3.1" "@preact/compat": "npm:^18.3.1"
"@preact/preset-vite": "npm:^2.9.1" "@preact/preset-vite": "npm:^2.9.1"
"@table-library/react-table-library": "npm:4.1.7" "@table-library/react-table-library": "npm:4.1.7"
"@trivago/prettier-plugin-sort-imports": "npm:^4.3.0" "@trivago/prettier-plugin-sort-imports": "npm:^4.3.0"
"@types/formidable": "npm:^3" "@types/formidable": "npm:^3"
"@types/node": "npm:^22.7.7" "@types/node": "npm:^22.7.8"
"@types/react": "npm:^18.3.11" "@types/react": "npm:^18.3.11"
"@types/react-dom": "npm:^18.3.1" "@types/react-dom": "npm:^18.3.1"
"@types/react-router-dom": "npm:^5.3.3" "@types/react-router-dom": "npm:^5.3.3"
@@ -1940,7 +1917,7 @@ __metadata:
terser: "npm:^5.36.0" terser: "npm:^5.36.0"
typesafe-i18n: "npm:^5.26.2" typesafe-i18n: "npm:^5.26.2"
typescript: "npm:^5.6.3" typescript: "npm:^5.6.3"
typescript-eslint: "npm:8.10.0" typescript-eslint: "npm:8.11.0"
vite: "npm:^5.4.9" vite: "npm:^5.4.9"
vite-plugin-imagemin: "npm:^0.6.1" vite-plugin-imagemin: "npm:^0.6.1"
vite-tsconfig-paths: "npm:^5.0.1" vite-tsconfig-paths: "npm:^5.0.1"
@@ -7042,17 +7019,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"typescript-eslint@npm:8.10.0": "typescript-eslint@npm:8.11.0":
version: 8.10.0 version: 8.11.0
resolution: "typescript-eslint@npm:8.10.0" resolution: "typescript-eslint@npm:8.11.0"
dependencies: dependencies:
"@typescript-eslint/eslint-plugin": "npm:8.10.0" "@typescript-eslint/eslint-plugin": "npm:8.11.0"
"@typescript-eslint/parser": "npm:8.10.0" "@typescript-eslint/parser": "npm:8.11.0"
"@typescript-eslint/utils": "npm:8.10.0" "@typescript-eslint/utils": "npm:8.11.0"
peerDependenciesMeta: peerDependenciesMeta:
typescript: typescript:
optional: true optional: true
checksum: 10c0/9eca1bfdea4e108bea06f0053b57f8a9eaeb43bf3316a39c6d29631bd3217ec67611e46d361417c48a5f6eeb99c4a7fc81c020734b1b47d7b8e42fa67d74ea0f checksum: 10c0/8f9b5916c9f47b0cbb26f142d1a266a6aaf33998ec87621252dffb56d8fe0ad01a944f8d8d837e4e6058153a1deee3557527d14fa7bf7ef80a927334529db6bd
languageName: node languageName: node
linkType: hard linkType: hard

View File

@@ -253,7 +253,7 @@ StateUpdateResult MqttSettings::update(JsonObject root, MqttSettings & settings)
bool changed = false; bool changed = false;
#ifndef TASMOTA_SDK #ifndef TASMOTA_SDK
newSettings.enableTLS = root["enableTLS"] | false; newSettings.enableTLS = root["enableTLS"];
newSettings.rootCA = root["rootCA"] | ""; newSettings.rootCA = root["rootCA"] | "";
#else #else
newSettings.enableTLS = false; newSettings.enableTLS = false;

View File

@@ -424,12 +424,12 @@ StateUpdateResult NetworkSettings::update(JsonObject root, NetworkSettings & set
settings.bssid = root["bssid"] | ""; settings.bssid = root["bssid"] | "";
settings.password = root["password"] | FACTORY_WIFI_PASSWORD; settings.password = root["password"] | FACTORY_WIFI_PASSWORD;
settings.hostname = root["hostname"] | FACTORY_WIFI_HOSTNAME; settings.hostname = root["hostname"] | FACTORY_WIFI_HOSTNAME;
settings.staticIPConfig = root["static_ip_config"] | false; settings.staticIPConfig = root["static_ip_config"];
settings.bandwidth20 = root["bandwidth20"] | false; settings.bandwidth20 = root["bandwidth20"];
settings.tx_power = static_cast<uint8_t>(root["tx_power"] | 0); settings.tx_power = static_cast<uint8_t>(root["tx_power"] | 0);
settings.nosleep = root["nosleep"] | true; settings.nosleep = root["nosleep"] | true;
settings.enableMDNS = root["enableMDNS"] | true; settings.enableMDNS = root["enableMDNS"] | true;
settings.enableCORS = root["enableCORS"] | false; settings.enableCORS = root["enableCORS"];
settings.CORSOrigin = root["CORSOrigin"] | "*"; settings.CORSOrigin = root["CORSOrigin"] | "*";
// extended settings // extended settings

View File

@@ -1,16 +0,0 @@
#!/bin/sh
# API
curl -X GET http://ems-esp.local/api/system/info
echo "\n"
# HA
ha_url="http://192.168.1.42:8123"
ha_token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIwMzMyZjU1MjhlZmM0NGIyOTgyMjIxNThiODU1NDkyNSIsImlhdCI6MTcyMTMwNDg2NSwiZXhwIjoyMDM2NjY0ODY1fQ.Q-Y7E_i7clH3ff4Ma-OMmhZfbN7aMi_CahKwmoar"
curl -X POST \
${ha_url}/api/services/script/test_notify \
-H "Authorization: Bearer ${ha_token}" \
-H "Content-Type: application/json" \

View File

@@ -116,7 +116,7 @@ export default () => {
}; };
count++; count++;
res.write(`data: ${JSON.stringify(data)}\n\n`); res.write(`data: ${JSON.stringify(data)}\n\n`);
}, 500); }, 1000);
// if client closes connection // if client closes connection
res.on('close', () => { res.on('close', () => {

View File

@@ -197,23 +197,85 @@ function custom_support() {
// called by Action endpoint // called by Action endpoint
function check_upgrade(version: string) { function check_upgrade(version: string) {
console.log('check upgrade from version', version); let data = {};
const data = { if (version) {
upgradeable: true console.log('check upgrade from version', version);
// upgradeable: false data = {
}; emsesp_version: VERSION,
upgradeable: true
// upgradeable: false,
};
} else {
console.log('requesting ems-esp version');
data = {
emsesp_version: VERSION
};
}
return data; return data;
} }
// START DATA // START DATA
// EMS-ESP Application Settings
let settings = {
locale: 'en',
tx_mode: 1,
ems_bus_id: 11,
syslog_enabled: false,
syslog_level: 3,
trace_raw: false,
syslog_mark_interval: 0,
syslog_host: '192.168.1.8',
syslog_port: 514,
boiler_heatingoff: false,
remote_timeout: 24,
remote_timeout_en: false,
shower_timer: true,
shower_alert: false,
shower_alert_coldshot: 10,
shower_alert_trigger: 7,
shower_min_duration: 180,
rx_gpio: 4,
tx_gpio: 5,
dallas_gpio: 14,
dallas_parasite: false,
led_gpio: 2,
hide_led: true,
low_clock: false,
telnet_enabled: true,
notoken_api: false,
readonly_mode: false,
analog_enabled: true,
pbutton_gpio: 34,
solar_maxflow: 30,
board_profile: 'E32V2',
fahrenheit: false,
bool_format: 1,
bool_dashboard: 1,
enum_format: 1,
weblog_level: 6,
weblog_buffer: 50,
weblog_compact: true,
phy_type: 1,
eth_power: 15,
eth_phy_addr: 0,
eth_clock_mode: 1,
platform: 'ESP32',
modbus_enabled: false,
modbus_port: 502,
modbus_max_clients: 10,
modbus_timeout: 10000,
developer_mode: true
};
// LOG // LOG
const LOG_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'logSettings'; const LOG_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'logSettings';
let log_settings = { let log_settings = {
level: 6, level: 6,
max_messages: 50, max_messages: 50,
compact: true, compact: true,
psram: true psram: true,
developer_mode: settings.developer_mode
}; };
// NTP // NTP
@@ -478,9 +540,6 @@ const signin = admin_signin;
const generate_token = { token: '1234' }; const generate_token = { token: '1234' };
//
// EMS-ESP Project specific
//
const EMSESP_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'settings'; const EMSESP_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'settings';
const EMSESP_CORE_DATA_ENDPOINT = REST_ENDPOINT_ROOT + 'coreData'; const EMSESP_CORE_DATA_ENDPOINT = REST_ENDPOINT_ROOT + 'coreData';
const EMSESP_SENSOR_DATA_ENDPOINT = REST_ENDPOINT_ROOT + 'sensorData'; const EMSESP_SENSOR_DATA_ENDPOINT = REST_ENDPOINT_ROOT + 'sensorData';
@@ -493,6 +552,7 @@ const EMSESP_DEVICEENTITIES_ENDPOINT2 = REST_ENDPOINT_ROOT + 'deviceEntities/:id
const EMSESP_DASHBOARD_DATA_ENDPOINT = REST_ENDPOINT_ROOT + 'dashboardData'; const EMSESP_DASHBOARD_DATA_ENDPOINT = REST_ENDPOINT_ROOT + 'dashboardData';
const EMSESP_BOARDPROFILE_ENDPOINT = REST_ENDPOINT_ROOT + 'boardProfile'; const EMSESP_BOARDPROFILE_ENDPOINT = REST_ENDPOINT_ROOT + 'boardProfile';
const EMSESP_WRITE_DEVICEVALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeDeviceValue'; const EMSESP_WRITE_DEVICEVALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeDeviceValue';
const EMSESP_WRITE_DEVICENAME_ENDPOINT = REST_ENDPOINT_ROOT + 'writeDeviceName'; const EMSESP_WRITE_DEVICENAME_ENDPOINT = REST_ENDPOINT_ROOT + 'writeDeviceName';
const EMSESP_WRITE_TEMPSENSOR_ENDPOINT = const EMSESP_WRITE_TEMPSENSOR_ENDPOINT =
@@ -502,10 +562,10 @@ const EMSESP_CUSTOMIZATION_ENTITIES_ENDPOINT =
REST_ENDPOINT_ROOT + 'customizationEntities'; REST_ENDPOINT_ROOT + 'customizationEntities';
const EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT = const EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT =
REST_ENDPOINT_ROOT + 'resetCustomizations'; REST_ENDPOINT_ROOT + 'resetCustomizations';
const EMSESP_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule'; const EMSESP_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule';
const EMSESP_CUSTOMENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'customEntities'; const EMSESP_CUSTOMENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'customEntities';
const EMSESP_MODULES_ENDPOINT = REST_ENDPOINT_ROOT + 'modules'; const EMSESP_MODULES_ENDPOINT = REST_ENDPOINT_ROOT + 'modules';
const EMSESP_ACTION_ENDPOINT = REST_ENDPOINT_ROOT + 'action'; const EMSESP_ACTION_ENDPOINT = REST_ENDPOINT_ROOT + 'action';
// these are used in the API calls only // these are used in the API calls only
@@ -513,7 +573,7 @@ const EMSESP_SYSTEM_INFO_ENDPOINT = API_ENDPOINT_ROOT + 'system/info';
const emsesp_info = { const emsesp_info = {
System: { System: {
version: '3.7-demo', version: VERSION,
uptime: '001+06:40:34.018', uptime: '001+06:40:34.018',
'uptime (seconds)': 110434, 'uptime (seconds)': 110434,
freemem: 131, freemem: 131,
@@ -663,56 +723,6 @@ const emsesp_allvalues = {
} }
}; };
let settings = {
locale: 'en',
tx_mode: 1,
ems_bus_id: 11,
syslog_enabled: false,
syslog_level: 3,
trace_raw: false,
syslog_mark_interval: 0,
syslog_host: '192.168.1.8',
syslog_port: 514,
boiler_heatingoff: false,
remote_timeout: 24,
remote_timeout_en: false,
shower_timer: true,
shower_alert: false,
shower_alert_coldshot: 10,
shower_alert_trigger: 7,
shower_min_duration: 180,
rx_gpio: 4,
tx_gpio: 5,
dallas_gpio: 14,
dallas_parasite: false,
led_gpio: 2,
hide_led: true,
low_clock: false,
telnet_enabled: true,
notoken_api: false,
readonly_mode: false,
analog_enabled: true,
pbutton_gpio: 34,
solar_maxflow: 30,
board_profile: 'E32V2',
fahrenheit: false,
bool_format: 1,
bool_dashboard: 1,
enum_format: 1,
weblog_level: 6,
weblog_buffer: 50,
weblog_compact: true,
phy_type: 1,
eth_power: 15,
eth_phy_addr: 0,
eth_clock_mode: 1,
platform: 'ESP32',
modbus_enabled: false,
modbus_port: 502,
modbus_max_clients: 10,
modbus_timeout: 10000
};
const emsesp_coredata = { const emsesp_coredata = {
connected: true, connected: true,
// connected: false, // connected: false,
@@ -4820,6 +4830,10 @@ router
return custom_support(); return custom_support();
} else if (action === 'checkUpgrade') { } else if (action === 'checkUpgrade') {
// check upgrade // check upgrade
// check if content has a param
if (!content.param) {
return check_upgrade('');
}
return check_upgrade(content.param); return check_upgrade(content.param);
} else if (action === 'uploadURL') { } else if (action === 'uploadURL') {
// upload URL // upload URL
@@ -4848,16 +4862,17 @@ router
if (data.device === 'system') { if (data.device === 'system') {
if (cmd === 'info') { if (cmd === 'info') {
return emsesp_info; return emsesp_info;
} } else if (cmd === 'format') {
if (cmd === 'format') {
console.log('formatting...'); console.log('formatting...');
return status(200); return status(200);
} } else if (cmd === 'restart') {
if (cmd === 'restart') {
console.log('restarting...'); console.log('restarting...');
system_status.status = 'restarting'; system_status.status = 'restarting';
countHardwarePoll = 0; countHardwarePoll = 0;
return status(200); return status(200);
} else if (cmd === 'read') {
console.log('send read command:', data.data);
return status(200);
} }
} }
return status(404); // not found return status(404); // not found

View File

@@ -85,8 +85,6 @@ lib_deps =
; ;
; builds for GitHub Actions CI ; builds for GitHub Actions CI
; We don't set EMSESP_DEFAULT_BOARD_PROFILE and let the code determine the board type. e.g. with board_build.extra_flags = '-DEMSESP_DEFAULT_BOARD_PROFILE="S32"'
;
; the Web interface is built separately during the GH Action script, so skipped on these targets ; the Web interface is built separately during the GH Action script, so skipped on these targets
; ;
[env:ci_s_4M] [env:ci_s_4M]
@@ -240,7 +238,7 @@ lib_ldf_mode = off
lib_ignore = Module EMS-ESP-Modules lib_ignore = Module EMS-ESP-Modules
; unit tests ; unit tests
; The code is in test/test_api.h/cpp ; The code is in ./test/test_api.*
; to run use `pio run -e native-test -t exec`. All tests should PASS. ; to run use `pio run -e native-test -t exec`. All tests should PASS.
; to update the test results, compile with -DEMSESP_UNITY_CREATE by uncommenting the line below ; to update the test results, compile with -DEMSESP_UNITY_CREATE by uncommenting the line below
; then run and capture the output between "START - CUT HERE" and "END - CUT HERE" into the test_api.h file ; then run and capture the output between "START - CUT HERE" and "END - CUT HERE" into the test_api.h file

View File

@@ -379,30 +379,25 @@ static void setup_commands(std::shared_ptr<Commands> const & commands) {
} }
}); });
// read <deviceID> <type ID> [offset] [length]
commands->add_command(ShellContext::MAIN, commands->add_command(ShellContext::MAIN,
CommandFlags::USER, CommandFlags::USER,
{F_(read)}, {F_(read)},
string_vector{F_(deviceid_mandatory), F_(typeid_mandatory), F_(offset_optional), F_(length_optional)}, string_vector{F_(deviceid_mandatory), F_(typeid_mandatory), F_(offset_optional), F_(length_optional)},
[=](Shell & shell, const std::vector<std::string> & arguments) { [=](Shell & shell, const std::vector<std::string> & arguments) {
uint8_t device_id = Helpers::hextoint(arguments.front().c_str()); // loop through arguments and add to data as text, separated by a space
std::string data;
for (const auto & arg : arguments) {
if (!data.empty()) {
data += " ";
}
data += arg;
}
if (!EMSESP::valid_device(device_id)) { if (!System::readCommand(data.c_str())) {
shell.printfln("Invalid deviceID"); shell.printfln("Invalid deviceID");
return; return;
} }
uint16_t type_id = Helpers::hextoint(arguments[1].c_str());
if (arguments.size() == 4) {
uint16_t offset = Helpers::hextoint(arguments[2].c_str());
uint8_t length = Helpers::hextoint(arguments.back().c_str());
EMSESP::send_read_request(type_id, device_id, offset, length, true);
} else if (arguments.size() == 3) {
uint16_t offset = Helpers::hextoint(arguments.back().c_str());
EMSESP::send_read_request(type_id, device_id, offset, 0, true);
} else {
EMSESP::send_read_request(type_id, device_id, 0, 0, true);
}
EMSESP::set_read_id(type_id);
}); });
commands->add_command(ShellContext::MAIN, commands->add_command(ShellContext::MAIN,

View File

@@ -99,7 +99,7 @@ char * Helpers::ultostr(char * ptr, uint32_t value, const uint8_t base) {
#endif #endif
/** /**
* fast atoi returning a std::string * fast itoa returning a std::string
* http://www.strudel.org.uk/itoa/ * http://www.strudel.org.uk/itoa/
* *
*/ */
@@ -122,8 +122,9 @@ std::string Helpers::itoa(int16_t value) {
} }
/* /*
* fast itoa and optimized for ESP32 * fast itoa
* written by Lukás Chmela, Released under GPLv3. http://www.strudel.org.uk/itoa/ version 0.4 * written by Lukás Chmela, Released under GPLv3. http://www.strudel.org.uk/itoa/ version 0.4
* optimized for ESP32
*/ */
char * Helpers::itoa(int32_t value, char * result, const uint8_t base) { char * Helpers::itoa(int32_t value, char * result, const uint8_t base) {
// check that the base if valid // check that the base if valid

View File

@@ -20,7 +20,6 @@
#define EMSESP_HELPERS_H #define EMSESP_HELPERS_H
#include "telegram.h" // for EMS_VALUE_* settings #include "telegram.h" // for EMS_VALUE_* settings
#include "common.h" #include "common.h"
namespace emsesp { namespace emsesp {

View File

@@ -63,6 +63,7 @@ MAKE_WORD_TRANSLATION(info_cmd, "list all values (verbose)", "Liste aller Werte"
MAKE_WORD_TRANSLATION(commands_cmd, "list all commands", "Liste aller Kommandos", "lijst van alle commando's", "", "wyświetl wszystkie komendy", "Viser alle kommandoer", "", "Tüm komutları listele", "elencaa tutti i comandi", "zobraziť všetky príkazy") // TODO translate MAKE_WORD_TRANSLATION(commands_cmd, "list all commands", "Liste aller Kommandos", "lijst van alle commando's", "", "wyświetl wszystkie komendy", "Viser alle kommandoer", "", "Tüm komutları listele", "elencaa tutti i comandi", "zobraziť všetky príkazy") // TODO translate
MAKE_WORD_TRANSLATION(entities_cmd, "list all entities", "Liste aller Entitäten", "lijst van alle entiteiten", "", "wyświetl wszsytkie encje", "Viser alle enheter", "", "Tüm varlıkları listele", "elenca tutte le entità", "zobraziť všetky entity") // TODO translate MAKE_WORD_TRANSLATION(entities_cmd, "list all entities", "Liste aller Entitäten", "lijst van alle entiteiten", "", "wyświetl wszsytkie encje", "Viser alle enheter", "", "Tüm varlıkları listele", "elenca tutte le entità", "zobraziť všetky entity") // TODO translate
MAKE_WORD_TRANSLATION(send_cmd, "send a telegram", "Sende EMS-Telegramm", "stuur een telegram", "", "wyślij telegram", "send et telegram", "", "Bir telegram gönder", "invia un telegramma", "poslať telegram") // TODO translate MAKE_WORD_TRANSLATION(send_cmd, "send a telegram", "Sende EMS-Telegramm", "stuur een telegram", "", "wyślij telegram", "send et telegram", "", "Bir telegram gönder", "invia un telegramma", "poslať telegram") // TODO translate
MAKE_WORD_TRANSLATION(read_cmd, "send read request", "", "", "", "", "", "", "", "", "") // TODO translate
MAKE_WORD_TRANSLATION(setiovalue_cmd, "set I/O value", "Setze Werte E/A", "instellen standaardwaarde", "", "ustaw wartość", "sett en io verdi", "", "Giriş/Çıkış değerlerini ayarla", "imposta valore io", "nastaviť hodnotu io") // TODO translate MAKE_WORD_TRANSLATION(setiovalue_cmd, "set I/O value", "Setze Werte E/A", "instellen standaardwaarde", "", "ustaw wartość", "sett en io verdi", "", "Giriş/Çıkış değerlerini ayarla", "imposta valore io", "nastaviť hodnotu io") // TODO translate
MAKE_WORD_TRANSLATION(changeloglevel_cmd, "change log level", "Ändere Protokollebene", "aanpassen log niveau", "", "zmień poziom log-u", "endre loggnivå", "", "Kayıt seviyesini değiştir", "cambia livello registrazione", "zmeniť úroveň protokolu") // TODO translate MAKE_WORD_TRANSLATION(changeloglevel_cmd, "change log level", "Ändere Protokollebene", "aanpassen log niveau", "", "zmień poziom log-u", "endre loggnivå", "", "Kayıt seviyesini değiştir", "cambia livello registrazione", "zmeniť úroveň protokolu") // TODO translate
MAKE_WORD_TRANSLATION(fetch_cmd, "refresh all EMS values", "Aktualisiere alle EMS-Werte", "Verversen alle EMS waardes", "", "odśwież wszystkie wartości EMS", "oppfrisk alle EMS verdier", "", "Bütün EMS değerlerini yenile", "aggiornare tutti i valori EMS", "obnoviť všetky hodnoty EMS") // TODO translate MAKE_WORD_TRANSLATION(fetch_cmd, "refresh all EMS values", "Aktualisiere alle EMS-Werte", "Verversen alle EMS waardes", "", "odśwież wszystkie wartości EMS", "oppfrisk alle EMS verdier", "", "Bütün EMS değerlerini yenile", "aggiornare tutti i valori EMS", "obnoviť všetky hodnoty EMS") // TODO translate
@@ -182,7 +183,7 @@ MAKE_WORD_TRANSLATION(eco, "eco", "Eco", "Eco", "Eko", "eko", "øko", "éco", "e
MAKE_WORD_TRANSLATION(ecoplus, "eco+", "Eco+", "Eco+", "Eko+", "eko+", "øko+", "éco+", "eko+", "Eco+") MAKE_WORD_TRANSLATION(ecoplus, "eco+", "Eco+", "Eco+", "Eko+", "eko+", "øko+", "éco+", "eko+", "Eco+")
MAKE_WORD_TRANSLATION(intelligent, "intelligent", "Intelligent", "intelligent", "Intelligent", "inteligentny", "intelligent", "intelligent", "akıllı", "intelligente", "inteligentný") MAKE_WORD_TRANSLATION(intelligent, "intelligent", "Intelligent", "intelligent", "Intelligent", "inteligentny", "intelligent", "intelligent", "akıllı", "intelligente", "inteligentný")
MAKE_WORD_TRANSLATION(flow, "flow", "Durchfluss", "volumestroom", "Flöde", "przepływ", "strømme", "débit", "akım", "flusso", "tok") MAKE_WORD_TRANSLATION(flow, "flow", "Durchfluss", "volumestroom", "Flöde", "przepływ", "strømme", "débit", "akım", "flusso", "tok")
MAKE_WORD_TRANSLATION(manual, "manual", "Manuell", "handmatig", "Manuell", "ręczny", "manuell", "manuel", "manuel", "manuale", "manuálny") MAKE_WORD_TRANSLATION(manual, "manual", "manuell", "handmatig", "Manuell", "ręczny", "manuell", "manuel", "manuel", "manuale", "manuálny")
MAKE_WORD_TRANSLATION(buffer, "buffer", "Speicher", "buffer", "Buffert", "bufor", "buffer", "buffer", "tampon", "Buffer", "zásobník") MAKE_WORD_TRANSLATION(buffer, "buffer", "Speicher", "buffer", "Buffert", "bufor", "buffer", "buffer", "tampon", "Buffer", "zásobník")
MAKE_WORD_TRANSLATION(bufferedflow, "buffered flow", "Durchlaufspeicher", "doorstroombuffer", "Buffertflöde", "przepływ buforowany", "bufret strømning", "", "tampon akım", "memoria flusso", "zásobníkový prietok") // TODO translate MAKE_WORD_TRANSLATION(bufferedflow, "buffered flow", "Durchlaufspeicher", "doorstroombuffer", "Buffertflöde", "przepływ buforowany", "bufret strømning", "", "tampon akım", "memoria flusso", "zásobníkový prietok") // TODO translate
MAKE_WORD_TRANSLATION(layeredbuffer, "layered buffer", "Schichtspeicher", "gelaagde buffer", "Lagrad buffert", "bufor warstwowy", "lagdelt buffer", "", "katmanlı akım", "strato memoria", "vrstvený zásobník") // TODO translate MAKE_WORD_TRANSLATION(layeredbuffer, "layered buffer", "Schichtspeicher", "gelaagde buffer", "Lagrad buffert", "bufor warstwowy", "lagdelt buffer", "", "katmanlı akım", "strato memoria", "vrstvený zásobník") // TODO translate

View File

@@ -409,7 +409,8 @@ void System::reload_settings() {
eth_phy_addr_ = settings.eth_phy_addr; eth_phy_addr_ = settings.eth_phy_addr;
eth_clock_mode_ = settings.eth_clock_mode; eth_clock_mode_ = settings.eth_clock_mode;
locale_ = settings.locale; locale_ = settings.locale;
developer_mode_ = settings.developer_mode;
}); });
} }
@@ -851,6 +852,7 @@ void System::system_check() {
// commands - takes static function pointers // commands - takes static function pointers
// can be called via Console using 'call system <cmd>' // can be called via Console using 'call system <cmd>'
void System::commands_init() { void System::commands_init() {
Command::add(EMSdevice::DeviceType::SYSTEM, F_(read), System::command_read, FL_(read_cmd), CommandFlag::ADMIN_ONLY);
Command::add(EMSdevice::DeviceType::SYSTEM, F_(send), System::command_send, FL_(send_cmd), CommandFlag::ADMIN_ONLY); Command::add(EMSdevice::DeviceType::SYSTEM, F_(send), System::command_send, FL_(send_cmd), CommandFlag::ADMIN_ONLY);
Command::add(EMSdevice::DeviceType::SYSTEM, F_(fetch), System::command_fetch, FL_(fetch_cmd), CommandFlag::ADMIN_ONLY); Command::add(EMSdevice::DeviceType::SYSTEM, F_(fetch), System::command_fetch, FL_(fetch_cmd), CommandFlag::ADMIN_ONLY);
Command::add(EMSdevice::DeviceType::SYSTEM, F_(restart), System::command_restart, FL_(restart_cmd), CommandFlag::ADMIN_ONLY); Command::add(EMSdevice::DeviceType::SYSTEM, F_(restart), System::command_restart, FL_(restart_cmd), CommandFlag::ADMIN_ONLY);
@@ -1689,6 +1691,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output
#endif #endif
node["modbusEnabled"] = settings.modbus_enabled; node["modbusEnabled"] = settings.modbus_enabled;
node["forceHeatingOff"] = settings.boiler_heatingoff; node["forceHeatingOff"] = settings.boiler_heatingoff;
node["developerMode"] = settings.developer_mode;
}); });
// Devices - show EMS devices if we have any // Devices - show EMS devices if we have any
@@ -2012,4 +2015,60 @@ bool System::uploadFirmwareURL(const char * url) {
return true; // OK return true; // OK
} }
// read command, e.g. read <deviceID> <type ID> [offset] [length] from console or API
bool System::readCommand(const char * data) {
// extract <deviceID> <type ID> [offset] [length] from string
char * p;
char value[11];
// make a copy so we can iterate, max 15 chars (XX XXXX XX XX)
char data_args[15];
strlcpy(data_args, data, sizeof(data_args));
uint8_t device_id = 0; // is in hex
uint16_t type_id = 0; // is in hex
uint8_t length = 0;
uint8_t offset = 0;
// first check deviceID
if ((p = strtok(data_args, " ,"))) { // delimiter comma or space
strlcpy(value, p, 10); // get string
device_id = (uint8_t)Helpers::hextoint(value); // convert hex to int
if (!EMSESP::valid_device(device_id)) {
LOG_ERROR("Invalid device ID (%d) for read command", device_id);
return false; // invalid device
}
}
// iterate until end
uint8_t num_args = 0;
while (p != 0) {
if ((p = strtok(nullptr, " ,"))) { // delimiter comma or space
strlcpy(value, p, 10); // get string
if (num_args == 0) {
type_id = (uint16_t)Helpers::hextoint(value); // convert hex to int
} else if (num_args == 1) {
offset = Helpers::atoint(value); // decimal
} else if (num_args == 2) {
length = Helpers::atoint(value); // decimal
}
num_args++;
}
}
if (num_args == 0) {
return false; // invalid number of arguments
}
EMSESP::send_read_request(type_id, device_id, offset, length, true);
EMSESP::set_read_id(type_id);
return true;
}
// system read command
bool System::command_read(const char * value, const int8_t id) {
return readCommand(value);
}
} // namespace emsesp } // namespace emsesp

View File

@@ -63,6 +63,7 @@ class System {
void loop(); void loop();
// commands // commands
static bool command_read(const char * value, const int8_t id);
static bool command_send(const char * value, const int8_t id); static bool command_send(const char * value, const int8_t id);
static bool command_publish(const char * value, const int8_t id); static bool command_publish(const char * value, const int8_t id);
static bool command_fetch(const char * value, const int8_t id); static bool command_fetch(const char * value, const int8_t id);
@@ -124,6 +125,8 @@ class System {
static bool is_valid_gpio(uint8_t pin, bool has_psram = false); static bool is_valid_gpio(uint8_t pin, bool has_psram = false);
static bool load_board_profile(std::vector<int8_t> & data, const std::string & board_profile); static bool load_board_profile(std::vector<int8_t> & data, const std::string & board_profile);
static bool readCommand(const char * data);
static void restart_requested(bool restart_requested) { static void restart_requested(bool restart_requested) {
restart_requested_ = restart_requested; restart_requested_ = restart_requested;
} }
@@ -170,6 +173,14 @@ class System {
readonly_mode_ = readonly_mode; readonly_mode_ = readonly_mode;
} }
bool developer_mode() {
return developer_mode_;
}
void developer_mode(bool developer_mode) {
developer_mode_ = developer_mode;
}
// Boolean Format API/MQTT // Boolean Format API/MQTT
uint8_t bool_format() { uint8_t bool_format() {
return bool_format_; return bool_format_;
@@ -398,6 +409,7 @@ class System {
uint16_t modbus_port_; uint16_t modbus_port_;
uint8_t modbus_max_clients_; uint8_t modbus_max_clients_;
uint32_t modbus_timeout_; uint32_t modbus_timeout_;
bool developer_mode_;
// ethernet // ethernet
uint8_t phy_type_; uint8_t phy_type_;

View File

@@ -638,7 +638,7 @@ uint16_t TxService::read_next_tx(const uint8_t offset, const uint8_t length) {
// some telegrams only reply with one byte less, but have higher offsets (boiler 0x10) // some telegrams only reply with one byte less, but have higher offsets (boiler 0x10)
// some reply with higher offset than requests and have not_set values intermediate (boiler 0xEA) // some reply with higher offset than requests and have not_set values intermediate (boiler 0xEA)
// We have th last byte received // We have the last byte received
if (offset + old_length >= telegram_last_->offset + telegram_last_->message_data[0]) { if (offset + old_length >= telegram_last_->offset + telegram_last_->message_data[0]) {
return 0; return 0;
} }

View File

@@ -973,16 +973,16 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
if (single) { if (single) {
// run dedicated tests only // run dedicated tests only
EMSESP::webCustomEntityService.test(); // custom entities // EMSESP::webCustomEntityService.test(); // custom entities
EMSESP::webCustomizationService.test(); // set customizations - this will overwrite any settings in the FS // EMSESP::webCustomizationService.test(); // set customizations - this will overwrite any settings in the FS
EMSESP::temperaturesensor_.test(); // add temperature sensors // EMSESP::temperaturesensor_.test(); // add temperature sensors
EMSESP::webSchedulerService.test(); // run scheduler tests, and conditions // EMSESP::webSchedulerService.test(); // run scheduler tests, and conditions
// request.url("/rest/deviceEntities"); // request.url("/rest/deviceEntities");
// EMSESP::webCustomizationService.device_entities(&request); // EMSESP::webCustomizationService.device_entities(&request);
request.url("/rest/dashboardData"); // request.url("/rest/dashboardData");
EMSESP::webDataService.dashboard_data(&request); // EMSESP::webDataService.dashboard_data(&request);
// COMMANDS // COMMANDS
// shell.invoke_command("call system fetch"); // shell.invoke_command("call system fetch");
@@ -999,28 +999,46 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
// EMSESP::webAPIService.webAPIService(&request); // EMSESP::webAPIService.webAPIService(&request);
// POST COMMANDS // POST COMMANDS
// request.method(HTTP_POST); request.method(HTTP_POST);
// char data1[] = "{\"device\":\"system\", \"cmd\":\"restart\",\"id\":-1}"; // char data1[] = "{\"device\":\"system\", \"cmd\":\"restart\",\"id\":-1}";
// deserializeJson(doc, data1); // deserializeJson(doc, data1);
// request.url("/api"); // request.url("/api");
// EMSESP::webAPIService.webAPIService(&request, doc.as<JsonVariant>()); // EMSESP::webAPIService.webAPIService(&request, doc.as<JsonVariant>());
// char data2[] = "{\"action\":\"customSupport\", \"param\":\"hello\"}"; char data2[] = "{\"action\":\"customSupport\", \"param\":\"hello\"}";
// deserializeJson(doc, data2); deserializeJson(doc, data2);
// request.url("/rest/action"); request.url("/rest/action");
// EMSESP::webStatusService.action(&request, doc.as<JsonVariant>()); EMSESP::webStatusService.action(&request, doc.as<JsonVariant>());
// char data3[] = "{\"action\":\"export\", \"param\":\"schedule\"}"; char data3[] = "{\"action\":\"export\", \"param\":\"schedule\"}";
// deserializeJson(doc, data3); deserializeJson(doc, data3);
// request.url("/rest/action"); request.url("/rest/action");
// EMSESP::webStatusService.action(&request, doc.as<JsonVariant>()); EMSESP::webStatusService.action(&request, doc.as<JsonVariant>());
// char data4[] = "{\"action\":\"export\", \"param\":\"allvalues\"}"; char data4[] = "{\"action\":\"export\", \"param\":\"allvalues\"}";
// deserializeJson(doc, data4); deserializeJson(doc, data4);
// request.url("/rest/action"); request.url("/rest/action");
// EMSESP::webStatusService.action(&request, doc.as<JsonVariant>()); EMSESP::webStatusService.action(&request, doc.as<JsonVariant>());
char data5[] = "{\"action\":\"checkUpgrade\", \"param\":\"3.7.0-dev.99\"}";
deserializeJson(doc, data5);
request.url("/rest/action");
EMSESP::webStatusService.action(&request, doc.as<JsonVariant>());
// char data6[] = "{\"device\":\"system\", \"cmd\":\"read\",\"value\":\"8 2 27 1\"}";
// deserializeJson(doc, data6);
// json = doc.as<JsonVariant>();
// request.url("/api");
// EMSESP::webAPIService.webAPIService(&request, json);
// char data7[] = "{\"device\":\"system\", \"cmd\":\"read\",\"value\":\"10 234\"}";
// deserializeJson(doc, data7);
// json = doc.as<JsonVariant>();
// request.url("/api");
// EMSESP::webAPIService.webAPIService(&request, json);
// shell.invoke_command("call system read \"8 2 27 1\"");
} else { } else {
EMSESP::webCustomEntityService.test(); // custom entities EMSESP::webCustomEntityService.test(); // custom entities

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.7.0-dev.46" #define EMSESP_APP_VERSION "3.7.0-dev.48"

View File

@@ -28,8 +28,9 @@ WebAPIService::WebAPIService(AsyncWebServer * server, SecurityManager * security
server->on(EMSESP_API_SERVICE_PATH, [this](AsyncWebServerRequest * request, JsonVariant json) { webAPIService(request, json); }); server->on(EMSESP_API_SERVICE_PATH, [this](AsyncWebServerRequest * request, JsonVariant json) { webAPIService(request, json); });
} }
// POST|GET /{device} // POST|GET api/
// POST|GET /{device}/{entity} // POST|GET api/{device}
// POST|GET api/{device}/{entity}
void WebAPIService::webAPIService(AsyncWebServerRequest * request, JsonVariant json) { void WebAPIService::webAPIService(AsyncWebServerRequest * request, JsonVariant json) {
JsonObject input; JsonObject input;
// if no body then treat it as a secure GET // if no body then treat it as a secure GET

View File

@@ -237,12 +237,13 @@ void WebLogService::transmit(const QueuedLogMessage & message) {
void WebLogService::getSetValues(AsyncWebServerRequest * request, JsonVariant json) { void WebLogService::getSetValues(AsyncWebServerRequest * request, JsonVariant json) {
if ((request->method() == HTTP_GET) || (!json.is<JsonObject>())) { if ((request->method() == HTTP_GET) || (!json.is<JsonObject>())) {
// GET - return the values // GET - return the values
auto * response = new AsyncJsonResponse(false); auto * response = new AsyncJsonResponse(false);
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
root["level"] = log_level(); root["level"] = log_level();
root["max_messages"] = maximum_log_messages(); root["max_messages"] = maximum_log_messages();
root["compact"] = compact(); root["compact"] = compact();
root["psram"] = (EMSESP::system_.PSram() > 0); root["psram"] = (EMSESP::system_.PSram() > 0);
root["developer_mode"] = EMSESP::system_.developer_mode();
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@@ -80,6 +80,7 @@ void WebSettings::read(WebSettings & settings, JsonObject root) {
root["modbus_port"] = settings.modbus_port; root["modbus_port"] = settings.modbus_port;
root["modbus_max_clients"] = settings.modbus_max_clients; root["modbus_max_clients"] = settings.modbus_max_clients;
root["modbus_timeout"] = settings.modbus_timeout; root["modbus_timeout"] = settings.modbus_timeout;
root["developer_mode"] = settings.developer_mode;
} }
// call on initialization and also when settings are updated via web or console // call on initialization and also when settings are updated via web or console
@@ -361,6 +362,9 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
settings.readonly_mode = root["readonly_mode"]; settings.readonly_mode = root["readonly_mode"];
EMSESP::system_.readonly_mode(settings.readonly_mode); EMSESP::system_.readonly_mode(settings.readonly_mode);
settings.developer_mode = root["developer_mode"];
EMSESP::system_.developer_mode(settings.developer_mode);
settings.bool_dashboard = root["bool_dashboard"] | EMSESP_DEFAULT_BOOL_FORMAT; settings.bool_dashboard = root["bool_dashboard"] | EMSESP_DEFAULT_BOOL_FORMAT;
EMSESP::system_.bool_dashboard(settings.bool_dashboard); EMSESP::system_.bool_dashboard(settings.bool_dashboard);

View File

@@ -65,10 +65,13 @@ class WebSettings {
uint8_t bool_format; uint8_t bool_format;
uint8_t bool_dashboard; uint8_t bool_dashboard;
uint8_t enum_format; uint8_t enum_format;
int8_t weblog_level;
uint8_t weblog_buffer; int8_t weblog_level;
bool weblog_compact; uint8_t weblog_buffer;
bool fahrenheit; bool weblog_compact;
bool fahrenheit;
bool modbus_enabled; bool modbus_enabled;
uint16_t modbus_port; uint16_t modbus_port;
uint8_t modbus_max_clients; uint8_t modbus_max_clients;
@@ -79,6 +82,8 @@ class WebSettings {
uint8_t eth_phy_addr; uint8_t eth_phy_addr;
uint8_t eth_clock_mode; uint8_t eth_clock_mode;
bool developer_mode; // developer mode
static void read(WebSettings & settings, JsonObject root); static void read(WebSettings & settings, JsonObject root);
static StateUpdateResult update(JsonObject root, WebSettings & settings); static StateUpdateResult update(JsonObject root, WebSettings & settings);

View File

@@ -154,29 +154,37 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json)
auto * response = new AsyncJsonResponse(); auto * response = new AsyncJsonResponse();
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
// get action and any optional param // param is optional - https://arduinojson.org/news/2024/09/18/arduinojson-7-2/
std::string action = json["action"]; std::string param;
std::string param = json["param"]; // is optional bool has_param = false;
JsonVariant param_optional = json["param"];
if (json["param"].is<const char *>()) {
param = param_optional.as<std::string>();
has_param = true;
} else {
has_param = false;
}
// check if we're authenticated for admin tasks, some actions are only for admins // check if we're authenticated for admin tasks, some actions are only for admins
Authentication authentication = _securityManager->authenticateRequest(request); Authentication authentication = _securityManager->authenticateRequest(request);
bool is_admin = AuthenticationPredicates::IS_ADMIN(authentication); bool is_admin = AuthenticationPredicates::IS_ADMIN(authentication);
bool ok = true; // call action command
bool ok = false;
std::string action = json["action"];
if (action == "checkUpgrade") { if (action == "checkUpgrade") {
ok = checkUpgrade(root, param); ok = checkUpgrade(root, param); // param could be empty, if so only send back version
} else if (action == "export") { } else if (action == "export") {
ok = exportData(root, param); if (has_param) {
ok = exportData(root, param);
}
} else if (action == "customSupport") { } else if (action == "customSupport") {
ok = customSupport(root); ok = customSupport(root);
} else if (action == "uploadURL" && is_admin) { } else if (action == "uploadURL" && is_admin) {
ok = uploadURL(param.c_str()); ok = uploadURL(param.c_str());
} }
#if defined(EMSESP_UNITY)
// store the result so we can test with Unity later
storeResponse(output);
#endif
#if defined(EMSESP_STANDALONE) && !defined(EMSESP_UNITY) #if defined(EMSESP_STANDALONE) && !defined(EMSESP_UNITY)
Serial.printf("%sweb output: %s[%s]", COLOR_WHITE, COLOR_BRIGHT_CYAN, request->url().c_str()); Serial.printf("%sweb output: %s[%s]", COLOR_WHITE, COLOR_BRIGHT_CYAN, request->url().c_str());
Serial.printf(" %s(%d)%s ", ok ? COLOR_BRIGHT_GREEN : COLOR_BRIGHT_RED, ok ? 200 : 400, COLOR_YELLOW); Serial.printf(" %s(%d)%s ", ok ? COLOR_BRIGHT_GREEN : COLOR_BRIGHT_RED, ok ? 200 : 400, COLOR_YELLOW);
@@ -195,18 +203,21 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json)
} }
// action = checkUpgrade // action = checkUpgrade
// returns true if there is an upgrade available
bool WebStatusService::checkUpgrade(JsonObject root, std::string & latest_version) { bool WebStatusService::checkUpgrade(JsonObject root, std::string & latest_version) {
version::Semver200_version settings_version(EMSESP_APP_VERSION); root["emsesp_version"] = EMSESP_APP_VERSION;
version::Semver200_version this_version(latest_version);
if (!latest_version.empty()) {
#if defined(EMSESP_DEBUG) #if defined(EMSESP_DEBUG)
emsesp::EMSESP::logger().debug("Checking for upgrade: %s > %s", EMSESP_APP_VERSION, latest_version.c_str()); emsesp::EMSESP::logger().debug("Checking for upgrade: %s > %s", EMSESP_APP_VERSION, latest_version.c_str());
#endif #endif
root["upgradeable"] = (this_version > settings_version); version::Semver200_version settings_version(EMSESP_APP_VERSION);
version::Semver200_version this_version(latest_version);
return true; root["upgradeable"] = (this_version > settings_version);
}
return true; // always ok
} }
// action = allvalues // action = allvalues
@@ -261,8 +272,9 @@ bool WebStatusService::exportData(JsonObject root, std::string & type) {
root.clear(); // don't need the "type" key added to the output root.clear(); // don't need the "type" key added to the output
allvalues(root); allvalues(root);
} else { } else {
return false; return false; // error
} }
return true; return true;
} }

View File

@@ -3,7 +3,8 @@
# Open this file in VSC, modify the token, go to the API call and click on 'Send Request' (or Ctrl+Alt+R) # Open this file in VSC, modify the token, go to the API call and click on 'Send Request' (or Ctrl+Alt+R)
# The response will be shown in the right panel # The response will be shown in the right panel
@host = http://ems-esp.local # @host = http://ems-esp.local
@host = http://192.168.1.206
@host_dev = http://10.10.10.175 @host_dev = http://10.10.10.175
@host_standalone = http://localhost:3080 @host_standalone = http://localhost:3080
@host_standalone2 = http://localhost:3082 @host_standalone2 = http://localhost:3082

31
test/test_api/api_test.sh Executable file
View File

@@ -0,0 +1,31 @@
#!/bin/sh
#
# Command line test for the API
#
# EMS_ESP API
emsesp_url="http://192.168.1.206"
emsesp_token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiYWRtaW4iOnRydWV9.2bHpWya2C7Q12WjNUBD6_7N3RCD7CMl-EGhyQVzFdDg"
curl -X GET ${emsesp_url}/api/system/info
echo "\n"
curl -X POST \
-H "Authorization: Bearer ${emsesp_token}" \
-H "Content-Type: application/json" \
-d '{"data":"8 1"}' \
${emsesp_url}/api/system/read
echo "\n"
# HA API
ha_url="http://192.168.1.42:8123"
ha_token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIwMzMyZjU1MjhlZmM0NGIyOTgyMjIxNThiODU1NDkyNSIsImlhdCI6MTcyMTMwNDg2NSwiZXhwIjoyMDM2NjY0ODY1fQ.Q-Y7E_i7clH3ff4Ma-OMmhZfbN7aMi_CahKwmoar"
# curl -X POST \
# ${ha_url}/api/services/script/test_notify \
# -H "Authorization: Bearer ${ha_token}" \
# -H "Content-Type: application/json"

View File

@@ -40,9 +40,9 @@ void test_2() {
"off\",\"heatingtemp\":\"heating temperature\",\"maintenance\":\"maintenance scheduled\",\"maintenancedate\":\"next maintenance " "off\",\"heatingtemp\":\"heating temperature\",\"maintenance\":\"maintenance scheduled\",\"maintenancedate\":\"next maintenance "
"date\",\"maintenancetime\":\"time to next maintenance\",\"nofrostmode\":\"nofrost mode\",\"nofrosttemp\":\"nofrost " "date\",\"maintenancetime\":\"time to next maintenance\",\"nofrostmode\":\"nofrost mode\",\"nofrosttemp\":\"nofrost "
"temperature\",\"nompower\":\"nominal Power\",\"nrgheat\":\"energy heating\",\"pumpcharacter\":\"boiler pump characteristic\",\"pumpdelay\":\"pump " "temperature\",\"nompower\":\"nominal Power\",\"nrgheat\":\"energy heating\",\"pumpcharacter\":\"boiler pump characteristic\",\"pumpdelay\":\"pump "
"delay\",\"pumpmode\":\"boiler pump mode\",\"pumpmodmax\":\"boiler pump max power\",\"pumpmodmin\":\"boiler pump min " "delay\",\"pumpmode\":\"boiler pump mode\",\"pumpmodmax\":\"boiler pump max power\",\"pumpmodmin\":\"boiler pump min power\",\"pumpontemp\":\"pump "
"power\",\"reset\":\"reset\",\"selburnpow\":\"burner selected max power\",\"selflowtemp\":\"selected flow temperature\",\"summertemp\":\"summer " "logic temperature\",\"reset\":\"reset\",\"selburnpow\":\"burner selected max power\",\"selflowtemp\":\"selected flow "
"temperature\"}]"; "temperature\",\"summertemp\":\"summer temperature\"}]";
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/boiler/commands")); TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/boiler/commands"));
} }
@@ -149,8 +149,8 @@ void test_17() {
} }
void test_18() { void test_18() {
auto expected_response = auto expected_response = "[{\"name\":\"seltemp\",\"fullname\":\"seltemp\",\"storage\":\"ram\",\"type\":\"number\",\"readable\":true,\"writeable\":true,"
"[{\"name\":\"seltemp\",\"storage\":\"ram\",\"type\":\"number\",\"readable\":true,\"writeable\":true,\"visible\":true,\"value\":\"14\"}]"; "\"visible\":true,\"value\":\"14\"}]";
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/custom/seltemp")); TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/custom/seltemp"));
} }
@@ -163,17 +163,20 @@ void test_19() {
"\"entityFormat\":1,\"base\":\"ems-esp\",\"discoveryPrefix\":\"homeassistant\",\"discoveryType\":0,\"nestedFormat\":1,\"haEnabled\":true,\"mqttQos\":0," "\"entityFormat\":1,\"base\":\"ems-esp\",\"discoveryPrefix\":\"homeassistant\",\"discoveryType\":0,\"nestedFormat\":1,\"haEnabled\":true,\"mqttQos\":0,"
"\"mqttRetain\":false,\"publishTimeHeartbeat\":60,\"publishTimeBoiler\":10,\"publishTimeThermostat\":10,\"publishTimeSolar\":10,\"publishTimeMixer\":" "\"mqttRetain\":false,\"publishTimeHeartbeat\":60,\"publishTimeBoiler\":10,\"publishTimeThermostat\":10,\"publishTimeSolar\":10,\"publishTimeMixer\":"
"10,\"publishTimeWater\":0,\"publishTimeOther\":10,\"publishTimeSensor\":10,\"publishSingle\":false,\"publish2command\":false,\"sendResponse\":false}," "10,\"publishTimeWater\":0,\"publishTimeOther\":10,\"publishTimeSensor\":10,\"publishSingle\":false,\"publish2command\":false,\"sendResponse\":false},"
"\"syslog\":{\"enabled\":false},\"sensor\":{\"temperatureSensors\":2,\"temperatureSensorReads\":0,\"temperatureSensorFails\":0,\"analogSensors\":2," "\"syslog\":{\"enabled\":false},\"sensor\":{\"temperatureSensors\":2,\"temperatureSensorReads\":0,\"temperatureSensorFails\":0,\"analogSensors\":3,"
"\"analogSensorReads\":0,\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":" "\"analogSensorReads\":0,\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":"
"\"Buderus\",\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0," "\"Buderus\",\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0,"
"\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":8,\"emsBusID\":11," "\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":8,\"emsBusID\":11,"
"\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":" "\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":"
"false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true," "false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true,"
"\"maxWebLogBuffer\":25,\"webLogBuffer\":0,\"modbusEnabled\":false,\"forceHeatingOff\":false},\"devices\":[{\"type\":\"boiler\",\"name\":\"Custom " "\"maxWebLogBuffer\":25,\"webLogBuffer\":0,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":"
"Name!!\",\"deviceID\":\"0x08\",\"productID\":123,\"brand\":\"\",\"version\":\"01.00\",\"entities\":37,\"handlersReceived\":\"0x18\"," "\"boiler\",\"name\":\"My Custom "
"Boiler\",\"deviceID\":\"0x08\",\"productID\":123,\"brand\":\"\",\"version\":\"01.00\",\"entities\":37,\"handlersReceived\":\"0x18\","
"\"handlersFetched\":\"0x14 0x33\",\"handlersPending\":\"0xBF 0x10 0x11 0xC2 0x15 0x1C 0x19 0x1A 0x35 0x34 0x2A 0xD1 0xE3 0xE4 0xE5 0xE9 0x2E " "\"handlersFetched\":\"0x14 0x33\",\"handlersPending\":\"0xBF 0x10 0x11 0xC2 0x15 0x1C 0x19 0x1A 0x35 0x34 0x2A 0xD1 0xE3 0xE4 0xE5 0xE9 0x2E "
"0x3B\"},{\"type\":\"thermostat\",\"name\":\"FW120\",\"deviceID\":\"0x10\",\"productID\":192,\"brand\":\"\",\"version\":\"01.00\",\"entities\":15," "0x3B\"},{\"type\":\"thermostat\",\"name\":\"FW120\",\"deviceID\":\"0x10\",\"productID\":192,\"brand\":\"\",\"version\":\"01.00\",\"entities\":15,"
"\"handlersReceived\":\"0x016F\",\"handlersFetched\":\"0x0170 0x0171\",\"handlersPending\":\"0xA3 0x06 0xA2 0x12 0x13 0x0172 0x0165 0x0168\"}]}]"; "\"handlersReceived\":\"0x016F\",\"handlersFetched\":\"0x0170 0x0171\",\"handlersPending\":\"0xA3 0x06 0xA2 0x12 0x13 0x0172 0x0165 "
"0x0168\"},{\"type\":\"temperaturesensor\",\"name\":\"temperaturesensor\",\"entities\":2},{\"type\":\"analogsensor\",\"name\":\"analogsensor\","
"\"entities\":3},{\"type\":\"scheduler\",\"name\":\"scheduler\",\"entities\":2},{\"type\":\"custom\",\"name\":\"custom\",\"entities\":4}]}]";
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/system")); TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/system"));
} }
@@ -186,17 +189,20 @@ void test_20() {
"\"entityFormat\":1,\"base\":\"ems-esp\",\"discoveryPrefix\":\"homeassistant\",\"discoveryType\":0,\"nestedFormat\":1,\"haEnabled\":true,\"mqttQos\":0," "\"entityFormat\":1,\"base\":\"ems-esp\",\"discoveryPrefix\":\"homeassistant\",\"discoveryType\":0,\"nestedFormat\":1,\"haEnabled\":true,\"mqttQos\":0,"
"\"mqttRetain\":false,\"publishTimeHeartbeat\":60,\"publishTimeBoiler\":10,\"publishTimeThermostat\":10,\"publishTimeSolar\":10,\"publishTimeMixer\":" "\"mqttRetain\":false,\"publishTimeHeartbeat\":60,\"publishTimeBoiler\":10,\"publishTimeThermostat\":10,\"publishTimeSolar\":10,\"publishTimeMixer\":"
"10,\"publishTimeWater\":0,\"publishTimeOther\":10,\"publishTimeSensor\":10,\"publishSingle\":false,\"publish2command\":false,\"sendResponse\":false}," "10,\"publishTimeWater\":0,\"publishTimeOther\":10,\"publishTimeSensor\":10,\"publishSingle\":false,\"publish2command\":false,\"sendResponse\":false},"
"\"syslog\":{\"enabled\":false},\"sensor\":{\"temperatureSensors\":2,\"temperatureSensorReads\":0,\"temperatureSensorFails\":0,\"analogSensors\":2," "\"syslog\":{\"enabled\":false},\"sensor\":{\"temperatureSensors\":2,\"temperatureSensorReads\":0,\"temperatureSensorFails\":0,\"analogSensors\":3,"
"\"analogSensorReads\":0,\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":" "\"analogSensorReads\":0,\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":"
"\"Buderus\",\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0," "\"Buderus\",\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0,"
"\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":8,\"emsBusID\":11," "\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":8,\"emsBusID\":11,"
"\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":" "\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":"
"false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true," "false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true,"
"\"maxWebLogBuffer\":25,\"webLogBuffer\":0,\"modbusEnabled\":false,\"forceHeatingOff\":false},\"devices\":[{\"type\":\"boiler\",\"name\":\"Custom " "\"maxWebLogBuffer\":25,\"webLogBuffer\":0,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":"
"Name!!\",\"deviceID\":\"0x08\",\"productID\":123,\"brand\":\"\",\"version\":\"01.00\",\"entities\":37,\"handlersReceived\":\"0x18\"," "\"boiler\",\"name\":\"My Custom "
"Boiler\",\"deviceID\":\"0x08\",\"productID\":123,\"brand\":\"\",\"version\":\"01.00\",\"entities\":37,\"handlersReceived\":\"0x18\","
"\"handlersFetched\":\"0x14 0x33\",\"handlersPending\":\"0xBF 0x10 0x11 0xC2 0x15 0x1C 0x19 0x1A 0x35 0x34 0x2A 0xD1 0xE3 0xE4 0xE5 0xE9 0x2E " "\"handlersFetched\":\"0x14 0x33\",\"handlersPending\":\"0xBF 0x10 0x11 0xC2 0x15 0x1C 0x19 0x1A 0x35 0x34 0x2A 0xD1 0xE3 0xE4 0xE5 0xE9 0x2E "
"0x3B\"},{\"type\":\"thermostat\",\"name\":\"FW120\",\"deviceID\":\"0x10\",\"productID\":192,\"brand\":\"\",\"version\":\"01.00\",\"entities\":15," "0x3B\"},{\"type\":\"thermostat\",\"name\":\"FW120\",\"deviceID\":\"0x10\",\"productID\":192,\"brand\":\"\",\"version\":\"01.00\",\"entities\":15,"
"\"handlersReceived\":\"0x016F\",\"handlersFetched\":\"0x0170 0x0171\",\"handlersPending\":\"0xA3 0x06 0xA2 0x12 0x13 0x0172 0x0165 0x0168\"}]}]"; "\"handlersReceived\":\"0x016F\",\"handlersFetched\":\"0x0170 0x0171\",\"handlersPending\":\"0xA3 0x06 0xA2 0x12 0x13 0x0172 0x0165 "
"0x0168\"},{\"type\":\"temperaturesensor\",\"name\":\"temperaturesensor\",\"entities\":2},{\"type\":\"analogsensor\",\"name\":\"analogsensor\","
"\"entities\":3},{\"type\":\"scheduler\",\"name\":\"scheduler\",\"entities\":2},{\"type\":\"custom\",\"name\":\"custom\",\"entities\":4}]}]";
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/system/info")); TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/system/info"));
} }
@@ -228,8 +234,8 @@ void test_25() {
} }
void test_26() { void test_26() {
auto expected_response = "[{\"name\":\"test_scheduler\",\"type\":\"boolean\",\"value\":\"on\",\"time\":\"12:00\",\"command\":\"system/" auto expected_response = "[{\"name\":\"test_scheduler\",\"fullname\":\"test_scheduler\",\"type\":\"boolean\",\"value\":\"on\",\"time\":\"12:00\","
"fetch\",\"cmd_data\":\"10\",\"readable\":true,\"writeable\":true,\"visible\":true}]"; "\"command\":\"system/fetch\",\"cmd_data\":\"10\",\"readable\":true,\"writeable\":true,\"visible\":true}]";
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/scheduler/test_scheduler")); TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/scheduler/test_scheduler"));
} }
@@ -244,14 +250,14 @@ void test_28() {
} }
void test_29() { void test_29() {
auto expected_response = auto expected_response = "[{\"id\":\"0B_0C0D_0E0F_1011\",\"name\":\"test_tempsensor2\",\"fullname\":\"test_tempsensor2\",\"value\":45.6,\"type\":"
"[{\"id\":\"0B_0C0D_0E0F_1011\",\"name\":\"test_tempsensor2\",\"value\":45.6,\"type\":\"number\",\"uom\":\"°C\",\"writeable\":false}]"; "\"number\",\"uom\":\"°C\",\"readable\":true,\"writeable\":false,\"visible\":true}]";
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/temperaturesensor/test_tempsensor2")); TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/temperaturesensor/test_tempsensor2"));
} }
void test_30() { void test_30() {
auto expected_response = auto expected_response = "[{\"id\":\"0B_0C0D_0E0F_1011\",\"name\":\"test_tempsensor2\",\"fullname\":\"test_tempsensor2\",\"value\":45.6,\"type\":"
"[{\"id\":\"0B_0C0D_0E0F_1011\",\"name\":\"test_tempsensor2\",\"value\":45.6,\"type\":\"number\",\"uom\":\"°C\",\"writeable\":false}]"; "\"number\",\"uom\":\"°C\",\"readable\":true,\"writeable\":false,\"visible\":true}]";
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/temperaturesensor/0B_0C0D_0E0F_1011")); TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/temperaturesensor/0B_0C0D_0E0F_1011"));
} }
@@ -261,18 +267,18 @@ void test_31() {
} }
void test_32() { void test_32() {
auto expected_response = "[{\"test_analogsensor1\":0,\"test_analogsensor2\":1}]"; auto expected_response = "[{\"test_analogsensor1\":0,\"test_analogsensor2\":1,\"test_analogsensor3\":0}]";
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/analogsensor")); TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/analogsensor"));
} }
void test_33() { void test_33() {
auto expected_response = "[{\"test_analogsensor1\":0,\"test_analogsensor2\":1}]"; auto expected_response = "[{\"test_analogsensor1\":0,\"test_analogsensor2\":1,\"test_analogsensor3\":0}]";
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/analogsensor/info")); TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/analogsensor/info"));
} }
void test_34() { void test_34() {
auto expected_response = auto expected_response = "[{\"name\":\"test_analogsensor1\",\"fullname\":\"test_analogsensor1\",\"gpio\":36,\"type\":\"number\",\"analog\":\"adc\","
"[{\"gpio\":36,\"type\":\"number\",\"analog\":\"adc\",\"value\":0,\"writeable\":false,\"offset\":0,\"factor\":0.1,\"uom\":\"mV\"}]"; "\"value\":0,\"readable\":true,\"writeable\":false,\"visible\":true,\"offset\":0,\"factor\":0.1,\"uom\":\"mV\"}]";
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/analogsensor/test_analogsensor1")); TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/analogsensor/test_analogsensor1"));
} }
@@ -287,12 +293,12 @@ void test_36() {
} }
void test_37() { void test_37() {
auto expected_response = "[{\"message\":\"no bad in boiler\"}]"; auto expected_response = "[{\"message\":\"no bad/value in boiler\"}]";
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/boiler/bad/value")); TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/boiler/bad/value"));
} }
void test_38() { void test_38() {
auto expected_response = "[{\"message\":\"Command comfort failed (Error)\"}]"; auto expected_response = "[{\"message\":\"no valu in comfort\"}]";
TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/boiler/comfort/valu")); TEST_ASSERT_EQUAL_STRING(expected_response, call_url("/api/boiler/comfort/valu"));
} }