Merge pull request #1245 from proddy/dev

Enhance version check to differentiate between ESP32 and ESP32-S3 bin versions #1240
This commit is contained in:
Proddy
2023-08-08 07:51:20 +02:00
committed by GitHub
16 changed files with 715 additions and 1472 deletions

View File

@@ -21,7 +21,7 @@
- Native support for Home Assistant, Domoticz and openHAB via [MQTT Discovery](https://www.home-assistant.io/docs/mqtt/discovery/) - Native support for Home Assistant, Domoticz and openHAB via [MQTT Discovery](https://www.home-assistant.io/docs/mqtt/discovery/)
- Can run standalone as an independent WiFi Access Point or join an existing WiFi network - Can run standalone as an independent WiFi Access Point or join an existing WiFi network
- Easy first-time configuration via a web Captive Portal - Easy first-time configuration via a web Captive Portal
- Support for more than [110 EMS devices](https://emsesp.github.io/docs/#/Supported-EMS-Devices) (boilers, thermostats, solar modules, mixer modules, heat pumps, gateways, switches, heat sources) - Support for more than [110+ EMS devices](https://emsesp.github.io/docs/All-Devices/) (boilers, thermostats, solar modules, mixer modules, heat pumps, gateways, switches, heat sources)
## **Documentation** ## **Documentation**

View File

@@ -1,5 +1,5 @@
{ {
"adapter": "react", "adapter": "react",
"baseLocale": "pl", "baseLocale": "pl",
"$schema": "https://unpkg.com/typesafe-i18n@5.25.1/schema/typesafe-i18n.json" "$schema": "https://unpkg.com/typesafe-i18n@5.26.0/schema/typesafe-i18n.json"
} }

View File

@@ -22,13 +22,14 @@
"@alova/adapter-xhr": "^1.0.1", "@alova/adapter-xhr": "^1.0.1",
"@emotion/react": "^11.11.1", "@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0", "@emotion/styled": "^11.11.0",
"@mui/icons-material": "^5.14.1", "@mui/icons-material": "^5.14.3",
"@mui/material": "^5.14.2", "@mui/material": "^5.14.3",
"@preact/compat": "^17.1.2", "@preact/compat": "^17.1.2",
"@prefresh/vite": "^2.4.1",
"@table-library/react-table-library": "4.1.4", "@table-library/react-table-library": "4.1.4",
"@types/lodash-es": "^4.17.8", "@types/lodash-es": "^4.17.8",
"@types/node": "^20.4.5", "@types/node": "^20.4.8",
"@types/react": "^18.2.17", "@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7", "@types/react-dom": "^18.2.7",
"@types/react-router-dom": "^5.3.3", "@types/react-router-dom": "^5.3.3",
"alova": "^2.9.3", "alova": "^2.9.3",
@@ -45,18 +46,19 @@
"react-router-dom": "^6.14.2", "react-router-dom": "^6.14.2",
"react-toastify": "^9.1.3", "react-toastify": "^9.1.3",
"sockette": "^2.0.6", "sockette": "^2.0.6",
"typesafe-i18n": "^5.25.1", "typesafe-i18n": "^5.26.0",
"typescript": "^5.1.6" "typescript": "^5.1.6"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.22.10",
"@preact/preset-vite": "^2.5.0", "@preact/preset-vite": "^2.5.0",
"@typescript-eslint/eslint-plugin": "^6.2.0", "@types/babel__core": "^7",
"@typescript-eslint/parser": "^6.2.0", "@typescript-eslint/eslint-plugin": "^6.3.0",
"cspell": "^6.31.2", "@typescript-eslint/parser": "^6.3.0",
"eslint": "^8.46.0", "eslint": "^8.46.0",
"eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-airbnb-typescript": "^17.1.0",
"eslint-config-prettier": "^8.9.0", "eslint-config-prettier": "^9.0.0",
"eslint-import-resolver-typescript": "^3.5.5", "eslint-import-resolver-typescript": "^3.5.5",
"eslint-plugin-autofix": "^1.1.0", "eslint-plugin-autofix": "^1.1.0",
"eslint-plugin-import": "^2.28.0", "eslint-plugin-import": "^2.28.0",
@@ -66,10 +68,10 @@
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"nodemon": "^3.0.1", "nodemon": "^3.0.1",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^3.0.0", "prettier": "^3.0.1",
"rollup-plugin-visualizer": "^5.9.2", "rollup-plugin-visualizer": "^5.9.2",
"terser": "^5.19.2", "terser": "^5.19.2",
"vite": "^4.4.7", "vite": "^4.4.9",
"vite-plugin-svgr": "^3.2.0", "vite-plugin-svgr": "^3.2.0",
"vite-tsconfig-paths": "^4.2.0" "vite-tsconfig-paths": "^4.2.0"
}, },

View File

@@ -1,5 +1,5 @@
import ForwardIcon from '@mui/icons-material/Forward'; import ForwardIcon from '@mui/icons-material/Forward';
import { Box, Fab, Paper, Typography, Button } from '@mui/material'; import { Box, Paper, Typography, MenuItem, TextField, Button } from '@mui/material';
import { useRequest } from 'alova'; import { useRequest } from 'alova';
import { useContext, useState } from 'react'; import { useContext, useState } from 'react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
@@ -7,12 +7,12 @@ import { FeaturesContext } from './contexts/features';
import type { ValidateFieldsError } from 'async-validator'; import type { ValidateFieldsError } from 'async-validator';
import type { Locales } from 'i18n/i18n-types'; import type { Locales } from 'i18n/i18n-types';
import type { FC } from 'react'; import type { ChangeEventHandler, FC } from 'react';
import type { SignInRequest } from 'types'; import type { SignInRequest } from 'types';
import * as AuthenticationApi from 'api/authentication'; import * as AuthenticationApi from 'api/authentication';
import { PROJECT_NAME } from 'api/env'; import { PROJECT_NAME } from 'api/env';
import { ValidatedTextField } from 'components'; import { ValidatedPasswordField, ValidatedTextField } from 'components';
import { AuthenticationContext } from 'contexts/authentication'; import { AuthenticationContext } from 'contexts/authentication';
import { ReactComponent as DEflag } from 'i18n/DE.svg'; import { ReactComponent as DEflag } from 'i18n/DE.svg';
@@ -82,7 +82,8 @@ const SignIn: FC = () => {
const submitOnEnter = onEnterCallback(signIn); const submitOnEnter = onEnterCallback(signIn);
const selectLocale = async (loc: Locales) => { const onLocaleSelected: ChangeEventHandler<HTMLInputElement> = async ({ target }) => {
const loc = target.value as Locales;
localStorage.setItem('lang', loc); localStorage.setItem('lang', loc);
await loadLocaleAsync(loc); await loadLocaleAsync(loc);
setLocale(loc); setLocale(loc);
@@ -111,82 +112,79 @@ const SignIn: FC = () => {
> >
<Typography variant="h4">{PROJECT_NAME}</Typography> <Typography variant="h4">{PROJECT_NAME}</Typography>
<Typography variant="subtitle2">{features.version}</Typography> <Typography variant="subtitle2">{features.version}</Typography>
<Box
mt={2}
mb={2}
sx={{
'& button, & a, & .MuiCard-root': {
mt: 1,
mx: 1
}
}}
>
<Button size="small" variant={locale === 'de' ? 'contained' : 'outlined'} onClick={() => selectLocale('de')}>
<DEflag style={{ width: 24 }} />
&nbsp;DE
</Button>
<Button size="small" variant={locale === 'en' ? 'contained' : 'outlined'} onClick={() => selectLocale('en')}>
<GBflag style={{ width: 24 }} />
&nbsp;EN
</Button>
<Button size="small" variant={locale === 'fr' ? 'contained' : 'outlined'} onClick={() => selectLocale('fr')}>
<FRflag style={{ width: 24 }} />
&nbsp;FR
</Button>
<Button size="small" variant={locale === 'it' ? 'contained' : 'outlined'} onClick={() => selectLocale('it')}>
<ITflag style={{ width: 24 }} />
&nbsp;IT
</Button>
<Button size="small" variant={locale === 'nl' ? 'contained' : 'outlined'} onClick={() => selectLocale('nl')}>
<NLflag style={{ width: 24 }} />
&nbsp;NL
</Button>
<Button size="small" variant={locale === 'no' ? 'contained' : 'outlined'} onClick={() => selectLocale('no')}>
<NOflag style={{ width: 24 }} />
&nbsp;NO
</Button>
<Button size="small" variant={locale === 'pl' ? 'contained' : 'outlined'} onClick={() => selectLocale('pl')}>
<PLflag style={{ width: 24 }} />
&nbsp;PL
</Button>
<Button size="small" variant={locale === 'sv' ? 'contained' : 'outlined'} onClick={() => selectLocale('sv')}>
<SVflag style={{ width: 24 }} />
&nbsp;SV
</Button>
<Button size="small" variant={locale === 'tr' ? 'contained' : 'outlined'} onClick={() => selectLocale('tr')}>
<TRflag style={{ width: 24 }} />
&nbsp;TR
</Button>
</Box>
<TextField name="locale" variant="outlined" value={locale} onChange={onLocaleSelected} size="small" select>
<MenuItem key="de" value="de">
<DEflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;DE
</MenuItem>
<MenuItem key="en" value="en">
<GBflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;EN
</MenuItem>
<MenuItem key="fr" value="fr">
<FRflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;FR
</MenuItem>
<MenuItem key="it" value="it">
<ITflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;IT
</MenuItem>
<MenuItem key="nl" value="nl">
<NLflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;NL
</MenuItem>
<MenuItem key="no" value="no">
<NOflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;NO
</MenuItem>
<MenuItem key="pl" value="pl">
<PLflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;PL
</MenuItem>
<MenuItem key="sv" value="sv">
<SVflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;SV
</MenuItem>
<MenuItem key="tr" value="tr">
<TRflag style={{ width: 16, verticalAlign: 'middle' }} />
&nbsp;TR
</MenuItem>
</TextField>
<Box display="flex" flexDirection="column" alignItems="center">
<ValidatedTextField <ValidatedTextField
fieldErrors={fieldErrors} fieldErrors={fieldErrors}
disabled={processing} disabled={processing}
sx={{
width: 240
}}
name="username" name="username"
label={LL.USERNAME(0)} label={LL.USERNAME(0)}
value={signInRequest.username} value={signInRequest.username}
onChange={updateLoginRequestValue} onChange={updateLoginRequestValue}
margin="normal" margin="normal"
variant="outlined" variant="outlined"
fullWidth
/> />
<ValidatedTextField <ValidatedPasswordField
fieldErrors={fieldErrors} fieldErrors={fieldErrors}
disabled={processing} disabled={processing}
type="password" sx={{
width: 240
}}
name="password" name="password"
label={LL.PASSWORD()} label={LL.PASSWORD()}
value={signInRequest.password} value={signInRequest.password}
onChange={updateLoginRequestValue} onChange={updateLoginRequestValue}
onKeyDown={submitOnEnter} onKeyDown={submitOnEnter}
margin="normal"
variant="outlined" variant="outlined"
fullWidth
/> />
<Fab variant="extended" color="primary" sx={{ mt: 2 }} onClick={validateAndSignIn} disabled={processing}> </Box>
<Button variant="contained" color="primary" sx={{ mt: 2 }} onClick={validateAndSignIn} disabled={processing}>
<ForwardIcon sx={{ mr: 1 }} /> <ForwardIcon sx={{ mr: 1 }} />
{LL.SIGN_IN()} {LL.SIGN_IN()}
</Fab> </Button>
</Paper> </Paper>
</Box> </Box>
); );

View File

@@ -54,7 +54,7 @@ export const alovaInstance = createAlova({
}); });
export const alovaInstanceGH = createAlova({ export const alovaInstanceGH = createAlova({
baseURL: 'https://api.github.com/repos/emsesp/EMS-ESP32', baseURL: 'https://api.github.com/repos/emsesp/EMS-ESP32/releases',
statesHook: ReactHook, statesHook: ReactHook,
requestAdapter: xhrRequestAdapter() requestAdapter: xhrRequestAdapter()
}); });

View File

@@ -1,5 +1,5 @@
import { alovaInstance, alovaInstanceGH } from './endpoints'; import { alovaInstance, alovaInstanceGH } from './endpoints';
import type { OTASettings, SystemStatus, LogSettings, Version } from 'types'; import type { OTASettings, SystemStatus, LogSettings } from 'types';
// SystemStatus - also used to ping in Restart monitor for pinging // SystemStatus - also used to ping in Restart monitor for pinging
export const readSystemStatus = () => alovaInstance.Get<SystemStatus>('/rest/systemStatus'); export const readSystemStatus = () => alovaInstance.Get<SystemStatus>('/rest/systemStatus');
@@ -20,24 +20,15 @@ export const fetchLog = () => alovaInstance.Post('/rest/fetchLog');
// Get versions from github // Get versions from github
export const getStableVersion = () => export const getStableVersion = () =>
alovaInstanceGH.Get<Version>('releases/latest', { alovaInstanceGH.Get('latest', {
transformData(response: any) { transformData(response: any) {
return { return response.data.name.substring(1);
version: response.data.name,
url: response.data.assets[1].browser_download_url,
changelog: response.data.assets[0].browser_download_url
};
} }
}); });
export const getDevVersion = () => export const getDevVersion = () =>
alovaInstanceGH.Get<Version>('releases/tags/latest', { alovaInstanceGH.Get('tags/latest', {
transformData(response: any) { transformData(response: any) {
return { return response.data.name.split(/\s+/).splice(-1)[0].substring(1);
version: response.data.name.split(/\s+/).splice(-1),
url: response.data.assets[1].browser_download_url,
changelog: response.data.assets[0].browser_download_url
};
} }
}); });

View File

@@ -23,26 +23,22 @@ import {
List, List,
ListItem, ListItem,
ListItemAvatar, ListItemAvatar,
ListItemText, ListItemText
Link,
Typography
} from '@mui/material'; } from '@mui/material';
import { useRequest } from 'alova'; import { useRequest } from 'alova';
import { useContext, useState } from 'react'; import { useContext, useState } from 'react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { FeaturesContext } from '../../contexts/features';
import RestartMonitor from './RestartMonitor'; import RestartMonitor from './RestartMonitor';
import SystemStatusVersionDialog from './SystemStatusVersionDialog';
import type { FC } from 'react'; import type { FC } from 'react';
import * as SystemApi from 'api/system'; import * as SystemApi from 'api/system';
import { ButtonRow, FormLoader, SectionContent, MessageBox } from 'components'; import { ButtonRow, FormLoader, SectionContent } from 'components';
import { AuthenticatedContext } from 'contexts/authentication'; import { AuthenticatedContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react'; import { useI18nContext } from 'i18n/i18n-react';
export const VERSIONCHECK_ENDPOINT = 'https://api.github.com/repos/emsesp/EMS-ESP32/releases/latest';
export const VERSIONCHECK_DEV_ENDPOINT = 'https://api.github.com/repos/emsesp/EMS-ESP32/releases/tags/latest';
export const uploadURL = window.location.origin + '/system/upload';
function formatNumber(num: number) { function formatNumber(num: number) {
return new Intl.NumberFormat().format(num); return new Intl.NumberFormat().format(num);
} }
@@ -54,8 +50,10 @@ const SystemStatusForm: FC = () => {
const [confirmRestart, setConfirmRestart] = useState<boolean>(false); const [confirmRestart, setConfirmRestart] = useState<boolean>(false);
const [confirmFactoryReset, setConfirmFactoryReset] = useState<boolean>(false); const [confirmFactoryReset, setConfirmFactoryReset] = useState<boolean>(false);
const [processing, setProcessing] = useState<boolean>(false); const [processing, setProcessing] = useState<boolean>(false);
const [showingVersion, setShowingVersion] = useState<boolean>(false);
const [restarting, setRestarting] = useState<boolean>(); const [restarting, setRestarting] = useState<boolean>();
const [versionDialogOpen, setVersionDialogOpen] = useState<boolean>(false);
const { features } = useContext(FeaturesContext);
const { send: restartCommand } = useRequest(SystemApi.restart(), { const { send: restartCommand } = useRequest(SystemApi.restart(), {
immediate: false immediate: false
@@ -69,10 +67,6 @@ const SystemStatusForm: FC = () => {
immediate: false immediate: false
}); });
// fetch versions from GH on load
const { data: latestVersion } = useRequest(SystemApi.getStableVersion);
const { data: latestDevVersion } = useRequest(SystemApi.getDevVersion);
const { data: data, send: loadData, error } = useRequest(SystemApi.readSystemStatus, { force: true }); const { data: data, send: loadData, error } = useRequest(SystemApi.readSystemStatus, { force: true });
const restart = async () => { const restart = async () => {
@@ -158,60 +152,6 @@ const SystemStatusForm: FC = () => {
</Dialog> </Dialog>
); );
const renderVersionDialog = () => (
<Dialog open={showingVersion} onClose={() => setShowingVersion(false)}>
<DialogTitle>{LL.VERSION_CHECK(1)}</DialogTitle>
<DialogContent dividers>
<MessageBox my={0} level="info" message={LL.VERSION_ON() + ' v' + data?.emsesp_version} />
{latestVersion && (
<Box mt={2} mb={2}>
{LL.THE_LATEST()}&nbsp;<u>{LL.OFFICIAL()}</u>&nbsp;{LL.RELEASE_IS()}&nbsp;<b>{latestVersion.version}</b>
&nbsp;(
<Link target="_blank" href={latestVersion.changelog} color="primary">
{LL.RELEASE_NOTES()}
</Link>
)&nbsp;(
<Link target="_blank" href={latestVersion.url} color="primary">
{LL.DOWNLOAD(1)}
</Link>
)
</Box>
)}
{latestDevVersion && (
<Box mt={2} mb={2}>
{LL.THE_LATEST()}&nbsp;<u>{LL.DEVELOPMENT()}</u>&nbsp;{LL.RELEASE_IS()}&nbsp;
<b>{latestDevVersion.version}</b>
&nbsp;(
<Link target="_blank" href={latestDevVersion.changelog} color="primary">
{LL.RELEASE_NOTES()}
</Link>
)&nbsp;(
<Link target="_blank" href={latestDevVersion.url} color="primary">
{LL.DOWNLOAD(1)}
</Link>
)
</Box>
)}
<Box color="warning.main" p={0} pl={0} pr={0} mt={4} mb={0}>
<Typography variant="body2">
{LL.USE()}&nbsp;
<Link href={uploadURL} color="primary">
{LL.UPLOAD()}
</Link>
&nbsp;{LL.SYSTEM_APPLY_FIRMWARE()}
</Typography>
</Box>
</DialogContent>
<DialogActions>
<Button variant="outlined" onClick={() => setShowingVersion(false)} color="secondary">
{LL.CLOSE()}
</Button>
</DialogActions>
</Dialog>
);
const renderFactoryResetDialog = () => ( const renderFactoryResetDialog = () => (
<Dialog open={confirmFactoryReset} onClose={() => setConfirmFactoryReset(false)}> <Dialog open={confirmFactoryReset} onClose={() => setConfirmFactoryReset(false)}>
<DialogTitle>{LL.FACTORY_RESET()}</DialogTitle> <DialogTitle>{LL.FACTORY_RESET()}</DialogTitle>
@@ -253,12 +193,10 @@ const SystemStatusForm: FC = () => {
<BuildIcon /> <BuildIcon />
</Avatar> </Avatar>
</ListItemAvatar> </ListItemAvatar>
<ListItemText primary={LL.EMS_ESP_VER()} secondary={'v' + data.emsesp_version} /> <ListItemText primary={LL.EMS_ESP_VER()} secondary={data.emsesp_version} />
{latestVersion && ( <Button color="primary" onClick={() => setVersionDialogOpen(true)}>
<Button color="primary" onClick={() => setShowingVersion(true)}>
{LL.VERSION_CHECK(0)} {LL.VERSION_CHECK(0)}
</Button> </Button>
)}
</ListItem> </ListItem>
<Divider variant="inset" component="li" /> <Divider variant="inset" component="li" />
<ListItem> <ListItem>
@@ -386,7 +324,6 @@ const SystemStatusForm: FC = () => {
</Box> </Box>
)} )}
</Box> </Box>
{renderVersionDialog()}
{renderRestartDialog()} {renderRestartDialog()}
{renderFactoryResetDialog()} {renderFactoryResetDialog()}
</> </>
@@ -396,6 +333,14 @@ const SystemStatusForm: FC = () => {
return ( return (
<SectionContent title={LL.STATUS_OF(LL.SYSTEM(1))} titleGutter> <SectionContent title={LL.STATUS_OF(LL.SYSTEM(1))} titleGutter>
{restarting ? <RestartMonitor /> : content()} {restarting ? <RestartMonitor /> : content()}
{data && (
<SystemStatusVersionDialog
open={versionDialogOpen}
onClose={() => setVersionDialogOpen(false)}
version={data.emsesp_version}
platform={features.platform}
/>
)}
</SectionContent> </SectionContent>
); );
}; };

View File

@@ -0,0 +1,108 @@
import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, Link, Typography } from '@mui/material';
import { useRequest } from 'alova';
import { useCallback, useEffect } from 'react';
import * as SystemApi from 'api/system';
import MessageBox from 'components/MessageBox';
import { useI18nContext } from 'i18n/i18n-react';
type SystemStatusVersionDialogProps = {
open: boolean;
onClose: () => void;
version: string;
platform: string;
};
const SystemStatusVersionDialog = ({ open, onClose, version, platform }: SystemStatusVersionDialogProps) => {
const { LL } = useI18nContext();
const { send: getLatestVersion, data: latestVersion } = useRequest(SystemApi.getStableVersion, {
immediate: false,
force: true
});
const { send: getLatestDevVersion, data: latestDevVersion } = useRequest(SystemApi.getDevVersion, {
immediate: false,
force: true
});
const STABLE_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/';
const DEV_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/latest/';
const uploadURL = window.location.origin + '/system/upload';
const connected = latestVersion && latestDevVersion;
const getVersions = useCallback(async () => {
await getLatestVersion();
await getLatestDevVersion();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (open) {
void getVersions();
}
}, [getVersions, open]);
const getBinURL = (v: string) => 'EMS-ESP-' + v.replaceAll('.', '_') + '-' + platform.replaceAll('-', '_') + '.bin';
return (
<Dialog open={open} onClose={onClose}>
<DialogTitle>{LL.VERSION_CHECK(1)}</DialogTitle>
<DialogContent dividers>
<MessageBox my={0} level="info" message={LL.VERSION_ON() + ' ' + version + ' (' + platform + ')'} />
{latestVersion && (
<Box mt={2} mb={2}>
{LL.THE_LATEST()}&nbsp;<b>{LL.OFFICIAL()}</b>&nbsp;{LL.RELEASE_IS()}&nbsp;<b>{latestVersion}</b>
&nbsp;(
<Link target="_blank" href={STABLE_URL + 'v' + latestVersion + '/CHANGELOG.md'} color="primary">
{LL.RELEASE_NOTES()}
</Link>
)&nbsp;(
<Link
target="_blank"
href={STABLE_URL + 'v' + latestVersion + '/' + getBinURL(latestVersion)}
color="primary"
>
{LL.DOWNLOAD(1)}
</Link>
)
</Box>
)}
{latestDevVersion && (
<Box mt={2} mb={2}>
{LL.THE_LATEST()}&nbsp;<b>{LL.DEVELOPMENT()}</b>&nbsp;{LL.RELEASE_IS()}&nbsp;
<b>{latestDevVersion}</b>
&nbsp;(
<Link target="_blank" href={DEV_URL + 'CHANGELOG_LATEST.md'} color="primary">
{LL.RELEASE_NOTES()}
</Link>
)&nbsp;(
<Link target="_blank" href={DEV_URL + getBinURL(latestDevVersion)} color="primary">
{LL.DOWNLOAD(1)}
</Link>
)
</Box>
)}
{connected && (
<Box color="warning.main" mt={2}>
<Typography variant="body2">
{LL.USE()}&nbsp;
<Link href={uploadURL} color="primary">
{LL.UPLOAD()}
</Link>
&nbsp;{LL.SYSTEM_APPLY_FIRMWARE()}
</Typography>
</Box>
)}
{!connected && <MessageBox my={2} level="warning" message="No internet connection" />}
</DialogContent>
<DialogActions>
<Button variant="outlined" onClick={onClose} color="secondary">
{LL.CLOSE()}
</Button>
</DialogActions>
</Dialog>
);
};
export default SystemStatusVersionDialog;

View File

@@ -180,7 +180,7 @@ const en: Translation = {
LOG_OF: '{0} Log', LOG_OF: '{0} Log',
STATUS_OF: '{0} Status', STATUS_OF: '{0} Status',
UPLOAD_DOWNLOAD: 'Upload/Download', UPLOAD_DOWNLOAD: 'Upload/Download',
VERSION_ON: 'You are currently on', VERSION_ON: 'You are currently on version',
SYSTEM_APPLY_FIRMWARE: 'to apply the new firmware', SYSTEM_APPLY_FIRMWARE: 'to apply the new firmware',
CLOSE: 'Close', CLOSE: 'Close',
USE: 'Use', USE: 'Use',

View File

@@ -180,7 +180,7 @@ const nl: Translation = {
LOG_OF: '{0} Log', LOG_OF: '{0} Log',
STATUS_OF: '{0} Status', STATUS_OF: '{0} Status',
UPLOAD_DOWNLOAD: 'Upload/Download', UPLOAD_DOWNLOAD: 'Upload/Download',
VERSION_ON: 'U bevindt zich momenteel op', VERSION_ON: 'U bevindt zich momenteel op versie',
SYSTEM_APPLY_FIRMWARE: 'om de nieuwe firmware te activeren', SYSTEM_APPLY_FIRMWARE: 'om de nieuwe firmware te activeren',
CLOSE: 'Sluiten', CLOSE: 'Sluiten',
USE: 'Gebruik', USE: 'Gebruik',

View File

@@ -47,9 +47,3 @@ export interface LogSettings {
max_messages: number; max_messages: number;
compact: false; compact: false;
} }
export interface Version {
version: string;
url: string;
changelog: string;
}

View File

@@ -4,6 +4,7 @@ import svgrPlugin from 'vite-plugin-svgr';
import { visualizer } from 'rollup-plugin-visualizer'; import { visualizer } from 'rollup-plugin-visualizer';
import ProgmemGenerator from './progmem-generator'; import ProgmemGenerator from './progmem-generator';
import preact from '@preact/preset-vite'; import preact from '@preact/preset-vite';
// import prefresh from '@prefresh/vite';
export default defineConfig(({ command, mode }) => { export default defineConfig(({ command, mode }) => {
if (mode === 'hosted') { if (mode === 'hosted') {
@@ -17,8 +18,9 @@ export default defineConfig(({ command, mode }) => {
plugins: [ plugins: [
preact(), preact(),
viteTsconfigPaths(), viteTsconfigPaths(),
svgrPlugin(), svgrPlugin()
ProgmemGenerator({ outputPath: '../lib/framework/WWWData.h', bytesPerLine: 20 }) // prefresh()
// ProgmemGenerator({ outputPath: '../lib/framework/WWWData.h', bytesPerLine: 20 })
], ],
build: { build: {
@@ -67,3 +69,6 @@ export default defineConfig(({ command, mode }) => {
}; };
} }
}); });
function prefresh(): PluginOption {
throw new Error('Function not implemented.');
}

File diff suppressed because it is too large Load Diff

View File

@@ -324,6 +324,7 @@ security_settings = {
}; };
const features = { const features = {
version: 'v3.6.0-demo', version: 'v3.6.0-demo',
// platform: 'ESP32'
platform: 'ESP32-S3' platform: 'ESP32-S3'
}; };
const verify_authentication = { access_token: '1234' }; const verify_authentication = { access_token: '1234' };

View File

@@ -39,7 +39,7 @@ unbuild_flags =
${common.core_unbuild_flags} ${common.core_unbuild_flags}
[espressi32_base] [espressi32_base]
platform = espressif32 platform = espressif32@6.3.2
framework = arduino framework = arduino
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
build_unflags = ${common.unbuild_flags} build_unflags = ${common.unbuild_flags}
@@ -64,8 +64,7 @@ check_flags =
; build for GitHub Actions CI ; build for GitHub Actions CI
; the Web interface is built seperately ; the Web interface is built seperately
[env:ci] [env:ci]
platform = espressif32 extends = espressi32_base
framework = arduino
extra_scripts = scripts/rename_fw.py extra_scripts = scripts/rename_fw.py
board = esp32dev board = esp32dev
board_build.partitions = esp32_partition_4M.csv board_build.partitions = esp32_partition_4M.csv
@@ -75,8 +74,7 @@ build_unflags = ${common.unbuild_flags}
; for github Actions actually standard platform is buggy, use dev-platform ; for github Actions actually standard platform is buggy, use dev-platform
[env:ci_s3] [env:ci_s3]
platform = https://github.com/platformio/platform-espressif32.git extends = espressi32_base
framework = arduino
extra_scripts = scripts/rename_fw.py extra_scripts = scripts/rename_fw.py
board = lolin_s3 board = lolin_s3
board_build.f_cpu = 240000000L board_build.f_cpu = 240000000L

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.6.0-dev.14" #define EMSESP_APP_VERSION "3.6.0-dev.16"