mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
add web for Modules
This commit is contained in:
@@ -30,7 +30,7 @@
|
|||||||
"@mui/material": "^5.15.19",
|
"@mui/material": "^5.15.19",
|
||||||
"@table-library/react-table-library": "4.1.7",
|
"@table-library/react-table-library": "4.1.7",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^20.12.12",
|
"@types/node": "^20.12.13",
|
||||||
"@types/react": "^18.3.3",
|
"@types/react": "^18.3.3",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
|
|||||||
@@ -141,6 +141,14 @@ const Modules: FC = () => {
|
|||||||
|
|
||||||
useLayoutTitle('Modules');
|
useLayoutTitle('Modules');
|
||||||
|
|
||||||
|
if (modules.length === 0) {
|
||||||
|
return (
|
||||||
|
<Typography variant="body2" color="error">
|
||||||
|
No modules detected
|
||||||
|
</Typography>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table
|
<Table
|
||||||
data={{ nodes: modules }}
|
data={{ nodes: modules }}
|
||||||
@@ -192,7 +200,8 @@ const Modules: FC = () => {
|
|||||||
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
||||||
<Box mb={2} color="warning.main">
|
<Box mb={2} color="warning.main">
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">
|
||||||
Activate or de-activate EMS-ESP library modules (** experimental **)
|
Activate or de-activate EMS-ESP library modules by selecting (**
|
||||||
|
experimental **)
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
{renderModules()}
|
{renderModules()}
|
||||||
|
|||||||
@@ -1738,12 +1738,12 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@types/node@npm:^20.12.12":
|
"@types/node@npm:^20.12.13":
|
||||||
version: 20.12.12
|
version: 20.12.13
|
||||||
resolution: "@types/node@npm:20.12.12"
|
resolution: "@types/node@npm:20.12.13"
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: "npm:~5.26.4"
|
undici-types: "npm:~5.26.4"
|
||||||
checksum: 10c0/f374b763c744e8f16e4f38cf6e2c0eef31781ec9228c9e43a6f267880fea420fab0a238b59f10a7cb3444e49547c5e3785787e371fc242307310995b21988812
|
checksum: 10c0/2ac92bb631dbddfb560eb3ba4eedbb1c688044a0130bc1ef032f5c0f20148ac7c9aa3c5aaa5a9787b6c4c6299847d754b96ee8c9def951481ba6628c46b683f5
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -1974,7 +1974,7 @@ __metadata:
|
|||||||
"@trivago/prettier-plugin-sort-imports": "npm:^4.3.0"
|
"@trivago/prettier-plugin-sort-imports": "npm:^4.3.0"
|
||||||
"@types/babel__core": "npm:^7"
|
"@types/babel__core": "npm:^7"
|
||||||
"@types/lodash-es": "npm:^4.17.12"
|
"@types/lodash-es": "npm:^4.17.12"
|
||||||
"@types/node": "npm:^20.12.12"
|
"@types/node": "npm:^20.12.13"
|
||||||
"@types/react": "npm:^18.3.3"
|
"@types/react": "npm:^18.3.3"
|
||||||
"@types/react-dom": "npm:^18.3.0"
|
"@types/react-dom": "npm:^18.3.0"
|
||||||
"@types/react-router-dom": "npm:^5.3.3"
|
"@types/react-router-dom": "npm:^5.3.3"
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ class FSPersistence {
|
|||||||
if (error == DeserializationError::Ok && jsonDocument.is<JsonObject>()) {
|
if (error == DeserializationError::Ok && jsonDocument.is<JsonObject>()) {
|
||||||
JsonObject jsonObject = jsonDocument.as<JsonObject>();
|
JsonObject jsonObject = jsonDocument.as<JsonObject>();
|
||||||
_statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
|
_statefulService->updateWithoutPropagation(jsonObject, _stateUpdater);
|
||||||
|
#ifdef EMSESP_DEBUG
|
||||||
|
Serial.printf("Reading settings from %s ", _filePath);
|
||||||
|
serializeJson(jsonDocument, Serial);
|
||||||
|
Serial.println();
|
||||||
|
#endif
|
||||||
settingsFile.close();
|
settingsFile.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -67,7 +72,9 @@ class FSPersistence {
|
|||||||
|
|
||||||
// serialize the data to the file
|
// serialize the data to the file
|
||||||
#ifdef EMSESP_DEBUG
|
#ifdef EMSESP_DEBUG
|
||||||
Serial.println("Writing settings to " + String(_filePath));
|
Serial.printf("Writing settings to %s ", _filePath);
|
||||||
|
serializeJson(jsonDocument, Serial);
|
||||||
|
Serial.println();
|
||||||
#endif
|
#endif
|
||||||
serializeJson(jsonDocument, settingsFile);
|
serializeJson(jsonDocument, settingsFile);
|
||||||
settingsFile.close();
|
settingsFile.close();
|
||||||
|
|||||||
@@ -2130,6 +2130,7 @@ let emsesp_schedule = {
|
|||||||
|
|
||||||
// SCHEDULE
|
// SCHEDULE
|
||||||
let emsesp_modules = {
|
let emsesp_modules = {
|
||||||
|
// 'modules': []
|
||||||
"modules": [
|
"modules": [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
@@ -2511,15 +2512,15 @@ router
|
|||||||
// Modules
|
// Modules
|
||||||
.post(EMSESP_MODULES_ENDPOINT, async (request: any) => {
|
.post(EMSESP_MODULES_ENDPOINT, async (request: any) => {
|
||||||
const content = await request.json();
|
const content = await request.json();
|
||||||
// TODO find the one and toggle it
|
let modules = content.modules;
|
||||||
console.log('modules saved', emsesp_modules);
|
for (let i = 0; i < modules.length; i++) {
|
||||||
/*
|
const name = modules[i].name;
|
||||||
const dd_objIndex = dd.data.findIndex((obj: any) => obj.id.slice(2) === fullname);
|
const objIndex = emsesp_modules.modules.findIndex((obj: any) => obj.name === name);
|
||||||
if (dd_objIndex !== -1) {
|
if (objIndex !== -1) {
|
||||||
let changed = new Boolean(false);
|
emsesp_modules.modules[objIndex].enabled = modules[i].enabled;
|
||||||
emsesp_modules = content;
|
}
|
||||||
|
}
|
||||||
*/
|
console.log('modules updated', emsesp_modules);
|
||||||
return status(200);
|
return status(200);
|
||||||
})
|
})
|
||||||
.get(EMSESP_MODULES_ENDPOINT, () => emsesp_modules)
|
.get(EMSESP_MODULES_ENDPOINT, () => emsesp_modules)
|
||||||
|
|||||||
@@ -37,12 +37,14 @@ WebSettingsService EMSESP::webSettingsService = WebSettingsService(&we
|
|||||||
WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
|
WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
|
||||||
WebSchedulerService EMSESP::webSchedulerService = WebSchedulerService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
|
WebSchedulerService EMSESP::webSchedulerService = WebSchedulerService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
|
||||||
WebCustomEntityService EMSESP::webCustomEntityService = WebCustomEntityService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
|
WebCustomEntityService EMSESP::webCustomEntityService = WebCustomEntityService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
|
||||||
|
WebModulesService EMSESP::webModulesService = WebModulesService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
|
||||||
#else
|
#else
|
||||||
ESP8266React EMSESP::esp8266React(&webServer, &LittleFS);
|
ESP8266React EMSESP::esp8266React(&webServer, &LittleFS);
|
||||||
WebSettingsService EMSESP::webSettingsService = WebSettingsService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
|
WebSettingsService EMSESP::webSettingsService = WebSettingsService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
|
||||||
WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
|
WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
|
||||||
WebSchedulerService EMSESP::webSchedulerService = WebSchedulerService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
|
WebSchedulerService EMSESP::webSchedulerService = WebSchedulerService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
|
||||||
WebCustomEntityService EMSESP::webCustomEntityService = WebCustomEntityService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
|
WebCustomEntityService EMSESP::webCustomEntityService = WebCustomEntityService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
|
||||||
|
WebModulesService EMSESP::webModulesService = WebModulesService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
WebActivityService EMSESP::webActivityService = WebActivityService(&webServer, EMSESP::esp8266React.getSecurityManager());
|
WebActivityService EMSESP::webActivityService = WebActivityService(&webServer, EMSESP::esp8266React.getSecurityManager());
|
||||||
@@ -75,7 +77,6 @@ TemperatureSensor EMSESP::temperaturesensor_; // Temperature sensors
|
|||||||
AnalogSensor EMSESP::analogsensor_; // Analog sensors
|
AnalogSensor EMSESP::analogsensor_; // Analog sensors
|
||||||
Shower EMSESP::shower_; // Shower logic
|
Shower EMSESP::shower_; // Shower logic
|
||||||
Preferences EMSESP::nvs_; // NV Storage
|
Preferences EMSESP::nvs_; // NV Storage
|
||||||
ModuleLibrary EMSESP::module_; // Module Library
|
|
||||||
|
|
||||||
// static/common variables
|
// static/common variables
|
||||||
uint16_t EMSESP::watch_id_ = WATCH_ID_NONE; // for when log is TRACE. 0 means no trace set
|
uint16_t EMSESP::watch_id_ = WATCH_ID_NONE; // for when log is TRACE. 0 means no trace set
|
||||||
@@ -1635,6 +1636,8 @@ void EMSESP::start() {
|
|||||||
analogsensor_.start(); // Analog external sensors
|
analogsensor_.start(); // Analog external sensors
|
||||||
webLogService.start(); // apply settings to weblog service
|
webLogService.start(); // apply settings to weblog service
|
||||||
|
|
||||||
|
webModulesService.begin(); // setup the external library modules
|
||||||
|
|
||||||
// Load our library of known devices into stack mem. Names are stored in Flash memory
|
// Load our library of known devices into stack mem. Names are stored in Flash memory
|
||||||
device_library_ = {
|
device_library_ = {
|
||||||
#include "device_library.h"
|
#include "device_library.h"
|
||||||
@@ -1646,8 +1649,6 @@ void EMSESP::start() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
webServer.begin(); // start the web server
|
webServer.begin(); // start the web server
|
||||||
|
|
||||||
module_.start(this); // setup the external library modules
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// main loop calling all services
|
// main loop calling all services
|
||||||
@@ -1666,7 +1667,7 @@ void EMSESP::loop() {
|
|||||||
publish_all_loop(); // with HA messages in parts to avoid flooding the mqtt queue
|
publish_all_loop(); // with HA messages in parts to avoid flooding the mqtt queue
|
||||||
mqtt_.loop(); // sends out anything in the MQTT queue
|
mqtt_.loop(); // sends out anything in the MQTT queue
|
||||||
webSchedulerService.loop(); // handle any scheduled jobs
|
webSchedulerService.loop(); // handle any scheduled jobs
|
||||||
module_.loop(); // loop the external library modules
|
webModulesService.loop(); // loop through the external library modules
|
||||||
|
|
||||||
// force a query on the EMS devices to fetch latest data at a set interval (1 min)
|
// force a query on the EMS devices to fetch latest data at a set interval (1 min)
|
||||||
scheduled_fetch_values();
|
scheduled_fetch_values();
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
#include "web/WebAPIService.h"
|
#include "web/WebAPIService.h"
|
||||||
#include "web/WebLogService.h"
|
#include "web/WebLogService.h"
|
||||||
#include "web/WebCustomEntityService.h"
|
#include "web/WebCustomEntityService.h"
|
||||||
|
#include "web/WebModulesService.h"
|
||||||
|
|
||||||
#include "emsdevicevalue.h"
|
#include "emsdevicevalue.h"
|
||||||
#include "emsdevice.h"
|
#include "emsdevice.h"
|
||||||
@@ -222,7 +223,6 @@ class EMSESP {
|
|||||||
static RxService rxservice_;
|
static RxService rxservice_;
|
||||||
static TxService txservice_;
|
static TxService txservice_;
|
||||||
static Preferences nvs_;
|
static Preferences nvs_;
|
||||||
static ModuleLibrary module_;
|
|
||||||
|
|
||||||
// web controllers
|
// web controllers
|
||||||
static ESP8266React esp8266React;
|
static ESP8266React esp8266React;
|
||||||
@@ -235,6 +235,7 @@ class EMSESP {
|
|||||||
static WebCustomizationService webCustomizationService;
|
static WebCustomizationService webCustomizationService;
|
||||||
static WebSchedulerService webSchedulerService;
|
static WebSchedulerService webSchedulerService;
|
||||||
static WebCustomEntityService webCustomEntityService;
|
static WebCustomEntityService webCustomEntityService;
|
||||||
|
static WebModulesService webModulesService;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::string device_tostring(const uint8_t device_id);
|
static std::string device_tostring(const uint8_t device_id);
|
||||||
@@ -280,7 +281,6 @@ class EMSESP {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// EMSESP();
|
|
||||||
static uuid::log::Logger logger_;
|
static uuid::log::Logger logger_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
82
src/web/WebModulesService.cpp
Normal file
82
src/web/WebModulesService.cpp
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
#include "WebModulesService.h"
|
||||||
|
|
||||||
|
namespace emsesp {
|
||||||
|
|
||||||
|
ModuleLibrary moduleLibrary; // Module Library
|
||||||
|
EMSESP * emsesp_; // forward declaration
|
||||||
|
|
||||||
|
WebModulesService::WebModulesService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||||
|
: _httpEndpoint(WebModules::read, WebModules::update, this, server, EMSESP_MODULES_SERVICE_PATH, securityManager, AuthenticationPredicates::IS_AUTHENTICATED)
|
||||||
|
, _fsPersistence(WebModules::read, WebModules::update, this, fs, EMSESP_MODULES_FILE) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// load the settings when the service starts
|
||||||
|
void WebModulesService::begin() {
|
||||||
|
EMSESP::logger().info("Starting Modules service");
|
||||||
|
moduleLibrary.start(emsesp_);
|
||||||
|
|
||||||
|
_fsPersistence.readFromFS(); // read the file from FS
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebModulesService::loop() {
|
||||||
|
moduleLibrary.loop(); // loop the external library modules
|
||||||
|
}
|
||||||
|
|
||||||
|
// this creates the modules file, saving it to the FS
|
||||||
|
// and also calls when the Modules web page is refreshed
|
||||||
|
void WebModules::read(WebModules & webModules, JsonObject root) {
|
||||||
|
// EMSESP::logger().debug("module read called"); // TODO remove
|
||||||
|
|
||||||
|
JsonDocument doc_modules;
|
||||||
|
JsonObject root_modules = doc_modules.to<JsonObject>();
|
||||||
|
moduleLibrary.list(root_modules); // get list the external library modules, put in root json object
|
||||||
|
|
||||||
|
JsonArray modules = root["modules"].to<JsonArray>();
|
||||||
|
uint8_t counter = 0;
|
||||||
|
for (const JsonObject module : root_modules["modules"].as<JsonArray>()) {
|
||||||
|
JsonObject mi = modules.add<JsonObject>();
|
||||||
|
mi["id"] = counter++; // id is only used to render the table and must be unique
|
||||||
|
mi["name"] = module["name"].as<std::string>();
|
||||||
|
mi["author"] = module["author"].as<std::string>();
|
||||||
|
mi["version"] = module["version"].as<std::string>();
|
||||||
|
mi["status"] = module["status"].as<std::string>();
|
||||||
|
mi["enabled"] = module["enabled"].as<bool>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read any Module settings from the FS settings
|
||||||
|
// and then apply the enable/disable
|
||||||
|
// it's also called on a save
|
||||||
|
StateUpdateResult WebModules::update(JsonObject root, WebModules & webModules) {
|
||||||
|
// EMSESP::logger().debug("module update called"); // TODO remove
|
||||||
|
|
||||||
|
if (root["modules"].is<JsonArray>()) {
|
||||||
|
for (const JsonObject module : root["modules"].as<JsonArray>()) {
|
||||||
|
// set enabled/disabled
|
||||||
|
moduleLibrary.enable(module["name"], module["enabled"].as<bool>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return StateUpdateResult::CHANGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace emsesp
|
||||||
50
src/web/WebModulesService.h
Normal file
50
src/web/WebModulesService.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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 WebModulesService_h
|
||||||
|
#define WebModulesService_h
|
||||||
|
|
||||||
|
#define EMSESP_MODULES_FILE "/config/emsespModules.json"
|
||||||
|
#define EMSESP_MODULES_SERVICE_PATH "/rest/modules" // GET and POST
|
||||||
|
|
||||||
|
namespace emsesp {
|
||||||
|
|
||||||
|
class WebModules {
|
||||||
|
public:
|
||||||
|
static void read(WebModules & webModules, JsonObject root);
|
||||||
|
static StateUpdateResult update(JsonObject root, WebModules & webModules);
|
||||||
|
};
|
||||||
|
|
||||||
|
class WebModulesService : public StatefulService<WebModules> {
|
||||||
|
public:
|
||||||
|
WebModulesService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
|
||||||
|
|
||||||
|
void begin();
|
||||||
|
void loop();
|
||||||
|
|
||||||
|
#ifndef EMSESP_STANDALONE
|
||||||
|
private:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HttpEndpoint<WebModules> _httpEndpoint;
|
||||||
|
FSPersistence<WebModules> _fsPersistence;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace emsesp
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user