mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
update #6
This commit is contained in:
@@ -23,14 +23,14 @@
|
||||
"@emotion/react": "^11.11.1",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@mui/icons-material": "^5.11.16",
|
||||
"@mui/material": "^5.13.4",
|
||||
"@mui/material": "^5.13.5",
|
||||
"@table-library/react-table-library": "4.1.4",
|
||||
"@types/lodash-es": "^4.17.7",
|
||||
"@types/node": "^20.3.0",
|
||||
"@types/react": "^18.2.11",
|
||||
"@types/react-dom": "^18.2.4",
|
||||
"@types/node": "^20.3.1",
|
||||
"@types/react": "^18.2.12",
|
||||
"@types/react-dom": "^18.2.5",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"alova": "^2.6.0",
|
||||
"alova": "^2.6.1",
|
||||
"async-validator": "^4.2.5",
|
||||
"axios": "^1.4.0",
|
||||
"history": "^5.3.0",
|
||||
@@ -47,8 +47,8 @@
|
||||
"typescript": "^5.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.9",
|
||||
"@typescript-eslint/parser": "^5.59.9",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.11",
|
||||
"@typescript-eslint/parser": "^5.59.11",
|
||||
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||
"eslint": "^8.42.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
@@ -65,7 +65,7 @@
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^2.8.8",
|
||||
"rollup-plugin-visualizer": "^5.9.2",
|
||||
"terser": "^5.17.7",
|
||||
"terser": "^5.18.0",
|
||||
"vite": "^4.3.9",
|
||||
"vite-plugin-svgr": "^3.2.0",
|
||||
"vite-tsconfig-paths": "^4.2.0"
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { APSettings, APStatus } from 'types';
|
||||
|
||||
export const readAPStatus = () => alovaInstance.Get<APStatus>('/apStatus');
|
||||
|
||||
// TODO change AXIOS to Alova
|
||||
export function readAPSettings(): AxiosPromise<APSettings> {
|
||||
return AXIOS.get('/apSettings');
|
||||
}
|
||||
|
||||
@@ -32,10 +32,10 @@ export const alovaInstance = createAlova({
|
||||
|
||||
responded: {
|
||||
onSuccess: async (response) => {
|
||||
if (response.status == 202) {
|
||||
if (response.status == 205) {
|
||||
throw new Error('Reboot required');
|
||||
} else if (response.status === 400) {
|
||||
throw new Error('Invalid command');
|
||||
throw new Error('Request Failed');
|
||||
} else if (response.status >= 400) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
@@ -114,8 +114,7 @@ export const AXIOS_BIN = axios.create({
|
||||
transformResponse: [(data) => unpack(data)]
|
||||
});
|
||||
|
||||
// TODO replace with alova
|
||||
// TODO see https://alova.js.org/next-step/download-upload-progress
|
||||
// TODO replace upload with alova, see https://alova.js.org/next-step/download-upload-progress
|
||||
export interface FileUploadConfig {
|
||||
cancelToken?: CancelToken;
|
||||
onUploadProgress?: (progressEvent: AxiosProgressEvent) => void;
|
||||
|
||||
@@ -28,7 +28,6 @@ export const apStatusHighlight = ({ status }: APStatus, theme: Theme) => {
|
||||
};
|
||||
|
||||
const APStatusForm: FC = () => {
|
||||
// TODO missing update!
|
||||
const { data: data, send: loadData, error } = useRequest(APApi.readAPStatus());
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
@@ -26,7 +26,6 @@ export const mqttStatusHighlight = ({ enabled, connected }: MqttStatus, theme: T
|
||||
|
||||
export const mqttPublishHighlight = ({ mqtt_fails }: MqttStatus, theme: Theme) => {
|
||||
if (mqtt_fails === 0) return theme.palette.success.main;
|
||||
|
||||
if (mqtt_fails < 10) return theme.palette.warning.main;
|
||||
|
||||
return theme.palette.error.main;
|
||||
@@ -39,8 +38,7 @@ export const mqttQueueHighlight = ({ mqtt_queued }: MqttStatus, theme: Theme) =>
|
||||
};
|
||||
|
||||
const MqttStatusForm: FC = () => {
|
||||
// TODO missing update!
|
||||
|
||||
// TODO replace with const { data: data, send: loadData, error } = useRequest(APApi.readAPStatus());
|
||||
const { loadData, data, errorMessage } = useRest<MqttStatus>({ read: MqttApi.readMqttStatus });
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
@@ -59,8 +59,7 @@ const IPs = (status: NetworkStatus) => {
|
||||
};
|
||||
|
||||
const NetworkStatusForm: FC = () => {
|
||||
// TODO missing update!
|
||||
|
||||
// TODO replace with const { data: data, send: loadData, error } = useRequest(APApi.readAPStatus());
|
||||
const { loadData, data, errorMessage } = useRest<NetworkStatus>({ read: NetworkApi.readNetworkStatus });
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
@@ -52,9 +52,9 @@ export const ntpStatusHighlight = ({ status }: NTPStatus, theme: Theme) => {
|
||||
};
|
||||
|
||||
const NTPStatusForm: FC = () => {
|
||||
// TODO missing update!
|
||||
|
||||
// TODO replace with const { data: data, send: loadData, error } = useRequest(APApi.readAPStatus());
|
||||
const { loadData, data, errorMessage } = useRest<NTPStatus>({ read: NTPApi.readNTPStatus });
|
||||
|
||||
const [localTime, setLocalTime] = useState<string>('');
|
||||
const [settingTime, setSettingTime] = useState<boolean>(false);
|
||||
const [processing, setProcessing] = useState<boolean>(false);
|
||||
|
||||
@@ -49,8 +49,7 @@ const levelLabel = (level: LogLevel) => {
|
||||
const SystemLog: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
// TODO missing update!
|
||||
|
||||
// TODO replace with const { data: data, send: loadData, error } = useRequest(APApi.readAPStatus());
|
||||
const { loadData, data, setData, origData, dirtyFlags, blocker, setDirtyFlags, setOrigData } = useRest<LogSettings>({
|
||||
read: SystemApi.readLogSettings
|
||||
});
|
||||
|
||||
@@ -53,8 +53,7 @@ const SystemStatusForm: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
const [restarting, setRestarting] = useState<boolean>();
|
||||
|
||||
// TODO missing update!
|
||||
|
||||
// TODO replace with const { data: data, send: loadData, error } = useRequest(APApi.readAPStatus());
|
||||
const { loadData, data, errorMessage } = useRest<SystemStatus>({ read: SystemApi.readSystemStatus });
|
||||
|
||||
const { me } = useContext(AuthenticatedContext);
|
||||
|
||||
@@ -69,7 +69,7 @@ const DashboardDevices: FC = () => {
|
||||
immediate: true
|
||||
});
|
||||
|
||||
const { data: deviceData, send: readDeviceData } = useRequest((data) => EMSESP.readDeviceData(data), {
|
||||
const { data: deviceData, send: readDeviceData } = useRequest((id) => EMSESP.readDeviceData(id), {
|
||||
initialData: {
|
||||
data: []
|
||||
},
|
||||
@@ -444,7 +444,7 @@ const DashboardDevices: FC = () => {
|
||||
};
|
||||
|
||||
const renderDeviceData = () => {
|
||||
if (!selectedDevice || deviceData.data === undefined) {
|
||||
if (!selectedDevice) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ import { Button, Typography, Box } from '@mui/material';
|
||||
import { useSort, SortToggleType } from '@table-library/react-table-library/sort';
|
||||
import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table';
|
||||
import { useTheme } from '@table-library/react-table-library/theme';
|
||||
import { useState, useContext, useCallback, useEffect } from 'react';
|
||||
import { useRequest } from 'alova';
|
||||
import { useState, useContext, useEffect } from 'react';
|
||||
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
@@ -17,24 +18,40 @@ import * as EMSESP from './api';
|
||||
|
||||
import { DeviceValueUOM, DeviceValueUOM_s, AnalogTypeNames } from './types';
|
||||
import { temperatureSensorItemValidation, analogSensorItemValidation } from './validators';
|
||||
import type { SensorData, TemperatureSensor, AnalogSensor } from './types';
|
||||
import type { TemperatureSensor, AnalogSensor } from './types';
|
||||
import type { FC } from 'react';
|
||||
import { ButtonRow, SectionContent } from 'components';
|
||||
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { extractErrorMessage } from 'utils';
|
||||
|
||||
const DashboardSensors: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
const { me } = useContext(AuthenticatedContext);
|
||||
const [sensorData, setSensorData] = useState<SensorData>({ ts: [], as: [], analog_enabled: false });
|
||||
const [selectedTemperatureSensor, setSelectedTemperatureSensor] = useState<TemperatureSensor>();
|
||||
const [selectedAnalogSensor, setSelectedAnalogSensor] = useState<AnalogSensor>();
|
||||
const [temperatureDialogOpen, setTemperatureDialogOpen] = useState<boolean>(false);
|
||||
const [analogDialogOpen, setAnalogDialogOpen] = useState<boolean>(false);
|
||||
const [creating, setCreating] = useState<boolean>(false);
|
||||
|
||||
const { data: sensorData, send: fetchSensorData } = useRequest(() => EMSESP.readSensorData(), {
|
||||
initialData: {
|
||||
ts: [],
|
||||
as: [],
|
||||
analog_enabled: false
|
||||
},
|
||||
force: true,
|
||||
immediate: true
|
||||
});
|
||||
|
||||
const { send: writeTemperatureSensor } = useRequest((data) => EMSESP.writeTemperatureSensor(data), {
|
||||
immediate: false
|
||||
});
|
||||
|
||||
const { send: writeAnalogSensor } = useRequest((data) => EMSESP.writeAnalogSensor(data), {
|
||||
immediate: false
|
||||
});
|
||||
|
||||
const isAdmin = me.admin;
|
||||
|
||||
const common_theme = useTheme({
|
||||
@@ -101,20 +118,6 @@ const DashboardSensors: FC = () => {
|
||||
}
|
||||
]);
|
||||
|
||||
const fetchSensorData = useCallback(async () => {
|
||||
if (!analogDialogOpen && !temperatureDialogOpen) {
|
||||
try {
|
||||
setSensorData((await EMSESP.readSensorData()).data);
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||
}
|
||||
}
|
||||
}, [LL, analogDialogOpen, temperatureDialogOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
void fetchSensorData();
|
||||
}, [fetchSensorData]);
|
||||
|
||||
const getSortIcon = (state: any, sortKey: any) => {
|
||||
if (state.sortKey === sortKey && state.reverse) {
|
||||
return <KeyboardArrowDownOutlinedIcon />;
|
||||
@@ -229,27 +232,18 @@ const DashboardSensors: FC = () => {
|
||||
};
|
||||
|
||||
const onTemperatureDialogSave = async (ts: TemperatureSensor) => {
|
||||
try {
|
||||
const response = await EMSESP.writeTemperatureSensor({
|
||||
id: ts.id,
|
||||
name: ts.n,
|
||||
offset: ts.o
|
||||
});
|
||||
if (response.status === 204) {
|
||||
toast.error(LL.UPDATE_OF(LL.SENSOR(2)) + ' ' + LL.FAILED(1));
|
||||
} else if (response.status === 403) {
|
||||
// TODO fix
|
||||
toast.error(LL.HTTP_ERROR('poep'));
|
||||
} else {
|
||||
await writeTemperatureSensor({ id: ts.id, name: ts.n, offset: ts.o })
|
||||
.then(() => {
|
||||
toast.success(LL.UPDATED_OF(LL.SENSOR(1)));
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||
} finally {
|
||||
setTemperatureDialogOpen(false);
|
||||
setSelectedTemperatureSensor(undefined);
|
||||
await fetchSensorData();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error(LL.UPDATE_OF(LL.SENSOR(2)) + ' ' + LL.FAILED(1));
|
||||
})
|
||||
.finally(async () => {
|
||||
setTemperatureDialogOpen(false);
|
||||
setSelectedTemperatureSensor(undefined);
|
||||
await fetchSensorData();
|
||||
});
|
||||
};
|
||||
|
||||
const updateAnalogSensor = (as: AnalogSensor) => {
|
||||
@@ -281,33 +275,27 @@ const DashboardSensors: FC = () => {
|
||||
};
|
||||
|
||||
const onAnalogDialogSave = async (as: AnalogSensor) => {
|
||||
try {
|
||||
const response = await EMSESP.writeAnalogSensor({
|
||||
id: as.id,
|
||||
gpio: as.g,
|
||||
name: as.n,
|
||||
offset: as.o,
|
||||
factor: as.f,
|
||||
uom: as.u,
|
||||
type: as.t,
|
||||
deleted: as.d
|
||||
});
|
||||
|
||||
if (response.status === 204) {
|
||||
toast.error(LL.UPDATE_OF(LL.ANALOG_SENSOR(5)) + ' ' + LL.FAILED(1));
|
||||
} else if (response.status === 403) {
|
||||
// TODO fix
|
||||
toast.error(LL.HTTP_ERROR('poep'));
|
||||
} else {
|
||||
await writeAnalogSensor({
|
||||
id: as.id,
|
||||
gpio: as.g,
|
||||
name: as.n,
|
||||
offset: as.o,
|
||||
factor: as.f,
|
||||
uom: as.u,
|
||||
type: as.t,
|
||||
deleted: as.d
|
||||
})
|
||||
.then(() => {
|
||||
toast.success(LL.UPDATED_OF(LL.ANALOG_SENSOR(2)));
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||
} finally {
|
||||
setAnalogDialogOpen(false);
|
||||
setSelectedAnalogSensor(undefined);
|
||||
await fetchSensorData();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error(LL.UPDATE_OF(LL.ANALOG_SENSOR(5)) + ' ' + LL.FAILED(1));
|
||||
})
|
||||
.finally(async () => {
|
||||
setAnalogDialogOpen(false);
|
||||
setSelectedAnalogSensor(undefined);
|
||||
await fetchSensorData();
|
||||
});
|
||||
};
|
||||
|
||||
const RenderTemperatureSensors = () => (
|
||||
@@ -433,7 +421,7 @@ const DashboardSensors: FC = () => {
|
||||
{sensorData?.analog_enabled === true && (
|
||||
<>
|
||||
<Typography sx={{ pt: 4, pb: 1 }} variant="h6" color="secondary">
|
||||
{LL.ANALOG_SENSORS(0)}
|
||||
{LL.ANALOG_SENSORS()}
|
||||
</Typography>
|
||||
<RenderAnalogSensors />
|
||||
{selectedAnalogSensor && (
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
} from '@mui/material';
|
||||
import { Body, Cell, Header, HeaderCell, HeaderRow, Row, Table } from '@table-library/react-table-library/table';
|
||||
import { useTheme as tableTheme } from '@table-library/react-table-library/theme';
|
||||
import { useRequest } from 'alova';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
@@ -32,7 +33,6 @@ import type { FC } from 'react';
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { extractErrorMessage, useRest } from 'utils';
|
||||
|
||||
export const isConnected = ({ status }: Status) => status !== busConnectionStatus.BUS_STATUS_OFFLINE;
|
||||
|
||||
@@ -64,9 +64,7 @@ const showQuality = (stat: Stat) => {
|
||||
};
|
||||
|
||||
const DashboardStatus: FC = () => {
|
||||
// TODO missing update!
|
||||
|
||||
const { loadData, data, errorMessage } = useRest<Status>({ read: EMSESP.readStatus });
|
||||
const { data: data, send: loadData, error } = useRequest(EMSESP.readStatus, { force: true });
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
@@ -75,6 +73,10 @@ const DashboardStatus: FC = () => {
|
||||
|
||||
const { me } = useContext(AuthenticatedContext);
|
||||
|
||||
const { send: scanDevices } = useRequest(EMSESP.scanDevices, {
|
||||
immediate: false
|
||||
});
|
||||
|
||||
const stats_theme = tableTheme({
|
||||
Table: `
|
||||
--data-table-library_grid-template-columns: repeat(1, minmax(0, 1fr)) 90px 90px 80px;
|
||||
@@ -160,14 +162,23 @@ const DashboardStatus: FC = () => {
|
||||
};
|
||||
|
||||
const scan = async () => {
|
||||
try {
|
||||
await EMSESP.scanDevices();
|
||||
toast.info(LL.SCANNING() + '...');
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||
} finally {
|
||||
setConfirmScan(false);
|
||||
}
|
||||
await scanDevices()
|
||||
.then(() => {
|
||||
toast.info(LL.SCANNING() + '...');
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.error(err.message);
|
||||
});
|
||||
setConfirmScan(false);
|
||||
|
||||
// try {
|
||||
// await EMSESP.scanDevices();
|
||||
// toast.info(LL.SCANNING() + '...');
|
||||
// } catch (error) {
|
||||
// toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||
// } finally {
|
||||
// setConfirmScan(false);
|
||||
// }
|
||||
};
|
||||
|
||||
const renderScanDialog = () => (
|
||||
@@ -187,7 +198,7 @@ const DashboardStatus: FC = () => {
|
||||
|
||||
const content = () => {
|
||||
if (!data) {
|
||||
return <FormLoader onRetry={loadData} errorMessage={errorMessage} />;
|
||||
return <FormLoader onRetry={loadData} errorMessage={error?.message} />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,6 +2,7 @@ import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import { Box, Button, Checkbox, MenuItem, Grid, Typography, Divider, InputAdornment, TextField } from '@mui/material';
|
||||
import { useRequest } from 'alova';
|
||||
import { useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
@@ -23,7 +24,7 @@ import {
|
||||
|
||||
import RestartMonitor from 'framework/system/RestartMonitor';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { numberValue, extractErrorMessage, updateValueDirty, useRest2 } from 'utils';
|
||||
import { numberValue, updateValueDirty, useRest2 } from 'utils';
|
||||
import { validate } from 'validators';
|
||||
|
||||
export function boardProfileSelectItems() {
|
||||
@@ -39,7 +40,7 @@ const SettingsApplication: FC = () => {
|
||||
loadData,
|
||||
saveData,
|
||||
saving,
|
||||
setData,
|
||||
updateDataValue,
|
||||
data,
|
||||
origData,
|
||||
dirtyFlags,
|
||||
@@ -51,45 +52,48 @@ const SettingsApplication: FC = () => {
|
||||
read: EMSESP.readSettings,
|
||||
update: EMSESP.writeSettings
|
||||
});
|
||||
|
||||
const [restarting, setRestarting] = useState<boolean>();
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
const updateFormValue = updateValueDirty(origData, dirtyFlags, setDirtyFlags, setData);
|
||||
const updateFormValue = updateValueDirty(origData, dirtyFlags, setDirtyFlags, updateDataValue);
|
||||
|
||||
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||
const [processingBoard, setProcessingBoard] = useState<boolean>(false);
|
||||
|
||||
// TODO remove - just for testing loaddata
|
||||
// useEffect(() => {
|
||||
// void loadData();
|
||||
// }, []);
|
||||
const {
|
||||
loading: processingBoard,
|
||||
send: readBoardProfile,
|
||||
onSuccess: onSuccessBoardProfile
|
||||
} = useRequest((boardProfile) => EMSESP.getBoardProfile(boardProfile), {
|
||||
immediate: false
|
||||
});
|
||||
|
||||
// TODO replace with Alova!
|
||||
const updateBoardProfile = async (boardProfile: string) => {
|
||||
setProcessingBoard(true);
|
||||
try {
|
||||
const response = await EMSESP.getBoardProfile({ board_profile: boardProfile });
|
||||
if (data) {
|
||||
setData({
|
||||
...data,
|
||||
board_profile: boardProfile,
|
||||
led_gpio: response.data.led_gpio,
|
||||
dallas_gpio: response.data.dallas_gpio,
|
||||
rx_gpio: response.data.rx_gpio,
|
||||
tx_gpio: response.data.tx_gpio,
|
||||
pbutton_gpio: response.data.pbutton_gpio,
|
||||
phy_type: response.data.phy_type,
|
||||
eth_power: response.data.eth_power,
|
||||
eth_phy_addr: response.data.eth_phy_addr,
|
||||
eth_clock_mode: response.data.eth_clock_mode
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||
} finally {
|
||||
setProcessingBoard(false);
|
||||
}
|
||||
const { send: restartCommand } = useRequest(EMSESP.restart(), {
|
||||
immediate: false
|
||||
});
|
||||
|
||||
onSuccessBoardProfile((event) => {
|
||||
const response = event.data as unknown as Settings;
|
||||
updateDataValue({
|
||||
...data,
|
||||
board_profile: response.board_profile,
|
||||
led_gpio: response.led_gpio,
|
||||
dallas_gpio: response.dallas_gpio,
|
||||
rx_gpio: response.rx_gpio,
|
||||
tx_gpio: response.tx_gpio,
|
||||
pbutton_gpio: response.pbutton_gpio,
|
||||
phy_type: response.phy_type,
|
||||
eth_power: response.eth_power,
|
||||
eth_phy_addr: response.eth_phy_addr,
|
||||
eth_clock_mode: response.eth_clock_mode
|
||||
});
|
||||
});
|
||||
|
||||
const updateBoardProfile = async (board_profile: string) => {
|
||||
await readBoardProfile(board_profile).catch((error) => {
|
||||
toast.error(error.message);
|
||||
});
|
||||
};
|
||||
|
||||
const content = () => {
|
||||
@@ -101,9 +105,10 @@ const SettingsApplication: FC = () => {
|
||||
try {
|
||||
setFieldErrors(undefined);
|
||||
await validate(createSettingsValidator(data), data);
|
||||
await saveData();
|
||||
} catch (errors: any) {
|
||||
setFieldErrors(errors);
|
||||
} finally {
|
||||
await saveData();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -111,7 +116,7 @@ const SettingsApplication: FC = () => {
|
||||
const boardProfile = event.target.value;
|
||||
updateFormValue(event);
|
||||
if (boardProfile === 'CUSTOM') {
|
||||
setData({
|
||||
updateDataValue({
|
||||
...data,
|
||||
board_profile: boardProfile
|
||||
});
|
||||
@@ -122,12 +127,10 @@ const SettingsApplication: FC = () => {
|
||||
|
||||
const restart = async () => {
|
||||
await validateAndSubmit();
|
||||
try {
|
||||
await EMSESP.restart();
|
||||
setRestarting(true);
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||
}
|
||||
await restartCommand().catch((error) => {
|
||||
toast.error(error.message);
|
||||
});
|
||||
setRestarting(true);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
} from '@mui/material';
|
||||
import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table';
|
||||
import { useTheme } from '@table-library/react-table-library/theme';
|
||||
import { useRequest } from 'alova';
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { unstable_useBlocker as useBlocker } from 'react-router-dom';
|
||||
import { toast } from 'react-toastify';
|
||||
@@ -32,13 +33,12 @@ import SettingsCustomizationDialog from './SettingsCustomizationDialog';
|
||||
import * as EMSESP from './api';
|
||||
|
||||
import { DeviceEntityMask } from './types';
|
||||
import type { DeviceShort, Devices, DeviceEntity } from './types';
|
||||
import type { DeviceShort, DeviceEntity } from './types';
|
||||
import type { FC } from 'react';
|
||||
import { ButtonRow, FormLoader, SectionContent, MessageBox, BlockNavigation } from 'components';
|
||||
import { ButtonRow, SectionContent, MessageBox, BlockNavigation } from 'components';
|
||||
|
||||
import RestartMonitor from 'framework/system/RestartMonitor';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { extractErrorMessage } from 'utils';
|
||||
|
||||
export const APIURL = window.location.origin + '/api/';
|
||||
|
||||
@@ -46,11 +46,10 @@ const SettingsCustomization: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
const [numChanges, setNumChanges] = useState<number>(0);
|
||||
const blocker = useBlocker(numChanges !== 0);
|
||||
|
||||
const [restarting, setRestarting] = useState<boolean>(false);
|
||||
const [restartNeeded, setRestartNeeded] = useState<boolean>(false);
|
||||
const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>();
|
||||
const [devices, setDevices] = useState<Devices>();
|
||||
const [errorMessage, setErrorMessage] = useState<string>();
|
||||
const [deviceEntities, setDeviceEntities] = useState<DeviceEntity[]>([]);
|
||||
const [selectedDevice, setSelectedDevice] = useState<number>(-1);
|
||||
const [confirmReset, setConfirmReset] = useState<boolean>(false);
|
||||
const [selectedFilters, setSelectedFilters] = useState<number>(0);
|
||||
@@ -58,6 +57,36 @@ const SettingsCustomization: FC = () => {
|
||||
const [selectedDeviceEntity, setSelectedDeviceEntity] = useState<DeviceEntity>();
|
||||
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
||||
|
||||
const { send: resetCustomizations } = useRequest(EMSESP.resetCustomizations(), {
|
||||
immediate: false
|
||||
});
|
||||
|
||||
const { data: devices } = useRequest(EMSESP.readDevices());
|
||||
|
||||
const { send: writeCustomEntities } = useRequest((data) => EMSESP.writeCustomEntities(data), { immediate: false });
|
||||
|
||||
const {
|
||||
send: readDeviceEntities,
|
||||
update: updateDeviceEntities,
|
||||
onSuccess: onSuccess
|
||||
} = useRequest((data) => EMSESP.readDeviceEntities(data), {
|
||||
initialData: [],
|
||||
immediate: false,
|
||||
force: true
|
||||
});
|
||||
|
||||
const setOriginalSettings = (data: DeviceEntity[]) => {
|
||||
setDeviceEntities(data.map((de) => ({ ...de, o_m: de.m, o_cn: de.cn, o_mi: de.mi, o_ma: de.ma })));
|
||||
};
|
||||
|
||||
onSuccess((event) => {
|
||||
setOriginalSettings(event.data);
|
||||
});
|
||||
|
||||
const { send: restartCommand } = useRequest(EMSESP.restart(), {
|
||||
immediate: false
|
||||
});
|
||||
|
||||
const entities_theme = useTheme({
|
||||
Table: `
|
||||
--data-table-library_grid-template-columns: 150px repeat(1, minmax(80px, 1fr)) 45px minmax(45px, auto) minmax(120px, auto);
|
||||
@@ -131,7 +160,7 @@ const SettingsCustomization: FC = () => {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (deviceEntities) {
|
||||
if (deviceEntities.length) {
|
||||
setNumChanges(
|
||||
deviceEntities
|
||||
.filter((de) => hasEntityChanged(de))
|
||||
@@ -148,29 +177,11 @@ const SettingsCustomization: FC = () => {
|
||||
}
|
||||
}, [deviceEntities]);
|
||||
|
||||
const fetchDevices = useCallback(async () => {
|
||||
try {
|
||||
setDevices((await EMSESP.readDevices()).data);
|
||||
} catch (error) {
|
||||
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||
}
|
||||
}, [LL]);
|
||||
|
||||
useEffect(() => {
|
||||
void fetchDevices();
|
||||
}, [fetchDevices]);
|
||||
|
||||
const setOriginalSettings = (data: DeviceEntity[]) => {
|
||||
setDeviceEntities(data.map((de) => ({ ...de, o_m: de.m, o_cn: de.cn, o_mi: de.mi, o_ma: de.ma })));
|
||||
};
|
||||
|
||||
const fetchDeviceEntities = async (unique_id: number) => {
|
||||
try {
|
||||
const new_deviceEntities = (await EMSESP.readDeviceEntities({ id: unique_id })).data;
|
||||
setOriginalSettings(new_deviceEntities);
|
||||
} catch (error) {
|
||||
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||
}
|
||||
const restart = async () => {
|
||||
await restartCommand().catch((error) => {
|
||||
toast.error(error.message);
|
||||
});
|
||||
setRestarting(true);
|
||||
};
|
||||
|
||||
function formatValue(value: any) {
|
||||
@@ -225,7 +236,7 @@ const SettingsCustomization: FC = () => {
|
||||
};
|
||||
|
||||
const maskDisabled = (set: boolean) => {
|
||||
setDeviceEntities(
|
||||
updateDeviceEntities(
|
||||
deviceEntities?.map(function (de) {
|
||||
if ((de.m & selectedFilters || !selectedFilters) && de.id.toLowerCase().includes(search.toLowerCase())) {
|
||||
return {
|
||||
@@ -246,31 +257,22 @@ const SettingsCustomization: FC = () => {
|
||||
const selected_device = parseInt(event.target.value, 10);
|
||||
setSelectedDevice(selected_device);
|
||||
setNumChanges(0);
|
||||
void fetchDeviceEntities(devices?.devices[selected_device].i);
|
||||
void readDeviceEntities(devices?.devices[selected_device].i);
|
||||
setRestartNeeded(false);
|
||||
}
|
||||
};
|
||||
|
||||
const resetCustomization = async () => {
|
||||
try {
|
||||
await EMSESP.resetCustomizations();
|
||||
await resetCustomizations();
|
||||
toast.info(LL.CUSTOMIZATIONS_RESTART());
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||
toast.error(error.message);
|
||||
} finally {
|
||||
setConfirmReset(false);
|
||||
}
|
||||
};
|
||||
|
||||
const restart = async () => {
|
||||
try {
|
||||
await EMSESP.restart();
|
||||
setRestarting(true);
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||
}
|
||||
};
|
||||
|
||||
const onDialogClose = () => {
|
||||
setDialogOpen(false);
|
||||
};
|
||||
@@ -300,7 +302,7 @@ const SettingsCustomization: FC = () => {
|
||||
const saveCustomization = async () => {
|
||||
if (devices && deviceEntities && selectedDevice !== -1) {
|
||||
const masked_entities = deviceEntities
|
||||
.filter((de) => hasEntityChanged(de))
|
||||
.filter((de: DeviceEntity) => hasEntityChanged(de))
|
||||
.map(
|
||||
(new_de) =>
|
||||
new_de.m.toString(16).padStart(2, '0') +
|
||||
@@ -318,72 +320,57 @@ const SettingsCustomization: FC = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await EMSESP.writeCustomEntities({
|
||||
id: devices?.devices[selectedDevice].i,
|
||||
entity_ids: masked_entities
|
||||
});
|
||||
if (response.status === 200) {
|
||||
toast.success(LL.CUSTOMIZATIONS_SAVED());
|
||||
} else if (response.status === 201) {
|
||||
setRestartNeeded(true);
|
||||
} else {
|
||||
toast.error(LL.PROBLEM_UPDATING());
|
||||
await writeCustomEntities({ id: devices?.devices[selectedDevice].i, entity_ids: masked_entities }).catch(
|
||||
(error) => {
|
||||
if (error.message === 'Reboot required') {
|
||||
setRestartNeeded(true);
|
||||
} else {
|
||||
toast.error(error.message);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||
}
|
||||
);
|
||||
// does this work or use onSuccess hook?
|
||||
setOriginalSettings(deviceEntities);
|
||||
}
|
||||
};
|
||||
|
||||
const renderDeviceList = () => {
|
||||
if (!devices) {
|
||||
return <FormLoader errorMessage={errorMessage} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box mb={2} color="warning.main">
|
||||
<Typography variant="body2">{LL.CUSTOMIZATIONS_HELP_1()}.</Typography>
|
||||
<Typography variant="body2" mt={1}>
|
||||
<OptionIcon type="favorite" isSet={true} />={LL.CUSTOMIZATIONS_HELP_2()}
|
||||
<OptionIcon type="readonly" isSet={true} />={LL.CUSTOMIZATIONS_HELP_3()}
|
||||
<OptionIcon type="api_mqtt_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_4()}
|
||||
<OptionIcon type="web_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_5()}
|
||||
<OptionIcon type="deleted" isSet={true} />={LL.CUSTOMIZATIONS_HELP_6()}
|
||||
</Typography>
|
||||
</Box>
|
||||
<TextField
|
||||
name="device"
|
||||
label={LL.EMS_DEVICE()}
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
value={selectedDevice}
|
||||
disabled={numChanges !== 0}
|
||||
onChange={changeSelectedDevice}
|
||||
margin="normal"
|
||||
select
|
||||
>
|
||||
<MenuItem disabled key={0} value={-1}>
|
||||
{LL.SELECT_DEVICE()}...
|
||||
const renderDeviceList = () => (
|
||||
<>
|
||||
<Box mb={2} color="warning.main">
|
||||
<Typography variant="body2">{LL.CUSTOMIZATIONS_HELP_1()}.</Typography>
|
||||
<Typography variant="body2" mt={1}>
|
||||
<OptionIcon type="favorite" isSet={true} />={LL.CUSTOMIZATIONS_HELP_2()}
|
||||
<OptionIcon type="readonly" isSet={true} />={LL.CUSTOMIZATIONS_HELP_3()}
|
||||
<OptionIcon type="api_mqtt_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_4()}
|
||||
<OptionIcon type="web_exclude" isSet={true} />={LL.CUSTOMIZATIONS_HELP_5()}
|
||||
<OptionIcon type="deleted" isSet={true} />={LL.CUSTOMIZATIONS_HELP_6()}
|
||||
</Typography>
|
||||
</Box>
|
||||
<TextField
|
||||
name="device"
|
||||
label={LL.EMS_DEVICE()}
|
||||
variant="outlined"
|
||||
fullWidth
|
||||
value={selectedDevice}
|
||||
disabled={numChanges !== 0}
|
||||
onChange={changeSelectedDevice}
|
||||
margin="normal"
|
||||
select
|
||||
>
|
||||
<MenuItem disabled key={0} value={-1}>
|
||||
{LL.SELECT_DEVICE()}...
|
||||
</MenuItem>
|
||||
{devices.devices.map((device: DeviceShort, index) => (
|
||||
<MenuItem key={index} value={index}>
|
||||
{device.s}
|
||||
</MenuItem>
|
||||
{devices.devices.map((device: DeviceShort, index) => (
|
||||
<MenuItem key={index} value={index}>
|
||||
{device.s}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</>
|
||||
);
|
||||
};
|
||||
))}
|
||||
</TextField>
|
||||
</>
|
||||
);
|
||||
|
||||
const renderDeviceData = () => {
|
||||
if (!deviceEntities) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (devices?.devices.length === 0 || deviceEntities[0].id === '') {
|
||||
if (deviceEntities.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -521,7 +508,7 @@ const SettingsCustomization: FC = () => {
|
||||
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
|
||||
{LL.DEVICE_ENTITIES()}
|
||||
</Typography>
|
||||
{renderDeviceList()}
|
||||
{devices && renderDeviceList()}
|
||||
{renderDeviceData()}
|
||||
{restartNeeded && (
|
||||
<MessageBox my={2} level="warning" message={LL.RESTART_TEXT()}>
|
||||
@@ -539,7 +526,7 @@ const SettingsCustomization: FC = () => {
|
||||
startIcon={<CancelIcon />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
onClick={() => devices && fetchDeviceEntities(devices.devices[selectedDevice].i)}
|
||||
onClick={() => devices && readDeviceEntities(devices.devices[selectedDevice].i)}
|
||||
>
|
||||
{LL.CANCEL()}
|
||||
</Button>
|
||||
|
||||
@@ -1,86 +1,63 @@
|
||||
import type {
|
||||
BoardProfile,
|
||||
BoardProfileName,
|
||||
APIcall,
|
||||
Settings,
|
||||
Status,
|
||||
CoreData,
|
||||
Devices,
|
||||
DeviceData,
|
||||
DeviceEntity,
|
||||
UniqueID,
|
||||
CustomEntities,
|
||||
WriteTemperatureSensor,
|
||||
WriteAnalogSensor,
|
||||
SensorData,
|
||||
Schedule,
|
||||
Entities
|
||||
Entities,
|
||||
DeviceData
|
||||
} from './types';
|
||||
import type { AxiosPromise } from 'axios';
|
||||
import { AXIOS, AXIOS_API, AXIOS_BIN, alovaInstance } from 'api/endpoints';
|
||||
import { AXIOS, AXIOS_API, alovaInstance } from 'api/endpoints';
|
||||
|
||||
// DashboardDevices
|
||||
export const readCoreData = () => alovaInstance.Get<CoreData>(`/coreData`);
|
||||
|
||||
export const readDeviceData = (id: number) =>
|
||||
alovaInstance.Get<DeviceData>('/deviceData', {
|
||||
params: { id },
|
||||
responseType: 'arraybuffer' // uses msgpack
|
||||
});
|
||||
|
||||
export const writeDeviceValue = (data: any) => alovaInstance.Post('/writeDeviceValue', data);
|
||||
|
||||
// SettingsApplication
|
||||
export const readSettings = () => alovaInstance.Get<Settings>('/settings');
|
||||
export const writeSettings = (data: any) => alovaInstance.Post('/settings', data);
|
||||
export const getBoardProfile = (boardProfile: string) =>
|
||||
alovaInstance.Get('/boardProfile', {
|
||||
params: { boardProfile }
|
||||
});
|
||||
export const restart = () => alovaInstance.Post('/restart');
|
||||
|
||||
//
|
||||
// TODO change below to use alova
|
||||
//
|
||||
// SettingsCustomization
|
||||
export const readDeviceEntities = (id: number) =>
|
||||
alovaInstance.Get<DeviceEntity[]>('/deviceEntities', {
|
||||
params: { id },
|
||||
responseType: 'arraybuffer',
|
||||
transformData(rawData: any) {
|
||||
return rawData.map((de: DeviceEntity) => ({ ...de, o_m: de.m, o_cn: de.cn, o_mi: de.mi, o_ma: de.ma }));
|
||||
}
|
||||
});
|
||||
export const readDevices = () => alovaInstance.Get<Devices>('/devices');
|
||||
export const resetCustomizations = () => alovaInstance.Post('/resetCustomizations');
|
||||
export const writeCustomEntities = (data: any) => alovaInstance.Post('/customEntities', data);
|
||||
|
||||
export function restart(): AxiosPromise<void> {
|
||||
return AXIOS.post('/restart');
|
||||
}
|
||||
// DashboardSensors
|
||||
export const readSensorData = () => alovaInstance.Get<SensorData>('/sensorData');
|
||||
export const writeTemperatureSensor = (ts: WriteTemperatureSensor) => alovaInstance.Post('/writeTemperatureSensor', ts);
|
||||
export const writeAnalogSensor = (as: WriteAnalogSensor) => alovaInstance.Post('/writeAnalogSensor', as);
|
||||
|
||||
// TODO change to GET
|
||||
export function getBoardProfile(boardProfile: BoardProfileName): AxiosPromise<BoardProfile> {
|
||||
return AXIOS.post('/boardProfile', boardProfile);
|
||||
}
|
||||
// TODO change to GET
|
||||
export function readDeviceEntities(unique_id: UniqueID): AxiosPromise<DeviceEntity[]> {
|
||||
return AXIOS_BIN.post('/deviceEntities', unique_id);
|
||||
}
|
||||
// TODO think about naming, get... and not get etc...
|
||||
|
||||
export function readStatus(): AxiosPromise<Status> {
|
||||
return AXIOS.get('/status');
|
||||
}
|
||||
// DashboardStatus
|
||||
export const readStatus = () => alovaInstance.Get<Status>('/status');
|
||||
export const scanDevices = () => alovaInstance.Post('/scanDevices');
|
||||
|
||||
export function readDevices(): AxiosPromise<Devices> {
|
||||
return AXIOS.get('/devices');
|
||||
}
|
||||
|
||||
export function scanDevices(): AxiosPromise<void> {
|
||||
return AXIOS.post('/scanDevices'); // call command
|
||||
}
|
||||
|
||||
export function readSensorData(): AxiosPromise<SensorData> {
|
||||
return AXIOS.get('/sensorData');
|
||||
}
|
||||
|
||||
export function writeCustomEntities(customEntities: CustomEntities): AxiosPromise<void> {
|
||||
return AXIOS.post('/customEntities', customEntities);
|
||||
}
|
||||
|
||||
export function writeTemperatureSensor(ts: WriteTemperatureSensor): AxiosPromise<void> {
|
||||
return AXIOS.post('/writeTemperatureSensor', ts);
|
||||
}
|
||||
|
||||
export function writeAnalogSensor(as: WriteAnalogSensor): AxiosPromise<void> {
|
||||
return AXIOS.post('/writeAnalogSensor', as);
|
||||
}
|
||||
|
||||
export function resetCustomizations(): AxiosPromise<void> {
|
||||
return AXIOS.post('/resetCustomizations'); // command
|
||||
}
|
||||
// ALOVA goes here....
|
||||
|
||||
export function API(apiCall: APIcall): AxiosPromise<void> {
|
||||
return AXIOS_API.post('/', apiCall); // command
|
||||
|
||||
@@ -131,8 +131,6 @@ export interface DeviceValue {
|
||||
m?: number; // min, optional
|
||||
x?: number; // max, optional
|
||||
}
|
||||
|
||||
// TODO can be refacvtored to DeviceValue[]?
|
||||
export interface DeviceData {
|
||||
data: DeviceValue[];
|
||||
}
|
||||
@@ -152,16 +150,6 @@ export interface DeviceEntity {
|
||||
o_ma?: number; // original max value
|
||||
}
|
||||
|
||||
export interface CustomEntities {
|
||||
id: number;
|
||||
entity_ids: string[];
|
||||
}
|
||||
|
||||
// TODO can be removed?
|
||||
export interface UniqueID {
|
||||
id: number;
|
||||
}
|
||||
|
||||
export enum DeviceValueUOM {
|
||||
NONE = 0,
|
||||
DEGREES,
|
||||
@@ -258,10 +246,6 @@ export const BOARD_PROFILES: BoardProfiles = {
|
||||
S3MINI: 'Liligo S3'
|
||||
};
|
||||
|
||||
export interface BoardProfileName {
|
||||
board_profile: string;
|
||||
}
|
||||
|
||||
export interface BoardProfile {
|
||||
board_profile: string;
|
||||
led_gpio: number;
|
||||
|
||||
@@ -23,14 +23,13 @@ export const updateValue =
|
||||
};
|
||||
|
||||
export const updateValueDirty =
|
||||
<S>(origData: any, dirtyFlags: any, setDirtyFlags: any, updateEntity: any) =>
|
||||
// <S>(origData: any, dirtyFlags: any, setDirtyFlags: any, updateEntity: UpdateEntity<S>) =>
|
||||
(origData: any, dirtyFlags: any, setDirtyFlags: any, updateDataValue: any) =>
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const updated_value = extractEventValue(event);
|
||||
const name = event.target.name;
|
||||
|
||||
// TODO not sure how this is even working!!
|
||||
updateEntity((prevState) => ({
|
||||
updateDataValue((prevState) => ({
|
||||
...prevState,
|
||||
[name]: updated_value
|
||||
}));
|
||||
@@ -38,9 +37,9 @@ export const updateValueDirty =
|
||||
const arr: string[] = dirtyFlags;
|
||||
|
||||
// TODO remove comments
|
||||
// console.log('updating ' + name + ' to ' + updated_value); // TODO remove
|
||||
// console.log('dirtyFlags:', dirtyFlags); // TODO remove
|
||||
// console.log('binding.ts origData:', origData); // TODO remove
|
||||
// console.log('updating ' + name + ' to ' + updated_value);
|
||||
// console.log('dirtyFlags:', dirtyFlags);
|
||||
// console.log('binding.ts origData:', origData);
|
||||
|
||||
if (origData[name] !== updated_value) {
|
||||
if (!arr.includes(name)) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// TODO can be removed!
|
||||
// TODO extractErrorMessage function can be removed!
|
||||
export const extractErrorMessage = (error: any, defaultMessage: string) => {
|
||||
if (error.request) {
|
||||
return defaultMessage + ' (' + error.request.status + ': ' + error.request.statusText + ')';
|
||||
|
||||
@@ -4,6 +4,6 @@ export * from './route';
|
||||
export * from './submit';
|
||||
export * from './time';
|
||||
export * from './useRest';
|
||||
// TODO remove
|
||||
// TODO remove useRest2
|
||||
export * from './useRest2';
|
||||
export * from './props';
|
||||
|
||||
@@ -52,8 +52,8 @@ export const useRest = <D>({ read, update }: RestRequestOptions<D>) => {
|
||||
const response = await update(toSave);
|
||||
setOrigData(response.data);
|
||||
setData(response.data);
|
||||
if (response.status === 202) {
|
||||
setRestartNeeded(true);
|
||||
if (response.status === 205) {
|
||||
setRestartNeeded(true); // reboot required
|
||||
} else {
|
||||
toast.success(LL.UPDATED_OF(LL.SETTINGS()));
|
||||
}
|
||||
|
||||
@@ -7,14 +7,15 @@ import type { AlovaXHRRequestConfig, AlovaXHRResponse, AlovaXHRResponseHeaders }
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
export interface RestRequestOptions<D> {
|
||||
export interface RestRequestOptions2<D> {
|
||||
read: () => Method<any, any, any, any, any, AlovaXHRResponse<any>, AlovaXHRResponseHeaders>;
|
||||
update: (
|
||||
value: D
|
||||
) => Method<any, unknown, unknown, unknown, AlovaXHRRequestConfig, AlovaXHRResponse<any>, AlovaXHRResponseHeaders>;
|
||||
}
|
||||
|
||||
export const useRest2 = <D>({ read, update }: RestRequestOptions<D>) => {
|
||||
// TODO rename back to useRest
|
||||
export const useRest2 = <D>({ read, update }: RestRequestOptions2<D>) => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
const [errorMessage, setErrorMessage] = useState<string>();
|
||||
@@ -32,12 +33,8 @@ export const useRest2 = <D>({ read, update }: RestRequestOptions<D>) => {
|
||||
onSuccess: onWriteSuccess
|
||||
} = useRequest((newData: D) => update(newData), { immediate: false });
|
||||
|
||||
const setData = (new_data: D) => {
|
||||
console.log('SET DATA'); // TODO remove console
|
||||
console.log('new_data:', new_data); // TODO remove console
|
||||
updateData({
|
||||
data: new_data
|
||||
});
|
||||
const updateDataValue = (new_data: D) => {
|
||||
updateData({ data: new_data });
|
||||
};
|
||||
|
||||
onWriteSuccess(() => {
|
||||
@@ -46,7 +43,7 @@ export const useRest2 = <D>({ read, update }: RestRequestOptions<D>) => {
|
||||
});
|
||||
|
||||
onReadComplete((event) => {
|
||||
setOrigData(event.data); // make a copy
|
||||
setOrigData(event.data);
|
||||
});
|
||||
|
||||
const loadData = async () => {
|
||||
@@ -62,7 +59,6 @@ export const useRest2 = <D>({ read, update }: RestRequestOptions<D>) => {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
console.log('SAVE DATA'); // TODO remove console
|
||||
setRestartNeeded(false);
|
||||
setErrorMessage(undefined);
|
||||
await writeData(data).catch((error) => {
|
||||
@@ -79,7 +75,7 @@ export const useRest2 = <D>({ read, update }: RestRequestOptions<D>) => {
|
||||
loadData,
|
||||
saveData,
|
||||
saving,
|
||||
setData,
|
||||
updateDataValue,
|
||||
data,
|
||||
origData,
|
||||
dirtyFlags,
|
||||
|
||||
@@ -767,14 +767,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mui/material@npm:^5.13.4":
|
||||
version: 5.13.4
|
||||
resolution: "@mui/material@npm:5.13.4"
|
||||
"@mui/material@npm:^5.13.5":
|
||||
version: 5.13.5
|
||||
resolution: "@mui/material@npm:5.13.5"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.21.0
|
||||
"@mui/base": 5.0.0-beta.4
|
||||
"@mui/core-downloads-tracker": ^5.13.4
|
||||
"@mui/system": ^5.13.2
|
||||
"@mui/system": ^5.13.5
|
||||
"@mui/types": ^7.2.4
|
||||
"@mui/utils": ^5.13.1
|
||||
"@types/react-transition-group": ^4.4.6
|
||||
@@ -796,7 +796,7 @@ __metadata:
|
||||
optional: true
|
||||
"@types/react":
|
||||
optional: true
|
||||
checksum: 1f0b26c74e06fb6849af7398b8bc1d211d0af146822c998a9c55c31552ffcf426834eac56dc909c15bae8a3b957df91f32d9c1b6cb1300e063d184bfb530512f
|
||||
checksum: 325a99809efa041aa615b144bfde634ad7def22102b6267769e140aee0cdeaa3f611b79d4e3dc85a832b1f120da19b3e57933fb17487c7d5f67d7c2bbe7f3254
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -838,9 +838,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mui/system@npm:^5.13.2":
|
||||
version: 5.13.2
|
||||
resolution: "@mui/system@npm:5.13.2"
|
||||
"@mui/system@npm:^5.13.5":
|
||||
version: 5.13.5
|
||||
resolution: "@mui/system@npm:5.13.5"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.21.0
|
||||
"@mui/private-theming": ^5.13.1
|
||||
@@ -862,7 +862,7 @@ __metadata:
|
||||
optional: true
|
||||
"@types/react":
|
||||
optional: true
|
||||
checksum: 34ebb580e5dd83123cc397c3fd54c3430f66ab715eb1538cf2510821d88249814294f79ea046081b61249643383fd9c23552d9791322855fa2099bf8f1c4e51b
|
||||
checksum: 0bef4c575d9c54e7d93ad14009aecf4a0f18440398a14a6523f3fcea665913ceb344dc496d02b56a3ef53e4dac828f8e7ca5a55fb60448a76363622159d18379
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1288,10 +1288,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:^20.3.0":
|
||||
version: 20.3.0
|
||||
resolution: "@types/node@npm:20.3.0"
|
||||
checksum: f717d92c29c4877db394b604771b3734216f013312f93252f72c2018aabe8083be905fbcf0644c859938c8183b6e0245faaeaab94c9e78268b87a449bc6ef4aa
|
||||
"@types/node@npm:^20.3.1":
|
||||
version: 20.3.1
|
||||
resolution: "@types/node@npm:20.3.1"
|
||||
checksum: 7e8a6f5d6fc1ad3778f038f5f8df570741459984280fd2e9539af32620d93438c955fd1b90d00f9cc438cd132ec04d7669ada9e32502336e78713a3ad9b51d10
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1309,12 +1309,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react-dom@npm:^18.2.4":
|
||||
version: 18.2.4
|
||||
resolution: "@types/react-dom@npm:18.2.4"
|
||||
"@types/react-dom@npm:^18.2.5":
|
||||
version: 18.2.5
|
||||
resolution: "@types/react-dom@npm:18.2.5"
|
||||
dependencies:
|
||||
"@types/react": "*"
|
||||
checksum: dfeaabb4268d39bdd5addc6c0b7099d5c57a364e70f1087b7c3ee189374312dc65201abfd3d87fee0de11d27c225678ce39c22d14b3035cde5792678704c27b5
|
||||
checksum: 7f438f695c91735ff16e6465573a4378fabad6709d99dd08bee4932967ca7e4ccc26dc248f4b88569529885bbca9b1aca0075bee7b833bfa932a558c49d2a066
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1368,14 +1368,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react@npm:^18.2.11":
|
||||
version: 18.2.11
|
||||
resolution: "@types/react@npm:18.2.11"
|
||||
"@types/react@npm:^18.2.12":
|
||||
version: 18.2.12
|
||||
resolution: "@types/react@npm:18.2.12"
|
||||
dependencies:
|
||||
"@types/prop-types": "*"
|
||||
"@types/scheduler": "*"
|
||||
csstype: ^3.0.2
|
||||
checksum: 9360d7be13195050eb16598796056123ee9d30470e7073a914300fed9282585d0dd0638bb5ff65843e308c3ac213d25b3388e8186f3134490c758f18f11f3bd8
|
||||
checksum: dbaefc7732f77cd0c2bdf6e704ab4ee0f611540777c0b9506d972f165144b6fd6883a29dad61f6965c974c040264852aa8def1e3866b5775b3965a4e67bf92f9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1393,14 +1393,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/eslint-plugin@npm:^5.59.9":
|
||||
version: 5.59.9
|
||||
resolution: "@typescript-eslint/eslint-plugin@npm:5.59.9"
|
||||
"@typescript-eslint/eslint-plugin@npm:^5.59.11":
|
||||
version: 5.59.11
|
||||
resolution: "@typescript-eslint/eslint-plugin@npm:5.59.11"
|
||||
dependencies:
|
||||
"@eslint-community/regexpp": ^4.4.0
|
||||
"@typescript-eslint/scope-manager": 5.59.9
|
||||
"@typescript-eslint/type-utils": 5.59.9
|
||||
"@typescript-eslint/utils": 5.59.9
|
||||
"@typescript-eslint/scope-manager": 5.59.11
|
||||
"@typescript-eslint/type-utils": 5.59.11
|
||||
"@typescript-eslint/utils": 5.59.11
|
||||
debug: ^4.3.4
|
||||
grapheme-splitter: ^1.0.4
|
||||
ignore: ^5.2.0
|
||||
@@ -1413,43 +1413,43 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 4bb9981bcc009c044ffd6b64288309480df2b6c9cdf6b345987e4b565d0973d1d98b7209f6b46b92880735d788f564e17553641087aa59f67990c84526622a27
|
||||
checksum: 77f29b8bde5d11a5f222b21e5a3546e86f79a07efd8352b3ebcde67fd2c568ba7c6946fa992dbb9d7d80b6f2455017266fdede1ed134bd181b03f98d81fe71c3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/parser@npm:^5.59.9":
|
||||
version: 5.59.9
|
||||
resolution: "@typescript-eslint/parser@npm:5.59.9"
|
||||
"@typescript-eslint/parser@npm:^5.59.11":
|
||||
version: 5.59.11
|
||||
resolution: "@typescript-eslint/parser@npm:5.59.11"
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager": 5.59.9
|
||||
"@typescript-eslint/types": 5.59.9
|
||||
"@typescript-eslint/typescript-estree": 5.59.9
|
||||
"@typescript-eslint/scope-manager": 5.59.11
|
||||
"@typescript-eslint/types": 5.59.11
|
||||
"@typescript-eslint/typescript-estree": 5.59.11
|
||||
debug: ^4.3.4
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: af0e041e8a541734ff237ec0eac47e355c2f78dd2b0db4eb4ab0c10ba1b6d5d70f84ddc16f856bc72c4cacd53ef04b5f4948baffb5c8cb2d9a0ffd83a8fbc547
|
||||
checksum: 3deea3a9b694ea97e315881ba37d0a90d7f37f0acbb5990270f44c79db9fc3d5675df856f8d1fb7d92c8d38dc63226a42402d57633513981ee526c06e6e8f3c3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/scope-manager@npm:5.59.9":
|
||||
version: 5.59.9
|
||||
resolution: "@typescript-eslint/scope-manager@npm:5.59.9"
|
||||
"@typescript-eslint/scope-manager@npm:5.59.11":
|
||||
version: 5.59.11
|
||||
resolution: "@typescript-eslint/scope-manager@npm:5.59.11"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": 5.59.9
|
||||
"@typescript-eslint/visitor-keys": 5.59.9
|
||||
checksum: 41622fd270e5b8574347ed5dd020bbb9752d85e6f40df180e944c1110d9bd2227a949067feb23dd4117dd2be0623c05a47bc363abe605c96deb295753f6dd080
|
||||
"@typescript-eslint/types": 5.59.11
|
||||
"@typescript-eslint/visitor-keys": 5.59.11
|
||||
checksum: e0173e9beb44408ba3e9a1eb173dd83f5c0281af09f936d03f635b7fac41abe1f829a88d0cba134f250dfa4ce527d8cfa32c96e7ada5de876a7aa8bcc933db3b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/type-utils@npm:5.59.9":
|
||||
version: 5.59.9
|
||||
resolution: "@typescript-eslint/type-utils@npm:5.59.9"
|
||||
"@typescript-eslint/type-utils@npm:5.59.11":
|
||||
version: 5.59.11
|
||||
resolution: "@typescript-eslint/type-utils@npm:5.59.11"
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree": 5.59.9
|
||||
"@typescript-eslint/utils": 5.59.9
|
||||
"@typescript-eslint/typescript-estree": 5.59.11
|
||||
"@typescript-eslint/utils": 5.59.11
|
||||
debug: ^4.3.4
|
||||
tsutils: ^3.21.0
|
||||
peerDependencies:
|
||||
@@ -1457,23 +1457,23 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: c3a9773d2b81350923025933623e1572538f79bf119b40bed17389eda11632f6d364a49b385aa6d915d85f7c3d45376085cc55263d865dbc2b753598bba6473b
|
||||
checksum: 9675cf17970bbf01814d8c8a94aa076fb7c5f5ab8c405800f972a68a72748db07070a526aa2c94d30b2e5ba43bdbef3929a588182bffc3387288b24223574f52
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/types@npm:5.59.9":
|
||||
version: 5.59.9
|
||||
resolution: "@typescript-eslint/types@npm:5.59.9"
|
||||
checksum: 951046891bcc9fa27d72a5489b496291e44cedcff204d3ce6c10c8916fc5e255332738efd4d7555200a55b49ff4ba1204e186960d216d51fea89fe92a982180e
|
||||
"@typescript-eslint/types@npm:5.59.11":
|
||||
version: 5.59.11
|
||||
resolution: "@typescript-eslint/types@npm:5.59.11"
|
||||
checksum: 8d007c6c66323582d526429d059c477dcb522b904938a6aaf29804027e6f427533fabe9eb3c987491df74d4288dab238c8c948886f03244a1d908f2985631368
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/typescript-estree@npm:5.59.9":
|
||||
version: 5.59.9
|
||||
resolution: "@typescript-eslint/typescript-estree@npm:5.59.9"
|
||||
"@typescript-eslint/typescript-estree@npm:5.59.11":
|
||||
version: 5.59.11
|
||||
resolution: "@typescript-eslint/typescript-estree@npm:5.59.11"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": 5.59.9
|
||||
"@typescript-eslint/visitor-keys": 5.59.9
|
||||
"@typescript-eslint/types": 5.59.11
|
||||
"@typescript-eslint/visitor-keys": 5.59.11
|
||||
debug: ^4.3.4
|
||||
globby: ^11.1.0
|
||||
is-glob: ^4.0.3
|
||||
@@ -1482,35 +1482,35 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
typescript:
|
||||
optional: true
|
||||
checksum: 2f3d8df6d454fbc52d305abfe8447bff8e8d63294ce47e4679c920f647643f5d15a1f693caf74f4fabece12d5ba27ebdb156d507b16fbd2751fc01ba6c4df3c8
|
||||
checksum: 4306317ad65668a05d9ec7b280eab94dd7e0d15394db633864bad5d9633fbb9dc516e6cd9f8a0fc2f7a4fc0d53658e5dac61cbee3e070b0b7ac99bdbb0bb45ef
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/utils@npm:5.59.9":
|
||||
version: 5.59.9
|
||||
resolution: "@typescript-eslint/utils@npm:5.59.9"
|
||||
"@typescript-eslint/utils@npm:5.59.11":
|
||||
version: 5.59.11
|
||||
resolution: "@typescript-eslint/utils@npm:5.59.11"
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils": ^4.2.0
|
||||
"@types/json-schema": ^7.0.9
|
||||
"@types/semver": ^7.3.12
|
||||
"@typescript-eslint/scope-manager": 5.59.9
|
||||
"@typescript-eslint/types": 5.59.9
|
||||
"@typescript-eslint/typescript-estree": 5.59.9
|
||||
"@typescript-eslint/scope-manager": 5.59.11
|
||||
"@typescript-eslint/types": 5.59.11
|
||||
"@typescript-eslint/typescript-estree": 5.59.11
|
||||
eslint-scope: ^5.1.1
|
||||
semver: ^7.3.7
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
checksum: b8a04a83c121faa3e36abb2b6113f2e0ec5cf86884d0cb8619bfc50f7442341ee17e4495d69f8abeb6edad9e0347de8382ea1708a5fd6da1e4c80b7b8215c6ab
|
||||
checksum: c1927950d97afcf3cfc4c3901bc1932caa32bfc533f950f7dab420c478097d3d8daf030c27489e0d49ecdc1f87c52c782833cc505b245ab2a3094c707b0d776e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@typescript-eslint/visitor-keys@npm:5.59.9":
|
||||
version: 5.59.9
|
||||
resolution: "@typescript-eslint/visitor-keys@npm:5.59.9"
|
||||
"@typescript-eslint/visitor-keys@npm:5.59.11":
|
||||
version: 5.59.11
|
||||
resolution: "@typescript-eslint/visitor-keys@npm:5.59.11"
|
||||
dependencies:
|
||||
"@typescript-eslint/types": 5.59.9
|
||||
"@typescript-eslint/types": 5.59.11
|
||||
eslint-visitor-keys: ^3.3.0
|
||||
checksum: 882fd03830cbe0eca8f9a547aecc6519ddbec10e55f5f3de66e605a3f3d42a6237abd3c09b34d9cc3343c8e11386e999876aec384efe523e1478cb22752d326d
|
||||
checksum: 1644c5bcb87e26717bc587f1ed1d87c96e89dae7d5bdafc1eed35a7c49e3157f8c37936b3897571892f412b7dd8439ba9cf8903128bb847831696f6517bb2d7a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1533,17 +1533,17 @@ __metadata:
|
||||
"@emotion/react": ^11.11.1
|
||||
"@emotion/styled": ^11.11.0
|
||||
"@mui/icons-material": ^5.11.16
|
||||
"@mui/material": ^5.13.4
|
||||
"@mui/material": ^5.13.5
|
||||
"@table-library/react-table-library": 4.1.4
|
||||
"@types/lodash-es": ^4.17.7
|
||||
"@types/node": ^20.3.0
|
||||
"@types/react": ^18.2.11
|
||||
"@types/react-dom": ^18.2.4
|
||||
"@types/node": ^20.3.1
|
||||
"@types/react": ^18.2.12
|
||||
"@types/react-dom": ^18.2.5
|
||||
"@types/react-router-dom": ^5.3.3
|
||||
"@typescript-eslint/eslint-plugin": ^5.59.9
|
||||
"@typescript-eslint/parser": ^5.59.9
|
||||
"@typescript-eslint/eslint-plugin": ^5.59.11
|
||||
"@typescript-eslint/parser": ^5.59.11
|
||||
"@vitejs/plugin-react-swc": ^3.3.2
|
||||
alova: ^2.6.0
|
||||
alova: ^2.6.1
|
||||
async-validator: ^4.2.5
|
||||
axios: ^1.4.0
|
||||
eslint: ^8.42.0
|
||||
@@ -1571,7 +1571,7 @@ __metadata:
|
||||
react-toastify: ^9.1.3
|
||||
rollup-plugin-visualizer: ^5.9.2
|
||||
sockette: ^2.0.6
|
||||
terser: ^5.17.7
|
||||
terser: ^5.18.0
|
||||
typesafe-i18n: ^5.24.3
|
||||
typescript: ^5.1.3
|
||||
vite: ^4.3.9
|
||||
@@ -1647,10 +1647,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"alova@npm:^2.6.0":
|
||||
version: 2.6.0
|
||||
resolution: "alova@npm:2.6.0"
|
||||
checksum: a99dd001f094cccbc6166c5cc56ed8d417434f9edf05aa5176992a3a3735600a3b626b41b50dd867b8a86b3edf44cfbd576568349af937626a7023f9b839226b
|
||||
"alova@npm:^2.6.1":
|
||||
version: 2.6.1
|
||||
resolution: "alova@npm:2.6.1"
|
||||
checksum: 55504d1cfab8efff3679d5734e7f78891b3b9c581c6669e6a6df6cc854d05c5d275f6645e1347c633f4418a41d418105857c7d96e0f69dc24abeccc06f0a8c18
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -5536,9 +5536,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"terser@npm:^5.17.7":
|
||||
version: 5.17.7
|
||||
resolution: "terser@npm:5.17.7"
|
||||
"terser@npm:^5.18.0":
|
||||
version: 5.18.0
|
||||
resolution: "terser@npm:5.18.0"
|
||||
dependencies:
|
||||
"@jridgewell/source-map": ^0.3.3
|
||||
acorn: ^8.8.2
|
||||
@@ -5546,7 +5546,7 @@ __metadata:
|
||||
source-map-support: ~0.5.20
|
||||
bin:
|
||||
terser: bin/terser
|
||||
checksum: 864154a1750daf516012e5add4f0749bfc71e8f4f918973ec3d504db6a148be976adf46ae490e795173eeff59ec579d7d464bb6354c1bb71f8e14ff398409aed
|
||||
checksum: 37f562843537c57e119b2ed6d96c2113344d9182a83613abd8e933534b89a3c622ee7ee47d4023249c1d34a2dd1b41a0e56fd6d2e2251f48b79fb7671f269b01
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -115,7 +115,7 @@ class HttpPostEndpoint {
|
||||
response->setLength();
|
||||
|
||||
if (outcome == StateUpdateResult::CHANGED_RESTART) {
|
||||
response->setCode(202); // added by proddy
|
||||
response->setCode(205); // added by proddy, reboot required
|
||||
}
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ void WiFiScanner::scanNetworks(AsyncWebServerRequest * request) {
|
||||
WiFi.scanDelete();
|
||||
WiFi.scanNetworks(true);
|
||||
}
|
||||
request->send(202);
|
||||
request->send(202); // special code to indicate scan in progress
|
||||
}
|
||||
|
||||
void WiFiScanner::listNetworks(AsyncWebServerRequest * request) {
|
||||
@@ -36,7 +36,7 @@ void WiFiScanner::listNetworks(AsyncWebServerRequest * request) {
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
} else if (numNetworks == -1) {
|
||||
request->send(202);
|
||||
request->send(202); // special code to indicate scan in progress
|
||||
} else {
|
||||
scanNetworks(request);
|
||||
}
|
||||
|
||||
@@ -480,7 +480,7 @@ const emsesp_sensordata = {
|
||||
{ id: '28-233D-9497-0C03', n: 'Dallas 1', t: 25.7, o: 1.2, u: 1 },
|
||||
{ id: '28-243D-7437-1E3A', n: 'Dallas 2 outside', t: 26.1, o: 0, u: 1 },
|
||||
{ id: '28-243E-7437-1E3B', n: 'Zolder', t: 27.1, o: 0, u: 16 },
|
||||
{ id: '28-183D-1892-0C33', n: 'Roof', o: 2, u: 1 }
|
||||
{ id: '28-183D-1892-0C33', n: 'Roof', o: 2, u: 1 } // no temperature
|
||||
],
|
||||
// as: [],
|
||||
as: [
|
||||
@@ -512,95 +512,15 @@ const status = {
|
||||
};
|
||||
|
||||
// Dashboard data
|
||||
// 7 - Nefit Trendline boiler
|
||||
// 1 - RC35 thermo
|
||||
// 2 - RC20 thermo
|
||||
// 3 - Buderus GB125 boiler
|
||||
// 4 - RC100 themo
|
||||
// 5 - Mixer MM10
|
||||
// 6 - Solar SM10
|
||||
// 7 - Nefit Trendline boiler
|
||||
// 99 - Custom
|
||||
|
||||
const emsesp_devicedata_7 = {
|
||||
data: [
|
||||
{ v: '', u: 0, id: '08reset', c: 'reset', l: ['-', 'maintenance', 'error'] },
|
||||
{ v: 'off', u: 0, id: '08heating active' },
|
||||
{ v: 'off', u: 0, id: '04tapwater active' },
|
||||
{ v: 5, u: 1, id: '04selected flow temperature', c: 'selflowtemp' },
|
||||
{ v: 0, u: 3, id: '0Eburner selected max power', c: 'selburnpow' },
|
||||
{ v: 0, u: 3, id: '00heating pump modulation' },
|
||||
{ v: 53.4, u: 1, id: '00current flow temperature' },
|
||||
{ v: 52.7, u: 1, id: '00return temperature' },
|
||||
{ v: 1.3, u: 10, id: '00system pressure' },
|
||||
{ v: 54.9, u: 1, id: '00actual boiler temperature' },
|
||||
{ v: 'off', u: 0, id: '00gas' },
|
||||
{ v: 'off', u: 0, id: '00gas stage 2' },
|
||||
{ v: 0, u: 9, id: '00flame current' },
|
||||
{ v: 'off', u: 0, id: '00heating pump' },
|
||||
{ v: 'off', u: 0, id: '00fan' },
|
||||
{ v: 'off', u: 0, id: '00ignition' },
|
||||
{ v: 'off', u: 0, id: '00oil preheating' },
|
||||
{ v: 'on', u: 0, id: '00heating activated', c: 'heatingactivated', l: ['off', 'on'] },
|
||||
{ v: 80, u: 1, id: '00heating temperature', c: 'heatingtemp' },
|
||||
{ v: 70, u: 3, id: '00burner pump max power', c: 'pumpmodmax' },
|
||||
{ v: 30, u: 3, id: '00burner pump min power', c: 'pumpmodmin' },
|
||||
{ v: 1, u: 8, id: '00pump delay', c: 'pumpdelay' },
|
||||
{ v: 10, u: 8, id: '00burner min period', c: 'burnminperiod' },
|
||||
{ v: 0, u: 3, id: '00burner min power', c: 'burnminpower' },
|
||||
{ v: 50, u: 3, id: '00burner max power', c: 'burnmaxpower' },
|
||||
{ v: -6, u: 2, id: '00hysteresis on temperature', c: 'boilhyston' },
|
||||
{ v: 6, u: 2, id: '00hysteresis off temperature', c: 'boilhystoff' },
|
||||
{ v: 0, u: 1, id: '00set flow temperature' },
|
||||
{ v: 0, u: 3, id: '00burner set power' },
|
||||
{ v: 0, u: 3, id: '00burner current power' },
|
||||
{ v: 326323, u: 0, id: '00burner starts' },
|
||||
{ v: 553437, u: 8, id: '00total burner operating time' },
|
||||
{ v: 451286, u: 8, id: '00total heat operating time' },
|
||||
{ v: 4672173, u: 8, id: '00total UBA operating time' },
|
||||
{ v: '1C(210) 06.06.2020 12:07 (0 min)', u: 0, id: '00last error code' },
|
||||
{ v: '0H', u: 0, id: '00service code' },
|
||||
{ v: 203, u: 0, id: '00service code number' },
|
||||
{ v: 'H00', u: 0, id: '00maintenance message' },
|
||||
{ v: 'manual', u: 0, id: '00maintenance scheduled', c: 'maintenance', l: ['off', 'time', 'date', 'manual'] },
|
||||
{ v: 6000, u: 7, id: '00time to next maintenance', c: 'maintenancetime' },
|
||||
{ v: '01.01.2012', u: 0, id: '00next maintenance date', c: 'maintenancedate', o: 'Format: < dd.mm.yyyy >' },
|
||||
{ v: 'on', u: 0, id: '00dhw turn on/off', c: 'wwtapactivated', l: ['off', 'on'] },
|
||||
{ v: 62, u: 1, id: '00dhw set temperature' },
|
||||
{ v: 60, u: 1, id: '00dhw selected temperature', c: 'wwseltemp' },
|
||||
{ v: 'flow', u: 0, id: '00dhw type' },
|
||||
{ v: 'hot', u: 0, id: '00dhw comfort', c: 'wwcomfort', l: ['hot', 'eco', 'intelligent'] },
|
||||
{ v: 40, u: 2, id: '00dhw flow temperature offset', c: 'wwflowtempoffset' },
|
||||
{ v: 100, u: 3, id: '00dhw max power', c: 'wwmaxpower' },
|
||||
{ v: 'off', u: 0, id: '00dhw circulation pump available', c: 'wwcircpump', l: ['off', 'on'] },
|
||||
{ v: '3-way valve', u: 0, id: '00dhw charging type' },
|
||||
{ v: -5, u: 2, id: '00dhw hysteresis on temperature', c: 'wwhyston' },
|
||||
{ v: 0, u: 2, id: '00dhw hysteresis off temperature', c: 'wwhystoff' },
|
||||
{ v: 70, u: 1, id: '00dhw disinfection temperature', c: 'wwdisinfectiontemp' },
|
||||
{
|
||||
v: 'off',
|
||||
u: 0,
|
||||
id: '00dhw circulation pump mode',
|
||||
c: 'wwcircmode',
|
||||
l: ['off', '1x3min', '2x3min', '3x3min', '4x3min', '5x3min', '6x3min', 'continuous']
|
||||
},
|
||||
{ v: 'off', u: 0, id: '00dhw circulation active', c: 'wwcirc', l: ['off', 'on'] },
|
||||
{ v: 47.3, u: 1, id: '00dhw current intern temperature' },
|
||||
{ v: 0, u: 4, id: '00dhw current tap water flow' },
|
||||
{ v: 47.3, u: 1, id: '00dhw storage intern temperature' },
|
||||
{ v: 'on', u: 0, id: '00dhw activated', c: 'wwactivated', l: ['off', 'on'] },
|
||||
{ v: 'off', u: 0, id: '00dhw one time charging', c: 'wwonetime', l: ['off', 'on'] },
|
||||
{ v: 'off', u: 0, id: '00dhw disinfecting', c: 'wwdisinfecting', l: ['off', 'on'] },
|
||||
{ v: 'off', u: 0, id: '00dhw charging' },
|
||||
{ v: 'off', u: 0, id: '00dhw recharging' },
|
||||
{ v: 'on', u: 0, id: '00dhw temperature ok' },
|
||||
{ v: 'off', u: 0, id: '00dhw active' },
|
||||
{ v: 'on', u: 0, id: '00dhw 3way valve active' },
|
||||
{ v: 0, u: 3, id: '00dhw set pump power' },
|
||||
{ v: 288768, u: 0, id: '00dhw starts' },
|
||||
{ v: 102151, u: 8, id: '00dhw active time' }
|
||||
]
|
||||
};
|
||||
|
||||
const emsesp_devicedata_1 = {
|
||||
data: [
|
||||
{
|
||||
@@ -1768,6 +1688,86 @@ const emsesp_devicedata_6 = {
|
||||
]
|
||||
};
|
||||
|
||||
const emsesp_devicedata_7 = {
|
||||
data: [
|
||||
{ v: '', u: 0, id: '08reset', c: 'reset', l: ['-', 'maintenance', 'error'] },
|
||||
{ v: 'off', u: 0, id: '08heating active' },
|
||||
{ v: 'off', u: 0, id: '04tapwater active' },
|
||||
{ v: 5, u: 1, id: '04selected flow temperature', c: 'selflowtemp' },
|
||||
{ v: 0, u: 3, id: '0Eburner selected max power', c: 'selburnpow' },
|
||||
{ v: 0, u: 3, id: '00heating pump modulation' },
|
||||
{ v: 53.4, u: 1, id: '00current flow temperature' },
|
||||
{ v: 52.7, u: 1, id: '00return temperature' },
|
||||
{ v: 1.3, u: 10, id: '00system pressure' },
|
||||
{ v: 54.9, u: 1, id: '00actual boiler temperature' },
|
||||
{ v: 'off', u: 0, id: '00gas' },
|
||||
{ v: 'off', u: 0, id: '00gas stage 2' },
|
||||
{ v: 0, u: 9, id: '00flame current' },
|
||||
{ v: 'off', u: 0, id: '00heating pump' },
|
||||
{ v: 'off', u: 0, id: '00fan' },
|
||||
{ v: 'off', u: 0, id: '00ignition' },
|
||||
{ v: 'off', u: 0, id: '00oil preheating' },
|
||||
{ v: 'on', u: 0, id: '00heating activated', c: 'heatingactivated', l: ['off', 'on'] },
|
||||
{ v: 80, u: 1, id: '00heating temperature', c: 'heatingtemp' },
|
||||
{ v: 70, u: 3, id: '00burner pump max power', c: 'pumpmodmax' },
|
||||
{ v: 30, u: 3, id: '00burner pump min power', c: 'pumpmodmin' },
|
||||
{ v: 1, u: 8, id: '00pump delay', c: 'pumpdelay' },
|
||||
{ v: 10, u: 8, id: '00burner min period', c: 'burnminperiod' },
|
||||
{ v: 0, u: 3, id: '00burner min power', c: 'burnminpower' },
|
||||
{ v: 50, u: 3, id: '00burner max power', c: 'burnmaxpower' },
|
||||
{ v: -6, u: 2, id: '00hysteresis on temperature', c: 'boilhyston' },
|
||||
{ v: 6, u: 2, id: '00hysteresis off temperature', c: 'boilhystoff' },
|
||||
{ v: 0, u: 1, id: '00set flow temperature' },
|
||||
{ v: 0, u: 3, id: '00burner set power' },
|
||||
{ v: 0, u: 3, id: '00burner current power' },
|
||||
{ v: 326323, u: 0, id: '00burner starts' },
|
||||
{ v: 553437, u: 8, id: '00total burner operating time' },
|
||||
{ v: 451286, u: 8, id: '00total heat operating time' },
|
||||
{ v: 4672173, u: 8, id: '00total UBA operating time' },
|
||||
{ v: '1C(210) 06.06.2020 12:07 (0 min)', u: 0, id: '00last error code' },
|
||||
{ v: '0H', u: 0, id: '00service code' },
|
||||
{ v: 203, u: 0, id: '00service code number' },
|
||||
{ v: 'H00', u: 0, id: '00maintenance message' },
|
||||
{ v: 'manual', u: 0, id: '00maintenance scheduled', c: 'maintenance', l: ['off', 'time', 'date', 'manual'] },
|
||||
{ v: 6000, u: 7, id: '00time to next maintenance', c: 'maintenancetime' },
|
||||
{ v: '01.01.2012', u: 0, id: '00next maintenance date', c: 'maintenancedate', o: 'Format: < dd.mm.yyyy >' },
|
||||
{ v: 'on', u: 0, id: '00dhw turn on/off', c: 'wwtapactivated', l: ['off', 'on'] },
|
||||
{ v: 62, u: 1, id: '00dhw set temperature' },
|
||||
{ v: 60, u: 1, id: '00dhw selected temperature', c: 'wwseltemp' },
|
||||
{ v: 'flow', u: 0, id: '00dhw type' },
|
||||
{ v: 'hot', u: 0, id: '00dhw comfort', c: 'wwcomfort', l: ['hot', 'eco', 'intelligent'] },
|
||||
{ v: 40, u: 2, id: '00dhw flow temperature offset', c: 'wwflowtempoffset' },
|
||||
{ v: 100, u: 3, id: '00dhw max power', c: 'wwmaxpower' },
|
||||
{ v: 'off', u: 0, id: '00dhw circulation pump available', c: 'wwcircpump', l: ['off', 'on'] },
|
||||
{ v: '3-way valve', u: 0, id: '00dhw charging type' },
|
||||
{ v: -5, u: 2, id: '00dhw hysteresis on temperature', c: 'wwhyston' },
|
||||
{ v: 0, u: 2, id: '00dhw hysteresis off temperature', c: 'wwhystoff' },
|
||||
{ v: 70, u: 1, id: '00dhw disinfection temperature', c: 'wwdisinfectiontemp' },
|
||||
{
|
||||
v: 'off',
|
||||
u: 0,
|
||||
id: '00dhw circulation pump mode',
|
||||
c: 'wwcircmode',
|
||||
l: ['off', '1x3min', '2x3min', '3x3min', '4x3min', '5x3min', '6x3min', 'continuous']
|
||||
},
|
||||
{ v: 'off', u: 0, id: '00dhw circulation active', c: 'wwcirc', l: ['off', 'on'] },
|
||||
{ v: 47.3, u: 1, id: '00dhw current intern temperature' },
|
||||
{ v: 0, u: 4, id: '00dhw current tap water flow' },
|
||||
{ v: 47.3, u: 1, id: '00dhw storage intern temperature' },
|
||||
{ v: 'on', u: 0, id: '00dhw activated', c: 'wwactivated', l: ['off', 'on'] },
|
||||
{ v: 'off', u: 0, id: '00dhw one time charging', c: 'wwonetime', l: ['off', 'on'] },
|
||||
{ v: 'off', u: 0, id: '00dhw disinfecting', c: 'wwdisinfecting', l: ['off', 'on'] },
|
||||
{ v: 'off', u: 0, id: '00dhw charging' },
|
||||
{ v: 'off', u: 0, id: '00dhw recharging' },
|
||||
{ v: 'on', u: 0, id: '00dhw temperature ok' },
|
||||
{ v: 'off', u: 0, id: '00dhw active' },
|
||||
{ v: 'on', u: 0, id: '00dhw 3way valve active' },
|
||||
{ v: 0, u: 3, id: '00dhw set pump power' },
|
||||
{ v: 288768, u: 0, id: '00dhw starts' },
|
||||
{ v: 102151, u: 8, id: '00dhw active time' }
|
||||
]
|
||||
};
|
||||
|
||||
const emsesp_devicedata_99 = {
|
||||
data: [
|
||||
{
|
||||
@@ -2026,7 +2026,7 @@ rest_server.get(LIST_NETWORKS_ENDPOINT, (req, res) => {
|
||||
res.json(list_networks);
|
||||
});
|
||||
rest_server.get(SCAN_NETWORKS_ENDPOINT, (req, res) => {
|
||||
res.sendStatus(202);
|
||||
res.sendStatus(202); // reboot required
|
||||
});
|
||||
|
||||
// AP
|
||||
@@ -2100,6 +2100,7 @@ rest_server.get(VERIFY_AUTHORIZATION_ENDPOINT, (req, res) => {
|
||||
res.json(verify_authentication);
|
||||
});
|
||||
rest_server.post(RESTART_ENDPOINT, (req, res) => {
|
||||
console.log('command: restart');
|
||||
res.sendStatus(200);
|
||||
});
|
||||
rest_server.post(FACTORY_RESET_ENDPOINT, (req, res) => {
|
||||
@@ -2128,7 +2129,7 @@ rest_server.get(EMSESP_SETTINGS_ENDPOINT, (req, res) => {
|
||||
rest_server.post(EMSESP_SETTINGS_ENDPOINT, (req, res) => {
|
||||
settings = req.body;
|
||||
console.log('Write settings: ' + JSON.stringify(settings));
|
||||
// res.status(202).json(settings); // restart needed
|
||||
// res.status(205).json(settings); // restart needed
|
||||
res.status(200).json(settings); // no restart needed
|
||||
});
|
||||
rest_server.get(EMSESP_CORE_DATA_ENDPOINT, (req, res) => {
|
||||
@@ -2184,8 +2185,9 @@ rest_server.get(EMSESP_DEVICEDATA_ENDPOINT, (req, res) => {
|
||||
res.end(null, 'binary');
|
||||
});
|
||||
|
||||
rest_server.post(EMSESP_DEVICEENTITIES_ENDPOINT, (req, res) => {
|
||||
const id = req.body.id;
|
||||
rest_server.get(EMSESP_DEVICEENTITIES_ENDPOINT, (req, res) => {
|
||||
const id = Number(req.query.id);
|
||||
console.log('deviceentities for device ' + id + ' received');
|
||||
let data = null;
|
||||
|
||||
if (id === 1) {
|
||||
@@ -2233,6 +2235,7 @@ function updateMask(entity, de, dd) {
|
||||
}
|
||||
|
||||
// find in dd, either looking for fullname or custom name
|
||||
// console.log('looking for ' + fullname + ' in ' + dd.data);
|
||||
dd_objIndex = dd.data.findIndex((obj) => obj.id.slice(2) === fullname);
|
||||
if (dd_objIndex !== -1) {
|
||||
let changed = new Boolean(false);
|
||||
@@ -2432,10 +2435,12 @@ rest_server.post(EMSESP_WRITE_ANALOG_ENDPOINT, (req, res) => {
|
||||
res.sendStatus(200);
|
||||
});
|
||||
|
||||
rest_server.post(EMSESP_BOARDPROFILE_ENDPOINT, (req, res) => {
|
||||
const board_profile = req.body.board_profile;
|
||||
rest_server.get(EMSESP_BOARDPROFILE_ENDPOINT, (req, res) => {
|
||||
const board_profile = req.query.boardProfile;
|
||||
|
||||
// default values
|
||||
const data = {
|
||||
board_profile: board_profile,
|
||||
led_gpio: settings.led_gpio,
|
||||
dallas_gpio: settings.dallas_gpio,
|
||||
rx_gpio: settings.rx_gpio,
|
||||
@@ -2559,9 +2564,10 @@ rest_server.post(EMSESP_BOARDPROFILE_ENDPOINT, (req, res) => {
|
||||
data.eth_clock_mode = 0;
|
||||
}
|
||||
|
||||
console.log('boardProfile POST. Sending back, profile: ' + board_profile + ', ' + 'data: ' + JSON.stringify(data));
|
||||
console.log('boardProfile GET. Sending back, profile: ' + board_profile + ', ' + 'data: ' + JSON.stringify(data));
|
||||
|
||||
res.send(data);
|
||||
// res.sendStatus(400); // send back an error, for testing
|
||||
res.json(data);
|
||||
});
|
||||
|
||||
// EMS-ESP API specific
|
||||
|
||||
@@ -33,10 +33,12 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
|
||||
, _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE)
|
||||
, _masked_entities_handler(CUSTOM_ENTITIES_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebCustomizationService::custom_entities, this, _1, _2),
|
||||
AuthenticationPredicates::IS_AUTHENTICATED))
|
||||
, _device_entities_handler(DEVICE_ENTITIES_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebCustomizationService::device_entities, this, _1, _2),
|
||||
AuthenticationPredicates::IS_AUTHENTICATED)) {
|
||||
server->on(DEVICE_ENTITIES_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebCustomizationService::device_entities, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
|
||||
server->on(DEVICES_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebCustomizationService::devices, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
@@ -49,10 +51,6 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
|
||||
_masked_entities_handler.setMaxContentLength(2048);
|
||||
_masked_entities_handler.setMaxJsonBufferSize(2048);
|
||||
server->addHandler(&_masked_entities_handler);
|
||||
|
||||
_device_entities_handler.setMethod(HTTP_POST);
|
||||
_device_entities_handler.setMaxContentLength(256);
|
||||
server->addHandler(&_device_entities_handler);
|
||||
}
|
||||
|
||||
// this creates the customization file, saving it to the FS
|
||||
@@ -165,7 +163,7 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization &
|
||||
void WebCustomizationService::reset_customization(AsyncWebServerRequest * request) {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
if (LittleFS.remove(EMSESP_CUSTOMIZATION_FILE)) {
|
||||
AsyncWebServerResponse * response = request->beginResponse(200); // OK
|
||||
AsyncWebServerResponse * response = request->beginResponse(205); // restart needed
|
||||
request->send(response);
|
||||
EMSESP::system_.restart_requested(true);
|
||||
return;
|
||||
@@ -199,17 +197,21 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) {
|
||||
}
|
||||
|
||||
// send back list of device entities
|
||||
void WebCustomizationService::device_entities(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
if (json.is<JsonObject>()) {
|
||||
void WebCustomizationService::device_entities(AsyncWebServerRequest * request) {
|
||||
uint8_t id;
|
||||
if (request->hasParam(F_(id))) {
|
||||
id = Helpers::atoint(request->getParam(F_(id))->value().c_str()); // get id from url
|
||||
|
||||
size_t buffer = EMSESP_JSON_SIZE_XXXXLARGE;
|
||||
auto * response = new MsgpackAsyncJsonResponse(true, buffer);
|
||||
|
||||
while (!response->getSize()) {
|
||||
delete response;
|
||||
buffer -= 1024;
|
||||
response = new MsgpackAsyncJsonResponse(true, buffer);
|
||||
}
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
if (emsdevice->unique_id() == json["id"]) {
|
||||
if (emsdevice->unique_id() == id) {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
JsonArray output = response->getRoot();
|
||||
emsdevice->generate_values_web_customization(output);
|
||||
@@ -319,7 +321,7 @@ void WebCustomizationService::custom_entities(AsyncWebServerRequest * request, J
|
||||
}
|
||||
}
|
||||
|
||||
AsyncWebServerResponse * response = request->beginResponse(need_reboot ? 201 : 200); // OK
|
||||
AsyncWebServerResponse * response = request->beginResponse(need_reboot ? 205 : 200); // reboot or just OK
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
// GET
|
||||
#define DEVICES_SERVICE_PATH "/rest/devices"
|
||||
#define EMSESP_CUSTOMIZATION_SERVICE_PATH "/rest/customization"
|
||||
#define DEVICE_ENTITIES_PATH "/rest/deviceEntities"
|
||||
|
||||
// POST
|
||||
#define DEVICE_ENTITIES_PATH "/rest/deviceEntities"
|
||||
#define CUSTOM_ENTITIES_PATH "/rest/customEntities"
|
||||
#define RESET_CUSTOMIZATION_SERVICE_PATH "/rest/resetCustomizations"
|
||||
|
||||
@@ -91,13 +91,13 @@ class WebCustomizationService : public StatefulService<WebCustomization> {
|
||||
|
||||
// GET
|
||||
void devices(AsyncWebServerRequest * request);
|
||||
void device_entities(AsyncWebServerRequest * request);
|
||||
|
||||
// POST
|
||||
void custom_entities(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void device_entities(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void reset_customization(AsyncWebServerRequest * request);
|
||||
void reset_customization(AsyncWebServerRequest * request); // command
|
||||
|
||||
AsyncCallbackJsonWebHandler _masked_entities_handler, _device_entities_handler;
|
||||
AsyncCallbackJsonWebHandler _masked_entities_handler;
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -327,6 +327,7 @@ void WebDataService::write_temperature_sensor(AsyncWebServerRequest * request, J
|
||||
if (EMSESP::system_.fahrenheit()) {
|
||||
offset10 = offset / 0.18;
|
||||
}
|
||||
|
||||
ok = EMSESP::temperaturesensor_.update(id, name, offset10);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,12 +26,11 @@ using namespace std::placeholders; // for `_1` etc
|
||||
|
||||
WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||
: _httpEndpoint(WebSettings::read, WebSettings::update, this, server, EMSESP_SETTINGS_SERVICE_PATH, securityManager)
|
||||
, _fsPersistence(WebSettings::read, WebSettings::update, this, fs, EMSESP_SETTINGS_FILE)
|
||||
, _boardProfileHandler(EMSESP_BOARD_PROFILE_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebSettingsService::board_profile, this, _1, _2), AuthenticationPredicates::IS_ADMIN)) {
|
||||
_boardProfileHandler.setMethod(HTTP_POST);
|
||||
_boardProfileHandler.setMaxContentLength(256);
|
||||
server->addHandler(&_boardProfileHandler);
|
||||
, _fsPersistence(WebSettings::read, WebSettings::update, this, fs, EMSESP_SETTINGS_FILE) {
|
||||
// GET
|
||||
server->on(EMSESP_BOARD_PROFILE_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebSettingsService::board_profile, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
|
||||
addUpdateHandler([&](const String & originId) { onUpdate(); }, false);
|
||||
}
|
||||
@@ -342,29 +341,29 @@ void WebSettingsService::save() {
|
||||
}
|
||||
|
||||
// build the json profile to send back
|
||||
void WebSettingsService::board_profile(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
if (json.is<JsonObject>()) {
|
||||
void WebSettingsService::board_profile(AsyncWebServerRequest * request) {
|
||||
if (request->hasParam("boardProfile")) {
|
||||
std::string board_profile = request->getParam("boardProfile")->value().c_str();
|
||||
|
||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_MEDIUM);
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
if (json.containsKey("board_profile")) {
|
||||
String board_profile = json["board_profile"];
|
||||
std::vector<int8_t> data; // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
|
||||
(void)System::load_board_profile(data, board_profile.c_str());
|
||||
root["led_gpio"] = data[0];
|
||||
root["dallas_gpio"] = data[1];
|
||||
root["rx_gpio"] = data[2];
|
||||
root["tx_gpio"] = data[3];
|
||||
root["pbutton_gpio"] = data[4];
|
||||
root["phy_type"] = data[5];
|
||||
root["eth_power"] = data[6];
|
||||
root["eth_phy_addr"] = data[7];
|
||||
root["eth_clock_mode"] = data[8];
|
||||
std::vector<int8_t> data; // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
|
||||
(void)System::load_board_profile(data, board_profile);
|
||||
root["board_profile"] = board_profile;
|
||||
root["led_gpio"] = data[0];
|
||||
root["dallas_gpio"] = data[1];
|
||||
root["rx_gpio"] = data[2];
|
||||
root["tx_gpio"] = data[3];
|
||||
root["pbutton_gpio"] = data[4];
|
||||
root["phy_type"] = data[5];
|
||||
root["eth_power"] = data[6];
|
||||
root["eth_phy_addr"] = data[7];
|
||||
root["eth_clock_mode"] = data[8];
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
AsyncWebServerResponse * response = request->beginResponse(200);
|
||||
|
||||
@@ -122,11 +122,10 @@ class WebSettingsService : public StatefulService<WebSettings> {
|
||||
void save();
|
||||
|
||||
private:
|
||||
HttpEndpoint<WebSettings> _httpEndpoint;
|
||||
FSPersistence<WebSettings> _fsPersistence;
|
||||
AsyncCallbackJsonWebHandler _boardProfileHandler;
|
||||
HttpEndpoint<WebSettings> _httpEndpoint;
|
||||
FSPersistence<WebSettings> _fsPersistence;
|
||||
|
||||
void board_profile(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void board_profile(AsyncWebServerRequest * request);
|
||||
|
||||
void onUpdate();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user