mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-05-09 15:35:51 +00:00
@@ -20,6 +20,7 @@ For more details go to [emsesp.org](https://emsesp.org/).
|
||||
- SRC climate creation [#2936](https://github.com/emsesp/EMS-ESP32/issues/2936) and [#2960](https://github.com/emsesp/EMS-ESP32/issues/2960)
|
||||
- missing translations [#3015](https://github.com/emsesp/EMS-ESP32/issues/3015)
|
||||
- custom entities check fetch length
|
||||
- modbus initialization [#3064](https://github.com/emsesp/EMS-ESP32/issues/3064)
|
||||
|
||||
## Changed
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
"@alova/adapter-xhr": "2.3.1",
|
||||
"@emotion/react": "^11.14.0",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
"@mui/icons-material": "^9.0.0",
|
||||
"@mui/material": "^9.0.0",
|
||||
"@mui/icons-material": "^9.0.1",
|
||||
"@mui/material": "^9.0.1",
|
||||
"@preact/compat": "^18.3.2",
|
||||
"@table-library/react-table-library": "4.1.15",
|
||||
"alova": "3.5.1",
|
||||
@@ -38,10 +38,10 @@
|
||||
"magic-string": "^0.30.21",
|
||||
"mime-types": "^3.0.2",
|
||||
"preact": "^10.29.1",
|
||||
"react": "^19.2.5",
|
||||
"react-dom": "^19.2.5",
|
||||
"react": "^19.2.6",
|
||||
"react-dom": "^19.2.6",
|
||||
"react-icons": "^5.6.0",
|
||||
"react-router": "^7.14.2",
|
||||
"react-router": "^7.15.0",
|
||||
"react-toastify": "^11.1.0",
|
||||
"typesafe-i18n": "^5.27.1",
|
||||
"typescript": "^6.0.3"
|
||||
@@ -55,17 +55,17 @@
|
||||
"@types/node": "^25.6.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"axe-core": "^4.11.3",
|
||||
"axe-core": "^4.11.4",
|
||||
"concurrently": "^9.2.1",
|
||||
"eslint": "^10.2.1",
|
||||
"eslint": "^10.3.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"prettier": "^3.8.3",
|
||||
"rollup-plugin-visualizer": "^7.0.1",
|
||||
"terser": "^5.46.1",
|
||||
"typescript-eslint": "^8.59.0",
|
||||
"vite": "^8.0.9",
|
||||
"terser": "^5.47.0",
|
||||
"typescript-eslint": "^8.59.2",
|
||||
"vite": "^8.0.11",
|
||||
"vite-plugin-imagemin": "^0.6.1",
|
||||
"vite-tsconfig-paths": "^6.1.1"
|
||||
},
|
||||
"packageManager": "pnpm@10.33.1+sha512.05ba3c1d5d1c18f68df06470d74055e62d41fc110a0c660db1b2dfb2785327f04cf0f68345d4609bc52089e7fa0343c31593b2f9594e2c5d5da426230acc9820"
|
||||
"packageManager": "pnpm@10.33.4"
|
||||
}
|
||||
|
||||
730
interface/pnpm-lock.yaml
generated
730
interface/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -59,7 +59,7 @@ framework = arduino
|
||||
board_build.partitions = partitions/esp32_partition_16M.csv
|
||||
board_upload.flash_size = 16MB
|
||||
board_build.app_partition_name = app0
|
||||
platform = espressif32@6.13.0 ; Arduino Core 2.0.17 / IDF 4.4.7
|
||||
platform = espressif32@7.0.0 ; Arduino Core 2.0.17 / IDF 4.4.7
|
||||
|
||||
; 32MB Flash variants
|
||||
[espressif32_base_32M]
|
||||
@@ -67,7 +67,7 @@ framework = arduino
|
||||
board_build.partitions = partitions/esp32_partition_32M.csv
|
||||
board_upload.flash_size = 32MB
|
||||
board_build.app_partition_name = app0
|
||||
platform = espressif32@6.13.0 ; Arduino Core 2.0.17 / IDF 4.4.7
|
||||
platform = espressif32@7.0.0 ; Arduino Core 2.0.17 / IDF 4.4.7
|
||||
|
||||
; use Tasmota's library for 4MB Flash variants.
|
||||
; Removes libs (like mbedtsl, so no WiFi_secure.h) to increase available heap
|
||||
@@ -105,7 +105,7 @@ board_build.filesystem = littlefs
|
||||
lib_deps =
|
||||
bblanchon/ArduinoJson @ 7.4.3
|
||||
ESP32Async/AsyncTCP @ 3.4.10
|
||||
ESP32Async/ESPAsyncWebServer @ 3.10.3
|
||||
ESP32Async/ESPAsyncWebServer @ 3.11.0
|
||||
; https://github.com/emsesp/EMS-ESP-Modules.git @ 1.0.8
|
||||
|
||||
; builds the web interface only, not the firmware
|
||||
|
||||
@@ -185,10 +185,14 @@ bool MqttSettingsService::configureMqtt() {
|
||||
#ifndef TASMOTA_SDK
|
||||
if (_state.enableTLS) {
|
||||
if (_state.rootCA == "insecure") {
|
||||
#if defined(EMSESP_DEBUG)
|
||||
emsesp::EMSESP::logger().debug("Start insecure MQTT");
|
||||
#endif
|
||||
static_cast<espMqttClientSecure *>(_mqttClient)->setInsecure();
|
||||
} else {
|
||||
#if defined(EMSESP_DEBUG)
|
||||
emsesp::EMSESP::logger().debug("Start secure MQTT with rootCA");
|
||||
#endif
|
||||
String certificate = "-----BEGIN CERTIFICATE-----\n" + _state.rootCA + "\n-----END CERTIFICATE-----\n";
|
||||
static_cast<espMqttClientSecure *>(_mqttClient)->setCACert(certificate.c_str());
|
||||
}
|
||||
|
||||
@@ -526,6 +526,29 @@ void System::syslog_init() {
|
||||
#endif
|
||||
}
|
||||
|
||||
// start or reconfigure modbus
|
||||
void System::modbus_init() {
|
||||
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
||||
if (settings.modbus_enabled) {
|
||||
if (EMSESP::modbus_ == nullptr) {
|
||||
EMSESP::modbus_ = new Modbus;
|
||||
EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000);
|
||||
} else if (settings.modbus_port != modbus_port_ || settings.modbus_max_clients != modbus_max_clients_ || settings.modbus_timeout != modbus_timeout_) {
|
||||
EMSESP::modbus_->stop();
|
||||
EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000);
|
||||
}
|
||||
} else if (EMSESP::modbus_ != nullptr) {
|
||||
EMSESP::modbus_->stop();
|
||||
delete EMSESP::modbus_;
|
||||
EMSESP::modbus_ = nullptr;
|
||||
}
|
||||
modbus_enabled_ = settings.modbus_enabled;
|
||||
modbus_port_ = settings.modbus_port;
|
||||
modbus_max_clients_ = settings.modbus_max_clients;
|
||||
modbus_timeout_ = settings.modbus_timeout;
|
||||
});
|
||||
}
|
||||
|
||||
// read specific major system settings to store locally for faster access
|
||||
void System::store_settings(WebSettings & settings) {
|
||||
version_ = settings.version;
|
||||
@@ -563,25 +586,6 @@ void System::store_settings(WebSettings & settings) {
|
||||
|
||||
locale_ = settings.locale;
|
||||
developer_mode_ = settings.developer_mode;
|
||||
|
||||
// start services
|
||||
if (settings.modbus_enabled) {
|
||||
if (EMSESP::modbus_ == nullptr) {
|
||||
EMSESP::modbus_ = new Modbus;
|
||||
EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000);
|
||||
} else if (settings.modbus_port != modbus_port_ || settings.modbus_max_clients != modbus_max_clients_ || settings.modbus_timeout != modbus_timeout_) {
|
||||
EMSESP::modbus_->stop();
|
||||
EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000);
|
||||
}
|
||||
} else if (EMSESP::modbus_ != nullptr) {
|
||||
EMSESP::modbus_->stop();
|
||||
delete EMSESP::modbus_;
|
||||
EMSESP::modbus_ = nullptr;
|
||||
}
|
||||
modbus_enabled_ = settings.modbus_enabled;
|
||||
modbus_port_ = settings.modbus_port;
|
||||
modbus_max_clients_ = settings.modbus_max_clients;
|
||||
modbus_timeout_ = settings.modbus_timeout;
|
||||
}
|
||||
|
||||
// Starts up core services
|
||||
@@ -631,6 +635,7 @@ void System::start() {
|
||||
network_init(); // network
|
||||
uart_init(); // start UART
|
||||
syslog_init(); // start syslog
|
||||
modbus_init(); // start modbus
|
||||
}
|
||||
|
||||
// button single click
|
||||
@@ -1713,7 +1718,7 @@ void System::exportSystemBackup(JsonObject output) {
|
||||
output["version"] = EMSESP_APP_VERSION; // add the version to the output
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// add date/time if NTP enabled and active
|
||||
// add date/time if NTP enabled and active
|
||||
if ((esp_sntp_enabled()) && (EMSESP::system_.ntp_connected())) {
|
||||
time_t now = time(nullptr);
|
||||
if (now > 1500000000L) {
|
||||
@@ -3266,7 +3271,7 @@ void System::set_valid_system_gpios() {
|
||||
valid_system_gpios_ = string_range_to_vector("0-21", "2, 8, 12-17, 18-19");
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
// https://docs.espressif.com/projects/esp-idf/en/stable/esp32s2/api-reference/peripherals/gpio.html
|
||||
// https://docs.espressif.com/projects/esp-idf/en/stable/esp32s2/api-reference/peripherals/gpio.html
|
||||
// excluded:
|
||||
// GPIO26 - GPIO32 = SPI flash and PSRAM
|
||||
// GPIO45 - GPIO46 = strapping pins
|
||||
@@ -3279,7 +3284,7 @@ void System::set_valid_system_gpios() {
|
||||
valid_system_gpios_ = string_range_to_vector("0-46", "19, 20, 26-32, 45-46, 39-42, 22-25");
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
// https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/api-reference/peripherals/gpio.html
|
||||
// https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/api-reference/peripherals/gpio.html
|
||||
// excluded:
|
||||
// GPIO3, GPIO45 - GPIO46 = strapping pins
|
||||
// GPIO26 - GPIO32 = SPI flash and PSRAM and not recommended
|
||||
@@ -3298,7 +3303,7 @@ void System::set_valid_system_gpios() {
|
||||
}
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
// https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/peripherals/gpio.html
|
||||
// https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/peripherals/gpio.html
|
||||
// excluded:
|
||||
// GPIO6 - GPIO11, GPIO16 - GPIO17 = used for SPI flash and PSRAM (dio mode only GPIO06-GPIO08, GPIO11)
|
||||
// GPIO20, GPIO24, GPIO28 - GPIO31 = don't exist
|
||||
@@ -3378,6 +3383,24 @@ void System::remove_gpio(uint8_t pin, bool also_system) {
|
||||
}
|
||||
}
|
||||
|
||||
// remove a gpio that has 0 for disable
|
||||
void System::remove_optional_gpio(uint8_t pin) {
|
||||
if (pin) {
|
||||
remove_gpio(pin, false);
|
||||
}
|
||||
}
|
||||
|
||||
// set unused gpios to default state input high-Z
|
||||
void System::reset_unused_gpios() {
|
||||
for (const auto & pin : valid_system_gpios_) {
|
||||
auto it = std::find_if(used_gpios_.begin(), used_gpios_.end(), [pin](const GpioUsage & usage) { return usage.pin == pin; });
|
||||
if (it == used_gpios_.end()) {
|
||||
LOG_DEBUG("reset pin %d", pin);
|
||||
pinMode(pin, INPUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return a list of GPIO's available for use
|
||||
std::vector<uint8_t> System::available_gpios() {
|
||||
std::vector<uint8_t> gpios;
|
||||
|
||||
@@ -122,6 +122,7 @@ class System {
|
||||
void show_mem(const char * note);
|
||||
void store_settings(class WebSettings & settings);
|
||||
void syslog_init();
|
||||
void modbus_init();
|
||||
bool check_upgrade();
|
||||
bool check_restore();
|
||||
void heartbeat_json(JsonObject output);
|
||||
@@ -376,6 +377,8 @@ class System {
|
||||
#endif
|
||||
|
||||
static void remove_gpio(uint8_t pin, bool also_system = false); // remove a gpio from both valid (optional) and used lists
|
||||
static void remove_optional_gpio(uint8_t pin);
|
||||
static void reset_unused_gpios();
|
||||
|
||||
// Partition info map: partition name -> {version, size, install_date}
|
||||
std::map<std::string, PartitionInfo, std::less<>, AllocatorPSRAM<std::pair<const std::string, PartitionInfo>>> partition_info_;
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define EMSESP_APP_VERSION "3.8.2-dev.20"
|
||||
#define EMSESP_APP_VERSION "3.8.2-dev.21"
|
||||
|
||||
@@ -166,7 +166,9 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web
|
||||
bool WebCustomEntityService::command_setvalue(const char * value, const int8_t id, const char * name) {
|
||||
// don't write if there is no value, to prevent setting an empty value by mistake when parsing attributes
|
||||
if (!strlen(value)) {
|
||||
#if defined(EMSESP_DEBUG)
|
||||
EMSESP::logger().debug("can't set empty value!");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -465,7 +465,9 @@ void WebSchedulerService::condition() {
|
||||
} else if (match.length() == 1 && match[0] == '0' && scheduleItem.retry_cnt == 1) {
|
||||
scheduleItem.retry_cnt = 0xFF;
|
||||
} else if (match.length() != 1) { // the match is not boolean
|
||||
#if defined(EMSESP_DEBUG)
|
||||
EMSESP::logger().debug("condition result: %s", match.c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
uint8_t WebSettings::flags_ = 0;
|
||||
uint16_t WebSettings::flags_ = 0;
|
||||
|
||||
WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||
: _httpEndpoint(WebSettings::read, WebSettings::update, this, server, EMSESP_SETTINGS_SERVICE_PATH, securityManager)
|
||||
@@ -114,11 +114,11 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
|
||||
reset_flags();
|
||||
|
||||
// before loading new board profile free old gpios from used list to allow remapping
|
||||
EMSESP::system_.remove_gpio(original_settings.led_gpio);
|
||||
EMSESP::system_.remove_gpio(original_settings.dallas_gpio);
|
||||
EMSESP::system_.remove_optional_gpio(original_settings.led_gpio);
|
||||
EMSESP::system_.remove_optional_gpio(original_settings.dallas_gpio);
|
||||
EMSESP::system_.remove_gpio(original_settings.pbutton_gpio);
|
||||
EMSESP::system_.remove_gpio(original_settings.rx_gpio);
|
||||
EMSESP::system_.remove_gpio(original_settings.tx_gpio);
|
||||
EMSESP::system_.remove_optional_gpio(original_settings.rx_gpio);
|
||||
EMSESP::system_.remove_optional_gpio(original_settings.tx_gpio);
|
||||
|
||||
// see if the user has changed the board profile
|
||||
// this will set: led_gpio, dallas_gpio, rx_gpio, tx_gpio, pbutton_gpio, phy_type, eth_power, eth_phy_addr, eth_clock_mode, led_type
|
||||
@@ -243,13 +243,13 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
|
||||
|
||||
// Modbus settings
|
||||
settings.modbus_enabled = root["modbus_enabled"] | EMSESP_DEFAULT_MODBUS_ENABLED;
|
||||
check_flag(original_settings.modbus_enabled, settings.modbus_enabled, ChangeFlags::RESTART);
|
||||
check_flag(original_settings.modbus_enabled, settings.modbus_enabled, ChangeFlags::MODBUS);
|
||||
settings.modbus_port = root["modbus_port"] | EMSESP_DEFAULT_MODBUS_PORT;
|
||||
check_flag(original_settings.modbus_port, settings.modbus_port, ChangeFlags::RESTART);
|
||||
check_flag(original_settings.modbus_port, settings.modbus_port, ChangeFlags::MODBUS);
|
||||
settings.modbus_max_clients = root["modbus_max_clients"] | EMSESP_DEFAULT_MODBUS_MAX_CLIENTS;
|
||||
check_flag(original_settings.modbus_max_clients, settings.modbus_max_clients, ChangeFlags::RESTART);
|
||||
check_flag(original_settings.modbus_max_clients, settings.modbus_max_clients, ChangeFlags::MODBUS);
|
||||
settings.modbus_timeout = root["modbus_timeout"] | EMSESP_DEFAULT_MODBUS_TIMEOUT;
|
||||
check_flag(original_settings.modbus_timeout, settings.modbus_timeout, ChangeFlags::RESTART);
|
||||
check_flag(original_settings.modbus_timeout, settings.modbus_timeout, ChangeFlags::MODBUS);
|
||||
|
||||
//
|
||||
// these may need mqtt restart to rebuild HA discovery topics
|
||||
@@ -372,7 +372,11 @@ void WebSettingsService::onUpdate() {
|
||||
Mqtt::reset_mqtt(); // reload MQTT, init HA etc
|
||||
}
|
||||
|
||||
if (WebSettings::has_flags(WebSettings::ChangeFlags::MODBUS)) {
|
||||
EMSESP::system_.modbus_init();
|
||||
}
|
||||
WebSettings::reset_flags();
|
||||
EMSESP::system_.reset_unused_gpios();
|
||||
}
|
||||
|
||||
void WebSettingsService::begin() {
|
||||
@@ -523,7 +527,7 @@ void WebSettings::set_board_profile(WebSettings & settings) {
|
||||
}
|
||||
|
||||
// returns true if the value was changed
|
||||
bool WebSettings::check_flag(int prev_v, int new_v, uint8_t flag) {
|
||||
bool WebSettings::check_flag(int prev_v, int new_v, uint16_t flag) {
|
||||
if (prev_v != new_v) {
|
||||
add_flags(flag);
|
||||
#if defined(EMSESP_DEBUG)
|
||||
@@ -534,11 +538,11 @@ bool WebSettings::check_flag(int prev_v, int new_v, uint8_t flag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void WebSettings::add_flags(uint8_t flags) {
|
||||
void WebSettings::add_flags(uint16_t flags) {
|
||||
flags_ |= flags;
|
||||
}
|
||||
|
||||
bool WebSettings::has_flags(uint8_t flags) {
|
||||
bool WebSettings::has_flags(uint16_t flags) {
|
||||
return (flags_ & flags) == flags;
|
||||
}
|
||||
|
||||
@@ -546,7 +550,7 @@ void WebSettings::reset_flags() {
|
||||
flags_ = ChangeFlags::NONE;
|
||||
}
|
||||
|
||||
uint8_t WebSettings::get_flags() {
|
||||
uint16_t WebSettings::get_flags() {
|
||||
return flags_;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ class WebSettings {
|
||||
static void read(WebSettings & settings, JsonObject root);
|
||||
static StateUpdateResult update(JsonObject root, WebSettings & settings);
|
||||
|
||||
enum ChangeFlags : uint8_t {
|
||||
enum ChangeFlags : uint16_t {
|
||||
NONE = 0,
|
||||
UART = (1 << 0), // 1 - uart
|
||||
SYSLOG = (1 << 1), // 2 - syslog
|
||||
@@ -98,19 +98,20 @@ class WebSettings {
|
||||
LED = (1 << 5), // 32 - led
|
||||
BUTTON = (1 << 6), // 64 - button
|
||||
MQTT = (1 << 7), // 128 - mqtt
|
||||
RESTART = 0xFF // 255 - restart request (all changes)
|
||||
MODBUS = (1 << 8), // 256 - modbus
|
||||
RESTART = 0xFFFF // restart request (all changes)
|
||||
};
|
||||
|
||||
static bool check_flag(int prev_v, int new_v, uint8_t flag);
|
||||
static void add_flags(uint8_t flags);
|
||||
static bool has_flags(uint8_t flags);
|
||||
static void reset_flags();
|
||||
static uint8_t get_flags();
|
||||
static bool check_flag(int prev_v, int new_v, uint16_t flag);
|
||||
static void add_flags(uint16_t flags);
|
||||
static bool has_flags(uint16_t flags);
|
||||
static void reset_flags();
|
||||
static uint16_t get_flags();
|
||||
|
||||
private:
|
||||
static void set_board_profile(WebSettings & settings);
|
||||
|
||||
static uint8_t flags_;
|
||||
static uint16_t flags_;
|
||||
};
|
||||
|
||||
class WebSettingsService : public StatefulService<WebSettings> {
|
||||
|
||||
Reference in New Issue
Block a user