diff --git a/interface/package.json b/interface/package.json index 5c4fb7ae5..981b20850 100644 --- a/interface/package.json +++ b/interface/package.json @@ -50,7 +50,7 @@ "@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": "^8.43.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^17.0.0", "eslint-config-prettier": "^8.8.0", diff --git a/interface/src/AuthenticatedRouting.tsx b/interface/src/AuthenticatedRouting.tsx index 7474821c8..2c99ce3c3 100644 --- a/interface/src/AuthenticatedRouting.tsx +++ b/interface/src/AuthenticatedRouting.tsx @@ -33,7 +33,7 @@ const AuthenticatedRouting: FC = () => { ); useEffect(() => { - // TODO how to replace AXIOS.interceptors.response.use ??? + // TODO replace AXIOS.interceptors.response.use ??? const axiosHandlerId = AXIOS.interceptors.response.use((response) => response, handleApiResponseError); return () => AXIOS.interceptors.response.eject(axiosHandlerId); }, [handleApiResponseError]); diff --git a/interface/src/SignIn.tsx b/interface/src/SignIn.tsx index 0cca183c9..bcd618fd2 100644 --- a/interface/src/SignIn.tsx +++ b/interface/src/SignIn.tsx @@ -42,6 +42,7 @@ const SignIn: FC = () => { const signIn = async () => { try { + // TODO move to Alova const { data: loginResponse } = await AuthenticationApi.signIn(signInRequest); authenticationContext.signIn(loginResponse.access_token); } catch (error) { diff --git a/interface/src/api/authentication.ts b/interface/src/api/authentication.ts index d66042236..805596a3c 100644 --- a/interface/src/api/authentication.ts +++ b/interface/src/api/authentication.ts @@ -9,10 +9,11 @@ import type { Me, SignInRequest, SignInResponse } from 'types'; export const SIGN_IN_PATHNAME = 'loginPathname'; export const SIGN_IN_SEARCH = 'loginSearch'; -// TODO move to Alova +// TODO move verifyAuthorization to Alova export function verifyAuthorization(): AxiosPromise { return AXIOS.get('/verifyAuthorization'); } +// TODO move signIn to Alova export function signIn(request: SignInRequest): AxiosPromise { return AXIOS.post('/signIn', request); } diff --git a/interface/src/api/endpoints.ts b/interface/src/api/endpoints.ts index cf2fbe799..9153dd17c 100644 --- a/interface/src/api/endpoints.ts +++ b/interface/src/api/endpoints.ts @@ -17,7 +17,7 @@ export const EVENT_SOURCE_ROOT = 'http://' + host + '/es/'; export const alovaInstance = createAlova({ statesHook: ReactHook, - timeout: 3000, + // timeout: 3000, localCache: { GET: { mode: 'placeholder', @@ -35,7 +35,9 @@ export const alovaInstance = createAlova({ responded: { onSuccess: async (response) => { - if (response.status == 205) { + if (response.status === 202) { + throw new Error('Wait'); + } else if (response.status === 205) { throw new Error('Reboot required'); } else if (response.status === 400) { throw new Error('Request Failed'); @@ -117,7 +119,7 @@ export const AXIOS_BIN = axios.create({ transformResponse: [(data) => unpack(data)] }); -// TODO replace upload with alova, see https://alova.js.org/next-step/download-upload-progress +// TODO replace fileupload with alova, see https://alova.js.org/next-step/download-upload-progress export interface FileUploadConfig { cancelToken?: CancelToken; onUploadProgress?: (progressEvent: AxiosProgressEvent) => void; diff --git a/interface/src/api/features.ts b/interface/src/api/features.ts index 6d8b663fa..c0dd66e4f 100644 --- a/interface/src/api/features.ts +++ b/interface/src/api/features.ts @@ -1,9 +1,5 @@ -import { AXIOS } from './endpoints'; -import type { AxiosPromise } from 'axios'; +import { alovaInstance } from './endpoints'; import type { Features } from 'types'; -// TODO move to Alova -export function readFeatures(): AxiosPromise { - return AXIOS.get('/features'); -} +export const readFeatures = () => alovaInstance.Get('/rest/features'); diff --git a/interface/src/api/system.ts b/interface/src/api/system.ts index 52db29d17..24bdaa10e 100644 --- a/interface/src/api/system.ts +++ b/interface/src/api/system.ts @@ -1,52 +1,27 @@ -import { AXIOS, AXIOS_BIN, alovaInstance, startUploadFile } from './endpoints'; +import { alovaInstance, startUploadFile } from './endpoints'; import type { FileUploadConfig } from './endpoints'; import type { AxiosPromise } from 'axios'; -import type { OTASettings, SystemStatus, LogSettings, LogEntries } from 'types'; - -// TODO move to Alova -// TODO fix this next! +import type { OTASettings, SystemStatus, LogSettings } from 'types'; export const readSystemStatus = (timeout?: number) => alovaInstance.Get('/rest/systemStatus', { params: { timeout } }); -// export function readSystemStatus(timeout?: number): AxiosPromise { -// return AXIOS.get('/systemStatus', { timeout }); -// } - -export function restart(): AxiosPromise { - return AXIOS.post('/restart'); -} - -export function partition(): AxiosPromise { - return AXIOS.post('/partition'); -} - -export function factoryReset(): AxiosPromise { - return AXIOS.post('/factoryReset'); -} +// commands +export const restart = () => alovaInstance.Post('/rest/restart'); +export const partition = () => alovaInstance.Post('/rest/partition'); +export const factoryReset = () => alovaInstance.Post('/rest/factoryReset'); -export function readOTASettings(): AxiosPromise { - return AXIOS.get('/otaSettings'); -} +// OTA +export const readOTASettings = () => alovaInstance.Get(`/rest/otaSettings`); +export const updateOTASettings = (data: any) => alovaInstance.Post('/rest/otaSettings', data); -export function updateOTASettings(otaSettings: OTASettings): AxiosPromise { - return AXIOS.post('/otaSettings', otaSettings); -} +// SystemLog +export const readLogSettings = () => alovaInstance.Get(`/rest/logSettings`); +export const updateLogSettings = (data: any) => alovaInstance.Post('/rest/logSettings', data); +export const fetchLog = () => alovaInstance.Post('/rest/fetchLog'); export const uploadFile = (file: File, config?: FileUploadConfig): AxiosPromise => startUploadFile('/uploadFile', file, config); - -export function readLogSettings(): AxiosPromise { - return AXIOS.get('/logSettings'); -} - -export function updateLogSettings(logSettings: LogSettings): AxiosPromise { - return AXIOS.post('/logSettings', logSettings); -} - -export function readLogEntries(): AxiosPromise { - return AXIOS_BIN.get('/fetchLog'); -} diff --git a/interface/src/components/upload/useFileUpload.ts b/interface/src/components/upload/useFileUpload.ts index da68b042c..b3a62a39b 100644 --- a/interface/src/components/upload/useFileUpload.ts +++ b/interface/src/components/upload/useFileUpload.ts @@ -9,6 +9,7 @@ import { useI18nContext } from 'i18n/i18n-react'; import { extractErrorMessage } from 'utils'; interface MediaUploadOptions { + // TODO fileupload move to alova upload: (file: File, config?: FileUploadConfig) => AxiosPromise; } diff --git a/interface/src/contexts/features/FeaturesLoader.tsx b/interface/src/contexts/features/FeaturesLoader.tsx index 8169d7b82..210b8f25b 100644 --- a/interface/src/contexts/features/FeaturesLoader.tsx +++ b/interface/src/contexts/features/FeaturesLoader.tsx @@ -1,30 +1,14 @@ -import { useCallback, useEffect, useState } from 'react'; +import { useRequest } from 'alova'; import { FeaturesContext } from '.'; import type { FC } from 'react'; -import type { Features } from 'types'; import type { RequiredChildrenProps } from 'utils'; import * as FeaturesApi from 'api/features'; import { ApplicationError, LoadingSpinner } from 'components'; -import { extractErrorMessage } from 'utils'; const FeaturesLoader: FC = (props) => { - const [errorMessage, setErrorMessage] = useState(); - const [features, setFeatures] = useState(); - - const loadFeatures = useCallback(async () => { - try { - const response = await FeaturesApi.readFeatures(); - setFeatures(response.data); - } catch (error) { - setErrorMessage(extractErrorMessage(error, 'Failed to fetch application details.')); - } - }, []); - - useEffect(() => { - void loadFeatures(); - }, [loadFeatures]); + const { data: features, error } = useRequest(FeaturesApi.readFeatures); if (features) { return ( @@ -38,8 +22,8 @@ const FeaturesLoader: FC = (props) => { ); } - if (errorMessage) { - return ; + if (error) { + return ; } return ; diff --git a/interface/src/framework/network/NetworkSettingsForm.tsx b/interface/src/framework/network/NetworkSettingsForm.tsx index 52d4521ed..3ca414935 100644 --- a/interface/src/framework/network/NetworkSettingsForm.tsx +++ b/interface/src/framework/network/NetworkSettingsForm.tsx @@ -18,6 +18,7 @@ import { InputAdornment, TextField } from '@mui/material'; +// eslint-disable-next-line import/named import { updateState, useRequest } from 'alova'; import { useContext, useEffect, useState } from 'react'; import { toast } from 'react-toastify'; @@ -29,6 +30,7 @@ import type { FC } from 'react'; import type { NetworkSettings } from 'types'; import * as NetworkApi from 'api/network'; +import * as SystemApi from 'api/system'; import { BlockFormControlLabel, ButtonRow, @@ -40,7 +42,7 @@ import { BlockNavigation } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; -import * as EMSESP from 'project/api'; + import { numberValue, updateValueDirty, useRest2 } from 'utils'; import { validate } from 'validators'; @@ -71,7 +73,7 @@ const WiFiSettingsForm: FC = () => { update: NetworkApi.updateNetworkSettings }); - const { send: restartCommand } = useRequest(EMSESP.restart(), { + const { send: restartCommand } = useRequest(SystemApi.restart(), { immediate: false }); diff --git a/interface/src/framework/network/WiFiNetworkScanner.tsx b/interface/src/framework/network/WiFiNetworkScanner.tsx index 97205d02c..72a967f21 100644 --- a/interface/src/framework/network/WiFiNetworkScanner.tsx +++ b/interface/src/framework/network/WiFiNetworkScanner.tsx @@ -1,82 +1,63 @@ import PermScanWifiIcon from '@mui/icons-material/PermScanWifi'; import { Button } from '@mui/material'; -import { useEffect, useState, useCallback, useRef } from 'react'; +import { useRequest } from 'alova'; +import { useState, useCallback, useRef } from 'react'; import { toast } from 'react-toastify'; import WiFiNetworkSelector from './WiFiNetworkSelector'; import type { FC } from 'react'; -import type { WiFiNetwork, WiFiNetworkList } from 'types'; import * as NetworkApi from 'api/network'; import { ButtonRow, FormLoader, SectionContent } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; const NUM_POLLS = 10; -const POLLING_FREQUENCY = 500; - -const compareNetworks = (network1: WiFiNetwork, network2: WiFiNetwork) => { - if (network1.rssi < network2.rssi) return 1; - if (network1.rssi > network2.rssi) return -1; - return 0; -}; +const POLLING_FREQUENCY = 1000; const WiFiNetworkScanner: FC = () => { const { LL } = useI18nContext(); const pollCount = useRef(0); - const [networkList, setNetworkList] = useState(); const [errorMessage, setErrorMessage] = useState(); + const { data: networkList, send: getNetworkList } = useRequest(NetworkApi.listNetworks, { + immediate: false + }); + + const { + send: scanNetworks, + onSuccess: onSuccessScanNetworks, + onError: onErrorScanNetworks + } = useRequest(NetworkApi.scanNetworks); + const finishedWithError = useCallback((message: string) => { toast.error(message); - setNetworkList(undefined); setErrorMessage(message); + pollCount.current = 0; }, []); - const pollNetworkList = useCallback(async () => { - try { - const response = await NetworkApi.listNetworks(); - if (response.status === 202) { - const completedPollCount = pollCount.current + 1; - if (completedPollCount < NUM_POLLS) { - pollCount.current = completedPollCount; - setTimeout(pollNetworkList, POLLING_FREQUENCY); - } else { - finishedWithError(LL.PROBLEM_LOADING()); - } - } else { - const newNetworkList = response.data; - newNetworkList.networks.sort(compareNetworks); - setNetworkList(newNetworkList); - } - } catch (error) { - if (error.response) { - finishedWithError(LL.PROBLEM_LOADING() + ' ' + error.response?.data.message); + onErrorScanNetworks((event) => { + console.log('onErrorScanNetworks'); // TODO fix + if (event.error?.message === 'Wait') { + // 202 + console.log('not ready...: ', event.error?.message); // TODO fix + const completedPollCount = pollCount.current + 1; + if (completedPollCount < NUM_POLLS) { + pollCount.current = completedPollCount; + setTimeout(scanNetworks, POLLING_FREQUENCY); } else { finishedWithError(LL.PROBLEM_LOADING()); } + } else { + finishedWithError(LL.PROBLEM_LOADING()); } - }, [finishedWithError, LL]); + }); - const startNetworkScan = useCallback(async () => { + onSuccessScanNetworks(() => { + console.log('onCompleteScanNetworks'); // TODO fix pollCount.current = 0; - setNetworkList(undefined); - setErrorMessage(undefined); - try { - await NetworkApi.scanNetworks(); - setTimeout(pollNetworkList, POLLING_FREQUENCY); - } catch (error) { - if (error.response) { - finishedWithError(LL.PROBLEM_LOADING() + ' ' + error.response?.data.message); - } else { - finishedWithError(LL.PROBLEM_LOADING()); - } - } - }, [finishedWithError, pollNetworkList, LL]); - - useEffect(() => { - void startNetworkScan(); - }, [startNetworkScan]); + void getNetworkList(); // fetch the list + }); const renderNetworkScanner = () => { if (!networkList) { @@ -93,7 +74,7 @@ const WiFiNetworkScanner: FC = () => { startIcon={} variant="outlined" color="secondary" - onClick={startNetworkScan} + onClick={scanNetworks} disabled={!errorMessage && !networkList} > {LL.SCAN_AGAIN()}… diff --git a/interface/src/framework/ntp/NTPSettingsForm.tsx b/interface/src/framework/ntp/NTPSettingsForm.tsx index 81a3d80ff..b1da11b97 100644 --- a/interface/src/framework/ntp/NTPSettingsForm.tsx +++ b/interface/src/framework/ntp/NTPSettingsForm.tsx @@ -1,6 +1,7 @@ import CancelIcon from '@mui/icons-material/Cancel'; import WarningIcon from '@mui/icons-material/Warning'; import { Button, Checkbox, MenuItem } from '@mui/material'; +// eslint-disable-next-line import/named import { updateState } from 'alova'; import { useState } from 'react'; import { selectedTimeZone, timeZoneSelectItems, TIME_ZONES } from './TZ'; diff --git a/interface/src/framework/system/GeneralFileUpload.tsx b/interface/src/framework/system/GeneralFileUpload.tsx index 9c0a04e6c..8e2243fed 100644 --- a/interface/src/framework/system/GeneralFileUpload.tsx +++ b/interface/src/framework/system/GeneralFileUpload.tsx @@ -12,6 +12,7 @@ import { useI18nContext } from 'i18n/i18n-react'; import * as EMSESP from 'project/api'; interface UploadFileProps { + // TODO fileupload upload move to alova uploadGeneralFile: (file: File, config?: FileUploadConfig) => AxiosPromise; } diff --git a/interface/src/framework/system/OTASettingsForm.tsx b/interface/src/framework/system/OTASettingsForm.tsx index 33543f0c9..e6cbaf6a5 100644 --- a/interface/src/framework/system/OTASettingsForm.tsx +++ b/interface/src/framework/system/OTASettingsForm.tsx @@ -18,21 +18,31 @@ import { } from 'components'; import { useI18nContext } from 'i18n/i18n-react'; -import { numberValue, updateValueDirty, useRest } from 'utils'; +import { numberValue, updateValueDirty, useRest2 } from 'utils'; import { validate } from 'validators'; import { OTA_SETTINGS_VALIDATOR } from 'validators/system'; const OTASettingsForm: FC = () => { - const { loadData, saving, data, setData, origData, dirtyFlags, setDirtyFlags, blocker, saveData, errorMessage } = - useRest({ - read: SystemApi.readOTASettings, - update: SystemApi.updateOTASettings - }); + const { + loadData, + saveData, + saving, + updateDataValue, + data, + origData, + dirtyFlags, + setDirtyFlags, + blocker, + errorMessage + } = useRest2({ + read: SystemApi.readOTASettings, + update: SystemApi.updateOTASettings + }); const { LL } = useI18nContext(); - const updateFormValue = updateValueDirty(origData, dirtyFlags, setDirtyFlags, setData); + const updateFormValue = updateValueDirty(origData, dirtyFlags, setDirtyFlags, updateDataValue); const [fieldErrors, setFieldErrors] = useState(); diff --git a/interface/src/framework/system/RestartMonitor.tsx b/interface/src/framework/system/RestartMonitor.tsx index 9ba331568..83ad443ba 100644 --- a/interface/src/framework/system/RestartMonitor.tsx +++ b/interface/src/framework/system/RestartMonitor.tsx @@ -1,3 +1,4 @@ +import { useRequest } from 'alova'; import { useRef, useState, useEffect } from 'react'; import type { FC } from 'react'; @@ -16,10 +17,14 @@ const RestartMonitor: FC = () => { const { LL } = useI18nContext(); + const { send: readSystemStatus } = useRequest((timeout) => SystemApi.readSystemStatus(timeout), { + immediate: false + }); + const timeoutAt = useRef(new Date().getTime() + RESTART_TIMEOUT); const poll = useRef(async () => { try { - await SystemApi.readSystemStatus(POLL_TIMEOUT); + await readSystemStatus(POLL_TIMEOUT); document.location.href = '/fileUpdated'; } catch (error) { if (new Date().getTime() < timeoutAt.current) { diff --git a/interface/src/framework/system/SystemLog.tsx b/interface/src/framework/system/SystemLog.tsx index e9ef0d388..4cff7ebea 100644 --- a/interface/src/framework/system/SystemLog.tsx +++ b/interface/src/framework/system/SystemLog.tsx @@ -1,11 +1,13 @@ import DownloadIcon from '@mui/icons-material/GetApp'; import WarningIcon from '@mui/icons-material/Warning'; import { Box, styled, Button, Checkbox, MenuItem, Grid, TextField } from '@mui/material'; -import { useState, useEffect, useCallback } from 'react'; +// eslint-disable-next-line import/named +import { useRequest } from 'alova'; +import { useState, useEffect } from 'react'; import { toast } from 'react-toastify'; import type { FC } from 'react'; -import type { LogSettings, LogEntry, LogEntries } from 'types'; +import type { LogSettings, LogEntry } from 'types'; import { addAccessTokenParameter } from 'api/authentication'; import { EVENT_SOURCE_ROOT } from 'api/endpoints'; import * as SystemApi from 'api/system'; @@ -14,7 +16,7 @@ import { SectionContent, FormLoader, BlockFormControlLabel, BlockNavigation } fr import { useI18nContext } from 'i18n/i18n-react'; import { LogLevel } from 'types'; -import { useRest, updateValueDirty, extractErrorMessage } from 'utils'; +import { updateValueDirty, useRest2 } from 'utils'; export const LOG_EVENTSOURCE_URL = EVENT_SOURCE_ROOT + 'log'; @@ -49,15 +51,20 @@ const levelLabel = (level: LogLevel) => { const SystemLog: FC = () => { const { LL } = useI18nContext(); - // TODO replace with const { data: data, send: loadData, error } = useRequest(APApi.readAPStatus); - const { loadData, data, setData, origData, dirtyFlags, blocker, setDirtyFlags, setOrigData } = useRest({ - read: SystemApi.readLogSettings - }); + const { loadData, data, updateDataValue, origData, dirtyFlags, setDirtyFlags, blocker, saveData, errorMessage } = + useRest2({ + read: SystemApi.readLogSettings, + update: SystemApi.updateLogSettings + }); - const [errorMessage, setErrorMessage] = useState(); - const [logEntries, setLogEntries] = useState({ events: [] }); + // called on page load to reset pointer and fetch all log entries + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { send: fetchLog } = useRequest(SystemApi.fetchLog()); + const [logEntries, setLogEntries] = useState([]); const [lastIndex, setLastIndex] = useState(0); + const updateFormValue = updateValueDirty(origData, dirtyFlags, setDirtyFlags, updateDataValue); + const paddedLevelLabel = (level: LogLevel) => { const label = levelLabel(level); return data?.compact ? ' ' + label[0] : label.padStart(8, '\xa0'); @@ -73,11 +80,9 @@ const SystemLog: FC = () => { return data?.compact ? label : label.padEnd(7, '\xa0'); }; - const updateFormValue = updateValueDirty(origData, dirtyFlags, setDirtyFlags, setData); - const onDownload = () => { let result = ''; - for (const i of logEntries.events) { + for (const i of logEntries) { result += i.t + ' ' + levelLabel(i.l) + ' ' + i.i + ': [' + i.n + '] ' + i.m + '\n'; } const a = document.createElement('a'); @@ -94,29 +99,22 @@ const SystemLog: FC = () => { const logentry = JSON.parse(rawData as string) as LogEntry; if (logentry.i > lastIndex) { setLastIndex(logentry.i); - setLogEntries((old) => ({ events: [...old.events, logentry] })); + setLogEntries((log) => [...log, logentry]); } } }; - const fetchLog = useCallback(async () => { - try { - await SystemApi.readLogEntries(); - } catch (error) { - setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING())); - } - }, [LL]); - - useEffect(() => { - void fetchLog(); - }, [fetchLog]); + const saveSettings = async () => { + await saveData(); + }; useEffect(() => { const es = new EventSource(addAccessTokenParameter(LOG_EVENTSOURCE_URL)); es.onmessage = onMessage; es.onerror = () => { es.close(); - window.location.reload(); + toast.error('EventSource failed'); + // window.location.reload(); }; return () => { @@ -124,28 +122,6 @@ const SystemLog: FC = () => { }; }); - const saveSettings = async () => { - if (data) { - try { - const response = await SystemApi.updateLogSettings({ - level: data.level, - max_messages: data.max_messages, - compact: data.compact - }); - - if (response.status !== 200) { - toast.error(LL.PROBLEM_UPDATING()); - } else { - setOrigData(response.data); - setDirtyFlags([]); - toast.success(LL.UPDATED_OF(LL.SETTINGS())); - } - } catch (error) { - toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); - } - } - }; - const content = () => { if (!data) { return ; @@ -231,17 +207,16 @@ const SystemLog: FC = () => { p: 1 }} > - {logEntries && - logEntries.events.map((e) => ( - - {e.t} - {data.compact && {paddedLevelLabel(e.l)} } - {!data.compact && {paddedLevelLabel(e.l)} } - {paddedIDLabel(e.i)} - {paddedNameLabel(e.n)} - {e.m} - - ))} + {logEntries.map((e) => ( + + {e.t} + {data.compact && {paddedLevelLabel(e.l)} } + {!data.compact && {paddedLevelLabel(e.l)} } + {paddedIDLabel(e.i)} + {paddedNameLabel(e.n)} + {e.m} + + ))} ); diff --git a/interface/src/framework/system/SystemStatusForm.tsx b/interface/src/framework/system/SystemStatusForm.tsx index 0913ea02a..54d3b922f 100644 --- a/interface/src/framework/system/SystemStatusForm.tsx +++ b/interface/src/framework/system/SystemStatusForm.tsx @@ -35,12 +35,11 @@ import { toast } from 'react-toastify'; import RestartMonitor from './RestartMonitor'; import type { FC } from 'react'; -import type { SystemStatus, Version } from 'types'; +import type { Version } from 'types'; import * as SystemApi from 'api/system'; import { ButtonRow, FormLoader, SectionContent, MessageBox } from 'components'; import { AuthenticatedContext } from 'contexts/authentication'; import { useI18nContext } from 'i18n/i18n-react'; -import { extractErrorMessage } from 'utils'; export const VERSIONCHECK_ENDPOINT = 'https://api.github.com/repos/emsesp/EMS-ESP32/releases/latest'; export const VERSIONCHECK_DEV_ENDPOINT = 'https://api.github.com/repos/emsesp/EMS-ESP32/releases/tags/latest'; @@ -52,9 +51,6 @@ function formatNumber(num: number) { const SystemStatusForm: FC = () => { const { LL } = useI18nContext(); - const [restarting, setRestarting] = useState(); - - const { data: data, send: loadData, error } = useRequest(SystemApi.readSystemStatus); const { me } = useContext(AuthenticatedContext); const [confirmRestart, setConfirmRestart] = useState(false); @@ -63,6 +59,21 @@ const SystemStatusForm: FC = () => { const [showingVersion, setShowingVersion] = useState(false); const [latestVersion, setLatestVersion] = useState(); const [latestDevVersion, setLatestDevVersion] = useState(); + const [restarting, setRestarting] = useState(); + + const { send: restartCommand } = useRequest(SystemApi.restart(), { + immediate: false + }); + + const { send: factoryResetCommand } = useRequest(SystemApi.factoryReset(), { + immediate: false + }); + + const { send: partitionCommand } = useRequest(SystemApi.partition(), { + immediate: false + }); + + const { data: data, send: loadData, error } = useRequest(SystemApi.readSystemStatus); useEffect(() => { void axios.get(VERSIONCHECK_ENDPOINT).then((response) => { @@ -83,30 +94,47 @@ const SystemStatusForm: FC = () => { const restart = async () => { setProcessing(true); - try { - const response = await SystemApi.restart(); - if (response.status === 200) { + await restartCommand() + .then(() => { setRestarting(true); - } - } catch (error) { - toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); - } finally { - setConfirmRestart(false); - setProcessing(false); - } + }) + .catch((err) => { + toast.error(err.message); + }) + .finally(() => { + setConfirmRestart(false); + setProcessing(false); + }); + }; + + const factoryReset = async () => { + setProcessing(true); + await factoryResetCommand() + .then(() => { + setRestarting(true); + }) + .catch((err) => { + toast.error(err.message); + }) + .finally(() => { + setConfirmFactoryReset(false); + setProcessing(false); + }); }; const partition = async () => { setProcessing(true); - try { - await SystemApi.partition(); - setRestarting(true); - } catch (error) { - toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); - } finally { - setConfirmRestart(false); - setProcessing(false); - } + await partitionCommand() + .then(() => { + setRestarting(true); + }) + .catch((err) => { + toast.error(err.message); + }) + .finally(() => { + setConfirmRestart(false); + setProcessing(false); + }); }; const renderRestartDialog = () => ( @@ -201,19 +229,6 @@ const SystemStatusForm: FC = () => { ); - const factoryReset = async () => { - setProcessing(true); - try { - await SystemApi.factoryReset(); - setRestarting(true); - } catch (error) { - toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); - } finally { - setConfirmFactoryReset(false); - setProcessing(false); - } - }; - const renderFactoryResetDialog = () => ( setConfirmFactoryReset(false)}> {LL.FACTORY_RESET()} @@ -243,7 +258,7 @@ const SystemStatusForm: FC = () => { const content = () => { if (!data) { - return ; + return ; } return ( diff --git a/interface/src/framework/system/UploadFileForm.tsx b/interface/src/framework/system/UploadFileForm.tsx index 568738124..5cb437cb7 100644 --- a/interface/src/framework/system/UploadFileForm.tsx +++ b/interface/src/framework/system/UploadFileForm.tsx @@ -15,6 +15,7 @@ const UploadFileForm: FC = () => { const { LL } = useI18nContext(); const uploadFile = useRef(async (file: File, config?: FileUploadConfig) => { + // TODO fileupload move to alova const response = await SystemApi.uploadFile(file, config); if (response.status === 200) { setRestarting(true); diff --git a/interface/src/project/SettingsApplication.tsx b/interface/src/project/SettingsApplication.tsx index 9c085dead..9a27e997f 100644 --- a/interface/src/project/SettingsApplication.tsx +++ b/interface/src/project/SettingsApplication.tsx @@ -12,6 +12,7 @@ import { createSettingsValidator } from './validators'; import type { Settings } from './types'; import type { ValidateFieldsError } from 'async-validator'; import type { FC } from 'react'; +import * as SystemApi from 'api/system'; import { SectionContent, FormLoader, @@ -69,7 +70,7 @@ const SettingsApplication: FC = () => { immediate: false }); - const { send: restartCommand } = useRequest(EMSESP.restart(), { + const { send: restartCommand } = useRequest(SystemApi.restart(), { immediate: false }); diff --git a/interface/src/project/SettingsCustomization.tsx b/interface/src/project/SettingsCustomization.tsx index 442a5335d..8c032ea16 100644 --- a/interface/src/project/SettingsCustomization.tsx +++ b/interface/src/project/SettingsCustomization.tsx @@ -35,6 +35,7 @@ import * as EMSESP from './api'; import { DeviceEntityMask } from './types'; import type { DeviceShort, DeviceEntity } from './types'; import type { FC } from 'react'; +import * as SystemApi from 'api/system'; import { ButtonRow, SectionContent, MessageBox, BlockNavigation } from 'components'; import RestartMonitor from 'framework/system/RestartMonitor'; @@ -78,7 +79,7 @@ const SettingsCustomization: FC = () => { setOriginalSettings(event.data); }); - const { send: restartCommand } = useRequest(EMSESP.restart(), { + const { send: restartCommand } = useRequest(SystemApi.restart(), { immediate: false }); diff --git a/interface/src/project/SettingsEntities.tsx b/interface/src/project/SettingsEntities.tsx index ce1a1276e..9d83cd329 100644 --- a/interface/src/project/SettingsEntities.tsx +++ b/interface/src/project/SettingsEntities.tsx @@ -4,6 +4,7 @@ import WarningIcon from '@mui/icons-material/Warning'; import { Button, Typography, Box } 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'; +// eslint-disable-next-line import/named import { updateState, useRequest } from 'alova'; import { useState, useCallback } from 'react'; import { unstable_useBlocker as useBlocker } from 'react-router-dom'; @@ -108,8 +109,8 @@ const SettingsEntities: FC = () => { }); const saveEntities = async () => { - await writeEntities( - entities + await writeEntities({ + entities: entities .filter((ei) => !ei.deleted) .map((condensed_ei) => ({ id: condensed_ei.id, @@ -122,7 +123,7 @@ const SettingsEntities: FC = () => { writeable: condensed_ei.writeable, value_type: condensed_ei.value_type })) - ) + }) .then(() => { toast.success(LL.ENTITIES_UPDATED()); }) diff --git a/interface/src/project/SettingsScheduler.tsx b/interface/src/project/SettingsScheduler.tsx index 8c93252e4..b7259d613 100644 --- a/interface/src/project/SettingsScheduler.tsx +++ b/interface/src/project/SettingsScheduler.tsx @@ -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'; +// eslint-disable-next-line import/named import { updateState, useRequest } from 'alova'; import { useState, useEffect, useCallback } from 'react'; import { unstable_useBlocker as useBlocker } from 'react-router-dom'; @@ -108,8 +109,8 @@ const SettingsScheduler: FC = () => { }); const saveSchedule = async () => { - await writeSchedule( - schedule + await writeSchedule({ + schedule: schedule .filter((si) => !si.deleted) .map((condensed_si) => ({ id: condensed_si.id, @@ -120,7 +121,7 @@ const SettingsScheduler: FC = () => { value: condensed_si.value, name: condensed_si.name })) - ) + }) .then(() => { toast.success(LL.SCHEDULE_UPDATED()); }) diff --git a/interface/src/project/api.ts b/interface/src/project/api.ts index 3d872829a..f1e2e37ff 100644 --- a/interface/src/project/api.ts +++ b/interface/src/project/api.ts @@ -31,7 +31,6 @@ export const getBoardProfile = (boardProfile: string) => alovaInstance.Get('/rest/boardProfile', { params: { boardProfile } }); -export const restart = () => alovaInstance.Post('/rest/restart'); // DashboardSensors export const readSensorData = () => alovaInstance.Get('/rest/sensorData'); @@ -70,7 +69,7 @@ export const readSchedule = () => alovaInstance.Get('/rest/schedule', { name: 'schedule', transformData(data: any) { - return data.map((si: ScheduleItem) => ({ + return data.schedule.map((si: ScheduleItem) => ({ ...si, o_id: si.id, o_active: si.active, @@ -85,12 +84,12 @@ export const readSchedule = () => }); export const writeSchedule = (data: any) => alovaInstance.Post('/rest/schedule', data); -// SettingsCustomization +// SettingsEntities export const readEntities = () => alovaInstance.Get('/rest/entities', { name: 'entities', transformData(data: any) { - return data.map((ei: EntityItem) => ({ + return data.entities.map((ei: EntityItem) => ({ ...ei, o_id: ei.id, o_device_id: ei.device_id, diff --git a/interface/src/types/system.ts b/interface/src/types/system.ts index 5ad12c59b..ec2b00469 100644 --- a/interface/src/types/system.ts +++ b/interface/src/types/system.ts @@ -42,10 +42,6 @@ export interface LogEntry { m: string; } -export interface LogEntries { - events: LogEntry[]; -} - export interface LogSettings { level: number; max_messages: number; diff --git a/interface/yarn.lock b/interface/yarn.lock index 6803c97b3..111162d73 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -620,10 +620,10 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.42.0": - version: 8.42.0 - resolution: "@eslint/js@npm:8.42.0" - checksum: 4ae46df1f32095cf9527d1f6a8a30512151f8eb66dd883a226face17c9e7cfdd2dcb3d4e3124fb67ac5801e0a776b1d7bba368276cfb1e1e4eefb047e38b41d6 +"@eslint/js@npm:8.43.0": + version: 8.43.0 + resolution: "@eslint/js@npm:8.43.0" + checksum: ff1a1587e8f28c21dda36a331cf70ca16b76e5897cecf10f6b4c326abddf18db565ee5f71feb89cbb0d3d20ff321a2536357562c0233868eed70784640b73cf4 languageName: node linkType: hard @@ -1546,7 +1546,7 @@ __metadata: alova: ^2.6.1 async-validator: ^4.2.5 axios: ^1.4.0 - eslint: ^8.42.0 + eslint: ^8.43.0 eslint-config-airbnb: ^19.0.4 eslint-config-airbnb-typescript: ^17.0.0 eslint-config-prettier: ^8.8.0 @@ -2850,14 +2850,14 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.42.0": - version: 8.42.0 - resolution: "eslint@npm:8.42.0" +"eslint@npm:^8.43.0": + version: 8.43.0 + resolution: "eslint@npm:8.43.0" dependencies: "@eslint-community/eslint-utils": ^4.2.0 "@eslint-community/regexpp": ^4.4.0 "@eslint/eslintrc": ^2.0.3 - "@eslint/js": 8.42.0 + "@eslint/js": 8.43.0 "@humanwhocodes/config-array": ^0.11.10 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 @@ -2895,7 +2895,7 @@ __metadata: text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 8ab5a3c1619008c946497a16b88a811b1f6c49a750a9bd0f81085dff4166418b9da4e46108b09d920877ab2f5981e3613332653b7f5e3917d8088bc4b8d40b5a + checksum: 1f9ff2c774e852c179ba569a3b672cbc4cf91aa59843ee32f7da363c10b5aad842672005ac04c760f6077b3471da428562274e0fcb0a78c2056866b3d36be948 languageName: node linkType: hard diff --git a/lib/ArduinoJson/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp b/lib/ArduinoJson/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp index 9fb5a4acb..b0843c78d 100644 --- a/lib/ArduinoJson/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/MsgPack/MsgPackDeserializer.hpp @@ -15,549 +15,535 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE template class MsgPackDeserializer { - public: - MsgPackDeserializer(MemoryPool* pool, TReader reader, - TStringStorage stringStorage) - : _pool(pool), - _reader(reader), - _stringStorage(stringStorage), - _foundSomething(false) {} - - template - DeserializationError parse(VariantData& variant, TFilter filter, - DeserializationOption::NestingLimit nestingLimit) { - DeserializationError::Code err; - err = parseVariant(&variant, filter, nestingLimit); - return _foundSomething ? err : DeserializationError::EmptyInput; - } - - private: - template - DeserializationError::Code parseVariant( - VariantData* variant, TFilter filter, - DeserializationOption::NestingLimit nestingLimit) { - DeserializationError::Code err; - - uint8_t code = 0; // TODO: why do we need to initialize this variable? - err = readByte(code); - if (err) - return err; - - _foundSomething = true; - - bool allowValue = filter.allowValue(); - - if (allowValue) { - // callers pass a null pointer only when value must be ignored - ARDUINOJSON_ASSERT(variant != 0); + public: + MsgPackDeserializer(MemoryPool * pool, TReader reader, TStringStorage stringStorage) + : _pool(pool) + , _reader(reader) + , _stringStorage(stringStorage) + , _foundSomething(false) { } - switch (code) { - case 0xc0: - // already null - return DeserializationError::Ok; + template + DeserializationError parse(VariantData & variant, TFilter filter, DeserializationOption::NestingLimit nestingLimit) { + DeserializationError::Code err; + err = parseVariant(&variant, filter, nestingLimit); + return _foundSomething ? err : DeserializationError::EmptyInput; + } - case 0xc1: - return DeserializationError::InvalidInput; + private: + template + DeserializationError::Code parseVariant(VariantData * variant, TFilter filter, DeserializationOption::NestingLimit nestingLimit) { + DeserializationError::Code err; - case 0xc2: - if (allowValue) - variant->setBoolean(false); - return DeserializationError::Ok; + uint8_t code = 0; + err = readByte(code); + if (err) + return err; - case 0xc3: - if (allowValue) - variant->setBoolean(true); - return DeserializationError::Ok; + _foundSomething = true; - case 0xc4: // bin 8 (not supported) - return skipString(); + bool allowValue = filter.allowValue(); - case 0xc5: // bin 16 (not supported) - return skipString(); + if (allowValue) { + // callers pass a null pointer only when value must be ignored + ARDUINOJSON_ASSERT(variant != 0); + } - case 0xc6: // bin 32 (not supported) - return skipString(); + switch (code) { + case 0xc0: + // already null + return DeserializationError::Ok; - case 0xc7: // ext 8 (not supported) - return skipExt(); + case 0xc1: + return DeserializationError::InvalidInput; - case 0xc8: // ext 16 (not supported) - return skipExt(); + case 0xc2: + if (allowValue) + variant->setBoolean(false); + return DeserializationError::Ok; - case 0xc9: // ext 32 (not supported) - return skipExt(); + case 0xc3: + if (allowValue) + variant->setBoolean(true); + return DeserializationError::Ok; - case 0xca: - if (allowValue) - return readFloat(variant); - else - return skipBytes(4); + case 0xc4: // bin 8 (not supported) + return skipString(); - case 0xcb: - if (allowValue) - return readDouble(variant); - else - return skipBytes(8); + case 0xc5: // bin 16 (not supported) + return skipString(); - case 0xcc: - if (allowValue) - return readInteger(variant); - else - return skipBytes(1); + case 0xc6: // bin 32 (not supported) + return skipString(); - case 0xcd: - if (allowValue) - return readInteger(variant); - else - return skipBytes(2); + case 0xc7: // ext 8 (not supported) + return skipExt(); - case 0xce: - if (allowValue) - return readInteger(variant); - else - return skipBytes(4); + case 0xc8: // ext 16 (not supported) + return skipExt(); - case 0xcf: -#if ARDUINOJSON_USE_LONG_LONG - if (allowValue) - return readInteger(variant); - else - return skipBytes(8); -#else - return skipBytes(8); // not supported -#endif + case 0xc9: // ext 32 (not supported) + return skipExt(); - case 0xd0: - if (allowValue) - return readInteger(variant); - else - return skipBytes(1); + case 0xca: + if (allowValue) + return readFloat(variant); + else + return skipBytes(4); - case 0xd1: - if (allowValue) - return readInteger(variant); - else - return skipBytes(2); + case 0xcb: + if (allowValue) + return readDouble(variant); + else + return skipBytes(8); - case 0xd2: - if (allowValue) - return readInteger(variant); - else - return skipBytes(4); + case 0xcc: + if (allowValue) + return readInteger(variant); + else + return skipBytes(1); - case 0xd3: + case 0xcd: + if (allowValue) + return readInteger(variant); + else + return skipBytes(2); + + case 0xce: + if (allowValue) + return readInteger(variant); + else + return skipBytes(4); + + case 0xcf: #if ARDUINOJSON_USE_LONG_LONG - if (allowValue) - return readInteger(variant); - else - return skipBytes(8); // not supported + if (allowValue) + return readInteger(variant); + else + return skipBytes(8); #else - return skipBytes(8); + return skipBytes(8); // not supported #endif - case 0xd4: // fixext 1 (not supported) - return skipBytes(2); + case 0xd0: + if (allowValue) + return readInteger(variant); + else + return skipBytes(1); + + case 0xd1: + if (allowValue) + return readInteger(variant); + else + return skipBytes(2); + + case 0xd2: + if (allowValue) + return readInteger(variant); + else + return skipBytes(4); + + case 0xd3: +#if ARDUINOJSON_USE_LONG_LONG + if (allowValue) + return readInteger(variant); + else + return skipBytes(8); // not supported +#else + return skipBytes(8); +#endif - case 0xd5: // fixext 2 (not supported) - return skipBytes(3); + case 0xd4: // fixext 1 (not supported) + return skipBytes(2); - case 0xd6: // fixext 4 (not supported) - return skipBytes(5); + case 0xd5: // fixext 2 (not supported) + return skipBytes(3); - case 0xd7: // fixext 8 (not supported) - return skipBytes(9); + case 0xd6: // fixext 4 (not supported) + return skipBytes(5); - case 0xd8: // fixext 16 (not supported) - return skipBytes(17); + case 0xd7: // fixext 8 (not supported) + return skipBytes(9); - case 0xd9: - if (allowValue) - return readString(variant); - else - return skipString(); + case 0xd8: // fixext 16 (not supported) + return skipBytes(17); - case 0xda: - if (allowValue) - return readString(variant); - else - return skipString(); + case 0xd9: + if (allowValue) + return readString(variant); + else + return skipString(); - case 0xdb: - if (allowValue) - return readString(variant); - else - return skipString(); + case 0xda: + if (allowValue) + return readString(variant); + else + return skipString(); - case 0xdc: - return readArray(variant, filter, nestingLimit); + case 0xdb: + if (allowValue) + return readString(variant); + else + return skipString(); - case 0xdd: - return readArray(variant, filter, nestingLimit); + case 0xdc: + return readArray(variant, filter, nestingLimit); - case 0xde: - return readObject(variant, filter, nestingLimit); + case 0xdd: + return readArray(variant, filter, nestingLimit); - case 0xdf: - return readObject(variant, filter, nestingLimit); - } + case 0xde: + return readObject(variant, filter, nestingLimit); + + case 0xdf: + return readObject(variant, filter, nestingLimit); + } + + switch (code & 0xf0) { + case 0x80: + return readObject(variant, code & 0x0F, filter, nestingLimit); - switch (code & 0xf0) { - case 0x80: - return readObject(variant, code & 0x0F, filter, nestingLimit); + case 0x90: + return readArray(variant, code & 0x0F, filter, nestingLimit); + } - case 0x90: - return readArray(variant, code & 0x0F, filter, nestingLimit); + if ((code & 0xe0) == 0xa0) { + if (allowValue) + return readString(variant, code & 0x1f); + else + return skipBytes(code & 0x1f); + } + + if (allowValue) + variant->setInteger(static_cast(code)); + + return DeserializationError::Ok; } - if ((code & 0xe0) == 0xa0) { - if (allowValue) - return readString(variant, code & 0x1f); - else - return skipBytes(code & 0x1f); + DeserializationError::Code readByte(uint8_t & value) { + int c = _reader.read(); + if (c < 0) + return DeserializationError::IncompleteInput; + value = static_cast(c); + return DeserializationError::Ok; } - if (allowValue) - variant->setInteger(static_cast(code)); - - return DeserializationError::Ok; - } - - DeserializationError::Code readByte(uint8_t& value) { - int c = _reader.read(); - if (c < 0) - return DeserializationError::IncompleteInput; - value = static_cast(c); - return DeserializationError::Ok; - } - - DeserializationError::Code readBytes(uint8_t* p, size_t n) { - if (_reader.readBytes(reinterpret_cast(p), n) == n) - return DeserializationError::Ok; - return DeserializationError::IncompleteInput; - } - - template - DeserializationError::Code readBytes(T& value) { - return readBytes(reinterpret_cast(&value), sizeof(value)); - } - - DeserializationError::Code skipBytes(size_t n) { - for (; n; --n) { - if (_reader.read() < 0) + DeserializationError::Code readBytes(uint8_t * p, size_t n) { + if (_reader.readBytes(reinterpret_cast(p), n) == n) + return DeserializationError::Ok; return DeserializationError::IncompleteInput; } - return DeserializationError::Ok; - } - - template - DeserializationError::Code readInteger(T& value) { - DeserializationError::Code err; - err = readBytes(value); - if (err) - return err; - - fixEndianess(value); + template + DeserializationError::Code readBytes(T & value) { + return readBytes(reinterpret_cast(&value), sizeof(value)); + } - return DeserializationError::Ok; - } + DeserializationError::Code skipBytes(size_t n) { + for (; n; --n) { + if (_reader.read() < 0) + return DeserializationError::IncompleteInput; + } + return DeserializationError::Ok; + } - template - DeserializationError::Code readInteger(VariantData* variant) { - DeserializationError::Code err; - T value; + template + DeserializationError::Code readInteger(T & value) { + DeserializationError::Code err; - err = readInteger(value); - if (err) - return err; + err = readBytes(value); + if (err) + return err; - variant->setInteger(value); + fixEndianess(value); - return DeserializationError::Ok; - } + return DeserializationError::Ok; + } - template - typename enable_if::type - readFloat(VariantData* variant) { - DeserializationError::Code err; - T value; + template + DeserializationError::Code readInteger(VariantData * variant) { + DeserializationError::Code err; + T value; - err = readBytes(value); - if (err) - return err; + err = readInteger(value); + if (err) + return err; - fixEndianess(value); - variant->setFloat(value); + variant->setInteger(value); - return DeserializationError::Ok; - } + return DeserializationError::Ok; + } - template - typename enable_if::type - readDouble(VariantData* variant) { - DeserializationError::Code err; - T value; + template + typename enable_if::type readFloat(VariantData * variant) { + DeserializationError::Code err; + T value; - err = readBytes(value); - if (err) - return err; + err = readBytes(value); + if (err) + return err; - fixEndianess(value); - variant->setFloat(value); + fixEndianess(value); + variant->setFloat(value); - return DeserializationError::Ok; - } + return DeserializationError::Ok; + } - template - typename enable_if::type - readDouble(VariantData* variant) { - DeserializationError::Code err; - uint8_t i[8]; // input is 8 bytes - T value; // output is 4 bytes - uint8_t* o = reinterpret_cast(&value); + template + typename enable_if::type readDouble(VariantData * variant) { + DeserializationError::Code err; + T value; - err = readBytes(i, 8); - if (err) - return err; + err = readBytes(value); + if (err) + return err; - doubleToFloat(i, o); - fixEndianess(value); - variant->setFloat(value); + fixEndianess(value); + variant->setFloat(value); - return DeserializationError::Ok; - } + return DeserializationError::Ok; + } - template - DeserializationError::Code readString(VariantData* variant) { - DeserializationError::Code err; - T size; + template + typename enable_if::type readDouble(VariantData * variant) { + DeserializationError::Code err; + uint8_t i[8]; // input is 8 bytes + T value; // output is 4 bytes + uint8_t * o = reinterpret_cast(&value); - err = readInteger(size); - if (err) - return err; + err = readBytes(i, 8); + if (err) + return err; - return readString(variant, size); - } + doubleToFloat(i, o); + fixEndianess(value); + variant->setFloat(value); - template - DeserializationError::Code readString() { - DeserializationError::Code err; - T size; + return DeserializationError::Ok; + } - err = readInteger(size); - if (err) - return err; + template + DeserializationError::Code readString(VariantData * variant) { + DeserializationError::Code err; + T size; - return readString(size); - } + err = readInteger(size); + if (err) + return err; - template - DeserializationError::Code skipString() { - DeserializationError::Code err; - T size; + return readString(variant, size); + } - err = readInteger(size); - if (err) - return err; + template + DeserializationError::Code readString() { + DeserializationError::Code err; + T size; - return skipBytes(size); - } + err = readInteger(size); + if (err) + return err; - DeserializationError::Code readString(VariantData* variant, size_t n) { - DeserializationError::Code err; + return readString(size); + } - err = readString(n); - if (err) - return err; + template + DeserializationError::Code skipString() { + DeserializationError::Code err; + T size; - variant->setString(_stringStorage.save()); - return DeserializationError::Ok; - } + err = readInteger(size); + if (err) + return err; - DeserializationError::Code readString(size_t n) { - DeserializationError::Code err; + return skipBytes(size); + } - _stringStorage.startString(); - for (; n; --n) { - uint8_t c; + DeserializationError::Code readString(VariantData * variant, size_t n) { + DeserializationError::Code err; - err = readBytes(c); - if (err) - return err; + err = readString(n); + if (err) + return err; - _stringStorage.append(static_cast(c)); + variant->setString(_stringStorage.save()); + return DeserializationError::Ok; } - if (!_stringStorage.isValid()) - return DeserializationError::NoMemory; + DeserializationError::Code readString(size_t n) { + DeserializationError::Code err; - return DeserializationError::Ok; - } + _stringStorage.startString(); + for (; n; --n) { + uint8_t c; - template - DeserializationError::Code readArray( - VariantData* variant, TFilter filter, - DeserializationOption::NestingLimit nestingLimit) { - DeserializationError::Code err; - TSize size; + err = readBytes(c); + if (err) + return err; - err = readInteger(size); - if (err) - return err; + _stringStorage.append(static_cast(c)); + } - return readArray(variant, size, filter, nestingLimit); - } + if (!_stringStorage.isValid()) + return DeserializationError::NoMemory; - template - DeserializationError::Code readArray( - VariantData* variant, size_t n, TFilter filter, - DeserializationOption::NestingLimit nestingLimit) { - DeserializationError::Code err; + return DeserializationError::Ok; + } - if (nestingLimit.reached()) - return DeserializationError::TooDeep; + template + DeserializationError::Code readArray(VariantData * variant, TFilter filter, DeserializationOption::NestingLimit nestingLimit) { + DeserializationError::Code err; + TSize size; - bool allowArray = filter.allowArray(); + err = readInteger(size); + if (err) + return err; - CollectionData* array; - if (allowArray) { - ARDUINOJSON_ASSERT(variant != 0); - array = &variant->toArray(); - } else { - array = 0; + return readArray(variant, size, filter, nestingLimit); } - TFilter memberFilter = filter[0U]; + template + DeserializationError::Code readArray(VariantData * variant, size_t n, TFilter filter, DeserializationOption::NestingLimit nestingLimit) { + DeserializationError::Code err; + + if (nestingLimit.reached()) + return DeserializationError::TooDeep; + + bool allowArray = filter.allowArray(); + + CollectionData * array; + if (allowArray) { + ARDUINOJSON_ASSERT(variant != 0); + array = &variant->toArray(); + } else { + array = 0; + } - for (; n; --n) { - VariantData* value; + TFilter memberFilter = filter[0U]; - if (memberFilter.allow()) { - ARDUINOJSON_ASSERT(array != 0); - value = array->addElement(_pool); - if (!value) - return DeserializationError::NoMemory; - } else { - value = 0; - } + for (; n; --n) { + VariantData * value; - err = parseVariant(value, memberFilter, nestingLimit.decrement()); - if (err) - return err; + if (memberFilter.allow()) { + ARDUINOJSON_ASSERT(array != 0); + value = array->addElement(_pool); + if (!value) + return DeserializationError::NoMemory; + } else { + value = 0; + } + + err = parseVariant(value, memberFilter, nestingLimit.decrement()); + if (err) + return err; + } + + return DeserializationError::Ok; } - return DeserializationError::Ok; - } - - template - DeserializationError::Code readObject( - VariantData* variant, TFilter filter, - DeserializationOption::NestingLimit nestingLimit) { - DeserializationError::Code err; - TSize size; - - err = readInteger(size); - if (err) - return err; - - return readObject(variant, size, filter, nestingLimit); - } - - template - DeserializationError::Code readObject( - VariantData* variant, size_t n, TFilter filter, - DeserializationOption::NestingLimit nestingLimit) { - DeserializationError::Code err; - - if (nestingLimit.reached()) - return DeserializationError::TooDeep; - - CollectionData* object; - if (filter.allowObject()) { - ARDUINOJSON_ASSERT(variant != 0); - object = &variant->toObject(); - } else { - object = 0; + template + DeserializationError::Code readObject(VariantData * variant, TFilter filter, DeserializationOption::NestingLimit nestingLimit) { + DeserializationError::Code err; + TSize size; + + err = readInteger(size); + if (err) + return err; + + return readObject(variant, size, filter, nestingLimit); } - for (; n; --n) { - err = readKey(); - if (err) - return err; + template + DeserializationError::Code readObject(VariantData * variant, size_t n, TFilter filter, DeserializationOption::NestingLimit nestingLimit) { + DeserializationError::Code err; - JsonString key = _stringStorage.str(); - TFilter memberFilter = filter[key.c_str()]; - VariantData* member; + if (nestingLimit.reached()) + return DeserializationError::TooDeep; - if (memberFilter.allow()) { - ARDUINOJSON_ASSERT(object != 0); + CollectionData * object; + if (filter.allowObject()) { + ARDUINOJSON_ASSERT(variant != 0); + object = &variant->toObject(); + } else { + object = 0; + } - // Save key in memory pool. - // This MUST be done before adding the slot. - key = _stringStorage.save(); + for (; n; --n) { + err = readKey(); + if (err) + return err; - VariantSlot* slot = object->addSlot(_pool); - if (!slot) - return DeserializationError::NoMemory; + JsonString key = _stringStorage.str(); + TFilter memberFilter = filter[key.c_str()]; + VariantData * member; - slot->setKey(key); + if (memberFilter.allow()) { + ARDUINOJSON_ASSERT(object != 0); - member = slot->data(); - } else { - member = 0; - } + // Save key in memory pool. + // This MUST be done before adding the slot. + key = _stringStorage.save(); - err = parseVariant(member, memberFilter, nestingLimit.decrement()); - if (err) - return err; - } + VariantSlot * slot = object->addSlot(_pool); + if (!slot) + return DeserializationError::NoMemory; + + slot->setKey(key); + + member = slot->data(); + } else { + member = 0; + } - return DeserializationError::Ok; - } + err = parseVariant(member, memberFilter, nestingLimit.decrement()); + if (err) + return err; + } - DeserializationError::Code readKey() { - DeserializationError::Code err; - uint8_t code; + return DeserializationError::Ok; + } - err = readByte(code); - if (err) - return err; + DeserializationError::Code readKey() { + DeserializationError::Code err; + uint8_t code; - if ((code & 0xe0) == 0xa0) - return readString(code & 0x1f); + err = readByte(code); + if (err) + return err; - switch (code) { - case 0xd9: - return readString(); + if ((code & 0xe0) == 0xa0) + return readString(code & 0x1f); - case 0xda: - return readString(); + switch (code) { + case 0xd9: + return readString(); - case 0xdb: - return readString(); + case 0xda: + return readString(); - default: - return DeserializationError::InvalidInput; + case 0xdb: + return readString(); + + default: + return DeserializationError::InvalidInput; + } } - } - template - DeserializationError::Code skipExt() { - DeserializationError::Code err; - T size; + template + DeserializationError::Code skipExt() { + DeserializationError::Code err; + T size; - err = readInteger(size); - if (err) - return err; + err = readInteger(size); + if (err) + return err; - return skipBytes(size + 1U); - } + return skipBytes(size + 1U); + } - MemoryPool* _pool; - TReader _reader; - TStringStorage _stringStorage; - bool _foundSomething; + MemoryPool * _pool; + TReader _reader; + TStringStorage _stringStorage; + bool _foundSomething; }; ARDUINOJSON_END_PRIVATE_NAMESPACE @@ -567,19 +553,17 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE // Parses a MessagePack input and puts the result in a JsonDocument. // https://arduinojson.org/v6/api/msgpack/deserializemsgpack/ template -DeserializationError deserializeMsgPack(JsonDocument& doc, Args&&... args) { - using namespace detail; - return deserialize(doc, detail::forward(args)...); +DeserializationError deserializeMsgPack(JsonDocument & doc, Args &&... args) { + using namespace detail; + return deserialize(doc, detail::forward(args)...); } // Parses a MessagePack input and puts the result in a JsonDocument. // https://arduinojson.org/v6/api/msgpack/deserializemsgpack/ template -DeserializationError deserializeMsgPack(JsonDocument& doc, TChar* input, - Args&&... args) { - using namespace detail; - return deserialize(doc, input, - detail::forward(args)...); +DeserializationError deserializeMsgPack(JsonDocument & doc, TChar * input, Args &&... args) { + using namespace detail; + return deserialize(doc, input, detail::forward(args)...); } ARDUINOJSON_END_PUBLIC_NAMESPACE diff --git a/lib/ArduinoJson/src/ArduinoJson/Variant/VariantCompare.hpp b/lib/ArduinoJson/src/ArduinoJson/Variant/VariantCompare.hpp index bb60b8a4f..dde086206 100644 --- a/lib/ArduinoJson/src/ArduinoJson/Variant/VariantCompare.hpp +++ b/lib/ArduinoJson/src/ArduinoJson/Variant/VariantCompare.hpp @@ -20,188 +20,198 @@ template struct Comparer; template -struct Comparer::value>::type> - : ComparerBase { - T rhs; // TODO: store adapted string? - - explicit Comparer(T value) : rhs(value) {} - - CompareResult visitString(const char* lhs, size_t n) { - int i = stringCompare(adaptString(rhs), adaptString(lhs, n)); - if (i < 0) - return COMPARE_RESULT_GREATER; - else if (i > 0) - return COMPARE_RESULT_LESS; - else - return COMPARE_RESULT_EQUAL; - } - - CompareResult visitNull() { - if (adaptString(rhs).isNull()) - return COMPARE_RESULT_EQUAL; - else - return COMPARE_RESULT_DIFFER; - } +struct Comparer::value>::type> : ComparerBase { + T rhs; + + explicit Comparer(T value) + : rhs(value) { + } + + CompareResult visitString(const char * lhs, size_t n) { + int i = stringCompare(adaptString(rhs), adaptString(lhs, n)); + if (i < 0) + return COMPARE_RESULT_GREATER; + else if (i > 0) + return COMPARE_RESULT_LESS; + else + return COMPARE_RESULT_EQUAL; + } + + CompareResult visitNull() { + if (adaptString(rhs).isNull()) + return COMPARE_RESULT_EQUAL; + else + return COMPARE_RESULT_DIFFER; + } }; template -struct Comparer::value || - is_floating_point::value>::type> - : ComparerBase { - T rhs; +struct Comparer::value || is_floating_point::value>::type> : ComparerBase { + T rhs; - explicit Comparer(T value) : rhs(value) {} + explicit Comparer(T value) + : rhs(value) { + } - CompareResult visitFloat(JsonFloat lhs) { - return arithmeticCompare(lhs, rhs); - } + CompareResult visitFloat(JsonFloat lhs) { + return arithmeticCompare(lhs, rhs); + } - CompareResult visitSignedInteger(JsonInteger lhs) { - return arithmeticCompare(lhs, rhs); - } + CompareResult visitSignedInteger(JsonInteger lhs) { + return arithmeticCompare(lhs, rhs); + } - CompareResult visitUnsignedInteger(JsonUInt lhs) { - return arithmeticCompare(lhs, rhs); - } + CompareResult visitUnsignedInteger(JsonUInt lhs) { + return arithmeticCompare(lhs, rhs); + } - CompareResult visitBoolean(bool lhs) { - return visitUnsignedInteger(static_cast(lhs)); - } + CompareResult visitBoolean(bool lhs) { + return visitUnsignedInteger(static_cast(lhs)); + } }; struct NullComparer : ComparerBase { - CompareResult visitNull() { - return COMPARE_RESULT_EQUAL; - } + CompareResult visitNull() { + return COMPARE_RESULT_EQUAL; + } }; template <> struct Comparer : NullComparer { - explicit Comparer(decltype(nullptr)) : NullComparer() {} + explicit Comparer(decltype(nullptr)) + : NullComparer() { + } }; struct ArrayComparer : ComparerBase { - const CollectionData* _rhs; + const CollectionData * _rhs; - explicit ArrayComparer(const CollectionData& rhs) : _rhs(&rhs) {} + explicit ArrayComparer(const CollectionData & rhs) + : _rhs(&rhs) { + } - CompareResult visitArray(const CollectionData& lhs) { - if (JsonArrayConst(&lhs) == JsonArrayConst(_rhs)) - return COMPARE_RESULT_EQUAL; - else - return COMPARE_RESULT_DIFFER; - } + CompareResult visitArray(const CollectionData & lhs) { + if (JsonArrayConst(&lhs) == JsonArrayConst(_rhs)) + return COMPARE_RESULT_EQUAL; + else + return COMPARE_RESULT_DIFFER; + } }; struct ObjectComparer : ComparerBase { - const CollectionData* _rhs; + const CollectionData * _rhs; - explicit ObjectComparer(const CollectionData& rhs) : _rhs(&rhs) {} + explicit ObjectComparer(const CollectionData & rhs) + : _rhs(&rhs) { + } - CompareResult visitObject(const CollectionData& lhs) { - if (JsonObjectConst(&lhs) == JsonObjectConst(_rhs)) - return COMPARE_RESULT_EQUAL; - else - return COMPARE_RESULT_DIFFER; - } + CompareResult visitObject(const CollectionData & lhs) { + if (JsonObjectConst(&lhs) == JsonObjectConst(_rhs)) + return COMPARE_RESULT_EQUAL; + else + return COMPARE_RESULT_DIFFER; + } }; struct RawComparer : ComparerBase { - const char* _rhsData; - size_t _rhsSize; - - explicit RawComparer(const char* rhsData, size_t rhsSize) - : _rhsData(rhsData), _rhsSize(rhsSize) {} - - CompareResult visitRawJson(const char* lhsData, size_t lhsSize) { - size_t size = _rhsSize < lhsSize ? _rhsSize : lhsSize; - int n = memcmp(lhsData, _rhsData, size); - if (n < 0) - return COMPARE_RESULT_LESS; - else if (n > 0) - return COMPARE_RESULT_GREATER; - else - return COMPARE_RESULT_EQUAL; - } + const char * _rhsData; + size_t _rhsSize; + + explicit RawComparer(const char * rhsData, size_t rhsSize) + : _rhsData(rhsData) + , _rhsSize(rhsSize) { + } + + CompareResult visitRawJson(const char * lhsData, size_t lhsSize) { + size_t size = _rhsSize < lhsSize ? _rhsSize : lhsSize; + int n = memcmp(lhsData, _rhsData, size); + if (n < 0) + return COMPARE_RESULT_LESS; + else if (n > 0) + return COMPARE_RESULT_GREATER; + else + return COMPARE_RESULT_EQUAL; + } }; struct VariantComparer : ComparerBase { - const VariantData* rhs; - - explicit VariantComparer(const VariantData* value) : rhs(value) {} - - CompareResult visitArray(const CollectionData& lhs) { - ArrayComparer comparer(lhs); - return accept(comparer); - } - - CompareResult visitObject(const CollectionData& lhs) { - ObjectComparer comparer(lhs); - return accept(comparer); - } - - CompareResult visitFloat(JsonFloat lhs) { - Comparer comparer(lhs); - return accept(comparer); - } - - CompareResult visitString(const char* lhs, size_t) { - Comparer comparer(lhs); - return accept(comparer); - } - - CompareResult visitRawJson(const char* lhsData, size_t lhsSize) { - RawComparer comparer(lhsData, lhsSize); - return accept(comparer); - } - - CompareResult visitSignedInteger(JsonInteger lhs) { - Comparer comparer(lhs); - return accept(comparer); - } - - CompareResult visitUnsignedInteger(JsonUInt lhs) { - Comparer comparer(lhs); - return accept(comparer); - } - - CompareResult visitBoolean(bool lhs) { - Comparer comparer(lhs); - return accept(comparer); - } - - CompareResult visitNull() { - NullComparer comparer; - return accept(comparer); - } - - private: - template - CompareResult accept(TComparer& comparer) { - CompareResult reversedResult = variantAccept(rhs, comparer); - switch (reversedResult) { - case COMPARE_RESULT_GREATER: - return COMPARE_RESULT_LESS; - case COMPARE_RESULT_LESS: - return COMPARE_RESULT_GREATER; - default: - return reversedResult; - } - } + const VariantData * rhs; + + explicit VariantComparer(const VariantData * value) + : rhs(value) { + } + + CompareResult visitArray(const CollectionData & lhs) { + ArrayComparer comparer(lhs); + return accept(comparer); + } + + CompareResult visitObject(const CollectionData & lhs) { + ObjectComparer comparer(lhs); + return accept(comparer); + } + + CompareResult visitFloat(JsonFloat lhs) { + Comparer comparer(lhs); + return accept(comparer); + } + + CompareResult visitString(const char * lhs, size_t) { + Comparer comparer(lhs); + return accept(comparer); + } + + CompareResult visitRawJson(const char * lhsData, size_t lhsSize) { + RawComparer comparer(lhsData, lhsSize); + return accept(comparer); + } + + CompareResult visitSignedInteger(JsonInteger lhs) { + Comparer comparer(lhs); + return accept(comparer); + } + + CompareResult visitUnsignedInteger(JsonUInt lhs) { + Comparer comparer(lhs); + return accept(comparer); + } + + CompareResult visitBoolean(bool lhs) { + Comparer comparer(lhs); + return accept(comparer); + } + + CompareResult visitNull() { + NullComparer comparer; + return accept(comparer); + } + + private: + template + CompareResult accept(TComparer & comparer) { + CompareResult reversedResult = variantAccept(rhs, comparer); + switch (reversedResult) { + case COMPARE_RESULT_GREATER: + return COMPARE_RESULT_LESS; + case COMPARE_RESULT_LESS: + return COMPARE_RESULT_GREATER; + default: + return reversedResult; + } + } }; template -struct Comparer::value>::type> - : VariantComparer { - explicit Comparer(const T& value) - : VariantComparer(VariantAttorney::getData(value)) {} +struct Comparer::value>::type> : VariantComparer { + explicit Comparer(const T & value) + : VariantComparer(VariantAttorney::getData(value)) { + } }; template -CompareResult compare(ArduinoJson::JsonVariantConst lhs, const T& rhs) { - Comparer comparer(rhs); - return variantAccept(VariantAttorney::getData(lhs), comparer); +CompareResult compare(ArduinoJson::JsonVariantConst lhs, const T & rhs) { + Comparer comparer(rhs); + return variantAccept(VariantAttorney::getData(lhs), comparer); } ARDUINOJSON_END_PRIVATE_NAMESPACE diff --git a/mock-api/server.js b/mock-api/server.js index 0c066335c..df2096afb 100644 --- a/mock-api/server.js +++ b/mock-api/server.js @@ -18,6 +18,9 @@ const delay = (ms) => new Promise((res) => setTimeout(res, ms)); const API_ENDPOINT_ROOT = '/api/'; const REST_ENDPOINT_ROOT = '/rest/'; +// network poll +let countWifiScanPoll = 0; + // LOG const LOG_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'logSettings'; log_settings = { @@ -27,7 +30,7 @@ log_settings = { }; const FETCH_LOG_ENDPOINT = REST_ENDPOINT_ROOT + 'fetchLog'; -const fetch_log = { +let fetch_log = { events: [ { t: '000+00:00:00.001', @@ -1780,26 +1783,26 @@ const emsesp_devicedata_99 = { }; // CUSTOM ENTITIES -let emsesp_entities = [ +let emsesp_entities = { // entities: [] - // entities: [ - { - id: 0, - device_id: 8, - type_id: 24, - offset: 0, - factor: 1, - name: 'boiler_flowtemp', - uom: 1, - value_type: 1, - writeable: true - } -]; + entities: [ + { + id: 0, + device_id: 8, + type_id: 24, + offset: 0, + factor: 1, + name: 'boiler_flowtemp', + uom: 1, + value_type: 1, + writeable: true + } + ] +}; // SCHEDULE -let emsesp_schedule = - // schedule: [ - [ +let emsesp_schedule = { + schedule: [ { id: 1, active: true, @@ -1836,7 +1839,8 @@ let emsesp_schedule = value: '', name: 'auto_restart' } - ]; + ] +}; // CUSTOMIZATIONS const emsesp_deviceentities_1 = [{}]; @@ -1993,16 +1997,13 @@ const emsesp_deviceentities_4 = [ ]; // LOG -rest_server.get(FETCH_LOG_ENDPOINT, (req, res) => { - const encoded = msgpack.encode(fetch_log); - console.log('fetchlog'); - res.write(encoded, 'binary'); - res.end(null, 'binary'); +rest_server.post(FETCH_LOG_ENDPOINT, (req, res) => { + console.log('command: fetchLog'); + res.sendStatus(200); }); rest_server.get(LOG_SETTINGS_ENDPOINT, (req, res) => { res.json(log_settings); }); -// TODO do we need to send back here a res.SendStatus(200) ? rest_server.post(LOG_SETTINGS_ENDPOINT, (req, res) => { log_settings = req.body; console.log(JSON.stringify(log_settings)); @@ -2019,14 +2020,21 @@ rest_server.get(NETWORK_SETTINGS_ENDPOINT, (req, res) => { rest_server.post(NETWORK_SETTINGS_ENDPOINT, (req, res) => { network_settings = req.body; console.log(JSON.stringify(network_settings)); - // TODO do we need to send back here a res.SendStatus(200) ? res.sendStatus(200); }); rest_server.get(LIST_NETWORKS_ENDPOINT, (req, res) => { + countWifiScanPoll = 0; // stop the poll res.json(list_networks); }); rest_server.get(SCAN_NETWORKS_ENDPOINT, (req, res) => { - res.sendStatus(202); // reboot required + console.log('scan networks'); + if (countWifiScanPoll++ === 2) { + console.log('done, have list'); + res.sendStatus(200); // ready to send list + } else { + console.log('...waiting #' + countWifiScanPoll); + res.sendStatus(202); // waiting.... + } }); // AP @@ -2050,8 +2058,7 @@ rest_server.get(OTA_SETTINGS_ENDPOINT, (req, res) => { rest_server.post(OTA_SETTINGS_ENDPOINT, (req, res) => { ota_settings = req.body; console.log(JSON.stringify(ota_settings)); - res.json(ota_settings); - // TODO do we need to send back a res.sendStatus(200); ? + res.sendStatus(200); }); // MQTT @@ -2061,8 +2068,7 @@ rest_server.get(MQTT_SETTINGS_ENDPOINT, (req, res) => { rest_server.post(MQTT_SETTINGS_ENDPOINT, (req, res) => { mqtt_settings = req.body; console.log(JSON.stringify(mqtt_settings)); - res.json(mqtt_settings); - // TODO do we need to send back a res.sendStatus(200); ? + res.sendStatus(200); }); rest_server.get(MQTT_STATUS_ENDPOINT, (req, res) => { res.json(mqtt_status); @@ -2075,9 +2081,7 @@ rest_server.get(NTP_SETTINGS_ENDPOINT, (req, res) => { rest_server.post(NTP_SETTINGS_ENDPOINT, (req, res) => { ntp_settings = req.body; console.log(JSON.stringify(ntp_settings)); - // TODO do we need to send back a res.sendStatus(200); ? - - res.json(ntp_settings); + res.sendStatus(200); }); rest_server.get(NTP_STATUS_ENDPOINT, (req, res) => { res.json(ntp_status); @@ -2096,9 +2100,7 @@ rest_server.get(SECURITY_SETTINGS_ENDPOINT, (req, res) => { rest_server.post(SECURITY_SETTINGS_ENDPOINT, (req, res) => { security_settings = req.body; console.log(JSON.stringify(security_settings)); - // TODO do we need to send back a res.sendStatus(200); ? - - res.json(security_settings); + res.sendStatus(200); }); rest_server.get(FEATURES_ENDPOINT, (req, res) => { res.json(features); @@ -2118,9 +2120,7 @@ rest_server.post(UPLOAD_FILE_ENDPOINT, (req, res) => { }); rest_server.post(SIGN_IN_ENDPOINT, (req, res) => { console.log('Signed in as ' + req.body.username); - // TODO do we need to send back a res.sendStatus(200); ? - - res.json(signin); + res.json(signin); // watch out, this has a return value }); rest_server.get(GENERATE_TOKEN_ENDPOINT, (req, res) => { res.json(generate_token); @@ -2693,7 +2693,7 @@ rest_server.get(SCHEDULE_ENDPOINT, (req, res) => { const ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'entities'; rest_server.get(ENTITIES_ENDPOINT, (req, res) => { - console.log('Sending Entities data'); + console.log('Sending Custom Entities data'); res.json(emsesp_entities); }); @@ -2734,5 +2734,5 @@ rest_server.get(ES_LOG_ENDPOINT, function (req, res) { log_index = 0; } fetch_log.events.push(data); // append to buffer - }, 1000); + }, 3000); }); diff --git a/src/web/WebLogService.cpp b/src/web/WebLogService.cpp index 5848a50d2..1800f0c25 100644 --- a/src/web/WebLogService.cpp +++ b/src/web/WebLogService.cpp @@ -1,7 +1,7 @@ /* * EMS-ESP - https://github.com/emsesp/EMS-ESP * Copyright 2020-2023 Paul Derbyshire - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -24,25 +24,16 @@ namespace emsesp { WebLogService::WebLogService(AsyncWebServer * server, SecurityManager * securityManager) : events_(EVENT_SOURCE_LOG_PATH) - , setValues_(LOG_SETTINGS_PATH, std::bind(&WebLogService::setValues, this, _1, _2), 256) { // for POSTS - + , setValues_(LOG_SETTINGS_PATH, std::bind(&WebLogService::setValues, this, _1, _2), 256) { events_.setFilter(securityManager->filterRequest(AuthenticationPredicates::IS_ADMIN)); - server->addHandler(&events_); - server->on(EVENT_SOURCE_LOG_PATH, HTTP_GET, std::bind(&WebLogService::forbidden, this, _1)); - - // for bring back the whole log - server->on(FETCH_LOG_PATH, HTTP_GET, std::bind(&WebLogService::fetchLog, this, _1)); + server->on(LOG_SETTINGS_PATH, HTTP_GET, std::bind(&WebLogService::getValues, this, _1)); // get settings - // get when page is loaded - server->on(LOG_SETTINGS_PATH, HTTP_GET, std::bind(&WebLogService::getValues, this, _1)); + // for bring back the whole log - is a command, hence a POST + server->on(FETCH_LOG_PATH, HTTP_POST, std::bind(&WebLogService::fetchLog, this, _1)); - // for setting a level server->addHandler(&setValues_); -} - -void WebLogService::forbidden(AsyncWebServerRequest * request) { - request->send(403); + server->addHandler(&events_); } // start the log service with INFO level @@ -211,6 +202,7 @@ void WebLogService::transmit(const QueuedLogMessage & message) { } // send the complete log buffer to the API, not filtering on log level +// done by resetting the pointer void WebLogService::fetchLog(AsyncWebServerRequest * request) { log_message_id_tail_ = 0; request->send(200); @@ -224,6 +216,8 @@ void WebLogService::setValues(AsyncWebServerRequest * request, JsonVariant & jso auto && body = json.as(); + // TODO refactor into one load and one save + uuid::log::Level level = body["level"]; log_level(level); diff --git a/src/web/WebLogService.h b/src/web/WebLogService.h index 1f069f922..aa852fabb 100644 --- a/src/web/WebLogService.h +++ b/src/web/WebLogService.h @@ -58,7 +58,6 @@ class WebLogService : public uuid::log::Handler { const std::shared_ptr content_; // Log message content }; - void forbidden(AsyncWebServerRequest * request); void transmit(const QueuedLogMessage & message); void fetchLog(AsyncWebServerRequest * request); void getValues(AsyncWebServerRequest * request); diff --git a/src/web/WebSchedulerService.cpp b/src/web/WebSchedulerService.cpp index 9dd8d25f6..22ffed2f4 100644 --- a/src/web/WebSchedulerService.cpp +++ b/src/web/WebSchedulerService.cpp @@ -50,7 +50,7 @@ void WebScheduler::read(WebScheduler & webScheduler, JsonObject & root) { } } -// call on initialization and also when the Scheduile web page is updated +// call on initialization and also when the Scheduile web page is saved // this loads the data into the internal class StateUpdateResult WebScheduler::update(JsonObject & root, WebScheduler & webScheduler) { #ifdef EMSESP_STANDALONE