This commit is contained in:
MichaelDvP
2024-09-16 13:48:18 +02:00
42 changed files with 407 additions and 619 deletions

View File

@@ -6,7 +6,6 @@ import type {
CoreData,
DeviceData,
DeviceEntity,
Devices,
Entities,
EntityItem,
ModuleItem,
@@ -53,11 +52,9 @@ export const readActivity = () => alovaInstance.Get<Activity>('/rest/activity');
// API
export const API = (apiCall: APIcall) => alovaInstance.Post('/api', apiCall);
// UploadFileForm
export const getSettings = () => alovaInstance.Get('/rest/getSettings');
export const getCustomizations = () => alovaInstance.Get('/rest/getCustomizations');
export const getEntities = () => alovaInstance.Get<Entities>('/rest/getEntities');
export const getSchedule = () => alovaInstance.Get('/rest/getSchedule');
// DownloadUpload
export const exportData = (type: string) =>
alovaInstance.Get('/rest/exportData', { params: { type } });
// SettingsCustomization
export const readDeviceEntities = (id: number) =>
@@ -75,7 +72,6 @@ export const readDeviceEntities = (id: number) =>
}));
}
});
export const readDevices = () => alovaInstance.Get<Devices>('/rest/devices');
export const resetCustomizations = () =>
alovaInstance.Post('/rest/resetCustomizations');
export const writeCustomizationEntities = (data: {

View File

@@ -1,12 +1,8 @@
import type { HardwareStatus, LogSettings, SystemStatus } from 'types';
import type { LogSettings, SystemStatus } from 'types';
import { alovaInstance, alovaInstanceGH } from './endpoints';
// hardwareStatus - also used to ping in Restart monitor for pinging
export const readHardwareStatus = () =>
alovaInstance.Get<HardwareStatus>('/rest/hardwareStatus');
// SystemStatus
// systemStatus - also used to ping in Restart monitor for pinging
export const readSystemStatus = () =>
alovaInstance.Get<SystemStatus>('/rest/systemStatus');

View File

@@ -50,8 +50,8 @@ import { useI18nContext } from 'i18n/i18n-react';
import {
API,
readCoreData,
readDeviceEntities,
readDevices,
resetCustomizations,
writeCustomizationEntities,
writeDeviceName
@@ -60,7 +60,7 @@ import SettingsCustomizationsDialog from './CustomizationsDialog';
import EntityMaskToggle from './EntityMaskToggle';
import OptionIcon from './OptionIcon';
import { DeviceEntityMask } from './types';
import type { APIcall, DeviceEntity, DeviceShort } from './types';
import type { APIcall, Device, DeviceEntity } from './types';
export const APIURL = window.location.origin + '/api/';
@@ -81,8 +81,8 @@ const Customizations = () => {
useLayoutTitle(LL.CUSTOMIZATIONS());
// fetch devices first
const { data: devices, send: fetchDevices } = useRequest(readDevices);
// fetch devices first from coreData
const { data: devices, send: fetchCoreData } = useRequest(readCoreData);
const { send: sendAPI } = useRequest((data: APIcall) => API(data), {
immediate: false
@@ -242,13 +242,13 @@ const Customizations = () => {
useEffect(() => {
if (devices && selectedDevice !== -1) {
void sendDeviceEntities(selectedDevice);
const id = devices.devices.findIndex((d) => d.i === selectedDevice);
if (id === -1) {
const index = devices.devices.findIndex((d) => d.id === selectedDevice);
if (index === -1) {
setSelectedDevice(-1);
setSelectedDeviceTypeNameURL('');
} else {
setSelectedDeviceTypeNameURL(devices.devices[id].url || '');
setSelectedDeviceName(devices.devices[id].s);
setSelectedDeviceTypeNameURL(devices.devices[index].url || '');
setSelectedDeviceName(devices.devices[index].n);
setNumChanges(0);
setRestartNeeded(false);
}
@@ -414,7 +414,7 @@ const Customizations = () => {
})
.finally(async () => {
setRename(false);
await fetchDevices();
await fetchCoreData();
});
};
@@ -449,9 +449,9 @@ const Customizations = () => {
<MenuItem disabled key={-1} value={-1}>
{LL.SELECT_DEVICE()}...
</MenuItem>
{devices.devices.map((device: DeviceShort) => (
<MenuItem key={device.i} value={device.i}>
{device.s}&nbsp;({device.tn})
{devices.devices.map((device: Device) => (
<MenuItem key={device.id} value={device.id}>
{device.n}&nbsp;({device.tn})
</MenuItem>
))}
</TextField>

View File

@@ -71,6 +71,7 @@ export interface Device {
p: number; // productid
v: string; // version
e: number; // entities
url?: string; // lowercase type name used in API URL
}
export interface TemperatureSensor {
@@ -113,20 +114,6 @@ export interface CoreData {
devices: Device[];
}
export interface DeviceShort {
i: number; // id
d?: number; // deviceid
p?: number; // productid
s: string; // shortname
t?: number; // device type id
tn?: string; // device type internal name (translated)
url?: string; // lowercase type name used in API URL
}
export interface Devices {
devices: DeviceShort[];
}
export interface DeviceValue {
id: string; // index, contains mask+name
v: unknown; // value, Number or String

View File

@@ -16,7 +16,7 @@ import {
} from '@mui/material';
import Grid from '@mui/material/Grid2';
import { readHardwareStatus } from 'api/system';
import { readSystemStatus } from 'api/system';
import { useRequest } from 'alova/client';
import RestartMonitor from 'app/status/RestartMonitor';
@@ -49,7 +49,7 @@ export function boardProfileSelectItems() {
}
const ApplicationSettings = () => {
const { data: hardwareData } = useRequest(readHardwareStatus);
const { data: hardwareData } = useRequest(readSystemStatus);
const {
loadData,

View File

@@ -18,13 +18,7 @@ import {
import Grid from '@mui/material/Grid2';
import * as SystemApi from 'api/system';
import {
API,
getCustomizations,
getEntities,
getSchedule,
getSettings
} from 'api/app';
import { API, exportData } from 'api/app';
import {
checkUpgrade,
getDevVersion,
@@ -52,48 +46,26 @@ const DownloadUpload = () => {
const [useDev, setUseDev] = useState<boolean>(false);
const [upgradeAvailable, setUpgradeAvailable] = useState<boolean>(false);
const { send: sendSettings } = useRequest(getSettings(), {
const { send: sendExportData } = useRequest((type: string) => exportData(type), {
immediate: false
}).onSuccess((event) => {
saveFile(event.data, 'settings.json');
});
const { send: sendCustomizations } = useRequest(getCustomizations(), {
immediate: false
}).onSuccess((event) => {
saveFile(event.data, 'customizations.json');
});
const { send: sendEntities } = useRequest(getEntities(), {
immediate: false
}).onSuccess((event) => {
saveFile(event.data, 'custom_entities.json');
});
const { send: sendSchedule } = useRequest(getSchedule(), {
immediate: false
}).onSuccess((event) => {
saveFile(event.data, 'schedule.json');
});
})
.onSuccess((event) => {
saveFile(event.data, event.args[0]);
toast.info(LL.DOWNLOAD_SUCCESSFUL());
})
.onError((error) => {
toast.error(error.message);
});
const { send: sendAPI } = useRequest((data: APIcall) => API(data), {
immediate: false
});
const { send: sendAPIandSave } = useRequest((data: APIcall) => API(data), {
immediate: false
}).onSuccess((event) => {
saveFile(
event.data,
String(event.args[0].device) + '_' + String(event.args[0].cmd) + '.txt'
);
});
const {
data: data,
send: loadData,
error
} = useRequest(SystemApi.readHardwareStatus);
} = useRequest(SystemApi.readSystemStatus);
const { send: sendUploadURL } = useRequest(
(data: { url: string }) => uploadURL(data),
@@ -123,6 +95,8 @@ const DownloadUpload = () => {
// immediate: false,
// initialData: '3.6.5'
});
// called immediately to get the latest version, on page load, then check for upgrade
const { data: latestDevVersion } = useRequest(getDevVersion, {
// uncomment next 2 lines for testing, uses https://github.com/emsesp/EMS-ESP32/releases/download/latest/EMS-ESP-3_7_0-dev_31-ESP32-16MB+.bin
// immediate: false,
@@ -175,40 +149,9 @@ const DownloadUpload = () => {
type: 'text/plain'
})
);
anchor.download = 'emsesp_' + filename;
anchor.download = 'emsesp_' + filename + '.json';
anchor.click();
URL.revokeObjectURL(anchor.href);
toast.info(LL.DOWNLOAD_SUCCESSFUL());
};
const downloadSettings = async () => {
await sendSettings().catch((error: Error) => {
toast.error(error.message);
});
};
const downloadCustomizations = async () => {
await sendCustomizations().catch((error: Error) => {
toast.error(error.message);
});
};
const downloadEntities = async () => {
await sendEntities().catch((error: Error) => {
toast.error(error.message);
});
};
const downloadSchedule = async () => {
await sendSchedule().catch((error: Error) => {
toast.error(error.message);
});
};
const callAPIandSave = async (device: string, cmd: string) => {
await sendAPIandSave({ device, cmd, id: 0 }).catch((error: Error) => {
toast.error(error.message);
});
};
useLayoutTitle(LL.DOWNLOAD_UPLOAD());
@@ -301,7 +244,7 @@ const DownloadUpload = () => {
startIcon={<DownloadIcon />}
variant="outlined"
color="primary"
onClick={downloadSettings}
onClick={() => sendExportData('settings')}
>
{LL.DOWNLOAD(1)}&nbsp;{LL.SETTINGS_OF(LL.APPLICATION())}
</Button>
@@ -311,7 +254,7 @@ const DownloadUpload = () => {
startIcon={<DownloadIcon />}
variant="outlined"
color="primary"
onClick={downloadCustomizations}
onClick={() => sendExportData('customizations')}
>
{LL.DOWNLOAD(1)}&nbsp;{LL.CUSTOMIZATIONS()}
</Button>
@@ -320,7 +263,7 @@ const DownloadUpload = () => {
startIcon={<DownloadIcon />}
variant="outlined"
color="primary"
onClick={downloadEntities}
onClick={() => sendExportData('entities')}
>
{LL.DOWNLOAD(1)}&nbsp;{LL.CUSTOM_ENTITIES(0)}
</Button>
@@ -329,7 +272,7 @@ const DownloadUpload = () => {
startIcon={<DownloadIcon />}
variant="outlined"
color="primary"
onClick={downloadSchedule}
onClick={() => sendExportData('schedule')}
>
{LL.DOWNLOAD(1)}&nbsp;{LL.SCHEDULE(0)}
</Button>

View File

@@ -36,7 +36,7 @@ const HardwareStatus = () => {
data: data,
send: loadData,
error
} = useAutoRequest(SystemApi.readHardwareStatus, { pollingTime: 2000 });
} = useAutoRequest(SystemApi.readSystemStatus, { pollingTime: 2000 });
const content = () => {
if (!data) {

View File

@@ -8,7 +8,7 @@ import {
Typography
} from '@mui/material';
import { readHardwareStatus } from 'api/system';
import { readSystemStatus } from 'api/system';
import { dialogStyle } from 'CustomTheme';
import { useAutoRequest } from 'alova/client';
@@ -22,7 +22,7 @@ const RestartMonitor = () => {
let count = 0;
const { data } = useAutoRequest(readHardwareStatus, {
const { data } = useAutoRequest(readSystemStatus, {
pollingTime: 1000,
force: true,
initialData: { status: 'Getting ready...' },
@@ -38,7 +38,7 @@ const RestartMonitor = () => {
document.location.href = '/';
}
})
.onError((error, _method) => {
.onError((error) => {
setErrorMessage(error.message);
});

View File

@@ -29,8 +29,8 @@ import {
useTheme
} from '@mui/material';
import * as SystemApi from 'api/system';
import { API } from 'api/app';
import { readSystemStatus } from 'api/system';
import { dialogStyle } from 'CustomTheme';
import { useAutoRequest, useRequest } from 'alova/client';
@@ -63,7 +63,7 @@ const SystemStatus = () => {
data: data,
send: loadData,
error
} = useAutoRequest(SystemApi.readSystemStatus, {
} = useAutoRequest(readSystemStatus, {
initialData: [],
pollingTime: 5000,
async middleware(_, next) {
@@ -101,7 +101,7 @@ const SystemStatus = () => {
const busStatus = () => {
if (data) {
switch (data.status) {
switch (data.bus_status) {
case busConnectionStatus.BUS_STATUS_CONNECTED:
return (
'EMS ' +
@@ -120,7 +120,7 @@ const SystemStatus = () => {
};
const busStatusHighlight = () => {
switch (data.status) {
switch (data.bus_status) {
case busConnectionStatus.BUS_STATUS_TX_ERRORS:
return theme.palette.warning.main;
case busConnectionStatus.BUS_STATUS_CONNECTED:

View File

@@ -8,7 +8,7 @@ import Grid from '@mui/material/Grid2';
import { fetchLogES, readLogSettings, updateLogSettings } from 'api/system';
import { useRequest, useSSE } from 'alova/client';
import { useSSE } from 'alova/client';
import {
BlockFormControlLabel,
BlockNavigation,

View File

@@ -16,7 +16,7 @@ const DragNdrop = ({ onFileSelected }) => {
const { LL } = useI18nContext();
const checkFileExtension = (file: File) => {
const validExtensions = ['.json', '.txt', '.csv', '.bin', '.md5'];
const validExtensions = ['.json', '.bin', '.md5'];
const fileName = file.name;
const fileExtension = fileName.substring(fileName.lastIndexOf('.'));
if (validExtensions.includes(fileExtension)) {

View File

@@ -2,8 +2,19 @@ import type { busConnectionStatus } from 'app/main/types';
import type { NetworkConnectionStatus } from './network';
export interface HardwareStatus {
export interface SystemStatus {
emsesp_version: string;
bus_status: busConnectionStatus;
uptime: number;
bus_uptime: number;
num_devices: number;
num_sensors: number;
num_analogs: number;
ntp_status: number;
mqtt_status: boolean;
ap_status: boolean;
network_status: NetworkConnectionStatus;
wifi_rssi: number;
build_flags: string;
esp_platform: string;
max_alloc_heap: number;
@@ -32,22 +43,6 @@ export interface HardwareStatus {
status: string;
}
export interface SystemStatus {
emsesp_version: string;
status: busConnectionStatus;
uptime: number;
bus_uptime: number;
num_devices: number;
num_sensors: number;
num_analogs: number;
free_heap: number;
ntp_status: number;
mqtt_status: boolean;
ap_status: boolean;
network_status: NetworkConnectionStatus;
wifi_rssi: number;
}
export enum LogLevel {
ERROR = 3,
WARNING = 4,