12 KiB
SPORE WiFi Configuration Process
Overview
SPORE implements a WiFi configuration system that handles initial setup, runtime reconfiguration, and automatic fallback mechanisms. The system supports both Station (STA) and Access Point (AP) modes with seamless switching between them.
WiFi Configuration Architecture
Core Components
NetworkManager: Handles WiFi operations and configurationNetworkService: Provides HTTP API endpoints for WiFi managementConfig: Stores WiFi credentials and connection parameters- LittleFS: Persistent storage for WiFi configuration
- ESP8266 WiFi Library: Low-level WiFi operations
Configuration Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
wifi_ssid |
String | "shroud" | Network SSID for connection |
wifi_password |
String | "th3r31sn0sp00n" | Network password |
wifi_connect_timeout_ms |
uint32_t | 15000 | Connection timeout (15 seconds) |
wifi_retry_delay_ms |
uint32_t | 500 | Delay between connection attempts |
WiFi Configuration Lifecycle
1. Boot Process
graph TD
A[System Boot] --> B[Initialize LittleFS]
B --> C[Load Configuration]
C --> D[Initialize WiFi Mode]
D --> E[Set Hostname from MAC]
E --> F[Attempt STA Connection]
F --> G{Connection Successful?}
G -->|Yes| H[STA Mode Active]
G -->|No| I[Switch to AP Mode]
I --> J[Create Access Point]
J --> K[AP Mode Active]
H --> L[Start UDP Services]
K --> L
L --> M[Initialize Node Context]
M --> N[Start Cluster Services]
Detailed Boot Sequence:
-
LittleFS Initialization
if (!LittleFS.begin()) { LOG_WARN("Config", "Failed to initialize LittleFS, using defaults"); setDefaults(); return; } -
Configuration Loading
- Load WiFi credentials from
/config.json - Fall back to defaults if file doesn't exist
- Validate configuration parameters
- Load WiFi credentials from
-
WiFi Mode Initialization
WiFi.mode(WIFI_STA); WiFi.begin(ctx.config.wifi_ssid.c_str(), ctx.config.wifi_password.c_str()); -
Hostname Generation
void NetworkManager::setHostnameFromMac() { uint8_t mac[6]; WiFi.macAddress(mac); char buf[32]; sprintf(buf, "esp-%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); WiFi.hostname(buf); ctx.hostname = String(buf); } -
Connection Attempt
unsigned long startAttemptTime = millis(); while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < ctx.config.wifi_connect_timeout_ms) { delay(ctx.config.wifi_retry_delay_ms); } -
Fallback to AP Mode
if (WiFi.status() != WL_CONNECTED) { LOG_WARN("WiFi", "Failed to connect to AP. Creating AP..."); WiFi.mode(WIFI_AP); WiFi.softAP(ctx.config.wifi_ssid.c_str(), ctx.config.wifi_password.c_str()); }
2. Runtime Reconfiguration
graph TD
A[HTTP API Request] --> B[Validate Parameters]
B --> C[Update Config Object]
C --> D[Save to Persistent Storage]
D --> E[Send Response to Client]
E --> F[Schedule Node Restart]
F --> G[Node Restarts]
G --> H[Apply New Configuration]
H --> I[Attempt New Connection]
Runtime Reconfiguration Process:
-
API Request Validation
if (!request->hasParam("ssid", true) || !request->hasParam("password", true)) { request->send(400, "application/json", "{\"error\": \"Missing required parameters\"}"); return; } -
Configuration Update
void NetworkManager::setWiFiConfig(const String& ssid, const String& password, uint32_t connect_timeout_ms, uint32_t retry_delay_ms) { ctx.config.wifi_ssid = ssid; ctx.config.wifi_password = password; ctx.config.wifi_connect_timeout_ms = connect_timeout_ms; ctx.config.wifi_retry_delay_ms = retry_delay_ms; } -
Persistent Storage
bool configSaved = networkManager.saveConfig(); if (!configSaved) { LOG_WARN("NetworkService", "Failed to save WiFi configuration to persistent storage"); } -
Restart Scheduling
request->onDisconnect([this]() { LOG_INFO("NetworkService", "Restarting node to apply WiFi configuration..."); delay(100); // Give time for response to be sent networkManager.restartNode(); });
WiFi Modes
Station Mode (STA)
Purpose: Connect to existing WiFi network as a client
Configuration:
- SSID and password required
- Automatic IP assignment via DHCP
- Hostname set from MAC address
- UDP services on configured port
Connection Process:
- Set WiFi mode to STA
- Begin connection with credentials
- Wait for connection with timeout
- Set hostname and start services
Access Point Mode (AP)
Purpose: Create WiFi hotspot when STA connection fails
Configuration:
- Uses configured SSID/password for AP
- Fixed IP address (usually 192.168.4.1)
- Allows other devices to connect
- Maintains cluster functionality
AP Creation Process:
- Switch WiFi mode to AP
- Create soft access point
- Set AP IP address
- Start services on AP IP
HTTP API Endpoints
Network Status
GET /api/network/status
Returns comprehensive WiFi and network status information.
Response Fields:
{
"wifi": {
"connected": true,
"mode": "STA",
"ssid": "MyNetwork",
"ip": "192.168.1.100",
"mac": "AA:BB:CC:DD:EE:FF",
"hostname": "esp-AABBCCDDEEFF",
"rssi": -45,
"ap_ip": "192.168.4.1",
"ap_mac": "AA:BB:CC:DD:EE:FF",
"stations_connected": 0
}
}
WiFi Scanning
GET /api/network/wifi/scan
Returns list of available WiFi networks from last scan.
Response Fields:
{
"access_points": [
{
"ssid": "MyNetwork",
"rssi": -45,
"channel": 6,
"encryption_type": 4,
"hidden": false,
"bssid": "AA:BB:CC:DD:EE:FF"
}
]
}
POST /api/network/wifi/scan
Initiates a new WiFi network scan.
Response:
{
"status": "scanning",
"message": "WiFi scan started"
}
WiFi Configuration
POST /api/network/wifi/config
Configures WiFi connection with new credentials.
Parameters:
ssid(required): Network SSIDpassword(required): Network passwordconnect_timeout_ms(optional): Connection timeout (default: 10000)retry_delay_ms(optional): Retry delay (default: 500)
Request Example:
curl -X POST http://192.168.1.100/api/network/wifi/config \
-d "ssid=MyNewNetwork&password=newpassword&connect_timeout_ms=15000"
Response:
{
"status": "success",
"message": "WiFi configuration updated and saved",
"config_saved": true,
"restarting": true
}
WiFi Scanning Process
Scanning Implementation
void NetworkManager::scanWifi() {
if (!isScanning) {
isScanning = true;
LOG_INFO("WiFi", "Starting WiFi scan...");
WiFi.scanNetworksAsync([this](int networksFound) {
LOG_INFO("WiFi", "Scan completed, found " + String(networksFound) + " networks");
this->processAccessPoints();
this->isScanning = false;
}, true);
}
}
Access Point Processing
void NetworkManager::processAccessPoints() {
int numNetworks = WiFi.scanComplete();
if (numNetworks <= 0) return;
accessPoints.clear();
for (int i = 0; i < numNetworks; i++) {
AccessPoint ap;
ap.ssid = WiFi.SSID(i);
ap.rssi = WiFi.RSSI(i);
ap.encryptionType = WiFi.encryptionType(i);
ap.channel = WiFi.channel(i);
ap.isHidden = ap.ssid.length() == 0;
uint8_t* newBssid = new uint8_t[6];
memcpy(newBssid, WiFi.BSSID(i), 6);
ap.bssid = newBssid;
accessPoints.push_back(ap);
}
WiFi.scanDelete();
}
Error Handling
Connection Failures
| Error Type | Handling | Recovery |
|---|---|---|
| Invalid Credentials | Log error, switch to AP mode | Manual reconfiguration via API |
| Network Unavailable | Log warning, switch to AP mode | Automatic retry on next boot |
| Timeout | Log timeout, switch to AP mode | Increase timeout or check network |
| Hardware Failure | Log error, continue in AP mode | Hardware replacement required |
API Error Responses
{
"error": "Missing required parameters",
"status": "error"
}
{
"error": "Failed to save configuration",
"status": "error",
"config_saved": false
}
Security Considerations
Current Implementation
- Plain Text Storage: WiFi passwords stored unencrypted
- Local Network Only: No internet exposure
- No Authentication: API access without authentication
- MAC-based Hostnames: Predictable hostname generation
Security Best Practices
- Network Isolation: Keep SPORE devices on isolated network
- Strong Passwords: Use complex WiFi passwords
- Regular Updates: Keep firmware updated
- Access Control: Implement network-level access control
Future Security Enhancements
- Password Encryption: Encrypt stored WiFi credentials
- API Authentication: Add authentication to configuration API
- Certificate-based Security: Implement TLS/SSL
- Access Control Lists: Role-based configuration access
Troubleshooting
Common Issues
-
WiFi Connection Fails
- Check SSID and password
- Verify network availability
- Check signal strength
- Increase connection timeout
-
Configuration Not Persisting
- Check LittleFS initialization
- Verify file write permissions
- Monitor available flash space
-
AP Mode Not Working
- Check AP credentials
- Verify IP address assignment
- Check for IP conflicts
-
Scan Not Finding Networks
- Wait for scan completion
- Check WiFi hardware
- Verify scan permissions
Debug Commands
# Check WiFi status
curl -s http://192.168.1.100/api/network/status | jq '.wifi'
# Scan for networks
curl -X POST http://192.168.1.100/api/network/wifi/scan
# View scan results
curl -s http://192.168.1.100/api/network/wifi/scan | jq '.'
# Test configuration
curl -X POST http://192.168.1.100/api/network/wifi/config \
-d "ssid=TestNetwork&password=testpass"
Log Analysis
Successful Connection:
[INFO] WiFi: Connected to AP, IP: 192.168.1.100
[INFO] WiFi: Hostname set to: esp-AABBCCDDEEFF
[INFO] WiFi: UDP listening on port 4210
Connection Failure:
[WARN] WiFi: Failed to connect to AP. Creating AP...
[INFO] WiFi: AP created, IP: 192.168.4.1
Configuration Update:
[INFO] NetworkService: Restarting node to apply WiFi configuration...
[INFO] WiFi: Connecting to AP...
Performance Considerations
Connection Time
- STA Connection: 5-15 seconds typical
- AP Creation: 1-3 seconds
- Scan Duration: 5-10 seconds
- Configuration Save: 100-500ms
Memory Usage
- WiFi Stack: ~20-30KB RAM
- Scan Results: ~1KB per network
- Configuration: ~200 bytes
- API Buffers: ~2-4KB
Network Overhead
- Scan Packets: Minimal impact
- Configuration API: ~500 bytes per request
- Status Updates: ~200 bytes per response
Best Practices
Configuration Management
- Use Strong Passwords: Implement password complexity requirements
- Set Appropriate Timeouts: Balance connection speed vs reliability
- Monitor Connection Quality: Track RSSI and connection stability
- Implement Retry Logic: Handle temporary network issues
- Log Configuration Changes: Audit trail for troubleshooting
Development Guidelines
- Handle All Error Cases: Implement comprehensive error handling
- Provide Clear Feedback: Inform users of connection status
- Optimize Scan Frequency: Balance discovery vs performance
- Test Fallback Scenarios: Ensure AP mode works correctly
- Document Configuration Options: Clear parameter documentation
Related Documentation
- Configuration Management - Persistent configuration system
- API Reference - Complete HTTP API documentation
- Architecture Overview - System architecture and components
- OpenAPI Specification - Machine-readable API specification