sligh changed to dashbaord
This commit is contained in:
@@ -15,7 +15,11 @@
|
||||
#define HEARTBEAT_INTERVAL_MS 10000 // how often to send a heartbeat (ms)
|
||||
|
||||
// ─── Probe sniffing ──────────────────────────────────────────────────────────
|
||||
#define PROBE_SNIFF 1 // 1 = enabled, 0 = disabled
|
||||
#define PROBE_DEDUP_SECS 30 // suppress same MAC+SSID within this window (seconds)
|
||||
#define PROBE_QUEUE_SIZE 32 // max probe events buffered between scan cycles
|
||||
#define DEAUTH_QUEUE_SIZE 32 // max deauth/disassoc events buffered between scan cycles
|
||||
#define PROBE_SNIFF 1 // 1 = enabled, 0 = disabled
|
||||
#define PROBE_DEDUP_SECS 30 // suppress same MAC+SSID within this window (seconds)
|
||||
#define DEDUP_CACHE_SIZE 64 // unique MAC+SSID pairs tracked for dedup
|
||||
#define PROBE_QUEUE_SIZE 128 // max probe events buffered between flushes
|
||||
#define DEAUTH_QUEUE_SIZE 128 // max deauth/disassoc events buffered between flushes
|
||||
|
||||
// ─── Channel hopping ─────────────────────────────────────────────────────────
|
||||
#define HOP_DWELL_MS 300 // ms to dwell on each channel (13 ch × 300ms ≈ 4s/sweep)
|
||||
|
||||
+75
-8
@@ -15,6 +15,8 @@ String nodeId;
|
||||
unsigned long lastScan = 0;
|
||||
unsigned long lastHeartbeat = 0;
|
||||
|
||||
static uint8_t homeChannel = 1; // channel of sandbox AP — updated after connect and scan
|
||||
|
||||
// ─── Probe sniffing globals ───────────────────────────────────────────────────
|
||||
|
||||
#if PROBE_SNIFF
|
||||
@@ -39,12 +41,12 @@ static QueueHandle_t deauthQueue;
|
||||
|
||||
// Dedup cache — suppress repeated MAC+SSID pairs within PROBE_DEDUP_SECS
|
||||
struct DedupEntry { uint8_t mac[6]; char ssid[33]; uint32_t last_ms; };
|
||||
static DedupEntry dedupCache[32];
|
||||
static DedupEntry dedupCache[DEDUP_CACHE_SIZE];
|
||||
static int dedupNext = 0;
|
||||
|
||||
static bool isDuplicate(const uint8_t* mac, const char* ssid) {
|
||||
uint32_t now = millis();
|
||||
for (int i = 0; i < 32; i++) {
|
||||
for (int i = 0; i < DEDUP_CACHE_SIZE; i++) {
|
||||
if (dedupCache[i].last_ms == 0) continue;
|
||||
if (memcmp(dedupCache[i].mac, mac, 6) == 0 &&
|
||||
strcmp(dedupCache[i].ssid, ssid) == 0) {
|
||||
@@ -59,10 +61,17 @@ static bool isDuplicate(const uint8_t* mac, const char* ssid) {
|
||||
strncpy(dedupCache[dedupNext].ssid, ssid, 32);
|
||||
dedupCache[dedupNext].ssid[32] = '\0';
|
||||
dedupCache[dedupNext].last_ms = now;
|
||||
dedupNext = (dedupNext + 1) % 32;
|
||||
dedupNext = (dedupNext + 1) % DEDUP_CACHE_SIZE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// ─── Channel hop state ───────────────────────────────────────────────────────
|
||||
|
||||
static const uint8_t HOP_LIST[] = {1,2,3,4,5,6,7,8,9,10,11,12,13};
|
||||
static const int HOP_COUNT = sizeof(HOP_LIST) / sizeof(HOP_LIST[0]);
|
||||
static int hopIdx = 0;
|
||||
static unsigned long lastHop = 0;
|
||||
|
||||
// Promiscuous callback — runs in WiFi task context, not safe to call UDP here.
|
||||
// Parse probe request, deauth, and disassoc frames and push to queues.
|
||||
static void promiscuous_rx_cb(void* buf, wifi_promiscuous_pkt_type_t type) {
|
||||
@@ -153,7 +162,16 @@ void setup() {
|
||||
void loop() {
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.println("[WIFI] Lost connection, reconnecting...");
|
||||
#if PROBE_SNIFF
|
||||
esp_wifi_set_promiscuous(false);
|
||||
#endif
|
||||
connectWiFi();
|
||||
#if PROBE_SNIFF
|
||||
esp_wifi_set_channel(homeChannel, WIFI_SECOND_CHAN_NONE);
|
||||
esp_wifi_set_promiscuous(true);
|
||||
hopIdx = 0;
|
||||
lastHop = millis();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -167,9 +185,14 @@ void loop() {
|
||||
if (now - lastScan >= SCAN_INTERVAL_MS) {
|
||||
lastScan = now;
|
||||
scanAndSend();
|
||||
return;
|
||||
}
|
||||
|
||||
delay(100);
|
||||
#if PROBE_SNIFF
|
||||
advanceHop();
|
||||
#endif
|
||||
|
||||
delay(10);
|
||||
}
|
||||
|
||||
// ─── WiFi ────────────────────────────────────────────────────────────────────
|
||||
@@ -188,6 +211,12 @@ void connectWiFi() {
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
Serial.printf("\n[WIFI] Connected — IP: %s\n", WiFi.localIP().toString().c_str());
|
||||
#if PROBE_SNIFF
|
||||
uint8_t primary; wifi_second_chan_t second;
|
||||
esp_wifi_get_channel(&primary, &second);
|
||||
if (primary > 0) homeChannel = primary;
|
||||
Serial.printf("[HOP] Home channel: %d\n", homeChannel);
|
||||
#endif
|
||||
} else {
|
||||
Serial.println("\n[WIFI] Failed to connect, will retry in loop");
|
||||
}
|
||||
@@ -196,11 +225,21 @@ void connectWiFi() {
|
||||
// ─── Scan ────────────────────────────────────────────────────────────────────
|
||||
|
||||
void scanAndSend() {
|
||||
#if PROBE_SNIFF
|
||||
// Stop hopping and return to home channel — scan requires a stable channel to start.
|
||||
esp_wifi_set_promiscuous(false);
|
||||
esp_wifi_set_channel(homeChannel, WIFI_SECOND_CHAN_NONE);
|
||||
delay(50);
|
||||
#endif
|
||||
|
||||
Serial.println("[SCAN] Starting...");
|
||||
int n = WiFi.scanNetworks(false, true); // async=false, show_hidden=true
|
||||
|
||||
if (n == WIFI_SCAN_FAILED) {
|
||||
Serial.println("[SCAN] Failed");
|
||||
#if PROBE_SNIFF
|
||||
esp_wifi_set_promiscuous(true);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -213,10 +252,19 @@ void scanAndSend() {
|
||||
WiFi.scanDelete();
|
||||
|
||||
#if PROBE_SNIFF
|
||||
// Scan may have disabled promiscuous mode internally — re-enable it.
|
||||
// Re-read home channel — scan resets the radio, AP channel may have shifted.
|
||||
uint8_t primary; wifi_second_chan_t second;
|
||||
esp_wifi_get_channel(&primary, &second);
|
||||
if (primary > 0) homeChannel = primary;
|
||||
|
||||
// Re-enable promiscuous and flush anything queued before the scan.
|
||||
esp_wifi_set_promiscuous(true);
|
||||
flushProbeQueue();
|
||||
flushDeauthQueue();
|
||||
|
||||
// Reset hop state so next cycle starts cleanly from channel 1.
|
||||
hopIdx = 0;
|
||||
lastHop = millis();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -276,12 +324,13 @@ void sendBeaconEvent(int idx) {
|
||||
// ─── Heartbeat ───────────────────────────────────────────────────────────────
|
||||
|
||||
void sendHeartbeat() {
|
||||
unsigned long now = millis();
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"{\"node_id\":\"%s\",\"ts\":%lu,\"type\":\"heartbeat\","
|
||||
"\"uptime_ms\":%lu,\"free_heap\":%lu,\"wifi_rssi\":%d}",
|
||||
nodeId.c_str(), millis(),
|
||||
millis(),
|
||||
nodeId.c_str(), now,
|
||||
now,
|
||||
(unsigned long)ESP.getFreeHeap(),
|
||||
WiFi.RSSI()
|
||||
);
|
||||
@@ -289,7 +338,7 @@ void sendHeartbeat() {
|
||||
udp.print(buf);
|
||||
udp.endPacket();
|
||||
Serial.printf("[HB] uptime=%lus heap=%luK ap=%ddBm\n",
|
||||
millis() / 1000,
|
||||
now / 1000,
|
||||
(unsigned long)ESP.getFreeHeap() / 1024,
|
||||
WiFi.RSSI()
|
||||
);
|
||||
@@ -377,4 +426,22 @@ void flushDeauthQueue() {
|
||||
}
|
||||
}
|
||||
|
||||
// Advance to the next channel in the hop list.
|
||||
// Non-blocking — returns immediately if the dwell time hasn't elapsed.
|
||||
// Flushes queues each time we land back on homeChannel (WiFi is usable there).
|
||||
void advanceHop() {
|
||||
unsigned long now = millis();
|
||||
if (now - lastHop < HOP_DWELL_MS) return;
|
||||
lastHop = now;
|
||||
|
||||
hopIdx = (hopIdx + 1) % HOP_COUNT;
|
||||
uint8_t ch = HOP_LIST[hopIdx];
|
||||
esp_wifi_set_channel(ch, WIFI_SECOND_CHAN_NONE);
|
||||
|
||||
if (ch == homeChannel && WiFi.status() == WL_CONNECTED) {
|
||||
flushProbeQueue();
|
||||
flushDeauthQueue();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PROBE_SNIFF
|
||||
|
||||
Reference in New Issue
Block a user