orion-rf/firmware/wifi_analyzer.cpp

148 lines
3.3 KiB
C++

#include <Arduino.h>
#include <WiFi.h>
#include <esp_wifi.h>
#include "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;
}