mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-11 02:09:57 +03:00
first commit using PsychicHttp
This commit is contained in:
@@ -608,13 +608,13 @@ void EMSESPShell::stopped() {
|
||||
// show welcome banner
|
||||
void EMSESPShell::display_banner() {
|
||||
println();
|
||||
printfln("┌───────────────────────────────────────┐");
|
||||
printfln("│ %sEMS-ESP version %-12s%s │", COLOR_BOLD_ON, EMSESP_APP_VERSION, COLOR_BOLD_OFF);
|
||||
printfln("│ %s%shttps://github.com/emsesp/EMS-ESP32%s │", COLOR_BRIGHT_GREEN, COLOR_UNDERLINE, COLOR_RESET);
|
||||
printfln("│ │");
|
||||
printfln("│ type %shelp%s to show available commands │", COLOR_UNDERLINE, COLOR_RESET);
|
||||
printfln("│ use %ssu%s to access Admin commands │", COLOR_UNDERLINE, COLOR_RESET);
|
||||
printfln("└───────────────────────────────────────┘");
|
||||
printfln("┌────────────────────────────────────────┐");
|
||||
printfln("│ %sEMS-ESP version %-13s%s │", COLOR_BOLD_ON, EMSESP_APP_VERSION, COLOR_BOLD_OFF);
|
||||
printfln("│ %s%shttps://github.com/emsesp/EMS-ESP32%s │", COLOR_BRIGHT_GREEN, COLOR_UNDERLINE, COLOR_RESET);
|
||||
printfln("│ │");
|
||||
printfln("│ type %shelp%s to show available commands │", COLOR_UNDERLINE, COLOR_RESET);
|
||||
printfln("│ use %ssu%s to access Admin commands │", COLOR_UNDERLINE, COLOR_RESET);
|
||||
printfln("└────────────────────────────────────────┘");
|
||||
println();
|
||||
|
||||
// set console name
|
||||
|
||||
@@ -252,4 +252,16 @@ enum {
|
||||
#error Target CONFIG_IDF_TARGET is not supported
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINO_VERSION
|
||||
#ifndef STRINGIZE
|
||||
#define STRINGIZE(s) #s
|
||||
#endif
|
||||
#if TASMOTA_SDK
|
||||
#define ARDUINO_VERSION_STR(major, minor, patch) "Tasmota Arduino v" STRINGIZE(major) "." STRINGIZE(minor) "." STRINGIZE(patch)
|
||||
#else
|
||||
#define ARDUINO_VERSION_STR(major, minor, patch) "ESP32 Arduino v" STRINGIZE(major) "." STRINGIZE(minor) "." STRINGIZE(patch)
|
||||
#endif
|
||||
#define ARDUINO_VERSION ARDUINO_VERSION_STR(ESP_ARDUINO_VERSION_MAJOR, ESP_ARDUINO_VERSION_MINOR, ESP_ARDUINO_VERSION_PATCH)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2023 Paul Derbyshire
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
/*
|
||||
* These is the EMS devices that we currently recognize
|
||||
* The types and flags are stored in emsdevice.h
|
||||
* The types and flags are stored in emsdevice.h
|
||||
*/
|
||||
|
||||
// Boilers - 0x08
|
||||
@@ -107,6 +107,7 @@
|
||||
{ 66, DeviceType::THERMOSTAT, "ES72/RC20", DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17 or remote
|
||||
{ 76, DeviceType::THERMOSTAT, "ES73", DeviceFlags::EMS_DEVICE_FLAG_RC30_N}, // 0x10
|
||||
{113, DeviceType::THERMOSTAT, "ES72/RC20", DeviceFlags::EMS_DEVICE_FLAG_RC20_N}, // 0x17
|
||||
{159, DeviceType::THERMOSTAT, "ES79", DeviceFlags::EMS_DEVICE_FLAG_RC35}, // 0x10
|
||||
|
||||
// Thermostat - Junkers - 0x10
|
||||
{105, DeviceType::THERMOSTAT, "FW100", DeviceFlags::EMS_DEVICE_FLAG_JUNKERS},
|
||||
@@ -181,4 +182,4 @@
|
||||
// Generic - 0x40 or other with no product-id and no version
|
||||
{0, DeviceType::GENERIC, "unknown", DeviceFlags::EMS_DEVICE_FLAG_NONE}
|
||||
|
||||
// clang-format on
|
||||
// clang-format on
|
||||
|
||||
@@ -2420,7 +2420,7 @@ bool Boiler::set_ww_mode(const char * value, const int8_t id) {
|
||||
if (is_received(EMS_TYPE_UBAParameterWWPlus)) {
|
||||
if (Helpers::value2enum(value, set, FL_(enum_comfort1))) {
|
||||
write_command(EMS_TYPE_UBAParameterWWPlus, 13, comfort[set], EMS_TYPE_UBAParameterWWPlus);
|
||||
write_command(0x05, 70, set ? 0xAA : 0x55); //
|
||||
write_command(0x05, 70, set == 0 ? 0xAA : 0x55); //
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -22,9 +22,11 @@ static_assert(uuid::thread_safe, "uuid-common must be thread-safe");
|
||||
static_assert(uuid::log::thread_safe, "uuid-log must be thread-safe");
|
||||
static_assert(uuid::console::thread_safe, "uuid-console must be thread-safe");
|
||||
|
||||
#include <WWWData.h>
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
AsyncWebServer webServer(80);
|
||||
PsychicHttpServer webServer; // web server is static and global
|
||||
|
||||
#if defined(EMSESP_STANDALONE)
|
||||
FS dummyFS;
|
||||
@@ -61,7 +63,7 @@ uuid::log::Logger EMSESP::logger() {
|
||||
uuid::syslog::SyslogService System::syslog_;
|
||||
#endif
|
||||
|
||||
// The services
|
||||
// Core EMS-ESP services
|
||||
RxService EMSESP::rxservice_; // incoming Telegram Rx handler
|
||||
TxService EMSESP::txservice_; // outgoing Telegram Tx handler
|
||||
Mqtt EMSESP::mqtt_; // mqtt handler
|
||||
@@ -69,7 +71,9 @@ System EMSESP::system_; // core system services
|
||||
TemperatureSensor EMSESP::temperaturesensor_; // Temperature sensors
|
||||
AnalogSensor EMSESP::analogsensor_; // Analog sensors
|
||||
Shower EMSESP::shower_; // Shower logic
|
||||
Preferences EMSESP::nvs_; // NV Storage
|
||||
|
||||
// NV Storage
|
||||
Preferences EMSESP::nvs_;
|
||||
|
||||
// static/common variables
|
||||
uint16_t EMSESP::watch_id_ = WATCH_ID_NONE; // for when log is TRACE. 0 means no trace set
|
||||
@@ -1389,8 +1393,6 @@ void EMSESP::scheduled_fetch_values() {
|
||||
}
|
||||
}
|
||||
|
||||
// EMSESP main class
|
||||
|
||||
EMSESP::EMSESP()
|
||||
#ifndef EMSESP_STANDALONE
|
||||
: telnet_([this](Stream & stream, const IPAddress & addr, uint16_t port) -> std::shared_ptr<uuid::console::Shell> {
|
||||
@@ -1400,6 +1402,73 @@ EMSESP::EMSESP()
|
||||
{
|
||||
}
|
||||
|
||||
// add web server endpoint
|
||||
void EMSESP::handler(const char * uri, const char * contentType, const uint8_t * content, size_t len) {
|
||||
// remap to root
|
||||
if (strcmp(uri, "/index.html") == 0) {
|
||||
uri = "/";
|
||||
}
|
||||
webServer.on(uri, HTTP_GET, [contentType, content, len](PsychicRequest * request) {
|
||||
PsychicResponse response(request);
|
||||
response.setCode(200);
|
||||
response.setContentType(contentType);
|
||||
response.addHeader("Content-Encoding", "gzip");
|
||||
// response.addHeader("Content-Encoding", "br"); // Brotli - only works over HTTPS
|
||||
response.setContent(content, len);
|
||||
return response.send();
|
||||
});
|
||||
};
|
||||
|
||||
// configure web server
|
||||
// this can be only be done after the network has been initialized
|
||||
void EMSESP::setupWeb() {
|
||||
// set maximum number of uri handlers (.on() calls). default was 8
|
||||
// WWWData has 19 (in registerRoutes(handler)
|
||||
// esp8266React services has 13
|
||||
// custom projects has around 23
|
||||
webServer.config.max_uri_handlers = 70;
|
||||
|
||||
// TODO add support for HTTPS
|
||||
webServer.listen(80); // start the web server
|
||||
|
||||
DefaultHeaders::Instance().addHeader("Server", "EMS-ESP");
|
||||
|
||||
WWWData::registerRoutes(handler); // add webServer.on() endpoints from the generated web code
|
||||
|
||||
esp8266React.registerURI(); // load up the core system web endpoints
|
||||
|
||||
// init EMS-ESP web endpoints
|
||||
webDataService.registerURI(); // /rest{deviceData,coreData,sensorData...}
|
||||
webStatusService.registerURI(); // /rest/status
|
||||
webSettingsService.registerURI(); // /rest/{settings,boardprofile}
|
||||
webAPIService.registerURI(); // /api/*, /rest/{getSettings,getSchedule,getCustomizations,getEntities}
|
||||
webLogService.registerURI(); // /rest/logSettings and EventSource
|
||||
webCustomizationService.registerURI(); // /rest{customization,customizationEntities,resetCustomizations,devices,deviceEntities}
|
||||
webSchedulerService.registerURI(); // /rest/schedule
|
||||
webCustomEntityService.registerURI(); // /rest/customentities
|
||||
|
||||
webServer.onNotFound([](PsychicRequest * request) {
|
||||
if (request->method() == HTTP_GET) {
|
||||
Serial.printf("redirecting not found %s\n", request->uri().c_str()); // TODO remove debug
|
||||
String url = "http://" + request->host(); // TODO add support for https
|
||||
return request->redirect(url.c_str());
|
||||
} else if (request->method() == HTTP_OPTIONS) {
|
||||
return request->reply(200);
|
||||
} else {
|
||||
return request->reply(404);
|
||||
}
|
||||
});
|
||||
|
||||
// Add CORS if specified in the network settings
|
||||
esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
||||
if (networkSettings.enableCORS) {
|
||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", networkSettings.CORSOrigin);
|
||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Headers", "Accept, Content-Type, Authorization");
|
||||
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Credentials", "true");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// start all the core services
|
||||
// the services must be loaded in the correct order
|
||||
void EMSESP::start() {
|
||||
@@ -1441,8 +1510,13 @@ void EMSESP::start() {
|
||||
bool factory_settings = false;
|
||||
#endif
|
||||
|
||||
esp8266React.begin(); // loads core system services settings (network, mqtt, ap, ntp etc)
|
||||
esp8266React.begin(); // loads core system services settings (network, mqtt, ap, ntp etc)
|
||||
|
||||
setupWeb(); // configure web server, now that the network has been initialized
|
||||
|
||||
webLogService.begin(); // start web log service. now we can start capturing logs to the web log
|
||||
|
||||
// start Prefences, the internal persistance storage
|
||||
nvs_.begin("ems-esp", false, "nvs");
|
||||
|
||||
LOG_INFO("Starting EMS-ESP version %s", EMSESP_APP_VERSION); // welcome message
|
||||
@@ -1496,11 +1570,11 @@ void EMSESP::start() {
|
||||
#if defined(EMSESP_STANDALONE)
|
||||
Mqtt::on_connect(); // simulate an MQTT connection
|
||||
#endif
|
||||
|
||||
webServer.begin(); // start the web server
|
||||
}
|
||||
|
||||
// main loop calling all services
|
||||
|
||||
|
||||
void EMSESP::loop() {
|
||||
esp8266React.loop(); // web services
|
||||
system_.loop(); // does LED and checks system health, and syslog service
|
||||
@@ -1527,6 +1601,7 @@ void EMSESP::loop() {
|
||||
if (system_.telnet_enabled()) {
|
||||
telnet_.loop();
|
||||
}
|
||||
|
||||
#else
|
||||
if (!shell_->running()) {
|
||||
::exit(0);
|
||||
|
||||
13
src/emsesp.h
13
src/emsesp.h
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2023 Paul Derbyshire
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -228,8 +228,10 @@ class EMSESP {
|
||||
static TxService txservice_;
|
||||
static Preferences nvs_;
|
||||
|
||||
// web controllers
|
||||
static ESP8266React esp8266React;
|
||||
// esp8266React framework
|
||||
static ESP8266React esp8266React;
|
||||
|
||||
// EMS-ESP web controllers
|
||||
static WebSettingsService webSettingsService;
|
||||
static WebStatusService webStatusService;
|
||||
static WebDataService webDataService;
|
||||
@@ -239,6 +241,8 @@ class EMSESP {
|
||||
static WebSchedulerService webSchedulerService;
|
||||
static WebCustomEntityService webCustomEntityService;
|
||||
|
||||
static void handler(const char * uri, const char * contentType, const uint8_t * content, size_t len);
|
||||
|
||||
private:
|
||||
static std::string device_tostring(const uint8_t device_id);
|
||||
static void process_UBADevices(std::shared_ptr<const Telegram> telegram);
|
||||
@@ -282,8 +286,9 @@ class EMSESP {
|
||||
uuid::telnet::TelnetService telnet_;
|
||||
#endif
|
||||
|
||||
void setupWeb();
|
||||
|
||||
protected:
|
||||
// EMSESP();
|
||||
static uuid::log::Logger logger_;
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -64,7 +64,8 @@ const char * const languages[] = {EMSESP_LOCALE_EN,
|
||||
EMSESP_LOCALE_NO,
|
||||
EMSESP_LOCALE_FR,
|
||||
EMSESP_LOCALE_TR,
|
||||
EMSESP_LOCALE_IT};
|
||||
EMSESP_LOCALE_IT,
|
||||
EMSESP_LOCALE_SK};
|
||||
#endif
|
||||
|
||||
static constexpr uint8_t NUM_LANGUAGES = sizeof(languages) / sizeof(const char *);
|
||||
@@ -253,7 +254,9 @@ bool System::command_watch(const char * value, const int8_t id) {
|
||||
}
|
||||
|
||||
void System::store_nvs_values() {
|
||||
Command::call(EMSdevice::DeviceType::BOILER, "nompower", "-1"); // trigger a write
|
||||
if (Command::find_command(EMSdevice::DeviceType::BOILER, 0, "nompower") != nullptr) {
|
||||
Command::call(EMSdevice::DeviceType::BOILER, "nompower", "-1"); // trigger a write
|
||||
}
|
||||
EMSESP::analogsensor_.store_counters();
|
||||
EMSESP::nvs_.end();
|
||||
}
|
||||
@@ -729,7 +732,11 @@ void System::network_init(bool refresh) {
|
||||
// ETH_CLOCK_GPIO17_OUT = 3 RMII clock output from GPIO17, for 50hz inverted clock
|
||||
auto clock_mode = (eth_clock_mode_t)eth_clock_mode_;
|
||||
|
||||
eth_present_ = ETH.begin((eth_phy_type_t)phy_addr, power, mdc, mdio, type, clock_mode);
|
||||
#if ESP_ARDUINO_VERSION_MAJOR < 3
|
||||
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);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1039,42 +1046,44 @@ bool System::check_restore() {
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// see if we have a temp file, if so try and read it
|
||||
File new_file = LittleFS.open(TEMP_FILENAME_PATH);
|
||||
if (new_file) {
|
||||
DynamicJsonDocument jsonDocument = DynamicJsonDocument(FS_BUFFER_SIZE);
|
||||
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"];
|
||||
if (settings_type == "settings") {
|
||||
// It's a settings file. Parse each section separately. If it's system related it will require a reboot
|
||||
reboot_required = saveSettings(NETWORK_SETTINGS_FILE, "Network", input);
|
||||
reboot_required |= saveSettings(AP_SETTINGS_FILE, "AP", input);
|
||||
reboot_required |= saveSettings(MQTT_SETTINGS_FILE, "MQTT", input);
|
||||
reboot_required |= saveSettings(NTP_SETTINGS_FILE, "NTP", input);
|
||||
reboot_required |= saveSettings(SECURITY_SETTINGS_FILE, "Security", input);
|
||||
reboot_required |= saveSettings(EMSESP_SETTINGS_FILE, "Settings", input);
|
||||
reboot_required |= saveSettings(OTA_SETTINGS_FILE, "OTA", input);
|
||||
} else if (settings_type == "customizations") {
|
||||
// it's a customization file, just replace it and there's no need to reboot
|
||||
saveSettings(EMSESP_CUSTOMIZATION_FILE, "Customizations", input);
|
||||
} else if (settings_type == "schedule") {
|
||||
// it's a schedule file, just replace it and there's no need to reboot
|
||||
saveSettings(EMSESP_SCHEDULER_FILE, "Schedule", input);
|
||||
} else if (settings_type == "entities") {
|
||||
// it's a entity file, just replace it and there's no need to reboot
|
||||
saveSettings(EMSESP_CUSTOMENTITY_FILE, "Entities", input);
|
||||
if (LittleFS.exists(TEMP_FILENAME_PATH)) { // prevents open(): /littlefs/tmp_upload does not exist, no permits for creation
|
||||
File new_file = LittleFS.open(TEMP_FILENAME_PATH);
|
||||
if (new_file) {
|
||||
DynamicJsonDocument jsonDocument = DynamicJsonDocument(FS_BUFFER_SIZE);
|
||||
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"];
|
||||
if (settings_type == "settings") {
|
||||
// It's a settings file. Parse each section separately. If it's system related it will require a reboot
|
||||
reboot_required = saveSettings(NETWORK_SETTINGS_FILE, "Network", input);
|
||||
reboot_required |= saveSettings(AP_SETTINGS_FILE, "AP", input);
|
||||
reboot_required |= saveSettings(MQTT_SETTINGS_FILE, "MQTT", input);
|
||||
reboot_required |= saveSettings(NTP_SETTINGS_FILE, "NTP", input);
|
||||
reboot_required |= saveSettings(SECURITY_SETTINGS_FILE, "Security", input);
|
||||
reboot_required |= saveSettings(EMSESP_SETTINGS_FILE, "Settings", input);
|
||||
reboot_required |= saveSettings(OTA_SETTINGS_FILE, "OTA", input);
|
||||
} else if (settings_type == "customizations") {
|
||||
// it's a customization file, just replace it and there's no need to reboot
|
||||
saveSettings(EMSESP_CUSTOMIZATION_FILE, "Customizations", input);
|
||||
} else if (settings_type == "schedule") {
|
||||
// it's a schedule file, just replace it and there's no need to reboot
|
||||
saveSettings(EMSESP_SCHEDULER_FILE, "Schedule", input);
|
||||
} else if (settings_type == "entities") {
|
||||
// it's a entity file, just replace it and there's no need to reboot
|
||||
saveSettings(EMSESP_CUSTOMENTITY_FILE, "Entities", input);
|
||||
} else {
|
||||
LOG_ERROR("Unrecognized file uploaded");
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR("Unrecognized file uploaded");
|
||||
LOG_ERROR("Unrecognized file uploaded, not json");
|
||||
}
|
||||
} 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);
|
||||
// close (just in case) and remove the temp file
|
||||
new_file.close();
|
||||
LittleFS.remove(TEMP_FILENAME_PATH);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1201,13 +1210,16 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
|
||||
// System
|
||||
node = output.createNestedObject("System Info");
|
||||
node["version"] = EMSESP_APP_VERSION;
|
||||
node["platform"] = EMSESP_PLATFORM;
|
||||
node["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
|
||||
node["uptime (seconds)"] = uuid::get_uptime_sec();
|
||||
#ifndef EMSESP_STANDALONE
|
||||
node["platform"] = ARDUINO_VERSION;
|
||||
node["sdk"] = ESP.getSdkVersion();
|
||||
node["free mem"] = getHeapMem();
|
||||
node["max alloc"] = getMaxAllocMem();
|
||||
node["used app"] = EMSESP::system_.appUsed(); // kilobytes
|
||||
node["free app"] = EMSESP::system_.appFree(); // kilobytes
|
||||
node["partition"] = esp_ota_get_running_partition()->label;
|
||||
#endif
|
||||
node["reset reason"] = EMSESP::system_.reset_reason(0) + " / " + EMSESP::system_.reset_reason(1);
|
||||
|
||||
@@ -1581,4 +1593,4 @@ bool System::ntp_connected() {
|
||||
return ntp_connected_;
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
} // namespace emsesp
|
||||
@@ -306,7 +306,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
run_test("general");
|
||||
|
||||
#ifdef EMSESP_STANDALONE
|
||||
AsyncWebServerRequest request;
|
||||
PsychicRequest request;
|
||||
request.method(HTTP_GET);
|
||||
request.url("/api/custom");
|
||||
request.url("/api/custom/boiler_flowtemp");
|
||||
@@ -321,7 +321,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
run_test("general");
|
||||
|
||||
#ifdef EMSESP_STANDALONE
|
||||
AsyncWebServerRequest request;
|
||||
PsychicRequest request;
|
||||
request.method(HTTP_GET);
|
||||
request.url("/api/boiler/coldshot");
|
||||
EMSESP::webAPIService.webAPIService_get(&request);
|
||||
@@ -846,7 +846,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
run_test("boiler");
|
||||
run_test("thermostat");
|
||||
|
||||
AsyncWebServerRequest request;
|
||||
PsychicRequest request;
|
||||
DynamicJsonDocument doc(2000);
|
||||
JsonVariant json;
|
||||
request.method(HTTP_GET);
|
||||
@@ -890,7 +890,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
Mqtt::nested_format(1);
|
||||
run_test("310");
|
||||
|
||||
AsyncWebServerRequest request;
|
||||
PsychicRequest request;
|
||||
request.method(HTTP_POST);
|
||||
DynamicJsonDocument doc(2000);
|
||||
JsonVariant json;
|
||||
@@ -915,7 +915,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
run_test("boiler");
|
||||
run_test("thermostat");
|
||||
|
||||
AsyncWebServerRequest requestX;
|
||||
PsychicRequest requestX;
|
||||
DynamicJsonDocument docX(2000);
|
||||
JsonVariant jsonX;
|
||||
|
||||
@@ -1084,7 +1084,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
EMSESP::mqtt_.incoming("home/cellar/heating/thermostat/mode"); // empty payload
|
||||
|
||||
// Web API TESTS
|
||||
AsyncWebServerRequest request;
|
||||
PsychicRequest request;
|
||||
|
||||
request.method(HTTP_GET);
|
||||
|
||||
@@ -1714,7 +1714,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
||||
// shell.invoke_command("call mixer wwc2 info");
|
||||
|
||||
// test API
|
||||
AsyncWebServerRequest request;
|
||||
PsychicRequest request;
|
||||
request.url("/api/mixer");
|
||||
EMSESP::webAPIService.webAPIService_get(&request);
|
||||
request.url("/api/mixer/hc1/pumpstatus");
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define EMSESP_TEST_H
|
||||
|
||||
#include "emsesp.h"
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <PsychicHttp.h>
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define EMSESP_APP_VERSION "3.6.5-dev.4"
|
||||
#define EMSESP_APP_VERSION "3.6.5-https.0"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2023 Paul Derbyshire
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -25,49 +25,46 @@ namespace emsesp {
|
||||
uint32_t WebAPIService::api_count_ = 0;
|
||||
uint16_t WebAPIService::api_fails_ = 0;
|
||||
|
||||
WebAPIService::WebAPIService(AsyncWebServer * server, SecurityManager * securityManager)
|
||||
: _securityManager(securityManager)
|
||||
, _apiHandler("/api", std::bind(&WebAPIService::webAPIService_post, this, _1, _2), 256) { // for POSTS, must use 'Content-Type: application/json' in header
|
||||
server->on("/api", HTTP_GET, std::bind(&WebAPIService::webAPIService_get, this, _1)); // for GETS
|
||||
server->addHandler(&_apiHandler);
|
||||
WebAPIService::WebAPIService(PsychicHttpServer * server, SecurityManager * securityManager)
|
||||
: _server(server)
|
||||
, _securityManager(securityManager) {
|
||||
}
|
||||
|
||||
void WebAPIService::registerURI() {
|
||||
// POST /{device}[/{hc|id}][/{name}]
|
||||
// note: must explicity use 'Content-Type: application/json' in header
|
||||
_server->on(EMSESP_API_SERVICE_PATH, HTTP_POST, [this](PsychicRequest * request, JsonVariant & json) {
|
||||
// if no body then treat it as a secure GET
|
||||
if (!json.is<JsonObject>()) {
|
||||
StaticJsonDocument<EMSESP_JSON_SIZE_SMALL> input_doc;
|
||||
JsonObject input = input_doc.to<JsonObject>();
|
||||
return parse(request, input);
|
||||
}
|
||||
|
||||
// extract values from the json. these will be used as default values
|
||||
auto && input = json.as<JsonObject>();
|
||||
return parse(request, input);
|
||||
});
|
||||
|
||||
// GET /{device}/{entity}
|
||||
_server->on(EMSESP_API_SERVICE_PATH, HTTP_GET, [this](PsychicRequest * request) {
|
||||
StaticJsonDocument<EMSESP_JSON_SIZE_SMALL> input_doc;
|
||||
JsonObject input = input_doc.to<JsonObject>();
|
||||
return parse(request, input);
|
||||
});
|
||||
|
||||
// for settings
|
||||
server->on(GET_SETTINGS_PATH, HTTP_GET, securityManager->wrapRequest(std::bind(&WebAPIService::getSettings, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
server->on(GET_CUSTOMIZATIONS_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebAPIService::getCustomizations, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
server->on(GET_SCHEDULE_PATH, HTTP_GET, securityManager->wrapRequest(std::bind(&WebAPIService::getSchedule, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
server->on(GET_ENTITIES_PATH, HTTP_GET, securityManager->wrapRequest(std::bind(&WebAPIService::getEntities, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
}
|
||||
|
||||
// HTTP GET
|
||||
// GET /{device}
|
||||
// GET /{device}/{entity}
|
||||
void WebAPIService::webAPIService_get(AsyncWebServerRequest * request) {
|
||||
// has no body JSON so create dummy as empty input object
|
||||
StaticJsonDocument<EMSESP_JSON_SIZE_SMALL> input_doc;
|
||||
JsonObject input = input_doc.to<JsonObject>();
|
||||
parse(request, input);
|
||||
}
|
||||
|
||||
// For HTTP POSTS with an optional JSON body
|
||||
// HTTP_POST | HTTP_PUT | HTTP_PATCH
|
||||
// POST /{device}[/{hc|id}][/{name}]
|
||||
void WebAPIService::webAPIService_post(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
// if no body then treat it as a secure GET
|
||||
if (!json.is<JsonObject>()) {
|
||||
webAPIService_get(request);
|
||||
return;
|
||||
}
|
||||
|
||||
// extract values from the json. these will be used as default values
|
||||
auto && input = json.as<JsonObject>();
|
||||
parse(request, input);
|
||||
_server->on(GET_SETTINGS_PATH, HTTP_GET, _securityManager->wrapRequest(std::bind(&WebAPIService::getSettings, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
_server->on(GET_CUSTOMIZATIONS_PATH,
|
||||
HTTP_GET,
|
||||
_securityManager->wrapRequest(std::bind(&WebAPIService::getCustomizations, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
_server->on(GET_SCHEDULE_PATH, HTTP_GET, _securityManager->wrapRequest(std::bind(&WebAPIService::getSchedule, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
_server->on(GET_ENTITIES_PATH, HTTP_GET, _securityManager->wrapRequest(std::bind(&WebAPIService::getEntities, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
}
|
||||
|
||||
// parse the URL looking for query or path parameters
|
||||
// reporting back any errors
|
||||
void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) {
|
||||
esp_err_t WebAPIService::parse(PsychicRequest * request, JsonObject & input) {
|
||||
// check if the user has admin privileges (token is included and authorized)
|
||||
bool is_admin = false;
|
||||
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
||||
@@ -77,6 +74,7 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) {
|
||||
|
||||
// check for query parameters first, the old style from v2
|
||||
// api?device={device}&cmd={name}&data={value}&id={hc}
|
||||
// TODO check if this works, because we're using wildcard now for api/*
|
||||
if (request->url() == "/api") {
|
||||
// get the device
|
||||
if (request->hasParam(F_(device))) {
|
||||
@@ -106,18 +104,24 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) {
|
||||
emsesp::EMSESP::system_.refreshHeapMem();
|
||||
|
||||
// output json buffer
|
||||
size_t buffer = EMSESP_JSON_SIZE_XXXLARGE;
|
||||
auto * response = new PrettyAsyncJsonResponse(false, buffer);
|
||||
while (!response->getSize()) {
|
||||
delete response;
|
||||
buffer -= 1024;
|
||||
response = new PrettyAsyncJsonResponse(false, buffer);
|
||||
}
|
||||
JsonObject output = response->getRoot();
|
||||
size_t buffer = EMSESP_JSON_SIZE_XXXLARGE;
|
||||
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false, buffer);
|
||||
|
||||
// TODO add back memory managegement. Be careful we do need to free()/delete() any object we extend with new()
|
||||
// while (!response->getSize()) {
|
||||
// delete response;
|
||||
// buffer -= 1024;
|
||||
// response = new PrettyAsyncJsonResponse(false, buffer);
|
||||
// response = PsychicJsonResponse(request, false, buffer);
|
||||
// }
|
||||
|
||||
JsonObject output = response.getRoot();
|
||||
|
||||
// call command
|
||||
uint8_t return_code = Command::process(request->url().c_str(), is_admin, input, output);
|
||||
|
||||
// handle failure
|
||||
if (return_code != CommandRet::OK) {
|
||||
char error[100];
|
||||
if (output.size()) {
|
||||
@@ -127,42 +131,29 @@ void WebAPIService::parse(AsyncWebServerRequest * request, JsonObject & input) {
|
||||
}
|
||||
emsesp::EMSESP::logger().err(error);
|
||||
api_fails_++;
|
||||
|
||||
// FAIL, OK, NOT_FOUND, ERROR, NOT_ALLOWED = 400 (bad request), 200 (OK), 400 (not found), 400 (bad request), 401 (unauthorized)
|
||||
int ret_codes[6] = {400, 200, 400, 400, 401, 400};
|
||||
request->reply(ret_codes[return_code]); // exit with error code
|
||||
}
|
||||
|
||||
// if we're returning single values, just sent as plain text
|
||||
api_count_++; // another succesful api call
|
||||
|
||||
// if we're returning single values, just sent as plain text and not json
|
||||
// https://github.com/emsesp/EMS-ESP32/issues/462#issuecomment-1093877210
|
||||
if (output.containsKey("api_data")) {
|
||||
JsonVariant data = output["api_data"];
|
||||
request->send(200, "text/plain; charset=utf-8", data.as<String>());
|
||||
api_count_++;
|
||||
delete response;
|
||||
return;
|
||||
return request->reply(200, "text/plain; charset=utf-8", data.as<const char *>());
|
||||
}
|
||||
|
||||
// send the json that came back from the command call
|
||||
// FAIL, OK, NOT_FOUND, ERROR, NOT_ALLOWED = 400 (bad request), 200 (OK), 400 (not found), 400 (bad request), 401 (unauthorized)
|
||||
int ret_codes[6] = {400, 200, 400, 400, 401, 400};
|
||||
response->setCode(ret_codes[return_code]);
|
||||
response->setLength();
|
||||
response->setContentType("application/json; charset=utf-8");
|
||||
request->send(response);
|
||||
api_count_++;
|
||||
|
||||
#if defined(EMSESP_STANDALONE)
|
||||
Serial.print(COLOR_YELLOW);
|
||||
Serial.print("web response code: ");
|
||||
Serial.println(ret_codes[return_code]);
|
||||
if (output.size()) {
|
||||
serializeJsonPretty(output, Serial);
|
||||
}
|
||||
Serial.println();
|
||||
Serial.print(COLOR_RESET);
|
||||
#endif
|
||||
// normal return
|
||||
// as setContentType("application/json; charset=utf-8")
|
||||
return response.send();
|
||||
}
|
||||
|
||||
void WebAPIService::getSettings(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false, FS_BUFFER_SIZE);
|
||||
JsonObject root = response->getRoot();
|
||||
esp_err_t WebAPIService::getSettings(PsychicRequest * request) {
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, this, FS_BUFFER_SIZE);
|
||||
JsonObject root = response.getRoot();
|
||||
|
||||
root["type"] = "settings";
|
||||
|
||||
@@ -177,44 +168,39 @@ void WebAPIService::getSettings(AsyncWebServerRequest * request) {
|
||||
System::extractSettings(SECURITY_SETTINGS_FILE, "Security", root);
|
||||
System::extractSettings(EMSESP_SETTINGS_FILE, "Settings", root);
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return response.send();
|
||||
}
|
||||
|
||||
void WebAPIService::getCustomizations(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false, FS_BUFFER_SIZE);
|
||||
JsonObject root = response->getRoot();
|
||||
esp_err_t WebAPIService::getCustomizations(PsychicRequest * request) {
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, this, FS_BUFFER_SIZE);
|
||||
JsonObject root = response.getRoot();
|
||||
|
||||
root["type"] = "customizations";
|
||||
|
||||
System::extractSettings(EMSESP_CUSTOMIZATION_FILE, "Customizations", root);
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return response.send();
|
||||
}
|
||||
|
||||
void WebAPIService::getSchedule(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false, FS_BUFFER_SIZE);
|
||||
JsonObject root = response->getRoot();
|
||||
esp_err_t WebAPIService::getSchedule(PsychicRequest * request) {
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, this, FS_BUFFER_SIZE);
|
||||
JsonObject root = response.getRoot();
|
||||
|
||||
root["type"] = "schedule";
|
||||
|
||||
System::extractSettings(EMSESP_SCHEDULER_FILE, "Schedule", root);
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return response.send();
|
||||
}
|
||||
|
||||
void WebAPIService::getEntities(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false, FS_BUFFER_SIZE);
|
||||
JsonObject root = response->getRoot();
|
||||
esp_err_t WebAPIService::getEntities(PsychicRequest * request) {
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, this, FS_BUFFER_SIZE);
|
||||
JsonObject root = response.getRoot();
|
||||
|
||||
root["type"] = "entities";
|
||||
|
||||
System::extractSettings(EMSESP_CUSTOMENTITY_FILE, "Entities", root);
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return response.send();
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#ifndef WebAPIService_h
|
||||
#define WebAPIService_h
|
||||
|
||||
#define EMSESP_API_SERVICE_PATH "/api"
|
||||
#define EMSESP_API_SERVICE_PATH "/api/*"
|
||||
#define GET_SETTINGS_PATH "/rest/getSettings"
|
||||
#define GET_CUSTOMIZATIONS_PATH "/rest/getCustomizations"
|
||||
#define GET_SCHEDULE_PATH "/rest/getSchedule"
|
||||
@@ -29,10 +29,9 @@ namespace emsesp {
|
||||
|
||||
class WebAPIService {
|
||||
public:
|
||||
WebAPIService(AsyncWebServer * server, SecurityManager * securityManager);
|
||||
WebAPIService(PsychicHttpServer * server, SecurityManager * securityManager);
|
||||
|
||||
void webAPIService_post(AsyncWebServerRequest * request, JsonVariant & json); // for POSTs
|
||||
void webAPIService_get(AsyncWebServerRequest * request); // for GETs
|
||||
void registerURI();
|
||||
|
||||
static uint32_t api_count() {
|
||||
return api_count_;
|
||||
@@ -43,18 +42,18 @@ class WebAPIService {
|
||||
}
|
||||
|
||||
private:
|
||||
SecurityManager * _securityManager;
|
||||
AsyncCallbackJsonWebHandler _apiHandler; // for POSTs
|
||||
SecurityManager * _securityManager;
|
||||
PsychicHttpServer * _server;
|
||||
|
||||
static uint32_t api_count_;
|
||||
static uint16_t api_fails_;
|
||||
|
||||
void parse(AsyncWebServerRequest * request, JsonObject & input);
|
||||
esp_err_t parse(PsychicRequest * request, JsonObject & input);
|
||||
|
||||
void getSettings(AsyncWebServerRequest * request);
|
||||
void getCustomizations(AsyncWebServerRequest * request);
|
||||
void getSchedule(AsyncWebServerRequest * request);
|
||||
void getEntities(AsyncWebServerRequest * request);
|
||||
esp_err_t getSettings(PsychicRequest * request);
|
||||
esp_err_t getCustomizations(PsychicRequest * request);
|
||||
esp_err_t getSchedule(PsychicRequest * request);
|
||||
esp_err_t getEntities(PsychicRequest * request);
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace emsesp {
|
||||
|
||||
using namespace std::placeholders; // for `_1` etc
|
||||
|
||||
WebCustomEntityService::WebCustomEntityService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||
WebCustomEntityService::WebCustomEntityService(PsychicHttpServer * server, FS * fs, SecurityManager * securityManager)
|
||||
: _httpEndpoint(WebCustomEntity::read,
|
||||
WebCustomEntity::update,
|
||||
this,
|
||||
@@ -33,6 +33,10 @@ WebCustomEntityService::WebCustomEntityService(AsyncWebServer * server, FS * fs,
|
||||
, _fsPersistence(WebCustomEntity::read, WebCustomEntity::update, this, fs, EMSESP_CUSTOMENTITY_FILE, FS_BUFFER_SIZE) {
|
||||
}
|
||||
|
||||
void WebCustomEntityService::registerURI() {
|
||||
_httpEndpoint.registerURI();
|
||||
}
|
||||
|
||||
// load the settings when the service starts
|
||||
void WebCustomEntityService::begin() {
|
||||
_fsPersistence.readFromFS();
|
||||
@@ -469,7 +473,7 @@ uint8_t WebCustomEntityService::has_commands() {
|
||||
return count;
|
||||
}
|
||||
|
||||
// send to dashboard, msgpack don't like serialized, use number
|
||||
// send to dashboard
|
||||
void WebCustomEntityService::generate_value_web(JsonObject & output) {
|
||||
EMSESP::webCustomEntityService.read([&](WebCustomEntity & webEntity) { customEntityItems = &webEntity.customEntityItems; });
|
||||
|
||||
|
||||
@@ -50,9 +50,11 @@ class WebCustomEntity {
|
||||
|
||||
class WebCustomEntityService : public StatefulService<WebCustomEntity> {
|
||||
public:
|
||||
WebCustomEntityService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
|
||||
WebCustomEntityService(PsychicHttpServer * server, FS * fs, SecurityManager * securityManager);
|
||||
|
||||
void begin();
|
||||
void registerURI();
|
||||
|
||||
void publish_single(const CustomEntityItem & entity);
|
||||
void publish(const bool force = false);
|
||||
bool command_setvalue(const char * value, const std::string name);
|
||||
|
||||
@@ -24,35 +24,38 @@ using namespace std::placeholders; // for `_1` etc
|
||||
|
||||
bool WebCustomization::_start = true;
|
||||
|
||||
WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||
: _httpEndpoint(WebCustomization::read,
|
||||
WebCustomizationService::WebCustomizationService(PsychicHttpServer * server, FS * fs, SecurityManager * securityManager)
|
||||
: _server(server)
|
||||
, _securityManager(securityManager)
|
||||
, _httpEndpoint(WebCustomization::read,
|
||||
WebCustomization::update,
|
||||
this,
|
||||
server,
|
||||
EMSESP_CUSTOMIZATION_SERVICE_PATH,
|
||||
securityManager,
|
||||
AuthenticationPredicates::IS_AUTHENTICATED)
|
||||
, _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE)
|
||||
, _masked_entities_handler(CUSTOMIZATION_ENTITIES_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebCustomizationService::customization_entities, this, _1, _2),
|
||||
AuthenticationPredicates::IS_AUTHENTICATED)) {
|
||||
server->on(DEVICE_ENTITIES_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebCustomizationService::device_entities, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
, _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE) {
|
||||
}
|
||||
|
||||
void WebCustomizationService::registerURI() {
|
||||
_httpEndpoint.registerURI();
|
||||
|
||||
server->on(DEVICES_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebCustomizationService::devices, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
_server->on(CUSTOMIZATION_ENTITIES_PATH,
|
||||
HTTP_POST,
|
||||
_securityManager->wrapCallback(std::bind(&WebCustomizationService::customization_entities, this, _1, _2),
|
||||
AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
server->on(RESET_CUSTOMIZATION_SERVICE_PATH,
|
||||
HTTP_POST,
|
||||
securityManager->wrapRequest(std::bind(&WebCustomizationService::reset_customization, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
_server->on(DEVICE_ENTITIES_PATH,
|
||||
HTTP_GET,
|
||||
_securityManager->wrapRequest(std::bind(&WebCustomizationService::device_entities, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
_masked_entities_handler.setMethod(HTTP_POST);
|
||||
_masked_entities_handler.setMaxContentLength(2048);
|
||||
_masked_entities_handler.setMaxJsonBufferSize(2048);
|
||||
server->addHandler(&_masked_entities_handler);
|
||||
_server->on(DEVICES_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
_securityManager->wrapRequest(std::bind(&WebCustomizationService::devices, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
_server->on(RESET_CUSTOMIZATION_SERVICE_PATH,
|
||||
HTTP_POST,
|
||||
_securityManager->wrapRequest(std::bind(&WebCustomizationService::reset_customization, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
}
|
||||
|
||||
// this creates the customization file, saving it to the FS
|
||||
@@ -163,24 +166,22 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization &
|
||||
}
|
||||
|
||||
// deletes the customization file
|
||||
void WebCustomizationService::reset_customization(AsyncWebServerRequest * request) {
|
||||
esp_err_t WebCustomizationService::reset_customization(PsychicRequest * request) {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
if (LittleFS.remove(EMSESP_CUSTOMIZATION_FILE)) {
|
||||
AsyncWebServerResponse * response = request->beginResponse(205); // restart needed
|
||||
request->send(response);
|
||||
EMSESP::system_.restart_requested(true);
|
||||
return;
|
||||
return request->reply(205); // restart needed
|
||||
}
|
||||
|
||||
// failed
|
||||
AsyncWebServerResponse * response = request->beginResponse(400); // bad request
|
||||
request->send(response);
|
||||
return request->reply(400); // bad request
|
||||
#endif
|
||||
}
|
||||
|
||||
// send back a list of devices used in the customization web page
|
||||
void WebCustomizationService::devices(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XLARGE);
|
||||
JsonObject root = response->getRoot();
|
||||
esp_err_t WebCustomizationService::devices(PsychicRequest * request) {
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false, EMSESP_JSON_SIZE_XLARGE);
|
||||
JsonObject root = response.getRoot();
|
||||
|
||||
// list is already sorted by device type
|
||||
// controller is ignored since it doesn't have any associated entities
|
||||
@@ -195,51 +196,47 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) {
|
||||
}
|
||||
}
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return response.send();
|
||||
}
|
||||
|
||||
// send back list of device entities
|
||||
void WebCustomizationService::device_entities(AsyncWebServerRequest * request) {
|
||||
esp_err_t WebCustomizationService::device_entities(PsychicRequest * request) {
|
||||
uint8_t id;
|
||||
if (request->hasParam(F_(id))) {
|
||||
id = Helpers::atoint(request->getParam(F_(id))->value().c_str()); // get id from url
|
||||
|
||||
size_t buffer = EMSESP_JSON_SIZE_XXXXLARGE;
|
||||
auto * response = new MsgpackAsyncJsonResponse(true, buffer);
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, true, EMSESP_JSON_SIZE_XXXXLARGE, true); // is array and also msgpack
|
||||
JsonArray output = response.getRoot();
|
||||
|
||||
// TODO add back memory management
|
||||
// while (!response) {
|
||||
// delete response;
|
||||
// buffer -= 1024;
|
||||
// // response = new MsgpackAsyncJsonResponse(true, buffer);
|
||||
// }
|
||||
|
||||
// TODO add msgpack
|
||||
|
||||
while (!response) {
|
||||
delete response;
|
||||
buffer -= 1024;
|
||||
response = new MsgpackAsyncJsonResponse(true, buffer);
|
||||
}
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
if (emsdevice->unique_id() == id) {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
JsonArray output = response->getRoot();
|
||||
emsdevice->generate_values_web_customization(output);
|
||||
#endif
|
||||
#if defined(EMSESP_DEBUG)
|
||||
size_t length = response->setLength();
|
||||
EMSESP::logger().debug("Customization buffer used: %d", length);
|
||||
#else
|
||||
response->setLength();
|
||||
#endif
|
||||
request->send(response);
|
||||
return;
|
||||
// request->send(response);
|
||||
// return;
|
||||
return response.send();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// invalid, but send OK anyway
|
||||
AsyncWebServerResponse * response = request->beginResponse(200);
|
||||
request->send(response);
|
||||
return request->reply(200); // OK
|
||||
}
|
||||
|
||||
// takes a list of updated entities with new masks from the web UI
|
||||
// saves it in the customization service
|
||||
// and updates the entity list real-time
|
||||
void WebCustomizationService::customization_entities(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
esp_err_t WebCustomizationService::customization_entities(PsychicRequest * request, JsonVariant & json) {
|
||||
bool need_reboot = false;
|
||||
if (json.is<JsonObject>()) {
|
||||
// find the device using the unique_id
|
||||
@@ -324,8 +321,7 @@ void WebCustomizationService::customization_entities(AsyncWebServerRequest * req
|
||||
}
|
||||
}
|
||||
|
||||
AsyncWebServerResponse * response = request->beginResponse(need_reboot ? 205 : 200); // reboot or just OK
|
||||
request->send(response);
|
||||
return request->reply(need_reboot ? 205 : 200); // reboot or just OK
|
||||
}
|
||||
|
||||
// load the settings when the service starts
|
||||
|
||||
@@ -80,9 +80,10 @@ class WebCustomization {
|
||||
|
||||
class WebCustomizationService : public StatefulService<WebCustomization> {
|
||||
public:
|
||||
WebCustomizationService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
|
||||
WebCustomizationService(PsychicHttpServer * server, FS * fs, SecurityManager * securityManager);
|
||||
|
||||
void begin();
|
||||
void registerURI();
|
||||
|
||||
// make all functions public so we can test in the debug and standalone mode
|
||||
#ifndef EMSESP_STANDALONE
|
||||
@@ -93,14 +94,16 @@ class WebCustomizationService : public StatefulService<WebCustomization> {
|
||||
FSPersistence<WebCustomization> _fsPersistence;
|
||||
|
||||
// GET
|
||||
void devices(AsyncWebServerRequest * request);
|
||||
void device_entities(AsyncWebServerRequest * request);
|
||||
esp_err_t devices(PsychicRequest * request);
|
||||
esp_err_t device_entities(PsychicRequest * request);
|
||||
|
||||
// POST
|
||||
void customization_entities(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void reset_customization(AsyncWebServerRequest * request); // command
|
||||
esp_err_t customization_entities(PsychicRequest * request, JsonVariant & json);
|
||||
esp_err_t reset_customization(PsychicRequest * request); // is a command
|
||||
|
||||
AsyncCallbackJsonWebHandler _masked_entities_handler;
|
||||
private:
|
||||
SecurityManager * _securityManager;
|
||||
PsychicHttpServer * _server;
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -22,57 +22,56 @@ namespace emsesp {
|
||||
|
||||
using namespace std::placeholders; // for `_1` etc
|
||||
|
||||
WebDataService::WebDataService(AsyncWebServer * server, SecurityManager * securityManager)
|
||||
: _write_value_handler(WRITE_DEVICE_VALUE_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebDataService::write_device_value, this, _1, _2), AuthenticationPredicates::IS_ADMIN))
|
||||
, _write_temperature_handler(WRITE_TEMPERATURE_SENSOR_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebDataService::write_temperature_sensor, this, _1, _2),
|
||||
AuthenticationPredicates::IS_ADMIN))
|
||||
, _write_analog_handler(WRITE_ANALOG_SENSOR_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebDataService::write_analog_sensor, this, _1, _2), AuthenticationPredicates::IS_ADMIN)) {
|
||||
// GET's
|
||||
server->on(DEVICE_DATA_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebDataService::device_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
server->on(CORE_DATA_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebDataService::core_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
server->on(SENSOR_DATA_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebDataService::sensor_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
// POST's
|
||||
server->on(SCAN_DEVICES_SERVICE_PATH,
|
||||
HTTP_POST,
|
||||
securityManager->wrapRequest(std::bind(&WebDataService::scan_devices, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
|
||||
_write_value_handler.setMethod(HTTP_POST);
|
||||
_write_value_handler.setMaxContentLength(256);
|
||||
server->addHandler(&_write_value_handler);
|
||||
|
||||
_write_temperature_handler.setMethod(HTTP_POST);
|
||||
_write_temperature_handler.setMaxContentLength(256);
|
||||
server->addHandler(&_write_temperature_handler);
|
||||
|
||||
_write_analog_handler.setMethod(HTTP_POST);
|
||||
_write_analog_handler.setMaxContentLength(256);
|
||||
server->addHandler(&_write_analog_handler);
|
||||
WebDataService::WebDataService(PsychicHttpServer * server, SecurityManager * securityManager)
|
||||
: _server(server)
|
||||
, _securityManager(securityManager) {
|
||||
}
|
||||
|
||||
void WebDataService::registerURI() {
|
||||
// GET's
|
||||
_server->on(CORE_DATA_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
_securityManager->wrapRequest(std::bind(&WebDataService::core_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
_server->on(DEVICE_DATA_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
_securityManager->wrapRequest(std::bind(&WebDataService::device_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
_server->on(SENSOR_DATA_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
_securityManager->wrapRequest(std::bind(&WebDataService::sensor_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
// POST's
|
||||
_server->on(SCAN_DEVICES_SERVICE_PATH,
|
||||
HTTP_POST,
|
||||
_securityManager->wrapRequest(std::bind(&WebDataService::scan_devices, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
|
||||
_server->on(WRITE_DEVICE_VALUE_SERVICE_PATH,
|
||||
HTTP_POST,
|
||||
_securityManager->wrapCallback(std::bind(&WebDataService::write_device_value, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
_server->on(WRITE_TEMPERATURE_SENSOR_SERVICE_PATH,
|
||||
HTTP_POST,
|
||||
_securityManager->wrapCallback(std::bind(&WebDataService::write_temperature_sensor, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
_server->on(WRITE_ANALOG_SENSOR_SERVICE_PATH,
|
||||
HTTP_POST,
|
||||
_securityManager->wrapCallback(std::bind(&WebDataService::write_analog_sensor, this, _1, _2), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
}
|
||||
|
||||
|
||||
// scan devices service
|
||||
void WebDataService::scan_devices(AsyncWebServerRequest * request) {
|
||||
esp_err_t WebDataService::scan_devices(PsychicRequest * request) {
|
||||
EMSESP::logger().info("Scanning devices...");
|
||||
EMSESP::scan_devices();
|
||||
request->send(200);
|
||||
return request->reply(200);
|
||||
}
|
||||
|
||||
// this is used in the dashboard and contains all ems device information
|
||||
// /coreData endpoint
|
||||
void WebDataService::core_data(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE);
|
||||
JsonObject root = response->getRoot();
|
||||
esp_err_t WebDataService::core_data(PsychicRequest * request) {
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false, EMSESP_JSON_SIZE_XXLARGE);
|
||||
JsonObject root = response.getRoot();
|
||||
|
||||
// list is already sorted by device type
|
||||
JsonArray devices = root.createNestedArray("devices");
|
||||
@@ -109,15 +108,14 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
|
||||
|
||||
root["connected"] = EMSESP::bus_status() != 2;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return response.send();
|
||||
}
|
||||
|
||||
// sensor data - sends back to web
|
||||
// /sensorData endpoint
|
||||
void WebDataService::sensor_data(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_XXLARGE);
|
||||
JsonObject root = response->getRoot();
|
||||
esp_err_t WebDataService::sensor_data(PsychicRequest * request) {
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false, EMSESP_JSON_SIZE_XXLARGE);
|
||||
JsonObject root = response.getRoot();
|
||||
|
||||
// temperature sensors
|
||||
JsonArray sensors = root.createNestedArray("ts");
|
||||
@@ -167,26 +165,26 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) {
|
||||
root["analog_enabled"] = EMSESP::analog_enabled();
|
||||
root["platform"] = EMSESP_PLATFORM;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return response.send();
|
||||
}
|
||||
|
||||
// The unique_id is the unique record ID from the Web table to identify which device to load
|
||||
// Compresses the JSON using MsgPack https://msgpack.org/index.html
|
||||
void WebDataService::device_data(AsyncWebServerRequest * request) {
|
||||
esp_err_t WebDataService::device_data(PsychicRequest * request) {
|
||||
uint8_t id;
|
||||
if (request->hasParam(F_(id))) {
|
||||
id = Helpers::atoint(request->getParam(F_(id))->value().c_str()); // get id from url
|
||||
|
||||
size_t buffer = EMSESP_JSON_SIZE_XXXXLARGE;
|
||||
auto * response = new MsgpackAsyncJsonResponse(false, buffer);
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false, EMSESP_JSON_SIZE_XXXXLARGE, true); // is jsonobject and also msgpack
|
||||
JsonObject output = response.getRoot();
|
||||
|
||||
// TODO add back memory management?
|
||||
// check size
|
||||
while (!response) {
|
||||
delete response;
|
||||
buffer -= 1024;
|
||||
response = new MsgpackAsyncJsonResponse(false, buffer);
|
||||
}
|
||||
// while (!response) {
|
||||
// delete response;
|
||||
// buffer -= 1024;
|
||||
// response = new MsgpackAsyncJsonResponse(false, buffer);
|
||||
// }
|
||||
|
||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||
if (emsdevice->unique_id() == id) {
|
||||
@@ -196,39 +194,26 @@ void WebDataService::device_data(AsyncWebServerRequest * request) {
|
||||
}
|
||||
EMSESP::wait_validate(0); // reset in case of timeout
|
||||
#ifndef EMSESP_STANDALONE
|
||||
JsonObject output = response->getRoot();
|
||||
emsdevice->generate_values_web(output);
|
||||
#endif
|
||||
|
||||
#if defined(EMSESP_DEBUG)
|
||||
size_t length = response->setLength();
|
||||
EMSESP::logger().debug("Dashboard buffer used: %d", length);
|
||||
#else
|
||||
response->setLength();
|
||||
#endif
|
||||
request->send(response);
|
||||
return;
|
||||
return response.send();
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
if (id == 99) {
|
||||
JsonObject output = response->getRoot();
|
||||
EMSESP::webCustomEntityService.generate_value_web(output);
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
return response.send();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// invalid
|
||||
AsyncWebServerResponse * response = request->beginResponse(400);
|
||||
request->send(response);
|
||||
return request->reply(400); // Invalid/bad request
|
||||
}
|
||||
|
||||
// assumes the service has been checked for admin authentication
|
||||
void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
esp_err_t WebDataService::write_device_value(PsychicRequest * request, JsonVariant & json) {
|
||||
if (json.is<JsonObject>()) {
|
||||
uint8_t unique_id = json["id"]; // unique ID
|
||||
const char * cmd = json["c"]; // the command
|
||||
@@ -236,9 +221,7 @@ void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVar
|
||||
|
||||
// quit on bad values
|
||||
if (strlen(cmd) == 0 || data.isNull()) {
|
||||
AsyncWebServerResponse * response = request->beginResponse(400); // bad request
|
||||
request->send(response);
|
||||
return;
|
||||
return request->reply(400); // Invalid/bad request
|
||||
}
|
||||
|
||||
// using the unique ID from the web find the real device type
|
||||
@@ -249,8 +232,8 @@ void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVar
|
||||
cmd = Command::parse_command_string(cmd, id); // extract hc or wwc
|
||||
|
||||
// create JSON for output
|
||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_SMALL);
|
||||
JsonObject output = response->getRoot();
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false, EMSESP_JSON_SIZE_SMALL);
|
||||
JsonObject output = response.getRoot();
|
||||
|
||||
// the data could be in any format, but we need string
|
||||
// authenticated is always true
|
||||
@@ -277,22 +260,22 @@ void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVar
|
||||
#endif
|
||||
}
|
||||
|
||||
response->setCode((return_code == CommandRet::OK) ? 200 : 400); // bad request
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
response.setCode((return_code == CommandRet::OK) ? 200 : 400); // bad request
|
||||
return response.send();
|
||||
}
|
||||
}
|
||||
|
||||
// special check for custom entities (which have a unique id of 99)
|
||||
if (unique_id == 99) {
|
||||
// parse the command as it could have a hc or wwc prefixed, e.g. hc2/seltemp
|
||||
int8_t id = -1;
|
||||
cmd = Command::parse_command_string(cmd, id);
|
||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_SMALL);
|
||||
JsonObject output = response->getRoot();
|
||||
uint8_t return_code = CommandRet::NOT_FOUND;
|
||||
uint8_t device_type = EMSdevice::DeviceType::CUSTOM;
|
||||
int8_t id = -1;
|
||||
cmd = Command::parse_command_string(cmd, id);
|
||||
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false, EMSESP_JSON_SIZE_SMALL);
|
||||
JsonObject output = response.getRoot();
|
||||
|
||||
uint8_t return_code = CommandRet::NOT_FOUND;
|
||||
uint8_t device_type = EMSdevice::DeviceType::CUSTOM;
|
||||
if (data.is<const char *>()) {
|
||||
return_code = Command::call(device_type, cmd, data.as<const char *>(), true, id, output);
|
||||
} else if (data.is<int>()) {
|
||||
@@ -310,21 +293,18 @@ void WebDataService::write_device_value(AsyncWebServerRequest * request, JsonVar
|
||||
#endif
|
||||
}
|
||||
|
||||
response->setCode((return_code == CommandRet::OK) ? 200 : 400); // bad request
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
response.setCode((return_code == CommandRet::OK) ? 200 : 400); // bad request
|
||||
return response.send();
|
||||
}
|
||||
}
|
||||
|
||||
// if we reach here, fail
|
||||
AsyncWebServerResponse * response = request->beginResponse(400); // bad request
|
||||
request->send(response);
|
||||
return request->reply(400); // Invalid/Bad Request
|
||||
}
|
||||
|
||||
// takes a temperaturesensor name and optional offset from the WebUI and update the customization settings
|
||||
// via the temperaturesensor service
|
||||
void WebDataService::write_temperature_sensor(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
esp_err_t WebDataService::write_temperature_sensor(PsychicRequest * request, JsonVariant & json) {
|
||||
bool ok = false;
|
||||
if (json.is<JsonObject>()) {
|
||||
JsonObject sensor = json;
|
||||
@@ -342,12 +322,11 @@ void WebDataService::write_temperature_sensor(AsyncWebServerRequest * request, J
|
||||
ok = EMSESP::temperaturesensor_.update(id, name, offset10);
|
||||
}
|
||||
|
||||
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 400); // bad request
|
||||
request->send(response);
|
||||
return request->reply(ok ? 200 : 400); // bad request); // Invalid/Bad Request
|
||||
}
|
||||
|
||||
// update the analog record, or create a new one
|
||||
void WebDataService::write_analog_sensor(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
esp_err_t WebDataService::write_analog_sensor(PsychicRequest * request, JsonVariant & json) {
|
||||
bool ok = false;
|
||||
if (json.is<JsonObject>()) {
|
||||
JsonObject analog = json;
|
||||
@@ -362,8 +341,7 @@ void WebDataService::write_analog_sensor(AsyncWebServerRequest * request, JsonVa
|
||||
ok = EMSESP::analogsensor_.update(gpio, name, offset, factor, uom, type, deleted);
|
||||
}
|
||||
|
||||
AsyncWebServerResponse * response = request->beginResponse(ok ? 200 : 400); // bad request
|
||||
request->send(response);
|
||||
return request->reply(ok ? 200 : 400); // bad request); // Invalid/Bad Request
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -34,25 +34,27 @@ namespace emsesp {
|
||||
|
||||
class WebDataService {
|
||||
public:
|
||||
WebDataService(AsyncWebServer * server, SecurityManager * securityManager);
|
||||
WebDataService(PsychicHttpServer * server, SecurityManager * securityManager);
|
||||
void registerURI();
|
||||
|
||||
// make all functions public so we can test in the debug and standalone mode
|
||||
#ifndef EMSESP_STANDALONE
|
||||
private:
|
||||
#endif
|
||||
|
||||
SecurityManager * _securityManager;
|
||||
PsychicHttpServer * _server;
|
||||
|
||||
// GET
|
||||
void core_data(AsyncWebServerRequest * request);
|
||||
void sensor_data(AsyncWebServerRequest * request);
|
||||
void device_data(AsyncWebServerRequest * request);
|
||||
esp_err_t core_data(PsychicRequest * request);
|
||||
esp_err_t sensor_data(PsychicRequest * request);
|
||||
esp_err_t device_data(PsychicRequest * request);
|
||||
|
||||
// POST
|
||||
void write_device_value(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void write_temperature_sensor(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void write_analog_sensor(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
void scan_devices(AsyncWebServerRequest * request); // command
|
||||
|
||||
AsyncCallbackJsonWebHandler _write_value_handler, _write_temperature_handler, _write_analog_handler;
|
||||
esp_err_t write_device_value(PsychicRequest * request, JsonVariant & json);
|
||||
esp_err_t write_temperature_sensor(PsychicRequest * request, JsonVariant & json);
|
||||
esp_err_t write_analog_sensor(PsychicRequest * request, JsonVariant & json);
|
||||
esp_err_t scan_devices(PsychicRequest * request); // command
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -22,18 +22,66 @@ using namespace std::placeholders;
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
WebLogService::WebLogService(AsyncWebServer * server, SecurityManager * securityManager)
|
||||
: events_(EVENT_SOURCE_LOG_PATH)
|
||||
, setValues_(LOG_SETTINGS_PATH, std::bind(&WebLogService::setValues, this, _1, _2), 256) {
|
||||
events_.setFilter(securityManager->filterRequest(AuthenticationPredicates::IS_ADMIN));
|
||||
WebLogService::WebLogService(PsychicHttpServer * server, SecurityManager * securityManager)
|
||||
// TODO fix event source
|
||||
: // : _events(EVENT_SOURCE_LOG_PATH)
|
||||
_server(server)
|
||||
, _securityManager(securityManager) {
|
||||
}
|
||||
|
||||
server->on(LOG_SETTINGS_PATH, HTTP_GET, std::bind(&WebLogService::getValues, this, _1)); // get settings
|
||||
|
||||
void WebLogService::registerURI() {
|
||||
// TODO fix event source
|
||||
/*
|
||||
_events_.onOpen([](PsychicEventSourceClient * client) {
|
||||
Serial.printf("[eventsource] connection #%u connected from %s\n", client->socket(), client->remoteIP().toString());
|
||||
client->send("Hello user!", NULL, millis(), 1000);
|
||||
});
|
||||
_events_.onClose([](PsychicEventSourceClient * client) {
|
||||
Serial.printf("[eventsource] connection #%u closed from %s\n", client->socket(), client->remoteIP().toString());
|
||||
});
|
||||
_server->on(EVENT_SOURCE_LOG_PATH, &events_);
|
||||
*/
|
||||
|
||||
// post
|
||||
_server->on(LOG_SETTINGS_PATH, HTTP_POST, [this](PsychicRequest * request, JsonVariant & json) {
|
||||
auto && body = json.as<JsonObject>();
|
||||
|
||||
uuid::log::Level level = body["level"];
|
||||
log_level(level);
|
||||
|
||||
uint8_t max_messages = body["max_messages"];
|
||||
maximum_log_messages(max_messages);
|
||||
|
||||
bool comp = body["compact"];
|
||||
compact(comp);
|
||||
|
||||
return request->reply(200); // OK
|
||||
});
|
||||
|
||||
_events.setFilter(_securityManager->filterRequest(AuthenticationPredicates::IS_ADMIN));
|
||||
|
||||
// get settings
|
||||
_server->on(LOG_SETTINGS_PATH, HTTP_GET, [this](PsychicRequest * request) {
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false, EMSESP_JSON_SIZE_SMALL);
|
||||
JsonObject root = response.getRoot();
|
||||
|
||||
root["level"] = log_level();
|
||||
root["max_messages"] = maximum_log_messages();
|
||||
root["compact"] = compact();
|
||||
return response.send();
|
||||
});
|
||||
|
||||
// for bring back the whole log - is a command, hence a POST
|
||||
server->on(FETCH_LOG_PATH, HTTP_POST, std::bind(&WebLogService::fetchLog, this, _1));
|
||||
// send the complete log buffer to the API, not filtering on log level
|
||||
// done by resetting the pointer
|
||||
_server->on(FETCH_LOG_PATH, HTTP_POST, [this](PsychicRequest * request) {
|
||||
log_message_id_tail_ = 0;
|
||||
return request->reply(200);
|
||||
});
|
||||
|
||||
server->addHandler(&setValues_);
|
||||
server->addHandler(&events_);
|
||||
// TODO remove?
|
||||
// server->addHandler(&events_);
|
||||
}
|
||||
|
||||
// start the log service with INFO level
|
||||
@@ -143,7 +191,7 @@ void WebLogService::operator<<(std::shared_ptr<uuid::log::Message> message) {
|
||||
}
|
||||
|
||||
void WebLogService::loop() {
|
||||
if (!events_.count() || log_messages_.empty()) {
|
||||
if (!_events.count() || log_messages_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -200,47 +248,43 @@ void WebLogService::transmit(const QueuedLogMessage & message) {
|
||||
char * buffer = new char[len + 1];
|
||||
if (buffer) {
|
||||
serializeJson(jsonDocument, buffer, len + 1);
|
||||
events_.send(buffer, "message", message.id_);
|
||||
_events.send(buffer, "message", message.id_);
|
||||
}
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
// send the complete log buffer to the API, not filtering on log level
|
||||
// done by resetting the pointer
|
||||
void WebLogService::fetchLog(AsyncWebServerRequest * request) {
|
||||
log_message_id_tail_ = 0;
|
||||
request->send(200);
|
||||
}
|
||||
|
||||
// sets the values like level after a POST
|
||||
void WebLogService::setValues(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||
if (!json.is<JsonObject>()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto && body = json.as<JsonObject>();
|
||||
|
||||
uuid::log::Level level = body["level"];
|
||||
log_level(level);
|
||||
|
||||
uint8_t max_messages = body["max_messages"];
|
||||
maximum_log_messages(max_messages);
|
||||
|
||||
bool comp = body["compact"];
|
||||
compact(comp);
|
||||
|
||||
request->send(200); // OK
|
||||
}
|
||||
// esp_err_t WebLogService::fetchLog(PsychicRequest * request) {
|
||||
// log_message_id_tail_ = 0;
|
||||
// request->send(200);
|
||||
// }
|
||||
|
||||
// return the current value settings after a GET
|
||||
void WebLogService::getValues(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_SMALL);
|
||||
JsonObject root = response->getRoot();
|
||||
root["level"] = log_level();
|
||||
root["max_messages"] = maximum_log_messages();
|
||||
root["compact"] = compact();
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
||||
// esp_err_t WebLogService::getValues(PsychicRequest * request) {
|
||||
// auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_SMALL);
|
||||
// JsonObject root = response->getRoot();
|
||||
// root["level"] = log_level();
|
||||
// root["max_messages"] = maximum_log_messages();
|
||||
// root["compact"] = compact();
|
||||
// response->setLength();
|
||||
// request->send(response);
|
||||
// }
|
||||
|
||||
// sets the values like level after a POST
|
||||
// esp_err_t WebLogService::setValues(PsychicRequest * request, JsonVariant & json) {
|
||||
// auto && body = json.as<JsonObject>();
|
||||
|
||||
// uuid::log::Level level = body["level"];
|
||||
// log_level(level);
|
||||
|
||||
// uint8_t max_messages = body["max_messages"];
|
||||
// maximum_log_messages(max_messages);
|
||||
|
||||
// bool comp = body["compact"];
|
||||
// compact(comp);
|
||||
|
||||
// return request->reply(200); // OK
|
||||
// }
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2023 Paul Derbyshire
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -30,10 +30,13 @@ class WebLogService : public uuid::log::Handler {
|
||||
static constexpr size_t MAX_LOG_MESSAGES = 50;
|
||||
static constexpr size_t REFRESH_SYNC = 50;
|
||||
|
||||
WebLogService(AsyncWebServer * server, SecurityManager * securityManager);
|
||||
WebLogService(PsychicHttpServer * server, SecurityManager * securityManager);
|
||||
|
||||
void begin();
|
||||
void start();
|
||||
void loop();
|
||||
void registerURI();
|
||||
|
||||
void begin();
|
||||
void start();
|
||||
uuid::log::Level log_level() const;
|
||||
void log_level(uuid::log::Level level);
|
||||
size_t maximum_log_messages() const;
|
||||
@@ -41,12 +44,13 @@ class WebLogService : public uuid::log::Handler {
|
||||
void maximum_log_messages(size_t count);
|
||||
bool compact() const;
|
||||
void compact(bool compact);
|
||||
void loop();
|
||||
|
||||
virtual void operator<<(std::shared_ptr<uuid::log::Message> message);
|
||||
|
||||
private:
|
||||
AsyncEventSource events_;
|
||||
PsychicEventSource _events;
|
||||
SecurityManager * _securityManager;
|
||||
PsychicHttpServer * _server;
|
||||
|
||||
class QueuedLogMessage {
|
||||
public:
|
||||
@@ -58,15 +62,15 @@ class WebLogService : public uuid::log::Handler {
|
||||
const std::shared_ptr<const uuid::log::Message> content_; // Log message content
|
||||
};
|
||||
|
||||
void transmit(const QueuedLogMessage & message);
|
||||
void fetchLog(AsyncWebServerRequest * request);
|
||||
void getValues(AsyncWebServerRequest * request);
|
||||
|
||||
void transmit(const QueuedLogMessage & message);
|
||||
char * messagetime(char * out, const uint64_t t, const size_t bufsize);
|
||||
|
||||
void setValues(AsyncWebServerRequest * request, JsonVariant & json);
|
||||
// TODO remove this?
|
||||
// PsychicJsonHandler setValues_; // for POSTs
|
||||
|
||||
AsyncCallbackJsonWebHandler setValues_; // for POSTs
|
||||
esp_err_t fetchLog(PsychicRequest * request);
|
||||
esp_err_t getValues(PsychicRequest * request);
|
||||
esp_err_t setValues(PsychicRequest * request, JsonVariant & json);
|
||||
|
||||
uint64_t last_transmit_ = 0; // Last transmit time
|
||||
size_t maximum_log_messages_ = MAX_LOG_MESSAGES; // Maximum number of log messages to buffer before they are output
|
||||
|
||||
@@ -22,11 +22,15 @@ namespace emsesp {
|
||||
|
||||
using namespace std::placeholders; // for `_1` etc
|
||||
|
||||
WebSchedulerService::WebSchedulerService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||
WebSchedulerService::WebSchedulerService(PsychicHttpServer * server, FS * fs, SecurityManager * securityManager)
|
||||
: _httpEndpoint(WebScheduler::read, WebScheduler::update, this, server, EMSESP_SCHEDULER_SERVICE_PATH, securityManager, AuthenticationPredicates::IS_AUTHENTICATED)
|
||||
, _fsPersistence(WebScheduler::read, WebScheduler::update, this, fs, EMSESP_SCHEDULER_FILE) {
|
||||
}
|
||||
|
||||
void WebSchedulerService::registerURI() {
|
||||
_httpEndpoint.registerURI();
|
||||
}
|
||||
|
||||
// load the settings when the service starts
|
||||
void WebSchedulerService::begin() {
|
||||
_fsPersistence.readFromFS();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2023 Paul Derbyshire
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -49,10 +49,12 @@ class WebScheduler {
|
||||
|
||||
class WebSchedulerService : public StatefulService<WebScheduler> {
|
||||
public:
|
||||
WebSchedulerService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
|
||||
WebSchedulerService(PsychicHttpServer * server, FS * fs, SecurityManager * securityManager);
|
||||
|
||||
void begin();
|
||||
void loop();
|
||||
void registerURI();
|
||||
|
||||
void publish_single(const char * name, const bool state);
|
||||
void publish(const bool force = false);
|
||||
bool has_commands();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2023 Paul Derbyshire
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -24,17 +24,21 @@ uint8_t WebSettings::flags_ = 0;
|
||||
|
||||
using namespace std::placeholders; // for `_1` etc
|
||||
|
||||
WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||
: _httpEndpoint(WebSettings::read, WebSettings::update, this, server, EMSESP_SETTINGS_SERVICE_PATH, securityManager)
|
||||
WebSettingsService::WebSettingsService(PsychicHttpServer * server, FS * fs, SecurityManager * securityManager)
|
||||
: _server(server)
|
||||
, _securityManager(securityManager)
|
||||
, _httpEndpoint(WebSettings::read, WebSettings::update, this, server, EMSESP_SETTINGS_SERVICE_PATH, securityManager)
|
||||
, _fsPersistence(WebSettings::read, WebSettings::update, this, fs, EMSESP_SETTINGS_FILE) {
|
||||
// GET
|
||||
server->on(EMSESP_BOARD_PROFILE_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebSettingsService::board_profile, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
|
||||
addUpdateHandler([&](const String & originId) { onUpdate(); }, false);
|
||||
}
|
||||
|
||||
void WebSettingsService::registerURI() {
|
||||
_httpEndpoint.registerURI();
|
||||
_server->on(EMSESP_BOARD_PROFILE_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
_securityManager->wrapRequest(std::bind(&WebSettingsService::board_profile, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
}
|
||||
|
||||
void WebSettings::read(WebSettings & settings, JsonObject & root) {
|
||||
root["version"] = settings.version;
|
||||
root["locale"] = settings.locale;
|
||||
@@ -91,6 +95,7 @@ StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings)
|
||||
if ((String)EMSESP_DEFAULT_BOARD_PROFILE != "default" && EMSESP::nvs_.getString("boot") == "") {
|
||||
EMSESP::nvs_.putString("boot", (const char *)EMSESP_DEFAULT_BOARD_PROFILE);
|
||||
}
|
||||
|
||||
/*
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
settings.board_profile = root["board_profile"] | "C3MINI";
|
||||
@@ -103,19 +108,28 @@ StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings)
|
||||
settings.board_profile = root["board_profile"] | EMSESP_DEFAULT_BOARD_PROFILE;
|
||||
#endif
|
||||
*/
|
||||
|
||||
if (!System::load_board_profile(data, settings.board_profile.c_str())) {
|
||||
// unknown, check for NVS or scan for ethernet, use default E32/E32V2/S32
|
||||
settings.board_profile = EMSESP::nvs_.getString("boot");
|
||||
if (!System::load_board_profile(data, settings.board_profile.c_str())) {
|
||||
#if CONFIG_IDF_TARGET_ESP32 && !defined(EMSESP_STANDALONE)
|
||||
if (settings.board_profile == "") { // empty: new test
|
||||
if (ETH.begin((eth_phy_type_t)1, 16, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_IN)) {
|
||||
#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)) {
|
||||
#endif
|
||||
EMSESP::nvs_.putString("boot", "E32");
|
||||
} else {
|
||||
EMSESP::nvs_.putString("boot", "Test");
|
||||
}
|
||||
} else if (settings.board_profile == "Test") {
|
||||
if (ETH.begin((eth_phy_type_t)0, 15, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_OUT)) {
|
||||
#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)) {
|
||||
#endif
|
||||
EMSESP::nvs_.putString("boot", "E32V2");
|
||||
} else {
|
||||
EMSESP::nvs_.putString("boot", "S32");
|
||||
@@ -352,12 +366,12 @@ void WebSettingsService::save() {
|
||||
}
|
||||
|
||||
// build the json profile to send back
|
||||
void WebSettingsService::board_profile(AsyncWebServerRequest * request) {
|
||||
esp_err_t WebSettingsService::board_profile(PsychicRequest * request) {
|
||||
if (request->hasParam("boardProfile")) {
|
||||
std::string board_profile = request->getParam("boardProfile")->value().c_str();
|
||||
|
||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_MEDIUM);
|
||||
JsonObject root = response->getRoot();
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false, EMSESP_JSON_SIZE_MEDIUM);
|
||||
JsonObject root = response.getRoot();
|
||||
|
||||
std::vector<int8_t> data; // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
|
||||
(void)System::load_board_profile(data, board_profile);
|
||||
@@ -372,13 +386,10 @@ void WebSettingsService::board_profile(AsyncWebServerRequest * request) {
|
||||
root["eth_phy_addr"] = data[7];
|
||||
root["eth_clock_mode"] = data[8];
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
return response.send();
|
||||
}
|
||||
|
||||
AsyncWebServerResponse * response = request->beginResponse(200);
|
||||
request->send(response);
|
||||
return request->reply(200);
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -117,16 +117,20 @@ class WebSettings {
|
||||
|
||||
class WebSettingsService : public StatefulService<WebSettings> {
|
||||
public:
|
||||
WebSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
|
||||
WebSettingsService(PsychicHttpServer * server, FS * fs, SecurityManager * securityManager);
|
||||
|
||||
void begin();
|
||||
void save();
|
||||
void registerURI();
|
||||
|
||||
private:
|
||||
SecurityManager * _securityManager;
|
||||
PsychicHttpServer * _server;
|
||||
|
||||
HttpEndpoint<WebSettings> _httpEndpoint;
|
||||
FSPersistence<WebSettings> _fsPersistence;
|
||||
|
||||
void board_profile(AsyncWebServerRequest * request);
|
||||
esp_err_t board_profile(PsychicRequest * request);
|
||||
|
||||
void onUpdate();
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2023 Paul Derbyshire
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -22,14 +22,18 @@ using namespace std::placeholders; // for `_1` etc
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
WebStatusService::WebStatusService(AsyncWebServer * server, SecurityManager * securityManager) {
|
||||
// rest endpoint for web page
|
||||
server->on(EMSESP_STATUS_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebStatusService::webStatusService, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
WebStatusService::WebStatusService(PsychicHttpServer * server, SecurityManager * securityManager)
|
||||
: _server(server)
|
||||
, _securityManager(securityManager) {
|
||||
WiFi.onEvent(std::bind(&WebStatusService::WiFiEvent, this, _1, _2));
|
||||
}
|
||||
|
||||
void WebStatusService::registerURI() {
|
||||
_server->on(EMSESP_STATUS_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
_securityManager->wrapRequest(std::bind(&WebStatusService::webStatusService, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
}
|
||||
|
||||
// handles both WiFI and Ethernet
|
||||
void WebStatusService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
@@ -114,9 +118,9 @@ void WebStatusService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void WebStatusService::webStatusService(AsyncWebServerRequest * request) {
|
||||
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_LARGE);
|
||||
JsonObject root = response->getRoot();
|
||||
esp_err_t WebStatusService::webStatusService(PsychicRequest * request) {
|
||||
PsychicJsonResponse response = PsychicJsonResponse(request, false, EMSESP_JSON_SIZE_LARGE);
|
||||
JsonObject root = response.getRoot();
|
||||
|
||||
root["status"] = EMSESP::bus_status(); // 0, 1 or 2
|
||||
root["tx_mode"] = EMSESP::txservice_.tx_mode();
|
||||
@@ -189,8 +193,7 @@ void WebStatusService::webStatusService(AsyncWebServerRequest * request) {
|
||||
}
|
||||
#endif
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return response.send();
|
||||
}
|
||||
|
||||
// start the multicast UDP service so EMS-ESP is discoverable via .local
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* EMS-ESP - https://github.com/emsesp/EMS-ESP
|
||||
* Copyright 2020-2023 Paul Derbyshire
|
||||
*
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -27,10 +27,14 @@ namespace emsesp {
|
||||
|
||||
class WebStatusService {
|
||||
public:
|
||||
WebStatusService(AsyncWebServer * server, SecurityManager * securityManager);
|
||||
WebStatusService(PsychicHttpServer * server, SecurityManager * securityManager);
|
||||
void registerURI();
|
||||
|
||||
private:
|
||||
void webStatusService(AsyncWebServerRequest * request);
|
||||
SecurityManager * _securityManager;
|
||||
PsychicHttpServer * _server;
|
||||
|
||||
esp_err_t webStatusService(PsychicRequest * request);
|
||||
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||
void mDNS_start() const;
|
||||
const char * disconnectReason(uint8_t code);
|
||||
|
||||
Reference in New Issue
Block a user