1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
#include <Arduino.h>
#include <WiFi.h>
#include <esp_wifi.h>
#include "../ui/display.h"
#include "../buttons.h"
// ===== CONFIG =====
#define GRAPH_WIDTH 128
#define GRAPH_HEIGHT 44
#define GRAPH_TOP 10
#define MAX_POINTS 128
#define SPIKE_THRESHOLD 30
// ===== STATE =====
struct SnifferGraph {
uint8_t graphData[MAX_POINTS];
uint8_t currentChannel = 1;
volatile uint16_t packetCounter = 0;
unsigned long lastChannelSwitch = 0;
unsigned long lastUpdate = 0;
};
static SnifferGraph sniffer;
// ===== CALLBACK =====
void IRAM_ATTR snifferCallback(void *buf, wifi_promiscuous_pkt_type_t type)
{
if (type == WIFI_PKT_MGMT || type == WIFI_PKT_DATA || type == WIFI_PKT_CTRL)
{
sniffer.packetCounter++;
}
}
// ===== INIT =====
void wifi_analyzer_start()
{
// display init (safe to call again)
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_5x8_tr);
u8g2.drawStr(0, 10, "Starting analyzer...");
u8g2.sendBuffer();
// reset graph
memset(sniffer.graphData, 0, sizeof(sniffer.graphData));
sniffer.packetCounter = 0;
sniffer.currentChannel = 1;
// reset WiFi
WiFi.disconnect(true, true);
esp_wifi_stop();
delay(200);
esp_wifi_deinit();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);
esp_wifi_set_storage(WIFI_STORAGE_RAM);
esp_wifi_set_mode(WIFI_MODE_NULL);
esp_wifi_start();
esp_wifi_set_channel(sniffer.currentChannel, WIFI_SECOND_CHAN_NONE);
esp_wifi_set_promiscuous_rx_cb(snifferCallback);
esp_wifi_set_promiscuous(true);
}
// ===== HELPERS =====
static void switchChannel()
{
sniffer.currentChannel++;
if (sniffer.currentChannel > 13) sniffer.currentChannel = 1;
esp_wifi_set_channel(sniffer.currentChannel, WIFI_SECOND_CHAN_NONE);
}
static void updateGraph(uint8_t value)
{
for (int i = 0; i < MAX_POINTS - 1; i++)
{
sniffer.graphData[i] = sniffer.graphData[i + 1];
}
sniffer.graphData[MAX_POINTS - 1] = value;
}
static void drawGraph(uint16_t pktCount)
{
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_5x8_tr);
char line1[16];
char line2[16];
sprintf(line1, "Ch:%d", sniffer.currentChannel);
sprintf(line2, "Pkts:%d", pktCount * 5);
u8g2.drawStr(0, 8, line1);
u8g2.drawStr(60, 8, line2);
for (int x = 1; x < GRAPH_WIDTH; x++)
{
int y1 = GRAPH_TOP + GRAPH_HEIGHT - sniffer.graphData[x - 1];
int y2 = GRAPH_TOP + GRAPH_HEIGHT - sniffer.graphData[x];
u8g2.drawLine(x - 1, y1, x, y2);
}
if (pktCount >= SPIKE_THRESHOLD)
{
u8g2.drawVLine(GRAPH_WIDTH / 2, GRAPH_TOP, GRAPH_HEIGHT);
}
u8g2.sendBuffer();
}
// ===== LOOP =====
void wifi_analyzer_loop()
{
static uint32_t lastPress = 0;
unsigned long now = millis();
// channel hopping
if (now - sniffer.lastChannelSwitch >= 1000)
{
sniffer.lastChannelSwitch = now;
switchChannel();
}
// graph update
if (now - sniffer.lastUpdate >= 200)
{
sniffer.lastUpdate = now;
uint16_t pktCount = sniffer.packetCounter;
uint8_t scaled = pktCount * 2;
uint8_t value = min(scaled, (uint8_t)GRAPH_HEIGHT);
updateGraph(value);
drawGraph(pktCount);
sniffer.packetCounter = 0;
}
// optional: small debounce to not hammer CPU
if (millis() - lastPress < 10)
return;
}
|