Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions moneo/WiFiManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include "WiFiManager.h"

// Add your networks here — the device scans and connects to the first available.
// Do NOT commit real credentials; replace these placeholders with your own locally.
const char* WIFI_NETWORKS[WIFI_NETWORK_COUNT][2] = {
{ "YOUR_WIFI_SSID", "YOUR_WIFI_PASSWORD" },
{ "SECOND_WIFI_SSID", "SECOND_WIFI_PASSWORD" }, // e.g. laptop hotspot
};
Comment on lines +5 to +8

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Config.h is already there, right?
Shouldn't we make use of that, or you're waiting to integrate it with the moneo.ino project file for orchestrating it?

It's fine if that's the case... this is the rudimentary part that Config.h abstracts. So it's fine for now; just confirming the reasoning.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The final connectivity flow should be:

  • Check NVS for saved networks
  • If found (client mode)
    • Scan the available SSIDs
    • Iterate over the saved networks to find a match in the available list
  • If not found (server mode)
    • Start an access point for other devices to connect to
    • Can be used for initial provisioning & configuration update etc.


WiFiManager::WiFiManager() : _lastReconnectAttempt(0) {}

bool WiFiManager::connect() {
// Try last known network first (from NVS)
String lastSSID, lastPass;
_loadLastNetwork(lastSSID, lastPass);

if (lastSSID.length() > 0) {
DLOGF("[WiFi] Trying last known: %s\n", lastSSID.c_str());
if (_tryNetwork(lastSSID.c_str(), lastPass.c_str())) return true;
}

// Scan and try all configured networks
DLOG("[WiFi] Scanning for known networks...");
int found = WiFi.scanNetworks();

// Iterate over our known networks (priority order), not the scan list.
// Cost scales with the few provisioned networks, not the many nearby ones.
for (int i = 0; i < WIFI_NETWORK_COUNT; i++) {
bool available = false;
for (int j = 0; j < found; j++) {
if (WiFi.SSID(j) == String(WIFI_NETWORKS[i][0])) {
available = true;
break; // this known network is in range — stop scanning for it
}
}
if (!available) continue;

DLOGF("[WiFi] Found: %s\n", WIFI_NETWORKS[i][0]);
if (_tryNetwork(WIFI_NETWORKS[i][0], WIFI_NETWORKS[i][1])) {
_saveLastNetwork(WIFI_NETWORKS[i][0], WIFI_NETWORKS[i][1]);
return true;
}
}
Comment on lines +28 to +43

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From computational complexity and determinacy perspective, it makes more sense to iterate over the known networks, and check if it's available on the available networks... instead of iterating over the available networks, to match with the known networks.

For example, you have 2 networks provisioned, and there are 6 networks available when scanning... in the current approach, you iterate 6 times, in altered approach, you only iterate twice. And if the first iteration already finds the network, it's an oneshot hit. Whereas in the current approach even if the known network is in the available list, but is not the first one, it at least has to iterate as many times as the known network's order is in the scanned network list.

This doesn't break software, and is fine for a demo; but these are the things (memory and time cost, i.e. computation complexity) if you're building for scale.


DLOG("[WiFi] No known network found.");
return false;
}

bool WiFiManager::ensureConnected() {
if (isConnected()) return true;
unsigned long now = millis();
if (now - _lastReconnectAttempt < WIFI_RECONNECT_INTERVAL) return false;
_lastReconnectAttempt = now;
return connect();
}

bool WiFiManager::_tryNetwork(const char* ssid, const char* password) {
WiFi.begin(ssid, password);
unsigned long start = millis();
while (WiFi.status() != WL_CONNECTED &&
millis() - start < WIFI_CONNECT_TIMEOUT_MS) {
delay(300);
}
if (WiFi.status() == WL_CONNECTED) {
DLOGF("[WiFi] Connected to %s — IP: %s\n", ssid,
WiFi.localIP().toString().c_str());
return true;
}
WiFi.disconnect();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why?

return false;
}

void WiFiManager::_saveLastNetwork(const char* ssid, const char* password) {
// Runtime state managed by the firmware (last connected network, future:
// last file synced, etc.) — kept separate from the provisioned network list.
_prefs.begin("moneo_runtime", false);
_prefs.putString("ssid", ssid);
_prefs.putString("pass", password);
_prefs.end();
}

void WiFiManager::_loadLastNetwork(String& ssid, String& password) {
_prefs.begin("moneo_runtime", true);
ssid = _prefs.getString("ssid", "");
password = _prefs.getString("pass", "");
_prefs.end();
}
33 changes: 33 additions & 0 deletions moneo/WiFiManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef WiFiManager_h
#define WiFiManager_h

#include <Arduino.h>
#include <WiFi.h>
#include <Preferences.h>
#include "Config.h"

// ============================================================
// WiFiManager — Auto-connects to known networks.
// Uses NVS (Preferences) to remember last connected network.
// Tries last known first, then scans all configured networks.
// ============================================================

class WiFiManager {
public:
WiFiManager();
bool connect();
bool isConnected() const { return WiFi.status() == WL_CONNECTED; }
bool ensureConnected();
String currentSSID() const { return WiFi.SSID(); }
String localIP() const { return WiFi.localIP().toString(); }

private:
bool _tryNetwork(const char* ssid, const char* password);
void _saveLastNetwork(const char* ssid, const char* password);
void _loadLastNetwork(String& ssid, String& password);

Preferences _prefs;
unsigned long _lastReconnectAttempt;
};

#endif