More settings refactorings

This commit is contained in:
2021-12-29 19:50:45 +01:00
parent 9540898ced
commit 3cd17b6479
17 changed files with 308 additions and 567 deletions

View File

@@ -18,6 +18,7 @@
#include <lockhelper.h>
#include <tickchrono.h>
#include <futurecpp.h>
#include <cpputils.h>
// local includes
#include "newsettings.h"
@@ -49,19 +50,19 @@ typename std::enable_if<
!std::is_same_v<T, wifi_stack::mac_t> &&
!std::is_same_v<T, std::optional<wifi_stack::mac_t>> &&
!std::is_same_v<T, wifi_auth_mode_t> &&
!std::is_same_v<T, sntp_sync_mode_t>
, bool>::type
!std::is_same_v<T, sntp_sync_mode_t> &&
!std::is_same_v<T, espchrono::DayLightSavingMode>
, void>::type
showInputForSetting(std::string_view key, T value, std::string &body)
{
HtmlTag spanTag{"span", "style=\"color: red;\"", body};
body += "Unsupported config type";
return false;
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, bool>
, bool>::type
, void>::type
showInputForSetting(std::string_view key, T value, std::string &body)
{
body += fmt::format("<input type=\"checkbox\" name=\"{}\" value=\"true\" {}/>"
@@ -69,14 +70,13 @@ showInputForSetting(std::string_view key, T value, std::string &body)
esphttpdutils::htmlentities(key),
value ? "checked " : "",
esphttpdutils::htmlentities(key));
return true;
}
template<typename T>
typename std::enable_if<
!std::is_same_v<T, bool> &&
std::is_integral_v<T>
, bool>::type
, void>::type
showInputForSetting(std::string_view key, T value, std::string &body)
{
body += fmt::format("<input type=\"number\" name=\"{}\" value=\"{}\" min=\"{}\" max=\"{}\" step=\"1\" />",
@@ -84,73 +84,67 @@ showInputForSetting(std::string_view key, T value, std::string &body)
value,
std::numeric_limits<T>::min(),
std::numeric_limits<T>::max());
return true;
}
template<typename T>
typename std::enable_if<
is_duration_v<T>
, bool>::type
, void>::type
showInputForSetting(std::string_view key, T value, std::string &body)
{
body += fmt::format("<input type=\"number\" name=\"{}\" value=\"{}\" step=\"1\" />",
esphttpdutils::htmlentities(key),
value.count());
return true;
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, std::string>
, bool>::type
, void>::type
showInputForSetting(std::string_view key, T value, std::string &body)
{
body += fmt::format("<input type=\"text\" name=\"{}\" value=\"{}\" />",
esphttpdutils::htmlentities(key),
esphttpdutils::htmlentities(value));
return true;
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, wifi_stack::ip_address_t>
, bool>::type
, void>::type
showInputForSetting(std::string_view key, T value, std::string &body)
{
body += fmt::format("<input type=\"text\" name=\"{}\" value=\"{}\" pattern=\"[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+\" />",
esphttpdutils::htmlentities(key),
esphttpdutils::htmlentities(wifi_stack::toString(value)));
return true;
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, wifi_stack::mac_t>
, bool>::type
, void>::type
showInputForSetting(std::string_view key, T value, std::string &body)
{
body += fmt::format("<input type=\"text\" name=\"{}\" value=\"{}\" pattern=\"[0-9a-fA-F]{{2}}(?:\\:[0-9a-fA-F]{{2}}){{5}}\" />",
esphttpdutils::htmlentities(key),
esphttpdutils::htmlentities(wifi_stack::toString(value)));
return true;
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, std::optional<wifi_stack::mac_t>>
, bool>::type
, void>::type
showInputForSetting(std::string_view key, T value, std::string &body)
{
body += fmt::format("<input type=\"text\" name=\"{}\" value=\"{}\" pattern=\"(?:[0-9a-fA-F]{{2}}(?:\\:[0-9a-fA-F]{{2}}){{5}})?\" /> ?",
esphttpdutils::htmlentities(key),
value ? esphttpdutils::htmlentities(wifi_stack::toString(*value)) : std::string{});
return true;
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, wifi_auth_mode_t>
, bool>::type
, void>::type
showInputForSetting(std::string_view key, T value, std::string &body)
{
HtmlTag select{"select", fmt::format("name=\"{}\"", esphttpdutils::htmlentities(key)), body};
@@ -171,26 +165,38 @@ showInputForSetting(std::string_view key, T value, std::string &body)
HANDLE_ENUM_KEY(WIFI_AUTH_WAPI_PSK)
HANDLE_ENUM_KEY(WIFI_AUTH_MAX)
#undef HANDLE_ENUM_KEY
return true;
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, sntp_sync_mode_t>
, bool>::type
, void>::type
showInputForSetting(std::string_view key, T value, std::string &body)
{
HtmlTag select{"select", fmt::format("name=\"{}\"", esphttpdutils::htmlentities(key)), body};
#define HANDLE_ENUM_KEY(x) \
{ \
HtmlTag option{"option", fmt::format("value=\"{}\"{}", std::to_underlying(x), value == x ? " selected" : ""), body}; \
body += esphttpdutils::htmlentities(#x); \
HtmlTag option{"option", fmt::format("value=\"{}\"{}", std::to_underlying(x), value == x ? " selected" : ""), body}; \
body += esphttpdutils::htmlentities(#x); \
}
HANDLE_ENUM_KEY(SNTP_SYNC_MODE_IMMED)
HANDLE_ENUM_KEY(SNTP_SYNC_MODE_SMOOTH)
#undef HANDLE_ENUM_KEY
return true;
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, espchrono::DayLightSavingMode>
, void>::type
showInputForSetting(std::string_view key, T value, std::string &body)
{
HtmlTag select{"select", fmt::format("name=\"{}\"", esphttpdutils::htmlentities(key)), body};
espchrono::iterateDayLightSavingMode([&](T enumVal, std::string_view enumKey){
HtmlTag option{"option", fmt::format("value=\"{}\"{}", std::to_underlying(enumVal), value == enumVal ? " selected" : ""), body};
body += esphttpdutils::htmlentities(enumKey);
});
}
} // namespace
@@ -304,10 +310,16 @@ esp_err_t webserver_newSettings_handler(httpd_req_t *req)
body += ' ';
if (config.allowReset())
{
HtmlTag buttonTag{"a", fmt::format("href=\"/resetNewSettings?{}=1\"", esphttpdutils::htmlentities(nvsName)), body};
body += "Reset";
}
else
{
HtmlTag buttonTag{"span", "style=\"color: yellow;\"", body};
body += "No Reset";
}
}
}
});
@@ -330,214 +342,98 @@ typename std::enable_if<
!std::is_same_v<T, wifi_stack::mac_t> &&
!std::is_same_v<T, std::optional<wifi_stack::mac_t>> &&
!std::is_same_v<T, wifi_auth_mode_t> &&
!std::is_same_v<T, sntp_sync_mode_t>
, bool>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue, std::string &body)
!std::is_same_v<T, sntp_sync_mode_t> &&
!std::is_same_v<T, espchrono::DayLightSavingMode>
, tl::expected<void, std::string>>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue)
{
body += "Unsupported config type";
return false;
return tl::make_unexpected("Unsupported config type");
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, bool>
, bool>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue, std::string &body)
, tl::expected<void, std::string>>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue)
{
if (newValue == "true")
{
if (const auto result = configs.write_config(config, true); result)
{
body += "applied";
return true;
}
else
{
body += result.error();
return false;
}
}
else if (newValue == "false")
{
if (const auto result = configs.write_config(config, false); result)
{
body += "applied";
return true;
}
else
{
body += result.error();
return false;
}
}
if (cpputils::is_in(newValue, "true", "false"))
return configs.write_config(config, newValue == "true");
else
{
body += fmt::format("only true and false allowed, not {}", newValue);
return false;
}
return tl::make_unexpected(fmt::format("only true and false allowed, not {}", newValue));
}
template<typename T>
typename std::enable_if<
!std::is_same_v<T, bool> &&
std::is_integral_v<T>
, bool>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue, std::string &body)
, tl::expected<void, std::string>>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue)
{
if (auto parsed = cpputils::fromString<T>(newValue))
{
if (const auto result = configs.write_config(config, *parsed); result)
{
body += "applied";
return true;
}
else
{
body += result.error();
return false;
}
}
return configs.write_config(config, *parsed);
else
{
body += fmt::format("could not parse {}", newValue);
return false;
}
return tl::make_unexpected(fmt::format("could not parse {}", newValue));
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, std::string>
, bool>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue, std::string &body)
, tl::expected<void, std::string>>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue)
{
if (const auto result = configs.write_config(config, std::string{newValue}); result)
{
body += "applied";
return true;
}
else
{
body += result.error();
return false;
}
return configs.write_config(config, std::string{newValue});
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, wifi_stack::ip_address_t>
, bool>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue, std::string &body)
, tl::expected<void, std::string>>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue)
{
if (const auto parsed = wifi_stack::fromString<wifi_stack::ip_address_t>(newValue); parsed)
{
if (const auto result = configs.write_config(config, *parsed); result)
{
body += "applied";
return true;
}
else
{
body += result.error();
return false;
}
}
return configs.write_config(config, *parsed);
else
{
body += parsed.error();
return false;
}
return tl::make_unexpected(parsed.error());
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, wifi_stack::mac_t>
, bool>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue, std::string &body)
, tl::expected<void, std::string>>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue)
{
if (const auto parsed = wifi_stack::fromString<wifi_stack::mac_t>(newValue); parsed)
{
if (const auto result = configs.write_config(config, *parsed); result)
{
body += "applied";
return true;
}
else
{
body += result.error();
return false;
}
}
return configs.write_config(config, *parsed);
else
{
body += parsed.error();
return false;
}
return tl::make_unexpected(parsed.error());
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, std::optional<wifi_stack::mac_t>>
, bool>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue, std::string &body)
, tl::expected<void, std::string>>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue)
{
if (newValue.empty())
{
if (const auto result = configs.write_config(config, std::nullopt); result)
{
body += "applied";
return true;
}
else
{
body += result.error();
return false;
}
}
return configs.write_config(config, std::nullopt);
else if (const auto parsed = wifi_stack::fromString<wifi_stack::mac_t>(newValue); parsed)
{
if (const auto result = configs.write_config(config, *parsed); result)
{
body += "applied";
return true;
}
else
{
body += result.error();
return false;
}
}
return configs.write_config(config, *parsed);
else
{
body += parsed.error();
return false;
}
return tl::make_unexpected(parsed.error());
}
template<typename T>
typename std::enable_if<
std::is_same_v<T, wifi_auth_mode_t> ||
std::is_same_v<T, sntp_sync_mode_t>
, bool>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue, std::string &body)
std::is_same_v<T, sntp_sync_mode_t> ||
std::is_same_v<T, espchrono::DayLightSavingMode>
, tl::expected<void, std::string>>::type
saveSetting(ConfigWrapper<T> &config, std::string_view newValue)
{
if (auto parsed = cpputils::fromString<std::underlying_type_t<T>>(newValue))
{
if (const auto result = configs.write_config(config, T(*parsed)); result)
{
body += "applied";
return true;
}
else
{
body += result.error();
return false;
}
}
return configs.write_config(config, T(*parsed));
else
{
body += fmt::format("could not parse {}", newValue);
return false;
}
return tl::make_unexpected(fmt::format("could not parse {}", newValue));
}
} // namespace
@@ -585,11 +481,13 @@ esp_err_t webserver_saveNewSettings_handler(httpd_req_t *req)
char valueBuf[257];
esphttpdutils::urldecode(valueBuf, valueBufEncoded);
body += nvsName;
body += ": ";
if (!saveSetting(config, valueBuf, body))
if (const auto result = saveSetting(config, valueBuf); result)
body += fmt::format("{} succeeded!\n", esphttpdutils::htmlentities(nvsName));
else
{
body += fmt::format("{} failed: {}\n", esphttpdutils::htmlentities(nvsName), esphttpdutils::htmlentities(result.error()));
success = false;
body += '\n';
}
});
if (body.empty())