-
Notifications
You must be signed in to change notification settings - Fork 0
Migration Guide
Upgrading from v4.1.0 to v4.2.0.
Version 4.2.0 is 100% backward compatible. Existing code will continue to work without any changes.
This guide helps you adopt the new v4.2.0 features to improve your code quality, reliability, and maintainability.
Access Point Configuration:
- Save AP settings to NVS flash
- Automatic loading on boot
- Commands:
config ap save/load/clear/show
Station Configuration:
- Save network credentials to NVS
- Base64 password encoding for security
- Commands:
config station save/load/clear/show
Benefits:
- Settings persist across reboots
- No need to reconfigure every time
- Secure password storage
Result Type:
- Type-safe error returns
- Descriptive error messages
- Easier error propagation
Example:
// Old way
bool connectWiFi(const char* ssid) {
if (!ssid) return false;
return WiFi.begin(ssid);
}
// New way
Result<void> connectWiFi(const char* ssid) {
if (!ssid) {
return {ErrorCode::WIFI_INVALID_SSID, "SSID cannot be null"};
}
if (!WiFi.begin(ssid)) {
return {ErrorCode::WIFI_CONNECT_FAILED, "Connection failed"};
}
return {}; // Success
}Log Levels:
- TRACE, DEBUG, INFO, WARN, ERROR, FATAL
- Configurable at runtime
- Optional timestamps
Example:
// Old way
Serial.println("[WiFi] Connecting...");
Serial.print("[WiFi] ERROR: ");
Serial.println(errorMsg);
// New way
LOG_INFO(TAG_WIFI, "Connecting to %s", ssid);
LOG_ERROR(TAG_WIFI, "Connection failed: %s", errorMsg);Automatic Tracking:
- Operation timing
- Min/avg/max statistics
- Call counts
Example:
void scanNetworks() {
ScopedTimer timer(g_wifiScanMonitor);
int count = WiFi.scanNetworks();
// Timing automatically recorded
}
// Later, view stats
printAllPerformanceStats();For Access Point Mode:
// Before (v4.1.0)
void setup() {
startAccessPoint("ESP32-AP", "password123");
}
// After (v4.2.0)
void setup() {
initializeAPConfig(); // Load saved config
// First time setup
if (!loadAPConfig()) {
saveAPConfig("ESP32-AP", "password123", 6);
}
startAccessPoint(); // Uses saved config
}For Station Mode:
// Before (v4.1.0)
void setup() {
connectToNetwork("HomeWiFi", "mypassword");
}
// After (v4.2.0)
void setup() {
initializeStationConfig(); // Load saved config
// Check if credentials saved
if (hasStationConfig()) {
// Auto-connect to saved network
startStationMode();
} else {
// First time - save credentials
saveStationConfig("HomeWiFi", "mypassword");
connectToNetwork("HomeWiFi", "mypassword");
}
}Configuration Commands:
Users can now configure via serial:
# AP configuration
> config ap save "MyESP32" "securepass" 6
> config ap show
# Station configuration
> config station save "HomeNetwork" "wifipassword"
> config station show
# Clear configuration
> config ap clear
> config station clearSimple Boolean Returns:
// Old pattern
bool myFunction() {
if (error) {
Serial.println("ERROR: Something failed");
return false;
}
return true;
}
// New pattern
Result<void> myFunction() {
if (error) {
return {ErrorCode::OPERATION_FAILED, "Something failed"};
}
return {}; // Success
}
// Usage
auto result = myFunction();
if (!result) {
LOG_ERROR(TAG_MODULE, "%s", result.getMessage());
}Functions with Return Values:
// Old pattern
int getValue(bool& success) {
if (notReady) {
success = false;
return 0;
}
success = true;
return 42;
}
// New pattern
Result<int> getValue() {
if (notReady) {
return {ErrorCode::NOT_READY, "System not initialized"};
}
return 42; // Success with value
}
// Usage
auto result = getValue();
if (result) {
int value = result.getValue();
// Use value
} else {
LOG_ERROR(TAG_MODULE, "%s", result.getMessage());
}Error Propagation:
// Old pattern
bool doMultipleThings() {
if (!step1()) return false;
if (!step2()) return false;
if (!step3()) return false;
return true;
}
// New pattern
Result<void> doMultipleThings() {
RETURN_IF_ERROR(step1());
RETURN_IF_ERROR(step2());
RETURN_IF_ERROR(step3());
return {};
}Basic Logging:
// Old way
Serial.println("[WiFi] Starting scan...");
// New way
LOG_INFO(TAG_WIFI, "Starting scan");Formatted Logging:
// Old way
Serial.print("[WiFi] Connected to ");
Serial.print(ssid);
Serial.print(" with IP ");
Serial.println(WiFi.localIP());
// New way
LOG_INFO(TAG_WIFI, "Connected to %s with IP %s",
ssid, WiFi.localIP().toString().c_str());Error Logging:
// Old way
Serial.print("[ERROR] Failed to connect: ");
Serial.println(errorCode);
// New way
LOG_ERROR(TAG_WIFI, "Failed to connect: %d", errorCode);Configure Logging:
void setup() {
Serial.begin(115200);
// Set log level
setLogLevel(LogLevel::INFO); // INFO, WARN, ERROR, FATAL
// Enable timestamps
setLogTimestamps(true);
}Log Levels:
-
TRACE- Very detailed debugging -
DEBUG- Detailed debugging -
INFO- Informational messages -
WARN- Warnings (non-critical issues) -
ERROR- Errors (critical issues) -
FATAL- Fatal errors (system-breaking)
Wrap Critical Operations:
// Before
void performScan() {
unsigned long start = millis();
int count = WiFi.scanNetworks();
Serial.printf("Scan took %lu ms\n", millis() - start);
}
// After
#include "performance_monitor.h"
void performScan() {
ScopedTimer timer(g_wifiScanMonitor);
int count = WiFi.scanNetworks();
// Timing automatically recorded with statistics
}View Statistics:
void loop() {
// Your main loop code
// Periodically print performance stats
static unsigned long lastStats = 0;
if (millis() - lastStats > 60000) { // Every minute
printAllPerformanceStats();
lastStats = millis();
}
}Monitor Memory:
void loop() {
static unsigned long lastMemCheck = 0;
if (millis() - lastMemCheck > 60000) {
logMemoryStats(TAG_SYSTEM);
lastMemCheck = millis();
}
}Replace Magic Numbers:
// Old way
delay(300);
if (strlen(ssid) > 32) { ... }
WiFi.begin(ssid, password, 0, NULL, true);
// New way
#include "config.h"
delay(SystemConstants::LED_STARTUP_ANIMATION_DELAY_MS);
if (strlen(ssid) > SystemConstants::MAX_SSID_LENGTH) { ... }
WiFi.begin(ssid, password, 0, NULL,
SystemConstants::WIFI_CONNECT_TIMEOUT_MS);Available Constants:
From config.h:
-
MAX_SSID_LENGTH= 32 -
MAX_PASSWORD_LENGTH= 63 -
MAX_NETWORKS= 20 -
WIFI_CONNECT_TIMEOUT_MS= 10000 -
SERIAL_BAUD_RATE= 115200 - And many more...
Access: http://[device-ip]/config
Features:
- Save/load AP configuration
- Save/load Station configuration
- Clear stored settings
- View current configuration
- All changes persist across reboots
Example Usage:
- Open web interface
- Navigate to Configuration page
- Fill in AP or Station settings
- Click "Save"
- Settings persist after reboot
AP Configuration:
// Save AP config
POST /config/ap
{
"ssid": "MyESP32",
"password": "securepass",
"channel": 6
}
// Load AP config
GET /config/ap
// Clear AP config
DELETE /config/apStation Configuration:
// Save Station config
POST /config/station
{
"ssid": "HomeWiFi",
"password": "mypassword"
}
// Load Station config
GET /config/station
// Clear Station config
DELETE /config/station# Build for all environments
pio run
# Build specific board
pio run -e esp32devExpected: Clean build with no errors
# Upload and monitor
pio run -e esp32dev --target upload --target monitor
# Test AP config
> config ap save "TestAP" "testpass" 11
> config ap show
> reboot
# After reboot, verify
> config ap show
# Should show saved settingsvoid setup() {
Serial.begin(115200);
setLogLevel(LogLevel::DEBUG);
setLogTimestamps(true);
LOG_INFO(TAG_MAIN, "System starting v4.2.0");
LOG_DEBUG(TAG_MAIN, "Debug logging enabled");
}Expected Output:
[2024-01-15 10:30:45] [INFO] [MAIN] System starting v4.2.0
[2024-01-15 10:30:45] [DEBUG] [MAIN] Debug logging enabled
void loop() {
static unsigned long lastPrint = 0;
if (millis() - lastPrint > 60000) {
printAllPerformanceStats();
logMemoryStats(TAG_SYSTEM);
lastPrint = millis();
}
}Expected Output:
ββββββββββββββββββββββββββββββββββββ
Performance Statistics
ββββββββββββββββββββββββββββββββββββ
WiFi Scan: 1235ms avg (min: 1104ms, max: 1458ms, count: 15)
Channel Analysis: 3421ms avg (min: 3102ms, max: 3895ms, count: 3)
...
You don't need to migrate everything at once. Here's a recommended phased approach:
Week 1: Add Logging
- Replace Serial.print with LOG_XXX macros
- No functional changes
- Immediate benefits: Better debugging
Week 2: Add Performance Monitoring
- Wrap critical functions with ScopedTimer
- No functional changes
- Benefits: Identify bottlenecks
Testing: Everything should work exactly as before
Week 3: Add Configuration Persistence
- Initialize config system
- Test save/load functionality
- Verify persistence across reboots
Testing: Test configuration commands thoroughly
Week 4+: Migrate Error Handling
- Start with leaf functions
- Work up the call stack
- Thorough testing after each module
Testing: Verify error cases handled correctly
void setup() {
Serial.begin(115200);
// Initialize configuration
initializeAPConfig();
initializeStationConfig();
// Check for saved Station config
if (hasStationConfig()) {
LOG_INFO(TAG_MAIN, "Using saved Station config");
startStationMode();
} else {
LOG_INFO(TAG_MAIN, "No Station config, starting AP");
startAccessPoint();
}
}// From serial command
if (command == "connect") {
String ssid = argument;
String password = secondArgument;
// Save for future use
saveStationConfig(ssid, password);
// Connect now
connectToNetwork(ssid, password);
}// Factory reset
void factoryReset() {
clearAPConfig();
clearStationConfig();
LOG_INFO(TAG_SYSTEM, "Configuration cleared");
ESP.restart();
}None! Version 4.2.0 is fully backward compatible.
All v4.1.0 code continues to work without modification. New features are purely additive.
- See
src/ap_config.cppfor configuration patterns - Check
include/error_handling.hfor Result examples - Look at
src/logging.cppfor logging implementation
- GitHub Issues: Report bugs or ask questions
- Documentation: Check
docs/folder for detailed guides
Version: 4.2.0
Compatibility: β
100% Backward Compatible
Migration Difficulty: π’ Easy (Optional)
Recommended: β
Yes - Significant Quality Improvements
GitHub Repository β’ Report Issues β’ Discussions
ESP32 WiFi Utility v4.2.0 β’ MIT License β’ Β© Arunkumar Mourougappane
Version: 4.2.0
License: MIT