mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-09 01:09:51 +03:00
Merge branch 'dev' of https://github.com/emsesp/EMS-ESP32 into dev2
This commit is contained in:
@@ -18,8 +18,6 @@
|
||||
|
||||
#include "emsesp.h"
|
||||
|
||||
using namespace std::placeholders; // for `_1` etc
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
uint32_t WebAPIService::api_count_ = 0;
|
||||
@@ -27,17 +25,26 @@ uint16_t WebAPIService::api_fails_ = 0;
|
||||
|
||||
WebAPIService::WebAPIService(AsyncWebServer * server, SecurityManager * securityManager)
|
||||
: _securityManager(securityManager)
|
||||
, _apiHandler("/api", std::bind(&WebAPIService::webAPIService_post, this, _1, _2)) { // for POSTS, must use 'Content-Type: application/json' in header
|
||||
server->on("/api", HTTP_GET, std::bind(&WebAPIService::webAPIService_get, this, _1)); // for GETS
|
||||
, _apiHandler(EMSESP_API_SERVICE_PATH, [this](AsyncWebServerRequest * request, JsonVariant json) { webAPIService_post(request, json); }) { // for POSTs
|
||||
server->on(EMSESP_API_SERVICE_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { webAPIService_get(request); }); // for GETs
|
||||
server->addHandler(&_apiHandler);
|
||||
|
||||
// for settings
|
||||
server->on(GET_SETTINGS_PATH, HTTP_GET, securityManager->wrapRequest(std::bind(&WebAPIService::getSettings, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
server->on(GET_SETTINGS_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { getSettings(request); }, 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));
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { getCustomizations(request); }, AuthenticationPredicates::IS_ADMIN));
|
||||
|
||||
server->on(GET_SCHEDULE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { getSchedule(request); }, AuthenticationPredicates::IS_ADMIN));
|
||||
|
||||
server->on(GET_ENTITIES_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { getEntities(request); }, AuthenticationPredicates::IS_ADMIN));
|
||||
}
|
||||
|
||||
// HTTP GET
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
using namespace std::placeholders; // for `_1` etc
|
||||
|
||||
WebCustomEntityService::WebCustomEntityService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||
: _httpEndpoint(WebCustomEntity::read,
|
||||
WebCustomEntity::update,
|
||||
@@ -628,52 +626,50 @@ bool WebCustomEntityService::get_value(std::shared_ptr<const Telegram> telegram)
|
||||
// hard coded tests
|
||||
#ifdef EMSESP_TEST
|
||||
void WebCustomEntityService::test() {
|
||||
update(
|
||||
[&](WebCustomEntity & webCustomEntity) {
|
||||
webCustomEntity.customEntityItems.clear();
|
||||
// test 1
|
||||
auto entityItem = CustomEntityItem();
|
||||
entityItem.ram = 0;
|
||||
entityItem.device_id = 8;
|
||||
entityItem.type_id = 24;
|
||||
entityItem.offset = 0;
|
||||
entityItem.factor = 1;
|
||||
entityItem.name = "test_custom";
|
||||
entityItem.uom = 1;
|
||||
entityItem.value_type = 1;
|
||||
entityItem.writeable = true;
|
||||
entityItem.data = "70";
|
||||
webCustomEntity.customEntityItems.push_back(entityItem);
|
||||
update([&](WebCustomEntity & webCustomEntity) {
|
||||
webCustomEntity.customEntityItems.clear();
|
||||
// test 1
|
||||
auto entityItem = CustomEntityItem();
|
||||
entityItem.ram = 0;
|
||||
entityItem.device_id = 8;
|
||||
entityItem.type_id = 24;
|
||||
entityItem.offset = 0;
|
||||
entityItem.factor = 1;
|
||||
entityItem.name = "test_custom";
|
||||
entityItem.uom = 1;
|
||||
entityItem.value_type = 1;
|
||||
entityItem.writeable = true;
|
||||
entityItem.data = "70";
|
||||
webCustomEntity.customEntityItems.push_back(entityItem);
|
||||
|
||||
// test 2
|
||||
entityItem.ram = 0;
|
||||
entityItem.device_id = 24;
|
||||
entityItem.type_id = 677;
|
||||
entityItem.offset = 3;
|
||||
entityItem.factor = 1;
|
||||
entityItem.name = "test_read_only";
|
||||
entityItem.uom = 0;
|
||||
entityItem.value_type = 2;
|
||||
entityItem.writeable = false;
|
||||
entityItem.data = "48";
|
||||
webCustomEntity.customEntityItems.push_back(entityItem);
|
||||
// test 2
|
||||
entityItem.ram = 0;
|
||||
entityItem.device_id = 24;
|
||||
entityItem.type_id = 677;
|
||||
entityItem.offset = 3;
|
||||
entityItem.factor = 1;
|
||||
entityItem.name = "test_read_only";
|
||||
entityItem.uom = 0;
|
||||
entityItem.value_type = 2;
|
||||
entityItem.writeable = false;
|
||||
entityItem.data = "48";
|
||||
webCustomEntity.customEntityItems.push_back(entityItem);
|
||||
|
||||
// test 2
|
||||
entityItem.ram = 1;
|
||||
entityItem.device_id = 0;
|
||||
entityItem.type_id = 0;
|
||||
entityItem.offset = 0;
|
||||
entityItem.factor = 1;
|
||||
entityItem.name = "test_ram";
|
||||
entityItem.uom = 0;
|
||||
entityItem.value_type = 8;
|
||||
entityItem.writeable = true;
|
||||
entityItem.data = "14";
|
||||
webCustomEntity.customEntityItems.push_back(entityItem);
|
||||
// test 2
|
||||
entityItem.ram = 1;
|
||||
entityItem.device_id = 0;
|
||||
entityItem.type_id = 0;
|
||||
entityItem.offset = 0;
|
||||
entityItem.factor = 1;
|
||||
entityItem.name = "test_ram";
|
||||
entityItem.uom = 0;
|
||||
entityItem.value_type = 8;
|
||||
entityItem.writeable = true;
|
||||
entityItem.data = "14";
|
||||
webCustomEntity.customEntityItems.push_back(entityItem);
|
||||
|
||||
return StateUpdateResult::CHANGED; // persist the changes
|
||||
},
|
||||
"local");
|
||||
return StateUpdateResult::CHANGED; // persist the changes
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -20,27 +20,24 @@
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
using namespace std::placeholders; // for `_1` etc
|
||||
|
||||
bool WebCustomization::_start = true;
|
||||
|
||||
WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||
: _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),
|
||||
securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { customization_entities(request, json); },
|
||||
AuthenticationPredicates::IS_AUTHENTICATED)) {
|
||||
server->on(DEVICE_ENTITIES_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebCustomizationService::device_entities, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { device_entities(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
server->on(DEVICES_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebCustomizationService::devices, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { devices(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
server->on(RESET_CUSTOMIZATION_SERVICE_PATH,
|
||||
HTTP_POST,
|
||||
securityManager->wrapRequest(std::bind(&WebCustomizationService::reset_customization, this, _1), AuthenticationPredicates::IS_ADMIN));
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { reset_customization(request); }, AuthenticationPredicates::IS_ADMIN));
|
||||
|
||||
_masked_entities_handler.setMethod(HTTP_POST);
|
||||
_masked_entities_handler.setMaxContentLength(2048);
|
||||
@@ -276,30 +273,28 @@ void WebCustomizationService::customization_entities(AsyncWebServerRequest * req
|
||||
emsdevice->getCustomizationEntities(entity_ids);
|
||||
|
||||
// Save the list to the customization file
|
||||
update(
|
||||
[&](WebCustomization & settings) {
|
||||
// see if we already have a mask list for this device, if so remove it
|
||||
for (auto it = settings.entityCustomizations.begin(); it != settings.entityCustomizations.end();) {
|
||||
if ((*it).product_id == product_id && (*it).device_id == device_id) {
|
||||
it = settings.entityCustomizations.erase(it);
|
||||
break;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
update([&](WebCustomization & settings) {
|
||||
// see if we already have a mask list for this device, if so remove it
|
||||
for (auto it = settings.entityCustomizations.begin(); it != settings.entityCustomizations.end();) {
|
||||
if ((*it).product_id == product_id && (*it).device_id == device_id) {
|
||||
it = settings.entityCustomizations.erase(it);
|
||||
break;
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
// create a new entry for this device if there are values
|
||||
EntityCustomization new_entry;
|
||||
new_entry.product_id = product_id;
|
||||
new_entry.device_id = device_id;
|
||||
// create a new entry for this device if there are values
|
||||
EntityCustomization new_entry;
|
||||
new_entry.product_id = product_id;
|
||||
new_entry.device_id = device_id;
|
||||
|
||||
new_entry.entity_ids = entity_ids;
|
||||
new_entry.entity_ids = entity_ids;
|
||||
|
||||
// add the record and save
|
||||
settings.entityCustomizations.push_back(new_entry);
|
||||
return StateUpdateResult::CHANGED;
|
||||
},
|
||||
"local");
|
||||
// add the record and save
|
||||
settings.entityCustomizations.push_back(new_entry);
|
||||
return StateUpdateResult::CHANGED;
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -320,54 +315,52 @@ void WebCustomizationService::begin() {
|
||||
// hard coded tests
|
||||
#ifdef EMSESP_TEST
|
||||
void WebCustomizationService::test() {
|
||||
update(
|
||||
[&](WebCustomization & webCustomization) {
|
||||
// Temperature sensors
|
||||
webCustomization.sensorCustomizations.clear();
|
||||
auto sensor = SensorCustomization();
|
||||
sensor.id = "01-0203-0405-0607";
|
||||
sensor.name = "test_sensor1";
|
||||
sensor.offset = 0;
|
||||
webCustomization.sensorCustomizations.push_back(sensor);
|
||||
update([&](WebCustomization & webCustomization) {
|
||||
// Temperature sensors
|
||||
webCustomization.sensorCustomizations.clear();
|
||||
auto sensor = SensorCustomization();
|
||||
sensor.id = "01-0203-0405-0607";
|
||||
sensor.name = "test_sensor1";
|
||||
sensor.offset = 0;
|
||||
webCustomization.sensorCustomizations.push_back(sensor);
|
||||
|
||||
sensor = SensorCustomization();
|
||||
sensor.id = "0B-0C0D-0E0F-1011";
|
||||
sensor.name = "test_sensor2";
|
||||
sensor.offset = 4;
|
||||
webCustomization.sensorCustomizations.push_back(sensor);
|
||||
sensor = SensorCustomization();
|
||||
sensor.id = "0B-0C0D-0E0F-1011";
|
||||
sensor.name = "test_sensor2";
|
||||
sensor.offset = 4;
|
||||
webCustomization.sensorCustomizations.push_back(sensor);
|
||||
|
||||
// Analog sensors
|
||||
// This actually adds the sensors as we use customizations to store them
|
||||
webCustomization.analogCustomizations.clear();
|
||||
auto analog = AnalogCustomization();
|
||||
analog.gpio = 36;
|
||||
analog.name = "test_analog1";
|
||||
analog.offset = 0;
|
||||
analog.factor = 0.1;
|
||||
analog.uom = 17;
|
||||
analog.type = 3;
|
||||
webCustomization.analogCustomizations.push_back(analog);
|
||||
// Analog sensors
|
||||
// This actually adds the sensors as we use customizations to store them
|
||||
webCustomization.analogCustomizations.clear();
|
||||
auto analog = AnalogCustomization();
|
||||
analog.gpio = 36;
|
||||
analog.name = "test_analog1";
|
||||
analog.offset = 0;
|
||||
analog.factor = 0.1;
|
||||
analog.uom = 17;
|
||||
analog.type = 3;
|
||||
webCustomization.analogCustomizations.push_back(analog);
|
||||
|
||||
analog = AnalogCustomization();
|
||||
analog.gpio = 37;
|
||||
analog.name = "test_analog2";
|
||||
analog.offset = 0;
|
||||
analog.factor = 1;
|
||||
analog.uom = 0;
|
||||
analog.type = 1;
|
||||
webCustomization.analogCustomizations.push_back(analog);
|
||||
analog = AnalogCustomization();
|
||||
analog.gpio = 37;
|
||||
analog.name = "test_analog2";
|
||||
analog.offset = 0;
|
||||
analog.factor = 1;
|
||||
analog.uom = 0;
|
||||
analog.type = 1;
|
||||
webCustomization.analogCustomizations.push_back(analog);
|
||||
|
||||
// EMS entities
|
||||
webCustomization.entityCustomizations.clear();
|
||||
auto emsEntity = EntityCustomization();
|
||||
emsEntity.product_id = 123;
|
||||
emsEntity.device_id = 8;
|
||||
emsEntity.entity_ids.push_back("08heatingactive|is my heating on?");
|
||||
webCustomization.entityCustomizations.push_back(emsEntity);
|
||||
// EMS entities
|
||||
webCustomization.entityCustomizations.clear();
|
||||
auto emsEntity = EntityCustomization();
|
||||
emsEntity.product_id = 123;
|
||||
emsEntity.device_id = 8;
|
||||
emsEntity.entity_ids.push_back("08heatingactive|is my heating on?");
|
||||
webCustomization.entityCustomizations.push_back(emsEntity);
|
||||
|
||||
return StateUpdateResult::CHANGED; // persist the changes
|
||||
},
|
||||
"local");
|
||||
return StateUpdateResult::CHANGED; // persist the changes
|
||||
});
|
||||
|
||||
EMSESP::analogsensor_.reload(); // this is needed to active the analog sensors
|
||||
}
|
||||
|
||||
@@ -20,33 +20,36 @@
|
||||
|
||||
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))
|
||||
securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { write_device_value(request, json); },
|
||||
AuthenticationPredicates::IS_ADMIN))
|
||||
, _write_temperature_handler(WRITE_TEMPERATURE_SENSOR_SERVICE_PATH,
|
||||
securityManager->wrapCallback(std::bind(&WebDataService::write_temperature_sensor, this, _1, _2),
|
||||
securityManager->wrapCallback([this](AsyncWebServerRequest * request,
|
||||
JsonVariant json) { write_temperature_sensor(request, json); },
|
||||
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)) {
|
||||
securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { write_analog_sensor(request, json); },
|
||||
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));
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { device_data(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
|
||||
server->on(CORE_DATA_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebDataService::core_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { core_data(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
|
||||
server->on(SENSOR_DATA_SERVICE_PATH,
|
||||
HTTP_GET,
|
||||
securityManager->wrapRequest(std::bind(&WebDataService::sensor_data, this, _1), AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { sensor_data(request); }, 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));
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { scan_devices(request); }, AuthenticationPredicates::IS_ADMIN));
|
||||
|
||||
|
||||
_write_value_handler.setMethod(HTTP_POST);
|
||||
_write_value_handler.setMaxContentLength(256);
|
||||
|
||||
@@ -18,19 +18,18 @@
|
||||
|
||||
#include "emsesp.h"
|
||||
|
||||
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)) {
|
||||
, setValues_(LOG_SETTINGS_PATH, [this](AsyncWebServerRequest * request, JsonVariant json) { setValues(request, json); }) {
|
||||
events_.setFilter(securityManager->filterRequest(AuthenticationPredicates::IS_ADMIN));
|
||||
|
||||
server->on(LOG_SETTINGS_PATH, HTTP_GET, std::bind(&WebLogService::getValues, this, _1)); // get settings
|
||||
// get settings
|
||||
server->on(LOG_SETTINGS_PATH, HTTP_GET, [this](AsyncWebServerRequest * request) { getValues(request); });
|
||||
|
||||
// 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));
|
||||
server->on(FETCH_LOG_PATH, HTTP_POST, [this](AsyncWebServerRequest * request) { fetchLog(request); });
|
||||
|
||||
server->addHandler(&setValues_);
|
||||
server->addHandler(&events_);
|
||||
@@ -59,12 +58,10 @@ uuid::log::Level WebLogService::log_level() const {
|
||||
}
|
||||
|
||||
void WebLogService::log_level(uuid::log::Level level) {
|
||||
EMSESP::webSettingsService.update(
|
||||
[&](WebSettings & settings) {
|
||||
settings.weblog_level = level;
|
||||
return StateUpdateResult::CHANGED;
|
||||
},
|
||||
"local");
|
||||
EMSESP::webSettingsService.update([&](WebSettings & settings) {
|
||||
settings.weblog_level = level;
|
||||
return StateUpdateResult::CHANGED;
|
||||
});
|
||||
uuid::log::Logger::register_handler(this, level);
|
||||
if (level == uuid::log::Level::OFF) {
|
||||
log_messages_.clear();
|
||||
@@ -87,12 +84,10 @@ void WebLogService::maximum_log_messages(size_t count) {
|
||||
while (log_messages_.size() > maximum_log_messages_) {
|
||||
log_messages_.pop_front();
|
||||
}
|
||||
EMSESP::webSettingsService.update(
|
||||
[&](WebSettings & settings) {
|
||||
settings.weblog_buffer = count;
|
||||
return StateUpdateResult::CHANGED;
|
||||
},
|
||||
"local");
|
||||
EMSESP::webSettingsService.update([&](WebSettings & settings) {
|
||||
settings.weblog_buffer = count;
|
||||
return StateUpdateResult::CHANGED;
|
||||
});
|
||||
}
|
||||
|
||||
bool WebLogService::compact() const {
|
||||
@@ -101,12 +96,10 @@ bool WebLogService::compact() const {
|
||||
|
||||
void WebLogService::compact(bool compact) {
|
||||
compact_ = compact;
|
||||
EMSESP::webSettingsService.update(
|
||||
[&](WebSettings & settings) {
|
||||
settings.weblog_compact = compact;
|
||||
return StateUpdateResult::CHANGED;
|
||||
},
|
||||
"local");
|
||||
EMSESP::webSettingsService.update([&](WebSettings & settings) {
|
||||
settings.weblog_compact = compact;
|
||||
return StateUpdateResult::CHANGED;
|
||||
});
|
||||
}
|
||||
|
||||
WebLogService::QueuedLogMessage::QueuedLogMessage(unsigned long id, std::shared_ptr<uuid::log::Message> && content)
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace emsesp {
|
||||
class WebLogService : public uuid::log::Handler {
|
||||
public:
|
||||
static constexpr size_t MAX_LOG_MESSAGES = 50;
|
||||
static constexpr size_t REFRESH_SYNC = 50;
|
||||
static constexpr size_t REFRESH_SYNC = 30;
|
||||
|
||||
WebLogService(AsyncWebServer * server, SecurityManager * securityManager);
|
||||
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
using namespace std::placeholders; // for `_1` etc
|
||||
|
||||
WebSchedulerService::WebSchedulerService(AsyncWebServer * 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) {
|
||||
@@ -432,25 +430,23 @@ void WebSchedulerService::loop() {
|
||||
// hard coded tests
|
||||
#if defined(EMSESP_TEST)
|
||||
void WebSchedulerService::test() {
|
||||
update(
|
||||
[&](WebScheduler & webScheduler) {
|
||||
webScheduler.scheduleItems.clear();
|
||||
// test 1
|
||||
auto si = ScheduleItem();
|
||||
si.active = true;
|
||||
si.flags = 1;
|
||||
si.time = "12:00";
|
||||
si.cmd = "system/fetch";
|
||||
si.value = "10";
|
||||
si.name = "test_scheduler";
|
||||
si.elapsed_min = 0;
|
||||
si.retry_cnt = 0xFF; // no startup retries
|
||||
update([&](WebScheduler & webScheduler) {
|
||||
webScheduler.scheduleItems.clear();
|
||||
// test 1
|
||||
auto si = ScheduleItem();
|
||||
si.active = true;
|
||||
si.flags = 1;
|
||||
si.time = "12:00";
|
||||
si.cmd = "system/fetch";
|
||||
si.value = "10";
|
||||
si.name = "test_scheduler";
|
||||
si.elapsed_min = 0;
|
||||
si.retry_cnt = 0xFF; // no startup retries
|
||||
|
||||
webScheduler.scheduleItems.push_back(si);
|
||||
webScheduler.scheduleItems.push_back(si);
|
||||
|
||||
return StateUpdateResult::CHANGED; // persist the changes
|
||||
},
|
||||
"local");
|
||||
return StateUpdateResult::CHANGED; // persist the changes
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -22,17 +22,13 @@ namespace emsesp {
|
||||
|
||||
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)
|
||||
, _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);
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { board_profile(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
addUpdateHandler([this] { onUpdate(); }, false);
|
||||
}
|
||||
|
||||
void WebSettings::read(WebSettings & settings, JsonObject root) {
|
||||
|
||||
@@ -18,100 +18,12 @@
|
||||
|
||||
#include "emsesp.h"
|
||||
|
||||
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));
|
||||
WiFi.onEvent(std::bind(&WebStatusService::WiFiEvent, this, _1, _2));
|
||||
}
|
||||
|
||||
// handles both WiFI and Ethernet
|
||||
void WebStatusService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
|
||||
switch (event) {
|
||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||
EMSESP::logger().warning("WiFi disconnected. Reason: %s (%d)",
|
||||
disconnectReason(info.wifi_sta_disconnected.reason),
|
||||
info.wifi_sta_disconnected.reason); // IDF 4.0
|
||||
EMSESP::system_.has_ipv6(false);
|
||||
break;
|
||||
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||
EMSESP::logger().info("WiFi connected with IP=%s, hostname=%s", WiFi.localIP().toString().c_str(), WiFi.getHostname());
|
||||
mDNS_start();
|
||||
break;
|
||||
|
||||
case ARDUINO_EVENT_ETH_START:
|
||||
// EMSESP::logger().info("Ethernet initialized");
|
||||
ETH.setHostname(EMSESP::system_.hostname().c_str());
|
||||
|
||||
// configure for static IP
|
||||
EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
||||
if (networkSettings.staticIPConfig) {
|
||||
ETH.config(networkSettings.localIP, networkSettings.gatewayIP, networkSettings.subnetMask, networkSettings.dnsIP1, networkSettings.dnsIP2);
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||
// prevent double calls
|
||||
if (!EMSESP::system_.ethernet_connected()) {
|
||||
EMSESP::logger().info("Ethernet connected with IP=%s, speed %d Mbps", ETH.localIP().toString().c_str(), ETH.linkSpeed());
|
||||
EMSESP::system_.ethernet_connected(true);
|
||||
mDNS_start();
|
||||
}
|
||||
break;
|
||||
|
||||
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||
EMSESP::logger().warning("Ethernet disconnected");
|
||||
EMSESP::system_.ethernet_connected(false);
|
||||
EMSESP::system_.has_ipv6(false);
|
||||
break;
|
||||
|
||||
case ARDUINO_EVENT_ETH_STOP:
|
||||
EMSESP::logger().info("Ethernet stopped");
|
||||
EMSESP::system_.ethernet_connected(false);
|
||||
EMSESP::system_.has_ipv6(false);
|
||||
break;
|
||||
|
||||
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
||||
EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
||||
if (networkSettings.enableIPv6) {
|
||||
WiFi.enableIpV6();
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||
EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
||||
if (networkSettings.enableIPv6) {
|
||||
ETH.enableIpV6();
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
||||
case ARDUINO_EVENT_ETH_GOT_IP6:
|
||||
if (EMSESP::system_.ethernet_connected()) {
|
||||
EMSESP::logger().info("Ethernet connected with IPv6=%s, speed %d Mbps", ETH.localIPv6().toString().c_str(), ETH.linkSpeed());
|
||||
} else {
|
||||
EMSESP::logger().info("WiFi connected with IPv6=%s, hostname=%s", WiFi.localIPv6().toString().c_str(), WiFi.getHostname());
|
||||
}
|
||||
mDNS_start();
|
||||
EMSESP::system_.has_ipv6(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { webStatusService(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
|
||||
}
|
||||
|
||||
void WebStatusService::webStatusService(AsyncWebServerRequest * request) {
|
||||
@@ -193,112 +105,4 @@ void WebStatusService::webStatusService(AsyncWebServerRequest * request) {
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
// start the multicast UDP service so EMS-ESP is discoverable via .local
|
||||
void WebStatusService::mDNS_start() const {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
MDNS.end();
|
||||
EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
||||
if (networkSettings.enableMDNS) {
|
||||
if (!MDNS.begin(EMSESP::system_.hostname().c_str())) {
|
||||
EMSESP::logger().warning("Failed to start mDNS responder service");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string address_s = EMSESP::system_.hostname() + ".local";
|
||||
|
||||
MDNS.addService("http", "tcp", 80); // add our web server and rest API
|
||||
MDNS.addService("telnet", "tcp", 23); // add our telnet console
|
||||
|
||||
MDNS.addServiceTxt("http", "tcp", "version", EMSESP_APP_VERSION);
|
||||
MDNS.addServiceTxt("http", "tcp", "address", address_s.c_str());
|
||||
|
||||
EMSESP::logger().info("mDNS responder service started");
|
||||
}
|
||||
});
|
||||
#else
|
||||
EMSESP::esp8266React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
||||
if (networkSettings.enableMDNS) {
|
||||
EMSESP::logger().info("mDNS responder service started");
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
const char * WebStatusService::disconnectReason(uint8_t code) {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
switch (code) {
|
||||
case WIFI_REASON_UNSPECIFIED: // = 1,
|
||||
return "unspecified";
|
||||
case WIFI_REASON_AUTH_EXPIRE: // = 2,
|
||||
return "auth expire";
|
||||
case WIFI_REASON_AUTH_LEAVE: // = 3,
|
||||
return "auth leave";
|
||||
case WIFI_REASON_ASSOC_EXPIRE: // = 4,
|
||||
return "assoc expired";
|
||||
case WIFI_REASON_ASSOC_TOOMANY: // = 5,
|
||||
return "assoc too many";
|
||||
case WIFI_REASON_NOT_AUTHED: // = 6,
|
||||
return "not authenticated";
|
||||
case WIFI_REASON_NOT_ASSOCED: // = 7,
|
||||
return "not assoc";
|
||||
case WIFI_REASON_ASSOC_LEAVE: // = 8,
|
||||
return "assoc leave";
|
||||
case WIFI_REASON_ASSOC_NOT_AUTHED: // = 9,
|
||||
return "assoc not authed";
|
||||
case WIFI_REASON_DISASSOC_PWRCAP_BAD: // = 10,
|
||||
return "disassoc powerCAP bad";
|
||||
case WIFI_REASON_DISASSOC_SUPCHAN_BAD: // = 11,
|
||||
return "disassoc supchan bad";
|
||||
case WIFI_REASON_IE_INVALID: // = 13,
|
||||
return "IE invalid";
|
||||
case WIFI_REASON_MIC_FAILURE: // = 14,
|
||||
return "MIC failure";
|
||||
case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: // = 15,
|
||||
return "4way handshake timeout";
|
||||
case WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT: // = 16,
|
||||
return "group key-update timeout";
|
||||
case WIFI_REASON_IE_IN_4WAY_DIFFERS: // = 17,
|
||||
return "IE in 4way differs";
|
||||
case WIFI_REASON_GROUP_CIPHER_INVALID: // = 18,
|
||||
return "group cipher invalid";
|
||||
case WIFI_REASON_PAIRWISE_CIPHER_INVALID: // = 19,
|
||||
return "pairwise cipher invalid";
|
||||
case WIFI_REASON_AKMP_INVALID: // = 20,
|
||||
return "AKMP invalid";
|
||||
case WIFI_REASON_UNSUPP_RSN_IE_VERSION: // = 21,
|
||||
return "unsupported RSN_IE version";
|
||||
case WIFI_REASON_INVALID_RSN_IE_CAP: // = 22,
|
||||
return "invalid RSN_IE_CAP";
|
||||
case WIFI_REASON_802_1X_AUTH_FAILED: // = 23,
|
||||
return "802 X1 auth failed";
|
||||
case WIFI_REASON_CIPHER_SUITE_REJECTED: // = 24,
|
||||
return "cipher suite rejected";
|
||||
case WIFI_REASON_BEACON_TIMEOUT: // = 200,
|
||||
return "beacon timeout";
|
||||
case WIFI_REASON_NO_AP_FOUND: // = 201,
|
||||
return "no AP found";
|
||||
case WIFI_REASON_AUTH_FAIL: // = 202,
|
||||
return "auth fail";
|
||||
case WIFI_REASON_ASSOC_FAIL: // = 203,
|
||||
return "assoc fail";
|
||||
case WIFI_REASON_HANDSHAKE_TIMEOUT: // = 204,
|
||||
return "handshake timeout";
|
||||
case WIFI_REASON_CONNECTION_FAIL: // 205,
|
||||
return "connection fail";
|
||||
case WIFI_REASON_AP_TSF_RESET: // 206,
|
||||
return "AP tsf reset";
|
||||
case WIFI_REASON_ROAMING: // 207,
|
||||
return "roaming";
|
||||
case WIFI_REASON_ASSOC_COMEBACK_TIME_TOO_LONG: // 208,
|
||||
return "assoc comeback time too long";
|
||||
case WIFI_REASON_SA_QUERY_TIMEOUT: // 209,
|
||||
return "sa query timeout";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
#endif
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
@@ -19,8 +19,6 @@
|
||||
#ifndef WebStatusService_h
|
||||
#define WebStatusService_h
|
||||
|
||||
#include <ESPmDNS.h>
|
||||
|
||||
#define EMSESP_STATUS_SERVICE_PATH "/rest/status"
|
||||
|
||||
namespace emsesp {
|
||||
@@ -30,10 +28,7 @@ class WebStatusService {
|
||||
WebStatusService(AsyncWebServer * server, SecurityManager * securityManager);
|
||||
|
||||
private:
|
||||
void webStatusService(AsyncWebServerRequest * request);
|
||||
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||
void mDNS_start() const;
|
||||
const char * disconnectReason(uint8_t code);
|
||||
void webStatusService(AsyncWebServerRequest * request);
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
Reference in New Issue
Block a user