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

View File

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

View File

@@ -83,7 +83,7 @@ const SystemStatus: FC = () => {
if (data) {
switch (data.status) {
case busConnectionStatus.BUS_STATUS_CONNECTED:
return LL.CONNECTED(0);
return LL.CONNECTED(0) + ' (' + formatDurationSec(data.bus_uptime) + ')';
case busConnectionStatus.BUS_STATUS_TX_ERRORS:
return LL.TX_ISSUES();
case busConnectionStatus.BUS_STATUS_OFFLINE:
@@ -178,6 +178,15 @@ const SystemStatus: FC = () => {
</ListItem>
<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>
<ListItemAvatar>
<Avatar sx={{ bgcolor: '#5d89f7', color: 'white' }}>
@@ -207,16 +216,6 @@ const SystemStatus: FC = () => {
</ListItem>
<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
disabled={!me.admin}
icon={BuildIcon}

View File

@@ -408,8 +408,6 @@ const Sensors: FC = () => {
return (
<SectionContent>
{sensorData.ts.length > 0 && (
<>
<Typography sx={{ pb: 1 }} variant="h6" color="secondary">
{LL.TEMP_SENSORS()}
</Typography>
@@ -423,9 +421,6 @@ const Sensors: FC = () => {
validator={temperatureSensorItemValidation()}
/>
)}
</>
)}
{sensorData?.analog_enabled === true && (
<>
<Typography sx={{ pt: 4, pb: 1 }} variant="h6" color="secondary">
@@ -444,7 +439,6 @@ const Sensors: FC = () => {
)}
</>
)}
<ButtonRow>
<Box mt={2} display="flex" flexWrap="wrap">
<Box flexGrow={1}>

View File

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

View File

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

View File

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

View File

@@ -13,7 +13,6 @@
#include "UploadFileService.h"
#include "RestartService.h"
#include "SecuritySettingsService.h"
#include "SystemStatus.h"
#include "WiFiScanner.h"
#include "NetworkSettingsService.h"
#include "NetworkStatus.h"
@@ -87,7 +86,6 @@ class ESP8266React {
AuthenticationService _authenticationService;
RestartService _restartService;
FactoryResetService _factoryResetService;
SystemStatus _systemStatus;
};
#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 = "*";
uint8_t tx_power = 0;
uint8_t provisionMode = 0;
static void read(DummySettings & settings, JsonObject root){};
static void read(DummySettings & settings){};
@@ -94,6 +96,9 @@ class DummySettingsService : public StatefulService<DummySettings> {
#define SecuritySettings DummySettings
#define MqttSettings DummySettings
#define NTPSettings DummySettings
#define OTASettings DummySettings
#define APSettings DummySettings
class ESP8266React {
public:
@@ -135,6 +140,14 @@ class ESP8266React {
return &_settings;
}
StatefulService<DummySettings> * getOTASettingsService() {
return &_settings;
}
StatefulService<DummySettings> * getAPSettingsService() {
return &_settings;
}
private:
DummySettingsService _settings;
SecuritySettingsService _securitySettingsService;

View File

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

View File

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

View File

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

View File

@@ -45,6 +45,7 @@ WebSchedulerService EMSESP::webSchedulerService = WebSchedulerService(&w
WebCustomEntityService EMSESP::webCustomEntityService = WebCustomEntityService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
#endif
WebActivityService EMSESP::webActivityService = WebActivityService(&webServer, EMSESP::esp8266React.getSecurityManager());
WebStatusService EMSESP::webStatusService = WebStatusService(&webServer, EMSESP::esp8266React.getSecurityManager());
WebDataService EMSESP::webDataService = WebDataService(&webServer, EMSESP::esp8266React.getSecurityManager());
WebAPIService EMSESP::webAPIService = WebAPIService(&webServer, EMSESP::esp8266React.getSecurityManager());

View File

@@ -39,7 +39,9 @@
#include <Preferences.h>
#include "ESP8266React.h"
#include "web/WebStatusService.h"
#include "web/WebActivityService.h"
#include "web/WebDataService.h"
#include "web/WebSettingsService.h"
#include "web/WebCustomizationService.h"
@@ -220,6 +222,7 @@ class EMSESP {
static ESP8266React esp8266React;
static WebSettingsService webSettingsService;
static WebStatusService webStatusService;
static WebActivityService webActivityService;
static WebDataService webDataService;
static WebAPIService webAPIService;
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["platform"] = EMSESP_PLATFORM;
response->setLength();
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") == "") {
EMSESP::nvs_.putString("boot", (const char *)EMSESP_DEFAULT_BOARD_PROFILE);
}
/*
#if CONFIG_IDF_TARGET_ESP32C3
settings.board_profile = root["board_profile"] | "C3MINI";

View File

@@ -18,86 +18,112 @@
#include "emsesp.h"
#ifndef EMSESP_STANDALONE
#include <esp_ota_ops.h>
#endif
namespace emsesp {
WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager) {
server->on(EMSESP_ACTIVITY_SERVICE_PATH,
HTTP_GET,
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { webStatusService(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
server->on(ESPSYSTEM_STATUS_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { ESPsystemStatus(request); });
server->on(SYSTEM_STATUS_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { systemStatus(request); });
}
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);
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["status"] = EMSESP::bus_status(); // 0, 1 or 2
root["tx_mode"] = EMSESP::txservice_.tx_mode();
root["uptime"] = EMSbus::bus_uptime();
root["num_devices"] = EMSESP::count_devices(); // excluding Controller
root["bus_uptime"] = EMSbus::bus_uptime();
root["num_devices"] = EMSESP::count_devices();
root["num_sensors"] = EMSESP::temperaturesensor_.no_sensors();
root["num_analogs"] = EMSESP::analogsensor_.no_sensors();
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()));
root["free_heap"] = EMSESP::system_.getHeapMem();
root["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
EMSESP::esp8266React.getOTASettingsService()->read([root](OTASettings & otaSettings) { root["ota_status"] = otaSettings.enabled; });
root["mqtt_status"] = EMSESP::mqtt_.connected();
#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()));
root["ntp_status"] = [] {
if (esp_sntp_enabled()) {
if (emsesp::EMSESP::system_.ntp_connected()) {
return 2;
} else {
return 1;
}
}
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

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
#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 {
@@ -28,7 +11,8 @@ class WebStatusService {
WebStatusService(AsyncWebServer * server, SecurityManager * securityManager);
private:
void webStatusService(AsyncWebServerRequest * request);
void systemStatus(AsyncWebServerRequest * request);
void ESPsystemStatus(AsyncWebServerRequest * request);
};
} // namespace emsesp