Enhance version check to differentiate between ESP32 and ESP32-S3 bin versions #1240

This commit is contained in:
proddy
2023-08-04 16:42:37 +02:00
parent 0cc14215e6
commit 9b92bfa81c
10 changed files with 174 additions and 993 deletions

View File

@@ -25,10 +25,9 @@
"@mui/icons-material": "^5.14.3", "@mui/icons-material": "^5.14.3",
"@mui/material": "^5.14.3", "@mui/material": "^5.14.3",
"@preact/compat": "^17.1.2", "@preact/compat": "^17.1.2",
"@prefresh/core": "^1.5.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.7",
"@types/react": "^18.2.18", "@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",
@@ -52,15 +51,13 @@
"devDependencies": { "devDependencies": {
"@babel/core": "^7.22.9", "@babel/core": "^7.22.9",
"@preact/preset-vite": "^2.5.0", "@preact/preset-vite": "^2.5.0",
"@prefresh/vite": "^2.4.1",
"@types/babel__core": "^7", "@types/babel__core": "^7",
"@typescript-eslint/eslint-plugin": "^6.2.1", "@typescript-eslint/eslint-plugin": "^6.2.1",
"@typescript-eslint/parser": "^6.2.1", "@typescript-eslint/parser": "^6.2.1",
"cspell": "^6.31.2",
"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": "^8.10.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",
@@ -70,7 +67,7 @@
"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.8", "vite": "^4.4.8",

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;
}

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' };