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/material": "^5.14.3",
"@preact/compat": "^17.1.2",
"@prefresh/core": "^1.5.1",
"@table-library/react-table-library": "4.1.4",
"@types/lodash-es": "^4.17.8",
"@types/node": "^20.4.5",
"@types/node": "^20.4.7",
"@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7",
"@types/react-router-dom": "^5.3.3",
@@ -52,15 +51,13 @@
"devDependencies": {
"@babel/core": "^7.22.9",
"@preact/preset-vite": "^2.5.0",
"@prefresh/vite": "^2.4.1",
"@types/babel__core": "^7",
"@typescript-eslint/eslint-plugin": "^6.2.1",
"@typescript-eslint/parser": "^6.2.1",
"cspell": "^6.31.2",
"eslint": "^8.46.0",
"eslint-config-airbnb": "^19.0.4",
"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-plugin-autofix": "^1.1.0",
"eslint-plugin-import": "^2.28.0",
@@ -70,7 +67,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"nodemon": "^3.0.1",
"npm-run-all": "^4.1.5",
"prettier": "^3.0.0",
"prettier": "^3.0.1",
"rollup-plugin-visualizer": "^5.9.2",
"terser": "^5.19.2",
"vite": "^4.4.8",

View File

@@ -54,7 +54,7 @@ export const alovaInstance = 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,
requestAdapter: xhrRequestAdapter()
});

View File

@@ -1,5 +1,5 @@
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
export const readSystemStatus = () => alovaInstance.Get<SystemStatus>('/rest/systemStatus');
@@ -20,24 +20,15 @@ export const fetchLog = () => alovaInstance.Post('/rest/fetchLog');
// Get versions from github
export const getStableVersion = () =>
alovaInstanceGH.Get<Version>('releases/latest', {
alovaInstanceGH.Get('latest', {
transformData(response: any) {
return {
version: response.data.name,
url: response.data.assets[1].browser_download_url,
changelog: response.data.assets[0].browser_download_url
};
return response.data.name.substring(1);
}
});
export const getDevVersion = () =>
alovaInstanceGH.Get<Version>('releases/tags/latest', {
alovaInstanceGH.Get('tags/latest', {
transformData(response: any) {
return {
version: response.data.name.split(/\s+/).splice(-1),
url: response.data.assets[1].browser_download_url,
changelog: response.data.assets[0].browser_download_url
};
return response.data.name.split(/\s+/).splice(-1)[0].substring(1);
}
});

View File

@@ -23,26 +23,22 @@ import {
List,
ListItem,
ListItemAvatar,
ListItemText,
Link,
Typography
ListItemText
} from '@mui/material';
import { useRequest } from 'alova';
import { useContext, useState } from 'react';
import { toast } from 'react-toastify';
import { FeaturesContext } from '../../contexts/features';
import RestartMonitor from './RestartMonitor';
import SystemStatusVersionDialog from './SystemStatusVersionDialog';
import type { FC } from 'react';
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 { 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) {
return new Intl.NumberFormat().format(num);
}
@@ -54,8 +50,10 @@ const SystemStatusForm: FC = () => {
const [confirmRestart, setConfirmRestart] = useState<boolean>(false);
const [confirmFactoryReset, setConfirmFactoryReset] = useState<boolean>(false);
const [processing, setProcessing] = useState<boolean>(false);
const [showingVersion, setShowingVersion] = useState<boolean>(false);
const [restarting, setRestarting] = useState<boolean>();
const [versionDialogOpen, setVersionDialogOpen] = useState<boolean>(false);
const { features } = useContext(FeaturesContext);
const { send: restartCommand } = useRequest(SystemApi.restart(), {
immediate: false
@@ -69,10 +67,6 @@ const SystemStatusForm: FC = () => {
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 restart = async () => {
@@ -158,60 +152,6 @@ const SystemStatusForm: FC = () => {
</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 = () => (
<Dialog open={confirmFactoryReset} onClose={() => setConfirmFactoryReset(false)}>
<DialogTitle>{LL.FACTORY_RESET()}</DialogTitle>
@@ -253,12 +193,10 @@ const SystemStatusForm: FC = () => {
<BuildIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary={LL.EMS_ESP_VER()} secondary={'v' + data.emsesp_version} />
{latestVersion && (
<Button color="primary" onClick={() => setShowingVersion(true)}>
{LL.VERSION_CHECK(0)}
</Button>
)}
<ListItemText primary={LL.EMS_ESP_VER()} secondary={data.emsesp_version} />
<Button color="primary" onClick={() => setVersionDialogOpen(true)}>
{LL.VERSION_CHECK(0)}
</Button>
</ListItem>
<Divider variant="inset" component="li" />
<ListItem>
@@ -386,7 +324,6 @@ const SystemStatusForm: FC = () => {
</Box>
)}
</Box>
{renderVersionDialog()}
{renderRestartDialog()}
{renderFactoryResetDialog()}
</>
@@ -396,6 +333,14 @@ const SystemStatusForm: FC = () => {
return (
<SectionContent title={LL.STATUS_OF(LL.SYSTEM(1))} titleGutter>
{restarting ? <RestartMonitor /> : content()}
{data && (
<SystemStatusVersionDialog
open={versionDialogOpen}
onClose={() => setVersionDialogOpen(false)}
version={data.emsesp_version}
platform={features.platform}
/>
)}
</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',
STATUS_OF: '{0} Status',
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',
CLOSE: 'Close',
USE: 'Use',

View File

@@ -180,7 +180,7 @@ const nl: Translation = {
LOG_OF: '{0} Log',
STATUS_OF: '{0} Status',
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',
CLOSE: 'Sluiten',
USE: 'Gebruik',

View File

@@ -47,9 +47,3 @@ export interface LogSettings {
max_messages: number;
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 = {
version: 'v3.6.0-demo',
// platform: 'ESP32'
platform: 'ESP32-S3'
};
const verify_authentication = { access_token: '1234' };