updates to backend to match new frontend - #1665

This commit is contained in:
proddy
2024-03-22 16:25:18 +01:00
parent c8e7eb3657
commit a2fa2515b3
23 changed files with 360 additions and 293 deletions

View File

@@ -49,7 +49,7 @@
"react-toastify": "^10.0.5", "react-toastify": "^10.0.5",
"sockette": "^2.0.6", "sockette": "^2.0.6",
"typesafe-i18n": "^5.26.2", "typesafe-i18n": "^5.26.2",
"typescript": "^5.4.2" "typescript": "^5.4.3"
}, },
"devDependencies": { "devDependencies": {
"@preact/compat": "^17.1.2", "@preact/compat": "^17.1.2",
@@ -70,7 +70,7 @@
"prettier": "^3.2.5", "prettier": "^3.2.5",
"rollup-plugin-visualizer": "^5.12.0", "rollup-plugin-visualizer": "^5.12.0",
"terser": "^5.29.2", "terser": "^5.29.2",
"vite": "^5.2.2", "vite": "^5.2.3",
"vite-plugin-imagemin": "^0.6.1", "vite-plugin-imagemin": "^0.6.1",
"vite-tsconfig-paths": "^4.3.2" "vite-tsconfig-paths": "^4.3.2"
}, },

View File

@@ -1,15 +1,15 @@
import NavigateNextIcon from '@mui/icons-material/NavigateNext'; import NavigateNextIcon from '@mui/icons-material/NavigateNext';
import { Avatar, ListItem, ListItemAvatar, ListItemButton, ListItemIcon, ListItemText } from '@mui/material'; import { Avatar, ListItem, ListItemAvatar, ListItemButton, ListItemIcon, ListItemText } from '@mui/material';
import { Fragment, type FC } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import type { SvgIconProps } from '@mui/material'; import type { SvgIconProps } from '@mui/material';
import type { FC } from 'react';
interface ListMenuItemProps { interface ListMenuItemProps {
icon: React.ComponentType<SvgIconProps>; icon: React.ComponentType<SvgIconProps>;
bgcolor?: string; bgcolor?: string;
label: string; label: string;
text: string; text: string;
to: string; to?: string;
disabled?: boolean; disabled?: boolean;
} }
@@ -27,12 +27,8 @@ function RenderIcon({ icon: Icon, bgcolor, label, text }: ListMenuItemProps) {
} }
const LayoutMenuItem: FC<ListMenuItemProps> = ({ icon, bgcolor, label, text, to, disabled }) => ( const LayoutMenuItem: FC<ListMenuItemProps> = ({ icon, bgcolor, label, text, to, disabled }) => (
<Fragment> <>
{disabled ? ( {to && !disabled ? (
<ListItem>
<RenderIcon icon={icon} bgcolor={bgcolor} label={label} text={text} to="" />
</ListItem>
) : (
<ListItem <ListItem
disablePadding disablePadding
secondaryAction={ secondaryAction={
@@ -45,8 +41,12 @@ const LayoutMenuItem: FC<ListMenuItemProps> = ({ icon, bgcolor, label, text, to,
<RenderIcon icon={icon} bgcolor={bgcolor} label={label} text={text} to="" /> <RenderIcon icon={icon} bgcolor={bgcolor} label={label} text={text} to="" />
</ListItemButton> </ListItemButton>
</ListItem> </ListItem>
) : (
<ListItem>
<RenderIcon icon={icon} bgcolor={bgcolor} label={label} text={text} to="" />
</ListItem>
)} )}
</Fragment> </>
); );
export default LayoutMenuItem; export default LayoutMenuItem;

View File

@@ -83,7 +83,7 @@ const SystemStatus: FC = () => {
if (data) { if (data) {
switch (data.status) { switch (data.status) {
case busConnectionStatus.BUS_STATUS_CONNECTED: case busConnectionStatus.BUS_STATUS_CONNECTED:
return LL.CONNECTED(0); return LL.CONNECTED(0) + ' (' + formatDurationSec(data.bus_uptime) + ')';
case busConnectionStatus.BUS_STATUS_TX_ERRORS: case busConnectionStatus.BUS_STATUS_TX_ERRORS:
return LL.TX_ISSUES(); return LL.TX_ISSUES();
case busConnectionStatus.BUS_STATUS_OFFLINE: case busConnectionStatus.BUS_STATUS_OFFLINE:
@@ -178,6 +178,15 @@ const SystemStatus: FC = () => {
</ListItem> </ListItem>
<Divider variant="inset" component="li" /> <Divider variant="inset" component="li" />
<ListMenuItem
disabled={!me.admin}
icon={TimerIcon}
bgcolor="#c5572c"
label={LL.UPTIME()}
text={formatDurationSec(data.uptime)}
/>
<Divider variant="inset" component="li" />
<ListItem> <ListItem>
<ListItemAvatar> <ListItemAvatar>
<Avatar sx={{ bgcolor: '#5d89f7', color: 'white' }}> <Avatar sx={{ bgcolor: '#5d89f7', color: 'white' }}>
@@ -207,16 +216,6 @@ const SystemStatus: FC = () => {
</ListItem> </ListItem>
<Divider variant="inset" component="li" /> <Divider variant="inset" component="li" />
<ListItem>
<ListItemAvatar>
<Avatar sx={{ bgcolor: '#c5572c', color: 'white' }}>
<TimerIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary={LL.UPTIME()} secondary={formatDurationSec(data.uptime)} />
</ListItem>
<Divider variant="inset" component="li" />
<ListMenuItem <ListMenuItem
disabled={!me.admin} disabled={!me.admin}
icon={BuildIcon} icon={BuildIcon}

View File

@@ -408,24 +408,19 @@ const Sensors: FC = () => {
return ( return (
<SectionContent> <SectionContent>
{sensorData.ts.length > 0 && ( <Typography sx={{ pb: 1 }} variant="h6" color="secondary">
<> {LL.TEMP_SENSORS()}
<Typography sx={{ pb: 1 }} variant="h6" color="secondary"> </Typography>
{LL.TEMP_SENSORS()} <RenderTemperatureSensors />
</Typography> {selectedTemperatureSensor && (
<RenderTemperatureSensors /> <DashboardSensorsTemperatureDialog
{selectedTemperatureSensor && ( open={temperatureDialogOpen}
<DashboardSensorsTemperatureDialog onClose={onTemperatureDialogClose}
open={temperatureDialogOpen} onSave={onTemperatureDialogSave}
onClose={onTemperatureDialogClose} selectedItem={selectedTemperatureSensor}
onSave={onTemperatureDialogSave} validator={temperatureSensorItemValidation()}
selectedItem={selectedTemperatureSensor} />
validator={temperatureSensorItemValidation()}
/>
)}
</>
)} )}
{sensorData?.analog_enabled === true && ( {sensorData?.analog_enabled === true && (
<> <>
<Typography sx={{ pt: 4, pb: 1 }} variant="h6" color="secondary"> <Typography sx={{ pt: 4, pb: 1 }} variant="h6" color="secondary">
@@ -444,7 +439,6 @@ const Sensors: FC = () => {
)} )}
</> </>
)} )}
<ButtonRow> <ButtonRow>
<Box mt={2} display="flex" flexWrap="wrap"> <Box mt={2} display="flex" flexWrap="wrap">
<Box flexGrow={1}> <Box flexGrow={1}>

View File

@@ -29,6 +29,7 @@ export interface SystemStatus {
esp_platform: string; esp_platform: string;
status: busConnectionStatus; status: busConnectionStatus;
uptime: number; uptime: number;
bus_uptime: number;
num_devices: number; num_devices: number;
num_sensors: number; num_sensors: number;
num_analogs: number; num_analogs: number;

View File

@@ -1817,8 +1817,8 @@ __metadata:
sockette: "npm:^2.0.6" sockette: "npm:^2.0.6"
terser: "npm:^5.29.2" terser: "npm:^5.29.2"
typesafe-i18n: "npm:^5.26.2" typesafe-i18n: "npm:^5.26.2"
typescript: "npm:^5.4.2" typescript: "npm:^5.4.3"
vite: "npm:^5.2.2" vite: "npm:^5.2.3"
vite-plugin-imagemin: "npm:^0.6.1" vite-plugin-imagemin: "npm:^0.6.1"
vite-tsconfig-paths: "npm:^4.3.2" vite-tsconfig-paths: "npm:^4.3.2"
languageName: unknown languageName: unknown
@@ -8294,23 +8294,23 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"typescript@npm:^5.4.2": "typescript@npm:^5.4.3":
version: 5.4.2 version: 5.4.3
resolution: "typescript@npm:5.4.2" resolution: "typescript@npm:5.4.3"
bin: bin:
tsc: bin/tsc tsc: bin/tsc
tsserver: bin/tsserver tsserver: bin/tsserver
checksum: 10/f8cfdc630ab1672f004e9561eb2916935b2d267792d07ce93e97fc601c7a65191af32033d5e9c0169b7dc37da7db9bf320f7432bc84527cb7697effaa4e4559d checksum: 10/de4c69f49a7ad4b1ea66a6dcc8b055ac34eb56af059a069d8988dd811c5e649be07e042e5bf573e8d0ac3ec2f30e6c999aa651cd09f6e9cbc6113749e8b6be20
languageName: node languageName: node
linkType: hard linkType: hard
"typescript@patch:typescript@npm%3A^5.4.2#optional!builtin<compat/typescript>": "typescript@patch:typescript@npm%3A^5.4.3#optional!builtin<compat/typescript>":
version: 5.4.2 version: 5.4.3
resolution: "typescript@patch:typescript@npm%3A5.4.2#optional!builtin<compat/typescript>::version=5.4.2&hash=5adc0c" resolution: "typescript@patch:typescript@npm%3A5.4.3#optional!builtin<compat/typescript>::version=5.4.3&hash=5adc0c"
bin: bin:
tsc: bin/tsc tsc: bin/tsc
tsserver: bin/tsserver tsserver: bin/tsserver
checksum: 10/f5f9a4133c2670761f0166eae5b3bafbc4a3fc24f0f42a93c9c893d9e9d6e66ea066969c5e7483fa66b4ae0e99125592553f3b92fd3599484de8be13b0615176 checksum: 10/5aedd97595582b08aadb8a70e8e3ddebaf5a9c1e5ad4d6503c2fcfc15329b5cf8d01145b09913e9555683ac16c5123a96be32b6d72614098ebd42df520eed9b1
languageName: node languageName: node
linkType: hard linkType: hard
@@ -8491,9 +8491,9 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"vite@npm:^5.2.2": "vite@npm:^5.2.3":
version: 5.2.2 version: 5.2.3
resolution: "vite@npm:5.2.2" resolution: "vite@npm:5.2.3"
dependencies: dependencies:
esbuild: "npm:^0.20.1" esbuild: "npm:^0.20.1"
fsevents: "npm:~2.3.3" fsevents: "npm:~2.3.3"
@@ -8527,7 +8527,7 @@ __metadata:
optional: true optional: true
bin: bin:
vite: bin/vite.js vite: bin/vite.js
checksum: 10/8e7f1e79e00a092b43378565898b5b60f66738d55fdcd2bb3a17b07183d32c3bfda30135490956ad8eb5eb77b0e56d4377655bf9478898616edbb20645477edb checksum: 10/5033a989462bc3127cb937ae5138024af68ec1b67accad07e07e116254b84fc6888a18d7a0358e3d3ce19fe160d72b6622259edc93e7fba47b84d042dcbe1e4e
languageName: node languageName: node
linkType: hard linkType: hard

View File

@@ -1,6 +1,6 @@
#include "ESP8266React.h" #include "ESP8266React.h"
#include "WWWData.h" #include "WWWData.h" // include auto-generated static web resources
ESP8266React::ESP8266React(AsyncWebServer * server, FS * fs) ESP8266React::ESP8266React(AsyncWebServer * server, FS * fs)
: _securitySettingsService(server, fs) : _securitySettingsService(server, fs)
@@ -17,8 +17,7 @@ ESP8266React::ESP8266React(AsyncWebServer * server, FS * fs)
, _mqttStatus(server, &_mqttSettingsService, &_securitySettingsService) , _mqttStatus(server, &_mqttSettingsService, &_securitySettingsService)
, _authenticationService(server, &_securitySettingsService) , _authenticationService(server, &_securitySettingsService)
, _restartService(server, &_securitySettingsService) , _restartService(server, &_securitySettingsService)
, _factoryResetService(server, fs, &_securitySettingsService) , _factoryResetService(server, fs, &_securitySettingsService) {
, _systemStatus(server, &_securitySettingsService) {
// //
// Serve static web resources // Serve static web resources
// //

View File

@@ -13,7 +13,6 @@
#include "UploadFileService.h" #include "UploadFileService.h"
#include "RestartService.h" #include "RestartService.h"
#include "SecuritySettingsService.h" #include "SecuritySettingsService.h"
#include "SystemStatus.h"
#include "WiFiScanner.h" #include "WiFiScanner.h"
#include "NetworkSettingsService.h" #include "NetworkSettingsService.h"
#include "NetworkStatus.h" #include "NetworkStatus.h"
@@ -87,7 +86,6 @@ class ESP8266React {
AuthenticationService _authenticationService; AuthenticationService _authenticationService;
RestartService _restartService; RestartService _restartService;
FactoryResetService _factoryResetService; FactoryResetService _factoryResetService;
SystemStatus _systemStatus;
}; };
#endif #endif

View File

@@ -1,66 +0,0 @@
#include "SystemStatus.h"
#include <esp_ota_ops.h>
#include "../../src/emsesp_stub.hpp"
SystemStatus::SystemStatus(AsyncWebServer * server, SecurityManager * securityManager) {
server->on(SYSTEM_STATUS_SERVICE_PATH,
HTTP_GET,
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { systemStatus(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
}
void SystemStatus::systemStatus(AsyncWebServerRequest * request) {
emsesp::EMSESP::system_.refreshHeapMem(); // refresh free heap and max alloc heap
auto * response = new AsyncJsonResponse(false);
JsonObject root = response->getRoot();
#ifdef EMSESP_DEBUG
root["emsesp_version"] = std::string(EMSESP_APP_VERSION) + " (DEBUG)";
#else
#ifdef EMSESP_TEST
root["emsesp_version"] = std::string(EMSESP_APP_VERSION) + " (TEST)";
#else
root["emsesp_version"] = EMSESP_APP_VERSION;
#endif
#endif
root["esp_platform"] = EMSESP_PLATFORM;
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::EMSESP::system_.getMaxAllocMem();
root["free_heap"] = emsesp::EMSESP::system_.getHeapMem();
root["arduino_version"] = ARDUINO_VERSION;
root["sdk_version"] = ESP.getSdkVersion();
root["partition"] = esp_ota_get_running_partition()->label;
root["flash_chip_size"] = ESP.getFlashChipSize() / 1024;
root["flash_chip_speed"] = ESP.getFlashChipSpeed();
root["app_used"] = emsesp::EMSESP::system_.appUsed();
root["app_free"] = emsesp::EMSESP::system_.appFree();
uint32_t FSused = LittleFS.usedBytes() / 1024;
root["fs_used"] = FSused;
root["fs_free"] = emsesp::EMSESP::system_.FStotal() - FSused;
root["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
if (emsesp::EMSESP::system_.PSram()) {
root["psram_size"] = emsesp::EMSESP::system_.PSram();
root["free_psram"] = ESP.getFreePsram() / 1024;
}
const esp_partition_t * partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, nullptr);
if (partition != NULL) { // factory partition found
root["has_loader"] = true;
} else { // check for not empty, smaller OTA partition
partition = esp_ota_get_next_update_partition(nullptr);
if (partition) {
uint64_t buffer;
esp_partition_read(partition, 0, &buffer, 8);
const esp_partition_t * running = esp_ota_get_running_partition();
root["has_loader"] = (buffer != 0xFFFFFFFFFFFFFFFF && running->size != partition->size);
}
}
response->setLength();
request->send(response);
}

View File

@@ -1,23 +0,0 @@
#ifndef SystemStatus_h
#define SystemStatus_h
#include <WiFi.h>
#include <AsyncTCP.h>
#include <FS.h>
#include <LittleFS.h>
#include <ArduinoJson.h>
#include <ESPAsyncWebServer.h>
#include "SecurityManager.h"
#define SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus"
class SystemStatus {
public:
SystemStatus(AsyncWebServer * server, SecurityManager * securityManager);
private:
void systemStatus(AsyncWebServerRequest * request);
};
#endif

View File

@@ -74,6 +74,8 @@ class DummySettings {
String CORSOrigin = "*"; String CORSOrigin = "*";
uint8_t tx_power = 0; uint8_t tx_power = 0;
uint8_t provisionMode = 0;
static void read(DummySettings & settings, JsonObject root){}; static void read(DummySettings & settings, JsonObject root){};
static void read(DummySettings & settings){}; static void read(DummySettings & settings){};
@@ -94,6 +96,9 @@ class DummySettingsService : public StatefulService<DummySettings> {
#define SecuritySettings DummySettings #define SecuritySettings DummySettings
#define MqttSettings DummySettings #define MqttSettings DummySettings
#define NTPSettings DummySettings #define NTPSettings DummySettings
#define OTASettings DummySettings
#define APSettings DummySettings
class ESP8266React { class ESP8266React {
public: public:
@@ -135,6 +140,14 @@ class ESP8266React {
return &_settings; return &_settings;
} }
StatefulService<DummySettings> * getOTASettingsService() {
return &_settings;
}
StatefulService<DummySettings> * getAPSettingsService() {
return &_settings;
}
private: private:
DummySettingsService _settings; DummySettingsService _settings;
SecuritySettingsService _securitySettingsService; SecuritySettingsService _securitySettingsService;

View File

@@ -407,6 +407,7 @@ const system_status = {
status: 0, status: 0,
// status: 2, // status: 2,
uptime: 77186, uptime: 77186,
bus_uptime: 77121,
num_devices: 2, num_devices: 2,
num_sensors: 1, num_sensors: 1,
num_analogs: 1, num_analogs: 1,

View File

@@ -12,7 +12,7 @@
"dependencies": { "dependencies": {
"@msgpack/msgpack": "^2.8.0", "@msgpack/msgpack": "^2.8.0",
"compression": "^1.7.4", "compression": "^1.7.4",
"express": "^4.18.3", "express": "^4.19.1",
"itty-router": "^4.2.2", "itty-router": "^4.2.2",
"multer": "^1.4.5-lts.1" "multer": "^1.4.5-lts.1"
}, },

View File

@@ -139,7 +139,7 @@ __metadata:
"@msgpack/msgpack": "npm:^2.8.0" "@msgpack/msgpack": "npm:^2.8.0"
"@types/multer": "npm:^1.4.11" "@types/multer": "npm:^1.4.11"
compression: "npm:^1.7.4" compression: "npm:^1.7.4"
express: "npm:^4.18.3" express: "npm:^4.19.1"
itty-router: "npm:^4.2.2" itty-router: "npm:^4.2.2"
multer: "npm:^1.4.5-lts.1" multer: "npm:^1.4.5-lts.1"
languageName: unknown languageName: unknown
@@ -279,10 +279,10 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"cookie@npm:0.5.0": "cookie@npm:0.6.0":
version: 0.5.0 version: 0.6.0
resolution: "cookie@npm:0.5.0" resolution: "cookie@npm:0.6.0"
checksum: 10/aae7911ddc5f444a9025fbd979ad1b5d60191011339bce48e555cb83343d0f98b865ff5c4d71fecdfb8555a5cafdc65632f6fce172f32aaf6936830a883a0380 checksum: 10/c1f8f2ea7d443b9331680598b0ae4e6af18a618c37606d1bbdc75bec8361cce09fe93e727059a673f2ba24467131a9fb5a4eec76bb1b149c1b3e1ccb268dc583
languageName: node languageName: node
linkType: hard linkType: hard
@@ -355,16 +355,16 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"express@npm:^4.18.3": "express@npm:^4.19.1":
version: 4.18.3 version: 4.19.1
resolution: "express@npm:4.18.3" resolution: "express@npm:4.19.1"
dependencies: dependencies:
accepts: "npm:~1.3.8" accepts: "npm:~1.3.8"
array-flatten: "npm:1.1.1" array-flatten: "npm:1.1.1"
body-parser: "npm:1.20.2" body-parser: "npm:1.20.2"
content-disposition: "npm:0.5.4" content-disposition: "npm:0.5.4"
content-type: "npm:~1.0.4" content-type: "npm:~1.0.4"
cookie: "npm:0.5.0" cookie: "npm:0.6.0"
cookie-signature: "npm:1.0.6" cookie-signature: "npm:1.0.6"
debug: "npm:2.6.9" debug: "npm:2.6.9"
depd: "npm:2.0.0" depd: "npm:2.0.0"
@@ -390,7 +390,7 @@ __metadata:
type-is: "npm:~1.6.18" type-is: "npm:~1.6.18"
utils-merge: "npm:1.0.1" utils-merge: "npm:1.0.1"
vary: "npm:~1.1.2" vary: "npm:~1.1.2"
checksum: 10/0bf4656d0020cdc477aec884c6245dceea78992f6c747c899c87dbb0598474658d4130a29c80f02c99d1f0d6ebef706e7131c70c5454c3e07aba761c5bd3d627 checksum: 10/7b817f21afe96e478cd7fe77cd5f52cf7d2d6b70c3e98f0e1399ce48356cef3c5f5d34bf93bdbc7bc326403005c45e2f8522f51b4cc319da52220066c9094745
languageName: node languageName: node
linkType: hard linkType: hard

View File

@@ -45,10 +45,11 @@ WebSchedulerService EMSESP::webSchedulerService = WebSchedulerService(&w
WebCustomEntityService EMSESP::webCustomEntityService = WebCustomEntityService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager()); WebCustomEntityService EMSESP::webCustomEntityService = WebCustomEntityService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
#endif #endif
WebStatusService EMSESP::webStatusService = WebStatusService(&webServer, EMSESP::esp8266React.getSecurityManager()); WebActivityService EMSESP::webActivityService = WebActivityService(&webServer, EMSESP::esp8266React.getSecurityManager());
WebDataService EMSESP::webDataService = WebDataService(&webServer, EMSESP::esp8266React.getSecurityManager()); WebStatusService EMSESP::webStatusService = WebStatusService(&webServer, EMSESP::esp8266React.getSecurityManager());
WebAPIService EMSESP::webAPIService = WebAPIService(&webServer, EMSESP::esp8266React.getSecurityManager()); WebDataService EMSESP::webDataService = WebDataService(&webServer, EMSESP::esp8266React.getSecurityManager());
WebLogService EMSESP::webLogService = WebLogService(&webServer, EMSESP::esp8266React.getSecurityManager()); WebAPIService EMSESP::webAPIService = WebAPIService(&webServer, EMSESP::esp8266React.getSecurityManager());
WebLogService EMSESP::webLogService = WebLogService(&webServer, EMSESP::esp8266React.getSecurityManager());
using DeviceFlags = EMSdevice; using DeviceFlags = EMSdevice;
using DeviceType = EMSdevice::DeviceType; using DeviceType = EMSdevice::DeviceType;

View File

@@ -39,7 +39,9 @@
#include <Preferences.h> #include <Preferences.h>
#include "ESP8266React.h" #include "ESP8266React.h"
#include "web/WebStatusService.h" #include "web/WebStatusService.h"
#include "web/WebActivityService.h"
#include "web/WebDataService.h" #include "web/WebDataService.h"
#include "web/WebSettingsService.h" #include "web/WebSettingsService.h"
#include "web/WebCustomizationService.h" #include "web/WebCustomizationService.h"
@@ -220,6 +222,7 @@ class EMSESP {
static ESP8266React esp8266React; static ESP8266React esp8266React;
static WebSettingsService webSettingsService; static WebSettingsService webSettingsService;
static WebStatusService webStatusService; static WebStatusService webStatusService;
static WebActivityService webActivityService;
static WebDataService webDataService; static WebDataService webDataService;
static WebAPIService webAPIService; static WebAPIService webAPIService;
static WebLogService webLogService; static WebLogService webLogService;

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.6.5-dev.18" #define EMSESP_APP_VERSION "3.6.5-dev.19"

View File

@@ -0,0 +1,101 @@
/*
* EMS-ESP - https://github.com/emsesp/EMS-ESP
* Copyright 2020-2024 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
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "emsesp.h"
namespace emsesp {
WebActivityService::WebActivityService(AsyncWebServer * server, SecurityManager * securityManager) {
server->on(EMSESP_ACTIVITY_SERVICE_PATH,
HTTP_GET,
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { webActivityService(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
}
void WebActivityService::webActivityService(AsyncWebServerRequest * request) {
auto * response = new AsyncJsonResponse(false);
JsonObject root = response->getRoot();
JsonArray statsJson = root["stats"].to<JsonArray>();
JsonObject statJson;
statJson = statsJson.add<JsonObject>();
statJson["id"] = 0;
statJson["s"] = EMSESP::rxservice_.telegram_count();
statJson["f"] = EMSESP::rxservice_.telegram_error_count();
statJson["q"] = EMSESP::rxservice_.quality();
statJson = statsJson.add<JsonObject>();
statJson["id"] = 1;
statJson["s"] = EMSESP::txservice_.telegram_read_count();
statJson["f"] = EMSESP::txservice_.telegram_read_fail_count();
statJson["q"] = EMSESP::txservice_.read_quality();
statJson = statsJson.add<JsonObject>();
statJson["id"] = 2;
statJson["s"] = EMSESP::txservice_.telegram_write_count();
statJson["f"] = EMSESP::txservice_.telegram_write_fail_count();
statJson["q"] = EMSESP::txservice_.write_quality();
if (EMSESP::sensor_enabled()) {
statJson = statsJson.add<JsonObject>();
statJson["id"] = 3;
statJson["s"] = EMSESP::temperaturesensor_.reads() - EMSESP::temperaturesensor_.fails();
statJson["f"] = EMSESP::temperaturesensor_.fails();
statJson["q"] =
EMSESP::temperaturesensor_.reads() == 0 ? 100 : 100 - (uint8_t)((100 * EMSESP::temperaturesensor_.fails()) / EMSESP::temperaturesensor_.reads());
}
if (EMSESP::analog_enabled()) {
statJson = statsJson.add<JsonObject>();
statJson["id"] = 4;
statJson["s"] = EMSESP::analogsensor_.reads() - EMSESP::analogsensor_.fails();
statJson["f"] = EMSESP::analogsensor_.fails();
statJson["q"] = EMSESP::analogsensor_.reads() == 0 ? 100 : 100 - (uint8_t)((100 * EMSESP::analogsensor_.fails()) / EMSESP::analogsensor_.reads());
}
if (Mqtt::enabled()) {
statJson = statsJson.add<JsonObject>();
statJson["id"] = 5;
statJson["s"] = Mqtt::publish_count() - Mqtt::publish_fails();
statJson["f"] = Mqtt::publish_fails();
statJson["q"] = Mqtt::publish_count() == 0 ? 100 : 100 - (uint8_t)((100 * Mqtt::publish_fails()) / Mqtt::publish_count());
}
statJson = statsJson.add<JsonObject>();
statJson["id"] = 6;
statJson["s"] = WebAPIService::api_count(); // + WebAPIService::api_fails();
statJson["f"] = WebAPIService::api_fails();
statJson["q"] = (WebAPIService::api_count() + WebAPIService::api_fails()) == 0
? 100
: 100 - (uint8_t)((100 * WebAPIService::api_fails()) / (WebAPIService::api_count() + WebAPIService::api_fails()));
#ifndef EMSESP_STANDALONE
if (EMSESP::system_.syslog_enabled()) {
statJson = statsJson.add<JsonObject>();
statJson["id"] = 7;
statJson["s"] = EMSESP::system_.syslog_count();
statJson["f"] = EMSESP::system_.syslog_fails();
statJson["q"] = (EMSESP::system_.syslog_count() + EMSESP::system_.syslog_fails()) == 0
? 100
: 100 - (uint8_t)((100 * EMSESP::system_.syslog_fails()) / (EMSESP::system_.syslog_count() + EMSESP::system_.syslog_fails()));
}
#endif
response->setLength();
request->send(response);
}
} // namespace emsesp

View File

@@ -0,0 +1,36 @@
/*
* EMS-ESP - https://github.com/emsesp/EMS-ESP
* Copyright 2020-2024 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
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WebActivityService_h
#define WebActivityService_h
#define EMSESP_ACTIVITY_SERVICE_PATH "/rest/activity"
namespace emsesp {
class WebActivityService {
public:
WebActivityService(AsyncWebServer * server, SecurityManager * securityManager);
private:
void webActivityService(AsyncWebServerRequest * request);
};
} // namespace emsesp
#endif

View File

@@ -157,7 +157,6 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) {
} }
root["analog_enabled"] = EMSESP::analog_enabled(); root["analog_enabled"] = EMSESP::analog_enabled();
root["platform"] = EMSESP_PLATFORM;
response->setLength(); response->setLength();
request->send(response); request->send(response);

View File

@@ -87,6 +87,7 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
if ((String)EMSESP_DEFAULT_BOARD_PROFILE != "default" && EMSESP::nvs_.getString("boot") == "") { if ((String)EMSESP_DEFAULT_BOARD_PROFILE != "default" && EMSESP::nvs_.getString("boot") == "") {
EMSESP::nvs_.putString("boot", (const char *)EMSESP_DEFAULT_BOARD_PROFILE); EMSESP::nvs_.putString("boot", (const char *)EMSESP_DEFAULT_BOARD_PROFILE);
} }
/* /*
#if CONFIG_IDF_TARGET_ESP32C3 #if CONFIG_IDF_TARGET_ESP32C3
settings.board_profile = root["board_profile"] | "C3MINI"; settings.board_profile = root["board_profile"] | "C3MINI";

View File

@@ -18,86 +18,112 @@
#include "emsesp.h" #include "emsesp.h"
#ifndef EMSESP_STANDALONE
#include <esp_ota_ops.h>
#endif
namespace emsesp { namespace emsesp {
WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager) { WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager) {
server->on(EMSESP_ACTIVITY_SERVICE_PATH, server->on(ESPSYSTEM_STATUS_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { ESPsystemStatus(request); });
HTTP_GET, server->on(SYSTEM_STATUS_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { systemStatus(request); });
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { webStatusService(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
} }
void WebStatusService::webStatusService(AsyncWebServerRequest * request) { void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
EMSESP::system_.refreshHeapMem(); // refresh free heap and max alloc heap
auto * response = new AsyncJsonResponse(false); auto * response = new AsyncJsonResponse(false);
JsonObject root = response->getRoot(); JsonObject root = response->getRoot();
root["status"] = EMSESP::bus_status(); // 0, 1 or 2 #ifdef EMSESP_DEBUG
root["tx_mode"] = EMSESP::txservice_.tx_mode(); root["emsesp_version"] = std::string(EMSESP_APP_VERSION) + " (DEBUG)";
root["uptime"] = EMSbus::bus_uptime(); #else
root["num_devices"] = EMSESP::count_devices(); // excluding Controller #ifdef EMSESP_TEST
root["num_sensors"] = EMSESP::temperaturesensor_.no_sensors(); root["emsesp_version"] = std::string(EMSESP_APP_VERSION) + " (TEST)";
root["num_analogs"] = EMSESP::analogsensor_.no_sensors(); #else
root["emsesp_version"] = EMSESP_APP_VERSION;
#endif
#endif
JsonArray statsJson = root["stats"].to<JsonArray>(); root["esp_platform"] = EMSESP_PLATFORM;
JsonObject statJson; root["status"] = EMSESP::bus_status(); // 0, 1 or 2
root["bus_uptime"] = EMSbus::bus_uptime();
statJson = statsJson.add<JsonObject>(); root["num_devices"] = EMSESP::count_devices();
statJson["id"] = 0; root["num_sensors"] = EMSESP::temperaturesensor_.no_sensors();
statJson["s"] = EMSESP::rxservice_.telegram_count(); root["num_analogs"] = EMSESP::analogsensor_.no_sensors();
statJson["f"] = EMSESP::rxservice_.telegram_error_count(); root["free_heap"] = EMSESP::system_.getHeapMem();
statJson["q"] = EMSESP::rxservice_.quality(); root["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
EMSESP::esp8266React.getOTASettingsService()->read([root](OTASettings & otaSettings) { root["ota_status"] = otaSettings.enabled; });
statJson = statsJson.add<JsonObject>(); root["mqtt_status"] = EMSESP::mqtt_.connected();
statJson["id"] = 1;
statJson["s"] = EMSESP::txservice_.telegram_read_count();
statJson["f"] = EMSESP::txservice_.telegram_read_fail_count();
statJson["q"] = EMSESP::txservice_.read_quality();
statJson = statsJson.add<JsonObject>();
statJson["id"] = 2;
statJson["s"] = EMSESP::txservice_.telegram_write_count();
statJson["f"] = EMSESP::txservice_.telegram_write_fail_count();
statJson["q"] = EMSESP::txservice_.write_quality();
if (EMSESP::sensor_enabled()) {
statJson = statsJson.add<JsonObject>();
statJson["id"] = 3;
statJson["s"] = EMSESP::temperaturesensor_.reads() - EMSESP::temperaturesensor_.fails();
statJson["f"] = EMSESP::temperaturesensor_.fails();
statJson["q"] =
EMSESP::temperaturesensor_.reads() == 0 ? 100 : 100 - (uint8_t)((100 * EMSESP::temperaturesensor_.fails()) / EMSESP::temperaturesensor_.reads());
}
if (EMSESP::analog_enabled()) {
statJson = statsJson.add<JsonObject>();
statJson["id"] = 4;
statJson["s"] = EMSESP::analogsensor_.reads() - EMSESP::analogsensor_.fails();
statJson["f"] = EMSESP::analogsensor_.fails();
statJson["q"] = EMSESP::analogsensor_.reads() == 0 ? 100 : 100 - (uint8_t)((100 * EMSESP::analogsensor_.fails()) / EMSESP::analogsensor_.reads());
}
if (Mqtt::enabled()) {
statJson = statsJson.add<JsonObject>();
statJson["id"] = 5;
statJson["s"] = Mqtt::publish_count() - Mqtt::publish_fails();
statJson["f"] = Mqtt::publish_fails();
statJson["q"] = Mqtt::publish_count() == 0 ? 100 : 100 - (uint8_t)((100 * Mqtt::publish_fails()) / Mqtt::publish_count());
}
statJson = statsJson.add<JsonObject>();
statJson["id"] = 6;
statJson["s"] = WebAPIService::api_count(); // + WebAPIService::api_fails();
statJson["f"] = WebAPIService::api_fails();
statJson["q"] = (WebAPIService::api_count() + WebAPIService::api_fails()) == 0
? 100
: 100 - (uint8_t)((100 * WebAPIService::api_fails()) / (WebAPIService::api_count() + WebAPIService::api_fails()));
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
if (EMSESP::system_.syslog_enabled()) { root["ntp_status"] = [] {
statJson = statsJson.add<JsonObject>(); if (esp_sntp_enabled()) {
statJson["id"] = 7; if (emsesp::EMSESP::system_.ntp_connected()) {
statJson["s"] = EMSESP::system_.syslog_count(); return 2;
statJson["f"] = EMSESP::system_.syslog_fails(); } else {
statJson["q"] = (EMSESP::system_.syslog_count() + EMSESP::system_.syslog_fails()) == 0 return 1;
? 100 }
: 100 - (uint8_t)((100 * EMSESP::system_.syslog_fails()) / (EMSESP::system_.syslog_count() + EMSESP::system_.syslog_fails())); }
return 0;
}();
#endif
response->setLength();
request->send(response);
}
void WebStatusService::ESPsystemStatus(AsyncWebServerRequest * request) {
EMSESP::system_.refreshHeapMem(); // refresh free heap and max alloc heap
auto * response = new AsyncJsonResponse(false);
JsonObject root = response->getRoot();
#ifdef EMSESP_DEBUG
root["emsesp_version"] = std::string(EMSESP_APP_VERSION) + " (DEBUG)";
#else
#ifdef EMSESP_TEST
root["emsesp_version"] = std::string(EMSESP_APP_VERSION) + " (TEST)";
#else
root["emsesp_version"] = EMSESP_APP_VERSION;
#endif
#endif
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;
root["flash_chip_size"] = ESP.getFlashChipSize() / 1024;
root["flash_chip_speed"] = ESP.getFlashChipSpeed();
root["app_used"] = EMSESP::system_.appUsed();
root["app_free"] = EMSESP::system_.appFree();
uint32_t FSused = LittleFS.usedBytes() / 1024;
root["fs_used"] = FSused;
root["fs_free"] = EMSESP::system_.FStotal() - FSused;
if (EMSESP::system_.PSram()) {
root["psram_size"] = EMSESP::system_.PSram();
root["free_psram"] = ESP.getFreePsram() / 1024;
}
const esp_partition_t * partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, nullptr);
if (partition != NULL) { // factory partition found
root["has_loader"] = true;
} else { // check for not empty, smaller OTA partition
partition = esp_ota_get_next_update_partition(nullptr);
if (partition) {
uint64_t buffer;
esp_partition_read(partition, 0, &buffer, 8);
const esp_partition_t * running = esp_ota_get_running_partition();
root["has_loader"] = (buffer != 0xFFFFFFFFFFFFFFFF && running->size != partition->size);
}
} }
#endif #endif

View File

@@ -1,25 +1,8 @@
/*
* EMS-ESP - https://github.com/emsesp/EMS-ESP
* Copyright 2020-2024 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
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WebStatusService_h #ifndef WebStatusService_h
#define WebStatusService_h #define WebStatusService_h
#define EMSESP_ACTIVITY_SERVICE_PATH "/rest/activity" #define ESPSYSTEM_STATUS_SERVICE_PATH "/rest/ESPSystemStatus"
#define SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus"
namespace emsesp { namespace emsesp {
@@ -28,7 +11,8 @@ class WebStatusService {
WebStatusService(AsyncWebServer * server, SecurityManager * securityManager); WebStatusService(AsyncWebServer * server, SecurityManager * securityManager);
private: private:
void webStatusService(AsyncWebServerRequest * request); void systemStatus(AsyncWebServerRequest * request);
void ESPsystemStatus(AsyncWebServerRequest * request);
}; };
} // namespace emsesp } // namespace emsesp