feat: wifiscan
This commit is contained in:
88
examples/wifiscan/README.md
Normal file
88
examples/wifiscan/README.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# WiFi Scanner Example
|
||||
|
||||
This example demonstrates how to use the async WiFi scanning functionality in SPORE with periodic scanning via tasks.
|
||||
|
||||
## Features
|
||||
|
||||
- **Async WiFi Scanning**: Non-blocking WiFi network discovery via NetworkManager
|
||||
- **Task-based Periodic Scanning**: Automatically scans for networks every minute using TaskManager
|
||||
- **Event-driven**: Uses the event system to handle scan events
|
||||
- **REST API**: HTTP endpoints to manually trigger scans and view results
|
||||
- **Detailed Results**: Shows SSID, RSSI, channel, and encryption type for each network
|
||||
|
||||
## Usage
|
||||
|
||||
1. Upload this example to your ESP8266 device
|
||||
2. Open the Serial Monitor at 115200 baud
|
||||
3. The device will automatically start scanning for WiFi networks every minute
|
||||
4. Results will be displayed in the Serial Monitor
|
||||
5. Use the REST API to manually trigger scans or view current results
|
||||
|
||||
## Event System
|
||||
|
||||
The WiFi scanner uses the following events:
|
||||
|
||||
- `wifi/scan/start`: Fired when scan starts (both manual and periodic)
|
||||
- `wifi/scan/complete`: Fired when scan completes successfully
|
||||
- `wifi/scan/error`: Fired when scan fails to start
|
||||
- `wifi/scan/timeout`: Fired when scan times out (10 seconds)
|
||||
|
||||
## Task Management
|
||||
|
||||
The example registers a periodic task:
|
||||
- **Task Name**: `wifi_scan_periodic`
|
||||
- **Interval**: 60 seconds (60000ms)
|
||||
- **Function**: Fires `wifi/scan/start` event and starts WiFi scan
|
||||
|
||||
## REST API
|
||||
|
||||
### Manual Scan Control
|
||||
- **Start Scan**: `POST /api/wifi/scan`
|
||||
- **Get Status**: `GET /api/wifi/status`
|
||||
|
||||
### Example API Usage
|
||||
```bash
|
||||
# Start a manual scan
|
||||
curl -X POST http://192.168.1.50/api/wifi/scan
|
||||
|
||||
# Get current scan status and results
|
||||
curl http://192.168.1.50/api/wifi/status
|
||||
|
||||
# Check task status
|
||||
curl http://192.168.1.50/api/tasks/status
|
||||
|
||||
# Disable periodic scanning
|
||||
curl -X POST http://192.168.1.50/api/tasks/control \
|
||||
-d task=wifi_scan_periodic -d action=disable
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
- **WiFiScannerService**: Manages periodic scanning and API endpoints
|
||||
- **NetworkManager**: Handles WiFi scanning operations and callbacks
|
||||
- **NodeContext**: Stores the WiFi access points data
|
||||
- **TaskManager**: Schedules periodic scan tasks
|
||||
- **Event System**: Provides communication between components
|
||||
|
||||
## WiFiAccessPoint Structure
|
||||
|
||||
```cpp
|
||||
struct WiFiAccessPoint {
|
||||
String ssid; // Network name
|
||||
int32_t rssi; // Signal strength
|
||||
uint8_t encryption; // Encryption type
|
||||
uint8_t* bssid; // MAC address
|
||||
int32_t channel; // WiFi channel
|
||||
bool isHidden; // Hidden network flag
|
||||
};
|
||||
```
|
||||
|
||||
## Task Configuration
|
||||
|
||||
The periodic scanning task can be controlled via the standard TaskManager API:
|
||||
- Enable/disable the task
|
||||
- Change the scan interval
|
||||
- Monitor task status
|
||||
- Start/stop the task
|
||||
|
||||
This provides flexibility to adjust scanning behavior based on application needs.
|
||||
183
examples/wifiscan/main.cpp
Normal file
183
examples/wifiscan/main.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
#include <Arduino.h>
|
||||
#include <functional>
|
||||
#include "Globals.h"
|
||||
#include "NodeContext.h"
|
||||
#include "NetworkManager.h"
|
||||
#include "ClusterManager.h"
|
||||
#include "ApiServer.h"
|
||||
#include "TaskManager.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class WiFiScannerService {
|
||||
public:
|
||||
WiFiScannerService(NodeContext& ctx, TaskManager& taskMgr, NetworkManager& networkMgr)
|
||||
: ctx(ctx), taskManager(taskMgr), network(networkMgr) {
|
||||
registerTasks();
|
||||
}
|
||||
|
||||
void registerApi(ApiServer& api) {
|
||||
api.addEndpoint("/api/wifi/scan", HTTP_POST, [this](AsyncWebServerRequest* request) {
|
||||
if (network.isWiFiScanning()) {
|
||||
JsonDocument resp;
|
||||
resp["success"] = false;
|
||||
resp["message"] = "WiFi scan already in progress";
|
||||
String json;
|
||||
serializeJson(resp, json);
|
||||
request->send(409, "application/json", json);
|
||||
return;
|
||||
}
|
||||
|
||||
network.startWiFiScan();
|
||||
|
||||
JsonDocument resp;
|
||||
resp["success"] = true;
|
||||
resp["message"] = "WiFi scan started";
|
||||
String json;
|
||||
serializeJson(resp, json);
|
||||
request->send(200, "application/json", json);
|
||||
});
|
||||
|
||||
api.addEndpoint("/api/wifi/status", HTTP_GET, [this](AsyncWebServerRequest* request) {
|
||||
JsonDocument doc;
|
||||
doc["scanning"] = network.isWiFiScanning();
|
||||
doc["networks_found"] = ctx.wifiAccessPoints->size();
|
||||
|
||||
JsonArray networks = doc["networks"].to<JsonArray>();
|
||||
for (const auto& ap : *ctx.wifiAccessPoints) {
|
||||
JsonObject network = networks.add<JsonObject>();
|
||||
network["ssid"] = ap.ssid;
|
||||
network["rssi"] = ap.rssi;
|
||||
network["channel"] = ap.channel;
|
||||
network["encryption"] = ap.encryption;
|
||||
network["hidden"] = ap.isHidden;
|
||||
}
|
||||
|
||||
String json;
|
||||
serializeJson(doc, json);
|
||||
request->send(200, "application/json", json);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
void registerTasks() {
|
||||
// Register task to start WiFi scan every minute (60000ms)
|
||||
taskManager.registerTask("wifi_scan_periodic", 60000, [this]() {
|
||||
if (!network.isWiFiScanning()) {
|
||||
Serial.println("[WiFiScannerService] Starting periodic WiFi scan...");
|
||||
ctx.fire("wifi/scan/start", nullptr);
|
||||
network.startWiFiScan();
|
||||
} else {
|
||||
Serial.println("[WiFiScannerService] Skipping scan - already in progress");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
NodeContext& ctx;
|
||||
TaskManager& taskManager;
|
||||
NetworkManager& network;
|
||||
};
|
||||
|
||||
NodeContext ctx({
|
||||
{"app", "wifiscan"},
|
||||
{"role", "demo"}
|
||||
});
|
||||
NetworkManager network(ctx);
|
||||
TaskManager taskManager(ctx);
|
||||
ClusterManager cluster(ctx, taskManager);
|
||||
ApiServer apiServer(ctx, taskManager, ctx.config.api_server_port);
|
||||
WiFiScannerService wifiScanner(ctx, taskManager, network);
|
||||
|
||||
// WiFi scan start callback
|
||||
void onWiFiScanStart(void* data) {
|
||||
Serial.println("[WiFi] Scan started...");
|
||||
}
|
||||
|
||||
// WiFi scan complete callback
|
||||
void onWiFiScanComplete(void* data) {
|
||||
Serial.println("\n=== WiFi Scan Results ===");
|
||||
|
||||
std::vector<WiFiAccessPoint>* accessPoints = static_cast<std::vector<WiFiAccessPoint>*>(data);
|
||||
|
||||
if (accessPoints->empty()) {
|
||||
Serial.println("No networks found");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.printf("Found %d networks:\n", accessPoints->size());
|
||||
Serial.println("SSID\t\t\tRSSI\tChannel\tEncryption");
|
||||
Serial.println("----------------------------------------");
|
||||
|
||||
for (const auto& ap : *accessPoints) {
|
||||
String encryptionStr = "Unknown";
|
||||
switch (ap.encryption) {
|
||||
case ENC_TYPE_NONE:
|
||||
encryptionStr = "Open";
|
||||
break;
|
||||
case ENC_TYPE_WEP:
|
||||
encryptionStr = "WEP";
|
||||
break;
|
||||
case ENC_TYPE_TKIP:
|
||||
encryptionStr = "WPA";
|
||||
break;
|
||||
case ENC_TYPE_CCMP:
|
||||
encryptionStr = "WPA2";
|
||||
break;
|
||||
case ENC_TYPE_AUTO:
|
||||
encryptionStr = "Auto";
|
||||
break;
|
||||
}
|
||||
|
||||
Serial.printf("%-20s\t%d\t%d\t%s\n",
|
||||
ap.ssid.c_str(), ap.rssi, ap.channel, encryptionStr.c_str());
|
||||
}
|
||||
Serial.println("========================\n");
|
||||
}
|
||||
|
||||
// WiFi scan error callback
|
||||
void onWiFiScanError(void* data) {
|
||||
Serial.println("[WiFi] Scan failed - error occurred");
|
||||
}
|
||||
|
||||
// WiFi scan timeout callback
|
||||
void onWiFiScanTimeout(void* data) {
|
||||
Serial.println("[WiFi] Scan failed - timeout");
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("\n=== WiFi Scanner Example ===");
|
||||
|
||||
// Initialize task manager first
|
||||
taskManager.initialize();
|
||||
ctx.taskManager = &taskManager;
|
||||
|
||||
// Initialize network tasks
|
||||
network.initTasks();
|
||||
|
||||
// Setup WiFi
|
||||
network.setupWiFi();
|
||||
|
||||
// Start the API server
|
||||
apiServer.begin();
|
||||
wifiScanner.registerApi(apiServer);
|
||||
|
||||
// Register WiFi scan event callbacks
|
||||
ctx.on("wifi/scan/start", onWiFiScanStart);
|
||||
ctx.on("wifi/scan/complete", onWiFiScanComplete);
|
||||
ctx.on("wifi/scan/error", onWiFiScanError);
|
||||
ctx.on("wifi/scan/timeout", onWiFiScanTimeout);
|
||||
|
||||
// Start an initial WiFi scan
|
||||
Serial.println("Starting initial WiFi scan...");
|
||||
ctx.fire("wifi/scan/start", nullptr);
|
||||
network.startWiFiScan();
|
||||
|
||||
// Print initial task status
|
||||
taskManager.printTaskStatus();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
taskManager.execute();
|
||||
yield();
|
||||
}
|
||||
Reference in New Issue
Block a user