optimize endpoints, so re-use where possible

This commit is contained in:
proddy
2024-09-13 10:03:11 +02:00
parent 63a3152b91
commit 191edffe3c
23 changed files with 192 additions and 428 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -307,11 +307,10 @@ const mqtt_status = {
};
// STATUS
const SYSTEM_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'systemStatus';
const ACTIVITY_ENDPOINT = REST_ENDPOINT_ROOT + 'activity';
// SETTINGS
const HARDWARE_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'hardwareStatus';
const SYSTEM_STATUS_ENDPOINT = REST_ENDPOINT_ROOT + 'systemStatus';
const SECURITY_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'securitySettings';
// SYSTEM SIGNIN
@@ -322,8 +321,23 @@ const GENERATE_TOKEN_ENDPOINT = REST_ENDPOINT_ROOT + 'generateToken';
const VERSION = '3.7.0-dev.0';
// const VERSION = '3.6.4';
let hardware_status = {
let system_status = {
emsesp_version: VERSION,
bus_status: 0,
// status: 2,
uptime: 77186,
bus_uptime: 77121,
num_devices: 2,
num_sensors: 1,
num_analogs: 1,
free_heap: 143,
ntp_status: 2,
mqtt_status: true,
ap_status: false,
network_status: 3, // wifi connected
// network_status: 10, // ethernet connected
// network_status: 6, // wifi disconnected
wifi_rssi: -41,
esp_platform: 'ESP32S3',
build_flags: 'DEMO',
cpu_type: 'ESP32-S3',
@@ -331,7 +345,6 @@ let hardware_status = {
cpu_cores: 2,
cpu_freq_mhz: 240,
max_alloc_heap: 191,
free_heap: 211,
arduino_version: 'ESP32 Arduino v2.0.17',
sdk_version: 'v4.4.7-dirty',
partition: 'app0',
@@ -347,30 +360,11 @@ let hardware_status = {
psram_size: 8189,
free_psram: 8166,
has_loader: true,
// model: ''
model: 'BBQKees Electronics EMS Gateway E32 V2 (E32 V2.0 P3/2024011)',
model: '',
// model: 'BBQKees Electronics EMS Gateway E32 V2 (E32 V2.0 P3/2024011)',
status: 'downloading'
};
const system_status = {
emsesp_version: VERSION,
status: 0,
// status: 2,
uptime: 77186,
bus_uptime: 77121,
num_devices: 2,
num_sensors: 1,
num_analogs: 1,
free_heap: 143,
ntp_status: 2,
mqtt_status: true,
ap_status: false,
network_status: 3, // wifi connected
// network_status: 10, // ethernet connected
// network_status: 6, // wifi disconnected
wifi_rssi: -41
};
let security_settings = {
jwt_secret: 'naughty!',
users: [
@@ -402,7 +396,6 @@ const generate_token = { token: '1234' };
const EMSESP_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'settings';
const EMSESP_CORE_DATA_ENDPOINT = REST_ENDPOINT_ROOT + 'coreData';
const EMSESP_SENSOR_DATA_ENDPOINT = REST_ENDPOINT_ROOT + 'sensorData';
const EMSESP_DEVICES_ENDPOINT = REST_ENDPOINT_ROOT + 'devices';
const EMSESP_DEVICEDATA_ENDPOINT1 = REST_ENDPOINT_ROOT + 'deviceData';
const EMSESP_DEVICEDATA_ENDPOINT2 = REST_ENDPOINT_ROOT + 'deviceData/:id?';
@@ -423,13 +416,9 @@ const EMSESP_RESET_CUSTOMIZATIONS_ENDPOINT =
const EMSESP_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'schedule';
const EMSESP_CUSTOMENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'customEntities';
const EMSESP_MODULES_ENDPOINT = REST_ENDPOINT_ROOT + 'modules';
const EMSESP_EXPORT_DATA_ENDPOINT = REST_ENDPOINT_ROOT + 'exportData';
// these are used in the API calls only
const EMSESP_GET_SETTINGS_ENDPOINT = REST_ENDPOINT_ROOT + 'getSettings';
const EMSESP_GET_CUSTOMIZATIONS_ENDPOINT = REST_ENDPOINT_ROOT + 'getCustomizations';
const EMSESP_GET_ENTITIES_ENDPOINT = REST_ENDPOINT_ROOT + 'getEntities';
const EMSESP_GET_SCHEDULE_ENDPOINT = REST_ENDPOINT_ROOT + 'getSchedule';
const EMSESP_SYSTEM_INFO_ENDPOINT = API_ENDPOINT_ROOT + 'system/info';
const emsesp_info = {
@@ -634,74 +623,6 @@ let settings = {
modbus_timeout: 10000
};
const emsesp_devices = {
devices: [
{
i: 2,
s: 'RC20',
t: 5,
tn: 'Thermostat',
url: 'thermostat'
},
{
i: 3,
s: 'Buderus GB125',
t: 5,
tn: 'Boiler',
url: 'boiler'
},
{
i: 4,
s: 'Moduline 1000',
t: 5,
tn: 'Thermostat',
url: 'thermostat'
},
{
i: 5,
s: 'MM10',
t: 7,
tn: 'Mixer Module',
url: 'mixer'
},
{
i: 6,
s: 'SM10',
t: 8,
tn: 'Solar Module',
url: 'solar'
},
{
i: 7,
s: 'Trendline HRC30/Generic Heatronic 3',
t: 4,
tn: 'Boiler',
url: 'boiler'
},
{
i: 8,
s: 'Bosch Compress 7000i AW Heat Pump',
t: 5,
tn: 'Boiler/HP',
url: 'boiler'
},
{
i: 9,
s: 'RC100H',
t: 6,
tn: 'Thermostat',
url: 'thermostat'
},
{
i: 10,
s: 'RC310',
t: 6,
tn: 'Thermostat',
url: 'thermostat'
}
]
};
const emsesp_coredata = {
connected: true,
// connected: false,
@@ -716,7 +637,8 @@ const emsesp_coredata = {
d: 8,
p: 123,
v: '06.01',
e: 69
e: 69,
url: 'boiler'
},
{
id: 3,
@@ -727,7 +649,8 @@ const emsesp_coredata = {
d: 8,
p: 123,
v: '06.01',
e: 73
e: 73,
url: 'boiler'
},
{
id: 1,
@@ -738,7 +661,8 @@ const emsesp_coredata = {
d: 24,
p: 86,
v: '04.01',
e: 57
e: 57,
url: 'thermostat'
},
{
id: 2,
@@ -749,7 +673,8 @@ const emsesp_coredata = {
d: 23,
p: 77,
v: '03.03',
e: 6
e: 6,
url: 'thermostat'
},
{
id: 4,
@@ -760,7 +685,8 @@ const emsesp_coredata = {
d: 16,
p: 165,
v: '04.01',
e: 3
e: 3,
url: 'thermostat'
},
{
id: 5,
@@ -782,7 +708,8 @@ const emsesp_coredata = {
d: 48,
p: 73,
v: '01.02',
e: 22
e: 22,
url: 'solar'
},
{
id: 8,
@@ -793,7 +720,8 @@ const emsesp_coredata = {
d: 8,
p: 172,
v: '01.20',
e: 152
e: 152,
url: 'boiler'
},
{
id: 9,
@@ -804,7 +732,8 @@ const emsesp_coredata = {
d: 56,
p: 200,
v: '40.07',
e: 4
e: 4,
url: 'thermostat'
},
{
id: 10,
@@ -815,7 +744,8 @@ const emsesp_coredata = {
d: 16,
p: 158,
v: '73.03',
e: 63
e: 63,
url: 'thermostat'
}
]
};
@@ -3871,10 +3801,26 @@ let emsesp_modules = {
};
// CUSTOMIZATION
const emsesp_deviceentities_1 = [
{ v: 'dummy value', n: 'dummy name', id: 'dummy', m: 0, w: false }
const dummy_deviceentities = [
{
v: 'unknown',
n: 'no entities for this device',
id: 'unknown',
m: 0,
w: false
}
];
// no data for these
const emsesp_deviceentities_1 = dummy_deviceentities;
const emsesp_deviceentities_3 = dummy_deviceentities;
const emsesp_deviceentities_5 = dummy_deviceentities;
const emsesp_deviceentities_6 = dummy_deviceentities;
const emsesp_deviceentities_8 = dummy_deviceentities;
const emsesp_deviceentities_9 = dummy_deviceentities;
const emsesp_deviceentities_10 = dummy_deviceentities;
const emsesp_deviceentities_none = dummy_deviceentities;
const emsesp_deviceentities_2 = [
{
v: '(0)',
@@ -3916,10 +3862,6 @@ const emsesp_deviceentities_2 = [
}
];
const emsesp_deviceentities_3 = [
{ v: 'dummy value', n: 'dummy name', id: 'dummy', m: 0, w: false }
];
const emsesp_deviceentities_4 = [
{
v: 16,
@@ -3943,13 +3885,6 @@ const emsesp_deviceentities_4 = [
w: true
}
];
const emsesp_deviceentities_5 = [
{ v: 'dummy value', n: 'dummy name', id: 'dummy', m: 0, w: false }
];
const emsesp_deviceentities_6 = [
{ v: 'dummy value', n: 'dummy name', id: 'dummy', m: 0, w: false }
];
const emsesp_deviceentities_7 = [
{ u: 0, n: '!reset', id: 'reset', m: 8, w: false },
@@ -4076,22 +4011,6 @@ const emsesp_deviceentities_7 = [
{ v: 102151, n: 'dhw active time', id: 'dhw/workm', m: 0, w: false }
];
const emsesp_deviceentities_8 = [
{ v: 'dummy value', n: 'dummy name', id: 'dummy', m: 0, w: false }
];
const emsesp_deviceentities_9 = [
{ v: 'dummy value', n: 'dummy name', id: 'dummy', m: 0, w: false }
];
const emsesp_deviceentities_10 = [
{ v: 'dummy value', n: 'dummy name', id: 'dummy', m: 0, w: false }
];
const emsesp_deviceentities_none = [
{ v: 'dummy value', n: 'dummy name', id: 'dummy', m: 0, w: false }
];
// END DATA
// LOG
@@ -4160,22 +4079,21 @@ router
// SYSTEM and SETTINGS
router
.get(SYSTEM_STATUS_ENDPOINT, () => system_status)
.get(ACTIVITY_ENDPOINT, () => activity)
.get(HARDWARE_STATUS_ENDPOINT, () => {
.get(SYSTEM_STATUS_ENDPOINT, () => {
if (countHardwarePoll === 0) {
console.log('Resetting hardware count...');
}
if (countHardwarePoll >= 2) {
countHardwarePoll = 0;
hardware_status.status = 'ready';
system_status.status = 'ready';
}
console.log('Hardware count ' + countHardwarePoll + ' of 2');
countHardwarePoll++;
return hardware_status;
return system_status;
})
.get(SECURITY_SETTINGS_ENDPOINT, () => security_settings)
.post(SECURITY_SETTINGS_ENDPOINT, async (request: any) => {
@@ -4289,11 +4207,6 @@ router
emsesp_sensordata.ts[2].t = Math.floor(Math.random() * 100);
return emsesp_sensordata;
})
.get(EMSESP_DEVICES_ENDPOINT, () => {
// sort by type
const sorted_devices = emsesp_devices.devices.sort((a, b) => a.t - b.t);
return { devices: sorted_devices };
})
.get(EMSESP_DEVICEDATA_ENDPOINT1, (request) =>
request.query.id ? deviceData(Number(request.query.id)) : status(404)
)
@@ -4501,11 +4414,11 @@ router
})
// Settings - board profile
.post(EMSESP_BOARDPROFILE_ENDPOINT, async (request: any) => {
const content = await request.json();
const board_profile = content.code;
.get(EMSESP_BOARDPROFILE_ENDPOINT, (request) => {
const board_profile = request.query.boardProfile;
const data = {
board_profile: settings.board_profile,
led_gpio: settings.led_gpio,
dallas_gpio: settings.dallas_gpio,
rx_gpio: settings.rx_gpio,
@@ -4629,15 +4542,32 @@ router
data.eth_clock_mode = 0;
}
console.log('board profile saved', data);
data.board_profile =
typeof board_profile === 'string' ? board_profile : settings.board_profile;
console.log('board profile for ' + board_profile + ' fetched: ', data);
return data;
})
// Download Settings
.get(EMSESP_GET_SETTINGS_ENDPOINT, () => emsesp_info)
.get(EMSESP_GET_CUSTOMIZATIONS_ENDPOINT, () => emsesp_deviceentities_1)
.get(EMSESP_GET_ENTITIES_ENDPOINT, () => emsesp_customentities)
.get(EMSESP_GET_SCHEDULE_ENDPOINT, () => emsesp_schedule)
.get(EMSESP_EXPORT_DATA_ENDPOINT, (request) => {
const type = request.query.type;
console.log('exporting ' + type + ' data');
switch (type) {
case 'settings':
return emsesp_info;
case 'customizations':
return emsesp_deviceentities_2; // fixed for one device
case 'entities':
return emsesp_customentities;
case 'schedule':
return emsesp_schedule;
case 'modules':
return emsesp_modules;
default:
return status(404);
}
})
// upload URL
.post('/rest/uploadURL', () => {
@@ -4673,7 +4603,7 @@ router
}
if (cmd === 'restart') {
console.log('restarting...');
hardware_status.status = 'restarting';
system_status.status = 'restarting';
countHardwarePoll = 0;
return status(200);
}

View File

@@ -1128,8 +1128,6 @@ bool System::check_restore() {
bool reboot_required = false;
#ifndef EMSESP_STANDALONE
// see if we have a temp file, if so try and read it
// TODO find a nicer way to see if a file exists without reporting an error, like using lfs_stat. exists() uses open so same problem.
File new_file = LittleFS.open(TEMP_FILENAME_PATH);
if (new_file) {
JsonDocument jsonDocument;

View File

@@ -29,9 +29,6 @@ WebCustomEntityService::WebCustomEntityService(AsyncWebServer * server, FS * fs,
securityManager,
AuthenticationPredicates::IS_AUTHENTICATED)
, _fsPersistence(WebCustomEntity::read, WebCustomEntity::update, this, fs, EMSESP_CUSTOMENTITY_FILE) {
server->on(EMSESP_GET_ENTITIES_PATH,
HTTP_GET,
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { getEntities(request); }, AuthenticationPredicates::IS_ADMIN));
}
// load the settings when the service starts
@@ -711,17 +708,4 @@ void WebCustomEntityService::test() {
}
#endif
// return entities as a json object
void WebCustomEntityService::getEntities(AsyncWebServerRequest * request) {
auto * response = new AsyncJsonResponse(false);
JsonObject root = response->getRoot();
root["type"] = "entities";
System::extractSettings(EMSESP_CUSTOMENTITY_FILE, "Entities", root);
response->setLength();
request->send(response);
}
} // namespace emsesp

View File

@@ -22,7 +22,6 @@
#define EMSESP_CUSTOMENTITY_FILE "/config/emsespEntity.json"
#define EMSESP_CUSTOMENTITY_SERVICE_PATH "/rest/customEntities" // GET and POST
#define EMSESP_GET_ENTITIES_PATH "/rest/getEntities"
namespace emsesp {

View File

@@ -28,13 +28,6 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
server->on(EMSESP_DEVICE_ENTITIES_PATH,
HTTP_GET,
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { device_entities(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
server->on(EMSESP_DEVICES_SERVICE_PATH,
HTTP_GET,
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { devices(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
server->on(EMSESP_GET_CUSTOMIZATIONS_PATH,
HTTP_GET,
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { getCustomizations(request); }, AuthenticationPredicates::IS_ADMIN));
// POST
server->on(EMSESP_RESET_CUSTOMIZATION_SERVICE_PATH,
@@ -166,29 +159,6 @@ void WebCustomizationService::reset_customization(AsyncWebServerRequest * reques
#endif
}
// send back a list of devices used in the customization web page
void WebCustomizationService::devices(AsyncWebServerRequest * request) {
auto * response = new AsyncJsonResponse(false);
JsonObject root = response->getRoot();
// list is already sorted by device type
// controller is ignored since it doesn't have any associated entities
JsonArray devices = root["devices"].to<JsonArray>();
for (const auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice->has_entities()) {
JsonObject obj = devices.add<JsonObject>();
obj["i"] = emsdevice->unique_id(); // its unique id
obj["s"] = emsdevice->name(); // custom name
obj["t"] = emsdevice->device_type(); // internal device type ID
obj["tn"] = std::string(emsdevice->device_type_2_device_name_translated()); // translated device type name
obj["url"] = emsdevice->device_type_name(); // non-translated, lower-case, used for API URL
}
}
response->setLength();
request->send(response);
}
// send back list of device entities
void WebCustomizationService::device_entities(AsyncWebServerRequest * request) {
uint8_t id;
@@ -425,17 +395,4 @@ void WebCustomizationService::test() {
}
#endif
// return all customizations in a json object
void WebCustomizationService::getCustomizations(AsyncWebServerRequest * request) {
auto * response = new AsyncJsonResponse(false);
JsonObject root = response->getRoot();
root["type"] = "customizations";
System::extractSettings(EMSESP_CUSTOMIZATION_FILE, "Customizations", root);
response->setLength();
request->send(response);
}
} // namespace emsesp

View File

@@ -22,9 +22,7 @@
#define EMSESP_CUSTOMIZATION_FILE "/config/emsespCustomization.json"
// GET
#define EMSESP_DEVICES_SERVICE_PATH "/rest/devices"
#define EMSESP_DEVICE_ENTITIES_PATH "/rest/deviceEntities"
#define EMSESP_GET_CUSTOMIZATIONS_PATH "/rest/getCustomizations"
// POST
#define EMSESP_CUSTOMIZATION_ENTITIES_PATH "/rest/customizationEntities"
@@ -98,9 +96,7 @@ class WebCustomizationService : public StatefulService<WebCustomization> {
FSPersistence<WebCustomization> _fsPersistence;
// GET
void devices(AsyncWebServerRequest * request);
void device_entities(AsyncWebServerRequest * request);
void getCustomizations(AsyncWebServerRequest * request);
// POST
void customization_entities(AsyncWebServerRequest * request, JsonVariant json);

View File

@@ -66,6 +66,7 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
obj["p"] = emsdevice->product_id(); // productid
obj["v"] = emsdevice->version(); // version
obj["e"] = emsdevice->count_entities(); // number of entities
obj["url"] = emsdevice->device_type_name(); // non-translated, lower-case, used for API URL in customization page
}
}

View File

@@ -25,9 +25,6 @@ namespace emsesp {
WebSchedulerService::WebSchedulerService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
: _httpEndpoint(WebScheduler::read, WebScheduler::update, this, server, EMSESP_SCHEDULER_SERVICE_PATH, securityManager, AuthenticationPredicates::IS_AUTHENTICATED)
, _fsPersistence(WebScheduler::read, WebScheduler::update, this, fs, EMSESP_SCHEDULER_FILE) {
server->on(EMSESP_GET_SCHEDULE_PATH,
HTTP_GET,
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { getSchedule(request); }, AuthenticationPredicates::IS_ADMIN));
}
// load the settings when the service starts
@@ -613,17 +610,4 @@ void WebSchedulerService::test() {
}
#endif
// return schedule entries in a json object
void WebSchedulerService::getSchedule(AsyncWebServerRequest * request) {
auto * response = new AsyncJsonResponse(false);
JsonObject root = response->getRoot();
root["type"] = "schedule";
System::extractSettings(EMSESP_SCHEDULER_FILE, "Schedule", root);
response->setLength();
request->send(response);
}
} // namespace emsesp

View File

@@ -21,7 +21,6 @@
#define EMSESP_SCHEDULER_FILE "/config/emsespScheduler.json"
#define EMSESP_SCHEDULER_SERVICE_PATH "/rest/schedule" // GET and POST
#define EMSESP_GET_SCHEDULE_PATH "/rest/getSchedule"
// bit flags for the schedule items. Matches those in interface/src/app/main/SchedulerDialog.tsx
// 0-127 (0->0x7F) is day schedule
@@ -91,8 +90,6 @@ class WebSchedulerService : public StatefulService<WebScheduler> {
HttpEndpoint<WebScheduler> _httpEndpoint;
FSPersistence<WebScheduler> _fsPersistence;
void getSchedule(AsyncWebServerRequest * request);
std::list<ScheduleItem> * scheduleItems_; // pointer to the list of schedule events
bool ha_registered_ = false;
std::deque<ScheduleItem *> cmd_changed_;

View File

@@ -28,9 +28,6 @@ WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, Securit
server->on(EMSESP_BOARD_PROFILE_SERVICE_PATH,
HTTP_GET,
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { board_profile(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
server->on(EMSESP_GET_SETTINGS_PATH,
HTTP_GET,
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { getSettings(request); }, AuthenticationPredicates::IS_ADMIN));
addUpdateHandler([this] { onUpdate(); }, false);
}
@@ -463,25 +460,4 @@ void WebSettingsService::board_profile(AsyncWebServerRequest * request) {
request->send(response);
}
// returns json with all system settings
void WebSettingsService::getSettings(AsyncWebServerRequest * request) {
auto * response = new AsyncJsonResponse(false);
JsonObject root = response->getRoot();
root["type"] = "settings";
JsonObject node = root["System"].to<JsonObject>();
node["version"] = EMSESP_APP_VERSION;
System::extractSettings(NETWORK_SETTINGS_FILE, "Network", root);
System::extractSettings(AP_SETTINGS_FILE, "AP", root);
System::extractSettings(MQTT_SETTINGS_FILE, "MQTT", root);
System::extractSettings(NTP_SETTINGS_FILE, "NTP", root);
System::extractSettings(SECURITY_SETTINGS_FILE, "Security", root);
System::extractSettings(EMSESP_SETTINGS_FILE, "Settings", root);
response->setLength();
request->send(response);
}
} // namespace emsesp

View File

@@ -25,7 +25,6 @@
#define EMSESP_SETTINGS_SERVICE_PATH "/rest/settings"
#define EMSESP_BOARD_PROFILE_SERVICE_PATH "/rest/boardProfile"
#define EMSESP_GET_SETTINGS_PATH "/rest/getSettings"
namespace emsesp {
@@ -136,7 +135,6 @@ class WebSettingsService : public StatefulService<WebSettings> {
FSPersistence<WebSettings> _fsPersistence;
void board_profile(AsyncWebServerRequest * request);
void getSettings(AsyncWebServerRequest * request);
void onUpdate();
};

View File

@@ -26,13 +26,16 @@ namespace emsesp {
WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager) {
// GET
server->on(EMSESP_HARDWARE_STATUS_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { hardwareStatus(request); });
server->on(EMSESP_SYSTEM_STATUS_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { systemStatus(request); });
server->on(EMSESP_EXPORT_DATA_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { exportData(request); });
// POST
server->on(EMSESP_CHECK_UPGRADE_PATH, [this](AsyncWebServerRequest * request, JsonVariant json) { checkUpgrade(request, json); });
}
// /rest/systemStatus
// This contains both system & hardware Status to avoid having multiple costly endpoints
// This is also used for polling during the RestartMonitor to see if EMS-ESP is alive
void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
EMSESP::system_.refreshHeapMem(); // refresh free heap and max alloc heap
@@ -40,7 +43,12 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
JsonObject root = response->getRoot();
root["emsesp_version"] = EMSESP_APP_VERSION;
root["status"] = EMSESP::bus_status(); // 0, 1 or 2
//
// System Status
//
root["emsesp_version"] = EMSESP_APP_VERSION;
root["bus_status"] = EMSESP::bus_status(); // 0, 1 or 2
root["bus_uptime"] = EMSbus::bus_uptime();
root["num_devices"] = EMSESP::count_devices();
root["num_sensors"] = EMSESP::temperaturesensor_.no_sensors();
@@ -74,20 +82,6 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
#endif
}
response->setLength();
request->send(response);
}
// /rest/hardwareStatus
// This is also used for polling during the RestartMonitor to see if EMS-ESP is alive
void WebStatusService::hardwareStatus(AsyncWebServerRequest * request) {
EMSESP::system_.refreshHeapMem(); // refresh free heap and max alloc heap
auto * response = new AsyncJsonResponse(false);
JsonObject root = response->getRoot();
root["emsesp_version"] = EMSESP_APP_VERSION;
#ifdef EMSESP_DEBUG
#ifdef EMSESP_TEST
root["build_flags"] = "DEBUG,TEST";
@@ -98,15 +92,16 @@ void WebStatusService::hardwareStatus(AsyncWebServerRequest * request) {
root["build_flags"] = "TEST";
#endif
//
// Hardware Status
//
root["esp_platform"] = EMSESP_PLATFORM;
#ifndef EMSESP_STANDALONE
root["cpu_type"] = ESP.getChipModel();
root["cpu_rev"] = ESP.getChipRevision();
root["cpu_cores"] = ESP.getChipCores();
root["cpu_freq_mhz"] = ESP.getCpuFreqMHz();
root["max_alloc_heap"] = EMSESP::system_.getMaxAllocMem();
root["free_heap"] = EMSESP::system_.getHeapMem();
root["arduino_version"] = ARDUINO_VERSION;
root["sdk_version"] = ESP.getSdkVersion();
root["partition"] = esp_ota_get_running_partition()->label; // active partition
@@ -170,4 +165,36 @@ void WebStatusService::checkUpgrade(AsyncWebServerRequest * request, JsonVariant
request->send(response);
}
// returns data for a specific feature/settings as a json object
void WebStatusService::exportData(AsyncWebServerRequest * request) {
auto * response = new AsyncJsonResponse();
JsonObject root = response->getRoot();
String type = request->getParam("type")->value();
if (type == "settings") {
JsonObject node = root["System"].to<JsonObject>();
node["version"] = EMSESP_APP_VERSION;
System::extractSettings(NETWORK_SETTINGS_FILE, "Network", root);
System::extractSettings(AP_SETTINGS_FILE, "AP", root);
System::extractSettings(MQTT_SETTINGS_FILE, "MQTT", root);
System::extractSettings(NTP_SETTINGS_FILE, "NTP", root);
System::extractSettings(SECURITY_SETTINGS_FILE, "Security", root);
System::extractSettings(EMSESP_SETTINGS_FILE, "Settings", root);
} else if (type == "schedule") {
System::extractSettings(EMSESP_SCHEDULER_FILE, "Schedule", root);
} else if (type == "customizations") {
System::extractSettings(EMSESP_CUSTOMIZATION_FILE, "Customizations", root);
} else if (type == "entities") {
System::extractSettings(EMSESP_CUSTOMENTITY_FILE, "Entities", root);
} else {
request->send(400);
return;
}
root["type"] = type;
response->setLength();
request->send(response);
}
} // namespace emsesp

View File

@@ -1,11 +1,11 @@
#ifndef WebStatusService_h
#define WebStatusService_h
#define EMSESP_HARDWARE_STATUS_SERVICE_PATH "/rest/hardwareStatus"
#define EMSESP_SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus"
#define EMSESP_CHECK_UPGRADE_PATH "/rest/checkUpgrade"
#define EMSESP_EXPORT_DATA_SERVICE_PATH "/rest/exportData"
#include <semver200.h>
#include <semver200.h> // for version checking
namespace emsesp {
@@ -15,8 +15,8 @@ class WebStatusService {
private:
void systemStatus(AsyncWebServerRequest * request);
void hardwareStatus(AsyncWebServerRequest * request);
void checkUpgrade(AsyncWebServerRequest * request, JsonVariant json);
void exportData(AsyncWebServerRequest * request);
};
} // namespace emsesp