15#ifndef WIFI_CONFIG_PORTAL_TIMEOUT
16#define WIFI_CONFIG_PORTAL_TIMEOUT 180
27 const String& client_ssid,
28 const String& client_password,
29 const String& ap_ssid,
30 const String& ap_password)
32 bool config_loaded =
load();
35 if (ap_ssid !=
"" && ap_password !=
"") {
44 if (!config_loaded && client_ssid !=
"" && client_password !=
"") {
55 const String& config_path,
56 const std::vector<ClientSSIDConfig>& client_configs,
const String& ap_ssid,
57 const String& ap_password)
59 bool config_loaded =
load();
62 if (ap_ssid !=
"" && ap_password !=
"") {
78 if (config.ssid_ ==
"" || config.password_ ==
"") {
92 for (
int i = 0; i < num_fill; i++) {
96 ESP_LOGD(__FILENAME__,
"Enabling WiFi provisioner");
100 WiFi.setMinSecurity(WIFI_AUTH_WPA_PSK);
104 WiFi.setHostname(hostname.c_str());
108 WiFi.begin(
"0",
"0", 0,
nullptr,
false);
114 WiFi.mode(WIFI_AP_STA);
134 this->ap_settings_.captive_portal_enabled_) {
135 dns_server_ = std::unique_ptr<DNSServer>(
new DNSServer());
137 dns_server_->setErrorReplyCode(DNSReplyCode::NoError);
150 WiFi.disconnect(
true);
155 WiFi.setHostname(hostname.c_str());
157 ESP_LOGI(__FILENAME__,
"Starting access point %s",
165 ESP_LOGE(__FILENAME__,
"Failed to start access point.");
172 WiFi.setHostname(hostname.c_str());
175 auto reconnect_cb = [
this]() {
176 static uint32_t attempt_num = 0;
177 static uint32_t current_config_idx = 0;
178 static int last_applied_idx = -1;
182 if (WiFi.status() == WL_CONNECTED) {
184 current_config_idx = 0;
189 if (num_configs == 0) {
190 ESP_LOGW(__FILENAME__,
191 "No client settings defined. Leaving WiFi client disconnected.");
195 uint32_t prev_config_idx = current_config_idx;
200 for (current_config_idx = current_config_idx;
201 current_config_idx < prev_config_idx + num_configs;
202 current_config_idx++) {
209 ESP_LOGD(__FILENAME__,
"Current client config index: %d",
211 ESP_LOGD(__FILENAME__,
"Attempt number: %d", attempt_num);
212 ESP_LOGD(__FILENAME__,
"Config SSID: %s", config.
ssid_.c_str());
218 "No valid client settings found. Leaving WiFi client disconnected.");
222 ESP_LOGI(__FILENAME__,
223 "Connecting to wifi SSID %s (connection attempt #%d).",
224 config.
ssid_.c_str(), attempt_num);
227 ESP_LOGI(__FILENAME__,
"Using static IP address: %s",
228 config.
ip_.toString().c_str());
244 int applied_idx =
static_cast<int>(current_config_idx % num_configs);
245 if (applied_idx != last_applied_idx) {
246 WiFi.disconnect(
false);
249 last_applied_idx = applied_idx;
251 current_config_idx++;
265 JsonObject apSettingsJson = root[
"apSettings"].to<JsonObject>();
268 JsonObject clientSettingsJson = root[
"clientSettings"].to<JsonObject>();
270 JsonArray clientConfigsJson = clientSettingsJson[
"settings"].to<JsonArray>();
271 int num_serialized = 0;
276 JsonObject clientConfigJson = clientConfigsJson.add<JsonObject>();
277 config.as_json(clientConfigJson);
283 if (config[
"hostname"].is<String>()) {
285 String hostname = config[
"hostname"].as<String>();
288 if (config[
"ssid"].is<String>()) {
289 String
ssid = config[
"ssid"].as<String>();
290 String password = config[
"password"].as<String>();
292 if (config[
"ap_mode"].is<String>()) {
293 if (config[
"ap_mode"].as<String>() ==
"Access Point" ||
294 config[
"ap_mode"].as<String>() ==
"Hotspot") {
306 if (config[
"apSettings"].is<JsonVariant>()) {
311 if (config[
"clientSettings"].is<JsonVariant>()) {
312 const JsonObject& client_settings_json = config[
"clientSettings"];
315 const JsonArray& client_settings_json_array =
316 client_settings_json[
"settings"];
317 for (
const JsonObject& cfg_json : client_settings_json_array) {
334 ESP_LOGI(__FILENAME__,
"Resetting WiFi SSID settings");
337 WiFi.disconnect(
true);
340 WiFi.begin(
"0",
"0", 0,
nullptr,
false);
345 if (WiFi.status() != WL_CONNECTED) {
346 ESP_LOGD(__FILENAME__,
347 "WiFi is not connected. Disconnecting to allow scanning.");
350 ESP_LOGI(__FILENAME__,
"Starting WiFi network scan");
351 int result = WiFi.scanNetworks(
true);
352 if (result == WIFI_SCAN_FAILED) {
353 ESP_LOGE(__FILENAME__,
"WiFi scan failed to start");
358 std::vector<WiFiNetworkInfo>& ssid_list) {
359 int num_networks = WiFi.scanComplete();
360 if (num_networks == WIFI_SCAN_RUNNING) {
361 return WIFI_SCAN_RUNNING;
363 if (num_networks == WIFI_SCAN_FAILED) {
364 return WIFI_SCAN_FAILED;
367 for (
int i = 0; i < num_networks; i++) {
368 WiFiNetworkInfo info(WiFi.SSID(i), WiFi.RSSI(i), WiFi.encryptionType(i),
369 WiFi.BSSID(i), WiFi.channel(i));
370 ssid_list.push_back(info);
Storage object for WiFi access point settings.
static AccessPointSettings from_json(const JsonObject &json)
void as_json(JsonObject &doc)
Storage object for WiFi client settings.
static ClientSSIDConfig from_json(const JsonObject &json)
virtual bool clear() override
Delete the data from a persistent storage.
virtual bool load() override
Load and populate the object from a persistent storage.
Automatic calling of the reset() method when the device needs to be reset.
static String get_hostname()
Get the current hostname.
static const std::shared_ptr< SensESPBaseApp > & get()
Get the singleton instance of the SensESPBaseApp.
WiFi network info storage class returned by scan results.
void start_access_point()
bool from_json(const JsonObject &config) override
AccessPointSettings ap_settings_
std::vector< ClientSSIDConfig > client_settings_
void init_wifi()
Bring the WiFi interface up from the current ap_settings_ / client_settings_ state....
int16_t get_wifi_scan_results(std::vector< WiFiNetworkInfo > &ssid_list)
WiFiProvisioner(const String &config_path, const String &client_ssid="", const String &client_password="", const String &ap_ssid="", const String &ap_password="")
~WiFiProvisioner() override
bool to_json(JsonObject &doc) override
void start_client_autoconnect()
std::unique_ptr< DNSServer > dns_server_
std::shared_ptr< reactesp::EventLoop > event_loop()
constexpr int kMaxNumClientConfigs