Merge pull request #2362 from proddy/dev

introduce system status in WebUI for easier monitoring of tasks
This commit is contained in:
Proddy
2025-01-20 17:42:07 +01:00
committed by GitHub
31 changed files with 11000 additions and 11085 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@ telegram_type_id,name,is_fetched
0x19,UBAMonitorSlow,
0x1A,UBASetPoints,
0x1C,UBAMaintenanceStatus,
0x1E,HydrTemp,
0x1E,WM10TempMessage,
0x23,JunkersSetMixer,fetched
0x26,UBASettingsWW,fetched
0x28,WeatherComp,fetched
@@ -109,10 +109,10 @@ telegram_type_id,name,is_fetched
0x02A0,RC300Curves,
0x02A1,RC300Curves,
0x02A2,RC300Curves,
0x02A5,EasyMonitor,
0x02A5,RC300Monitor,
0x02A6,RC300Monitor,
0x02A7,RC300Monitor,
0x02A8,RC300Monitor,
0x02A8,CRFMonitor,
0x02A9,RC300Monitor,
0x02AA,RC300Monitor,
0x02AB,RC300Monitor,
@@ -133,7 +133,7 @@ telegram_type_id,name,is_fetched
0x02BE,RC300Set,
0x02BF,RC300Set,
0x02C0,RC300Set,
0x02CC,HPPressure,fetched
0x02CC,RC300Set2,
0x02CD,MMPLUSConfigMessage,fetched
0x02CE,RC300Set2,
0x02D0,RC300Set2,
1 telegram_type_id name is_fetched
13 0x19 UBAMonitorSlow
14 0x1A UBASetPoints
15 0x1C UBAMaintenanceStatus
16 0x1E HydrTemp WM10TempMessage
17 0x23 JunkersSetMixer fetched
18 0x26 UBASettingsWW fetched
19 0x28 WeatherComp fetched
109 0x02A0 RC300Curves
110 0x02A1 RC300Curves
111 0x02A2 RC300Curves
112 0x02A5 EasyMonitor RC300Monitor
113 0x02A6 RC300Monitor
114 0x02A7 RC300Monitor
115 0x02A8 RC300Monitor CRFMonitor
116 0x02A9 RC300Monitor
117 0x02AA RC300Monitor
118 0x02AB RC300Monitor
133 0x02BE RC300Set
134 0x02BF RC300Set
135 0x02C0 RC300Set
136 0x02CC HPPressure RC300Set2 fetched
137 0x02CD MMPLUSConfigMessage fetched
138 0x02CE RC300Set2
139 0x02D0 RC300Set2

View File

@@ -44,7 +44,7 @@
"@babel/core": "^7.26.0",
"@eslint/js": "^9.18.0",
"@preact/compat": "^18.3.1",
"@preact/preset-vite": "^2.9.4",
"@preact/preset-vite": "^2.10.0",
"@trivago/prettier-plugin-sort-imports": "^5.2.1",
"@types/formidable": "^3",
"@types/node": "^22.10.7",
@@ -58,7 +58,7 @@
"rollup-plugin-visualizer": "^5.14.0",
"terser": "^5.37.0",
"typescript-eslint": "8.20.0",
"vite": "^6.0.7",
"vite": "^6.0.9",
"vite-plugin-imagemin": "^0.6.1",
"vite-tsconfig-paths": "^5.1.4"
},

View File

@@ -58,7 +58,7 @@ const AuthenticatedRouting = () => {
<Route path="/settings/ntp" element={<NTPSettings />} />
<Route path="/settings/ap" element={<APSettings />} />
<Route path="/settings/modules" element={<Modules />} />
<Route path="/settings/upload" element={<DownloadUpload />} />
<Route path="/settings/downloadUpload" element={<DownloadUpload />} />
<Route path="/settings/network/*" element={<Network />} />
<Route path="/settings/security/*" element={<Security />} />

View File

@@ -2,7 +2,7 @@ import type { LogSettings, SystemStatus } from 'types';
import { alovaInstance, alovaInstanceGH } from './endpoints';
// systemStatus - also used to ping in Restart monitor for pinging
// systemStatus - also used to ping in System Monitor for pinging
export const readSystemStatus = () =>
alovaInstance.Get<SystemStatus>('/rest/systemStatus');

View File

@@ -38,7 +38,7 @@ import {
import { useTheme } from '@table-library/react-table-library/theme';
import { dialogStyle } from 'CustomTheme';
import { useRequest } from 'alova/client';
import RestartMonitor from 'app/status/RestartMonitor';
import SystemMonitor from 'app/status/SystemMonitor';
import {
BlockNavigation,
ButtonRow,
@@ -737,7 +737,7 @@ const Customizations = () => {
return (
<SectionContent>
{blocker ? <BlockNavigation blocker={blocker} /> : null}
{restarting ? <RestartMonitor /> : renderContent()}
{restarting ? <SystemMonitor /> : renderContent()}
{selectedDeviceEntity && (
<SettingsCustomizationsDialog
open={dialogOpen}

View File

@@ -19,7 +19,7 @@ import {
import { readSystemStatus } from 'api/system';
import { useRequest } from 'alova/client';
import RestartMonitor from 'app/status/RestartMonitor';
import SystemMonitor from 'app/status/SystemMonitor';
import type { ValidateFieldsError } from 'async-validator';
import {
BlockFormControlLabel,
@@ -859,7 +859,7 @@ const ApplicationSettings = () => {
return (
<SectionContent>
{blocker ? <BlockNavigation blocker={blocker} /> : null}
{restarting ? <RestartMonitor /> : content()}
{restarting ? <SystemMonitor /> : content()}
</SectionContent>
);
};

View File

@@ -9,7 +9,7 @@ import { API, callAction } from 'api/app';
import { useRequest } from 'alova/client';
import type { APIcall } from 'app/main/types';
import RestartMonitor from 'app/status/RestartMonitor';
import SystemMonitor from 'app/status/SystemMonitor';
import {
FormLoader,
SectionContent,
@@ -123,7 +123,7 @@ const DownloadUpload = () => {
};
return (
<SectionContent>{restarting ? <RestartMonitor /> : content()}</SectionContent>
<SectionContent>{restarting ? <SystemMonitor /> : content()}</SectionContent>
);
};

View File

@@ -151,7 +151,7 @@ const Settings = () => {
bgcolor="#5d89f7"
label={LL.DOWNLOAD_UPLOAD()}
text={LL.DOWNLOAD_UPLOAD_1()}
to="upload"
to="downloadUpload"
/>
</List>

View File

@@ -24,7 +24,7 @@ import { getDevVersion, getStableVersion } from 'api/system';
import { dialogStyle } from 'CustomTheme';
import { useRequest } from 'alova/client';
import RestartMonitor from 'app/status/RestartMonitor';
import SystemMonitor from 'app/status/SystemMonitor';
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
import { useI18nContext } from 'i18n/i18n-react';
@@ -224,7 +224,7 @@ const Version = () => {
<>
<Box p={2} border="1px solid grey" borderRadius={2}>
<Typography mb={2} variant="h6" color="primary">
Firmware Version
Firmware&nbsp;{LL.VERSION()}
</Typography>
<Grid
@@ -360,7 +360,7 @@ const Version = () => {
};
return (
<SectionContent>{restarting ? <RestartMonitor /> : content()}</SectionContent>
<SectionContent>{restarting ? <SystemMonitor /> : content()}</SectionContent>
);
};

View File

@@ -43,7 +43,7 @@ import { updateValueDirty, useRest } from 'utils';
import { validate } from 'validators';
import { createNetworkSettingsValidator } from 'validators/network';
import RestartMonitor from '../../status/RestartMonitor';
import SystemMonitor from '../../status/SystemMonitor';
import { WiFiConnectionContext } from './WiFiConnectionContext';
import { isNetworkOpen, networkSecurityMode } from './WiFiNetworkSelector';
@@ -400,7 +400,7 @@ const NetworkSettings = () => {
return (
<SectionContent>
{blocker ? <BlockNavigation blocker={blocker} /> : null}
{restarting ? <RestartMonitor /> : content()}
{restarting ? <SystemMonitor /> : content()}
</SectionContent>
);
};

View File

@@ -1,85 +0,0 @@
import { useState } from 'react';
import {
Box,
CircularProgress,
Dialog,
DialogContent,
Typography
} from '@mui/material';
import { readSystemStatus } from 'api/system';
import { dialogStyle } from 'CustomTheme';
import { useRequest } from 'alova/client';
import MessageBox from 'components/MessageBox';
import { useI18nContext } from 'i18n/i18n-react';
import { useInterval } from 'utils';
const RestartMonitor = () => {
const [errorMessage, setErrorMessage] = useState<string>();
const { LL } = useI18nContext();
let count = 0;
const { data, send } = useRequest(readSystemStatus, {
force: true,
initialData: { status: 'Getting ready...' },
async middleware(_, next) {
if (count++ >= 1) {
// skip first request (1 second) to allow AsyncWS to send its response
await next();
}
}
})
.onSuccess((event) => {
if (event.data.status === 'ready' || event.data.status === undefined) {
document.location.href = '/';
}
})
.onError((error) => {
setErrorMessage(error.message);
});
useInterval(() => {
void send();
}, 1000); // check every second
return (
<Dialog fullWidth={true} sx={dialogStyle} open={true}>
<DialogContent dividers>
<Box m={0} py={0} display="flex" alignItems="center" flexDirection="column">
<Typography
color="secondary"
variant="h6"
fontWeight={400}
textAlign="center"
>
{data?.status === 'uploading'
? LL.WAIT_FIRMWARE()
: data?.status === 'restarting'
? LL.APPLICATION_RESTARTING()
: data?.status === 'ready'
? LL.RESTARTING_PRE()
: LL.RESTARTING_POST()}
&hellip;
</Typography>
<Typography mt={2} variant="h6" fontWeight={400} textAlign="center">
{LL.PLEASE_WAIT()}
</Typography>
{errorMessage ? (
<MessageBox my={2} level="error" message={errorMessage} />
) : (
<Box py={2}>
<CircularProgress size={32} />
</Box>
)}
</Box>
</DialogContent>
</Dialog>
);
};
export default RestartMonitor;

View File

@@ -40,7 +40,7 @@ import { NTPSyncStatus, NetworkConnectionStatus } from 'types';
import { useInterval } from 'utils';
import { formatDateTime } from 'utils/time';
import RestartMonitor from './RestartMonitor';
import SystemMonitor from './SystemMonitor';
const SystemStatus = () => {
const { LL } = useI18nContext();
@@ -349,7 +349,7 @@ const SystemStatus = () => {
};
return (
<SectionContent>{restarting ? <RestartMonitor /> : content()}</SectionContent>
<SectionContent>{restarting ? <SystemMonitor /> : content()}</SectionContent>
);
};

View File

@@ -0,0 +1,124 @@
import { useState } from 'react';
import CancelIcon from '@mui/icons-material/Cancel';
import {
Box,
Button,
CircularProgress,
Dialog,
DialogContent,
Typography
} from '@mui/material';
import { callAction } from 'api/app';
import { readSystemStatus } from 'api/system';
import { dialogStyle } from 'CustomTheme';
import { useRequest } from 'alova/client';
import MessageBox from 'components/MessageBox';
import { useI18nContext } from 'i18n/i18n-react';
import { SystemStatusCodes } from 'types';
import { useInterval } from 'utils';
const SystemMonitor = () => {
const [errorMessage, setErrorMessage] = useState<string>();
const { LL } = useI18nContext();
let count = 0;
const { send: setSystemStatus } = useRequest(
(status: string) => callAction({ action: 'systemStatus', param: status }),
{
immediate: false
}
);
const { data, send } = useRequest(readSystemStatus, {
force: true,
async middleware(_, next) {
if (count++ >= 1) {
// skip first request (1 second) to allow AsyncWS to send its response
await next();
}
}
})
.onSuccess((event) => {
if (
event.data.status === SystemStatusCodes.SYSTEM_STATUS_NORMAL ||
event.data.status === undefined
) {
document.location.href = '/';
} else if (
event.data.status === SystemStatusCodes.SYSTEM_STATUS_ERROR_UPLOAD
) {
setErrorMessage('Please check system logs for possible causes');
}
})
.onError((error) => {
setErrorMessage(error.message);
});
useInterval(() => {
void send();
}, 1000); // check every second
const onCancel = async () => {
setErrorMessage(undefined);
await setSystemStatus(
SystemStatusCodes.SYSTEM_STATUS_NORMAL as unknown as string
);
document.location.href = '/';
};
return (
<Dialog fullWidth={true} sx={dialogStyle} open={true}>
<DialogContent dividers>
<Box m={0} py={0} display="flex" alignItems="center" flexDirection="column">
<Typography
color="secondary"
variant="h6"
fontWeight={400}
textAlign="center"
>
{data?.status === SystemStatusCodes.SYSTEM_STATUS_UPLOADING
? LL.WAIT_FIRMWARE()
: data?.status === SystemStatusCodes.SYSTEM_STATUS_RESTART_REQUESTED
? LL.APPLICATION_RESTARTING()
: data?.status === SystemStatusCodes.SYSTEM_STATUS_NORMAL
? LL.RESTARTING_PRE()
: data?.status === SystemStatusCodes.SYSTEM_STATUS_ERROR_UPLOAD
? 'Upload Failed'
: LL.RESTARTING_POST()}
</Typography>
{errorMessage ? (
<MessageBox my={2} level="error" message={errorMessage}>
<Button
size="small"
sx={{ ml: 2 }}
startIcon={<CancelIcon />}
variant="contained"
color="error"
onClick={onCancel}
>
{LL.RESET(0)}
</Button>
</MessageBox>
) : (
<>
<Typography mt={2} variant="h6" fontWeight={400} textAlign="center">
{LL.PLEASE_WAIT()}&hellip;
</Typography>
<Box py={2}>
<CircularProgress size={32} />
</Box>
</>
)}
</Box>
</DialogContent>
</Dialog>
);
};
export default SystemMonitor;

View File

@@ -2,6 +2,15 @@ import type { busConnectionStatus } from 'app/main/types';
import type { NetworkConnectionStatus } from './network';
export enum SystemStatusCodes {
SYSTEM_STATUS_NORMAL = 0,
SYSTEM_STATUS_PENDING_UPLOAD = 1,
SYSTEM_STATUS_UPLOADING = 2,
SYSTEM_STATUS_ERROR_UPLOAD = 3,
SYSTEM_STATUS_PENDING_RESTART = 4,
SYSTEM_STATUS_RESTART_REQUESTED = 5
}
export interface SystemStatus {
emsesp_version: string;
bus_status: busConnectionStatus;
@@ -41,7 +50,7 @@ export interface SystemStatus {
model: string;
has_loader: boolean;
has_partition: boolean;
status: string;
status: number; // SystemStatusCodes which matches SYSTEM_STATUS in System.h
temperature?: number;
}

View File

@@ -33,7 +33,7 @@ __metadata:
languageName: node
linkType: hard
"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.22.13, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0, @babel/code-frame@npm:^7.26.2":
"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0, @babel/code-frame@npm:^7.26.2":
version: 7.26.2
resolution: "@babel/code-frame@npm:7.26.2"
dependencies:
@@ -766,7 +766,7 @@ __metadata:
languageName: node
linkType: hard
"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15":
"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0":
version: 1.5.0
resolution: "@jridgewell/sourcemap-codec@npm:1.5.0"
checksum: 10c0/2eb864f276eb1096c3c11da3e9bb518f6d9fc0023c78344cdc037abadc725172c70314bdb360f2d4b7bffec7f5d657ce006816bc5d4ecb35e61b66132db00c18
@@ -1014,11 +1014,10 @@ __metadata:
languageName: node
linkType: hard
"@preact/preset-vite@npm:^2.9.4":
version: 2.9.4
resolution: "@preact/preset-vite@npm:2.9.4"
"@preact/preset-vite@npm:^2.10.0":
version: 2.10.0
resolution: "@preact/preset-vite@npm:2.10.0"
dependencies:
"@babel/code-frame": "npm:^7.22.13"
"@babel/plugin-transform-react-jsx": "npm:^7.22.15"
"@babel/plugin-transform-react-jsx-development": "npm:^7.22.5"
"@prefresh/vite": "npm:^2.4.1"
@@ -1026,14 +1025,11 @@ __metadata:
babel-plugin-transform-hook-names: "npm:^1.0.2"
debug: "npm:^4.3.4"
kolorist: "npm:^1.8.0"
magic-string: "npm:0.30.5"
node-html-parser: "npm:^6.1.10"
source-map: "npm:^0.7.4"
stack-trace: "npm:^1.0.0-pre2"
vite-prerender-plugin: "npm:^0.5.3"
peerDependencies:
"@babel/core": 7.x
vite: 2.x || 3.x || 4.x || 5.x || 6.x
checksum: 10c0/a42aab866ef1ea4d2dac82be3a5b5c207c5e030d429cc5dbe88a259da0a52a1fd8f21f77d1ce2bef82a803b854f7653a579aed0aa7eca371108e5308ba43bc2f
checksum: 10c0/bb8ab0577fb3e91baab151b9682514a18d244efb97b5f26c3aed3878335603aa7f22696050e96c7eb7261456382f966b27594960a2251d5b5ee354796407023f
languageName: node
linkType: hard
@@ -1086,135 +1082,135 @@ __metadata:
languageName: node
linkType: hard
"@rollup/rollup-android-arm-eabi@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-android-arm-eabi@npm:4.30.1"
"@rollup/rollup-android-arm-eabi@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-android-arm-eabi@npm:4.31.0"
conditions: os=android & cpu=arm
languageName: node
linkType: hard
"@rollup/rollup-android-arm64@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-android-arm64@npm:4.30.1"
"@rollup/rollup-android-arm64@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-android-arm64@npm:4.31.0"
conditions: os=android & cpu=arm64
languageName: node
linkType: hard
"@rollup/rollup-darwin-arm64@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-darwin-arm64@npm:4.30.1"
"@rollup/rollup-darwin-arm64@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-darwin-arm64@npm:4.31.0"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"@rollup/rollup-darwin-x64@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-darwin-x64@npm:4.30.1"
"@rollup/rollup-darwin-x64@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-darwin-x64@npm:4.31.0"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"@rollup/rollup-freebsd-arm64@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-freebsd-arm64@npm:4.30.1"
"@rollup/rollup-freebsd-arm64@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-freebsd-arm64@npm:4.31.0"
conditions: os=freebsd & cpu=arm64
languageName: node
linkType: hard
"@rollup/rollup-freebsd-x64@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-freebsd-x64@npm:4.30.1"
"@rollup/rollup-freebsd-x64@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-freebsd-x64@npm:4.31.0"
conditions: os=freebsd & cpu=x64
languageName: node
linkType: hard
"@rollup/rollup-linux-arm-gnueabihf@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.30.1"
"@rollup/rollup-linux-arm-gnueabihf@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.31.0"
conditions: os=linux & cpu=arm & libc=glibc
languageName: node
linkType: hard
"@rollup/rollup-linux-arm-musleabihf@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.30.1"
"@rollup/rollup-linux-arm-musleabihf@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.31.0"
conditions: os=linux & cpu=arm & libc=musl
languageName: node
linkType: hard
"@rollup/rollup-linux-arm64-gnu@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.30.1"
"@rollup/rollup-linux-arm64-gnu@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.31.0"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
"@rollup/rollup-linux-arm64-musl@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-linux-arm64-musl@npm:4.30.1"
"@rollup/rollup-linux-arm64-musl@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-linux-arm64-musl@npm:4.31.0"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
"@rollup/rollup-linux-loongarch64-gnu@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.30.1"
"@rollup/rollup-linux-loongarch64-gnu@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.31.0"
conditions: os=linux & cpu=loong64 & libc=glibc
languageName: node
linkType: hard
"@rollup/rollup-linux-powerpc64le-gnu@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.30.1"
"@rollup/rollup-linux-powerpc64le-gnu@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.31.0"
conditions: os=linux & cpu=ppc64 & libc=glibc
languageName: node
linkType: hard
"@rollup/rollup-linux-riscv64-gnu@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.30.1"
"@rollup/rollup-linux-riscv64-gnu@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.31.0"
conditions: os=linux & cpu=riscv64 & libc=glibc
languageName: node
linkType: hard
"@rollup/rollup-linux-s390x-gnu@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.30.1"
"@rollup/rollup-linux-s390x-gnu@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.31.0"
conditions: os=linux & cpu=s390x & libc=glibc
languageName: node
linkType: hard
"@rollup/rollup-linux-x64-gnu@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-linux-x64-gnu@npm:4.30.1"
"@rollup/rollup-linux-x64-gnu@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-linux-x64-gnu@npm:4.31.0"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
"@rollup/rollup-linux-x64-musl@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-linux-x64-musl@npm:4.30.1"
"@rollup/rollup-linux-x64-musl@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-linux-x64-musl@npm:4.31.0"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
"@rollup/rollup-win32-arm64-msvc@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.30.1"
"@rollup/rollup-win32-arm64-msvc@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.31.0"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"@rollup/rollup-win32-ia32-msvc@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.30.1"
"@rollup/rollup-win32-ia32-msvc@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.31.0"
conditions: os=win32 & cpu=ia32
languageName: node
linkType: hard
"@rollup/rollup-win32-x64-msvc@npm:4.30.1":
version: 4.30.1
resolution: "@rollup/rollup-win32-x64-msvc@npm:4.30.1"
"@rollup/rollup-win32-x64-msvc@npm:4.31.0":
version: 4.31.0
resolution: "@rollup/rollup-win32-x64-msvc@npm:4.31.0"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
@@ -1363,11 +1359,11 @@ __metadata:
linkType: hard
"@types/imagemin@npm:*":
version: 9.0.0
resolution: "@types/imagemin@npm:9.0.0"
version: 9.0.1
resolution: "@types/imagemin@npm:9.0.1"
dependencies:
"@types/node": "npm:*"
checksum: 10c0/b68f227bd39357ea6b4d0c6b020906ba48e5cc8490b0e3aebc9540d662565fc523cf9578f7f53c9351ddcdec5d0f3685679e83be50803234ea83cc743b07dc67
checksum: 10c0/0f5edd5e1b39c132424f2e2c29c8a713d9c813bb99f8dcf987b5b56ff85989412d4b77ac99b1b7794050e7bde4ff82d885eb87bbf135ac2a02e1096eeb3b18eb
languageName: node
linkType: hard
@@ -1595,7 +1591,7 @@ __metadata:
"@mui/icons-material": "npm:^6.4.0"
"@mui/material": "npm:^6.4.0"
"@preact/compat": "npm:^18.3.1"
"@preact/preset-vite": "npm:^2.9.4"
"@preact/preset-vite": "npm:^2.10.0"
"@table-library/react-table-library": "npm:4.1.7"
"@trivago/prettier-plugin-sort-imports": "npm:^5.2.1"
"@types/formidable": "npm:^3"
@@ -1622,7 +1618,7 @@ __metadata:
typesafe-i18n: "npm:^5.26.2"
typescript: "npm:^5.7.3"
typescript-eslint: "npm:8.20.0"
vite: "npm:^6.0.7"
vite: "npm:^6.0.9"
vite-plugin-imagemin: "npm:^0.6.1"
vite-tsconfig-paths: "npm:^5.1.4"
languageName: unknown
@@ -2036,9 +2032,9 @@ __metadata:
linkType: hard
"caniuse-lite@npm:^1.0.30001688":
version: 1.0.30001692
resolution: "caniuse-lite@npm:1.0.30001692"
checksum: 10c0/fca5105561ea12f3de593f3b0f062af82f7d07519e8dbcb97f34e7fd23349bcef1b1622a9a6cd2164d98e3d2f20059ef7e271edae46567aef88caf4c16c7708a
version: 1.0.30001695
resolution: "caniuse-lite@npm:1.0.30001695"
checksum: 10c0/acf90a767051fdd8083711b3ff9f07a28149c55e394115d8f874f149aa4f130e6bc50cea1dd94fe03035b9ebbe13b64f446518a6d2e19f72650962bdff44b2c5
languageName: node
linkType: hard
@@ -4482,7 +4478,7 @@ __metadata:
languageName: node
linkType: hard
"kolorist@npm:^1.8.0":
"kolorist@npm:^1.6.0, kolorist@npm:^1.8.0":
version: 1.8.0
resolution: "kolorist@npm:1.8.0"
checksum: 10c0/73075db44a692bf6c34a649f3b4b3aea4993b84f6b754cbf7a8577e7c7db44c0bad87752bd23b0ce533f49de2244ce2ce03b7b1b667a85ae170a94782cc50f9b
@@ -4634,12 +4630,12 @@ __metadata:
languageName: node
linkType: hard
"magic-string@npm:0.30.5":
version: 0.30.5
resolution: "magic-string@npm:0.30.5"
"magic-string@npm:^0.30.6":
version: 0.30.17
resolution: "magic-string@npm:0.30.17"
dependencies:
"@jridgewell/sourcemap-codec": "npm:^1.4.15"
checksum: 10c0/38ac220ca7539e96da7ea2f38d85796bdf5c69b6bcae728c4bc2565084e6dc326b9174ee9770bea345cf6c9b3a24041b767167874fab5beca874d2356a9d1520
"@jridgewell/sourcemap-codec": "npm:^1.5.0"
checksum: 10c0/16826e415d04b88378f200fe022b53e638e3838b9e496edda6c0e086d7753a44a6ed187adc72d19f3623810589bf139af1a315541cd6a26ae0771a0193eaf7b8
languageName: node
linkType: hard
@@ -4960,7 +4956,7 @@ __metadata:
languageName: node
linkType: hard
"node-html-parser@npm:^6.1.10":
"node-html-parser@npm:^6.1.12":
version: 6.1.13
resolution: "node-html-parser@npm:6.1.13"
dependencies:
@@ -5859,28 +5855,28 @@ __metadata:
linkType: hard
"rollup@npm:^4.23.0":
version: 4.30.1
resolution: "rollup@npm:4.30.1"
version: 4.31.0
resolution: "rollup@npm:4.31.0"
dependencies:
"@rollup/rollup-android-arm-eabi": "npm:4.30.1"
"@rollup/rollup-android-arm64": "npm:4.30.1"
"@rollup/rollup-darwin-arm64": "npm:4.30.1"
"@rollup/rollup-darwin-x64": "npm:4.30.1"
"@rollup/rollup-freebsd-arm64": "npm:4.30.1"
"@rollup/rollup-freebsd-x64": "npm:4.30.1"
"@rollup/rollup-linux-arm-gnueabihf": "npm:4.30.1"
"@rollup/rollup-linux-arm-musleabihf": "npm:4.30.1"
"@rollup/rollup-linux-arm64-gnu": "npm:4.30.1"
"@rollup/rollup-linux-arm64-musl": "npm:4.30.1"
"@rollup/rollup-linux-loongarch64-gnu": "npm:4.30.1"
"@rollup/rollup-linux-powerpc64le-gnu": "npm:4.30.1"
"@rollup/rollup-linux-riscv64-gnu": "npm:4.30.1"
"@rollup/rollup-linux-s390x-gnu": "npm:4.30.1"
"@rollup/rollup-linux-x64-gnu": "npm:4.30.1"
"@rollup/rollup-linux-x64-musl": "npm:4.30.1"
"@rollup/rollup-win32-arm64-msvc": "npm:4.30.1"
"@rollup/rollup-win32-ia32-msvc": "npm:4.30.1"
"@rollup/rollup-win32-x64-msvc": "npm:4.30.1"
"@rollup/rollup-android-arm-eabi": "npm:4.31.0"
"@rollup/rollup-android-arm64": "npm:4.31.0"
"@rollup/rollup-darwin-arm64": "npm:4.31.0"
"@rollup/rollup-darwin-x64": "npm:4.31.0"
"@rollup/rollup-freebsd-arm64": "npm:4.31.0"
"@rollup/rollup-freebsd-x64": "npm:4.31.0"
"@rollup/rollup-linux-arm-gnueabihf": "npm:4.31.0"
"@rollup/rollup-linux-arm-musleabihf": "npm:4.31.0"
"@rollup/rollup-linux-arm64-gnu": "npm:4.31.0"
"@rollup/rollup-linux-arm64-musl": "npm:4.31.0"
"@rollup/rollup-linux-loongarch64-gnu": "npm:4.31.0"
"@rollup/rollup-linux-powerpc64le-gnu": "npm:4.31.0"
"@rollup/rollup-linux-riscv64-gnu": "npm:4.31.0"
"@rollup/rollup-linux-s390x-gnu": "npm:4.31.0"
"@rollup/rollup-linux-x64-gnu": "npm:4.31.0"
"@rollup/rollup-linux-x64-musl": "npm:4.31.0"
"@rollup/rollup-win32-arm64-msvc": "npm:4.31.0"
"@rollup/rollup-win32-ia32-msvc": "npm:4.31.0"
"@rollup/rollup-win32-x64-msvc": "npm:4.31.0"
"@types/estree": "npm:1.0.6"
fsevents: "npm:~2.3.2"
dependenciesMeta:
@@ -5926,7 +5922,7 @@ __metadata:
optional: true
bin:
rollup: dist/bin/rollup
checksum: 10c0/a318c57e2ca9741e1503bcd75483949c6e83edd72234a468010a3098a34248f523e44f7ad4fde90dc5c2da56abc1b78ac42a9329e1dbd708682728adbd8df7cc
checksum: 10c0/0d6da45098af14c678e78be887fefefbf5a97fef6277c5a1c24ca722537bb3a02e695c6fcad8880218d8fbef8a7a17d865786afd99bb6e70409fad73844ca8cf
languageName: node
linkType: hard
@@ -6091,6 +6087,15 @@ __metadata:
languageName: node
linkType: hard
"simple-code-frame@npm:^1.3.0":
version: 1.3.0
resolution: "simple-code-frame@npm:1.3.0"
dependencies:
kolorist: "npm:^1.6.0"
checksum: 10c0/f74332d839689b30deddc079f52845c05e455160888c2076056dd070d0088b8e84a0f36b6d273d38a8698e738dc5f34bbe6ecdcc86146b9d4250c67374f975c5
languageName: node
linkType: hard
"slash@npm:^3.0.0":
version: 3.0.0
resolution: "slash@npm:3.0.0"
@@ -6824,6 +6829,19 @@ __metadata:
languageName: node
linkType: hard
"vite-prerender-plugin@npm:^0.5.3":
version: 0.5.3
resolution: "vite-prerender-plugin@npm:0.5.3"
dependencies:
magic-string: "npm:^0.30.6"
node-html-parser: "npm:^6.1.12"
simple-code-frame: "npm:^1.3.0"
source-map: "npm:^0.7.4"
stack-trace: "npm:^1.0.0-pre2"
checksum: 10c0/9a07b851c50e5ee463351fe6db93801d819ba822c8a4628e1bfa175e367730d1987fac4260f51b004cefed4ca459e8275ba2b3a9615186c3498f6683509207ae
languageName: node
linkType: hard
"vite-tsconfig-paths@npm:^5.1.4":
version: 5.1.4
resolution: "vite-tsconfig-paths@npm:5.1.4"
@@ -6840,9 +6858,9 @@ __metadata:
languageName: node
linkType: hard
"vite@npm:^6.0.7":
version: 6.0.7
resolution: "vite@npm:6.0.7"
"vite@npm:^6.0.9":
version: 6.0.9
resolution: "vite@npm:6.0.9"
dependencies:
esbuild: "npm:^0.24.2"
fsevents: "npm:~2.3.3"
@@ -6888,7 +6906,7 @@ __metadata:
optional: true
bin:
vite: bin/vite.js
checksum: 10c0/ae81047b4290a7206b9394a39a782d509e9610462e7946422ba22d5bc615b5a322c07e33d7bf9dd0b3312ec3f5c63353b725913d1519324bfdf539b4f1e03f52
checksum: 10c0/b36f0f51318d6c33184da31e280862f23ef89712884e088b864c9edf112d65f6cf6795f201916e370a4434575fd3e2868f07f3bd63c6bdd5c2ae2295fa7f6d8a
languageName: node
linkType: hard

View File

@@ -70,7 +70,6 @@ let settings = {
let system_status = {
emsesp_version: 'XX.XX.XX', // defined later
bus_status: 0,
// status: 2,
uptime: 77186,
bus_uptime: 77121,
num_devices: 2,
@@ -108,7 +107,8 @@ let system_status = {
has_loader: true,
model: '',
// model: 'BBQKees Electronics EMS Gateway E32 V2 (E32 V2.0 P3/2024011)',
status: 'downloading'
// status: 0,
status: 3
};
let VERSION_IS_UPGRADEABLE: boolean;

View File

@@ -1410,3 +1410,4 @@ eldhw
elgendhw
solarinfl
currsolarinfl
temprature

View File

@@ -31,19 +31,16 @@ const std::initializer_list<Modbus::EntityModbusInfo> Modbus::modbus_register_ma
EOL
# build emsesp for standalone
make clean
make -s ARGS=-DEMSESP_STANDALONE
# Generate Modbus entity parameters
# One to build the modbus_entity_parameters.hpp header file
# And then run entity_dump test again to create the dump_entities.csv file with the correct modbus counts
make clean
make -s ARGS=-DEMSESP_MODBUS
rm -f ./src/core/modbus_entity_parameters.hpp
echo "test entity_dump" | ./emsesp | python3 ./scripts/strip_csv.py | python3 ./scripts/update_modbus_registers.py >./src/core/modbus_entity_parameters.hpp
ls -al ./src/core/modbus_entity_parameters.hpp
# dump_entities.csv
make -s ARGS=-DEMSESP_STANDALONE
rm -f ./docs/dump_entities.csv
echo "test entity_dump" | ./emsesp | python3 ./scripts/strip_csv.py >./docs/dump_entities.csv
ls -al ./docs/dump_entities.csv

View File

@@ -118,7 +118,8 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) {
request->_tempFile.close(); // close the file handle as the upload is now done
AsyncWebServerResponse * response = request->beginResponse(200);
request->send(response);
emsesp::EMSESP::system_.restart_pending(true); // will be handled by the main loop. We use pending for the Web's RestartMonitor
emsesp::EMSESP::system_.systemStatus(
emsesp::SYSTEM_STATUS::SYSTEM_STATUS_PENDING_RESTART); // will be handled by the main loop. We use pending for the Web's SystemMonitor
return;
}
@@ -127,7 +128,8 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) {
if (_is_firmware && !request->_tempObject) {
AsyncWebServerResponse * response = request->beginResponse(200);
request->send(response);
emsesp::EMSESP::system_.restart_pending(true); // will be handled by the main loop. We use pending for the Web's RestartMonitor
emsesp::EMSESP::system_.systemStatus(
emsesp::SYSTEM_STATUS::SYSTEM_STATUS_PENDING_RESTART); // will be handled by the main loop. We use pending for the Web's SystemMonitor
return;
}

View File

@@ -196,8 +196,8 @@
{161, DeviceType::WATER, "MM200", DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
{163, DeviceType::WATER, "SM100, MS100", DeviceFlags::EMS_DEVICE_FLAG_SM100},
{164, DeviceType::WATER, "SM200, MS200", DeviceFlags::EMS_DEVICE_FLAG_SM100},
{248, DeviceType::MIXER, "HM210", DeviceFlags::EMS_DEVICE_FLAG_MMPLUS},
{157, DeviceType::THERMOSTAT, "RC120", DeviceFlags::EMS_DEVICE_FLAG_CR120}
{248, DeviceType::MIXER, "HM210", DeviceFlags::EMS_DEVICE_FLAG_MMPLUS}
// {157, DeviceType::THERMOSTAT, "RC120", DeviceFlags::EMS_DEVICE_FLAG_CR120}
#endif
// clang-format on

View File

@@ -1297,6 +1297,13 @@ void EMSdevice::dump_devicevalue_info() {
Serial.print(product_id_);
Serial.print(',');
// <tag>/<shortname> unless generating for modbus registers - used in scripts/generate_csv_and_headers.sh
#ifndef EMSESP_MODBUS
if (dv.tag > DeviceValueTAG::TAG_DEVICE_DATA) {
Serial.print(tag_to_string(dv.tag));
Serial.print('.');
}
#endif
Serial.print(dv.short_name);
Serial.print(',');

View File

@@ -329,7 +329,7 @@ void EMSESP::show_ems(uuid::console::Shell & shell) {
shell.println();
}
// Dump all entities to Serial out
// Dump all entities to Serial out - used to create the dump_entities.csv file
// this is intended to run within the OS with lots of available memory!
#if defined(EMSESP_STANDALONE)
void EMSESP::dump_all_entities(uuid::console::Shell & shell) {
@@ -367,7 +367,7 @@ void EMSESP::dump_all_entities(uuid::console::Shell & shell) {
// for testing the mixer use ... if (device.product_id == 69) {
emsdevices.push_back(
EMSFactory::add(device.device_type, device_id, device.product_id, "1.0", device.default_name, device.flags, EMSdevice::Brand::NO_BRAND));
emsdevices.back()->dump_devicevalue_info();
emsdevices.back()->dump_devicevalue_info(); // print out the entities
}
}
}
@@ -1734,29 +1734,34 @@ void EMSESP::loop() {
esp32React.loop(); // web services
system_.loop(); // does LED and checks system health, and syslog service
// if we're doing an OTA upload, skip everything except from console refresh
static bool upload_status = true; // ready for any OTA uploads
if (!system_.upload_isrunning()) {
// run the loop, unless we're in the middle of an OTA upload
if (EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_NORMAL) {
// service loops
webLogService.loop(); // log in Web UI
rxservice_.loop(); // process any incoming Rx telegrams
shower_.loop(); // check for shower on/off
temperaturesensor_.loop(); // read sensor temperatures
analogsensor_.loop(); // read analog sensor values
publish_all_loop(); // with HA messages in parts to avoid flooding the mqtt queue
publish_all_loop(); // with HA messages in parts to avoid flooding the MQTT queue
mqtt_.loop(); // sends out anything in the MQTT queue
webModulesService.loop(); // loop through the external library modules
if (system_.PSram() == 0) { // run non-async if there is no PSRAM available
webSchedulerService.loop();
}
scheduled_fetch_values(); // force a query on the EMS devices to fetch latest data at a set interval (1 min)
}
} else if (upload_status) {
// start an upload from a URL, if it exists. This is blocking.
if (!system_.uploadFirmwareURL()) {
upload_status = false; // abort all other attempts, until reset (after a restart normally)
system_.upload_isrunning(false);
if (EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_PENDING_UPLOAD) {
// start an upload from a URL, assuming if the URL exists from a previous pass.
// Note this function is synchronous and blocking.
if (system_.uploadFirmwareURL()) {
// firmware has been uploaded, set status to uploading
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_UPLOADING);
} else {
// if it fails to pass, reset
Shell::loop_all(); // flush log buffers so latest error message are shown in console
system_.uploadFirmwareURL("reset");
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_ERROR_UPLOAD);
}
}

View File

@@ -83,8 +83,6 @@ uuid::log::Logger System::logger_{F_(system), uuid::log::Facility::KERN};
// init statics
PButton System::myPButton_;
bool System::restart_requested_ = false;
bool System::restart_pending_ = false;
bool System::test_set_all_active_ = false;
uint32_t System::max_alloc_mem_;
uint32_t System::heap_mem_;
@@ -298,8 +296,7 @@ void System::system_restart(const char * partitionname) {
}
// make sure it's only executed once
restart_requested(false);
restart_pending(false);
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_NORMAL);
store_nvs_values(); // save any NVS values
Shell::loop_all(); // flush log to output
@@ -307,8 +304,7 @@ void System::system_restart(const char * partitionname) {
delay(1000); // wait 1 second
ESP.restart();
#else
restart_requested(false);
restart_pending(false);
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_NORMAL);
if (partitionname != nullptr) {
LOG_INFO("Restarting EMS-ESP from %s partition", partitionname);
} else {
@@ -565,27 +561,10 @@ void System::led_init(bool refresh) {
}
}
// returns true if OTA is uploading
bool System::upload_isrunning() {
#if defined(EMSESP_STANDALONE)
return false;
#else
return upload_isrunning_ || Update.isRunning();
#endif
}
void System::upload_isrunning(bool in_progress) {
// if we've just started an upload
if (!upload_isrunning_ && in_progress) {
EMSuart::stop();
}
upload_isrunning_ = in_progress;
}
// checks system health and handles LED flashing wizardry
void System::loop() {
// check if we're supposed to do a reset/restart
if (restart_requested()) {
if (systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED) {
system_restart();
}
@@ -706,7 +685,7 @@ void System::heartbeat_json(JsonObject output) {
#ifndef EMSESP_STANDALONE
output["freemem"] = getHeapMem();
output["max_alloc"] = getMaxAllocMem();
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32
output["temperature"] = temperature_;
#endif
#endif
@@ -1901,7 +1880,7 @@ bool System::load_board_profile(std::vector<int8_t> & data, const std::string &
return true;
}
// format command - factory reset, removing all config files
// format command - factory reset, removing all config fi`les
bool System::command_format(const char * value, const int8_t id) {
LOG_INFO("Removing all config files");
#ifndef EMSESP_STANDALONE
@@ -1915,8 +1894,8 @@ bool System::command_format(const char * value, const int8_t id) {
}
#endif
EMSESP::system_.restart_requested(true); // will be handled by the main loop
// restart will be handled by the main loop
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED);
return true;
}
@@ -1926,11 +1905,13 @@ bool System::command_restart(const char * value, const int8_t id) {
// if it has an id then it's a web call and we need to queue the restart
// default id is -1 when calling /api/system/restart directly for example
LOG_INFO("Preparing to restart system");
EMSESP::system_.restart_pending(true);
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_PENDING_RESTART);
return true;
}
LOG_INFO("Restarting system immediately");
EMSESP::system_.restart_requested(true); // will be handled by the main loop
// restart will be handled by the main loop
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED);
return true;
}
@@ -2022,25 +2003,38 @@ String System::getBBQKeesGatewayDetails() {
// Stream from an URL and send straight to OTA uploader service.
//
// This function needs to be called twice, once with a url to persist it, and second with no arguments to start the upload
// This function needs to be called twice, 1st pass once with a url to persist it, 2nd pass with no arguments to start the upload
// This is to avoid timeouts in callback functions, like calling from a web hook.
bool System::uploadFirmwareURL(const char * url) {
#ifndef EMSESP_STANDALONE
static String saved_url;
// if the URL is not empty, store the URL for the 2nd pass
// if the URL is not empty, store the URL for the 2nd pass and exit
if (url && strlen(url) > 0) {
saved_url = url;
EMSESP::system_.upload_isrunning(true); // tell EMS-ESP we're ready to start the uploading process
// if the passed URL is "reset" abort the current upload. This is called when an error happens during OTA
if (strncmp(url, "reset", 5) == 0) {
LOG_DEBUG("Firmware upload - resetting");
saved_url.clear();
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_NORMAL);
return true;
}
// make sure we have a valid URL
// given a URL to download from, save it
saved_url = url;
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_PENDING_UPLOAD); // we're ready to start the upload
return true;
}
// assumed we have a valid URL from the 1st pass
if (saved_url.isEmpty()) {
LOG_ERROR("Firmware upload failed - invalid URL");
return false; // error
}
LOG_INFO("Firmware downloading from %s", saved_url.c_str());
Shell::loop_all(); // flush log buffers so latest messages are shown in console
// Configure temporary client
HTTPClient http;
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); // important for GitHub 302's
@@ -2051,42 +2045,46 @@ bool System::uploadFirmwareURL(const char * url) {
// start a connection, returns -1 if fails
int httpCode = http.GET();
if (httpCode != HTTP_CODE_OK) {
LOG_ERROR("Firmware upload failed. URL %s, HTTP code %d", saved_url.c_str(), httpCode);
LOG_ERROR("Firmware upload failed - HTTP code %d", httpCode);
http.end();
return false; // error
}
// check we have enough space for the upload in the ota partition
int firmware_size = http.getSize();
LOG_INFO("Firmware uploading (file: %s, size: %d bytes). Please wait...", saved_url.c_str(), firmware_size);
LOG_INFO("Firmware uploading (size: %d bytes). Please wait...", firmware_size);
if (!Update.begin(firmware_size)) {
LOG_ERROR("Firmware upload failed - no space");
http.end();
return false; // error
}
// flush log buffers so latest messages are shown
Shell::loop_all();
Shell::loop_all(); // flush log buffers so latest messages are shown in console
// TODO do we need to stop the UART with EMSuart::stop() ?
// get tcp stream and send it to Updater
WiFiClient * stream = http.getStreamPtr();
if (Update.writeStream(*stream) != firmware_size) {
LOG_ERROR("Firmware upload failed - size differences");
http.end();
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_ERROR_UPLOAD);
return false; // error
}
if (!Update.end(true)) {
LOG_ERROR("Firmware upload failed - general error");
http.end();
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_ERROR_UPLOAD);
return false; // error
}
// finished with upload
http.end();
EMSESP::system_.upload_isrunning(false);
saved_url.clear(); // prevent from downloading again
LOG_INFO("Firmware uploaded successfully. Restarting...");
restart_pending(true);
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED);
#endif
return true; // OK
@@ -2148,4 +2146,14 @@ bool System::command_read(const char * value, const int8_t id) {
return readCommand(value);
}
// set the system status code - SYSTEM_STATUS in system.h
void System::systemStatus(uint8_t status_code) {
systemStatus_ = status_code;
LOG_DEBUG("Setting System status code %d", status_code);
}
uint8_t System::systemStatus() {
return systemStatus_;
}
} // namespace emsesp

View File

@@ -59,6 +59,15 @@ namespace emsesp {
enum PHY_type : uint8_t { PHY_TYPE_NONE = 0, PHY_TYPE_LAN8720, PHY_TYPE_TLK110 };
enum SYSTEM_STATUS : uint8_t {
SYSTEM_STATUS_NORMAL = 0,
SYSTEM_STATUS_PENDING_UPLOAD = 1,
SYSTEM_STATUS_UPLOADING = 2,
SYSTEM_STATUS_ERROR_UPLOAD = 3,
SYSTEM_STATUS_PENDING_RESTART = 4,
SYSTEM_STATUS_RESTART_REQUESTED = 5
};
class System {
public:
void start();
@@ -88,8 +97,7 @@ class System {
void store_nvs_values();
void system_restart(const char * partition = nullptr);
void upload_isrunning(bool in_progress);
bool upload_isrunning();
void show_mem(const char * note);
void reload_settings();
void syslog_init();
@@ -122,6 +130,9 @@ class System {
void button_init(bool refresh);
void commands_init();
void systemStatus(uint8_t status_code);
uint8_t systemStatus();
static void extractSettings(const char * filename, const char * section, JsonObject output);
static bool saveSettings(const char * filename, const char * section, JsonObject input);
@@ -130,20 +141,6 @@ class System {
static bool readCommand(const char * data);
static void restart_requested(bool restart_requested) {
restart_requested_ = restart_requested;
}
static bool restart_requested() {
return restart_requested_;
}
static void restart_pending(bool restart_pending) {
restart_pending_ = restart_pending;
}
static bool restart_pending() {
return restart_pending_;
}
bool telnet_enabled() {
return telnet_enabled_;
}
@@ -341,12 +338,13 @@ class System {
private:
static uuid::log::Logger logger_;
static bool restart_requested_;
static bool restart_pending_; // used in 2-stage process to call restart from Web API
static bool test_set_all_active_; // force all entities in a device to have a value
static uint32_t max_alloc_mem_;
static uint32_t heap_mem_;
uint8_t systemStatus_; // uses SYSTEM_STATUS enum
// button
static PButton myPButton_; // PButton instance
static void button_OnClick(PButton & b);

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.7.2-dev.11"
#define EMSESP_APP_VERSION "3.7.2-dev.12"

View File

@@ -160,7 +160,8 @@ void WebCustomizationService::reset_customization(AsyncWebServerRequest * reques
if (LittleFS.remove(EMSESP_CUSTOMIZATION_FILE)) {
AsyncWebServerResponse * response = request->beginResponse(205); // restart needed
request->send(response);
EMSESP::system_.restart_pending(true);
emsesp::EMSESP::system_.systemStatus(
emsesp::SYSTEM_STATUS::SYSTEM_STATUS_PENDING_RESTART); // will be handled by the main loop. We use pending for the Web's SystemMonitor
return;
}

View File

@@ -523,7 +523,7 @@ void WebSchedulerService::loop() {
void WebSchedulerService::scheduler_task(void * pvParameters) {
while (1) {
delay(10); // no need to hurry
if (!EMSESP::system_.upload_isrunning()) {
if (EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_NORMAL) {
EMSESP::webSchedulerService.loop();
}
}

View File

@@ -42,7 +42,7 @@ WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * se
// /rest/systemStatus
// This contains both system & hardware Status to avoid having multiple costly endpoints
// This is also used for polling during the RestartMonitor to see if EMS-ESP is alive
// This is also used for polling during the SystemMonitor to see if EMS-ESP is alive
void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
EMSESP::system_.refreshHeapMem(); // refresh free heap and max alloc heap
@@ -146,12 +146,11 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
root["has_partition"] = false;
}
// Matches status codes in RestartMonitor.tsx
if (EMSESP::system_.restart_pending()) {
root["status"] = "restarting";
EMSESP::system_.restart_requested(true); // tell emsesp loop to start restart
} else {
root["status"] = EMSESP::system_.upload_isrunning() ? "uploading" : "ready";
// Also used in SystemMonitor.tsx
root["status"] = EMSESP::system_.systemStatus(); // send the status. See System.h for status codes
if (EMSESP::system_.systemStatus() == SYSTEM_STATUS::SYSTEM_STATUS_PENDING_RESTART) {
// we're ready to do the actual restart ASAP
EMSESP::system_.systemStatus(SYSTEM_STATUS::SYSTEM_STATUS_RESTART_REQUESTED);
}
#endif
@@ -194,6 +193,8 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json)
ok = getCustomSupport(root);
} else if (action == "uploadURL" && is_admin) {
ok = uploadURL(param.c_str());
} else if (action == "systemStatus" && is_admin) {
ok = setSystemStatus(param.c_str());
}
#if defined(EMSESP_STANDALONE) && !defined(EMSESP_UNITY)
@@ -359,4 +360,11 @@ bool WebStatusService::uploadURL(const char * url) {
return true;
}
// action = systemStatus
// sets the system status
bool WebStatusService::setSystemStatus(const char * status) {
emsesp::EMSESP::system_.systemStatus(Helpers::atoint(status));
return true;
}
} // namespace emsesp

View File

@@ -27,7 +27,7 @@ class WebStatusService {
bool exportData(JsonObject root, std::string & type);
bool getCustomSupport(JsonObject root);
bool uploadURL(const char * url);
bool setSystemStatus(const char * status);
void allvalues(JsonObject output);
};