mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-05-02 04:05:14 +00:00
Compare commits
6 Commits
c9c059ca65
...
f8257de0dd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8257de0dd | ||
|
|
3b3ecc9f1d | ||
|
|
84105acf5d | ||
|
|
def5173692 | ||
|
|
6b31fef1af | ||
|
|
51d90095aa |
@@ -8,7 +8,7 @@ the LICENSE file.
|
|||||||
|
|
||||||
#include "ClientPosix.h"
|
#include "ClientPosix.h"
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
|
||||||
namespace espMqttClientInternals {
|
namespace espMqttClientInternals {
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ the LICENSE file.
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ espMqttClientSecure & espMqttClientSecure::setPreSharedKey(const char * pskIdent
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
espMqttClient::espMqttClient()
|
espMqttClient::espMqttClient()
|
||||||
: MqttClientSetup(espMqttClientTypes::UseInternalTask::NO)
|
: MqttClientSetup(espMqttClientTypes::UseInternalTask::NO)
|
||||||
, _client() {
|
, _client() {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ the LICENSE file.
|
|||||||
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||||
#include "Transport/ClientSync.h"
|
#include "Transport/ClientSync.h"
|
||||||
#include "Transport/ClientSecureSync.h"
|
#include "Transport/ClientSecureSync.h"
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__) || defined(__APPLE__)
|
||||||
#include "Transport/ClientPosix.h"
|
#include "Transport/ClientPosix.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ class espMqttClientSecure : public MqttClientSetup<espMqttClientSecure> {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
class espMqttClient : public MqttClientSetup<espMqttClient> {
|
class espMqttClient : public MqttClientSetup<espMqttClient> {
|
||||||
public:
|
public:
|
||||||
espMqttClient();
|
espMqttClient();
|
||||||
|
|||||||
@@ -380,12 +380,16 @@ std::string commands(std::string & expr, bool quotes) {
|
|||||||
if (return_code != CommandRet::OK && return_code != CommandRet::NO_VALUE) {
|
if (return_code != CommandRet::OK && return_code != CommandRet::NO_VALUE) {
|
||||||
return expr = "";
|
return expr = "";
|
||||||
}
|
}
|
||||||
|
std::string data;
|
||||||
std::string data = output["api_data"] | "";
|
if (output["api_data"].is<std::string>()) {
|
||||||
|
data = output["api_data"].as<std::string>();
|
||||||
if (!isnum(data) && quotes) {
|
if (!isnum(data) && quotes) {
|
||||||
data.insert(data.begin(), '"');
|
data.insert(data.begin(), '"');
|
||||||
data.insert(data.end(), '"');
|
data.insert(data.end(), '"');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
serializeJson(output, data);
|
||||||
|
}
|
||||||
expr.replace(f, l, data);
|
expr.replace(f, l, data);
|
||||||
e = f + data.length();
|
e = f + data.length();
|
||||||
expr_new = Helpers::toLower(expr);
|
expr_new = Helpers::toLower(expr);
|
||||||
@@ -700,7 +704,6 @@ std::string compute(const std::string & expr) {
|
|||||||
std::string cmd = expr_new.substr(f, e - f).c_str();
|
std::string cmd = expr_new.substr(f, e - f).c_str();
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
if (DeserializationError::Ok == deserializeJson(doc, cmd)) {
|
if (DeserializationError::Ok == deserializeJson(doc, cmd)) {
|
||||||
HTTPClient http;
|
|
||||||
std::string url, header_s, value_s, method_s, key_s, keys_s;
|
std::string url, header_s, value_s, method_s, key_s, keys_s;
|
||||||
// search keys lower case
|
// search keys lower case
|
||||||
for (JsonPair p : doc.as<JsonObject>()) {
|
for (JsonPair p : doc.as<JsonObject>()) {
|
||||||
@@ -720,33 +723,126 @@ std::string compute(const std::string & expr) {
|
|||||||
keys_s = p.key().c_str();
|
keys_s = p.key().c_str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (http.begin(url.c_str())) {
|
bool content_set = false;
|
||||||
int httpResult = 0;
|
|
||||||
for (JsonPair p : doc[header_s].as<JsonObject>()) {
|
|
||||||
http.addHeader(p.key().c_str(), p.value().as<std::string>().c_str());
|
|
||||||
}
|
|
||||||
std::string value = doc[value_s] | "";
|
std::string value = doc[value_s] | "";
|
||||||
std::string method = doc[method_s] | "get";
|
std::string method = doc[method_s] | "GET";
|
||||||
|
if (value.length()) {
|
||||||
// if there is data, force a POST
|
method = "POST";
|
||||||
|
}
|
||||||
|
std::string result;
|
||||||
|
int httpResult = 0;
|
||||||
|
#ifndef NO_TLS_SUPPORT
|
||||||
|
if (Helpers::toLower(url.c_str()).starts_with("https://")) {
|
||||||
|
WiFiClient * basic_client = new WiFiClient;
|
||||||
|
ESP_SSLClient * ssl_client = new ESP_SSLClient;
|
||||||
|
ssl_client->setInsecure(); // with root CA we should set here: ssl_client->setCACert(rootCACert);
|
||||||
|
ssl_client->setBufferSizes(1024, 1024);
|
||||||
|
ssl_client->setSessionTimeout(120); // Set the timeout in seconds (>=120 seconds)
|
||||||
|
url.replace(0, 8, "");
|
||||||
|
std::string host = url;
|
||||||
|
auto index = url.find_first_of('/');
|
||||||
|
if (index != std::string::npos) {
|
||||||
|
host = url.substr(0, index);
|
||||||
|
url.replace(0, index, "");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
index = host.find_first_of('@');
|
||||||
|
std::string auth;
|
||||||
|
if (index != std::string::npos) {
|
||||||
|
auth = base64::encode(host.substr(0, index));
|
||||||
|
host.replace(0, index, "");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
ssl_client->setClient(basic_client);
|
||||||
|
if (ssl_client->connect(host.c_str(), 443)) {
|
||||||
if (value.length() || Helpers::toLower(method) == "post") {
|
if (value.length() || Helpers::toLower(method) == "post") {
|
||||||
if (value.find_first_of('{') != std::string::npos) {
|
ssl_client->print("POST ");
|
||||||
http.addHeader(asyncsrv::T_Content_Type, asyncsrv::T_application_json, false); // auto-set to JSON
|
ssl_client->print(url.c_str());
|
||||||
|
ssl_client->println(" HTTP/1.1");
|
||||||
|
ssl_client->print("Host: ");
|
||||||
|
ssl_client->println(host.c_str());
|
||||||
|
for (JsonPair p : doc[header_s].as<JsonObject>()) {
|
||||||
|
content_set |= (emsesp::Helpers::toLower(p.key().c_str()) == "content-type");
|
||||||
|
ssl_client->print(p.key().c_str());
|
||||||
|
ssl_client->print(": ");
|
||||||
|
ssl_client->println(p.value().as<std::string>().c_str());
|
||||||
}
|
}
|
||||||
httpResult = http.POST(value.c_str());
|
if (!content_set) {
|
||||||
|
ssl_client->print("Content-Type: ");
|
||||||
|
if (value.starts_with('{')) {
|
||||||
|
ssl_client->println(asyncsrv::T_application_json);
|
||||||
} else {
|
} else {
|
||||||
httpResult = http.GET(); // normal GET
|
ssl_client->println(asyncsrv::T_text_plain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ssl_client->print("Content-Length: ");
|
||||||
|
ssl_client->println(value.length());
|
||||||
|
ssl_client->println("Connection: close");
|
||||||
|
ssl_client->print("\r\n");
|
||||||
|
ssl_client->print(value.c_str());
|
||||||
|
} else {
|
||||||
|
ssl_client->print("GET ");
|
||||||
|
ssl_client->print(url.c_str());
|
||||||
|
ssl_client->println(" HTTP/1.1");
|
||||||
|
ssl_client->print("Host: ");
|
||||||
|
ssl_client->println(host.c_str());
|
||||||
|
for (JsonPair p : doc[header_s].as<JsonObject>()) {
|
||||||
|
ssl_client->print(p.key().c_str());
|
||||||
|
ssl_client->print(": ");
|
||||||
|
ssl_client->println(p.value().as<std::string>().c_str());
|
||||||
|
}
|
||||||
|
ssl_client->println("Connection: close");
|
||||||
|
}
|
||||||
|
auto ms = millis();
|
||||||
|
while (!ssl_client->available() && millis() - ms < 3000) {
|
||||||
|
delay(0);
|
||||||
|
}
|
||||||
|
while (ssl_client->available()) {
|
||||||
|
result += (char)ssl_client->read();
|
||||||
|
}
|
||||||
|
ssl_client->stop();
|
||||||
|
index = result.find_first_of(' ');
|
||||||
|
if (index != std::string::npos) {
|
||||||
|
httpResult = stoi(result.substr(index + 1, 3));
|
||||||
|
}
|
||||||
|
index = result.find("\r\n\r\n");
|
||||||
|
if (index != std::string::npos) {
|
||||||
|
result.replace(0, index + 4, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete ssl_client;
|
||||||
|
delete basic_client;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (Helpers::toLower(url.c_str()).starts_with("http://")) {
|
||||||
|
HTTPClient * http = new HTTPClient;
|
||||||
|
if (http->begin(url.c_str())) {
|
||||||
|
for (JsonPair p : doc[header_s].as<JsonObject>()) {
|
||||||
|
http->addHeader(p.key().c_str(), p.value().as<std::string>().c_str());
|
||||||
|
content_set |= (emsesp::Helpers::toLower(p.key().c_str()) == "content-type");
|
||||||
|
}
|
||||||
|
if (value.length() || Helpers::toLower(method) == "post") {
|
||||||
|
if (!content_set) {
|
||||||
|
http->addHeader("Content-Type", value.starts_with('{') ? asyncsrv::T_application_json : asyncsrv::T_text_plain);
|
||||||
|
}
|
||||||
|
httpResult = http->POST(value.c_str());
|
||||||
|
} else {
|
||||||
|
httpResult = http->GET(); // normal GET
|
||||||
}
|
}
|
||||||
|
|
||||||
if (httpResult > 0) {
|
if (httpResult > 0) {
|
||||||
std::string result = http.getString().c_str();
|
result = http->getString().c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
http->end();
|
||||||
|
delete http;
|
||||||
|
}
|
||||||
|
if (httpResult == 200) {
|
||||||
std::string key = doc[key_s] | "";
|
std::string key = doc[key_s] | "";
|
||||||
JsonDocument keys_doc; // JsonDocument to hold "keys" after doc is parsed with HTTP body
|
JsonDocument keys_doc; // JsonDocument to hold "keys" after doc is parsed with HTTP body
|
||||||
if (doc[keys_s].is<JsonArray>()) {
|
if (doc[keys_s].is<JsonArray>()) {
|
||||||
keys_doc.set(doc[keys_s].as<JsonArray>());
|
keys_doc.set(doc[keys_s].as<JsonArray>());
|
||||||
}
|
}
|
||||||
JsonArray keys = keys_doc.as<JsonArray>();
|
JsonArray keys = keys_doc.as<JsonArray>();
|
||||||
|
|
||||||
if (key.length() || !keys.isNull()) {
|
if (key.length() || !keys.isNull()) {
|
||||||
doc.clear();
|
doc.clear();
|
||||||
if (DeserializationError::Ok == deserializeJson(doc, result)) {
|
if (DeserializationError::Ok == deserializeJson(doc, result)) {
|
||||||
@@ -767,9 +863,9 @@ std::string compute(const std::string & expr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expr_new.replace(f, e - f, result.c_str());
|
expr_new.replace(f, e - f, result);
|
||||||
}
|
} else if (httpResult != 0) {
|
||||||
http.end();
|
EMSESP::logger().warning("URL command failed with https code: %d, response: %s", httpResult, result.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f = expr_new.find_first_of('{', e);
|
f = expr_new.find_first_of('{', e);
|
||||||
|
|||||||
@@ -38,6 +38,15 @@
|
|||||||
#include "../test/test.h"
|
#include "../test/test.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef NO_TLS_SUPPORT
|
||||||
|
#define ENABLE_SMTP
|
||||||
|
#define USE_ESP_SSLCLIENT
|
||||||
|
#define READYCLIENT_SSL_CLIENT ESP_SSLClient
|
||||||
|
#define READYCLIENT_TYPE_1 // TYPE 1 when using ESP_SSLClient
|
||||||
|
#include <ESP_SSLClient.h>
|
||||||
|
#include <ReadyMail.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
// Languages supported. Note: the order is important
|
// Languages supported. Note: the order is important
|
||||||
@@ -106,6 +115,115 @@ bool System::command_send(const char * value, const int8_t id) {
|
|||||||
return EMSESP::txservice_.send_raw(value); // ignore id
|
return EMSESP::txservice_.send_raw(value); // ignore id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool System::command_sendmail(const char * value, const int8_t id) {
|
||||||
|
bool enabled = false;
|
||||||
|
bool ssl, starttls;
|
||||||
|
uint16_t port;
|
||||||
|
String server, login, pass, sender, recp, subject;
|
||||||
|
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
||||||
|
enabled = settings.email_enabled;
|
||||||
|
ssl = settings.email_ssl;
|
||||||
|
starttls = settings.email_starttls;
|
||||||
|
server = settings.email_server;
|
||||||
|
port = settings.email_port;
|
||||||
|
login = settings.email_login;
|
||||||
|
pass = settings.email_pass;
|
||||||
|
sender = settings.email_sender;
|
||||||
|
recp = settings.email_recp;
|
||||||
|
subject = settings.email_subject;
|
||||||
|
});
|
||||||
|
if (!enabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LOG_DEBUG("Command sendmail port %d%s called with '%s'", port, ssl ? " (SSL)" : starttls ? " (STARTTLS)" : "", value);
|
||||||
|
// LOG_DEBUG("Command sendmail port %d called with '%s'", port, value);
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
#ifndef NO_TLS_SUPPORT
|
||||||
|
WiFiClient * basic_client = new WiFiClient;
|
||||||
|
ESP_SSLClient * ssl_client = new ESP_SSLClient;
|
||||||
|
ReadyClient * r_client = new ReadyClient(*ssl_client);
|
||||||
|
SMTPClient * smtp = new SMTPClient(*r_client);
|
||||||
|
|
||||||
|
ssl_client->setClient(basic_client);
|
||||||
|
ssl_client->setInsecure();
|
||||||
|
ssl_client->setBufferSizes(1024, 1024);
|
||||||
|
r_client->addPort(port, starttls ? readymail_protocol_tls : ssl ? readymail_protocol_ssl : readymail_protocol_plain_text);
|
||||||
|
|
||||||
|
// smtp->connect(server, port, sendmailCallback);
|
||||||
|
smtp->connect(server, port);
|
||||||
|
if (!smtp->isConnected()) {
|
||||||
|
LOG_ERROR("Sendmail connection error");
|
||||||
|
delete smtp;
|
||||||
|
delete r_client;
|
||||||
|
delete ssl_client;
|
||||||
|
delete basic_client;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LOG_INFO("authenticate %s:%s", login.c_str(), pass.c_str());
|
||||||
|
smtp->authenticate(login, pass, readymail_auth_password);
|
||||||
|
if (!smtp->isAuthenticated()) {
|
||||||
|
LOG_ERROR("Sendmail authenticate error");
|
||||||
|
delete smtp;
|
||||||
|
delete r_client;
|
||||||
|
delete ssl_client;
|
||||||
|
delete basic_client;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
JsonDocument doc;
|
||||||
|
String body = value;
|
||||||
|
if (body.length()) {
|
||||||
|
auto error = deserializeJson(doc, (const char *)value);
|
||||||
|
if (!error && doc.as<JsonObject>().size() >= 0) {
|
||||||
|
subject = doc["subject"] | subject;
|
||||||
|
recp = doc["to"] | recp;
|
||||||
|
sender = doc["from"] | sender;
|
||||||
|
body = doc["body"] | body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SMTPMessage & msg = smtp->getMessage();
|
||||||
|
msg.headers.add(rfc822_subject, subject);
|
||||||
|
msg.headers.add(rfc822_from, sender);
|
||||||
|
msg.headers.add(rfc822_to, recp);
|
||||||
|
|
||||||
|
// Use addCustom to add custom header e.g. Importance and Priority.
|
||||||
|
// msg.headers.addCustom("Importance", PRIORITY);
|
||||||
|
// msg.headers.addCustom("X-MSMail-Priority", PRIORITY);
|
||||||
|
// msg.headers.addCustom("X-Priority", PRIORITY_NUM);
|
||||||
|
EMSESP::webSchedulerService.computed_value.clear();
|
||||||
|
EMSESP::webSchedulerService.raw_value = body.c_str();
|
||||||
|
for (uint16_t wait = 0; wait < 2000 && !EMSESP::webSchedulerService.raw_value.empty(); wait++) {
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
if (!EMSESP::webSchedulerService.computed_value.empty()) {
|
||||||
|
body = EMSESP::webSchedulerService.computed_value.c_str();
|
||||||
|
EMSESP::webSchedulerService.computed_value.clear();
|
||||||
|
EMSESP::webSchedulerService.computed_value.shrink_to_fit(); // free allocated memory
|
||||||
|
}
|
||||||
|
msg.text.body(body);
|
||||||
|
|
||||||
|
// bodyText.replace("\r\n", "<br>\r\n");
|
||||||
|
// msg.html.body("<html><body><div style=\"color:#cc0066;\">" + bodyText + "</div></body></html>");
|
||||||
|
// msg.html.transferEncoding("base64");
|
||||||
|
|
||||||
|
// With embedFile function, the html message will send as attachment.
|
||||||
|
// if (EMBED_MESSAGE)
|
||||||
|
// msg.html.embedFile(true, "msg.html", embed_message_type_attachment);
|
||||||
|
|
||||||
|
msg.timestamp = time(nullptr);
|
||||||
|
|
||||||
|
success = smtp->send(msg);
|
||||||
|
|
||||||
|
delete smtp;
|
||||||
|
delete r_client;
|
||||||
|
delete ssl_client;
|
||||||
|
delete basic_client;
|
||||||
|
#endif
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
// return string of languages and count
|
// return string of languages and count
|
||||||
std::string System::languages_string() {
|
std::string System::languages_string() {
|
||||||
std::string languages_string = std::to_string(NUM_LANGUAGES) + " languages (";
|
std::string languages_string = std::to_string(NUM_LANGUAGES) + " languages (";
|
||||||
@@ -238,7 +356,8 @@ bool System::command_message(const char * value, const int8_t id, JsonObject out
|
|||||||
LOG_INFO("Message: %s", EMSESP::webSchedulerService.computed_value.c_str()); // send to log
|
LOG_INFO("Message: %s", EMSESP::webSchedulerService.computed_value.c_str()); // send to log
|
||||||
Mqtt::queue_publish(F_(message), EMSESP::webSchedulerService.computed_value); // send to MQTT if enabled
|
Mqtt::queue_publish(F_(message), EMSESP::webSchedulerService.computed_value); // send to MQTT if enabled
|
||||||
output["api_data"] = EMSESP::webSchedulerService.computed_value; // send to API
|
output["api_data"] = EMSESP::webSchedulerService.computed_value; // send to API
|
||||||
|
EMSESP::webSchedulerService.computed_value.clear();
|
||||||
|
EMSESP::webSchedulerService.computed_value.shrink_to_fit();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,7 +582,6 @@ void System::system_restart(const char * partitionname) {
|
|||||||
|
|
||||||
Mqtt::disconnect(); // gracefully disconnect MQTT, needed for QOS1
|
Mqtt::disconnect(); // gracefully disconnect MQTT, needed for QOS1
|
||||||
EMSuart::stop(); // stop UART so there is no interference
|
EMSuart::stop(); // stop UART so there is no interference
|
||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
delay(1000); // wait 1 second
|
delay(1000); // wait 1 second
|
||||||
ESP.restart(); // ka-boom! - this is the only place where the ESP32 restart is called
|
ESP.restart(); // ka-boom! - this is the only place where the ESP32 restart is called
|
||||||
@@ -565,7 +683,6 @@ void System::store_settings(WebSettings & settings) {
|
|||||||
|
|
||||||
locale_ = settings.locale;
|
locale_ = settings.locale;
|
||||||
developer_mode_ = settings.developer_mode;
|
developer_mode_ = settings.developer_mode;
|
||||||
|
|
||||||
// start services
|
// start services
|
||||||
if (settings.modbus_enabled) {
|
if (settings.modbus_enabled) {
|
||||||
if (EMSESP::modbus_ == nullptr) {
|
if (EMSESP::modbus_ == nullptr) {
|
||||||
@@ -607,20 +724,11 @@ void System::start() {
|
|||||||
appfree_ = esp_ota_get_running_partition()->size / 1024 - appused_;
|
appfree_ = esp_ota_get_running_partition()->size / 1024 - appused_;
|
||||||
refreshHeapMem(); // refresh free heap and max alloc heap
|
refreshHeapMem(); // refresh free heap and max alloc heap
|
||||||
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
||||||
#if ESP_IDF_VERSION_MAJOR < 5
|
|
||||||
temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT();
|
|
||||||
temp_sensor_get_config(&temp_sensor);
|
|
||||||
temp_sensor.dac_offset = TSENS_DAC_DEFAULT; // DEFAULT: range:-10℃ ~ 80℃, error < 1℃.
|
|
||||||
temp_sensor_set_config(temp_sensor);
|
|
||||||
temp_sensor_start();
|
|
||||||
temp_sensor_read_celsius(&temperature_);
|
|
||||||
#else
|
|
||||||
temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(-10, 80);
|
temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(-10, 80);
|
||||||
temperature_sensor_install(&temp_sensor_config, &temperature_handle_);
|
temperature_sensor_install(&temp_sensor_config, &temperature_handle_);
|
||||||
temperature_sensor_enable(temperature_handle_);
|
temperature_sensor_enable(temperature_handle_);
|
||||||
temperature_sensor_get_celsius(temperature_handle_, &temperature_);
|
temperature_sensor_get_celsius(temperature_handle_, &temperature_);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EMSESP::esp32React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
EMSESP::esp32React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
||||||
@@ -841,16 +949,9 @@ void System::send_info_mqtt() {
|
|||||||
doc["IPv4 gateway"] = uuid::printable_to_string(WiFi.gatewayIP());
|
doc["IPv4 gateway"] = uuid::printable_to_string(WiFi.gatewayIP());
|
||||||
doc["IPv4 nameserver"] = uuid::printable_to_string(WiFi.dnsIP());
|
doc["IPv4 nameserver"] = uuid::printable_to_string(WiFi.dnsIP());
|
||||||
|
|
||||||
#if ESP_IDF_VERSION_MAJOR < 5
|
|
||||||
if (WiFi.localIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.localIPv6().toString() != "::") {
|
|
||||||
doc["IPv6 address"] = uuid::printable_to_string(WiFi.localIPv6());
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (WiFi.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.linkLocalIPv6().toString() != "::") {
|
if (WiFi.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.linkLocalIPv6().toString() != "::") {
|
||||||
doc["IPv6 address"] = uuid::printable_to_string(WiFi.linkLocalIPv6());
|
doc["IPv6 address"] = uuid::printable_to_string(WiFi.linkLocalIPv6());
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Mqtt::queue_publish_retain(F_(info), doc.as<JsonObject>()); // topic called "info" and it's Retained
|
Mqtt::queue_publish_retain(F_(info), doc.as<JsonObject>()); // topic called "info" and it's Retained
|
||||||
@@ -959,13 +1060,8 @@ void System::network_init() {
|
|||||||
delay(500);
|
delay(500);
|
||||||
digitalWrite(eth_power_, HIGH);
|
digitalWrite(eth_power_, HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ESP_IDF_VERSION_MAJOR < 5
|
|
||||||
eth_present_ = ETH.begin(phy_addr, power, mdc, mdio, type, clock_mode);
|
|
||||||
#else
|
|
||||||
eth_present_ = ETH.begin(type, phy_addr, mdc, mdio, power, clock_mode);
|
eth_present_ = ETH.begin(type, phy_addr, mdc, mdio, power, clock_mode);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check health of system, done every 5 seconds
|
// check health of system, done every 5 seconds
|
||||||
@@ -976,13 +1072,9 @@ void System::system_check() {
|
|||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
||||||
#if ESP_IDF_VERSION_MAJOR < 5
|
|
||||||
temp_sensor_read_celsius(&temperature_);
|
|
||||||
#else
|
|
||||||
temperature_sensor_get_celsius(temperature_handle_, &temperature_);
|
temperature_sensor_get_celsius(temperature_handle_, &temperature_);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef EMSESP_PINGTEST
|
#ifdef EMSESP_PINGTEST
|
||||||
static uint64_t ping_count = 0;
|
static uint64_t ping_count = 0;
|
||||||
@@ -1034,6 +1126,7 @@ void System::commands_init() {
|
|||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(read), System::command_read, FL_(read_cmd), CommandFlag::ADMIN_ONLY);
|
Command::add(EMSdevice::DeviceType::SYSTEM, F_(read), System::command_read, FL_(read_cmd), CommandFlag::ADMIN_ONLY);
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(send), System::command_send, FL_(send_cmd), CommandFlag::ADMIN_ONLY);
|
Command::add(EMSdevice::DeviceType::SYSTEM, F_(send), System::command_send, FL_(send_cmd), CommandFlag::ADMIN_ONLY);
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(fetch), System::command_fetch, FL_(fetch_cmd), CommandFlag::ADMIN_ONLY);
|
Command::add(EMSdevice::DeviceType::SYSTEM, F_(fetch), System::command_fetch, FL_(fetch_cmd), CommandFlag::ADMIN_ONLY);
|
||||||
|
Command::add(EMSdevice::DeviceType::SYSTEM, F_(sendmail), System::command_sendmail, FL_(sendmail_cmd), CommandFlag::ADMIN_ONLY);
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(restart), System::command_restart, FL_(restart_cmd), CommandFlag::ADMIN_ONLY);
|
Command::add(EMSdevice::DeviceType::SYSTEM, F_(restart), System::command_restart, FL_(restart_cmd), CommandFlag::ADMIN_ONLY);
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(format), System::command_format, FL_(format_cmd), CommandFlag::ADMIN_ONLY);
|
Command::add(EMSdevice::DeviceType::SYSTEM, F_(format), System::command_format, FL_(format_cmd), CommandFlag::ADMIN_ONLY);
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(txpause), System::command_txpause, FL_(txpause_cmd), CommandFlag::ADMIN_ONLY);
|
Command::add(EMSdevice::DeviceType::SYSTEM, F_(txpause), System::command_txpause, FL_(txpause_cmd), CommandFlag::ADMIN_ONLY);
|
||||||
@@ -1275,16 +1368,9 @@ void System::show_system(uuid::console::Shell & shell) {
|
|||||||
shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(WiFi.localIP()).c_str(), uuid::printable_to_string(WiFi.subnetMask()).c_str());
|
shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(WiFi.localIP()).c_str(), uuid::printable_to_string(WiFi.subnetMask()).c_str());
|
||||||
shell.printfln(" IPv4 gateway: %s", uuid::printable_to_string(WiFi.gatewayIP()).c_str());
|
shell.printfln(" IPv4 gateway: %s", uuid::printable_to_string(WiFi.gatewayIP()).c_str());
|
||||||
shell.printfln(" IPv4 nameserver: %s", uuid::printable_to_string(WiFi.dnsIP()).c_str());
|
shell.printfln(" IPv4 nameserver: %s", uuid::printable_to_string(WiFi.dnsIP()).c_str());
|
||||||
#if ESP_IDF_VERSION_MAJOR < 5
|
|
||||||
if (WiFi.localIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.localIPv6().toString() != "::") {
|
|
||||||
shell.printfln(" IPv6 address: %s", uuid::printable_to_string(WiFi.localIPv6()).c_str());
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (WiFi.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.linkLocalIPv6().toString() != "::") {
|
if (WiFi.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.linkLocalIPv6().toString() != "::") {
|
||||||
shell.printfln(" IPv6 address: %s", uuid::printable_to_string(WiFi.linkLocalIPv6()).c_str());
|
shell.printfln(" IPv6 address: %s", uuid::printable_to_string(WiFi.linkLocalIPv6()).c_str());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WL_CONNECT_FAILED:
|
case WL_CONNECT_FAILED:
|
||||||
@@ -1315,15 +1401,9 @@ void System::show_system(uuid::console::Shell & shell) {
|
|||||||
shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(ETH.localIP()).c_str(), uuid::printable_to_string(ETH.subnetMask()).c_str());
|
shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(ETH.localIP()).c_str(), uuid::printable_to_string(ETH.subnetMask()).c_str());
|
||||||
shell.printfln(" IPv4 gateway: %s", uuid::printable_to_string(ETH.gatewayIP()).c_str());
|
shell.printfln(" IPv4 gateway: %s", uuid::printable_to_string(ETH.gatewayIP()).c_str());
|
||||||
shell.printfln(" IPv4 nameserver: %s", uuid::printable_to_string(ETH.dnsIP()).c_str());
|
shell.printfln(" IPv4 nameserver: %s", uuid::printable_to_string(ETH.dnsIP()).c_str());
|
||||||
#if ESP_IDF_VERSION_MAJOR < 5
|
|
||||||
if (ETH.localIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && ETH.localIPv6().toString() != "::") {
|
|
||||||
shell.printfln(" IPv6 address: %s", uuid::printable_to_string(ETH.localIPv6()).c_str());
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (ETH.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && ETH.linkLocalIPv6().toString() != "::") {
|
if (ETH.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && ETH.linkLocalIPv6().toString() != "::") {
|
||||||
shell.printfln(" IPv6 address: %s", uuid::printable_to_string(ETH.linkLocalIPv6()).c_str());
|
shell.printfln(" IPv6 address: %s", uuid::printable_to_string(ETH.linkLocalIPv6()).c_str());
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
shell.println();
|
shell.println();
|
||||||
|
|
||||||
@@ -1345,7 +1425,6 @@ void System::show_system(uuid::console::Shell & shell) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
shell.println();
|
shell.println();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1355,301 +1434,7 @@ bool System::check_restore() {
|
|||||||
bool reboot_required = false; // true if we need to reboot
|
bool reboot_required = false; // true if we need to reboot
|
||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
File new_file = LittleFS.open(TEMP_FILENAME_PATH);
|
|
||||||
if (new_file) {
|
|
||||||
JsonDocument jsonDocument;
|
|
||||||
DeserializationError error = deserializeJson(jsonDocument, new_file);
|
|
||||||
if (error == DeserializationError::Ok && jsonDocument.is<JsonObject>()) {
|
|
||||||
JsonObject input = jsonDocument.as<JsonObject>();
|
|
||||||
// see what type of file it is, either settings or customization. anything else is ignored
|
|
||||||
std::string settings_type = input["type"];
|
|
||||||
LOG_INFO("Restoring '%s' settings...", settings_type.c_str());
|
|
||||||
|
|
||||||
// system backup, which is a consolidated json object with all the settings files
|
|
||||||
if (settings_type == "systembackup") {
|
|
||||||
reboot_required = true;
|
|
||||||
JsonArray sections = input["systembackup"].as<JsonArray>();
|
|
||||||
for (JsonObject section : sections) {
|
|
||||||
std::string section_type = section["type"];
|
|
||||||
LOG_DEBUG("Restoring '%s' section...", section_type.c_str());
|
|
||||||
if (section_type == "settings") {
|
|
||||||
saveSettings(NETWORK_SETTINGS_FILE, section);
|
|
||||||
saveSettings(AP_SETTINGS_FILE, section);
|
|
||||||
saveSettings(MQTT_SETTINGS_FILE, section);
|
|
||||||
saveSettings(NTP_SETTINGS_FILE, section);
|
|
||||||
saveSettings(SECURITY_SETTINGS_FILE, section);
|
|
||||||
saveSettings(EMSESP_SETTINGS_FILE, section);
|
|
||||||
}
|
|
||||||
if (section_type == "schedule") {
|
|
||||||
saveSettings(EMSESP_SCHEDULER_FILE, section);
|
|
||||||
}
|
|
||||||
if (section_type == "customizations") {
|
|
||||||
saveSettings(EMSESP_CUSTOMIZATION_FILE, section);
|
|
||||||
}
|
|
||||||
if (section_type == "entities") {
|
|
||||||
saveSettings(EMSESP_CUSTOMENTITY_FILE, section);
|
|
||||||
}
|
|
||||||
if (section_type == "modules") {
|
|
||||||
saveSettings(EMSESP_MODULES_FILE, section);
|
|
||||||
}
|
|
||||||
if (section_type == "customSupport") {
|
|
||||||
// it's a custom support, extract json and write to /config/customSupport.json file
|
|
||||||
File customSupportFile = LittleFS.open(EMSESP_CUSTOMSUPPORT_FILE, "w");
|
|
||||||
if (customSupportFile) {
|
|
||||||
serializeJson(section, customSupportFile);
|
|
||||||
customSupportFile.close();
|
|
||||||
LOG_INFO("Custom support file updated");
|
|
||||||
} else {
|
|
||||||
LOG_ERROR("Failed to save custom support file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (section_type == "nvs") {
|
|
||||||
// Restore NVS values
|
|
||||||
JsonArray nvs_entries = section["nvs"].as<JsonArray>();
|
|
||||||
for (JsonObject entry : nvs_entries) {
|
|
||||||
std::string key = entry["key"] | "";
|
|
||||||
int type = entry["type"] | NVS_TYPE_ANY;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case NVS_TYPE_I8:
|
|
||||||
if (entry["value"].is<JsonVariantConst>()) {
|
|
||||||
int8_t v = entry["value"];
|
|
||||||
EMSESP::nvs_.putChar(key.c_str(), v);
|
|
||||||
LOG_DEBUG("Restored NVS value: %s = %d", key.c_str(), v);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NVS_TYPE_U8:
|
|
||||||
if (entry["value"].is<JsonVariantConst>()) {
|
|
||||||
uint8_t v = entry["value"];
|
|
||||||
EMSESP::nvs_.putUChar(key.c_str(), v);
|
|
||||||
LOG_DEBUG("Restored NVS value: %s = %d", key.c_str(), v);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NVS_TYPE_I32:
|
|
||||||
if (entry["value"].is<JsonVariantConst>()) {
|
|
||||||
int32_t v = entry["value"];
|
|
||||||
EMSESP::nvs_.putInt(key.c_str(), v);
|
|
||||||
LOG_DEBUG("Restored NVS value: %s = %d", key.c_str(), v);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NVS_TYPE_U32:
|
|
||||||
if (entry["value"].is<JsonVariantConst>()) {
|
|
||||||
uint32_t v = entry["value"];
|
|
||||||
EMSESP::nvs_.putUInt(key.c_str(), v);
|
|
||||||
LOG_DEBUG("Restored NVS value: %s = %d", key.c_str(), v);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NVS_TYPE_I64:
|
|
||||||
if (entry["value"].is<JsonVariantConst>()) {
|
|
||||||
int64_t v = entry["value"];
|
|
||||||
EMSESP::nvs_.putLong64(key.c_str(), v);
|
|
||||||
LOG_DEBUG("Restored NVS value: %s = %d", key.c_str(), v);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NVS_TYPE_U64:
|
|
||||||
if (entry["value"].is<JsonVariantConst>()) {
|
|
||||||
uint64_t v = entry["value"];
|
|
||||||
EMSESP::nvs_.putULong64(key.c_str(), v);
|
|
||||||
LOG_DEBUG("Restored NVS value: %s = %d", key.c_str(), v);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NVS_TYPE_BLOB:
|
|
||||||
// used for double values
|
|
||||||
if (entry["value"].is<JsonVariantConst>()) {
|
|
||||||
double v = entry["value"];
|
|
||||||
EMSESP::nvs_.putDouble(key.c_str(), v);
|
|
||||||
LOG_DEBUG("Restored NVS value: %s = %d", key.c_str(), v);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NVS_TYPE_STR:
|
|
||||||
case NVS_TYPE_ANY:
|
|
||||||
default:
|
|
||||||
if (entry["value"].is<JsonVariantConst>()) {
|
|
||||||
std::string v = entry["value"];
|
|
||||||
EMSESP::nvs_.putString(key.c_str(), v.c_str());
|
|
||||||
LOG_DEBUG("Restored NVS value: %s = %s", key.c_str(), v.c_str());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// It's a single settings file. Parse each section separately. If it's system related it will require a reboot
|
|
||||||
else if (settings_type == "settings") {
|
|
||||||
reboot_required = saveSettings(NETWORK_SETTINGS_FILE, input);
|
|
||||||
reboot_required |= saveSettings(AP_SETTINGS_FILE, input);
|
|
||||||
reboot_required |= saveSettings(MQTT_SETTINGS_FILE, input);
|
|
||||||
reboot_required |= saveSettings(NTP_SETTINGS_FILE, input);
|
|
||||||
reboot_required |= saveSettings(SECURITY_SETTINGS_FILE, input);
|
|
||||||
reboot_required |= saveSettings(EMSESP_SETTINGS_FILE, input);
|
|
||||||
} else if (settings_type == "customizations") {
|
|
||||||
saveSettings(EMSESP_CUSTOMIZATION_FILE, input);
|
|
||||||
} else if (settings_type == "schedule") {
|
|
||||||
saveSettings(EMSESP_SCHEDULER_FILE, input);
|
|
||||||
} else if (settings_type == "entities") {
|
|
||||||
saveSettings(EMSESP_CUSTOMENTITY_FILE, input);
|
|
||||||
} else if (settings_type == "customSupport") {
|
|
||||||
// it's a custom support file - save it to /config
|
|
||||||
new_file.close();
|
|
||||||
if (LittleFS.rename(TEMP_FILENAME_PATH, EMSESP_CUSTOMSUPPORT_FILE)) {
|
|
||||||
LOG_INFO("Custom support file stored");
|
|
||||||
return false; // no need to reboot
|
|
||||||
} else {
|
|
||||||
LOG_ERROR("Failed to save custom support file");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG_ERROR("Unrecognized file uploaded");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG_ERROR("Unrecognized file uploaded, not json.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// close (just in case) and remove the temp file
|
|
||||||
new_file.close();
|
|
||||||
LittleFS.remove(TEMP_FILENAME_PATH);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return reboot_required;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle upgrades from previous versions
|
|
||||||
// this function will not be called on a clean install, with no settings files yet created
|
|
||||||
// returns true if we need a reboot
|
|
||||||
bool System::check_upgrade() {
|
|
||||||
bool missing_version = true;
|
|
||||||
std::string settingsVersion;
|
|
||||||
|
|
||||||
// fetch current version from settings file
|
|
||||||
EMSESP::webSettingsService.read([&](WebSettings const & settings) { settingsVersion = settings.version.c_str(); });
|
|
||||||
|
|
||||||
// see if we're missing a version, will be < 3.5.0b13 from Dec 23 2022
|
|
||||||
missing_version = (settingsVersion.empty() || (settingsVersion.length() < 5));
|
|
||||||
if (missing_version) {
|
|
||||||
LOG_WARNING("No version information found. Assuming version 3.5.0");
|
|
||||||
settingsVersion = "3.5.0"; // this was the last stable version without version info
|
|
||||||
}
|
|
||||||
|
|
||||||
version::Semver200_version settings_version(settingsVersion);
|
|
||||||
version::Semver200_version this_version(EMSESP_APP_VERSION);
|
|
||||||
|
|
||||||
std::string settings_version_type = settings_version.prerelease().empty() ? "" : ("-" + settings_version.prerelease());
|
|
||||||
std::string this_version_type = this_version.prerelease().empty() ? "" : ("-" + this_version.prerelease());
|
|
||||||
bool save_version = true;
|
|
||||||
bool reboot_required = false;
|
|
||||||
|
|
||||||
LOG_DEBUG("Checking for version upgrades from v%d.%d.%d%s",
|
|
||||||
settings_version.major(),
|
|
||||||
settings_version.minor(),
|
|
||||||
settings_version.patch(),
|
|
||||||
settings_version_type.c_str());
|
|
||||||
|
|
||||||
// compare versions
|
|
||||||
if (this_version > settings_version) {
|
|
||||||
// we need to do an upgrade
|
|
||||||
if (missing_version) {
|
|
||||||
LOG_NOTICE("Upgrading to version %d.%d.%d%s", this_version.major(), this_version.minor(), this_version.patch(), this_version_type.c_str());
|
|
||||||
} else {
|
|
||||||
LOG_NOTICE("Upgrading from version %d.%d.%d%s to %d.%d.%d%s",
|
|
||||||
settings_version.major(),
|
|
||||||
settings_version.minor(),
|
|
||||||
settings_version.patch(),
|
|
||||||
settings_version_type.c_str(),
|
|
||||||
this_version.major(),
|
|
||||||
this_version.minor(),
|
|
||||||
this_version.patch(),
|
|
||||||
this_version_type.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we're coming from 3.4.4 or 3.5.0b14 which had no version stored then we need to apply new settings
|
|
||||||
if (missing_version) {
|
|
||||||
LOG_INFO("Upgrade: Setting MQTT Entity ID format to older v3.4 format (0)");
|
|
||||||
EMSESP::esp32React.getMqttSettingsService()->update([&](MqttSettings & mqttSettings) {
|
|
||||||
mqttSettings.entity_format = Mqtt::entityFormat::SINGLE_LONG; // use old Entity ID format from v3.4
|
|
||||||
return StateUpdateResult::CHANGED;
|
|
||||||
});
|
|
||||||
} else if (settings_version.major() == 3 && settings_version.minor() <= 6) {
|
|
||||||
EMSESP::esp32React.getMqttSettingsService()->update([&](MqttSettings & mqttSettings) {
|
|
||||||
if (mqttSettings.entity_format == 1) {
|
|
||||||
mqttSettings.entity_format = Mqtt::entityFormat::SINGLE_OLD; // use old Entity ID format from v3.6
|
|
||||||
LOG_INFO("Upgrade: Setting MQTT Entity ID format to v3.6 format (3)");
|
|
||||||
return StateUpdateResult::CHANGED;
|
|
||||||
} else if (mqttSettings.entity_format == 2) {
|
|
||||||
mqttSettings.entity_format = Mqtt::entityFormat::MULTI_OLD; // use old Entity ID format from v3.6
|
|
||||||
LOG_INFO("Upgrade: Setting MQTT Entity ID format to v3.6 format (4)");
|
|
||||||
return StateUpdateResult::CHANGED;
|
|
||||||
}
|
|
||||||
return StateUpdateResult::UNCHANGED;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// changes pre < v3.7.0
|
|
||||||
if (settings_version.major() == 3 && settings_version.minor() < 7) {
|
|
||||||
// network changes
|
|
||||||
// 1) WiFi Tx Power is now using the value * 4 (was 20)
|
|
||||||
// 2) WiFi sleep is now off by default (was on)
|
|
||||||
EMSESP::esp32React.getNetworkSettingsService()->update([&](NetworkSettings & networkSettings) {
|
|
||||||
auto changed = StateUpdateResult::UNCHANGED;
|
|
||||||
if (networkSettings.tx_power == 20) {
|
|
||||||
networkSettings.tx_power = WIFI_POWER_19_5dBm; // use 19.5 as we don't have 20 anymore
|
|
||||||
LOG_INFO("Upgrade: Setting WiFi TX Power to Auto");
|
|
||||||
changed = StateUpdateResult::CHANGED;
|
|
||||||
}
|
|
||||||
if (networkSettings.nosleep != true) {
|
|
||||||
networkSettings.nosleep = true;
|
|
||||||
LOG_INFO("Upgrade: Disabling WiFi nosleep");
|
|
||||||
changed = StateUpdateResult::CHANGED;
|
|
||||||
}
|
|
||||||
return changed;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// changes to application settings
|
|
||||||
EMSESP::webSettingsService.update([&](WebSettings & settings) {
|
|
||||||
// force web buffer to 25 for those boards without psram
|
|
||||||
if ((EMSESP::system_.PSram() == 0) && (settings.weblog_buffer != 25)) {
|
|
||||||
settings.weblog_buffer = 25;
|
|
||||||
return StateUpdateResult::CHANGED;
|
|
||||||
}
|
|
||||||
return StateUpdateResult::UNCHANGED;
|
|
||||||
});
|
|
||||||
} else if (this_version < settings_version) {
|
|
||||||
// downgrading
|
|
||||||
LOG_NOTICE("Downgrading from version %d.%d.%d%s to version %d.%d.%d%s",
|
|
||||||
settings_version.major(),
|
|
||||||
settings_version.minor(),
|
|
||||||
settings_version.patch(),
|
|
||||||
settings_version_type.c_str(),
|
|
||||||
this_version.major(),
|
|
||||||
this_version.minor(),
|
|
||||||
this_version.patch(),
|
|
||||||
this_version_type.c_str());
|
|
||||||
} else {
|
|
||||||
save_version = false; // same version, do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we did a change, set the new version and save it, no need to reboot
|
|
||||||
if (save_version) {
|
|
||||||
EMSESP::webSettingsService.update([&](WebSettings & settings) {
|
|
||||||
settings.version = EMSESP_APP_VERSION;
|
|
||||||
LOG_DEBUG("Upgrade: Setting version to %s", EMSESP_APP_VERSION);
|
|
||||||
return StateUpdateResult::CHANGED;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reboot_required) {
|
|
||||||
LOG_INFO("Upgrade: Rebooting to apply changes");
|
|
||||||
return true; // need reboot
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // no reboot required
|
|
||||||
}
|
|
||||||
|
|
||||||
// map each config filename to its human-readable section key
|
// map each config filename to its human-readable section key
|
||||||
#ifndef EMSESP_STANDALONE
|
|
||||||
static const std::pair<const char *, const char *> SECTION_MAP[] = {
|
static const std::pair<const char *, const char *> SECTION_MAP[] = {
|
||||||
{NETWORK_SETTINGS_FILE, "Network"},
|
{NETWORK_SETTINGS_FILE, "Network"},
|
||||||
{AP_SETTINGS_FILE, "AP"},
|
{AP_SETTINGS_FILE, "AP"},
|
||||||
@@ -1763,38 +1548,29 @@ void System::exportSystemBackup(JsonObject output) {
|
|||||||
|
|
||||||
const char * nvs_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, "nvs1") ? "nvs1" : "nvs"; // nvs1 is on 16MBs
|
const char * nvs_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, "nvs1") ? "nvs1" : "nvs"; // nvs1 is on 16MBs
|
||||||
nvs_iterator_t it = nullptr;
|
nvs_iterator_t it = nullptr;
|
||||||
#if ESP_IDF_VERSION_MAJOR < 5
|
|
||||||
it = nvs_entry_find(nvs_part, "ems-esp", NVS_TYPE_ANY);
|
|
||||||
if (it == nullptr) {
|
|
||||||
#else
|
|
||||||
esp_err_t err = nvs_entry_find(nvs_part, "ems-esp", NVS_TYPE_ANY, &it);
|
esp_err_t err = nvs_entry_find(nvs_part, "ems-esp", NVS_TYPE_ANY, &it);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
#endif
|
|
||||||
LOG_ERROR("Failed to find NVS entry for %s", nvs_part);
|
LOG_ERROR("Failed to find NVS entry for %s", nvs_part);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArray entries = node["nvs"].to<JsonArray>();
|
JsonArray entries = node["nvs"].to<JsonArray>();
|
||||||
#if ESP_IDF_VERSION_MAJOR < 5
|
|
||||||
while (it != nullptr) {
|
|
||||||
nvs_entry_info_t info;
|
|
||||||
nvs_entry_info(it, &info);
|
|
||||||
#else
|
|
||||||
while (err == ESP_OK) {
|
while (err == ESP_OK) {
|
||||||
nvs_entry_info_t info;
|
nvs_entry_info_t info;
|
||||||
nvs_entry_info(it, &info);
|
nvs_entry_info(it, &info);
|
||||||
#endif
|
|
||||||
JsonObject entry = entries.add<JsonObject>();
|
JsonObject entry = entries.add<JsonObject>();
|
||||||
entry["type"] = info.type;
|
entry["type"] = info.type; // e.g. NVS_TYPE_U32 or NVS_TYPE_STR etc
|
||||||
entry["key"] = info.key;
|
entry["key"] = info.key;
|
||||||
|
|
||||||
LOG_DEBUG("Exporting NVS value: %s = %d", info.key, info.type);
|
LOG_DEBUG("Exporting NVS value: %s = %d", info.key, info.type);
|
||||||
|
|
||||||
|
// serialize based on the type. We use putString, putChar, putUChar, putDouble, putBool, putULong only
|
||||||
switch (info.type) {
|
switch (info.type) {
|
||||||
case NVS_TYPE_I8:
|
case NVS_TYPE_I8:
|
||||||
entry["value"] = EMSESP::nvs_.getChar(info.key);
|
entry["value"] = EMSESP::nvs_.getChar(info.key);
|
||||||
break;
|
break;
|
||||||
case NVS_TYPE_U8:
|
case NVS_TYPE_U8:
|
||||||
|
// also used for bool
|
||||||
entry["value"] = EMSESP::nvs_.getUChar(info.key);
|
entry["value"] = EMSESP::nvs_.getUChar(info.key);
|
||||||
break;
|
break;
|
||||||
case NVS_TYPE_I32:
|
case NVS_TYPE_I32:
|
||||||
@@ -1810,22 +1586,19 @@ void System::exportSystemBackup(JsonObject output) {
|
|||||||
entry["value"] = EMSESP::nvs_.getULong64(info.key);
|
entry["value"] = EMSESP::nvs_.getULong64(info.key);
|
||||||
break;
|
break;
|
||||||
case NVS_TYPE_BLOB:
|
case NVS_TYPE_BLOB:
|
||||||
entry["value"] = EMSESP::nvs_.getDouble(info.key); // bytes used for double values
|
// used for double (e.g. sensor values, nrgheat, nrgww), and stored as bytes in NVS
|
||||||
|
entry["value"] = EMSESP::nvs_.getDouble(info.key);
|
||||||
break;
|
break;
|
||||||
case NVS_TYPE_STR:
|
case NVS_TYPE_STR:
|
||||||
case NVS_TYPE_ANY:
|
case NVS_TYPE_ANY:
|
||||||
default:
|
default:
|
||||||
|
// any other value we store as a string
|
||||||
entry["value"] = EMSESP::nvs_.getString(info.key);
|
entry["value"] = EMSESP::nvs_.getString(info.key);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ESP_IDF_VERSION_MAJOR < 5
|
|
||||||
it = nvs_entry_next(it);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
err = nvs_entry_next(&it);
|
err = nvs_entry_next(&it);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (it != nullptr) {
|
if (it != nullptr) {
|
||||||
nvs_release_iterator(it);
|
nvs_release_iterator(it);
|
||||||
@@ -3323,6 +3096,10 @@ void System::set_valid_system_gpios() {
|
|||||||
} else {
|
} else {
|
||||||
valid_system_gpios_ = string_range_to_vector("0-39", "6-11, 20, 24, 28-31");
|
valid_system_gpios_ = string_range_to_vector("0-39", "6-11, 20, 24, 28-31");
|
||||||
}
|
}
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||||
|
// https://docs.espressif.com/projects/esp-idf/en/v5.5.3/esp32c6/api-reference/peripherals/gpio.html
|
||||||
|
// 24-30 used for flash, 12-13 USB, 16-17 uart0
|
||||||
|
valid_system_gpios_ = string_range_to_vector("0-30", "12-13, 16-17, 24-30");
|
||||||
#elif defined(EMSESP_STANDALONE)
|
#elif defined(EMSESP_STANDALONE)
|
||||||
valid_system_gpios_ = string_range_to_vector("0-39");
|
valid_system_gpios_ = string_range_to_vector("0-39");
|
||||||
#endif
|
#endif
|
||||||
@@ -3407,3 +3184,4 @@ void System::restore_snapshot_gpios(std::vector<int8_t> & u_gpios, std::vector<i
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|
||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "3.8.2-dev.C13"
|
#define EMSESP_APP_VERSION "3.9.0-dev.0"
|
||||||
|
|||||||
@@ -363,39 +363,139 @@ bool WebSchedulerService::command(const char * name, const std::string & command
|
|||||||
commands(s, false);
|
commands(s, false);
|
||||||
url.replace(q + 1, l, s);
|
url.replace(q + 1, l, s);
|
||||||
}
|
}
|
||||||
if (http.begin(url.c_str())) {
|
std::string value = doc["value"] | data; // extract value if its in the command, or take the data
|
||||||
// add any given headers
|
|
||||||
for (JsonPair p : doc["header"].as<JsonObject>()) {
|
|
||||||
http.addHeader(p.key().c_str(), p.value().as<String>().c_str());
|
|
||||||
}
|
|
||||||
std::string value = doc["value"] | data.c_str(); // extract value if its in the command, or take the data
|
|
||||||
std::string method = doc["method"] | "GET"; // default GET
|
std::string method = doc["method"] | "GET"; // default GET
|
||||||
|
|
||||||
commands(value, false);
|
commands(value, false);
|
||||||
// if there is data, force a POST
|
if (value.length()) {
|
||||||
|
method = "POST";
|
||||||
|
}
|
||||||
|
std::string result;
|
||||||
int httpResult = 0;
|
int httpResult = 0;
|
||||||
if (value.length() || method == "post") { // we have all lowercase
|
#ifndef NO_TLS_SUPPORT
|
||||||
if (value.find_first_of('{') != std::string::npos) {
|
if (Helpers::toLower(url.c_str()).starts_with("https://")) {
|
||||||
http.addHeader(asyncsrv::T_Content_Type, asyncsrv::T_application_json, false); // auto-set to JSON
|
WiFiClient * basic_client = new WiFiClient;
|
||||||
|
ESP_SSLClient * ssl_client = new ESP_SSLClient;
|
||||||
|
ssl_client->setInsecure(); // with root CA we should set here: ssl_client->setCACert(rootCACert);
|
||||||
|
ssl_client->setBufferSizes(1024, 1024);
|
||||||
|
ssl_client->setSessionTimeout(120); // Set the timeout in seconds (>=120 seconds)
|
||||||
|
url.replace(0, 8, "");
|
||||||
|
std::string host = url;
|
||||||
|
auto index = url.find_first_of('/');
|
||||||
|
if (index != std::string::npos) {
|
||||||
|
host = url.substr(0, index);
|
||||||
|
url.replace(0, index, "");
|
||||||
}
|
}
|
||||||
httpResult = http.POST(value.c_str());
|
// EMSESP::logger().debug("Host: %s, URL: %s", host.c_str(), url.c_str());
|
||||||
|
ssl_client->setClient(basic_client);
|
||||||
|
if (ssl_client->connect(host.c_str(), 443)) {
|
||||||
|
if (value.length() || Helpers::toLower(method) == "post") {
|
||||||
|
// EMSESP::logger().debug("POST %s HTTP/1.1", url.c_str());
|
||||||
|
ssl_client->print("POST ");
|
||||||
|
ssl_client->print(url.c_str());
|
||||||
|
ssl_client->println(" HTTP/1.1");
|
||||||
|
ssl_client->print("Host: ");
|
||||||
|
ssl_client->println(host.c_str());
|
||||||
|
bool content_set = false;
|
||||||
|
for (JsonPair p : doc["header"].as<JsonObject>()) {
|
||||||
|
content_set |= (emsesp::Helpers::toLower(p.key().c_str()) == "content-type");
|
||||||
|
ssl_client->print(p.key().c_str());
|
||||||
|
ssl_client->print(": ");
|
||||||
|
ssl_client->println(p.value().as<std::string>().c_str());
|
||||||
|
}
|
||||||
|
if (!content_set) {
|
||||||
|
ssl_client->print("Content-Type: ");
|
||||||
|
if (value.starts_with('{')) {
|
||||||
|
ssl_client->println(asyncsrv::T_application_json);
|
||||||
} else {
|
} else {
|
||||||
httpResult = http.GET(); // normal GET
|
ssl_client->println(asyncsrv::T_text_plain);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
http.end();
|
ssl_client->print("Content-Length: ");
|
||||||
|
ssl_client->println(value.length());
|
||||||
|
ssl_client->println("Connection: close");
|
||||||
|
ssl_client->print("\r\n");
|
||||||
|
ssl_client->print(value.c_str());
|
||||||
|
} else {
|
||||||
|
// EMSESP::logger().debug("GET %s HTTP/1.1", url.c_str());
|
||||||
|
ssl_client->print("GET ");
|
||||||
|
ssl_client->print(url.c_str());
|
||||||
|
ssl_client->println(" HTTP/1.1");
|
||||||
|
ssl_client->print("Host: ");
|
||||||
|
ssl_client->println(host.c_str());
|
||||||
|
for (JsonPair p : doc["header"].as<JsonObject>()) {
|
||||||
|
ssl_client->print(p.key().c_str());
|
||||||
|
ssl_client->print(": ");
|
||||||
|
ssl_client->println(p.value().as<std::string>().c_str());
|
||||||
|
}
|
||||||
|
ssl_client->println("Connection: close");
|
||||||
|
}
|
||||||
|
auto ms = millis();
|
||||||
|
while (ssl_client->connected() && !ssl_client->available() && millis() - ms < 3000) {
|
||||||
|
delay(0);
|
||||||
|
}
|
||||||
|
while (ssl_client->available()) {
|
||||||
|
result += (char)ssl_client->read();
|
||||||
|
}
|
||||||
|
ssl_client->stop();
|
||||||
|
// EMSESP::logger().debug("HTTPS response: %s", result.c_str());
|
||||||
|
index = result.find_first_of(' ');
|
||||||
|
if (index != std::string::npos) {
|
||||||
|
httpResult = stoi(result.substr(index + 1, 3));
|
||||||
|
// EMSESP::logger().debug("HTTPS code: %i", httpResult);
|
||||||
|
}
|
||||||
|
index = result.find("\r\n\r\n");
|
||||||
|
if (index != std::string::npos) {
|
||||||
|
result.replace(0, index + 4, "");
|
||||||
|
// EMSESP::logger().debug("HTTPS response: %s", result.c_str());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EMSESP::logger().warning("HTTPS connection failed");
|
||||||
|
}
|
||||||
|
delete ssl_client;
|
||||||
|
delete basic_client;
|
||||||
// check HTTP return code
|
// check HTTP return code
|
||||||
if (httpResult != 200) {
|
if (httpResult != 200) {
|
||||||
char error[100];
|
EMSESP::logger().warning("Schedule '%s': URL command failed with http code %d", name, httpResult);
|
||||||
snprintf(error, sizeof(error), "Schedule %s: URL command failed with http code %d", name, httpResult);
|
return false;
|
||||||
EMSESP::logger().warning(error);
|
}
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (Helpers::toLower(url.c_str()).starts_with("http://")) {
|
||||||
|
HTTPClient * http = new HTTPClient;
|
||||||
|
if (http->begin(url.c_str())) {
|
||||||
|
bool content_set = false;
|
||||||
|
for (JsonPair p : doc["header"].as<JsonObject>()) {
|
||||||
|
http->addHeader(p.key().c_str(), p.value().as<std::string>().c_str());
|
||||||
|
content_set |= p.key() == "content-type";
|
||||||
|
}
|
||||||
|
// if there is data, force a POST
|
||||||
|
if (Helpers::toLower(method) == "post") { // we have all lowercase
|
||||||
|
if (!content_set) {
|
||||||
|
// http->addHeader("Content-Type", value.find_first_of('{') != std::string::npos ? "application/json" : "text/plain");
|
||||||
|
if (value.starts_with('{')) {
|
||||||
|
http->addHeader(asyncsrv::T_Content_Type, asyncsrv::T_application_json, false); // auto-set to JSON
|
||||||
|
} else {
|
||||||
|
http->addHeader(asyncsrv::T_Content_Type, asyncsrv::T_text_plain, false); // auto-set to JSON
|
||||||
|
}
|
||||||
|
}
|
||||||
|
httpResult = http->POST(value.c_str());
|
||||||
|
} else {
|
||||||
|
httpResult = http->GET(); // normal GET
|
||||||
|
if (httpResult > 0) {
|
||||||
|
result = http->getString().c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
http->end();
|
||||||
|
delete http;
|
||||||
|
// check HTTP return code
|
||||||
|
if (httpResult != 200) {
|
||||||
|
EMSESP::logger().warning("Schedule '%s': URL command failed with http code %d", name, httpResult);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
char msg[100];
|
EMSESP::logger().debug("Schedule %s: URL '%s' command successful with http code %d", name, url.c_str(), httpResult);
|
||||||
snprintf(msg, sizeof(msg), "Schedule %s: URL command successful with http code %d", name, httpResult);
|
|
||||||
EMSESP::logger().debug(msg);
|
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,20 @@ void WebSettings::read(WebSettings & settings, JsonObject root) {
|
|||||||
root["modbus_max_clients"] = settings.modbus_max_clients;
|
root["modbus_max_clients"] = settings.modbus_max_clients;
|
||||||
root["modbus_timeout"] = settings.modbus_timeout;
|
root["modbus_timeout"] = settings.modbus_timeout;
|
||||||
root["developer_mode"] = settings.developer_mode;
|
root["developer_mode"] = settings.developer_mode;
|
||||||
|
#ifndef NO_TLS_SUPPORT
|
||||||
|
root["email_enabled"] = settings.email_enabled;
|
||||||
|
#else
|
||||||
|
root["email_enabled"] = false;
|
||||||
|
#endif
|
||||||
|
root["email_ssl"] = settings.email_ssl;
|
||||||
|
root["email_starttls"] = settings.email_starttls;
|
||||||
|
root["email_server"] = settings.email_server;
|
||||||
|
root["email_port"] = settings.email_port;
|
||||||
|
root["email_login"] = settings.email_login;
|
||||||
|
root["email_pass"] = settings.email_pass;
|
||||||
|
root["email_sender"] = settings.email_sender;
|
||||||
|
root["email_recp"] = settings.email_recp;
|
||||||
|
root["email_subject"] = settings.email_subject;
|
||||||
}
|
}
|
||||||
|
|
||||||
// call on initialization and also when settings are updated/saved via web or console
|
// call on initialization and also when settings are updated/saved via web or console
|
||||||
@@ -243,13 +257,9 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
|
|||||||
|
|
||||||
// Modbus settings
|
// Modbus settings
|
||||||
settings.modbus_enabled = root["modbus_enabled"] | EMSESP_DEFAULT_MODBUS_ENABLED;
|
settings.modbus_enabled = root["modbus_enabled"] | EMSESP_DEFAULT_MODBUS_ENABLED;
|
||||||
check_flag(original_settings.modbus_enabled, settings.modbus_enabled, ChangeFlags::RESTART);
|
|
||||||
settings.modbus_port = root["modbus_port"] | EMSESP_DEFAULT_MODBUS_PORT;
|
settings.modbus_port = root["modbus_port"] | EMSESP_DEFAULT_MODBUS_PORT;
|
||||||
check_flag(original_settings.modbus_port, settings.modbus_port, ChangeFlags::RESTART);
|
|
||||||
settings.modbus_max_clients = root["modbus_max_clients"] | EMSESP_DEFAULT_MODBUS_MAX_CLIENTS;
|
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);
|
|
||||||
settings.modbus_timeout = root["modbus_timeout"] | EMSESP_DEFAULT_MODBUS_TIMEOUT;
|
settings.modbus_timeout = root["modbus_timeout"] | EMSESP_DEFAULT_MODBUS_TIMEOUT;
|
||||||
check_flag(original_settings.modbus_timeout, settings.modbus_timeout, ChangeFlags::RESTART);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// these may need mqtt restart to rebuild HA discovery topics
|
// these may need mqtt restart to rebuild HA discovery topics
|
||||||
@@ -300,6 +310,20 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
|
|||||||
settings.weblog_level = root["weblog_level"] | EMSESP_DEFAULT_WEBLOG_LEVEL;
|
settings.weblog_level = root["weblog_level"] | EMSESP_DEFAULT_WEBLOG_LEVEL;
|
||||||
settings.weblog_compact = root["weblog_compact"] | EMSESP_DEFAULT_WEBLOG_COMPACT;
|
settings.weblog_compact = root["weblog_compact"] | EMSESP_DEFAULT_WEBLOG_COMPACT;
|
||||||
|
|
||||||
|
settings.email_enabled = root["email_enabled"] | FACTORY_EMAIL_ENABLE;
|
||||||
|
settings.email_ssl = root["email_ssl"] | FACTORY_EMAIL_SSL;
|
||||||
|
settings.email_starttls = root["email_starttls"] | FACTORY_EMAIL_STARTTLS;
|
||||||
|
settings.email_server = root["email_server"] | FACTORY_EMAIL_SERVER;
|
||||||
|
settings.email_port = root["email_port"] | FACTORY_EMAIL_PORT;
|
||||||
|
settings.email_login = root["email_login"] | FACTORY_EMAIL_LOGIN;
|
||||||
|
settings.email_pass = root["email_pass"] | FACTORY_EMAIL_PASSWORD;
|
||||||
|
settings.email_sender = root["email_sender"] | FACTORY_EMAIL_FROM;
|
||||||
|
settings.email_recp = root["email_recp"] | FACTORY_EMAIL_TO;
|
||||||
|
settings.email_subject = root["email_subject"] | FACTORY_EMAIL_SUBJECT;
|
||||||
|
|
||||||
|
if (settings.email_ssl && settings.email_starttls) {
|
||||||
|
settings.email_ssl = false;
|
||||||
|
}
|
||||||
// if no psram limit weblog buffer to 25 messages
|
// if no psram limit weblog buffer to 25 messages
|
||||||
if (EMSESP::system_.PSram() > 0) {
|
if (EMSESP::system_.PSram() > 0) {
|
||||||
settings.weblog_buffer = root["weblog_buffer"] | EMSESP_DEFAULT_WEBLOG_BUFFER;
|
settings.weblog_buffer = root["weblog_buffer"] | EMSESP_DEFAULT_WEBLOG_BUFFER;
|
||||||
@@ -458,23 +482,14 @@ void WebSettings::set_board_profile(WebSettings & settings) {
|
|||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
// check for no PSRAM, could be a E32 or S32?
|
// check for no PSRAM, could be a E32 or S32?
|
||||||
if (!ESP.getPsramSize()) {
|
if (!ESP.getPsramSize()) {
|
||||||
#if ESP_ARDUINO_VERSION_MAJOR < 3
|
|
||||||
if (ETH.begin(1, 16, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_IN)) {
|
|
||||||
#else
|
|
||||||
if (ETH.begin(ETH_PHY_LAN8720, 1, 23, 18, 16, ETH_CLOCK_GPIO0_IN)) {
|
if (ETH.begin(ETH_PHY_LAN8720, 1, 23, 18, 16, ETH_CLOCK_GPIO0_IN)) {
|
||||||
#endif
|
|
||||||
settings.board_profile = "E32"; // Ethernet without PSRAM
|
settings.board_profile = "E32"; // Ethernet without PSRAM
|
||||||
} else {
|
} else {
|
||||||
settings.board_profile = "S32"; // ESP32 standard WiFi without PSRAM
|
settings.board_profile = "S32"; // ESP32 standard WiFi without PSRAM
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// check for boards with PSRAM, could be a E32V2 otherwise default back to the S32
|
// check for boards with PSRAM, could be a E32V2 otherwise default back to the S32
|
||||||
#if ESP_ARDUINO_VERSION_MAJOR < 3
|
|
||||||
if (ETH.begin(0, 15, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_OUT)) {
|
|
||||||
#else
|
|
||||||
if (ETH.begin(ETH_PHY_LAN8720, 0, 23, 18, 15, ETH_CLOCK_GPIO0_OUT)) {
|
if (ETH.begin(ETH_PHY_LAN8720, 0, 23, 18, 15, ETH_CLOCK_GPIO0_OUT)) {
|
||||||
#endif
|
|
||||||
|
|
||||||
if (analogReadMilliVolts(39) > 700) { // core voltage > 2.6V
|
if (analogReadMilliVolts(39) > 700) { // core voltage > 2.6V
|
||||||
settings.board_profile = "E32V2_2"; // Ethernet, PSRAM, internal sensors
|
settings.board_profile = "E32V2_2"; // Ethernet, PSRAM, internal sensors
|
||||||
} else {
|
} else {
|
||||||
@@ -551,3 +566,4 @@ uint8_t WebSettings::get_flags() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|
||||||
Reference in New Issue
Block a user