alova - refactor wifi scan

This commit is contained in:
Proddy
2023-06-18 10:46:50 +02:00
parent ed55a96b80
commit b1d666d7b9
14 changed files with 58 additions and 60 deletions

View File

@@ -35,9 +35,10 @@ export const alovaInstance = createAlova({
responded: {
onSuccess: async (response) => {
if (response.status === 202) {
throw new Error('Wait');
} else if (response.status === 205) {
// if (response.status === 202) {
// throw new Error('Wait'); // wifi scan in progress
// } else
if (response.status === 205) {
throw new Error('Reboot required');
} else if (response.status === 400) {
throw new Error('Request Failed');

View File

@@ -4,7 +4,10 @@ import type { WiFiNetworkList, NetworkSettings, NetworkStatus } from 'types';
export const readNetworkStatus = () => alovaInstance.Get<NetworkStatus>('/rest/networkStatus');
export const scanNetworks = () => alovaInstance.Get('/rest/scanNetworks');
export const listNetworks = () => alovaInstance.Get<WiFiNetworkList>('/rest/listNetworks');
export const listNetworks = () =>
alovaInstance.Get<WiFiNetworkList>('/rest/listNetworks', {
name: 'listNetworks'
});
export const readNetworkSettings = () =>
alovaInstance.Get<NetworkSettings>('/rest/networkSettings', { name: 'networkSettings' });
export const updateNetworkSettings = (wifiSettings: NetworkSettings) =>

View File

@@ -3,7 +3,7 @@ import type { AxiosPromise } from 'axios';
import type { SecuritySettings, Token } from 'types';
// TODO move to Alova
// TODO move these 3 to Alova
export function readSecuritySettings(): AxiosPromise<SecuritySettings> {
return AXIOS.get('/securitySettings');
}

View File

@@ -4,10 +4,8 @@ import type { AxiosPromise } from 'axios';
import type { OTASettings, SystemStatus, LogSettings } from 'types';
export const readSystemStatus = (timeout?: number) =>
alovaInstance.Get<SystemStatus>('/rest/systemStatus', {
params: { timeout }
});
// SystemStatus - also used to ping in Restart monitor
export const readSystemStatus = () => alovaInstance.Get<SystemStatus>('/rest/systemStatus');
// commands
export const restart = () => alovaInstance.Post('/rest/restart');
@@ -23,5 +21,6 @@ export const readLogSettings = () => alovaInstance.Get<LogSettings>(`/rest/logSe
export const updateLogSettings = (data: any) => alovaInstance.Post('/rest/logSettings', data);
export const fetchLog = () => alovaInstance.Post('/rest/fetchLog');
// TODO fileupload move to Alova
export const uploadFile = (file: File, config?: FileUploadConfig): AxiosPromise<void> =>
startUploadFile('/uploadFile', file, config);

View File

@@ -1,8 +1,8 @@
import PermScanWifiIcon from '@mui/icons-material/PermScanWifi';
import { Button } from '@mui/material';
import { useRequest } from 'alova';
import { useState, useCallback, useRef } from 'react';
import { toast } from 'react-toastify';
// eslint-disable-next-line import/named
import { updateState, useRequest } from 'alova';
import { useState, useRef } from 'react';
import WiFiNetworkSelector from './WiFiNetworkSelector';
import type { FC } from 'react';
@@ -15,48 +15,37 @@ const NUM_POLLS = 10;
const POLLING_FREQUENCY = 1000;
const WiFiNetworkScanner: FC = () => {
const { LL } = useI18nContext();
const pollCount = useRef(0);
const { LL } = useI18nContext();
const [errorMessage, setErrorMessage] = useState<string>();
const { data: networkList, send: getNetworkList } = useRequest(NetworkApi.listNetworks, {
const { send: scanNetworks, onComplete: onCompleteScanNetworks } = useRequest(NetworkApi.scanNetworks); // is called on page load to start network scan
const {
data: networkList,
send: getNetworkList,
onSuccess: onSuccessNetworkList
} = useRequest(NetworkApi.listNetworks, {
immediate: false
});
const {
send: scanNetworks,
onSuccess: onSuccessScanNetworks,
onError: onErrorScanNetworks
} = useRequest(NetworkApi.scanNetworks);
const finishedWithError = useCallback((message: string) => {
toast.error(message);
setErrorMessage(message);
pollCount.current = 0;
}, []);
onErrorScanNetworks((event) => {
console.log('onErrorScanNetworks'); // TODO fix
if (event.error?.message === 'Wait') {
// 202
console.log('not ready...: ', event.error?.message); // TODO fix
onSuccessNetworkList((event) => {
if (!event.data) {
const completedPollCount = pollCount.current + 1;
if (completedPollCount < NUM_POLLS) {
pollCount.current = completedPollCount;
setTimeout(scanNetworks, POLLING_FREQUENCY);
setTimeout(getNetworkList, POLLING_FREQUENCY);
} else {
finishedWithError(LL.PROBLEM_LOADING());
setErrorMessage(LL.PROBLEM_LOADING());
pollCount.current = 0;
}
} else {
finishedWithError(LL.PROBLEM_LOADING());
}
});
onSuccessScanNetworks(() => {
console.log('onCompleteScanNetworks'); // TODO fix
onCompleteScanNetworks(() => {
pollCount.current = 0;
void getNetworkList(); // fetch the list
setErrorMessage(undefined);
updateState('listNetworks', () => undefined);
void getNetworkList();
});
const renderNetworkScanner = () => {

View File

@@ -23,6 +23,7 @@ import { useRest } from 'utils';
import { createUserValidator } from 'validators';
const ManageUsersForm: FC = () => {
// TODO move to Alova
const { loadData, saving, data, setData, saveData, errorMessage } = useRest<SecuritySettings>({
read: SecurityApi.readSecuritySettings,
update: SecurityApi.updateSecuritySettings

View File

@@ -18,6 +18,7 @@ const SecuritySettingsForm: FC = () => {
const { LL } = useI18nContext();
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
// TODO move to Alova
const { loadData, saving, data, setData, origData, dirtyFlags, blocker, setDirtyFlags, saveData, errorMessage } =
useRest<SecuritySettings>({
read: SecurityApi.readSecuritySettings,

View File

@@ -12,7 +12,7 @@ import { useI18nContext } from 'i18n/i18n-react';
import * as EMSESP from 'project/api';
interface UploadFileProps {
// TODO fileupload upload move to alova
// TODO fileupload move to alova
uploadGeneralFile: (file: File, config?: FileUploadConfig) => AxiosPromise<void>;
}

View File

@@ -8,7 +8,6 @@ import { FormLoader } from 'components';
import { useI18nContext } from 'i18n/i18n-react';
const RESTART_TIMEOUT = 2 * 60 * 1000;
const POLL_TIMEOUT = 2000;
const POLL_INTERVAL = 5000;
const RestartMonitor: FC = () => {
@@ -17,14 +16,15 @@ const RestartMonitor: FC = () => {
const { LL } = useI18nContext();
const { send: readSystemStatus } = useRequest((timeout) => SystemApi.readSystemStatus(timeout), {
const { send: readSystemStatus } = useRequest(SystemApi.readSystemStatus(), {
force: true,
immediate: false
});
const timeoutAt = useRef(new Date().getTime() + RESTART_TIMEOUT);
const poll = useRef(async () => {
try {
await readSystemStatus(POLL_TIMEOUT);
await readSystemStatus();
document.location.href = '/fileUpdated';
} catch (error) {
if (new Date().getTime() < timeoutAt.current) {

View File

@@ -73,7 +73,7 @@ const SystemStatusForm: FC = () => {
immediate: false
});
const { data: data, send: loadData, error } = useRequest(SystemApi.readSystemStatus);
const { data: data, send: loadData, error } = useRequest(SystemApi.readSystemStatus, { force: true });
useEffect(() => {
void axios.get(VERSIONCHECK_ENDPOINT).then((response) => {

View File

@@ -184,9 +184,7 @@ const SettingsEntities: FC = () => {
}
function showHex(value: number, digit: number) {
return digit === 4
? '0x' + ('000' + value.toString(16).toUpperCase()).slice(-4)
: '0x' + ('0' + value.toString(16).toUpperCase()).slice(-2);
return '0x' + value.toString(16).toUpperCase().padStart(digit, '0');
}
const renderEntity = () => {
@@ -212,7 +210,7 @@ const SettingsEntities: FC = () => {
<Row key={ei.name} item={ei} onClick={() => editEntityItem(ei)}>
<Cell>{ei.name}</Cell>
<Cell>{showHex(ei.device_id as number, 2)}</Cell>
<Cell>{showHex(ei.type_id as number, 4)}</Cell>
<Cell>{showHex(ei.type_id as number, 3)}</Cell>
<Cell>{ei.offset}</Cell>
<Cell>{formatValue(ei.value, ei.uom)}</Cell>
</Row>

View File

@@ -58,8 +58,8 @@ const SettingsEntitiesDialog = ({
// convert to hex strings straight away
setEditItem({
...selectedItem,
device_id: selectedItem.device_id.toString(16).toUpperCase().slice(-2),
type_id: selectedItem.type_id.toString(16).toUpperCase().slice(-4)
device_id: selectedItem.device_id.toString(16).toUpperCase(),
type_id: selectedItem.type_id.toString(16).toUpperCase()
});
}
}, [open, selectedItem]);

View File

@@ -12,11 +12,12 @@ WiFiScanner::WiFiScanner(AsyncWebServer * server, SecurityManager * securityMana
};
void WiFiScanner::scanNetworks(AsyncWebServerRequest * request) {
request->send(202); // special code to indicate scan in progress
if (WiFi.scanComplete() != -1) {
WiFi.scanDelete();
WiFi.scanNetworks(true);
}
request->send(202); // special code to indicate scan in progress
}
void WiFiScanner::listNetworks(AsyncWebServerRequest * request) {

View File

@@ -271,7 +271,8 @@ const FACTORY_RESET_ENDPOINT = REST_ENDPOINT_ROOT + 'factoryReset';
const UPLOAD_FILE_ENDPOINT = REST_ENDPOINT_ROOT + 'uploadFile';
const SIGN_IN_ENDPOINT = REST_ENDPOINT_ROOT + 'signIn';
const GENERATE_TOKEN_ENDPOINT = REST_ENDPOINT_ROOT + 'generateToken';
const system_status = {
let system_status = {
emsesp_version: '3.6.0-demo',
esp_platform: 'ESP32',
max_alloc_heap: 89,
@@ -2023,19 +2024,20 @@ rest_server.post(NETWORK_SETTINGS_ENDPOINT, (req, res) => {
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) => {
console.log('scan networks');
if (countWifiScanPoll++ === 2) {
if (countWifiScanPoll++ === 4) {
console.log('done, have list');
res.sendStatus(200); // ready to send list
res.json(list_networks); // send list
} else {
console.log('...waiting #' + countWifiScanPoll);
res.sendStatus(202); // waiting....
res.sendStatus(200); // waiting....
}
});
// TODO should be a post as its a command?
rest_server.get(SCAN_NETWORKS_ENDPOINT, (req, res) => {
console.log('start scan networks');
countWifiScanPoll = 0; // stop the poll
res.sendStatus(200); // always 202, poll for list
});
// AP
rest_server.get(AP_SETTINGS_ENDPOINT, (req, res) => {
@@ -2092,6 +2094,9 @@ rest_server.post(TIME_ENDPOINT, (req, res) => {
// SYSTEM
rest_server.get(SYSTEM_STATUS_ENDPOINT, (req, res) => {
console.log('get systemStatus');
// create some random data to see if caching works
system_status.fs_used = Math.floor(Math.random() * (Math.floor(200) - 100) + 100);
res.json(system_status);
});
rest_server.get(SECURITY_SETTINGS_ENDPOINT, (req, res) => {