172 lines
4.5 KiB
C++
172 lines
4.5 KiB
C++
#include "webserver_dumpnvs.h"
|
|
|
|
// esp-idf includes
|
|
#include <esp_http_server.h>
|
|
#include <esp_log.h>
|
|
|
|
// 3rdparty lib includes
|
|
#include <htmlbuilder.h>
|
|
#include <fmt/core.h>
|
|
#include <espcppmacros.h>
|
|
#include <esphttpdutils.h>
|
|
#include <espchrono.h>
|
|
#include <lockhelper.h>
|
|
#include <tickchrono.h>
|
|
#include <ArduinoJson.h>
|
|
|
|
// local includes
|
|
#include "globals.h"
|
|
#include "webserver_lock.h"
|
|
#include "settingsutils.h"
|
|
|
|
using esphttpdutils::HtmlTag;
|
|
using namespace espchrono;
|
|
using namespace std::chrono_literals;
|
|
|
|
namespace {
|
|
constexpr const char * const TAG = "BOBBYWEB";
|
|
} // namespace
|
|
|
|
template<typename T>
|
|
typename std::enable_if<
|
|
!std::is_same<T, bool>::value &&
|
|
!std::is_integral<T>::value &&
|
|
!std::is_same<T, std::array<int8_t, 4>>::value &&
|
|
!std::is_same<T, std::string>::value &&
|
|
!std::is_same<T, espchrono::minutes32>::value &&
|
|
!std::is_same<T, espchrono::DayLightSavingMode>::value &&
|
|
!std::is_same<T, UnifiedModelMode>::value
|
|
&& !std::is_same<T, OtaAnimationModes>::value
|
|
, bool>::type
|
|
showInputForSetting(std::string_view key, T value, JsonObject &body)
|
|
{
|
|
body[key] = nullptr;
|
|
return false;
|
|
}
|
|
|
|
template<typename T>
|
|
typename std::enable_if<
|
|
std::is_same<T, bool>::value
|
|
, bool>::type
|
|
showInputForSetting(std::string_view key, T value, JsonObject &body)
|
|
{
|
|
body[key] = value;
|
|
return true;
|
|
}
|
|
|
|
template<typename T>
|
|
typename std::enable_if<
|
|
!std::is_same<T, bool>::value &&
|
|
std::is_integral<T>::value
|
|
, bool>::type
|
|
showInputForSetting(std::string_view key, T value, JsonObject &body)
|
|
{
|
|
body[key] = value;
|
|
return true;
|
|
}
|
|
|
|
template<typename T>
|
|
typename std::enable_if<
|
|
std::is_same<T, std::array<int8_t, 4>>::value
|
|
, bool>::type
|
|
showInputForSetting(std::string_view key, T value, JsonObject &body)
|
|
{
|
|
std::string array_str = fmt::format("{}{}{}{}", value[0], value[1], value[2], value[3]);
|
|
body[key] = array_str;
|
|
return true;
|
|
}
|
|
|
|
template<typename T>
|
|
typename std::enable_if<
|
|
std::is_same<T, std::string>::value
|
|
, bool>::type
|
|
showInputForSetting(std::string_view key, T value, JsonObject &body)
|
|
{
|
|
body[key] = value;
|
|
return true;
|
|
}
|
|
|
|
template<typename T>
|
|
typename std::enable_if<
|
|
std::is_same<T, espchrono::minutes32>::value
|
|
, bool>::type
|
|
showInputForSetting(std::string_view key, T value, JsonObject &body)
|
|
{
|
|
body[key] = value.count();
|
|
return true;
|
|
}
|
|
|
|
template<typename T>
|
|
typename std::enable_if<
|
|
std::is_same<T, espchrono::DayLightSavingMode>::value
|
|
, bool>::type
|
|
showInputForSetting(std::string_view key, T value, JsonObject &body)
|
|
{
|
|
body[key] = toString(espchrono::DayLightSavingMode(value));
|
|
return true;
|
|
}
|
|
|
|
template<typename T>
|
|
typename std::enable_if<
|
|
std::is_same<T, UnifiedModelMode>::value
|
|
, bool>::type
|
|
showInputForSetting(std::string_view key, T value, JsonObject &body)
|
|
{
|
|
body[key] = int(value);
|
|
return true;
|
|
}
|
|
|
|
template<typename T>
|
|
typename std::enable_if<
|
|
std::is_same<T, OtaAnimationModes>::value
|
|
, bool>::type
|
|
showInputForSetting(std::string_view key, T value, JsonObject &body)
|
|
{
|
|
body[key] = int(value);
|
|
return true;
|
|
}
|
|
|
|
esp_err_t webserver_dump_nvs_handler(httpd_req_t *req)
|
|
{
|
|
|
|
DynamicJsonDocument doc(6144);
|
|
|
|
JsonObject settings = doc.createNestedObject("settings");
|
|
|
|
configs.callForEveryConfig([&](auto &config){
|
|
const std::string_view nvsName{config.nvsName()};
|
|
showInputForSetting(nvsName, config.value(), settings);
|
|
});
|
|
|
|
const auto profile = settingsPersister.currentlyOpenProfileIndex();
|
|
const auto switchBackProfile = profile ? int(*profile) : 0;
|
|
|
|
JsonObject profiles = doc.createNestedObject("profiles");
|
|
|
|
// Profile settings
|
|
for (uint8_t profile_num = 0; profile_num < 4; profile_num++) {
|
|
|
|
#ifdef SIMPLIFIED_TRIGGER_TRIGGERONPRESET
|
|
if (profile_num == SIMPLIFIED_TRIGGER_TRIGGERONPRESET) {
|
|
continue;
|
|
}
|
|
#endif
|
|
settingsutils::switchProfile(profile_num);
|
|
|
|
const auto cur_profile = settingsPersister.currentlyOpenProfileIndex();
|
|
const auto profile_str = cur_profile ? std::to_string(*cur_profile) : "-";
|
|
|
|
JsonObject profile = profiles.createNestedObject(profile_str);
|
|
|
|
profileSettings.executeForEveryProfileSetting([&](const char *key, auto &value){
|
|
showInputForSetting(key, value, profile);
|
|
});
|
|
}
|
|
|
|
settingsutils::switchProfile(switchBackProfile);
|
|
|
|
std::string body;
|
|
serializeJson(doc, body);
|
|
CALL_AND_EXIT(esphttpdutils::webserver_resp_send, req, esphttpdutils::ResponseStatus::Ok, "application/json", body)
|
|
}
|