mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
alova - implementing UpdateState
This commit is contained in:
@@ -40,7 +40,7 @@
|
||||
"react-dom": "latest",
|
||||
"react-dropzone": "^14.2.3",
|
||||
"react-icons": "^4.9.0",
|
||||
"react-router-dom": "^6.12.1",
|
||||
"react-router-dom": "^6.13.0",
|
||||
"react-toastify": "^9.1.3",
|
||||
"sockette": "^2.0.6",
|
||||
"typesafe-i18n": "^5.24.3",
|
||||
|
||||
@@ -5,11 +5,10 @@ import type { APSettings, APStatus } from 'types';
|
||||
|
||||
export const readAPStatus = () => alovaInstance.Get<APStatus>('/apStatus');
|
||||
|
||||
// TODO change AXIOS to Alova
|
||||
// TODO change APSettings AXIOS to Alova
|
||||
export function readAPSettings(): AxiosPromise<APSettings> {
|
||||
return AXIOS.get('/apSettings');
|
||||
}
|
||||
|
||||
export function updateAPSettings(apSettings: APSettings): AxiosPromise<APSettings> {
|
||||
return AXIOS.post('/apSettings', apSettings);
|
||||
}
|
||||
|
||||
@@ -6,9 +6,6 @@ import { unpack } from '../api/unpack';
|
||||
|
||||
import type { AxiosPromise, CancelToken, AxiosProgressEvent } from 'axios';
|
||||
|
||||
export const WS_BASE_URL = '/ws/';
|
||||
export const ES_BASE_URL = '/es/';
|
||||
|
||||
export const REST_BASE_URL = '/rest/';
|
||||
export const API_BASE_URL = '/api/';
|
||||
|
||||
@@ -16,13 +13,14 @@ export const ACCESS_TOKEN = 'access_token';
|
||||
|
||||
const location = window.location;
|
||||
const webProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
export const WS_BASE_URL = '/ws/';
|
||||
export const ES_BASE_URL = '/es/';
|
||||
export const WEB_SOCKET_ROOT = webProtocol + '//' + location.host + WS_BASE_URL;
|
||||
export const EVENT_SOURCE_ROOT = location.protocol + '//' + location.host + ES_BASE_URL;
|
||||
|
||||
export const alovaInstance = createAlova({
|
||||
baseURL: '/rest/',
|
||||
statesHook: ReactHook,
|
||||
timeout: 50000,
|
||||
timeout: 5000,
|
||||
requestAdapter: xhrRequestAdapter(),
|
||||
beforeRequest(method) {
|
||||
if (localStorage.getItem(ACCESS_TOKEN)) {
|
||||
|
||||
@@ -28,7 +28,7 @@ export const apStatusHighlight = ({ status }: APStatus, theme: Theme) => {
|
||||
};
|
||||
|
||||
const APStatusForm: FC = () => {
|
||||
const { data: data, send: loadData, error } = useRequest(APApi.readAPStatus());
|
||||
const { data: data, send: loadData, error } = useRequest(APApi.readAPStatus);
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||
import { Typography, Button, Box } from '@mui/material';
|
||||
import { useRequest } from 'alova';
|
||||
import { toast } from 'react-toastify';
|
||||
import type { FileUploadConfig } from 'api/endpoints';
|
||||
import type { AxiosPromise } from 'axios';
|
||||
@@ -9,7 +10,6 @@ import { SingleUpload, useFileUpload } from 'components';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import * as EMSESP from 'project/api';
|
||||
import { extractErrorMessage } from 'utils';
|
||||
|
||||
interface UploadFileProps {
|
||||
uploadGeneralFile: (file: File, config?: FileUploadConfig) => AxiosPromise<void>;
|
||||
@@ -18,6 +18,19 @@ interface UploadFileProps {
|
||||
const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
||||
const [uploadFile, cancelUpload, uploading, uploadProgress, md5] = useFileUpload({ upload: uploadGeneralFile });
|
||||
|
||||
const { send: getSettings, onSuccess: onSuccessGetSettings } = useRequest(EMSESP.getSettings(), {
|
||||
immediate: false
|
||||
});
|
||||
const { send: getCustomizations, onSuccess: onSuccessgetCustomizations } = useRequest(EMSESP.getCustomizations(), {
|
||||
immediate: false
|
||||
});
|
||||
const { send: getEntities, onSuccess: onSuccessGetEntities } = useRequest(EMSESP.getEntities(), {
|
||||
immediate: false
|
||||
});
|
||||
const { send: getSchedule, onSuccess: onSuccessGetSchedule } = useRequest(EMSESP.getSchedule(), {
|
||||
immediate: false
|
||||
});
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
const saveFile = (json: any, endpoint: string) => {
|
||||
@@ -35,56 +48,41 @@ const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
||||
toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
||||
};
|
||||
|
||||
onSuccessGetSettings((event) => {
|
||||
saveFile(event.data, 'settings');
|
||||
});
|
||||
onSuccessgetCustomizations((event) => {
|
||||
saveFile(event.data, 'customizations');
|
||||
});
|
||||
onSuccessGetEntities((event) => {
|
||||
saveFile(event.data, 'entities');
|
||||
});
|
||||
onSuccessGetSchedule((event) => {
|
||||
saveFile(event.data, 'schedule');
|
||||
});
|
||||
|
||||
const downloadSettings = async () => {
|
||||
try {
|
||||
const response = await EMSESP.getSettings();
|
||||
if (response.status !== 200) {
|
||||
toast.error(LL.PROBLEM_LOADING());
|
||||
} else {
|
||||
saveFile(response.data, 'settings');
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||
}
|
||||
await getSettings().catch((error) => {
|
||||
toast.error(error.message);
|
||||
});
|
||||
};
|
||||
|
||||
const downloadCustomizations = async () => {
|
||||
try {
|
||||
const response = await EMSESP.getCustomizations();
|
||||
if (response.status !== 200) {
|
||||
toast.error(LL.PROBLEM_LOADING());
|
||||
} else {
|
||||
saveFile(response.data, 'customizations');
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||
}
|
||||
await getCustomizations().catch((error) => {
|
||||
toast.error(error.message);
|
||||
});
|
||||
};
|
||||
|
||||
const downloadEntities = async () => {
|
||||
try {
|
||||
const response = await EMSESP.getEntities();
|
||||
if (response.status !== 200) {
|
||||
toast.error(LL.PROBLEM_LOADING());
|
||||
} else {
|
||||
saveFile(response.data, 'entities');
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||
}
|
||||
await getEntities().catch((error) => {
|
||||
toast.error(error.message);
|
||||
});
|
||||
};
|
||||
|
||||
const downloadSchedule = async () => {
|
||||
try {
|
||||
const response = await EMSESP.getSchedule();
|
||||
if (response.status !== 200) {
|
||||
toast.error(LL.PROBLEM_LOADING());
|
||||
} else {
|
||||
saveFile(response.data, 'schedule');
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||
}
|
||||
await getSchedule().catch((error) => {
|
||||
toast.error(error.message);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -170,15 +170,6 @@ const DashboardStatus: FC = () => {
|
||||
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 = () => (
|
||||
|
||||
@@ -4,6 +4,7 @@ import DownloadIcon from '@mui/icons-material/GetApp';
|
||||
import GitHubIcon from '@mui/icons-material/GitHub';
|
||||
import MenuBookIcon from '@mui/icons-material/MenuBookTwoTone';
|
||||
import { Typography, Button, Box, List, ListItem, ListItemText, Link, ListItemAvatar } from '@mui/material';
|
||||
import { useRequest } from 'alova';
|
||||
import { toast } from 'react-toastify';
|
||||
import * as EMSESP from './api';
|
||||
import type { FC } from 'react';
|
||||
@@ -11,16 +12,19 @@ import type { FC } from 'react';
|
||||
import { SectionContent } from 'components';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { extractErrorMessage } from 'utils';
|
||||
|
||||
const HelpInformation: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
const saveFile = (json: any, endpoint: string) => {
|
||||
const { send: API, onSuccess: onSuccessAPI } = useRequest((data) => EMSESP.API(data), {
|
||||
immediate: false
|
||||
});
|
||||
|
||||
onSuccessAPI((event) => {
|
||||
const a = document.createElement('a');
|
||||
const filename = 'emsesp_' + endpoint + '.txt';
|
||||
const filename = 'emsesp_info.txt';
|
||||
a.href = URL.createObjectURL(
|
||||
new Blob([JSON.stringify(json, null, 2)], {
|
||||
new Blob([JSON.stringify(event.data, null, 2)], {
|
||||
type: 'text/plain'
|
||||
})
|
||||
);
|
||||
@@ -29,23 +33,12 @@ const HelpInformation: FC = () => {
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
||||
};
|
||||
});
|
||||
|
||||
const callAPI = async (endpoint: string) => {
|
||||
try {
|
||||
const response = await EMSESP.API({
|
||||
device: 'system',
|
||||
entity: endpoint,
|
||||
id: 0
|
||||
});
|
||||
if (response.status !== 200) {
|
||||
toast.error(LL.PROBLEM_LOADING());
|
||||
} else {
|
||||
saveFile(response.data, endpoint);
|
||||
}
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||
}
|
||||
const callAPI = async () => {
|
||||
await API({ device: 'system', entity: 'info', id: 0 }).catch((error) => {
|
||||
toast.error(error.message);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -96,7 +89,7 @@ const HelpInformation: FC = () => {
|
||||
size="small"
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
onClick={() => callAPI('info')}
|
||||
onClick={() => callAPI()}
|
||||
>
|
||||
{LL.SUPPORT_INFO()}
|
||||
</Button>
|
||||
|
||||
@@ -61,7 +61,7 @@ const SettingsCustomization: FC = () => {
|
||||
immediate: false
|
||||
});
|
||||
|
||||
const { data: devices } = useRequest(EMSESP.readDevices());
|
||||
const { data: devices } = useRequest(EMSESP.readDevices);
|
||||
|
||||
const { send: writeCustomEntities } = useRequest((data) => EMSESP.writeCustomEntities(data), { immediate: false });
|
||||
|
||||
@@ -236,8 +236,9 @@ const SettingsCustomization: FC = () => {
|
||||
};
|
||||
|
||||
const maskDisabled = (set: boolean) => {
|
||||
// TODO fix update!
|
||||
updateDeviceEntities(
|
||||
deviceEntities?.map(function (de) {
|
||||
deviceEntities.map(function (de) {
|
||||
if ((de.m & selectedFilters || !selectedFilters) && de.id.toLowerCase().includes(search.toLowerCase())) {
|
||||
return {
|
||||
...de,
|
||||
@@ -329,7 +330,6 @@ const SettingsCustomization: FC = () => {
|
||||
}
|
||||
}
|
||||
);
|
||||
// does this work or use onSuccess hook?
|
||||
setOriginalSettings(deviceEntities);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -124,7 +124,7 @@ const SettingsCustomizationDialog = ({ open, onClose, onSave, selectedItem }: Se
|
||||
{LL.CANCEL()}
|
||||
</Button>
|
||||
<Button startIcon={<DoneIcon />} variant="outlined" onClick={save} color="primary">
|
||||
{LL.UPDATE(0)}
|
||||
{LL.UPDATE()}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
@@ -6,6 +6,7 @@ import WarningIcon from '@mui/icons-material/Warning';
|
||||
import { Box, Typography, Divider, Stack, Button } 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 { updateState, useRequest } from 'alova';
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { unstable_useBlocker as useBlocker } from 'react-router-dom';
|
||||
import { toast } from 'react-toastify';
|
||||
@@ -19,23 +20,30 @@ import type { FC } from 'react';
|
||||
import { ButtonRow, FormLoader, SectionContent, BlockNavigation } from 'components';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { extractErrorMessage } from 'utils';
|
||||
|
||||
const SettingsScheduler: FC = () => {
|
||||
const { LL, locale } = useI18nContext();
|
||||
const [numChanges, setNumChanges] = useState<number>(0);
|
||||
const blocker = useBlocker(numChanges !== 0);
|
||||
const [schedule, setSchedule] = useState<ScheduleItem[]>([]);
|
||||
const [selectedScheduleItem, setSelectedScheduleItem] = useState<ScheduleItem>();
|
||||
const [dow, setDow] = useState<string[]>([]);
|
||||
const [errorMessage, setErrorMessage] = useState<string>();
|
||||
const [creating, setCreating] = useState<boolean>(false);
|
||||
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
||||
|
||||
const {
|
||||
data: schedule,
|
||||
send: fetchSchedule,
|
||||
error
|
||||
} = useRequest(EMSESP.readSchedule, {
|
||||
initialData: []
|
||||
});
|
||||
|
||||
const { send: writeSchedule } = useRequest((data) => EMSESP.writeSchedule(data), { immediate: false });
|
||||
|
||||
function hasScheduleChanged(si: ScheduleItem) {
|
||||
return (
|
||||
si.id !== si.o_id ||
|
||||
(si?.name || '') !== (si?.o_name || '') ||
|
||||
(si.name || '') !== (si.o_name || '') ||
|
||||
si.active !== si.o_active ||
|
||||
si.deleted !== si.o_deleted ||
|
||||
si.flags !== si.o_flags ||
|
||||
@@ -46,10 +54,13 @@ const SettingsScheduler: FC = () => {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (schedule) {
|
||||
setNumChanges(schedule ? schedule.filter((si) => hasScheduleChanged(si)).length : 0);
|
||||
}
|
||||
}, [schedule]);
|
||||
const formatter = new Intl.DateTimeFormat(locale, { weekday: 'short', timeZone: 'UTC' });
|
||||
const days = [1, 2, 3, 4, 5, 6, 7].map((day) => {
|
||||
const dd = day < 10 ? `0${day}` : day;
|
||||
return new Date(`2017-01-${dd}T00:00:00+00:00`);
|
||||
});
|
||||
setDow(days.map((date) => formatter.format(date)));
|
||||
}, [locale]);
|
||||
|
||||
const schedule_theme = useTheme({
|
||||
Table: `
|
||||
@@ -96,63 +107,30 @@ const SettingsScheduler: FC = () => {
|
||||
`
|
||||
});
|
||||
|
||||
const fetchSchedule = useCallback(async () => {
|
||||
try {
|
||||
const response = await EMSESP.readSchedule();
|
||||
setSchedule(
|
||||
response.data.schedule.map((si) => ({
|
||||
...si,
|
||||
o_id: si.id,
|
||||
o_active: si.active,
|
||||
o_deleted: si.deleted,
|
||||
o_flags: si.flags,
|
||||
o_time: si.time,
|
||||
o_cmd: si.cmd,
|
||||
o_value: si.value,
|
||||
o_name: si.name
|
||||
}))
|
||||
);
|
||||
} catch (error) {
|
||||
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||
}
|
||||
}, [LL]);
|
||||
|
||||
useEffect(() => {
|
||||
const formatter = new Intl.DateTimeFormat(locale, { weekday: 'short', timeZone: 'UTC' });
|
||||
const days = [1, 2, 3, 4, 5, 6, 7].map((day) => {
|
||||
const dd = day < 10 ? `0${day}` : day;
|
||||
return new Date(`2017-01-${dd}T00:00:00+00:00`);
|
||||
});
|
||||
setDow(days.map((date) => formatter.format(date)));
|
||||
void fetchSchedule();
|
||||
}, [locale, fetchSchedule]);
|
||||
|
||||
const saveSchedule = async () => {
|
||||
if (schedule) {
|
||||
try {
|
||||
const response = await EMSESP.writeSchedule({
|
||||
schedule: schedule
|
||||
.filter((si) => !si.deleted)
|
||||
.map((condensed_si) => ({
|
||||
id: condensed_si.id,
|
||||
active: condensed_si.active,
|
||||
flags: condensed_si.flags,
|
||||
time: condensed_si.time,
|
||||
cmd: condensed_si.cmd,
|
||||
value: condensed_si.value,
|
||||
name: condensed_si.name
|
||||
}))
|
||||
});
|
||||
if (response.status === 200) {
|
||||
toast.success(LL.SCHEDULE_UPDATED());
|
||||
} else {
|
||||
toast.error(LL.PROBLEM_UPDATING());
|
||||
}
|
||||
await writeSchedule(
|
||||
schedule
|
||||
.filter((si) => !si.deleted)
|
||||
.map((condensed_si) => ({
|
||||
id: condensed_si.id,
|
||||
active: condensed_si.active,
|
||||
flags: condensed_si.flags,
|
||||
time: condensed_si.time,
|
||||
cmd: condensed_si.cmd,
|
||||
value: condensed_si.value,
|
||||
name: condensed_si.name
|
||||
}))
|
||||
)
|
||||
.then(() => {
|
||||
toast.success(LL.SCHEDULE_UPDATED());
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.error(err.message);
|
||||
})
|
||||
.finally(async () => {
|
||||
await fetchSchedule();
|
||||
} catch (error) {
|
||||
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||
}
|
||||
}
|
||||
setNumChanges(0);
|
||||
});
|
||||
};
|
||||
|
||||
const editScheduleItem = useCallback((si: ScheduleItem) => {
|
||||
@@ -167,11 +145,14 @@ const SettingsScheduler: FC = () => {
|
||||
|
||||
const onDialogSave = (updatedItem: ScheduleItem) => {
|
||||
setDialogOpen(false);
|
||||
if (schedule && creating) {
|
||||
setSchedule([...schedule.filter((si) => creating || si.o_id !== updatedItem.o_id), updatedItem]);
|
||||
} else {
|
||||
setSchedule(schedule?.map((si) => (si.id === updatedItem.id ? { ...si, ...updatedItem } : si)));
|
||||
}
|
||||
|
||||
updateState('schedule', (data) => {
|
||||
const new_data = creating
|
||||
? [...data.filter((si) => creating || si.o_id !== updatedItem.o_id), updatedItem]
|
||||
: data.map((si) => (si.id === updatedItem.id ? { ...si, ...updatedItem } : si));
|
||||
setNumChanges(new_data.filter((si) => hasScheduleChanged(si)).length);
|
||||
return new_data;
|
||||
});
|
||||
};
|
||||
|
||||
const addScheduleItem = () => {
|
||||
@@ -191,7 +172,7 @@ const SettingsScheduler: FC = () => {
|
||||
|
||||
const renderSchedule = () => {
|
||||
if (!schedule) {
|
||||
return <FormLoader errorMessage={errorMessage} />;
|
||||
return <FormLoader onRetry={fetchSchedule} errorMessage={error?.message} />;
|
||||
}
|
||||
|
||||
const dayBox = (si: ScheduleItem, flag: number) => (
|
||||
|
||||
@@ -215,7 +215,7 @@ const SettingsSchedulerDialog = ({
|
||||
/>
|
||||
<TextField
|
||||
name="value"
|
||||
label={LL.VALUE(0)}
|
||||
label={LL.VALUE(1)}
|
||||
multiline
|
||||
margin="normal"
|
||||
fullWidth
|
||||
|
||||
@@ -8,89 +8,88 @@ import type {
|
||||
WriteTemperatureSensor,
|
||||
WriteAnalogSensor,
|
||||
SensorData,
|
||||
Schedule,
|
||||
Entities,
|
||||
DeviceData
|
||||
DeviceData,
|
||||
ScheduleItem
|
||||
} from './types';
|
||||
import type { AxiosPromise } from 'axios';
|
||||
import { AXIOS, AXIOS_API, alovaInstance } from 'api/endpoints';
|
||||
import { AXIOS, alovaInstance } from 'api/endpoints';
|
||||
|
||||
// DashboardDevices
|
||||
export const readCoreData = () => alovaInstance.Get<CoreData>(`/coreData`);
|
||||
export const readCoreData = () => alovaInstance.Get<CoreData>(`/rest/coreData`);
|
||||
export const readDeviceData = (id: number) =>
|
||||
alovaInstance.Get<DeviceData>('/deviceData', {
|
||||
alovaInstance.Get<DeviceData>('/rest/deviceData', {
|
||||
params: { id },
|
||||
responseType: 'arraybuffer' // uses msgpack
|
||||
});
|
||||
export const writeDeviceValue = (data: any) => alovaInstance.Post('/writeDeviceValue', data);
|
||||
export const writeDeviceValue = (data: any) => alovaInstance.Post('/rest/writeDeviceValue', data);
|
||||
|
||||
// SettingsApplication
|
||||
export const readSettings = () => alovaInstance.Get<Settings>('/settings');
|
||||
export const writeSettings = (data: any) => alovaInstance.Post('/settings', data);
|
||||
export const readSettings = () => alovaInstance.Get<Settings>('/rest/settings');
|
||||
export const writeSettings = (data: any) => alovaInstance.Post('/rest/settings', data);
|
||||
export const getBoardProfile = (boardProfile: string) =>
|
||||
alovaInstance.Get('/boardProfile', {
|
||||
alovaInstance.Get('/rest/boardProfile', {
|
||||
params: { boardProfile }
|
||||
});
|
||||
export const restart = () => alovaInstance.Post('/restart');
|
||||
export const restart = () => alovaInstance.Post('/rest/restart');
|
||||
|
||||
// SettingsCustomization
|
||||
export const readDeviceEntities = (id: number) =>
|
||||
alovaInstance.Get<DeviceEntity[]>('/deviceEntities', {
|
||||
alovaInstance.Get<DeviceEntity[]>('/rest/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 }));
|
||||
transformData(data: any) {
|
||||
return data.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 const readDevices = () => alovaInstance.Get<Devices>('/rest/devices');
|
||||
export const resetCustomizations = () => alovaInstance.Post('/rest/resetCustomizations');
|
||||
export const writeCustomEntities = (data: any) => alovaInstance.Post('/rest/customEntities', data);
|
||||
|
||||
// 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 think about naming, get... and not get etc...
|
||||
export const readSensorData = () => alovaInstance.Get<SensorData>('/rest/sensorData');
|
||||
export const writeTemperatureSensor = (ts: WriteTemperatureSensor) =>
|
||||
alovaInstance.Post('/rest/writeTemperatureSensor', ts);
|
||||
export const writeAnalogSensor = (as: WriteAnalogSensor) => alovaInstance.Post('/rest/writeAnalogSensor', as);
|
||||
|
||||
// DashboardStatus
|
||||
export const readStatus = () => alovaInstance.Get<Status>('/status');
|
||||
export const scanDevices = () => alovaInstance.Post('/scanDevices');
|
||||
export const readStatus = () => alovaInstance.Get<Status>('/rest/status');
|
||||
export const scanDevices = () => alovaInstance.Post('/rest/scanDevices');
|
||||
|
||||
// ALOVA goes here....
|
||||
// HelpInformation
|
||||
export const API = (apiCall: APIcall) => alovaInstance.Post('/api', apiCall);
|
||||
|
||||
export function API(apiCall: APIcall): AxiosPromise<void> {
|
||||
return AXIOS_API.post('/', apiCall); // command
|
||||
}
|
||||
// GeneralFileUpload
|
||||
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');
|
||||
|
||||
export function getSettings(): AxiosPromise<void> {
|
||||
return AXIOS.get('/getSettings');
|
||||
}
|
||||
|
||||
export function getCustomizations(): AxiosPromise<void> {
|
||||
return AXIOS.get('/getCustomizations');
|
||||
}
|
||||
|
||||
export function getSchedule(): AxiosPromise<Schedule> {
|
||||
return AXIOS.get('/getSchedule');
|
||||
}
|
||||
|
||||
export function readSchedule(): AxiosPromise<Schedule> {
|
||||
return AXIOS.get('/schedule');
|
||||
}
|
||||
|
||||
export function writeSchedule(schedule: Schedule): AxiosPromise<void> {
|
||||
return AXIOS.post('/schedule', schedule);
|
||||
}
|
||||
|
||||
export function getEntities(): AxiosPromise<Entities> {
|
||||
return AXIOS.get('/getEntities');
|
||||
}
|
||||
// SettingsScheduler
|
||||
export const readSchedule = () =>
|
||||
alovaInstance.Get<ScheduleItem[]>('/rest/schedule', {
|
||||
name: 'schedule',
|
||||
transformData(data: any) {
|
||||
return data.map((si: ScheduleItem) => ({
|
||||
...si,
|
||||
o_id: si.id,
|
||||
o_active: si.active,
|
||||
o_deleted: si.deleted,
|
||||
o_flags: si.flags,
|
||||
o_time: si.time,
|
||||
o_cmd: si.cmd,
|
||||
o_value: si.value,
|
||||
o_name: si.name
|
||||
}));
|
||||
}
|
||||
});
|
||||
export const writeSchedule = (data: any) => alovaInstance.Post('/rest/schedule', data);
|
||||
|
||||
// SettingsCustomization
|
||||
// TODO move last Entities* to Alova
|
||||
export function readEntities(): AxiosPromise<Entities> {
|
||||
return AXIOS.get('/entities');
|
||||
}
|
||||
|
||||
export function writeEntities(entities: Entities): AxiosPromise<void> {
|
||||
return AXIOS.post('/entities', entities);
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ export interface ScheduleItem {
|
||||
time: string;
|
||||
cmd: string;
|
||||
value: string;
|
||||
name?: string; // optional
|
||||
name: string; // optional
|
||||
o_id?: number;
|
||||
o_active?: boolean;
|
||||
o_deleted?: boolean;
|
||||
@@ -303,10 +303,6 @@ export interface ScheduleItem {
|
||||
o_name?: string;
|
||||
}
|
||||
|
||||
export interface Schedule {
|
||||
schedule: ScheduleItem[];
|
||||
}
|
||||
|
||||
export enum ScheduleFlag {
|
||||
SCHEDULE_SUN = 1,
|
||||
SCHEDULE_MON = 2,
|
||||
|
||||
@@ -90,6 +90,8 @@ export const schedulerItemValidation = () =>
|
||||
new Schema({
|
||||
name: [
|
||||
{
|
||||
// TODO name must be unique - add check
|
||||
required: true,
|
||||
type: 'string',
|
||||
pattern: /^[a-zA-Z0-9_\\.]{0,15}$/,
|
||||
message: "Must be <15 characters: alpha numeric, '_' or '.'"
|
||||
|
||||
@@ -3,15 +3,11 @@ import { useState } from 'react';
|
||||
import { unstable_useBlocker as useBlocker } from 'react-router-dom';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import type { AlovaXHRRequestConfig, AlovaXHRResponse, AlovaXHRResponseHeaders } from '@alova/adapter-xhr';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
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>;
|
||||
read: () => Method<any, any, any, any, any, any, any>;
|
||||
update: (value: D) => Method<any, any, any, any, any, any, any>;
|
||||
}
|
||||
|
||||
// TODO rename back to useRest
|
||||
|
||||
@@ -1567,7 +1567,7 @@ __metadata:
|
||||
react-dom: latest
|
||||
react-dropzone: ^14.2.3
|
||||
react-icons: ^4.9.0
|
||||
react-router-dom: ^6.12.1
|
||||
react-router-dom: ^6.13.0
|
||||
react-toastify: ^9.1.3
|
||||
rollup-plugin-visualizer: ^5.9.2
|
||||
sockette: ^2.0.6
|
||||
@@ -4807,27 +4807,27 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-router-dom@npm:^6.12.1":
|
||||
version: 6.12.1
|
||||
resolution: "react-router-dom@npm:6.12.1"
|
||||
"react-router-dom@npm:^6.13.0":
|
||||
version: 6.13.0
|
||||
resolution: "react-router-dom@npm:6.13.0"
|
||||
dependencies:
|
||||
"@remix-run/router": 1.6.3
|
||||
react-router: 6.12.1
|
||||
react-router: 6.13.0
|
||||
peerDependencies:
|
||||
react: ">=16.8"
|
||||
react-dom: ">=16.8"
|
||||
checksum: 4de0d4159a9dd2de0477d7608e9055262ebdd5dc41fc918b44b38170cc8ed407fa7dbb73bdb85e9469614502ad4772523b8a7f32c2609e62973feb41b70d871b
|
||||
checksum: 760c57063e305b0623f7b39bca3c7f5c169af557867eac7d1b19419111f7b6a9ed95d2083305c40ce98fd3be27e82c61f5674c90dd066a67653cb15901d00991
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-router@npm:6.12.1":
|
||||
version: 6.12.1
|
||||
resolution: "react-router@npm:6.12.1"
|
||||
"react-router@npm:6.13.0":
|
||||
version: 6.13.0
|
||||
resolution: "react-router@npm:6.13.0"
|
||||
dependencies:
|
||||
"@remix-run/router": 1.6.3
|
||||
peerDependencies:
|
||||
react: ">=16.8"
|
||||
checksum: 33a39eca122f3519f1aa91d8e6585fab669b3b06b621aa624f7db1ffda6b84676facd57028652f2fba7325a208abef906a5ba6c91d55d5a5d29993583d82dd61
|
||||
checksum: c58b4b943d3a76d328c6ef299567a85d84a69b417f5f5d07596b0b9bd40632a828591d6f470b0f233ff9095f489f9fd5c8666fb03513e9470927447169a91d8a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
@@ -1798,8 +1798,9 @@ let emsesp_entities = {
|
||||
};
|
||||
|
||||
// SCHEDULE
|
||||
let emsesp_schedule = {
|
||||
schedule: [
|
||||
let emsesp_schedule =
|
||||
// schedule: [
|
||||
[
|
||||
{
|
||||
id: 1,
|
||||
active: true,
|
||||
@@ -1836,11 +1837,9 @@ let emsesp_schedule = {
|
||||
value: '',
|
||||
name: 'auto_restart'
|
||||
}
|
||||
]
|
||||
};
|
||||
];
|
||||
|
||||
// CUSTOMIZATIONS
|
||||
|
||||
const emsesp_deviceentities_1 = [{}];
|
||||
const emsesp_deviceentities_3 = [{}];
|
||||
const emsesp_deviceentities_5 = [{}];
|
||||
@@ -2327,7 +2326,7 @@ rest_server.post(EMSESP_CUSTOM_ENTITIES_ENDPOINT, (req, res) => {
|
||||
|
||||
rest_server.post(EMSESP_WRITE_SCHEDULE_ENDPOINT, (req, res) => {
|
||||
console.log('write schedule');
|
||||
console.log(req.body.schedule);
|
||||
console.log(req.body);
|
||||
emsesp_schedule = req.body;
|
||||
res.sendStatus(200);
|
||||
});
|
||||
@@ -2625,6 +2624,7 @@ rest_server.post(API_ENDPOINT_ROOT, (req, res) => {
|
||||
if (req.body.device === 'system') {
|
||||
if (req.body.entity === 'info') {
|
||||
console.log('sending system info: ' + JSON.stringify(emsesp_info));
|
||||
res.json(emsesp_info);
|
||||
} else if (req.body.entity === 'settings') {
|
||||
console.log('sending system settings: ' + JSON.stringify(settings));
|
||||
res.json(settings);
|
||||
@@ -2652,25 +2652,37 @@ rest_server.get(SYSTEM_INFO_ENDPOINT, (req, res) => {
|
||||
|
||||
const GET_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'getSettings';
|
||||
rest_server.get(GET_SETTINGS_ENDPOINT, (req, res) => {
|
||||
console.log('System Settings:');
|
||||
console.log('getSettings:');
|
||||
res.json(settings);
|
||||
});
|
||||
|
||||
const GET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'getCustomizations';
|
||||
rest_server.get(GET_CUSTOMIZATIONS_ENDPOINT, (req, res) => {
|
||||
console.log('Customization');
|
||||
console.log('getCustomization');
|
||||
// not implemented yet
|
||||
res.sendStatus(200);
|
||||
});
|
||||
|
||||
const GET_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule';
|
||||
const GET_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'getEntities';
|
||||
rest_server.get(GET_ENTITIES_ENDPOINT, (req, res) => {
|
||||
console.log('getEntities');
|
||||
res.json(emsesp_entities);
|
||||
});
|
||||
|
||||
const GET_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'getSchedule';
|
||||
rest_server.get(GET_SCHEDULE_ENDPOINT, (req, res) => {
|
||||
console.log('getSchedule');
|
||||
res.json(emsesp_schedule);
|
||||
});
|
||||
|
||||
const SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule';
|
||||
rest_server.get(SCHEDULE_ENDPOINT, (req, res) => {
|
||||
console.log('Sending Schedule data');
|
||||
res.json(emsesp_schedule);
|
||||
});
|
||||
|
||||
const GET_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'entities';
|
||||
rest_server.get(GET_ENTITIES_ENDPOINT, (req, res) => {
|
||||
const ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'entities';
|
||||
rest_server.get(ENTITIES_ENDPOINT, (req, res) => {
|
||||
console.log('Sending Entities data');
|
||||
res.json(emsesp_entities);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user