#include "settings_html.h" #include #include "../../../src/communication/contactorcontrol/comm_contactorcontrol.h" #include "../../../src/communication/equipmentstopbutton/comm_equipmentstopbutton.h" #include "../../charger/CHARGERS.h" #include "../../communication/can/comm_can.h" #include "../../communication/nvm/comm_nvm.h" #include "../../datalayer/datalayer.h" #include "index_html.h" #include "src/battery/BATTERIES.h" #include "src/inverter/INVERTERS.h" extern bool settingsUpdated; template constexpr auto to_underlying(E e) noexcept { return static_cast>(e); } template std::vector enum_values() { static_assert(std::is_enum_v, "Template argument must be an enum type."); constexpr auto count = to_underlying(EnumType::Highest); std::vector values; for (int i = 1; i < count; ++i) { values.push_back(static_cast(i)); } return values; } template std::vector> enum_values_and_names(Func name_for_type, const EnumType* noneValue = nullptr) { auto values = enum_values(); std::vector> pairs; for (auto& type : values) { auto name = name_for_type(type); if (name != nullptr) { pairs.push_back(std::pair(String(name), type)); } } std::sort(pairs.begin(), pairs.end(), [](const auto& a, const auto& b) { return a.first < b.first; }); if (noneValue) { pairs.insert(pairs.begin(), std::pair(name_for_type(*noneValue), *noneValue)); } return pairs; } template String options_for_enum_with_none(TEnum selected, Func name_for_type, TEnum noneValue) { String options; TEnum none = noneValue; auto values = enum_values_and_names(name_for_type, &none); for (const auto& [name, type] : values) { options += (""; } return options; } template String options_for_enum(TEnum selected, Func name_for_type) { String options; auto values = enum_values_and_names(name_for_type, nullptr); for (const auto& [name, type] : values) { options += (""; } return options; } template String options_from_map(int selected, const TMap& value_name_map) { String options; for (const auto& [value, name] : value_name_map) { options += "