This commit is contained in:
MichaelDvP
2024-06-15 13:47:49 +02:00
237 changed files with 12578 additions and 17832 deletions

View File

@@ -636,15 +636,15 @@ void EMSESPShell::stopped() {
// show welcome banner
void EMSESPShell::display_banner() {
println();
printfln("┌──────────────────────────────────────────");
printfln("│ %sEMS-ESP version %-12s%s ", COLOR_BOLD_ON, EMSESP_APP_VERSION, COLOR_BOLD_OFF);
printfln(" ");
printfln("│ %shelp%s to show available commands ", COLOR_UNDERLINE, COLOR_RESET);
printfln("│ %ssu%s to access admin commands ", COLOR_UNDERLINE, COLOR_RESET);
printfln(" ");
printfln("│ %s%shttps://github.com/emsesp/EMS-ESP32%s ", COLOR_BRIGHT_GREEN, COLOR_UNDERLINE, COLOR_RESET);
printfln(" ");
printfln("└──────────────────────────────────────────");
printfln("┌───────────────────────────────────────┐");
printfln(" %sEMS-ESP version %-20s%s │", COLOR_BOLD_ON, EMSESP_APP_VERSION, COLOR_BOLD_OFF);
printfln("│ │");
printfln(" %shelp%s to show available commands │", COLOR_UNDERLINE, COLOR_RESET);
printfln(" %ssu%s to access admin commands │", COLOR_UNDERLINE, COLOR_RESET);
printfln("│ │");
printfln(" %s%shttps://github.com/emsesp/EMS-ESP32%s │", COLOR_BRIGHT_GREEN, COLOR_UNDERLINE, COLOR_RESET);
printfln("│ │");
printfln("└───────────────────────────────────────┘");
println();
// set console name

View File

@@ -218,7 +218,7 @@
#endif
#ifndef EMSESP_DEFAULT_ENTITY_FORMAT
#define EMSESP_DEFAULT_ENTITY_FORMAT 1 // in MQTT discovery, use shortnames and not multiple (prefixed with base)
#define EMSESP_DEFAULT_ENTITY_FORMAT 1 // in MQTT discovery, single instance, shortname (EntityFormat::SINGLE_SHORT)
#endif
// matches Web UI settings
@@ -241,13 +241,13 @@ enum {
};
#if CONFIG_IDF_TARGET_ESP32C3
#define EMSESP_PLATFORM "ESP32-C3";
#define EMSESP_PLATFORM "ESP32-C3"
#elif CONFIG_IDF_TARGET_ESP32S2
#define EMSESP_PLATFORM "ESP32-S2";
#define EMSESP_PLATFORM "ESP32-S2"
#elif CONFIG_IDF_TARGET_ESP32S3
#define EMSESP_PLATFORM "ESP32-S3";
#define EMSESP_PLATFORM "ESP32-S3"
#elif CONFIG_IDF_TARGET_ESP32 || EMSESP_STANDALONE
#define EMSESP_PLATFORM "ESP32";
#define EMSESP_PLATFORM "ESP32"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif

View File

@@ -1730,15 +1730,10 @@ void Boiler::process_UBASetPoints(std::shared_ptr<const Telegram> telegram) {
}
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
// 0x35 - not yet implemented, not readable, only for settings
void Boiler::process_UBAFlags(std::shared_ptr<const Telegram> telegram) {
}
#pragma GCC diagnostic pop
// 0x1C
// 08 00 1C 94 0B 0A 1D 31 08 00 80 00 00 00 -> message for 29.11.2020
// 08 00 1C 94 0B 0A 1D 31 00 00 00 00 00 00 -> message reset

View File

@@ -187,9 +187,6 @@ void Heatpump::process_HPMonitor2(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, airHumidity_, 1);
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
/*
* Type 0x42B- HeatPump Monitor 1
* e.g. "38 10 FF 00 03 2B 00 D1 08 2A 01"
@@ -198,8 +195,6 @@ void Heatpump::process_HPMonitor1(std::shared_ptr<const Telegram> telegram) {
// still to implement
}
#pragma GCC diagnostic pop
// 0x09A0
// Heatpump(0x53) -> All(0x00), ?(0x09A0), data: 02 23 01 3E 01 39 00 5D 01 DE 01 38 00 40 00 5E 00 58 00 3F 01 34 00 02
void Heatpump::process_HPTemperature(std::shared_ptr<const Telegram> telegram) {

View File

@@ -162,9 +162,6 @@ void Heatsource::process_amSettingMessage(std::shared_ptr<const Telegram> telegr
has_update(telegram, releaseWait_, 15); // pos 15: Boiler release wait time (min)
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
// 0x054F AM200 not broadcasted message, 7 bytes long
// Boiler(0x60) -> Me(0x0B), amCommand(0x054F), data: 00 00 00 00 00 00 00
void Heatsource::process_amCommandMessage(std::shared_ptr<const Telegram> telegram) {
@@ -182,8 +179,6 @@ void Heatsource::process_amExtraMessage(std::shared_ptr<const Telegram> telegram
has_update(telegram, blockRemainWw_, 25); // minutes
}
#pragma GCC diagnostic pop
// Settings AM200
// pos 12: off(00)/Keelbypass(01)/(hc1pump(02) only standalone)

View File

@@ -154,9 +154,6 @@ void Mixer::process_MMPLUSConfigMessage_HC(std::shared_ptr<const Telegram> teleg
has_update(telegram, flowTempOffset_, 2); // Mixer increase [0-20 K]
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
// Thermostat(0x10) -> Mixer(0x20), ?(0x2E1), data: 01 1C 64 00 01
// Thermostat(0x10) -> Mixing Module(0x20), (0x2E1), data: 01 00 00 00 01
// Thermostat(0x10) -> Mixing Module(0x20), (0x2EB), data: 00
@@ -180,8 +177,6 @@ void Mixer::process_IPMSetMessage(std::shared_ptr<const Telegram> telegram) {
// pos 1: pump in %?
}
#pragma GCC diagnostic pop
bool Mixer::set_flowSetTemp(const char * value, const int8_t id) {
int v;
if (!Helpers::value2number(value, v)) {

View File

@@ -614,9 +614,6 @@ void Thermostat::process_RC10Set(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, heatingpid_, 6);
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
// type 0xB2, mode setting Data: 04 00
// not used, we read mode from monitor 0xB1
void Thermostat::process_RC10Set_2(std::shared_ptr<const Telegram> telegram) {
@@ -629,8 +626,6 @@ void Thermostat::process_RC10Set_2(std::shared_ptr<const Telegram> telegram) {
// has_update(hc->mode, mode >> 1); // store as enum 0, 1, 2
}
#pragma GCC diagnostic pop
// 0xA8 - for reading the mode from the RC20 thermostat (0x17)
// RC20Set(0xA8), data: 01 00 FF F6 01 06 00 01 0D 01 00 FF FF 01 02 02 02 00 00 05 1E 05 1E 02 1C 00 FF 00 00 26 02
void Thermostat::process_RC20Set(std::shared_ptr<const Telegram> telegram) {
@@ -1613,7 +1608,7 @@ void Thermostat::process_RCTime(std::shared_ptr<const Telegram> telegram) {
tm_->tm_isdst = -1; // determine dst
ttime = mktime(tm_); // thermostat time
}
struct timeval newnow = {.tv_sec = ttime};
struct timeval newnow = {.tv_sec = ttime, .tv_usec = 0};
settimeofday(&newnow, nullptr);
LOG_INFO("ems-esp time set from thermostat");
}

View File

@@ -168,14 +168,11 @@ void Water::process_SM100wwStatus2(std::shared_ptr<const Telegram> telegram) {
has_update(telegram, wwPumpMod_, 9);
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
// SM100wwCommand - 0x07AB
// Thermostat(0x10) -> Solar Module(0x2A), (0x7AB), data: 01 00 01
void Water::process_SM100wwCommand(std::shared_ptr<const Telegram> telegram) {
// not implemented yet
}
#pragma GCC diagnostic pop
/*
* MM100 messages

View File

@@ -1701,7 +1701,7 @@ bool EMSdevice::generate_values(JsonObject output, const int8_t tag_filter, cons
char time_s[60];
snprintf(time_s,
sizeof(time_s),
"%d %s %d %s %d %s",
"%lu %s %lu %s %lu %s",
(time_value / 1440),
Helpers::translated_word(FL_(days)),
((time_value % 1440) / 60),

View File

@@ -37,12 +37,14 @@ WebSettingsService EMSESP::webSettingsService = WebSettingsService(&we
WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
WebSchedulerService EMSESP::webSchedulerService = WebSchedulerService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
WebCustomEntityService EMSESP::webCustomEntityService = WebCustomEntityService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
WebModulesService EMSESP::webModulesService = WebModulesService(&webServer, &dummyFS, EMSESP::esp8266React.getSecurityManager());
#else
ESP8266React EMSESP::esp8266React(&webServer, &LittleFS);
WebSettingsService EMSESP::webSettingsService = WebSettingsService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
WebCustomizationService EMSESP::webCustomizationService = WebCustomizationService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
WebSchedulerService EMSESP::webSchedulerService = WebSchedulerService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
WebCustomEntityService EMSESP::webCustomEntityService = WebCustomEntityService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
WebModulesService EMSESP::webModulesService = WebModulesService(&webServer, &LittleFS, EMSESP::esp8266React.getSecurityManager());
#endif
WebActivityService EMSESP::webActivityService = WebActivityService(&webServer, EMSESP::esp8266React.getSecurityManager());
@@ -1589,7 +1591,7 @@ void EMSESP::start() {
nvs_.begin("ems-esp", false, "nvs"); // fallback to small nvs
}
#ifndef EMSESP_STANDALONE
LOG_INFO("Starting EMS-ESP version %s from partition %s", EMSESP_APP_VERSION, esp_ota_get_running_partition()->label); // welcome message
LOG_INFO("Starting EMS-ESP version %s from %s partition", EMSESP_APP_VERSION, esp_ota_get_running_partition()->label); // welcome message
#else
LOG_INFO("Starting EMS-ESP version %s", EMSESP_APP_VERSION); // welcome message
#endif
@@ -1634,6 +1636,8 @@ void EMSESP::start() {
analogsensor_.start(); // Analog external sensors
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
device_library_ = {
#include "device_library.h"
@@ -1663,6 +1667,7 @@ void EMSESP::loop() {
publish_all_loop(); // with HA messages in parts to avoid flooding the mqtt queue
mqtt_.loop(); // sends out anything in the MQTT queue
webSchedulerService.loop(); // handle any scheduled jobs
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)
scheduled_fetch_values();

View File

@@ -49,6 +49,7 @@
#include "web/WebAPIService.h"
#include "web/WebLogService.h"
#include "web/WebCustomEntityService.h"
#include "web/WebModulesService.h"
#include "emsdevicevalue.h"
#include "emsdevice.h"
@@ -65,6 +66,10 @@
#include "command.h"
#include "version.h"
// Load external modules
class Module {}; // forward declaration
#include <ModuleLibrary.h>
#define WATCH_ID_NONE 0 // no watch id set
// helpers for callback functions
@@ -230,6 +235,7 @@ class EMSESP {
static WebCustomizationService webCustomizationService;
static WebSchedulerService webSchedulerService;
static WebCustomEntityService webCustomEntityService;
static WebModulesService webModulesService;
private:
static std::string device_tostring(const uint8_t device_id);
@@ -275,7 +281,6 @@ class EMSESP {
#endif
protected:
// EMSESP();
static uuid::log::Logger logger_;
};

View File

@@ -676,14 +676,14 @@ bool Mqtt::queue_publish(const std::string & topic, const std::string & payload)
return queue_publish_message(topic, payload, mqtt_retain_);
}
// MQTT Publish, using a user's retain flag - except for char * strings
// MQTT Publish, using a user's retain flag - except for char * strings payload
bool Mqtt::queue_publish(const char * topic, const char * payload) {
return queue_publish_message((topic), payload, mqtt_retain_);
return queue_publish_message(topic, payload, mqtt_retain_);
}
// MQTT Publish, using a specific retain flag, topic is a flash string
// MQTT Publish, using a user's retain flag - std::string payload
bool Mqtt::queue_publish(const char * topic, const std::string & payload) {
return queue_publish_message((topic), payload, mqtt_retain_);
return queue_publish_message(topic, payload, mqtt_retain_);
}
bool Mqtt::queue_publish(const char * topic, const JsonObjectConst payload) {
@@ -697,7 +697,7 @@ bool Mqtt::queue_publish(const std::string & topic, const JsonObjectConst payloa
// MQTT Publish, using a specific retain flag, topic is a flash string, forcing retain flag
bool Mqtt::queue_publish_retain(const char * topic, const std::string & payload, const bool retain) {
return queue_publish_message((topic), payload, retain);
return queue_publish_message(topic, payload, retain);
}
// publish json doc, only if its not empty, using the retain flag
@@ -841,18 +841,23 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
// build unique identifier also used as object_id which also becomes the Entity ID in HA
char uniq_id[80];
// list of boiler entities that need conversion for 3.6 compatibility, add ww suffix
// used when entity_format is SINGLE_OLD or MULTI_OLD to keep with 3.6.5
// see #1714 - https://github.com/emsesp/EMS-ESP32/issues/1714
const char * dhw_old[] =
{FL_(nrgWw)[0], FL_(upTimeCompWw)[0], FL_(nrgConsCompWw)[0], FL_(auxElecHeatNrgConsWw)[0], FL_(nrgSuppWw)[0], FL_(wwAltOpPrioWw)[0], FL_(hpCircPumpWw)[0]};
uint8_t num_dhw_old = sizeof(dhw_old) / sizeof(dhw_old[0]);
// create the uniq_d based on the entity format
if (Mqtt::entity_format() == entityFormat::MULTI_SHORT) {
// prefix base name to each uniq_id and use the shortname
// base name + shortname
snprintf(uniq_id, sizeof(uniq_id), "%s_%s_%s", mqtt_basename_.c_str(), device_name, entity_with_tag);
} else if (Mqtt::entity_format() == entityFormat::SINGLE_SHORT) {
// shortname, no mqtt base. This is the default version.
// shortname (default)
snprintf(uniq_id, sizeof(uniq_id), "%s_%s", device_name, entity_with_tag);
} else if (Mqtt::entity_format() == entityFormat::SINGLE_OLD) {
// shortname, remap to 3.6.
// shortname, remap to 3.6
if (has_tag && (device_type == EMSdevice::DeviceType::BOILER || device_type == EMSdevice::DeviceType::THERMOSTAT)
&& tag == DeviceValue::DeviceValueTAG::TAG_DHW1) {
snprintf(entity_with_tag, sizeof(entity_with_tag), "ww%s", entity);
@@ -872,7 +877,7 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
snprintf(uniq_id, sizeof(uniq_id), "%s_%s", device_name, entity_with_tag);
}
} else if (Mqtt::entity_format() == entityFormat::MULTI_OLD) {
// shortname, remap to 3.6.
// base name + shortname, remap to 3.6
if (has_tag && (device_type == EMSdevice::DeviceType::BOILER || device_type == EMSdevice::DeviceType::THERMOSTAT)
&& tag == DeviceValue::DeviceValueTAG::TAG_DHW1) {
snprintf(entity_with_tag, sizeof(entity_with_tag), "ww%s", entity);
@@ -1176,8 +1181,11 @@ void Mqtt::add_ha_uom(JsonObject doc, const uint8_t type, const uint8_t uom, con
doc[sc_ha] = F_(measurement);
break;
case DeviceValueUOM::WH:
// https://github.com/emsesp/EMS-ESP32/issues/1796
if (entity == FL_(energyToday)[0]) {
doc[sc_ha] = F_(total_increasing);
} else if (entity == FL_(energyLastHour)[0]) {
doc[sc_ha] = "total";
} else {
doc[sc_ha] = F_(measurement);
}
@@ -1388,19 +1396,17 @@ void Mqtt::add_ha_sections_to_doc(const char * name,
char tpl[150];
// make local copy of state, as the pointer will get derefenced
char state[50];
strcpy(state, state_t);
// skip conditional Jinja2 templates if not home assistant
if (discovery_type() == discoveryType::HOMEASSISTANT) {
// EMS-ESP status check
// snprintf(tpl, sizeof(tpl), "%s/status", Mqtt::base().c_str());
// avty_json["t"] = tpl;
// snprintf(tpl, sizeof(tpl), tpl_draft, "value == 'online'");
// avty_json["val_tpl"] = tpl;
// avty.add(avty_json); // returns 0 if no mem
const char * tpl_draft = "{{'online' if %s else 'offline'}}";
// condition 1
avty_json.clear();
avty_json["t"] = state_t;
avty_json["t"] = state;
snprintf(tpl, sizeof(tpl), tpl_draft, cond1 == nullptr ? "value is defined" : cond1);
avty_json["val_tpl"] = tpl;
avty.add(avty_json); // returns 0 if no mem
@@ -1408,7 +1414,7 @@ void Mqtt::add_ha_sections_to_doc(const char * name,
// condition 2
if (cond2 != nullptr) {
avty_json.clear();
avty_json["t"] = state_t;
avty_json["t"] = state;
snprintf(tpl, sizeof(tpl), tpl_draft, cond2);
avty_json["val_tpl"] = tpl;
avty.add(avty_json); // returns 0 if no mem
@@ -1417,7 +1423,7 @@ void Mqtt::add_ha_sections_to_doc(const char * name,
// negative condition
if (negcond != nullptr) {
avty_json.clear();
avty_json["t"] = state_t;
avty_json["t"] = state;
snprintf(tpl, sizeof(tpl), "{{'offline' if %s else 'online'}}", negcond);
avty_json["val_tpl"] = tpl;
avty.add(avty_json); // returns 0 if no mem

View File

@@ -138,10 +138,6 @@ class Mqtt {
return discovery_prefix_ + "/";
}
static void base(const char * base) {
mqtt_base_ = base;
}
static uint32_t publish_count() {
return mqtt_message_id_;
}

View File

@@ -45,6 +45,7 @@
#else // ESP32 Before IDF 4.0
#include "../rom/rtc.h"
#endif
#include <esp_mac.h>
#endif
namespace emsesp {
@@ -291,7 +292,7 @@ void System::system_restart(const char * partitionname) {
}
esp_ota_set_boot_partition(partition);
}
LOG_INFO("Restarting EMS-ESP from partition '%s'", partitionname);
LOG_INFO("Restarting EMS-ESP from %s partition", partitionname);
} else {
LOG_INFO("Restarting EMS-ESP...");
}
@@ -963,10 +964,17 @@ void System::show_system(uuid::console::Shell & shell) {
shell.println("System:");
shell.printfln(" Version: %s", EMSESP_APP_VERSION);
shell.printfln(" Platform: %s", EMSESP_PLATFORM);
shell.printfln(" Language: %s", locale().c_str());
shell.printfln(" Board profile: %s", board_profile().c_str());
shell.printfln(" Uptime: %s", uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3).c_str());
#ifndef EMSESP_STANDALONE
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/misc_system_api.html
unsigned char mac_base[6] = {0};
esp_efuse_mac_get_default(mac_base);
esp_read_mac(mac_base, ESP_MAC_WIFI_STA);
shell.printfln(" Base MAC Address: %02X:%02X:%02X:%02X:%02X:%02X", mac_base[0], mac_base[1], mac_base[2], mac_base[3], mac_base[4], mac_base[5]);
shell.printfln(" SDK version: %s", ESP.getSdkVersion());
shell.printfln(" CPU frequency: %lu MHz", ESP.getCpuFreqMHz());
shell.printfln(" Free heap/Max alloc: %lu KB / %lu KB", getHeapMem(), getMaxAllocMem());

View File

@@ -1186,7 +1186,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
EMSESP::mqtt_.incoming("ems-esp/thermostat/mode/auto", "auto"); // invalid, not allowed
// check extended MQTT base
Mqtt::base("home/cellar/heating");
// Mqtt::base("home/cellar/heating");
EMSESP::mqtt_.incoming("home/cellar/heating/thermostat/mode"); // empty payload
// Web API TESTS

View File

@@ -73,12 +73,13 @@ void EMSuart::uart_event_task(void * pvParameters) {
void EMSuart::start(const uint8_t tx_mode, const uint8_t rx_gpio, const uint8_t tx_gpio) {
if (tx_mode_ == 0xFF) {
uart_config_t uart_config = {
.baud_rate = EMSUART_BAUD,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
.baud_rate = EMSUART_BAUD,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.rx_flow_ctrl_thresh = 0, // not used - https://docs.espressif.com/projects/esp-idf/en/v3.3.6/api-reference/peripherals/uart.html
.source_clk = UART_SCLK_APB,
};
#if defined(EMSUART_RX_INVERT)
inverse_mask |= UART_SIGNAL_RXD_INV;

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.7.0-dev.12"
#define EMSESP_APP_VERSION "3.7.0-dev.13"

View File

@@ -0,0 +1,91 @@
/*
* 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");
#ifdef EMSESP_TEST
moduleLibrary.start(emsesp_, true); // hot load the test modules as well
#else
moduleLibrary.start(emsesp_);
#endif
_fsPersistence.readFromFS(); // read the file from FS - this will call the update function WebModules::update()
}
void WebModulesService::loop() {
moduleLibrary.loop(); // loop the external library modules
}
// this creates the modules settings file, saving it to the file system
// it adds data to an empty 'root' json object
// and also calls when the Modules web page is refreshed/loaded
void WebModules::read(WebModules & webModules, JsonObject root) {
JsonDocument doc_modules;
JsonObject root_modules = doc_modules.to<JsonObject>();
moduleLibrary.list(root_modules); // get list the external library modules, put in a 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["key"] = module["key"].as<std::string>();
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<uint8_t>();
mi["enabled"] = module["enabled"].as<bool>();
mi["message"] = module["message"].as<std::string>();
mi["license"] = module["license"].as<std::string>();
}
}
// read any Module settings from the settings file
// and then apply the enable/disable that is set by the user
// This function is called when ems-esp boots and also on a save from the Modules web page
StateUpdateResult WebModules::update(JsonObject root, WebModules & webModules) {
bool err = false;
if (root["modules"].is<JsonArray>()) {
for (const JsonObject module : root["modules"].as<JsonArray>()) {
auto key = module["key"].as<const char *>();
auto license = module["license"].as<const char *>();
auto enable = module["enabled"].as<bool>();
err &= moduleLibrary.enable(key, license, enable);
}
}
return err ? StateUpdateResult::ERROR : StateUpdateResult::CHANGED;
}
} // namespace emsesp

View 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

View File

@@ -31,10 +31,7 @@ void WebSchedulerService::begin() {
_fsPersistence.readFromFS();
// save a local pointer to the scheduler item list
EMSESP::webSchedulerService.read([&](WebScheduler & webScheduler) {
//
scheduleItems_ = &webScheduler.scheduleItems;
});
EMSESP::webSchedulerService.read([&](WebScheduler & webScheduler) { scheduleItems_ = &webScheduler.scheduleItems; });
EMSESP::logger().info("Starting Scheduler service");
Mqtt::subscribe(EMSdevice::DeviceType::SCHEDULER, "scheduler/#", nullptr); // use empty function callback

View File

@@ -251,7 +251,6 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
settings.analog_enabled = root["analog_enabled"] | EMSESP_DEFAULT_ANALOG_ENABLED;
check_flag(prev, settings.analog_enabled, ChangeFlags::ADC);
//
// these need system restarts first before settings are activated...
//
@@ -294,7 +293,6 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
//
// without checks or necessary restarts...
//
settings.trace_raw = root["trace_raw"] | EMSESP_DEFAULT_TRACELOG_RAW;
EMSESP::trace_raw(settings.trace_raw);

View File

@@ -70,6 +70,16 @@ void WebStatusService::systemStatus(AsyncWebServerRequest * request) {
root["ap_status"] = EMSESP::esp8266React.apStatus();
if (emsesp::EMSESP::system_.ethernet_connected()) {
root["network_status"] = 10; // custom code #10 - ETHERNET_STATUS_CONNECTED
root["wifi_rssi"] = 0;
} else {
root["network_status"] = static_cast<uint8_t>(WiFi.status());
#ifndef EMSESP_STANDALONE
root["wifi_rssi"] = WiFi.RSSI();
#endif
}
response->setLength();
request->send(response);
}