mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-05-02 12:07:02 +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);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,13 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "emsesp.h"
|
#include "emsesp.h"
|
||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
uint8_t WebSettings::flags_ = 0;
|
uint8_t WebSettings::flags_ = 0;
|
||||||
|
|
||||||
WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||||
: _httpEndpoint(WebSettings::read, WebSettings::update, this, server, EMSESP_SETTINGS_SERVICE_PATH, securityManager)
|
: _httpEndpoint(WebSettings::read, WebSettings::update, this, server, EMSESP_SETTINGS_SERVICE_PATH, securityManager)
|
||||||
, _fsPersistence(WebSettings::read, WebSettings::update, this, fs, EMSESP_SETTINGS_FILE) {
|
, _fsPersistence(WebSettings::read, WebSettings::update, this, fs, EMSESP_SETTINGS_FILE) {
|
||||||
securityManager->addEndpoint(server, EMSESP_BOARD_PROFILE_SERVICE_PATH, AuthenticationPredicates::IS_AUTHENTICATED, [this](AsyncWebServerRequest * request) {
|
securityManager->addEndpoint(server, EMSESP_BOARD_PROFILE_SERVICE_PATH, AuthenticationPredicates::IS_AUTHENTICATED, [this](AsyncWebServerRequest * request) {
|
||||||
@@ -30,9 +30,9 @@ WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, Securit
|
|||||||
});
|
});
|
||||||
|
|
||||||
addUpdateHandler([this] { onUpdate(); }, false);
|
addUpdateHandler([this] { onUpdate(); }, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSettings::read(WebSettings & settings, JsonObject root) {
|
void WebSettings::read(WebSettings & settings, JsonObject root) {
|
||||||
root["version"] = settings.version;
|
root["version"] = settings.version;
|
||||||
root["board_profile"] = settings.board_profile;
|
root["board_profile"] = settings.board_profile;
|
||||||
root["platform"] = EMSESP_PLATFORM;
|
root["platform"] = EMSESP_PLATFORM;
|
||||||
@@ -83,11 +83,25 @@ 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
|
||||||
// note, settings is empty when the service starts
|
// note, settings is empty when the service starts
|
||||||
StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
|
StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
|
||||||
// make a copy of the settings to compare to later
|
// make a copy of the settings to compare to later
|
||||||
const WebSettings original_settings(settings);
|
const WebSettings original_settings(settings);
|
||||||
|
|
||||||
@@ -202,12 +216,12 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
|
|||||||
settings.syslog_port = root["syslog_port"] | EMSESP_DEFAULT_SYSLOG_PORT;
|
settings.syslog_port = root["syslog_port"] | EMSESP_DEFAULT_SYSLOG_PORT;
|
||||||
check_flag(original_settings.syslog_port, settings.syslog_port, ChangeFlags::SYSLOG);
|
check_flag(original_settings.syslog_port, settings.syslog_port, ChangeFlags::SYSLOG);
|
||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
settings.syslog_host = root["syslog_host"] | EMSESP_DEFAULT_SYSLOG_HOST;
|
settings.syslog_host = root["syslog_host"] | EMSESP_DEFAULT_SYSLOG_HOST;
|
||||||
if (original_settings.syslog_host != settings.syslog_host) {
|
if (original_settings.syslog_host != settings.syslog_host) {
|
||||||
add_flags(ChangeFlags::SYSLOG);
|
add_flags(ChangeFlags::SYSLOG);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// temperature sensor
|
// temperature sensor
|
||||||
settings.dallas_parasite = root["dallas_parasite"] | EMSESP_DEFAULT_DALLAS_PARASITE;
|
settings.dallas_parasite = root["dallas_parasite"] | EMSESP_DEFAULT_DALLAS_PARASITE;
|
||||||
@@ -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;
|
||||||
@@ -329,11 +353,11 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return StateUpdateResult::CHANGED;
|
return StateUpdateResult::CHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is called after any of the settings have been persisted to the filesystem
|
// this is called after any of the settings have been persisted to the filesystem
|
||||||
// either via the Web UI or via the Console
|
// either via the Web UI or via the Console
|
||||||
void WebSettingsService::onUpdate() {
|
void WebSettingsService::onUpdate() {
|
||||||
// skip if we're restarting anyway
|
// skip if we're restarting anyway
|
||||||
|
|
||||||
if (WebSettings::has_flags(WebSettings::ChangeFlags::RESTART)) {
|
if (WebSettings::has_flags(WebSettings::ChangeFlags::RESTART)) {
|
||||||
@@ -373,18 +397,18 @@ void WebSettingsService::onUpdate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WebSettings::reset_flags();
|
WebSettings::reset_flags();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSettingsService::begin() {
|
void WebSettingsService::begin() {
|
||||||
_fsPersistence.readFromFS();
|
_fsPersistence.readFromFS();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSettingsService::save() {
|
void WebSettingsService::save() {
|
||||||
_fsPersistence.writeToFS();
|
_fsPersistence.writeToFS();
|
||||||
}
|
}
|
||||||
|
|
||||||
// send the board profile as JSON
|
// send the board profile as JSON
|
||||||
void WebSettingsService::board_profile(AsyncWebServerRequest * request) {
|
void WebSettingsService::board_profile(AsyncWebServerRequest * request) {
|
||||||
if (request->hasParam("boardProfile")) {
|
if (request->hasParam("boardProfile")) {
|
||||||
std::string board_profile = request->getParam("boardProfile")->value().c_str();
|
std::string board_profile = request->getParam("boardProfile")->value().c_str();
|
||||||
|
|
||||||
@@ -413,11 +437,11 @@ void WebSettingsService::board_profile(AsyncWebServerRequest * request) {
|
|||||||
|
|
||||||
AsyncWebServerResponse * response = request->beginResponse(200);
|
AsyncWebServerResponse * response = request->beginResponse(200);
|
||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// loads the board profile to set the gpios
|
// loads the board profile to set the gpios
|
||||||
// if the board profile is not found, or default, it will try to autodetect the board profile
|
// if the board profile is not found, or default, it will try to autodetect the board profile
|
||||||
void WebSettings::set_board_profile(WebSettings & settings) {
|
void WebSettings::set_board_profile(WebSettings & settings) {
|
||||||
// The optional NVS boot value has priority and overrides any board_profile setting.
|
// The optional NVS boot value has priority and overrides any board_profile setting.
|
||||||
// This is only done for BBQKees boards
|
// This is only done for BBQKees boards
|
||||||
// Note 1: we never set the NVS boot value in the code - this is done on initial pre-loading
|
// Note 1: we never set the NVS boot value in the code - this is done on initial pre-loading
|
||||||
@@ -425,9 +449,9 @@ void WebSettings::set_board_profile(WebSettings & settings) {
|
|||||||
if (EMSESP::system_.getBBQKeesGatewayDetails(FUSE_VALUE::MFG).startsWith("BBQKees")) {
|
if (EMSESP::system_.getBBQKeesGatewayDetails(FUSE_VALUE::MFG).startsWith("BBQKees")) {
|
||||||
String bbq_board = EMSESP::system_.getBBQKeesGatewayDetails(FUSE_VALUE::BOARD);
|
String bbq_board = EMSESP::system_.getBBQKeesGatewayDetails(FUSE_VALUE::BOARD);
|
||||||
if (!bbq_board.isEmpty() && settings.board_profile != "CUSTOM") {
|
if (!bbq_board.isEmpty() && settings.board_profile != "CUSTOM") {
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
EMSESP::logger().info("Overriding board profile with fuse value %s", bbq_board.c_str());
|
EMSESP::logger().info("Overriding board profile with fuse value %s", bbq_board.c_str());
|
||||||
#endif
|
#endif
|
||||||
settings.board_profile = bbq_board;
|
settings.board_profile = bbq_board;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,9 +469,9 @@ void WebSettings::set_board_profile(WebSettings & settings) {
|
|||||||
std::vector<int8_t> data(10, 99); // initialize with 99 for all values, just as a safe guard to catch bad gpios
|
std::vector<int8_t> data(10, 99); // initialize with 99 for all values, just as a safe guard to catch bad gpios
|
||||||
if (settings.board_profile != "default") {
|
if (settings.board_profile != "default") {
|
||||||
if (!System::load_board_profile(data, settings.board_profile.c_str())) {
|
if (!System::load_board_profile(data, settings.board_profile.c_str())) {
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
EMSESP::logger().debug("Unable to identify board profile %s", settings.board_profile.c_str());
|
EMSESP::logger().debug("Unable to identify board profile %s", settings.board_profile.c_str());
|
||||||
#endif
|
#endif
|
||||||
settings.board_profile = "default"; // can't find profile, fallback to "default"
|
settings.board_profile = "default"; // can't find profile, fallback to "default"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -455,26 +479,17 @@ void WebSettings::set_board_profile(WebSettings & settings) {
|
|||||||
// we still don't have a valid board profile. Let's see if we can determine one from the build config or hardware
|
// we still don't have a valid board profile. Let's see if we can determine one from the build config or hardware
|
||||||
if (settings.board_profile == "default") {
|
if (settings.board_profile == "default") {
|
||||||
EMSESP::logger().info("Autodetecting board profile");
|
EMSESP::logger().info("Autodetecting board profile");
|
||||||
#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 {
|
||||||
@@ -484,29 +499,29 @@ void WebSettings::set_board_profile(WebSettings & settings) {
|
|||||||
settings.board_profile = "S32"; // ESP32 standard WiFi with PSRAM
|
settings.board_profile = "S32"; // ESP32 standard WiFi with PSRAM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// override if we know the target from the build config like C3, S2, S3 etc..
|
// override if we know the target from the build config like C3, S2, S3 etc..
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
settings.board_profile = "C3MINI";
|
settings.board_profile = "C3MINI";
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
settings.board_profile = "S2MINI";
|
settings.board_profile = "S2MINI";
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
settings.board_profile = "S32S3"; // BBQKees Gateway S3
|
settings.board_profile = "S32S3"; // BBQKees Gateway S3
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||||
settings.board_profile = "CUSTOM";
|
settings.board_profile = "CUSTOM";
|
||||||
#endif
|
#endif
|
||||||
// apply the new board profile setting
|
// apply the new board profile setting
|
||||||
System::load_board_profile(data, settings.board_profile.c_str());
|
System::load_board_profile(data, settings.board_profile.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// log board profile and PSRAM info
|
// log board profile and PSRAM info
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
uint32_t psram_size = ESP.getPsramSize() / 1024; // in KB
|
uint32_t psram_size = ESP.getPsramSize() / 1024; // in KB
|
||||||
if (psram_size > 0) {
|
if (psram_size > 0) {
|
||||||
EMSESP::logger().info("Loaded board profile %s (PSRAM: %lu KB)", settings.board_profile.c_str(), psram_size);
|
EMSESP::logger().info("Loaded board profile %s (PSRAM: %lu KB)", settings.board_profile.c_str(), psram_size);
|
||||||
} else {
|
} else {
|
||||||
EMSESP::logger().info("Loaded board profile %s (PSRAM: not available)", settings.board_profile.c_str());
|
EMSESP::logger().info("Loaded board profile %s (PSRAM: not available)", settings.board_profile.c_str());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// apply the new board profile settings
|
// apply the new board profile settings
|
||||||
// 0=led, 1=dallas, 2=rx, 3=tx, 4=button, 5=phy_type, 6=eth_power, 7=eth_phy_addr, 8=eth_clock_mode, 9=led_type
|
// 0=led, 1=dallas, 2=rx, 3=tx, 4=button, 5=phy_type, 6=eth_power, 7=eth_phy_addr, 8=eth_clock_mode, 9=led_type
|
||||||
@@ -520,34 +535,35 @@ void WebSettings::set_board_profile(WebSettings & settings) {
|
|||||||
settings.eth_phy_addr = data[7]; // Ethernet PHY Address
|
settings.eth_phy_addr = data[7]; // Ethernet PHY Address
|
||||||
settings.eth_clock_mode = data[8]; // Ethernet Clock Mode
|
settings.eth_clock_mode = data[8]; // Ethernet Clock Mode
|
||||||
settings.led_type = data[9]; // LED Type
|
settings.led_type = data[9]; // LED Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if the value was changed
|
// 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, uint8_t flag) {
|
||||||
if (prev_v != new_v) {
|
if (prev_v != new_v) {
|
||||||
add_flags(flag);
|
add_flags(flag);
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
// EMSESP::logger().debug("check_flag: flag %d, prev_v=%d, new_v=%d", flag, prev_v, new_v);
|
// EMSESP::logger().debug("check_flag: flag %d, prev_v=%d, new_v=%d", flag, prev_v, new_v);
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSettings::add_flags(uint8_t flags) {
|
void WebSettings::add_flags(uint8_t flags) {
|
||||||
flags_ |= flags;
|
flags_ |= flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSettings::has_flags(uint8_t flags) {
|
bool WebSettings::has_flags(uint8_t flags) {
|
||||||
return (flags_ & flags) == flags;
|
return (flags_ & flags) == flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSettings::reset_flags() {
|
void WebSettings::reset_flags() {
|
||||||
flags_ = ChangeFlags::NONE;
|
flags_ = ChangeFlags::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t WebSettings::get_flags() {
|
uint8_t WebSettings::get_flags() {
|
||||||
return flags_;
|
return flags_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace emsesp
|
||||||
|
|
||||||
} // namespace emsesp
|
|
||||||
|
|||||||
Reference in New Issue
Block a user