// // Created by erki on 07/01/24. // #pragma once #include "nvs_handle.hpp" #include #include #include #include #include #include #include #include #include struct CJsonStringDeleter { void operator()(char* json_str) const { if (json_str) cJSON_free(json_str); } }; using CJsonStrPtr = std::unique_ptr; struct CJsonDeleter { void operator()(cJSON* element) const { if (element) cJSON_Delete(element); } }; using CJsonPtr = std::unique_ptr; class WifiProvisioner { public: struct Parameter { etl::string<100> name; etl::string<15> nvs_name; enum class Type { INT, FLOAT, STRING }; Type type; using Value = std::variant>; Value data; Parameter() = default; Parameter(const char* name, const char* nvs_name, const Parameter::Type type) : name(name) , nvs_name(nvs_name) , type(type) , data(std::monostate()) { } std::expected tryReadAndAssignValue(nvs::NVSHandle* file_handle); std::expected tryValidateAndAssign(cJSON* object); template std::expected getValue() const { static_assert(std::is_same_v || std::is_same_v || std::is_same_v>, "T must be in the Value variant."); if (holds_alternative(data)) return std::unexpected(std::make_error_code(std::errc::io_error)); if constexpr (std::is_same_v) { if (type != Type::INT) return std::unexpected(std::make_error_code(std::errc::invalid_argument)); return std::get(data); } else if constexpr (std::is_same_v) { if (type != Type::FLOAT) return std::unexpected(std::make_error_code(std::errc::invalid_argument)); return std::get(data); } else { if (type != Type::STRING) return std::unexpected(std::make_error_code(std::errc::invalid_argument)); return std::get>(data); } } }; explicit WifiProvisioner(const char* settings_namespace, etl::delegate&)> success_cb); ~WifiProvisioner(); WifiProvisioner() = delete; WifiProvisioner(const WifiProvisioner&) = delete; WifiProvisioner(WifiProvisioner&&) = delete; WifiProvisioner& operator=(const WifiProvisioner&) = delete; WifiProvisioner& operator=(WifiProvisioner&&) = delete; bool parametersAreConfigured(); void clearSettings(); std::expected startProvisioning(); const etl::vector& getParameters(); std::expected getParameter(const etl::string<15>& name); std::expected addParameter(const char* name, const char* nvs_name, const Parameter::Type type); CJsonPtr getParameterObjects() const; std::expected tryConfigureParameters(CJsonPtr json_root); private: std::unique_ptr file_handle_; bool settings_initialized_ = false; httpd_handle_t http_server_ = nullptr; etl::vector params_; etl::delegate& params)> success_cb_; esp_err_t initializeNvsNamespace_(); std::expected initializeWifiAp_(); std::expected initializeCaptivePortal_(); std::expected writeAndCommitParameters_(); };