mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 08:19:52 +03:00
Merge branch 'dev' into dev
This commit is contained in:
@@ -9,8 +9,6 @@ import * as AuthenticationApi from './api/authentication';
|
||||
import { PROJECT_NAME } from './api/env';
|
||||
import { AuthenticationContext } from './contexts/authentication';
|
||||
|
||||
import { AxiosError } from 'axios';
|
||||
|
||||
import { extractErrorMessage, onEnterCallback, updateValue } from './utils';
|
||||
import { SignInRequest } from './types';
|
||||
import { ValidatedTextField } from './components';
|
||||
@@ -24,6 +22,8 @@ import { ReactComponent as NLflag } from './i18n/NL.svg';
|
||||
import { ReactComponent as DEflag } from './i18n/DE.svg';
|
||||
import { ReactComponent as GBflag } from './i18n/GB.svg';
|
||||
import { ReactComponent as SEflag } from './i18n/SE.svg';
|
||||
import { ReactComponent as PLflag } from './i18n/PL.svg';
|
||||
import { ReactComponent as NOflag } from './i18n/NO.svg';
|
||||
|
||||
const SignIn: FC = () => {
|
||||
const authenticationContext = useContext(AuthenticationContext);
|
||||
@@ -56,8 +56,8 @@ const SignIn: FC = () => {
|
||||
try {
|
||||
const { data: loginResponse } = await AuthenticationApi.signIn(signInRequest);
|
||||
authenticationContext.signIn(loginResponse.access_token);
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError) {
|
||||
} catch (error) {
|
||||
if (error.response) {
|
||||
if (error.response?.status === 401) {
|
||||
enqueueSnackbar(LL.INVALID_LOGIN(), { variant: 'warning' });
|
||||
}
|
||||
@@ -125,6 +125,14 @@ const SignIn: FC = () => {
|
||||
<SEflag style={{ width: 24 }} />
|
||||
SE
|
||||
</Button>
|
||||
<Button size="small" variant={locale === 'pl' ? 'contained' : 'outlined'} onClick={() => selectLocale('pl')}>
|
||||
<PLflag style={{ width: 24 }} />
|
||||
PL
|
||||
</Button>
|
||||
<Button size="small" variant={locale === 'no' ? 'contained' : 'outlined'} onClick={() => selectLocale('no')}>
|
||||
<NOflag style={{ width: 24 }} />
|
||||
NO
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
<ValidatedTextField
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import axios, { AxiosPromise, CancelToken } from 'axios';
|
||||
import axios, { AxiosPromise, CancelToken, AxiosProgressEvent } from 'axios';
|
||||
|
||||
import { decode } from '@msgpack/msgpack';
|
||||
|
||||
@@ -89,7 +89,7 @@ function calculateEventSourceRoot(endpointPath: string) {
|
||||
|
||||
export interface FileUploadConfig {
|
||||
cancelToken?: CancelToken;
|
||||
onUploadProgress?: (progressEvent: ProgressEvent) => void;
|
||||
onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;
|
||||
}
|
||||
|
||||
export const startUploadFile = (url: string, file: File, config?: FileUploadConfig): AxiosPromise<void> => {
|
||||
|
||||
@@ -93,7 +93,7 @@ const LayoutAuthMenu: FC = () => {
|
||||
<PLflag style={{ width: 16, verticalAlign: 'middle' }} />
|
||||
PL
|
||||
</MenuItem>
|
||||
<MenuItem key="no" value="no" disabled>
|
||||
<MenuItem key="no" value="no">
|
||||
<NOflag style={{ width: 16, verticalAlign: 'middle' }} />
|
||||
NO
|
||||
</MenuItem>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { FC, Fragment } from 'react';
|
||||
import { useDropzone, DropzoneState } from 'react-dropzone';
|
||||
|
||||
import { AxiosProgressEvent } from 'axios';
|
||||
|
||||
import { Box, Button, LinearProgress, Theme, Typography, useTheme } from '@mui/material';
|
||||
|
||||
import CloudUploadIcon from '@mui/icons-material/CloudUpload';
|
||||
@@ -8,8 +10,6 @@ import CancelIcon from '@mui/icons-material/Cancel';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
|
||||
const progressPercentage = (progress: ProgressEvent) => Math.round((progress.loaded * 100) / progress.total);
|
||||
|
||||
const getBorderColor = (theme: Theme, props: DropzoneState) => {
|
||||
if (props.isDragAccept) {
|
||||
return theme.palette.success.main;
|
||||
@@ -27,7 +27,7 @@ export interface SingleUploadProps {
|
||||
onDrop: (acceptedFiles: File[]) => void;
|
||||
onCancel: () => void;
|
||||
uploading: boolean;
|
||||
progress?: ProgressEvent;
|
||||
progress?: AxiosProgressEvent;
|
||||
}
|
||||
|
||||
const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, uploading, progress }) => {
|
||||
@@ -47,8 +47,8 @@ const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, uploading, prog
|
||||
|
||||
const progressText = () => {
|
||||
if (uploading) {
|
||||
if (progress?.lengthComputable) {
|
||||
return LL.UPLOADING() + `: ${progressPercentage(progress)}%`;
|
||||
if (progress?.total) {
|
||||
return LL.UPLOADING() + ': ' + Math.round((progress.loaded * 100) / progress.total) + '%';
|
||||
}
|
||||
return LL.UPLOADING() + `\u2026`;
|
||||
}
|
||||
@@ -80,8 +80,8 @@ const SingleUpload: FC<SingleUploadProps> = ({ onDrop, onCancel, uploading, prog
|
||||
<Fragment>
|
||||
<Box width="100%" p={2}>
|
||||
<LinearProgress
|
||||
variant={!progress || progress.lengthComputable ? 'determinate' : 'indeterminate'}
|
||||
value={!progress ? 0 : progress.lengthComputable ? progressPercentage(progress) : 0}
|
||||
variant={!progress || progress.total ? 'determinate' : 'indeterminate'}
|
||||
value={!progress ? 0 : progress.total ? Math.round((progress.loaded * 100) / progress.total) : 0}
|
||||
/>
|
||||
</Box>
|
||||
<Button startIcon={<CancelIcon />} variant="outlined" color="secondary" onClick={onCancel}>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import axios, { AxiosPromise, CancelTokenSource } from 'axios';
|
||||
import axios, { AxiosPromise, CancelTokenSource, AxiosProgressEvent } from 'axios';
|
||||
import { useSnackbar } from 'notistack';
|
||||
|
||||
import { extractErrorMessage } from '../../utils';
|
||||
@@ -16,7 +16,7 @@ const useFileUpload = ({ upload }: MediaUploadOptions) => {
|
||||
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
const [uploading, setUploading] = useState<boolean>(false);
|
||||
const [uploadProgress, setUploadProgress] = useState<ProgressEvent>();
|
||||
const [uploadProgress, setUploadProgress] = useState<AxiosProgressEvent>();
|
||||
const [uploadCancelToken, setUploadCancelToken] = useState<CancelTokenSource>();
|
||||
|
||||
const resetUploadingStates = () => {
|
||||
@@ -47,7 +47,7 @@ const useFileUpload = ({ upload }: MediaUploadOptions) => {
|
||||
});
|
||||
resetUploadingStates();
|
||||
enqueueSnackbar(LL.UPLOAD() + ' ' + LL.SUCCESSFUL(), { variant: 'success' });
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
if (axios.isCancel(error)) {
|
||||
enqueueSnackbar(LL.UPLOAD() + ' ' + LL.ABORTED(), { variant: 'warning' });
|
||||
} else {
|
||||
|
||||
@@ -28,7 +28,7 @@ const Authentication: FC<RequiredChildrenProps> = ({ children }) => {
|
||||
const decodedMe = AuthenticationApi.decodeMeJWT(accessToken);
|
||||
setMe(decodedMe);
|
||||
enqueueSnackbar(LL.LOGGED_IN({ name: decodedMe.username }), { variant: 'success' });
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
setMe(undefined);
|
||||
throw new Error('Failed to parse JWT');
|
||||
}
|
||||
@@ -54,7 +54,7 @@ const Authentication: FC<RequiredChildrenProps> = ({ children }) => {
|
||||
await AuthenticationApi.verifyAuthorization();
|
||||
setMe(AuthenticationApi.decodeMeJWT(accessToken));
|
||||
setInitialized(true);
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
setMe(undefined);
|
||||
setInitialized(true);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ const FeaturesLoader: FC<RequiredChildrenProps> = (props) => {
|
||||
try {
|
||||
const response = await FeaturesApi.readFeatures();
|
||||
setFeatures(response.data);
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
setErrorMessage(extractErrorMessage(error, 'Failed to fetch application details.'));
|
||||
}
|
||||
}, []);
|
||||
|
||||
@@ -5,6 +5,7 @@ import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import ReportIcon from '@mui/icons-material/Report';
|
||||
import SpeakerNotesOffIcon from '@mui/icons-material/SpeakerNotesOff';
|
||||
import AutoAwesomeMotionIcon from '@mui/icons-material/AutoAwesomeMotion';
|
||||
|
||||
import { ButtonRow, FormLoader, SectionContent } from '../../components';
|
||||
import { MqttStatus, MqttDisconnectReason } from '../../types';
|
||||
@@ -31,6 +32,12 @@ export const mqttPublishHighlight = ({ mqtt_fails }: MqttStatus, theme: Theme) =
|
||||
return theme.palette.error.main;
|
||||
};
|
||||
|
||||
export const mqttQueueHighlight = ({ mqtt_queued }: MqttStatus, theme: Theme) => {
|
||||
if (mqtt_queued <= 1) return theme.palette.success.main;
|
||||
|
||||
return theme.palette.warning.main;
|
||||
};
|
||||
|
||||
const MqttStatusForm: FC = () => {
|
||||
const { loadData, data, errorMessage } = useRest<MqttStatus>({ read: MqttApi.readMqttStatus });
|
||||
|
||||
@@ -38,14 +45,14 @@ const MqttStatusForm: FC = () => {
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
const mqttStatus = ({ enabled, connected }: MqttStatus) => {
|
||||
const mqttStatus = ({ enabled, connected, connect_count }: MqttStatus) => {
|
||||
if (!enabled) {
|
||||
return LL.NOT_ENABLED();
|
||||
}
|
||||
if (connected) {
|
||||
return LL.CONNECTED();
|
||||
return LL.CONNECTED() + (connect_count > 1 ? ' (' + connect_count + ')' : '');
|
||||
}
|
||||
return LL.DISCONNECTED();
|
||||
return LL.DISCONNECTED() + (connect_count > 1 ? ' (' + connect_count + ')' : '');
|
||||
};
|
||||
|
||||
const disconnectReason = ({ disconnect_reason }: MqttStatus) => {
|
||||
@@ -77,36 +84,44 @@ const MqttStatusForm: FC = () => {
|
||||
}
|
||||
|
||||
const renderConnectionStatus = () => {
|
||||
if (data.connected) {
|
||||
return (
|
||||
<>
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar>#</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary="Client ID" secondary={data.client_id} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar sx={{ bgcolor: mqttPublishHighlight(data, theme) }}>
|
||||
<SpeakerNotesOffIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={'MQTT Publish ' + LL.ERRORS()} secondary={data.mqtt_fails} />
|
||||
</ListItem>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{!data.connected && (
|
||||
<>
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar>
|
||||
<ReportIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={LL.DISCONNECT_REASON()} secondary={disconnectReason(data)} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
</>
|
||||
)}
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar>
|
||||
<ReportIcon />
|
||||
<Avatar>#</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary="Client ID" secondary={data.client_id} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar sx={{ bgcolor: mqttQueueHighlight(data, theme) }}>
|
||||
<AutoAwesomeMotionIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={LL.DISCONNECT_REASON()} secondary={disconnectReason(data)} />
|
||||
<ListItemText primary="MQTT Queue" secondary={data.mqtt_queued} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar sx={{ bgcolor: mqttPublishHighlight(data, theme) }}>
|
||||
<SpeakerNotesOffIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={'MQTT ' + LL.ERRORS()} secondary={data.mqtt_fails} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
</>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { useEffect, FC, useState, useCallback, useRef } from 'react';
|
||||
import { useSnackbar } from 'notistack';
|
||||
|
||||
import { AxiosError } from 'axios';
|
||||
|
||||
import { Button } from '@mui/material';
|
||||
import PermScanWifiIcon from '@mui/icons-material/PermScanWifi';
|
||||
|
||||
@@ -57,8 +55,8 @@ const WiFiNetworkScanner: FC = () => {
|
||||
newNetworkList.networks.sort(compareNetworks);
|
||||
setNetworkList(newNetworkList);
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError) {
|
||||
} catch (error) {
|
||||
if (error.response) {
|
||||
finishedWithError(LL.PROBLEM_LOADING() + ' ' + error.response?.data.message);
|
||||
} else {
|
||||
finishedWithError(LL.PROBLEM_LOADING());
|
||||
@@ -73,8 +71,8 @@ const WiFiNetworkScanner: FC = () => {
|
||||
try {
|
||||
await NetworkApi.scanNetworks();
|
||||
setTimeout(pollNetworkList, POLLING_FREQUENCY);
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof AxiosError) {
|
||||
} catch (error) {
|
||||
if (error.response) {
|
||||
finishedWithError(LL.PROBLEM_LOADING() + ' ' + error.response?.data.message);
|
||||
} else {
|
||||
finishedWithError(LL.PROBLEM_LOADING());
|
||||
|
||||
@@ -91,7 +91,7 @@ const NTPStatusForm: FC = () => {
|
||||
enqueueSnackbar(LL.TIME_SET(), { variant: 'success' });
|
||||
setSettingTime(false);
|
||||
loadData();
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
} finally {
|
||||
setProcessing(false);
|
||||
|
||||
@@ -37,7 +37,7 @@ const GenerateToken: FC<GenerateTokenProps> = ({ username, onClose }) => {
|
||||
const getToken = useCallback(async () => {
|
||||
try {
|
||||
setToken((await SecurityApi.generateToken(username)).data);
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
}
|
||||
}, [username, enqueueSnackbar, LL]);
|
||||
|
||||
@@ -50,7 +50,7 @@ const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
||||
} else {
|
||||
saveFile(response.data, 'settings');
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||
}
|
||||
};
|
||||
@@ -63,7 +63,7 @@ const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
||||
} else {
|
||||
saveFile(response.data, 'customizations');
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@ const RestartMonitor: FC = () => {
|
||||
try {
|
||||
await SystemApi.readSystemStatus(POLL_TIMEOUT);
|
||||
document.location.href = '/fileUpdated';
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
if (new Date().getTime() < timeoutAt.current) {
|
||||
setTimeoutId(setTimeout(poll.current, POLL_INTERVAL));
|
||||
} else {
|
||||
|
||||
@@ -111,7 +111,7 @@ const SystemLog: FC = () => {
|
||||
if (response.status !== 200) {
|
||||
enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' });
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
}
|
||||
}
|
||||
@@ -163,7 +163,7 @@ const SystemLog: FC = () => {
|
||||
const fetchLog = useCallback(async () => {
|
||||
try {
|
||||
setLogEntries((await SystemApi.readLogEntries()).data);
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||
}
|
||||
}, [LL]);
|
||||
|
||||
@@ -86,7 +86,7 @@ const SystemStatusForm: FC = () => {
|
||||
try {
|
||||
await SystemApi.restart();
|
||||
enqueueSnackbar(LL.APPLICATION_RESTARTING(), { variant: 'info' });
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||
} finally {
|
||||
setConfirmRestart(false);
|
||||
@@ -180,7 +180,7 @@ const SystemStatusForm: FC = () => {
|
||||
try {
|
||||
await SystemApi.factoryReset();
|
||||
enqueueSnackbar(LL.SYSTEM_FACTORY_TEXT(), { variant: 'info' });
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
} finally {
|
||||
setConfirmFactoryReset(false);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,270 +1,269 @@
|
||||
import type { BaseTranslation } from '../i18n-types';
|
||||
|
||||
const no: BaseTranslation = {
|
||||
LANGUAGE: 'Language',
|
||||
RETRY: 'Retry',
|
||||
LOADING: 'Loading',
|
||||
IS_REQUIRED: 'is required',
|
||||
SIGN_IN: 'Sign In',
|
||||
SIGN_OUT: 'Sign Out',
|
||||
USERNAME: 'Username',
|
||||
PASSWORD: 'Password',
|
||||
LANGUAGE: 'Språk',
|
||||
RETRY: 'Forsøk igjen',
|
||||
LOADING: 'Laster',
|
||||
IS_REQUIRED: 'er nødvendig',
|
||||
SIGN_IN: 'Logg inn',
|
||||
SIGN_OUT: 'Logg ut',
|
||||
USERNAME: 'Brukernavn',
|
||||
PASSWORD: 'Passord',
|
||||
DASHBOARD: 'Dashboard',
|
||||
SETTINGS: 'Settings',
|
||||
SAVED: 'saved',
|
||||
HELP: 'Help',
|
||||
LOGGED_IN: 'Logged in as {name}',
|
||||
PLEASE_SIGNIN: 'Please sign in to continue',
|
||||
UPLOAD_SUCCESSFUL: 'Upload successful',
|
||||
DOWNLOAD_SUCCESSFUL: 'Download successful',
|
||||
INVALID_LOGIN: 'Invalid login details',
|
||||
NETWORK: 'Network',
|
||||
SECURITY: 'Security',
|
||||
ONOFF_CAP: 'ON/OFF',
|
||||
ONOFF: 'on/off',
|
||||
SETTINGS: 'Innstillinger',
|
||||
SAVED: 'lagret',
|
||||
HELP: 'Hjelp',
|
||||
LOGGED_IN: 'Logget in som {name}',
|
||||
PLEASE_SIGNIN: 'Venligst logge inn for å fortsetta',
|
||||
UPLOAD_SUCCESSFUL: 'Opplasting lykkes',
|
||||
DOWNLOAD_SUCCESSFUL: 'Nedlasting lykkes',
|
||||
INVALID_LOGIN: 'Ugyldig innlogging',
|
||||
NETWORK: 'Nettverk',
|
||||
SECURITY: 'Sikkerhet',
|
||||
ONOFF_CAP: 'PÅ/AV',
|
||||
ONOFF: 'på/av',
|
||||
TYPE: 'Type',
|
||||
DESCRIPTION: 'Description',
|
||||
ENTITIES: 'Entities',
|
||||
REFRESH: 'Refresh',
|
||||
EXPORT: 'Export',
|
||||
DEVICE_DETAILS: 'Device Details',
|
||||
BRAND: 'Brand',
|
||||
ENTITY_NAME: 'Entity Name',
|
||||
VALUE: 'Value',
|
||||
SHOW_FAV: 'only show favorites',
|
||||
DEVICE_SENSOR_DATA: 'Device and Sensor Data',
|
||||
DEVICES_SENSORS: 'Devices & Sensors',
|
||||
ATTACHED_SENSORS: 'Attached EMS-ESP Sensors',
|
||||
RUN_COMMAND: 'Call Command',
|
||||
CHANGE_VALUE: 'Change Value',
|
||||
CANCEL: 'Cancel',
|
||||
RESET: 'Reset',
|
||||
DESCRIPTION: 'Beskrivelse',
|
||||
ENTITIES: 'Ojekter',
|
||||
REFRESH: 'Oppdater',
|
||||
EXPORT: 'Eksport',
|
||||
DEVICE_DETAILS: 'Enhetsdetaljer',
|
||||
BRAND: 'Fabrikat',
|
||||
ENTITY_NAME: 'Objektsnavn',
|
||||
VALUE: 'Verdi',
|
||||
SHOW_FAV: ' Vis kun favoritter',
|
||||
DEVICE_SENSOR_DATA: 'Enheter og Sensordata',
|
||||
DEVICES_SENSORS: 'Enheter og Sensorer',
|
||||
ATTACHED_SENSORS: 'Tilkoblede EMS-ESP Sensorer',
|
||||
RUN_COMMAND: 'Kjør kommando',
|
||||
CHANGE_VALUE: 'Endre Verdi',
|
||||
CANCEL: 'Avbryt',
|
||||
RESET: 'Nullstill',
|
||||
SEND: 'Send',
|
||||
SAVE: 'Save',
|
||||
REMOVE: 'Remove',
|
||||
PROBLEM_UPDATING: 'Problem updating',
|
||||
PROBLEM_LOADING: 'Problem loading',
|
||||
ACCESS_DENIED: 'Access Denied',
|
||||
SAVE: 'Lagre',
|
||||
REMOVE: 'Fjern',
|
||||
PROBLEM_UPDATING: 'Problem med oppdatering',
|
||||
PROBLEM_LOADING: 'Problem med opplasting',
|
||||
ACCESS_DENIED: 'Tilgang nektet',
|
||||
ANALOG_SENSOR: 'Analog Sensor',
|
||||
ANALOG_SENSORS: 'Analog Sensors',
|
||||
UPDATED: 'Updated',
|
||||
UPDATE: 'Update',
|
||||
REMOVED: 'Removed',
|
||||
DELETION: 'Deletion',
|
||||
OFFSET: 'Offset',
|
||||
FACTOR: 'Factor',
|
||||
FREQ: 'Frequency',
|
||||
STARTVALUE: 'Start value',
|
||||
WARN_GPIO: 'Warning: be careful when assigning a GPIO!',
|
||||
EDIT: 'Edit',
|
||||
TEMP_SENSOR: 'Temperature Sensor',
|
||||
TEMP_SENSORS: 'Temperature Sensors',
|
||||
WRITE_COMMAND: 'Write command {cmd}',
|
||||
ANALOG_SENSORS: 'Analoge Sensorer',
|
||||
UPDATED: 'Oppdatert',
|
||||
UPDATE: 'Oppdater',
|
||||
REMOVED: 'Slettet',
|
||||
DELETION: 'Sletting',
|
||||
OFFSET: 'Kompensering',
|
||||
FACTOR: 'Faktor',
|
||||
FREQ: 'Frekvens',
|
||||
STARTVALUE: 'Startverdi',
|
||||
WARN_GPIO: 'Advarsel: vær forsiktig ved aktivering av GPIO!',
|
||||
EDIT: 'Endre',
|
||||
TEMP_SENSOR: 'Temperatursensor',
|
||||
TEMP_SENSORS: 'Temperaturesensorer',
|
||||
WRITE_COMMAND: 'Skriv kommando {cmd}',
|
||||
EMS_BUS_WARNING:
|
||||
'EMS bus disconnected. If this warning still persists after a few seconds please check settings and board profile',
|
||||
EMS_BUS_SCANNING: 'Scanning for EMS devices...',
|
||||
CONNECTED: 'Connected',
|
||||
TX_ISSUES: 'Tx issues - try a different Tx Mode',
|
||||
DISCONNECTED: 'Disconnected',
|
||||
EMS_SCAN: 'Are you sure you want to initiate a full device scan of the EMS bus?',
|
||||
EMS_BUS_STATUS: 'EMS Bus Status',
|
||||
ACTIVE_DEVICES: 'Active Devices & Sensors',
|
||||
DEVICE: 'Device',
|
||||
SUCCESS: 'SUCCESS',
|
||||
FAIL: 'FAIL',
|
||||
QUALITY: 'QUALITY',
|
||||
SCAN_DEVICES: 'Scan for new devices',
|
||||
EMS_BUS_STATUS_TITLE: 'EMS Bus & Activity Status',
|
||||
SCAN: 'Scan',
|
||||
'EMS bussen koblet ned. Hvis denne advarselen fortsetter etter noen f¨sekunder sjekk instillinger og prosessorkort',
|
||||
EMS_BUS_SCANNING: 'Søker etter EMS enheter...',
|
||||
CONNECTED: 'Tilkoblet',
|
||||
TX_ISSUES: 'Tx problemer - prøv en annen Tx Modus',
|
||||
DISCONNECTED: 'Frakoblet',
|
||||
EMS_SCAN: 'Er du sikker på du vil starte full søking av EMS bussen?',
|
||||
EMS_BUS_STATUS: 'EMS Buss Status',
|
||||
ACTIVE_DEVICES: 'Aktive Enheter og Sensorer',
|
||||
DEVICE: 'Enhet',
|
||||
SUCCESS: 'VELLYKKET',
|
||||
FAIL: 'MISLYKKET',
|
||||
QUALITY: 'KVALITET',
|
||||
SCAN_DEVICES: 'Søk etter nye enheter',
|
||||
EMS_BUS_STATUS_TITLE: 'EMS Buss & Aktivitet Status',
|
||||
SCAN: 'Søk',
|
||||
STATUS_NAMES: [
|
||||
'EMS Telegrams Received (Rx)',
|
||||
'EMS Reads (Tx)',
|
||||
'EMS Writes (Tx)',
|
||||
'Temperature Sensor Reads',
|
||||
'Analog Sensor Reads',
|
||||
'MQTT Publishes',
|
||||
'API Calls',
|
||||
'Syslog Messages'
|
||||
'EMS Telegrammer Mottatt (Rx)',
|
||||
'EMS Lest (Tx)',
|
||||
'EMS Skrevet (Tx)',
|
||||
'Temperatur Sensor Lest',
|
||||
'Analog Sensor Lest',
|
||||
'MQTT Publiseringer',
|
||||
'API Anrop',
|
||||
'Syslog Meldinger'
|
||||
],
|
||||
NUM_DEVICES: '{num} Device{{s}}',
|
||||
NUM_TEMP_SENSORS: '{num} Temperature Sensor{{s}}',
|
||||
NUM_ANALOG_SENSORS: '{num} Analog Sensor{{s}}',
|
||||
NUM_DAYS: '{num} Day{{s}}',
|
||||
NUM_SECONDS: '{num} Second{{s}}',
|
||||
NUM_HOURS: '{num} Hour{{s}}',
|
||||
NUM_MINUTES: '{num} Minute{{s}}',
|
||||
APPLICATION_SETTINGS: 'Application Settings',
|
||||
CUSTOMIZATION: 'Customization',
|
||||
APPLICATION_RESTARTING: 'EMS-ESP is restarting',
|
||||
NUM_DEVICES: '{num} Enhet{{er}}',
|
||||
NUM_TEMP_SENSORS: '{num} Temperatursensor{{er}}',
|
||||
NUM_ANALOG_SENSORS: '{num} Analogsensor{{er}}',
|
||||
NUM_DAYS: '{num} Dag{{er}}',
|
||||
NUM_SECONDS: '{num} Sekund{{er}}',
|
||||
NUM_HOURS: '{num} Time{{r}}',
|
||||
NUM_MINUTES: '{num} Minutt{{er}}',
|
||||
APPLICATION_SETTINGS: 'Innstillinger',
|
||||
CUSTOMIZATION: 'Tilpasninger',
|
||||
APPLICATION_RESTARTING: 'EMS-ESP restarter',
|
||||
BOARD_PROFILE_TEXT:
|
||||
'Select a pre-configured interface board profile from the list below or choose Custom to configure your own hardware settings',
|
||||
BOARD_PROFILE: 'Board Profile',
|
||||
BUTTON: 'Button',
|
||||
TEMPERATURE: 'Temperature',
|
||||
DISABLED: 'disabled',
|
||||
GENERAL_OPTIONS: 'General Options',
|
||||
LANGUAGE_ENTITIES: 'Language (for device entities)',
|
||||
HIDE_LED: 'Hide LED',
|
||||
ENABLE_TELNET: 'Enable Telnet Console',
|
||||
ENABLE_ANALOG: 'Enable Analog Sensors',
|
||||
CONVERT_FAHRENHEIT: 'Convert temperature values to Fahrenheit',
|
||||
BYPASS_TOKEN: 'Bypass Access Token authorization on API calls',
|
||||
READONLY: 'Enable read-only mode (blocks all outgoing EMS Tx Write commands)',
|
||||
UNDERCLOCK_CPU: 'Underclock CPU speed',
|
||||
ENABLE_SHOWER_TIMER: 'Enable Shower Timer',
|
||||
ENABLE_SHOWER_ALERT: 'Enable Shower Alert',
|
||||
TRIGGER_TIME: 'Trigger Time',
|
||||
COLD_SHOT_DURATION: 'Cold Shot Duration',
|
||||
FORMATTING_OPTIONS: 'Formatting Options',
|
||||
BOOLEAN_FORMAT_DASHBOARD: 'Boolean Format Dashboard',
|
||||
BOOLEAN_FORMAT_API: 'Boolean Format API/MQTT',
|
||||
'Velg en pre-konfigurert prosessor profil fra listen under eller velg Tilpasset for å konfigurere dine egne innstillinger',
|
||||
BOARD_PROFILE: 'Prosessor Profil',
|
||||
BUTTON: 'Knapp',
|
||||
TEMPERATURE: 'Temperatur',
|
||||
DISABLED: 'avslått',
|
||||
GENERAL_OPTIONS: 'Generelle Innstillinger',
|
||||
LANGUAGE_ENTITIES: 'Språk (for objekter)',
|
||||
HIDE_LED: 'Skjul LED',
|
||||
ENABLE_TELNET: 'Aktiver Telnet',
|
||||
ENABLE_ANALOG: 'Aktiver Analoge Sensorer',
|
||||
CONVERT_FAHRENHEIT: 'Konverter temperatur til Fahrenheit',
|
||||
BYPASS_TOKEN: 'Utelat Aksess Token authorisering av API kall',
|
||||
READONLY: 'Aktiver read-only modus (blokker all EMS Tx Skriving)',
|
||||
UNDERCLOCK_CPU: 'Underklokking av prosessorhastighet',
|
||||
ENABLE_SHOWER_TIMER: 'Aktiver Dusjtimer',
|
||||
ENABLE_SHOWER_ALERT: 'Aktiver Dusj-varsling',
|
||||
TRIGGER_TIME: 'Aktiveringstid',
|
||||
COLD_SHOT_DURATION: 'Tid på kaldt vann',
|
||||
FORMATTING_OPTIONS: 'Formatteringsalternativs',
|
||||
BOOLEAN_FORMAT_DASHBOARD: 'Bool Format Dashboard',
|
||||
BOOLEAN_FORMAT_API: 'Bool Format API/MQTT',
|
||||
ENUM_FORMAT: 'Enum Format API/MQTT',
|
||||
INDEX: 'Index',
|
||||
ENABLE_PARASITE: 'Enable parasite power',
|
||||
INDEX: 'Indeks',
|
||||
ENABLE_PARASITE: 'Aktiver parasitt strømforsyning',
|
||||
LOGGING: 'Logging',
|
||||
LOG_HEX: 'Log EMS telegrams in hexadecimal',
|
||||
ENABLE_SYSLOG: 'Enable Syslog',
|
||||
MARK_INTERVAL: 'Mark Interval',
|
||||
SECONDS: 'seconds',
|
||||
MINUTES: 'minutes',
|
||||
RESTART: 'Restart',
|
||||
HOURS: 'hours',
|
||||
RESTART_TEXT: 'EMS-ESP needs to be restarted to apply changed system settings',
|
||||
RESTART_CONFIRM: 'Are you sure you want to restart EMS-ESP?',
|
||||
COMMAND: 'Command',
|
||||
CUSTOMIZATIONS_RESTART: 'All customizations have been removed. Restarting...',
|
||||
CUSTOMIZATIONS_FULL: 'Selected entities exceeded limit. Please save in batches',
|
||||
CUSTOMIZATIONS_SAVED: 'Customizations saved',
|
||||
CUSTOMIZATIONS_HELP_1: 'Select a device and customize the entities options or click to rename',
|
||||
CUSTOMIZATIONS_HELP_2: 'mark as favorite',
|
||||
CUSTOMIZATIONS_HELP_3: 'disable write action',
|
||||
CUSTOMIZATIONS_HELP_4: 'exclude from MQTT and API',
|
||||
CUSTOMIZATIONS_HELP_5: 'hide from Dashboard',
|
||||
SELECT_DEVICE: 'Select a device',
|
||||
SET_ALL: 'set all',
|
||||
OPTIONS: 'Options',
|
||||
NAME: 'Name',
|
||||
LOG_HEX: 'Logg EMS telegrammer i hexadesimal',
|
||||
ENABLE_SYSLOG: 'Aktiver Syslog',
|
||||
MARK_INTERVAL: 'Oppdateringsintervall',
|
||||
SECONDS: 'sekunder',
|
||||
MINUTES: 'minutter',
|
||||
RESTART: 'Omstart',
|
||||
HOURS: 'timer',
|
||||
RESTART_TEXT: 'EMS-ESP må omstartes for å iverksette endrede systeminstillinger',
|
||||
RESTART_CONFIRM: 'Er du sikker på at du vil omstarte EMS-ESP?',
|
||||
COMMAND: 'Kommando',
|
||||
CUSTOMIZATIONS_RESTART: 'Alle tilpasninger har blitt slettet. Restarter...',
|
||||
CUSTOMIZATIONS_FULL: 'Antall valgte objekter for høyt. Largre i mindre antall om gangen',
|
||||
CUSTOMIZATIONS_SAVED: 'Tilpasninger lagret',
|
||||
CUSTOMIZATIONS_HELP_1: 'Velg en enhet og tilpass underenheter med hjelp av alternativer eller velg å gi nytt navn',
|
||||
CUSTOMIZATIONS_HELP_2: 'merk som favoritt',
|
||||
CUSTOMIZATIONS_HELP_3: 'inaktiviser skriving',
|
||||
CUSTOMIZATIONS_HELP_4: 'ekskludere fra MQTT og API',
|
||||
CUSTOMIZATIONS_HELP_5: 'gjemme fra Dashboard',
|
||||
SELECT_DEVICE: 'Velg en enhet',
|
||||
SET_ALL: 'sett alle',
|
||||
OPTIONS: 'Alternativ',
|
||||
NAME: 'Navn',
|
||||
CUSTOMIZATIONS_RESET:
|
||||
'Are you sure you want remove all customizations including the custom settings of the Temperature and Analog sensors?',
|
||||
DEVICE_ENTITIES: 'Device Entities',
|
||||
USER_CUSTOMIZATION: 'User Customization',
|
||||
SUPPORT_INFORMATION: 'Support Information',
|
||||
CLICK_HERE: 'Click Here',
|
||||
HELP_INFORMATION_1: 'Visit the online wiki to get instructions on how to configure EMS-ESP',
|
||||
HELP_INFORMATION_2: 'For live community chat join our Discord server',
|
||||
HELP_INFORMATION_3: 'To request a feature or report a bug',
|
||||
'Er du sikker på att du vil fjerne tilpassninger inkludert innstillinger for Temperatur og Analoge sensorer?',
|
||||
DEVICE_ENTITIES: 'Enhets objekter',
|
||||
USER_CUSTOMIZATION: 'Brukertilpasninger',
|
||||
SUPPORT_INFORMATION: 'Supportinformasjon',
|
||||
CLICK_HERE: 'Klikk her',
|
||||
HELP_INFORMATION_1: 'Besøk wiki for instruksjoner for å konfigurere EMS-ESP',
|
||||
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_4:
|
||||
'remember to download and attach your system information for a faster response when reporting an issue',
|
||||
HELP_INFORMATION_5:
|
||||
'EMS-ESP is a free and open-source project. Please support its future development by giving it a star on Github!',
|
||||
SUPPORT_INFO: 'Support Info',
|
||||
UPLOAD: 'Upload',
|
||||
DOWNLOAD: 'Download',
|
||||
ABORTED: 'aborted',
|
||||
FAILED: 'failed',
|
||||
SUCCESSFUL: 'successful',
|
||||
'husk å laste ned og legg ved din systeminformasjon for en raskere respons når du rapporterer et problem',
|
||||
HELP_INFORMATION_5: 'EMS-ESP er gratis og åpen kildekode. Bidra til utviklingen ved å gi oss en stjerne på GitHub!',
|
||||
SUPPORT_INFO: 'Supportinfo',
|
||||
UPLOAD: 'Opplasning',
|
||||
DOWNLOAD: 'Nedlasting',
|
||||
ABORTED: 'avbrutt',
|
||||
FAILED: 'feilet',
|
||||
SUCCESSFUL: 'vellykket',
|
||||
SYSTEM: 'System',
|
||||
LOG: 'Log',
|
||||
LOG: 'Logg',
|
||||
STATUS: 'Status',
|
||||
UPLOAD_DOWNLOAD: 'Upload/Download',
|
||||
SYSTEM_VERSION_RUNNING: 'You are currently running version',
|
||||
SYSTEM_APPLY_FIRMWARE: 'to apply the new firmware',
|
||||
CLOSE: 'Close',
|
||||
USE: 'Use',
|
||||
FACTORY_RESET: 'Factory Reset',
|
||||
SYSTEM_FACTORY_TEXT: 'Device has been factory reset and will now restart',
|
||||
SYSTEM_FACTORY_TEXT_DIALOG: 'Are you sure you want to reset the device to its factory defaults?',
|
||||
VERSION_CHECK: 'Version Check',
|
||||
THE_LATEST: 'The latest',
|
||||
VERSION_IS: 'version is',
|
||||
PLATFORM: 'Device (Platform / SDK)',
|
||||
UPTIME: 'System Uptime',
|
||||
CPU_FREQ: 'CPU Frequency',
|
||||
HEAP: 'Heap (Free / Max Alloc)',
|
||||
PSRAM: 'PSRAM (Size / Free)',
|
||||
FLASH: 'Flash Chip (Size / Speed)',
|
||||
APPSIZE: 'Application (Used / Free)',
|
||||
FILESYSTEM: 'File System (Used / Free)',
|
||||
BUFFER_SIZE: 'Buffer Size',
|
||||
COMPACT: 'Compact',
|
||||
ENABLE_OTA: 'Enable OTA Updates',
|
||||
DOWNLOAD_CUSTOMIZATION_TEXT: 'Download the entity customizations',
|
||||
UPLOAD_DOWNLOAD: 'Opp/Nedlasting',
|
||||
SYSTEM_VERSION_RUNNING: 'Du benytter versjon',
|
||||
SYSTEM_APPLY_FIRMWARE: 'for å aktivere ny firmware',
|
||||
CLOSE: 'Steng',
|
||||
USE: 'Bruk',
|
||||
FACTORY_RESET: 'Sett tilbake til fabrikkinstilling',
|
||||
SYSTEM_FACTORY_TEXT: 'Enhet har blitt satt tilbake til fabrikkinstilling og vil restarte',
|
||||
SYSTEM_FACTORY_TEXT_DIALOG: 'Er du sikker på at du vil resette enheten til fabrikkinstillinger?',
|
||||
VERSION_CHECK: 'Versjonsjekk',
|
||||
THE_LATEST: 'Den nyeste',
|
||||
VERSION_IS: 'versjonen er',
|
||||
PLATFORM: 'Enhet (Platform / SDK)',
|
||||
UPTIME: 'System Oppetid',
|
||||
CPU_FREQ: 'CPU Frekvens',
|
||||
HEAP: 'Heap (Ledig / Max Allokert)',
|
||||
PSRAM: 'PSRAM (Størrelse / Ledig)',
|
||||
FLASH: 'Flash Chip (Størrelse / Hastighet)',
|
||||
APPSIZE: 'Applikasjon (Brukt / Ledig)',
|
||||
FILESYSTEM: 'File System (Brukt / Ledig)',
|
||||
BUFFER_SIZE: 'Buffer Størrelse',
|
||||
COMPACT: 'Komprimere',
|
||||
ENABLE_OTA: 'Aktiviser OTA oppdateringer',
|
||||
DOWNLOAD_CUSTOMIZATION_TEXT: 'Last ned objektstilpasninger',
|
||||
DOWNLOAD_SETTINGS_TEXT:
|
||||
'Download the application settings. Be careful when sharing your settings as this file contains passwords and other sensitive system information',
|
||||
UPLOAD_TEXT: 'Upload a new firmware (.bin) file, settings or customizations (.json) file below',
|
||||
UPLOADING: 'Uploading',
|
||||
UPLOAD_DROP_TEXT: 'Drop file or click here',
|
||||
ERROR: 'Unexpected Error, please try again',
|
||||
TIME_SET: 'Time set',
|
||||
MANAGE_USERS: 'Manage Users',
|
||||
IS_ADMIN: 'is Admin',
|
||||
USER_WARNING: 'You must have at least one admin user configured',
|
||||
ADD: 'Add',
|
||||
ACCESS_TOKEN_FOR: 'Access Token for',
|
||||
'Last ned applikasjonskonfigurasjon. Vær varsom med å dele fila da den inneholder passord og annen sensitiv system informasjon',
|
||||
UPLOAD_TEXT: 'Last opp en ny firmware (.bin) fil, innstillinger eller tilpassninger (.json) fil nedenfor',
|
||||
UPLOADING: 'Opplasting',
|
||||
UPLOAD_DROP_TEXT: 'Slipp fil eller klikk her',
|
||||
ERROR: 'Ukjent feil, prøv igjen',
|
||||
TIME_SET: 'Still in tid',
|
||||
MANAGE_USERS: 'Administrer Brukere',
|
||||
IS_ADMIN: 'er Admin',
|
||||
USER_WARNING: 'Du må ha minst en admin bruker konfigurert',
|
||||
ADD: 'Legg til',
|
||||
ACCESS_TOKEN_FOR: 'Aksess Token for',
|
||||
ACCESS_TOKEN_TEXT:
|
||||
'The token below is used with REST API calls that require authorization. It can be passed either as a Bearer token in the Authorization header or in the access_token URL query parameter.',
|
||||
GENERATING_TOKEN: 'Generating token',
|
||||
USER: 'User',
|
||||
MODIFY: 'Modify',
|
||||
'Token nedenfor benyttes med REST API-kall som krever autorisering. Den kan sendes med enten som en Bearer token i Authorization-headern eller i access_token URL query-parameter.',
|
||||
GENERATING_TOKEN: 'Generer token',
|
||||
USER: 'Bruker',
|
||||
MODIFY: 'Endre',
|
||||
SU_TEXT:
|
||||
'The su (super user) password is used to sign authentication tokens and also enable admin privileges within the Console.',
|
||||
NOT_ENABLED: 'Not enabled',
|
||||
ERRORS: 'Errors',
|
||||
DISCONNECT_REASON: 'Disconnect Reason',
|
||||
ENABLE_MQTT: 'Enable MQTT',
|
||||
OPTIONAL: 'Optional',
|
||||
FORMATTING: 'Formatting',
|
||||
'su brukeren (super user) passord benyttes for å signere autentiserings token samt å tillate admin privileger i konsoll modus.',
|
||||
NOT_ENABLED: 'Ikke aktiv',
|
||||
ERRORS: 'Feil',
|
||||
DISCONNECT_REASON: 'Årsak til nedkobling',
|
||||
ENABLE_MQTT: 'Aktiver MQTT',
|
||||
OPTIONAL: 'Valgfritt',
|
||||
FORMATTING: 'Formatering',
|
||||
FORMAT: 'Format',
|
||||
MQTT_NEST_1: 'Nested in a single topic',
|
||||
MQTT_NEST_2: 'As individual topics',
|
||||
MQTT_RESPONSE: 'Publish command output to a `response` topic',
|
||||
MQTT_PUBLISH_TEXT_1: 'Publish single value topics on change',
|
||||
MQTT_PUBLISH_TEXT_2: 'Publish to command topics (ioBroker)',
|
||||
MQTT_PUBLISH_TEXT_3: 'Enable MQTT Discovery (Home Assistant, Domoticz)',
|
||||
MQTT_PUBLISH_TEXT_4: 'Prefix for the Discovery topics',
|
||||
MQTT_PUBLISH_INTERVALS: 'Publish Intervals',
|
||||
MQTT_INT_BOILER: 'Boilers and Heat Pumps',
|
||||
MQTT_INT_THERMOSTATS: 'Thermostats',
|
||||
MQTT_INT_SOLAR: 'Solar Modules',
|
||||
MQTT_INT_MIXER: 'Mixer Modules',
|
||||
DEFAULT: 'Default',
|
||||
MQTT_CLEAN_SESSION: 'Set Clean Session',
|
||||
MQTT_RETAIN_FLAG: 'Always set Retain flag',
|
||||
INACTIVE: 'Inactive',
|
||||
ACTIVE: 'Active',
|
||||
UNKNOWN: 'Unknown',
|
||||
SET_TIME: 'Set Time',
|
||||
SET_TIME_TEXT: 'Enter local date and time below to set the time',
|
||||
LOCAL_TIME: 'Local Time',
|
||||
UTC_TIME: 'UTC Time',
|
||||
ENABLE_NTP: 'Enable NTP',
|
||||
TIME_ZONE: 'Time Zone',
|
||||
ACCESS_POINT: 'Access Point',
|
||||
AP_PROVIDE: 'Enable Access Point',
|
||||
AP_PROVIDE_TEXT_1: 'always',
|
||||
AP_PROVIDE_TEXT_2: 'when WiFi is disconnected',
|
||||
AP_PROVIDE_TEXT_3: 'never',
|
||||
AP_PREFERRED_CHANNEL: 'Preferred Channel',
|
||||
AP_HIDE_SSID: 'Hide SSID',
|
||||
NETWORK_SCAN: 'Scan WiFi Networks',
|
||||
IDLE: 'Idle',
|
||||
LOST: 'Lost',
|
||||
SCANNING: 'Scanning',
|
||||
SCAN_AGAIN: 'Scan again',
|
||||
NETWORK_SCANNER: 'Network Scanner',
|
||||
NETWORK_NO_WIFI: 'No WiFi networks found',
|
||||
NETWORK_BLANK_SSID: 'leave blank to disable WiFi',
|
||||
POWER: 'Power',
|
||||
NETWORK_DISABLE_SLEEP: 'Disable WiFi Sleep Mode',
|
||||
NETWORK_LOW_BAND: 'Use Lower WiFi Bandwidth',
|
||||
NETWORK_USE_DNS: 'Enable mDNS Service',
|
||||
NETWORK_ENABLE_IPV6: 'Enable IPv6 support',
|
||||
NETWORK_FIXED_IP: 'Use Fixed IP address',
|
||||
MQTT_NEST_1: 'Nestet i en topic',
|
||||
MQTT_NEST_2: 'Som individuelle topics',
|
||||
MQTT_RESPONSE: 'Publiser kommandoer til en `response` topic',
|
||||
MQTT_PUBLISH_TEXT_1: 'Publiser singel verdi topics ved endringer',
|
||||
MQTT_PUBLISH_TEXT_2: 'Publiser til kommando topics (ioBroker)',
|
||||
MQTT_PUBLISH_TEXT_3: 'Aktiver MQTT Discovery (Home Assistant, Domoticz)',
|
||||
MQTT_PUBLISH_TEXT_4: 'Prefiks for Discovery topics',
|
||||
MQTT_PUBLISH_INTERVALS: 'Publiseringsintervall',
|
||||
MQTT_INT_BOILER: 'Fyr/Varmepumpe',
|
||||
MQTT_INT_THERMOSTATS: 'Termostat',
|
||||
MQTT_INT_SOLAR: 'Solpaneler',
|
||||
MQTT_INT_MIXER: 'Blandeventil',
|
||||
DEFAULT: 'Standard',
|
||||
MQTT_CLEAN_SESSION: 'Benytt Clean Session',
|
||||
MQTT_RETAIN_FLAG: 'Alltid sett Retain flag',
|
||||
INACTIVE: 'Innaktiv',
|
||||
ACTIVE: 'Aktiv',
|
||||
UNKNOWN: 'Ukjent',
|
||||
SET_TIME: 'Sett Tid',
|
||||
SET_TIME_TEXT: 'Skriv inn dato og klokke nedenfor',
|
||||
LOCAL_TIME: 'Lokaltid',
|
||||
UTC_TIME: 'UTC Tid',
|
||||
ENABLE_NTP: 'Aktiver NTP',
|
||||
TIME_ZONE: 'Tidssone',
|
||||
ACCESS_POINT: 'Aksesspunkt',
|
||||
AP_PROVIDE: 'Aktiver Aksesspunkt',
|
||||
AP_PROVIDE_TEXT_1: 'alltid',
|
||||
AP_PROVIDE_TEXT_2: 'når WiFi er utilgjengelig',
|
||||
AP_PROVIDE_TEXT_3: 'aldri',
|
||||
AP_PREFERRED_CHANNEL: 'Foretrukket kanal',
|
||||
AP_HIDE_SSID: 'Skjul SSID',
|
||||
NETWORK_SCAN: 'Søk etter trådløst nettverk',
|
||||
IDLE: 'Klar',
|
||||
LOST: 'Mistet',
|
||||
SCANNING: 'Søker',
|
||||
SCAN_AGAIN: 'Søk igjen',
|
||||
NETWORK_SCANNER: 'Nettverk Scanner',
|
||||
NETWORK_NO_WIFI: 'Ingen trådløse nett funnet',
|
||||
NETWORK_BLANK_SSID: 'la feltet være blankt for å deaktivisere trådløst nettverk',
|
||||
POWER: 'Effekt',
|
||||
NETWORK_DISABLE_SLEEP: 'Hindre at trådløst nettverk går i Sleep Mode',
|
||||
NETWORK_LOW_BAND: 'Benytt smalere båndbredde på trådløst nettverk',
|
||||
NETWORK_USE_DNS: 'Aktiviser mDNS Service',
|
||||
NETWORK_ENABLE_IPV6: 'Aktiviser IPv6 støtte',
|
||||
NETWORK_FIXED_IP: 'Benytt statisk IP adresse',
|
||||
ADMIN: 'Admin',
|
||||
GUEST: 'Guest',
|
||||
NEW: 'New',
|
||||
RENAME: 'Rename',
|
||||
ENTITY: 'Entity'
|
||||
GUEST: 'Gjest',
|
||||
NEW: 'Ny',
|
||||
RENAME: 'Bytt navn',
|
||||
ENTITY: 'Entitet'
|
||||
};
|
||||
|
||||
export default no;
|
||||
|
||||
@@ -96,8 +96,7 @@ const pl: BaseTranslation = {
|
||||
APPLICATION_SETTINGS: 'Ustawienia aplikacji',
|
||||
CUSTOMIZATION: 'Personalizacja',
|
||||
APPLICATION_RESTARTING: 'Trwa ponowne uruchamianie',
|
||||
BOARD_PROFILE_TEXT:
|
||||
'Wybierz z listy wstępną konfigurację płytki interfejsu lub stwórz własną konfigurację.',
|
||||
BOARD_PROFILE_TEXT: 'Wybierz z listy wstępną konfigurację płytki interfejsu lub stwórz własną konfigurację.',
|
||||
BOARD_PROFILE: 'Profil płytki',
|
||||
BUTTON: 'Przycisk',
|
||||
TEMPERATURE: 'Temperatura',
|
||||
|
||||
@@ -364,7 +364,7 @@ const DashboardData: FC = () => {
|
||||
const fetchCoreData = useCallback(async () => {
|
||||
try {
|
||||
setCoreData((await EMSESP.readCoreData()).data);
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||
}
|
||||
}, [enqueueSnackbar, LL]);
|
||||
@@ -385,7 +385,7 @@ const DashboardData: FC = () => {
|
||||
const unique_id = parseInt(id);
|
||||
try {
|
||||
setDeviceData((await EMSESP.readDeviceData({ id: unique_id })).data);
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||
}
|
||||
};
|
||||
@@ -393,7 +393,7 @@ const DashboardData: FC = () => {
|
||||
const fetchSensorData = async () => {
|
||||
try {
|
||||
setSensorData((await EMSESP.readSensorData()).data);
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||
}
|
||||
};
|
||||
@@ -474,7 +474,7 @@ const DashboardData: FC = () => {
|
||||
enqueueSnackbar(LL.WRITE_COMMAND({ cmd: 'send' }), { variant: 'success' });
|
||||
}
|
||||
setDeviceValue(undefined);
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
} finally {
|
||||
refreshData();
|
||||
@@ -508,7 +508,7 @@ const DashboardData: FC = () => {
|
||||
<ValidatedTextField
|
||||
name="v"
|
||||
label={deviceValue.id.slice(2)}
|
||||
value={deviceValue.u ? numberValue(deviceValue.v) : deviceValue.v}
|
||||
value={typeof deviceValue.v === 'number' ? Math.round(deviceValue.v * 10) / 10 : deviceValue.v}
|
||||
autoFocus
|
||||
multiline={deviceValue.u ? false : true}
|
||||
sx={{ width: '30ch' }}
|
||||
@@ -566,7 +566,7 @@ const DashboardData: FC = () => {
|
||||
enqueueSnackbar(LL.TEMP_SENSOR() + ' ' + LL.UPDATED(), { variant: 'success' });
|
||||
}
|
||||
setSensor(undefined);
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
} finally {
|
||||
setSensor(undefined);
|
||||
@@ -992,7 +992,7 @@ const DashboardData: FC = () => {
|
||||
} else {
|
||||
enqueueSnackbar(LL.ANALOG_SENSOR() + ' ' + LL.REMOVED(), { variant: 'success' });
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
} finally {
|
||||
setAnalog(undefined);
|
||||
@@ -1020,7 +1020,7 @@ const DashboardData: FC = () => {
|
||||
} else {
|
||||
enqueueSnackbar(LL.ANALOG_SENSOR() + ' ' + LL.UPDATED(), { variant: 'success' });
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
} finally {
|
||||
setAnalog(undefined);
|
||||
|
||||
@@ -149,7 +149,7 @@ const DashboardStatus: FC = () => {
|
||||
try {
|
||||
await EMSESP.scanDevices();
|
||||
enqueueSnackbar(LL.SCANNING() + '...', { variant: 'info' });
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
} finally {
|
||||
setConfirmScan(false);
|
||||
|
||||
@@ -50,7 +50,7 @@ const HelpInformation: FC = () => {
|
||||
} else {
|
||||
saveFile(response.data, endpoint);
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -68,7 +68,7 @@ const SettingsApplication: FC = () => {
|
||||
eth_clock_mode: response.data.eth_clock_mode
|
||||
});
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
} finally {
|
||||
setProcessingBoard(false);
|
||||
@@ -107,7 +107,7 @@ const SettingsApplication: FC = () => {
|
||||
try {
|
||||
await EMSESP.restart();
|
||||
enqueueSnackbar(LL.APPLICATION_RESTARTING(), { variant: 'info' });
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -131,7 +131,7 @@ const SettingsCustomization: FC = () => {
|
||||
const fetchDevices = useCallback(async () => {
|
||||
try {
|
||||
setDevices((await EMSESP.readDevices()).data);
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||
}
|
||||
}, [LL]);
|
||||
@@ -144,7 +144,7 @@ const SettingsCustomization: FC = () => {
|
||||
try {
|
||||
const new_deviceEntities = (await EMSESP.readDeviceEntities({ id: unique_id })).data;
|
||||
setInitialMask(new_deviceEntities);
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||
}
|
||||
};
|
||||
@@ -165,17 +165,21 @@ const SettingsCustomization: FC = () => {
|
||||
}
|
||||
|
||||
function formatName(de: DeviceEntity) {
|
||||
if (de.n === undefined || de.n === de.id) {
|
||||
return de.id;
|
||||
}
|
||||
|
||||
if (de.n[0] === '!') {
|
||||
return LL.COMMAND() + ': ' + de.n.slice(1);
|
||||
if (de.n === undefined) {
|
||||
return (
|
||||
<>
|
||||
(
|
||||
<Link target="_blank" href={APIURL + devices?.devices[selectedDevice].t + '/' + de.id}>
|
||||
{de.id}
|
||||
</Link>
|
||||
)
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{de.cn !== undefined && de.cn !== '' ? de.cn : de.n}
|
||||
{de.n[0] === '!' ? LL.COMMAND() + ': ' + de.n.slice(1) : de.cn !== undefined && de.cn !== '' ? de.cn : de.n}
|
||||
(
|
||||
<Link target="_blank" href={APIURL + devices?.devices[selectedDevice].t + '/' + de.id}>
|
||||
{de.id}
|
||||
@@ -239,7 +243,7 @@ const SettingsCustomization: FC = () => {
|
||||
try {
|
||||
await EMSESP.resetCustomizations();
|
||||
enqueueSnackbar(LL.CUSTOMIZATIONS_RESTART(), { variant: 'info' });
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
} finally {
|
||||
setConfirmReset(false);
|
||||
@@ -250,13 +254,15 @@ const SettingsCustomization: FC = () => {
|
||||
if (devices && deviceEntities && selectedDevice !== -1) {
|
||||
const masked_entities = deviceEntities
|
||||
.filter((de) => de.m !== de.o_m || de.cn !== de.o_cn || de.ma !== de.o_ma || de.mi !== de.o_mi)
|
||||
.map((new_de) =>
|
||||
new_de.m.toString(16).padStart(2, '0') +
|
||||
new_de.id +
|
||||
((new_de.cn || new_de.mi || new_de.ma) ? '|' : '') +
|
||||
(new_de.cn ? new_de.cn : '') +
|
||||
(new_de.mi ? '>' + new_de.mi : '') +
|
||||
(new_de.ma ? '<' + new_de.ma : ''));
|
||||
.map(
|
||||
(new_de) =>
|
||||
new_de.m.toString(16).padStart(2, '0') +
|
||||
new_de.id +
|
||||
(new_de.cn || new_de.mi || new_de.ma ? '|' : '') +
|
||||
(new_de.cn ? new_de.cn : '') +
|
||||
(new_de.mi ? '>' + new_de.mi : '') +
|
||||
(new_de.ma ? '<' + new_de.ma : '')
|
||||
);
|
||||
|
||||
// check size in bytes to match buffer in CPP, which is 4096
|
||||
const bytes = new TextEncoder().encode(JSON.stringify(masked_entities)).length;
|
||||
@@ -275,7 +281,7 @@ const SettingsCustomization: FC = () => {
|
||||
} else {
|
||||
enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' });
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
}
|
||||
setInitialMask(deviceEntities);
|
||||
@@ -322,7 +328,7 @@ const SettingsCustomization: FC = () => {
|
||||
};
|
||||
|
||||
const editEntity = (de: DeviceEntity) => {
|
||||
if (de.n && de.n[0] === '!') {
|
||||
if (de.n === undefined || (de.n && de.n[0] === '!')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ export interface MqttStatus {
|
||||
client_id: string;
|
||||
disconnect_reason: MqttDisconnectReason;
|
||||
mqtt_fails: number;
|
||||
mqtt_queued: number;
|
||||
connect_count: number;
|
||||
}
|
||||
|
||||
export interface MqttSettings {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { AxiosError } from 'axios';
|
||||
|
||||
export const extractErrorMessage = (error: unknown, defaultMessage: string) => {
|
||||
if (error instanceof AxiosError) {
|
||||
export const extractErrorMessage = (error: any, defaultMessage: string) => {
|
||||
if (error.request) {
|
||||
return defaultMessage + ' (' + error.request.statusText + ')';
|
||||
} else if (error instanceof Error) {
|
||||
return defaultMessage + ' (' + error.message + ')';
|
||||
|
||||
@@ -26,7 +26,7 @@ export const useRest = <D>({ read, update }: RestRequestOptions<D>) => {
|
||||
setErrorMessage(undefined);
|
||||
try {
|
||||
setData((await read()).data);
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
const message = extractErrorMessage(error, LL.PROBLEM_LOADING());
|
||||
enqueueSnackbar(message, { variant: 'error' });
|
||||
setErrorMessage(message);
|
||||
@@ -49,7 +49,7 @@ export const useRest = <D>({ read, update }: RestRequestOptions<D>) => {
|
||||
} else {
|
||||
enqueueSnackbar(LL.SETTINGS() + ' ' + LL.SAVED(), { variant: 'success' });
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
} catch (error) {
|
||||
const message = extractErrorMessage(error, LL.PROBLEM_UPDATING());
|
||||
enqueueSnackbar(message, { variant: 'error' });
|
||||
setErrorMessage(message);
|
||||
|
||||
Reference in New Issue
Block a user