From a2fa2515b30234ddbe47e808965949e7eb248277 Mon Sep 17 00:00:00 2001 From: proddy Date: Fri, 22 Mar 2024 16:25:18 +0100 Subject: [PATCH] updates to backend to match new frontend - #1665 --- interface/package.json | 4 +- .../src/components/layout/ListMenuItem.tsx | 18 +- .../src/framework/system/SystemStatus.tsx | 21 +- interface/src/project/Sensors.tsx | 30 +-- interface/src/types/system.ts | 1 + interface/yarn.lock | 28 +- lib/framework/ESP8266React.cpp | 5 +- lib/framework/ESP8266React.h | 2 - lib/framework/SystemStatus.cpp | 66 ----- lib/framework/SystemStatus.h | 23 -- lib_standalone/ESP8266React.h | 13 + mock-api/handler.ts | 1 + mock-api/package.json | 2 +- mock-api/yarn.lock | 20 +- src/emsesp.cpp | 9 +- src/emsesp.h | 3 + src/version.h | 2 +- src/web/WebActivityService.cpp | 101 ++++++++ src/web/WebActivityService.h | 36 +++ src/web/WebDataService.cpp | 1 - src/web/WebSettingsService.cpp | 1 + src/web/WebStatusService.cpp | 242 ++++++++++-------- src/web/WebStatusService.h | 24 +- 23 files changed, 360 insertions(+), 293 deletions(-) delete mode 100644 lib/framework/SystemStatus.cpp delete mode 100644 lib/framework/SystemStatus.h create mode 100644 src/web/WebActivityService.cpp create mode 100644 src/web/WebActivityService.h diff --git a/interface/package.json b/interface/package.json index 22c5ed7e7..d1c034dba 100644 --- a/interface/package.json +++ b/interface/package.json @@ -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" }, diff --git a/interface/src/components/layout/ListMenuItem.tsx b/interface/src/components/layout/ListMenuItem.tsx index b324c69a5..67bd17ff9 100644 --- a/interface/src/components/layout/ListMenuItem.tsx +++ b/interface/src/components/layout/ListMenuItem.tsx @@ -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; 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 = ({ icon, bgcolor, label, text, to, disabled }) => ( - - {disabled ? ( - - - - ) : ( + <> + {to && !disabled ? ( = ({ icon, bgcolor, label, text, to, + ) : ( + + + )} - + ); export default LayoutMenuItem; diff --git a/interface/src/framework/system/SystemStatus.tsx b/interface/src/framework/system/SystemStatus.tsx index c244dc5ce..b6be4bfd0 100644 --- a/interface/src/framework/system/SystemStatus.tsx +++ b/interface/src/framework/system/SystemStatus.tsx @@ -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 = () => { + + + @@ -207,16 +216,6 @@ const SystemStatus: FC = () => { - - - - - - - - - - { return ( - {sensorData.ts.length > 0 && ( - <> - - {LL.TEMP_SENSORS()} - - - {selectedTemperatureSensor && ( - - )} - + + {LL.TEMP_SENSORS()} + + + {selectedTemperatureSensor && ( + )} - {sensorData?.analog_enabled === true && ( <> @@ -444,7 +439,6 @@ const Sensors: FC = () => { )} )} - diff --git a/interface/src/types/system.ts b/interface/src/types/system.ts index 3ba224219..ae7e9fa32 100644 --- a/interface/src/types/system.ts +++ b/interface/src/types/system.ts @@ -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; diff --git a/interface/yarn.lock b/interface/yarn.lock index 92e73f1c1..a93c9b8fd 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -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": - version: 5.4.2 - resolution: "typescript@patch:typescript@npm%3A5.4.2#optional!builtin::version=5.4.2&hash=5adc0c" +"typescript@patch:typescript@npm%3A^5.4.3#optional!builtin": + version: 5.4.3 + resolution: "typescript@patch:typescript@npm%3A5.4.3#optional!builtin::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 diff --git a/lib/framework/ESP8266React.cpp b/lib/framework/ESP8266React.cpp index d32f1f873..be7baf8f1 100644 --- a/lib/framework/ESP8266React.cpp +++ b/lib/framework/ESP8266React.cpp @@ -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 // diff --git a/lib/framework/ESP8266React.h b/lib/framework/ESP8266React.h index 4f5988933..733547b4d 100644 --- a/lib/framework/ESP8266React.h +++ b/lib/framework/ESP8266React.h @@ -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 diff --git a/lib/framework/SystemStatus.cpp b/lib/framework/SystemStatus.cpp deleted file mode 100644 index b90ef7c38..000000000 --- a/lib/framework/SystemStatus.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "SystemStatus.h" - -#include - -#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); -} diff --git a/lib/framework/SystemStatus.h b/lib/framework/SystemStatus.h deleted file mode 100644 index bd2d7ebf6..000000000 --- a/lib/framework/SystemStatus.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef SystemStatus_h -#define SystemStatus_h - -#include -#include -#include -#include -#include -#include - -#include "SecurityManager.h" - -#define SYSTEM_STATUS_SERVICE_PATH "/rest/systemStatus" - -class SystemStatus { - public: - SystemStatus(AsyncWebServer * server, SecurityManager * securityManager); - - private: - void systemStatus(AsyncWebServerRequest * request); -}; - -#endif diff --git a/lib_standalone/ESP8266React.h b/lib_standalone/ESP8266React.h index ca7b194b3..896092c31 100644 --- a/lib_standalone/ESP8266React.h +++ b/lib_standalone/ESP8266React.h @@ -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 { #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 * getOTASettingsService() { + return &_settings; + } + + StatefulService * getAPSettingsService() { + return &_settings; + } + private: DummySettingsService _settings; SecuritySettingsService _securitySettingsService; diff --git a/mock-api/handler.ts b/mock-api/handler.ts index e0cacbe08..41b1e1900 100644 --- a/mock-api/handler.ts +++ b/mock-api/handler.ts @@ -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, diff --git a/mock-api/package.json b/mock-api/package.json index 84d67c1e0..452155bae 100644 --- a/mock-api/package.json +++ b/mock-api/package.json @@ -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" }, diff --git a/mock-api/yarn.lock b/mock-api/yarn.lock index e65751be3..d8927febb 100644 --- a/mock-api/yarn.lock +++ b/mock-api/yarn.lock @@ -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 diff --git a/src/emsesp.cpp b/src/emsesp.cpp index de546383a..926bf77ae 100644 --- a/src/emsesp.cpp +++ b/src/emsesp.cpp @@ -45,10 +45,11 @@ WebSchedulerService EMSESP::webSchedulerService = WebSchedulerService(&w WebCustomEntityService EMSESP::webCustomEntityService = WebCustomEntityService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager()); #endif -WebStatusService EMSESP::webStatusService = WebStatusService(&webServer, EMSESP::esp8266React.getSecurityManager()); -WebDataService EMSESP::webDataService = WebDataService(&webServer, EMSESP::esp8266React.getSecurityManager()); -WebAPIService EMSESP::webAPIService = WebAPIService(&webServer, EMSESP::esp8266React.getSecurityManager()); -WebLogService EMSESP::webLogService = WebLogService(&webServer, EMSESP::esp8266React.getSecurityManager()); +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()); +WebLogService EMSESP::webLogService = WebLogService(&webServer, EMSESP::esp8266React.getSecurityManager()); using DeviceFlags = EMSdevice; using DeviceType = EMSdevice::DeviceType; diff --git a/src/emsesp.h b/src/emsesp.h index 427476e41..60e9d4e0d 100644 --- a/src/emsesp.h +++ b/src/emsesp.h @@ -39,7 +39,9 @@ #include #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; diff --git a/src/version.h b/src/version.h index f186bb10a..100ff9ffa 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.6.5-dev.18" +#define EMSESP_APP_VERSION "3.6.5-dev.19" diff --git a/src/web/WebActivityService.cpp b/src/web/WebActivityService.cpp new file mode 100644 index 000000000..a72c0fc49 --- /dev/null +++ b/src/web/WebActivityService.cpp @@ -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 . + */ + +#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(); + JsonObject statJson; + + statJson = statsJson.add(); + statJson["id"] = 0; + statJson["s"] = EMSESP::rxservice_.telegram_count(); + statJson["f"] = EMSESP::rxservice_.telegram_error_count(); + statJson["q"] = EMSESP::rxservice_.quality(); + + statJson = statsJson.add(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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(); + 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 \ No newline at end of file diff --git a/src/web/WebActivityService.h b/src/web/WebActivityService.h new file mode 100644 index 000000000..bf5a2899b --- /dev/null +++ b/src/web/WebActivityService.h @@ -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 . + */ + +#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 diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp index 4295668b9..7a613d1d1 100644 --- a/src/web/WebDataService.cpp +++ b/src/web/WebDataService.cpp @@ -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); diff --git a/src/web/WebSettingsService.cpp b/src/web/WebSettingsService.cpp index 16f1015ea..cef8da39f 100644 --- a/src/web/WebSettingsService.cpp +++ b/src/web/WebSettingsService.cpp @@ -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"; diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp index 91b33c60e..07948dee1 100644 --- a/src/web/WebStatusService.cpp +++ b/src/web/WebStatusService.cpp @@ -1,108 +1,134 @@ -/* - * 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 . - */ - -#include "emsesp.h" - -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)); -} - -void WebStatusService::webStatusService(AsyncWebServerRequest * request) { - auto * response = new AsyncJsonResponse(false); - JsonObject root = response->getRoot(); - - 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["num_sensors"] = EMSESP::temperaturesensor_.no_sensors(); - root["num_analogs"] = EMSESP::analogsensor_.no_sensors(); - - JsonArray statsJson = root["stats"].to(); - JsonObject statJson; - - statJson = statsJson.add(); - statJson["id"] = 0; - statJson["s"] = EMSESP::rxservice_.telegram_count(); - statJson["f"] = EMSESP::rxservice_.telegram_error_count(); - statJson["q"] = EMSESP::rxservice_.quality(); - - statJson = statsJson.add(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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(); - 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 \ No newline at end of file +/* + * 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 . + */ + +#include "emsesp.h" + +#ifndef EMSESP_STANDALONE +#include +#endif + +namespace emsesp { + +WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager) { + 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::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["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(); + 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 + 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 + + response->setLength(); + request->send(response); +} + +} // namespace emsesp diff --git a/src/web/WebStatusService.h b/src/web/WebStatusService.h index e5b235f52..0099364aa 100644 --- a/src/web/WebStatusService.h +++ b/src/web/WebStatusService.h @@ -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 . - */ - #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