mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
URL updates
This commit is contained in:
@@ -27,7 +27,7 @@
|
||||
"@mui/icons-material": "^6.1.1",
|
||||
"@mui/material": "^6.1.1",
|
||||
"@table-library/react-table-library": "4.1.7",
|
||||
"alova": "3.0.16",
|
||||
"alova": "3.0.17",
|
||||
"async-validator": "^4.2.5",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"mime-types": "^2.1.35",
|
||||
@@ -47,8 +47,8 @@
|
||||
"@preact/preset-vite": "^2.9.1",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/formidable": "^3",
|
||||
"@types/node": "^22.7.3",
|
||||
"@types/react": "^18.3.9",
|
||||
"@types/node": "^22.7.4",
|
||||
"@types/react": "^18.3.10",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"concurrently": "^9.0.1",
|
||||
@@ -57,7 +57,7 @@
|
||||
"formidable": "^3.5.1",
|
||||
"prettier": "^3.3.3",
|
||||
"rollup-plugin-visualizer": "^5.12.0",
|
||||
"terser": "^5.34.0",
|
||||
"terser": "^5.34.1",
|
||||
"typescript-eslint": "8.7.0",
|
||||
"vite": "^5.4.8",
|
||||
"vite-plugin-imagemin": "^0.6.1",
|
||||
|
||||
@@ -2,6 +2,7 @@ import { alovaInstance } from 'api/endpoints';
|
||||
|
||||
import type {
|
||||
APIcall,
|
||||
Action,
|
||||
Activity,
|
||||
CoreData,
|
||||
DeviceData,
|
||||
@@ -52,9 +53,9 @@ export const readActivity = () => alovaInstance.Get<Activity>('/rest/activity');
|
||||
// API
|
||||
export const API = (apiCall: APIcall) => alovaInstance.Post('/api', apiCall);
|
||||
|
||||
// DownloadUpload
|
||||
export const exportData = (type: string) =>
|
||||
alovaInstance.Get('/rest/exportData', { params: { type } });
|
||||
// Generic action
|
||||
export const callAction = (action: Action) =>
|
||||
alovaInstance.Post('/rest/action', action);
|
||||
|
||||
// SettingsCustomization
|
||||
export const readDeviceEntities = (id: number) =>
|
||||
@@ -118,7 +119,7 @@ export const writeModules = (data: {
|
||||
license: string;
|
||||
}) => alovaInstance.Post('/rest/modules', data);
|
||||
|
||||
// SettingsEntities
|
||||
// CustomEntities
|
||||
export const readCustomEntities = () =>
|
||||
alovaInstance.Get<EntityItem[]>('/rest/customEntities', {
|
||||
transform(data) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useContext } from 'react';
|
||||
import { useContext, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import CommentIcon from '@mui/icons-material/CommentTwoTone';
|
||||
@@ -16,18 +16,17 @@ import {
|
||||
ListItemAvatar,
|
||||
ListItemButton,
|
||||
ListItemText,
|
||||
Paper,
|
||||
Stack,
|
||||
Typography,
|
||||
styled
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
|
||||
import { useRequest } from 'alova/client';
|
||||
import { SectionContent, useLayoutTitle } from 'components';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { saveFile } from 'utils/file';
|
||||
|
||||
import { API } from '../../api/app';
|
||||
import { API, callAction } from '../../api/app';
|
||||
import type { APIcall } from './types';
|
||||
|
||||
const Help = () => {
|
||||
@@ -36,33 +35,79 @@ const Help = () => {
|
||||
|
||||
const { me } = useContext(AuthenticatedContext);
|
||||
|
||||
const { send: sendAPI } = useRequest((data: APIcall) => API(data), {
|
||||
immediate: false
|
||||
}).onSuccess((event) => {
|
||||
const anchor = document.createElement('a');
|
||||
anchor.href = URL.createObjectURL(
|
||||
new Blob([JSON.stringify(event.data, null, 2)], {
|
||||
type: 'text/plain'
|
||||
})
|
||||
const [customSupportIMG, setCustomSupportIMG] = useState<string | null>(null);
|
||||
const [customSupportHTML, setCustomSupportHTML] = useState<string | null>(null);
|
||||
|
||||
useRequest(() => callAction({ action: 'customSupport' })).onSuccess(
|
||||
(event: { data: { img_url: string; html: string[] } }) => {
|
||||
if (event.data) {
|
||||
setCustomSupportIMG(event.data.img_url);
|
||||
setCustomSupportHTML(event.data.html.join('<br/>'));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
anchor.download =
|
||||
'emsesp_' + event.args[0].device + '_' + event.args[0].entity + '.txt';
|
||||
anchor.click();
|
||||
URL.revokeObjectURL(anchor.href);
|
||||
const { send: sendExportAllValues } = useRequest(
|
||||
() => callAction({ action: 'export', param: 'allvalues' }),
|
||||
{
|
||||
immediate: false
|
||||
}
|
||||
)
|
||||
.onSuccess((event) => {
|
||||
saveFile(event.data, 'allvalues', '.txt');
|
||||
toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
||||
});
|
||||
|
||||
const callAPI = async (device: string, cmd: string) => {
|
||||
await sendAPI({ device, cmd, id: 0 }).catch((error: Error) => {
|
||||
})
|
||||
.onError((error) => {
|
||||
toast.error(error.message);
|
||||
});
|
||||
|
||||
const { send: sendAPI } = useRequest((data: APIcall) => API(data), {
|
||||
immediate: false
|
||||
})
|
||||
.onSuccess((event) => {
|
||||
saveFile(event.data, 'system_info', '.json');
|
||||
toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
||||
})
|
||||
.onError((error) => {
|
||||
toast.error(error.message);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SectionContent>
|
||||
{me.admin ? (
|
||||
<Stack
|
||||
padding={1}
|
||||
mb={2}
|
||||
direction="row"
|
||||
divider={<Divider orientation="vertical" flexItem />}
|
||||
sx={{
|
||||
borderRadius: 3,
|
||||
border: '2px solid grey',
|
||||
justifyContent: 'space-evenly',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography variant="subtitle1">
|
||||
{customSupportHTML ? (
|
||||
<div dangerouslySetInnerHTML={{ __html: customSupportHTML }} />
|
||||
) : (
|
||||
LL.HELP_INFORMATION_5()
|
||||
)}
|
||||
</Typography>
|
||||
<Box
|
||||
component="img"
|
||||
sx={{
|
||||
maxHeight: 250
|
||||
}}
|
||||
src={
|
||||
customSupportIMG
|
||||
? customSupportIMG
|
||||
: 'https://emsesp.org/_media/images/installer.jpeg'
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
{me.admin && (
|
||||
<List sx={{ borderRadius: 3, border: '2px solid grey' }}>
|
||||
<ListItem>
|
||||
<ListItemButton component="a" href="https://emsesp.org">
|
||||
@@ -100,31 +145,6 @@ const Help = () => {
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
</List>
|
||||
) : (
|
||||
<Stack
|
||||
spacing={1}
|
||||
padding={1}
|
||||
direction="row"
|
||||
divider={<Divider orientation="vertical" flexItem />}
|
||||
sx={{
|
||||
borderRadius: 3,
|
||||
border: '2px solid grey',
|
||||
justifyContent: 'space-around',
|
||||
alignItems: 'center'
|
||||
}}
|
||||
>
|
||||
<Typography border="red" variant="subtitle1">
|
||||
{LL.HELP_INFORMATION_5()}
|
||||
</Typography>
|
||||
<Box
|
||||
padding={1}
|
||||
component="img"
|
||||
sx={{
|
||||
maxHeight: { xs: 100, md: 250 }
|
||||
}}
|
||||
src="https://emsesp.org/_media/images/installer.jpeg"
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
<Box p={2} color="warning.main">
|
||||
@@ -135,7 +155,7 @@ const Help = () => {
|
||||
startIcon={<DownloadIcon />}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={() => callAPI('system', 'info')}
|
||||
onClick={() => sendAPI({ device: 'system', cmd: 'info', id: 0 })}
|
||||
>
|
||||
{LL.DOWNLOAD(1)} {LL.SUPPORT_INFORMATION(0)}
|
||||
</Button>
|
||||
@@ -146,7 +166,7 @@ const Help = () => {
|
||||
startIcon={<DownloadIcon />}
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={() => callAPI('system', 'allvalues')}
|
||||
onClick={() => sendExportAllValues()}
|
||||
>
|
||||
{LL.DOWNLOAD(1)} {LL.ALLVALUES()}
|
||||
</Button>
|
||||
|
||||
@@ -265,6 +265,12 @@ export interface APIcall {
|
||||
cmd: string;
|
||||
id: number;
|
||||
}
|
||||
|
||||
export interface Action {
|
||||
action: string;
|
||||
param?: string; // optional
|
||||
}
|
||||
|
||||
export interface WriteAnalogSensor {
|
||||
id: number;
|
||||
gpio: number;
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
import Grid from '@mui/material/Grid2';
|
||||
|
||||
import * as SystemApi from 'api/system';
|
||||
import { API, exportData } from 'api/app';
|
||||
import { API, callAction } from 'api/app';
|
||||
import {
|
||||
checkUpgrade,
|
||||
getDevVersion,
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
useLayoutTitle
|
||||
} from 'components';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { saveFile } from 'utils/file';
|
||||
|
||||
const DownloadUpload = () => {
|
||||
const { LL } = useI18nContext();
|
||||
@@ -46,11 +47,23 @@ const DownloadUpload = () => {
|
||||
const [useDev, setUseDev] = useState<boolean>(false);
|
||||
const [upgradeAvailable, setUpgradeAvailable] = useState<boolean>(false);
|
||||
|
||||
const { send: sendExportData } = useRequest((type: string) => exportData(type), {
|
||||
const { send: sendCheckUpgrade } = useRequest(
|
||||
(version: string) => callAction({ action: 'checkUpgrade', param: version }),
|
||||
{
|
||||
immediate: false
|
||||
})
|
||||
}
|
||||
).onSuccess((event) => {
|
||||
setUpgradeAvailable((event.data as { upgradeable: boolean }).upgradeable);
|
||||
});
|
||||
|
||||
const { send: sendExportData } = useRequest(
|
||||
(type: string) => callAction({ action: 'export', param: type }),
|
||||
{
|
||||
immediate: false
|
||||
}
|
||||
)
|
||||
.onSuccess((event) => {
|
||||
saveFile(event.data, event.args[0]);
|
||||
saveFile(event.data, event.args[0], '.json');
|
||||
toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
||||
})
|
||||
.onError((error) => {
|
||||
@@ -83,12 +96,6 @@ const DownloadUpload = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const { send: sendCheckUpgrade } = useRequest(checkUpgrade, {
|
||||
immediate: false
|
||||
}).onSuccess((event) => {
|
||||
setUpgradeAvailable(event.data.upgradeable);
|
||||
});
|
||||
|
||||
// called immediately to get the latest version, on page load
|
||||
const { data: latestVersion } = useRequest(getStableVersion, {
|
||||
// uncomment next 2 lines for testing, uses https://github.com/emsesp/EMS-ESP32/releases/download/v3.6.5/EMS-ESP-3_6_5-ESP32-16MB+.bin
|
||||
@@ -102,7 +109,7 @@ const DownloadUpload = () => {
|
||||
// immediate: false,
|
||||
// initialData: '3.7.0-dev.32'
|
||||
}).onSuccess((event) => {
|
||||
void sendCheckUpgrade({ version: event.data });
|
||||
void sendCheckUpgrade(event.data);
|
||||
});
|
||||
|
||||
const STABLE_URL = 'https://github.com/emsesp/EMS-ESP32/releases/download/';
|
||||
@@ -142,18 +149,6 @@ const DownloadUpload = () => {
|
||||
setRestarting(true);
|
||||
};
|
||||
|
||||
const saveFile = (json: unknown, filename: string) => {
|
||||
const anchor = document.createElement('a');
|
||||
anchor.href = URL.createObjectURL(
|
||||
new Blob([JSON.stringify(json, null, 2)], {
|
||||
type: 'text/plain'
|
||||
})
|
||||
);
|
||||
anchor.download = 'emsesp_' + filename + '.json';
|
||||
anchor.click();
|
||||
URL.revokeObjectURL(anchor.href);
|
||||
};
|
||||
|
||||
useLayoutTitle(LL.DOWNLOAD_UPLOAD());
|
||||
|
||||
const internet_live =
|
||||
|
||||
11
interface/src/utils/file.ts
Normal file
11
interface/src/utils/file.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export const saveFile = (json: unknown, filename: string, extension: string) => {
|
||||
const anchor = document.createElement('a');
|
||||
anchor.href = URL.createObjectURL(
|
||||
new Blob([JSON.stringify(json, null, 2)], {
|
||||
type: 'text/plain'
|
||||
})
|
||||
);
|
||||
anchor.download = 'emsesp_' + filename + extension;
|
||||
anchor.click();
|
||||
URL.revokeObjectURL(anchor.href);
|
||||
};
|
||||
@@ -1446,12 +1446,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:^22.7.3":
|
||||
version: 22.7.3
|
||||
resolution: "@types/node@npm:22.7.3"
|
||||
"@types/node@npm:^22.7.4":
|
||||
version: 22.7.4
|
||||
resolution: "@types/node@npm:22.7.4"
|
||||
dependencies:
|
||||
undici-types: "npm:~6.19.2"
|
||||
checksum: 10c0/0e579813528b0370454337a952f43b792cd12731e10fdca0fdb627158e980c1219bba99e9048c134b6a19325d817016059afe016ccd372326c838a1b85a51574
|
||||
checksum: 10c0/c22bf54515c78ff3170142c1e718b90e2a0003419dc2d55f79c9c9362edd590a6ab1450deb09ff6e1b32d1b4698da407930b16285e8be3a009ea6cd2695cac01
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1518,13 +1518,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react@npm:^18.3.9":
|
||||
version: 18.3.9
|
||||
resolution: "@types/react@npm:18.3.9"
|
||||
"@types/react@npm:^18.3.10":
|
||||
version: 18.3.10
|
||||
resolution: "@types/react@npm:18.3.10"
|
||||
dependencies:
|
||||
"@types/prop-types": "npm:*"
|
||||
csstype: "npm:^3.0.2"
|
||||
checksum: 10c0/a92b8e061d0c833e096254782c56a802316593f4a907fb834b557cabe848a0829b9eb6056404ea239eb4d5ec5ac7b7724309761516c0a7a277916fa04dd4f805
|
||||
checksum: 10c0/f5be1de1b0331c1fdb33d577f4cf7f1b949d4bded5347b2351a537f03c51dade5be115e21b161dcf1b37061954d320f6a0bdf8d7b70e24eda51071fdd614383d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1678,11 +1678,11 @@ __metadata:
|
||||
"@table-library/react-table-library": "npm:4.1.7"
|
||||
"@trivago/prettier-plugin-sort-imports": "npm:^4.3.0"
|
||||
"@types/formidable": "npm:^3"
|
||||
"@types/node": "npm:^22.7.3"
|
||||
"@types/react": "npm:^18.3.9"
|
||||
"@types/node": "npm:^22.7.4"
|
||||
"@types/react": "npm:^18.3.10"
|
||||
"@types/react-dom": "npm:^18.3.0"
|
||||
"@types/react-router-dom": "npm:^5.3.3"
|
||||
alova: "npm:3.0.16"
|
||||
alova: "npm:3.0.17"
|
||||
async-validator: "npm:^4.2.5"
|
||||
concurrently: "npm:^9.0.1"
|
||||
eslint: "npm:^9.11.1"
|
||||
@@ -1698,7 +1698,7 @@ __metadata:
|
||||
react-router-dom: "npm:^6.26.2"
|
||||
react-toastify: "npm:^10.0.5"
|
||||
rollup-plugin-visualizer: "npm:^5.12.0"
|
||||
terser: "npm:^5.34.0"
|
||||
terser: "npm:^5.34.1"
|
||||
typesafe-i18n: "npm:^5.26.2"
|
||||
typescript: "npm:^5.6.2"
|
||||
typescript-eslint: "npm:8.7.0"
|
||||
@@ -1764,13 +1764,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"alova@npm:3.0.16":
|
||||
version: 3.0.16
|
||||
resolution: "alova@npm:3.0.16"
|
||||
"alova@npm:3.0.17":
|
||||
version: 3.0.17
|
||||
resolution: "alova@npm:3.0.17"
|
||||
dependencies:
|
||||
"@alova/shared": "npm:^1.0.5"
|
||||
rate-limiter-flexible: "npm:^5.0.3"
|
||||
checksum: 10c0/66cb597f4f00feda04b7619dd852fde92bc920cc97b018be70791240c8e8c64677a998a02a684f3aace5997322236a677264f25afe6bcaf4ec856ae42be859a8
|
||||
checksum: 10c0/e8a2ae885a3ff44dafec230d9388dc22b6445bb0cf8511fc9855b5a98ad9961941b0d33a7da874df23db4af0dba75872a470e3edebbdcc5ead8aecbc7fcc3d6b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -6654,9 +6654,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"terser@npm:^5.34.0":
|
||||
version: 5.34.0
|
||||
resolution: "terser@npm:5.34.0"
|
||||
"terser@npm:^5.34.1":
|
||||
version: 5.34.1
|
||||
resolution: "terser@npm:5.34.1"
|
||||
dependencies:
|
||||
"@jridgewell/source-map": "npm:^0.3.3"
|
||||
acorn: "npm:^8.8.2"
|
||||
@@ -6664,7 +6664,7 @@ __metadata:
|
||||
source-map-support: "npm:~0.5.20"
|
||||
bin:
|
||||
terser: bin/terser
|
||||
checksum: 10c0/74e8ef4e565e5600415cd9377a90eed419b8076465d453c0c76aef4053c45371512d2de76c34d01e004cdd49ea5a749d77eeb343f7e665b2d172158ca08ba23e
|
||||
checksum: 10c0/51c7d704c5c4ae88bf937124112c9972aed4e1fd29d805cc2d86e0f54cd631ecd4e69db5bb3c1e3b450c741c86e2313328bea0fde925329e8a31a07a7941723c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
@@ -117,6 +117,55 @@ function updateMask(entity: any, de: any, dd: any) {
|
||||
}
|
||||
}
|
||||
|
||||
// called by Action endpoint
|
||||
function export_data(type: string) {
|
||||
console.log('exporting ' + type + '...');
|
||||
switch (type) {
|
||||
case 'settings':
|
||||
return emsesp_info;
|
||||
case 'customizations':
|
||||
return emsesp_deviceentities_2; // fixed for one device
|
||||
case 'entities':
|
||||
return emsesp_customentities;
|
||||
case 'schedule':
|
||||
return emsesp_schedule;
|
||||
case 'modules':
|
||||
return emsesp_modules;
|
||||
case 'allvalues':
|
||||
return emsesp_allvalues;
|
||||
default:
|
||||
return status(404);
|
||||
}
|
||||
}
|
||||
|
||||
// called by Action endpoint
|
||||
function custom_support() {
|
||||
return {
|
||||
html: [
|
||||
'This product is installed and managed by:',
|
||||
'',
|
||||
'<b>Bosch Installer Example</b>',
|
||||
'Nefit Road 12',
|
||||
'1234 AB Amsterdam',
|
||||
'Phone: +31 123 456 789',
|
||||
'email: support@boschinstaller.nl',
|
||||
'',
|
||||
"For help and questions please <a target='_blank' href='https://emsesp.org'>contact</a> your installer."
|
||||
],
|
||||
img_url: 'https://emsesp.org/_media/images/designer.png'
|
||||
};
|
||||
}
|
||||
|
||||
// called by Action endpoint
|
||||
function check_upgrade(version: string) {
|
||||
console.log('check upgrade from version', version);
|
||||
const data = {
|
||||
upgradeable: true
|
||||
// upgradeable: false
|
||||
};
|
||||
return data;
|
||||
}
|
||||
|
||||
// START DATA
|
||||
|
||||
// LOG
|
||||
@@ -402,7 +451,6 @@ const EMSESP_DEVICEDATA_ENDPOINT2 = REST_ENDPOINT_ROOT + 'deviceData/:id?';
|
||||
const EMSESP_DEVICEENTITIES_ENDPOINT1 = REST_ENDPOINT_ROOT + 'deviceEntities';
|
||||
const EMSESP_DEVICEENTITIES_ENDPOINT2 = REST_ENDPOINT_ROOT + 'deviceEntities/:id?';
|
||||
|
||||
const EMSESP_CHECK_UPGRADE_ENDPOINT = REST_ENDPOINT_ROOT + 'checkUpgrade';
|
||||
const EMSESP_BOARDPROFILE_ENDPOINT = REST_ENDPOINT_ROOT + 'boardProfile';
|
||||
const EMSESP_WRITE_DEVICEVALUE_ENDPOINT = REST_ENDPOINT_ROOT + 'writeDeviceValue';
|
||||
const EMSESP_WRITE_DEVICENAME_ENDPOINT = REST_ENDPOINT_ROOT + 'writeDeviceName';
|
||||
@@ -416,7 +464,8 @@ const EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT =
|
||||
const EMSESP_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule';
|
||||
const EMSESP_CUSTOMENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'customEntities';
|
||||
const EMSESP_MODULES_ENDPOINT = REST_ENDPOINT_ROOT + 'modules';
|
||||
const EMSESP_EXPORT_DATA_ENDPOINT = REST_ENDPOINT_ROOT + 'exportData';
|
||||
|
||||
const EMSESP_ACTION_ENDPOINT = REST_ENDPOINT_ROOT + 'action';
|
||||
|
||||
// these are used in the API calls only
|
||||
const EMSESP_SYSTEM_INFO_ENDPOINT = API_ENDPOINT_ROOT + 'system/info';
|
||||
@@ -4081,16 +4130,10 @@ router
|
||||
router
|
||||
.get(ACTIVITY_ENDPOINT, () => activity)
|
||||
.get(SYSTEM_STATUS_ENDPOINT, () => {
|
||||
if (countHardwarePoll === 0) {
|
||||
console.log('Resetting hardware count...');
|
||||
}
|
||||
|
||||
if (countHardwarePoll >= 2) {
|
||||
countHardwarePoll = 0;
|
||||
system_status.status = 'ready';
|
||||
}
|
||||
|
||||
console.log('Hardware count ' + countHardwarePoll + ' of 2');
|
||||
countHardwarePoll++;
|
||||
|
||||
return system_status;
|
||||
@@ -4402,17 +4445,6 @@ router
|
||||
return status(200);
|
||||
})
|
||||
|
||||
// check upgrade
|
||||
.post(EMSESP_CHECK_UPGRADE_ENDPOINT, async (request: any) => {
|
||||
const content = await request.json();
|
||||
console.log('check upgrade from ', content.version);
|
||||
const data = {
|
||||
upgradeable: true
|
||||
// upgradeable: false
|
||||
};
|
||||
return data;
|
||||
})
|
||||
|
||||
// Settings - board profile
|
||||
.get(EMSESP_BOARDPROFILE_ENDPOINT, (request) => {
|
||||
const board_profile = request.query.boardProfile;
|
||||
@@ -4549,32 +4581,32 @@ router
|
||||
return data;
|
||||
})
|
||||
|
||||
// Download Settings
|
||||
.get(EMSESP_EXPORT_DATA_ENDPOINT, (request) => {
|
||||
const type = request.query.type;
|
||||
console.log('exporting ' + type + ' data');
|
||||
switch (type) {
|
||||
case 'settings':
|
||||
return emsesp_info;
|
||||
case 'customizations':
|
||||
return emsesp_deviceentities_2; // fixed for one device
|
||||
case 'entities':
|
||||
return emsesp_customentities;
|
||||
case 'schedule':
|
||||
return emsesp_schedule;
|
||||
case 'modules':
|
||||
return emsesp_modules;
|
||||
default:
|
||||
return status(404);
|
||||
}
|
||||
})
|
||||
|
||||
// upload URL
|
||||
.post('/rest/uploadURL', () => {
|
||||
console.log('upload File from URL');
|
||||
return status(200);
|
||||
})
|
||||
|
||||
// generic action for all /rest/... endpoints
|
||||
// takes an action and param in JSON
|
||||
.post(EMSESP_ACTION_ENDPOINT, async (request: any) => {
|
||||
const content = await request.json();
|
||||
if (content.hasOwnProperty('action')) {
|
||||
const action = content.action;
|
||||
if (action === 'export') {
|
||||
// export data
|
||||
return export_data(content.param);
|
||||
} else if (action === 'customSupport') {
|
||||
// send custom support
|
||||
return custom_support();
|
||||
} else if (action === 'checkUpgrade') {
|
||||
// check upgrade
|
||||
return check_upgrade(content.param);
|
||||
}
|
||||
}
|
||||
return status(404); // cmd not found
|
||||
})
|
||||
|
||||
// API which are usually POST for security
|
||||
.post(EMSESP_SYSTEM_INFO_ENDPOINT, () => emsesp_info)
|
||||
.get(EMSESP_SYSTEM_INFO_ENDPOINT, () => emsesp_info)
|
||||
@@ -4594,9 +4626,6 @@ router
|
||||
if (cmd === 'info') {
|
||||
return emsesp_info;
|
||||
}
|
||||
if (cmd === 'allvalues') {
|
||||
return emsesp_allvalues;
|
||||
}
|
||||
if (cmd === 'format') {
|
||||
console.log('formatting...');
|
||||
return status(200);
|
||||
|
||||
@@ -39,7 +39,7 @@ unbuild_flags =
|
||||
${common.core_unbuild_flags}
|
||||
|
||||
[espressif32_base]
|
||||
platform = espressif32@6.8.1
|
||||
platform = espressif32@6.9.0
|
||||
framework = arduino
|
||||
board_build.filesystem = littlefs
|
||||
build_flags =
|
||||
|
||||
@@ -75,7 +75,7 @@ MAKE_WORD_TRANSLATION(schedule_cmd, "enable schedule item", "Aktiviere Zeitplane
|
||||
MAKE_WORD_TRANSLATION(entity_cmd, "set custom value on ems", "Sende eigene Entitäten zu EMS", "verstuur custom waarde naar EMS", "", "wyślij własną wartość na EMS", "", "", "emp üzerinde özel değer ayarla", "imposta valori personalizzati su EMS", "nastaviť vlastnú hodnotu na ems") // TODO translate
|
||||
MAKE_WORD_TRANSLATION(commands_response, "get response", "Hole Antwort", "Verzoek om antwoord", "", "uzyskaj odpowiedź", "", "", "gelen cevap", "", "získať odpoveď") // TODO translate
|
||||
MAKE_WORD_TRANSLATION(coldshot_cmd, "send a cold shot of water", "Zugabe einer Menge kalten Wassers", "", "", "uruchom tryśnięcie zimnej wody", "", "", "soğuk su gönder", "", "pošlite studenú dávku vody") // TODO translate
|
||||
MAKE_WORD_TRANSLATION(allvalues_cmd, "output all values in system", "Alle Werte im System ausgeben", "", "", "wyświetl wszystkie wartości", "", "", "", "", "vypísať všetky hodnoty") // TODO translate
|
||||
MAKE_WORD_TRANSLATION(allvalues_cmd, "output all values in system", "Alle Werte im System ausgeben", "", "", "wyświetl wszystkie wartości", "", "", "", "", "vypísať všetky hodnoty") // TODO remove
|
||||
MAKE_WORD_TRANSLATION(message_cmd, "send a message", "Eine Nachricht senden", "", "", "", "", "", "", "", "poslať správu") // TODO translate
|
||||
MAKE_WORD_TRANSLATION(values_cmd, "list all values", "Liste alle Werte auf", "", "", "", "", "", "", "", "vypísať všetky hodnoty") // TODO translate
|
||||
|
||||
|
||||
@@ -113,6 +113,7 @@ bool System::command_response(const char * value, const int8_t id, JsonObject ou
|
||||
|
||||
// output all the devices and the values
|
||||
// not system info
|
||||
// TODO remove?
|
||||
bool System::command_allvalues(const char * value, const int8_t id, JsonObject output) {
|
||||
JsonDocument doc;
|
||||
JsonObject device_output;
|
||||
@@ -874,7 +875,7 @@ void System::commands_init() {
|
||||
|
||||
// these commands will return data in JSON format
|
||||
Command::add(EMSdevice::DeviceType::SYSTEM, F("response"), System::command_response, FL_(commands_response));
|
||||
Command::add(EMSdevice::DeviceType::SYSTEM, F("allvalues"), System::command_allvalues, FL_(allvalues_cmd));
|
||||
Command::add(EMSdevice::DeviceType::SYSTEM, F("allvalues"), System::command_allvalues, FL_(allvalues_cmd)); // TODO remove
|
||||
|
||||
// MQTT subscribe "ems-esp/system/#"
|
||||
Mqtt::subscribe(EMSdevice::DeviceType::SYSTEM, "system/#", nullptr); // use empty function callback
|
||||
@@ -1139,7 +1140,7 @@ void System::show_system(uuid::console::Shell & shell) {
|
||||
|
||||
// see if there is a restore of an older settings file that needs to be applied
|
||||
bool System::check_restore() {
|
||||
bool reboot_required = false;
|
||||
bool reboot_required = false; // true if we need to reboot
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
File new_file = LittleFS.open(TEMP_FILENAME_PATH);
|
||||
@@ -1167,11 +1168,20 @@ bool System::check_restore() {
|
||||
} else if (settings_type == "entities") {
|
||||
// it's a entity file, just replace it and there's no need to reboot
|
||||
saveSettings(EMSESP_CUSTOMENTITY_FILE, "Entities", input);
|
||||
} else if (settings_type == "custom_support") {
|
||||
// it's a custom support file - save it to /config
|
||||
new_file.close();
|
||||
if (LittleFS.rename(TEMP_FILENAME_PATH, EMSESP_CUSTOMSUPPORT_FILE)) {
|
||||
LOG_INFO("Custom support information loaded");
|
||||
return false; // no need to reboot
|
||||
} else {
|
||||
LOG_ERROR("Failed to save custom support file");
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR("Unrecognized file uploaded");
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR("Unrecognized file uploaded, not json. Will be removed.");
|
||||
LOG_ERROR("Unrecognized file uploaded, not json.");
|
||||
}
|
||||
|
||||
// close (just in case) and remove the temp file
|
||||
|
||||
@@ -43,6 +43,8 @@ using uuid::console::Shell;
|
||||
|
||||
#define EMSESP_FS_CONFIG_DIRECTORY "/config"
|
||||
|
||||
#define EMSESP_CUSTOMSUPPORT_FILE "/config/customSupport.json"
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
enum PHY_type : uint8_t { PHY_TYPE_NONE = 0, PHY_TYPE_LAN8720, PHY_TYPE_TLK110 };
|
||||
@@ -63,7 +65,7 @@ class System {
|
||||
static bool command_message(const char * value, const int8_t id);
|
||||
static bool command_info(const char * value, const int8_t id, JsonObject output);
|
||||
static bool command_response(const char * value, const int8_t id, JsonObject output);
|
||||
static bool command_allvalues(const char * value, const int8_t id, JsonObject output);
|
||||
static bool command_allvalues(const char * value, const int8_t id, JsonObject output); // TODO fix
|
||||
|
||||
static bool get_value_info(JsonObject root, const char * cmd);
|
||||
static void get_value_json(JsonObject output, const std::string & circuit, const std::string & name, JsonVariant val);
|
||||
|
||||
@@ -327,7 +327,6 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
|
||||
// shell.invoke_command("show devices");
|
||||
// shell.invoke_command("show values");
|
||||
// shell.invoke_command("call system allvalues");
|
||||
// shell.invoke_command("call system publish");
|
||||
// shell.invoke_command("show mqtt");
|
||||
ok = true;
|
||||
@@ -792,7 +791,6 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
|
||||
shell.invoke_command("call temperaturesensor");
|
||||
shell.invoke_command("show values");
|
||||
shell.invoke_command("call system allvalues");
|
||||
shell.invoke_command("call temperaturesensor info");
|
||||
shell.invoke_command("call temperaturesensor values");
|
||||
|
||||
@@ -842,7 +840,6 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
|
||||
shell.invoke_command("call analogsensor");
|
||||
shell.invoke_command("show values");
|
||||
shell.invoke_command("call system allvalues");
|
||||
shell.invoke_command("call analogsensor info");
|
||||
shell.invoke_command("call analogsensor values");
|
||||
|
||||
|
||||
@@ -463,7 +463,6 @@ uint8_t WebCustomEntityService::count_entities() {
|
||||
uint8_t count = 0;
|
||||
for (const CustomEntityItem & entity : *customEntityItems_) {
|
||||
render_value(output, entity);
|
||||
// TODO check JsonVariant
|
||||
if (output[entity.name].is<JsonVariantConst>() || entity.writeable) {
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -27,10 +27,9 @@ namespace emsesp {
|
||||
WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager) {
|
||||
// GET
|
||||
server->on(EMSESP_SYSTEM_STATUS_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { systemStatus(request); });
|
||||
server->on(EMSESP_EXPORT_DATA_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { exportData(request); });
|
||||
|
||||
// POST
|
||||
server->on(EMSESP_CHECK_UPGRADE_PATH, [this](AsyncWebServerRequest * request, JsonVariant json) { checkUpgrade(request, json); });
|
||||
// generic action - POST
|
||||
server->on(EMSESP_ACTION_SERVICE_PATH, [this](AsyncWebServerRequest * request, JsonVariant json) { action(request, json); });
|
||||
}
|
||||
|
||||
// /rest/systemStatus
|
||||
@@ -146,13 +145,42 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
// returns trues if there is an upgrade available
|
||||
void WebStatusService::checkUpgrade(AsyncWebServerRequest * request, JsonVariant json) {
|
||||
// generic action handler - as a POST
|
||||
void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json) {
|
||||
auto * response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
// get action and optional param
|
||||
std::string action = json["action"];
|
||||
std::string param = json["param"]; // is optional
|
||||
|
||||
// TODO remove
|
||||
Serial.printf("Action: %s\n", action.c_str());
|
||||
Serial.printf("Param: %s\n", param.c_str());
|
||||
|
||||
bool ok = true;
|
||||
if (action == "checkUpgrade") {
|
||||
ok = checkUpgrade(root, param);
|
||||
} else if (action == "export") {
|
||||
ok = exportData(root, param);
|
||||
} else if (action == "customSupport") {
|
||||
ok = customSupport(root);
|
||||
}
|
||||
|
||||
// send response
|
||||
if (!ok) {
|
||||
request->send(400);
|
||||
return;
|
||||
}
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
|
||||
// returns true if there is an upgrade available
|
||||
bool WebStatusService::checkUpgrade(JsonObject root, std::string & latest_version) {
|
||||
version::Semver200_version settings_version(EMSESP_APP_VERSION);
|
||||
const std::string latest_version = json["version"] | EMSESP_APP_VERSION;
|
||||
version::Semver200_version this_version(latest_version);
|
||||
|
||||
#if defined(EMSESP_DEBUG)
|
||||
@@ -161,16 +189,11 @@ void WebStatusService::checkUpgrade(AsyncWebServerRequest * request, JsonVariant
|
||||
|
||||
root["upgradeable"] = (this_version > settings_version);
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns data for a specific feature/settings as a json object
|
||||
void WebStatusService::exportData(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
String type = request->getParam("type")->value();
|
||||
bool WebStatusService::exportData(JsonObject root, std::string & type) {
|
||||
root["type"] = type;
|
||||
|
||||
if (type == "settings") {
|
||||
@@ -189,12 +212,15 @@ void WebStatusService::exportData(AsyncWebServerRequest * request) {
|
||||
} else if (type == "entities") {
|
||||
System::extractSettings(EMSESP_CUSTOMENTITY_FILE, "Entities", root);
|
||||
} else {
|
||||
request->send(400);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
// custom support
|
||||
bool WebStatusService::customSupport(JsonObject root) {
|
||||
root["custom_support"] = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
#define WebStatusService_h
|
||||
|
||||
#define EMSESP_SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus"
|
||||
#define EMSESP_CHECK_UPGRADE_PATH "/rest/checkUpgrade"
|
||||
#define EMSESP_EXPORT_DATA_SERVICE_PATH "/rest/exportData"
|
||||
|
||||
#define EMSESP_ACTION_SERVICE_PATH "/rest/action"
|
||||
|
||||
#include <semver200.h> // for version checking
|
||||
|
||||
@@ -13,10 +13,14 @@ class WebStatusService {
|
||||
public:
|
||||
WebStatusService(AsyncWebServer * server, SecurityManager * securityManager);
|
||||
|
||||
private:
|
||||
protected:
|
||||
void systemStatus(AsyncWebServerRequest * request);
|
||||
void checkUpgrade(AsyncWebServerRequest * request, JsonVariant json);
|
||||
void exportData(AsyncWebServerRequest * request);
|
||||
void action(AsyncWebServerRequest * request, JsonVariant json);
|
||||
|
||||
private:
|
||||
bool checkUpgrade(JsonObject root, std::string & latest_version);
|
||||
bool exportData(JsonObject root, std::string & type);
|
||||
bool customSupport(JsonObject root);
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
Reference in New Issue
Block a user