T-DeckLoader/.pio/libdeps/esp32s3box/GFX Library for Arduino/examples/WiFiAnalyzer/PicoWiFiAnalyzerUTF8/PicoWiFiAnalyzerUTF8.ino
2024-06-09 01:14:09 -04:00

343 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Pico W WiFi Analyzer
* Require Raspberry Pi Pico W board support.
*/
#define SCAN_INTERVAL 3000
// #define SCAN_COUNT_SLEEP 3
/*******************************************************************************
* Start of Arduino_GFX setting
*
* Arduino_GFX try to find the settings depends on selected board in Arduino IDE
* Or you can define the display dev kit not in the board list
* Defalult pin list for non display dev kit:
* Arduino Nano, Micro and more: CS: 9, DC: 8, RST: 7, BL: 6, SCK: 13, MOSI: 11, MISO: 12
* ESP32 various dev board : CS: 5, DC: 27, RST: 33, BL: 22, SCK: 18, MOSI: 23, MISO: nil
* ESP32-C3 various dev board : CS: 7, DC: 2, RST: 1, BL: 3, SCK: 4, MOSI: 6, MISO: nil
* ESP32-S2 various dev board : CS: 34, DC: 38, RST: 33, BL: 21, SCK: 36, MOSI: 35, MISO: nil
* ESP32-S3 various dev board : CS: 40, DC: 41, RST: 42, BL: 48, SCK: 36, MOSI: 35, MISO: nil
* ESP8266 various dev board : CS: 15, DC: 4, RST: 2, BL: 5, SCK: 14, MOSI: 13, MISO: 12
* Raspberry Pi Pico dev board : CS: 17, DC: 27, RST: 26, BL: 28, SCK: 18, MOSI: 19, MISO: 16
* RTL8720 BW16 old patch core : CS: 18, DC: 17, RST: 2, BL: 23, SCK: 19, MOSI: 21, MISO: 20
* RTL8720_BW16 Official core : CS: 9, DC: 8, RST: 6, BL: 3, SCK: 10, MOSI: 12, MISO: 11
* RTL8722 dev board : CS: 18, DC: 17, RST: 22, BL: 23, SCK: 13, MOSI: 11, MISO: 12
* RTL8722_mini dev board : CS: 12, DC: 14, RST: 15, BL: 13, SCK: 11, MOSI: 9, MISO: 10
* Seeeduino XIAO dev board : CS: 3, DC: 2, RST: 1, BL: 0, SCK: 8, MOSI: 10, MISO: 9
* Teensy 4.1 dev board : CS: 39, DC: 41, RST: 40, BL: 22, SCK: 13, MOSI: 11, MISO: 12
******************************************************************************/
#include <U8g2lib.h>
#include <Arduino_GFX_Library.h>
#define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin
/* More dev device declaration: https://github.com/moononournation/Arduino_GFX/wiki/Dev-Device-Declaration */
#if defined(DISPLAY_DEV_KIT)
Arduino_GFX *gfx = create_default_Arduino_GFX();
#else /* !defined(DISPLAY_DEV_KIT) */
/* More data bus class: https://github.com/moononournation/Arduino_GFX/wiki/Data-Bus-Class */
Arduino_DataBus *bus = create_default_Arduino_DataBus();
/* More display class: https://github.com/moononournation/Arduino_GFX/wiki/Display-Class */
Arduino_GFX *gfx = new Arduino_ILI9341(bus, DF_GFX_RST, 3 /* rotation */, false /* IPS */);
#endif /* !defined(DISPLAY_DEV_KIT) */
/*******************************************************************************
* End of Arduino_GFX setting
******************************************************************************/
#include "WiFi.h"
#define log_i(format, ...) Serial.printf(format, ##__VA_ARGS__)
int16_t w, h, text_size, banner_height, graph_baseline, graph_height, channel_width, signal_width;
// RSSI RANGE
#define RSSI_CEILING -40
#define RSSI_FLOOR -100
// Channel color mapping from channel 1 to 14
uint16_t channel_color[] = {
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA};
uint8_t scan_count = 0;
void setup()
{
Serial.begin(115200);
// Serial.setDebugOutput(true);
// while(!Serial);
Serial.println("Arduino_GFX Pico WiFi Analyzer UTF8 example");
// Set WiFi to station mode and disconnect from an AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
#ifdef GFX_EXTRA_PRE_INIT
GFX_EXTRA_PRE_INIT();
#endif
#ifdef GFX_BL
pinMode(GFX_BL, OUTPUT);
digitalWrite(GFX_BL, HIGH);
#endif
// Init Display
if (!gfx->begin())
{
Serial.println("gfx->begin() failed!");
}
gfx->setUTF8Print(true); // enable UTF8 support for the Arduino print() function
gfx->setFont(u8g2_font_unifont_t_cjk);
w = gfx->width();
h = gfx->height();
text_size = (w < 224) ? 1 : 2;
banner_height = text_size * 16;
graph_baseline = h - (2 * 16); // minus 2 text lines
graph_height = graph_baseline - banner_height - (2 * 16); // minus 2 text lines
channel_width = w / 17;
signal_width = channel_width * 2;
// init banner
gfx->setTextSize(text_size);
gfx->fillScreen(BLACK);
gfx->setTextColor(MAGENTA);
gfx->setCursor(0, 28);
gfx->print("Pico W");
gfx->setTextColor(WHITE);
gfx->print(" WiFi分析儀");
}
bool matchBssidPrefix(uint8_t *a, uint8_t *b)
{
for (uint8_t i = 0; i < 5; i++)
{ // only compare first 5 bytes
if (a[i] != b[i])
{
return false;
}
}
return true;
}
void loop()
{
uint8_t ap_count_list[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int32_t noise_list[] = {RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR};
int32_t peak_list[] = {RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR, RSSI_FLOOR};
int16_t peak_id_list[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
int32_t channel;
int16_t idx;
int32_t rssi;
uint8_t bssidA[6];
uint8_t bssidB[6];
String ssid;
uint16_t color;
int16_t height, offset, text_width;
// WiFi.scanNetworks will return the number of networks found
int n = WiFi.scanNetworks();
// clear old graph
gfx->fillRect(0, banner_height, w, h - banner_height, BLACK);
gfx->setTextSize(1);
if (n == 0)
{
gfx->setTextColor(WHITE);
gfx->setCursor(0, banner_height + 14);
gfx->println("找不到WiFi");
}
else
{
for (int i = 0; i < n; i++)
{
channel = WiFi.channel(i);
idx = channel - 1;
rssi = WiFi.RSSI(i);
WiFi.BSSID(i, bssidA);
// channel peak stat
if (peak_list[idx] < rssi)
{
peak_list[idx] = rssi;
peak_id_list[idx] = i;
}
// check signal come from same AP
bool duplicate_SSID = false;
for (int j = 0; j < i; j++)
{
if ((WiFi.channel(j) == channel) && matchBssidPrefix(WiFi.BSSID(j, bssidB), bssidA))
{
duplicate_SSID = true;
break;
}
}
if (!duplicate_SSID)
{
ap_count_list[idx]++;
// noise stat
int32_t noise = rssi - RSSI_FLOOR;
noise *= noise;
if (channel > 4)
{
noise_list[idx - 4] += noise;
}
if (channel > 3)
{
noise_list[idx - 3] += noise;
}
if (channel > 2)
{
noise_list[idx - 2] += noise;
}
if (channel > 1)
{
noise_list[idx - 1] += noise;
}
noise_list[idx] += noise;
if (channel < 14)
{
noise_list[idx + 1] += noise;
}
if (channel < 13)
{
noise_list[idx + 2] += noise;
}
if (channel < 12)
{
noise_list[idx + 3] += noise;
}
if (channel < 11)
{
noise_list[idx + 4] += noise;
}
}
}
// plot found WiFi info
for (int i = 0; i < n; i++)
{
channel = WiFi.channel(i);
idx = channel - 1;
rssi = WiFi.RSSI(i);
color = channel_color[idx];
height = constrain(map(rssi, RSSI_FLOOR, RSSI_CEILING, 1, graph_height), 1, graph_height);
offset = (channel + 1) * channel_width;
// trim rssi with RSSI_FLOOR
if (rssi < RSSI_FLOOR)
{
rssi = RSSI_FLOOR;
}
// plot chart
// gfx->drawLine(offset, graph_baseline - height, offset - signal_width, graph_baseline + 1, color);
// gfx->drawLine(offset, graph_baseline - height, offset + signal_width, graph_baseline + 1, color);
gfx->startWrite();
gfx->writeEllipseHelper(offset, graph_baseline + 1, signal_width, height, 0b0011, color);
gfx->endWrite();
if (i == peak_id_list[idx])
{
// Print SSID, signal strengh and if not encrypted
String ssid = WiFi.SSID(i);
if (ssid.length() == 0)
{
WiFi.BSSID(i, bssidA);
// bssidA to ssid
char mac[18] = {0};
sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", bssidA[0], bssidA[1], bssidA[2], bssidA[3], bssidA[4], bssidA[5]);
ssid = String(mac);
}
text_width = (ssid.length() + 6) * 8;
if (text_width > w)
{
offset = 0;
}
else
{
offset -= signal_width;
if ((offset + text_width) > w)
{
offset = w - text_width;
}
}
gfx->setTextColor(color);
gfx->setCursor(offset, graph_baseline - height - 2);
gfx->print(ssid);
gfx->print('(');
gfx->print(rssi);
gfx->print(')');
if (WiFi.encryptionType(i) == ENC_TYPE_NONE)
{
gfx->print('*');
}
}
}
}
// print WiFi stat
gfx->setTextColor(WHITE);
gfx->setCursor(0, banner_height + 14);
gfx->print("找到");
gfx->print(n);
gfx->print("個WiFi訊噪比較好");
bool listed_first_channel = false;
int32_t min_noise = noise_list[0]; // init with channel 1 value
for (channel = 2; channel <= 11; channel++) // channels 12-14 may not available
{
idx = channel - 1;
log_i("min_noise: %d, noise_list[%d]: %d", min_noise, idx, noise_list[idx]);
if (noise_list[idx] < min_noise)
{
min_noise = noise_list[idx];
}
}
for (channel = 1; channel <= 11; channel++) // channels 12-14 may not available
{
idx = channel - 1;
// check channel with min noise
if (noise_list[idx] == min_noise)
{
if (!listed_first_channel)
{
listed_first_channel = true;
}
else
{
gfx->print(", ");
}
gfx->print(channel);
}
}
// draw graph base axle
gfx->drawFastHLine(0, graph_baseline, 320, WHITE);
for (channel = 1; channel <= 14; channel++)
{
idx = channel - 1;
offset = (channel + 1) * channel_width;
gfx->setTextColor(channel_color[idx]);
gfx->setCursor(offset - ((channel < 10) ? 4 : 8), graph_baseline + 14);
gfx->print(channel);
if (ap_count_list[idx] > 0)
{
gfx->setCursor(offset - ((ap_count_list[idx] < 10) ? 12 : 16), graph_baseline + 16 + 14);
gfx->print('{');
gfx->print(ap_count_list[idx]);
gfx->print('}');
}
}
// Wait a bit before scanning again
delay(SCAN_INTERVAL);
}