Initial commit

This commit is contained in:
2026-03-31 13:17:21 +02:00
commit 7eeecff042
6821 changed files with 3514215 additions and 0 deletions

View File

@@ -0,0 +1,362 @@
/*
* ESP WiFi Analyzer
* Require ESP8266/ESP32 board support.
*/
// POWER SAVING SETTING
#define SCAN_INTERVAL 3000
// #define SCAN_COUNT_SLEEP 3
// #define LCD_PWR_PIN 14
/*******************************************************************************
* 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: 35, 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 <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
******************************************************************************/
#if defined(ESP32)
#include "WiFi.h"
#else
#include "ESP8266WiFi.h"
#define log_i(format, ...) Serial.printf(format, ##__VA_ARGS__)
#endif
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);
// Set WiFi to station mode and disconnect from an AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
#if defined(LCD_PWR_PIN)
pinMode(LCD_PWR_PIN, OUTPUT); // sets the pin as output
digitalWrite(LCD_PWR_PIN, HIGH); // power on
#endif
#ifdef GFX_BL
pinMode(GFX_BL, OUTPUT);
digitalWrite(GFX_BL, HIGH);
#endif
// init LCD
gfx->begin();
w = gfx->width();
h = gfx->height();
text_size = (h < 200) ? 1 : 2;
banner_height = text_size * 3 * 4;
graph_baseline = h - 20; // minus 2 text lines
graph_height = graph_baseline - banner_height - 30; // minus 3 text lines
channel_width = w / 17;
signal_width = channel_width * 2;
// init banner
gfx->setTextSize(text_size);
gfx->fillScreen(BLACK);
gfx->setTextColor(RED);
gfx->setCursor(0, 0);
gfx->print("ESP");
gfx->setTextColor(WHITE);
gfx->print(" WiFi Analyzer");
}
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 *bssid;
String ssid;
uint16_t color;
int16_t height, offset, text_width;
// WiFi.scanNetworks will return the number of networks found
#if defined(ESP32)
int n = WiFi.scanNetworks(false /* async */, true /* show_hidden */, true /* passive */, 500 /* max_ms_per_chan */);
#else
int n = WiFi.scanNetworks(false /* async */, true /* show_hidden */);
#endif
// 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);
gfx->println("no networks found");
}
else
{
for (int i = 0; i < n; i++)
{
channel = WiFi.channel(i);
idx = channel - 1;
rssi = WiFi.RSSI(i);
bssid = WiFi.BSSID(i);
// 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), bssid))
{
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->drawEllipseHelper(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)
{
ssid = WiFi.BSSIDstr(i);
}
text_width = (ssid.length() + 6) * 6;
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 - 10 - height);
gfx->print(ssid);
gfx->print('(');
gfx->print(rssi);
gfx->print(')');
#if defined(ESP32)
if (WiFi.encryptionType(i) == WIFI_AUTH_OPEN)
#else
if (WiFi.encryptionType(i) == ENC_TYPE_NONE)
#endif
{
gfx->print('*');
}
}
}
}
// print WiFi stat
gfx->setTextColor(WHITE);
gfx->setCursor(0, banner_height);
gfx->print(n);
gfx->print(" networks found, lesser noise channels: ");
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) ? 3 : 6), graph_baseline + 2);
gfx->print(channel);
if (ap_count_list[idx] > 0)
{
gfx->setCursor(offset - ((ap_count_list[idx] < 10) ? 9 : 12), graph_baseline + 8 + 2);
gfx->print('{');
gfx->print(ap_count_list[idx]);
gfx->print('}');
}
}
// Wait a bit before scanning again
delay(SCAN_INTERVAL);
#if defined(SCAN_COUNT_SLEEP)
// POWER SAVING
if (++scan_count >= SCAN_COUNT_SLEEP)
{
#if defined(LCD_PWR_PIN)
pinMode(LCD_PWR_PIN, INPUT); // disable pin
#endif
#if defined(GFX_BL)
pinMode(GFX_BL, INPUT); // disable pin
#endif
#if defined(ESP32)
esp_sleep_enable_ext0_wakeup(GPIO_NUM_36, LOW);
esp_deep_sleep_start();
#else
ESP.deepSleep(0);
#endif
}
#endif // defined(SCAN_COUNT_SLEEP)
}

View File

@@ -0,0 +1,367 @@
/*
* ESP WiFi Analyzer
* Require ESP8266/ESP32 board support.
*/
// POWER SAVING SETTING
#define SCAN_INTERVAL 3000
// #define SCAN_COUNT_SLEEP 3
// #define LCD_PWR_PIN 14
/*******************************************************************************
* 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: 35, 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
******************************************************************************/
#if defined(ESP32)
#include "WiFi.h"
#else
#include "ESP8266WiFi.h"
#define log_i(format, ...) Serial.printf(format, ##__VA_ARGS__)
#endif
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);
// Set WiFi to station mode and disconnect from an AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
#if defined(LCD_PWR_PIN)
pinMode(LCD_PWR_PIN, OUTPUT); // sets the pin as output
digitalWrite(LCD_PWR_PIN, HIGH); // power on
#endif
#ifdef GFX_BL
pinMode(GFX_BL, OUTPUT);
digitalWrite(GFX_BL, HIGH);
#endif
// init LCD
gfx->begin();
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(RED);
gfx->setCursor(0, 28);
gfx->print("ESP");
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 *bssid;
String ssid;
uint16_t color;
int16_t height, offset, text_width;
// WiFi.scanNetworks will return the number of networks found
#if defined(ESP32)
int n = WiFi.scanNetworks(false /* async */, true /* show_hidden */, true /* passive */, 500 /* max_ms_per_chan */);
#else
int n = WiFi.scanNetworks(false /* async */, true /* show_hidden */);
#endif
// 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);
bssid = WiFi.BSSID(i);
// 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), bssid))
{
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->drawEllipseHelper(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)
{
ssid = WiFi.BSSIDstr(i);
}
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 defined(ESP32)
if (WiFi.encryptionType(i) == WIFI_AUTH_OPEN)
#else
if (WiFi.encryptionType(i) == ENC_TYPE_NONE)
#endif
{
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);
#if defined(SCAN_COUNT_SLEEP)
// POWER SAVING
if (++scan_count >= SCAN_COUNT_SLEEP)
{
#if defined(LCD_PWR_PIN)
pinMode(LCD_PWR_PIN, INPUT); // disable pin
#endif
#if defined(GFX_BL)
pinMode(GFX_BL, INPUT); // disable pin
#endif
#if defined(ESP32)
esp_sleep_enable_ext0_wakeup(GPIO_NUM_36, LOW);
esp_deep_sleep_start();
#else
ESP.deepSleep(0);
#endif
}
#endif // defined(SCAN_COUNT_SLEEP)
}

View File

@@ -0,0 +1,327 @@
/*
* 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: 35, 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 <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);
// 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_BL
pinMode(GFX_BL, OUTPUT);
digitalWrite(GFX_BL, HIGH);
#endif
// init LCD
gfx->begin();
w = gfx->width();
h = gfx->height();
text_size = (h < 200) ? 1 : 2;
banner_height = text_size * 3 * 4;
graph_baseline = h - 20; // minus 2 text lines
graph_height = graph_baseline - banner_height - 30; // minus 3 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, 0);
gfx->print("Pico W");
gfx->setTextColor(WHITE);
gfx->print(" WiFi Analyzer");
}
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);
gfx->println("no networks found");
}
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->drawEllipseHelper(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) * 6;
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 - 10 - height);
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);
gfx->print(n);
gfx->print(" networks found, lesser noise channels: ");
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) ? 3 : 6), graph_baseline + 2);
gfx->print(channel);
if (ap_count_list[idx] > 0)
{
gfx->setCursor(offset - ((ap_count_list[idx] < 10) ? 9 : 12), graph_baseline + 8 + 2);
gfx->print('{');
gfx->print(ap_count_list[idx]);
gfx->print('}');
}
}
// Wait a bit before scanning again
delay(SCAN_INTERVAL);
}

View File

@@ -0,0 +1,332 @@
/*
* 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: 35, 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);
// 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_BL
pinMode(GFX_BL, OUTPUT);
digitalWrite(GFX_BL, HIGH);
#endif
// init LCD
gfx->begin();
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->drawEllipseHelper(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);
}

View File

@@ -0,0 +1,341 @@
/*******************************************************************************
* Rtl WiFi Analyzer
* For RTL872x only.
*
* Add realtek ameba core support to Arduino IDE:
* https://github.com/ambiot/ambd_arduino
*
* Old patch realtek ameba core variant.cpp to RTL8720DN pinout:
* https://github.com/mikey60/BW16-RTL8720DN-Module-Arduino
*
* Defalult pin list for non display dev kit:
* RTL8720 BW16 old patch core : CS: 18, DC: 17, RST: 2, BL: 23
* RTL8720_BW16 Official core : CS: 9, DC: 8, RST: 6, BL: 3
* RTL8722 dev board : CS: 18, DC: 17, RST: 22, BL: 23
* RTL8722_mini dev board : CS: 12, DC: 14, RST: 15, BL: 13
******************************************************************************/
#define SCAN_INTERVAL 3000
#include <lwip_netconf.h>
#include <wifi_conf.h>
#include <wifi_constants.h>
#include <wifi_structures.h>
#include <wl_definitions.h>
#include <wl_types.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
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 */);
static int16_t w, h, text_size, banner_height, graph24_baseline, graph50_baseline, graph_baseline, graph_height, channel24_width, channel50_width, channel_width, signal_width;
// RSSI RANGE
#define RSSI_CEILING -40
#define RSSI_FLOOR -100
// Channel legend mapping
static uint16_t channel_legend[] = {
1, 2, 3, 4, 5, 6, 7, // 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, // 8, 9, 10, 11, 12, 13, 14,
32, 0, 0, 0, 40, 0, 0, // 32, 34, 36, 38, 40, 42, 44,
0, 48, 0, 0, 0, 56, 0, // 46, 48, 50, 52, 54, 56, 58,
0, 0, 64, 0, 0, 0, // 60, 62, 64, 68,N/A, 96,
100, 0, 0, 0, 108, 0, 0, //100,102,104,106,108,110,112,
0, 116, 0, 0, 0, 124, 0, //114,116,118,120,122,124,126,
0, 0, 132, 0, 0, 0, 140, //128,N/A,132,134,136,138,140,
0, 0, 0, 149, 0, 0, 0, //142,144,N/A,149,151,153,155,
157, 0, 0, 0, 165, 0, 0, //157,159,161,163,165,167,169,
0, 173}; //171,173
// Channel color mapping
static uint16_t channel_color[] = {
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, WHITE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE};
static uint16_t channelIdx(int channel)
{
if (channel <= 14) // 2.4 GHz, channel 1-14
{
return channel - 1;
}
if (channel <= 64) // 5 GHz, channel 32 - 64
{
return 14 + ((channel - 32) / 2);
}
if (channel == 68)
{
return 31;
}
if (channel == 96)
{
return 33;
}
if (channel <= 144) // channel 98 - 144
{
return 34 + ((channel - 100) / 2);
}
// channel 149 - 177
return 58 + ((channel - 149) / 2);
}
static uint8_t _networkCount;
static char _networkSsid[WL_NETWORKS_LIST_MAXNUM][WL_SSID_MAX_LENGTH];
static int32_t _networkRssi[WL_NETWORKS_LIST_MAXNUM];
static uint32_t _networkEncr[WL_NETWORKS_LIST_MAXNUM];
static uint8_t _networkChannel[WL_NETWORKS_LIST_MAXNUM];
static char _networkMac[WL_NETWORKS_LIST_MAXNUM][18];
static rtw_result_t wifidrv_scan_result_handler(rtw_scan_handler_result_t *malloced_scan_result)
{
rtw_scan_result_t *record;
if (malloced_scan_result->scan_complete != RTW_TRUE)
{
record = &malloced_scan_result->ap_details;
record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */
if (_networkCount < WL_NETWORKS_LIST_MAXNUM)
{
strcpy(_networkSsid[_networkCount], (char *)record->SSID.val);
_networkRssi[_networkCount] = record->signal_strength;
_networkEncr[_networkCount] = record->security;
_networkChannel[_networkCount] = record->channel;
sprintf(_networkMac[_networkCount], "%02X:%02X:%02X:%02X:%02X:%02X",
record->BSSID.octet[0], record->BSSID.octet[1], record->BSSID.octet[2],
record->BSSID.octet[3], record->BSSID.octet[4], record->BSSID.octet[5]);
_networkCount++;
}
}
return RTW_SUCCESS;
}
static int8_t scanNetworks()
{
uint8_t attempts = 10;
_networkCount = 0;
if (wifi_scan_networks(wifidrv_scan_result_handler, NULL) != RTW_SUCCESS)
{
return WL_FAILURE;
}
do
{
delay(SCAN_INTERVAL);
} while ((_networkCount == 0) && (--attempts > 0));
return _networkCount;
}
void setup()
{
LwIP_Init();
wifi_on(RTW_MODE_STA);
#if defined(LCD_PWR_PIN)
pinMode(LCD_PWR_PIN, OUTPUT); // sets the pin as output
digitalWrite(LCD_PWR_PIN, HIGH); // power on
#endif
#ifdef GFX_BL
pinMode(GFX_BL, OUTPUT);
digitalWrite(GFX_BL, HIGH);
#endif
// init LCD
gfx->begin();
w = gfx->width();
h = gfx->height();
text_size = (h < 200) ? 1 : 2;
banner_height = (text_size * 8) + 4;
graph_height = ((gfx->height() - banner_height) / 2) - 30;
graph24_baseline = banner_height + graph_height + 10;
graph50_baseline = graph24_baseline + graph_height + 30;
channel24_width = w / 17;
channel50_width = w / 62;
// direct draw banner to output display
gfx->setTextSize(text_size);
gfx->fillScreen(BLACK);
gfx->setTextColor(GREEN);
gfx->setCursor(2, 2);
gfx->print("RTL");
gfx->setTextColor(WHITE);
gfx->print(" WiFi Analyzer");
}
void loop()
{
uint8_t ap_count_list[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
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, 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, 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, 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, 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, RSSI_FLOOR};
int16_t peak_id_list[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
int32_t channel;
uint16_t idx;
int32_t rssi;
String ssid;
uint16_t color;
int16_t height, offset, text_width;
int n = 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);
gfx->println("No networks found");
}
else
{
for (int i = 0; i < n; i++)
{
channel = _networkChannel[i];
idx = channelIdx(channel);
rssi = _networkRssi[i];
// channel peak stat
if (peak_list[idx] < rssi)
{
peak_list[idx] = rssi;
peak_id_list[idx] = i;
}
ap_count_list[idx]++;
}
// plot found WiFi info
for (int i = 0; i < n; i++)
{
channel = _networkChannel[i];
idx = channelIdx(channel);
rssi = _networkRssi[i];
color = channel_color[idx];
height = constrain(map(rssi, RSSI_FLOOR, RSSI_CEILING, 1, graph_height), 1, graph_height);
if (idx < 14)
{
graph_baseline = graph24_baseline;
channel_width = channel24_width;
signal_width = channel24_width * 2;
offset = (idx + 2) * channel24_width;
}
else
{
graph_baseline = graph50_baseline;
channel_width = channel50_width;
signal_width = channel50_width * 2;
offset = (idx - 14 + 2) * channel50_width;
}
// trim rssi with RSSI_FLOOR
if (rssi < RSSI_FLOOR)
{
rssi = RSSI_FLOOR;
}
// plot chart
gfx->startWrite();
gfx->drawEllipseHelper(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 = _networkSsid[i];
if (ssid.length() == 0)
{
ssid = _networkMac[i];
}
text_width = (ssid.length() + 6) * 6;
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 - 10 - height);
gfx->print(ssid);
gfx->print('(');
gfx->print(rssi);
gfx->print(')');
if (_networkEncr[i] == RTW_SECURITY_OPEN)
{
gfx->print('*');
}
}
}
}
// print WiFi found
gfx->setTextColor(WHITE);
gfx->setCursor(2, banner_height);
gfx->print(n);
gfx->print(" networks");
// draw 2.4 GHz graph base axle
gfx->drawFastHLine(0, graph24_baseline, 320, WHITE);
for (idx = 0; idx < 14; idx++)
{
channel = channel_legend[idx];
offset = (idx + 2) * channel24_width;
if (channel > 0)
{
gfx->setTextColor(channel_color[idx]);
gfx->setCursor(offset - ((channel < 10) ? 3 : 6), graph24_baseline + 2);
gfx->print(channel);
}
if (ap_count_list[idx] > 0)
{
gfx->setTextColor(LIGHTGREY);
gfx->setCursor(offset - ((ap_count_list[idx] < 10) ? 3 : 6), graph24_baseline + 8 + 2);
gfx->print(ap_count_list[idx]);
}
}
// draw 5 GHz graph base axle
gfx->drawFastHLine(0, graph50_baseline, 320, WHITE);
for (idx = 14; idx < 71; idx++)
{
channel = channel_legend[idx];
offset = (idx - 14 + 2) * channel50_width;
if (channel > 0)
{
gfx->setTextColor(channel_color[idx]);
gfx->setCursor(offset - ((channel < 100) ? 6 : 9), graph50_baseline + 2);
gfx->print(channel);
}
if (ap_count_list[idx] > 0)
{
gfx->setTextColor(DARKGREY);
gfx->setCursor(offset - ((ap_count_list[idx] < 10) ? 3 : 6), graph50_baseline + 8 + 2);
gfx->print(ap_count_list[idx]);
}
}
// Wait a bit before scanning again
delay(SCAN_INTERVAL);
}

View File

@@ -0,0 +1,338 @@
/*******************************************************************************
* Rtl WiFi Analyzer
* For RTL872x only.
*
* Add realtek ameba core support to Arduino IDE:
* https://github.com/ambiot/ambd_arduino
*
* Old patch realtek ameba core variant.cpp to RTL8720DN pinout:
* https://github.com/mikey60/BW16-RTL8720DN-Module-Arduino
*
* Defalult pin list for non display dev kit:
* RTL8720 BW16 old patch core : CS: 18, DC: 17, RST: 2, BL: 23
* RTL8720_BW16 Official core : CS: 9, DC: 8, RST: 6, BL: 3
* RTL8722 dev board : CS: 18, DC: 17, RST: 22, BL: 23
* RTL8722_mini dev board : CS: 12, DC: 14, RST: 15, BL: 13
******************************************************************************/
#define SCAN_INTERVAL 3000
#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 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 */);
#include <lwip_netconf.h>
#include <wifi_conf.h>
#include <wifi_constants.h>
#include <wifi_structures.h>
#include <wl_definitions.h>
#include <wl_types.h>
int16_t w, h, text_size, banner_height, graph24_baseline, graph50_baseline, graph_baseline, graph_height, channel24_width, channel50_width, channel_width, signal_width;
// RSSI RANGE
#define RSSI_CEILING -40
#define RSSI_FLOOR -100
// Channel legend mapping
uint16_t channel_legend[] = {
1, 2, 3, 4, 5, 6, 7, // 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, // 8, 9, 10, 11, 12, 13, 14,
32, 0, 0, 0, 40, 0, 0, // 32, 34, 36, 38, 40, 42, 44,
0, 48, 0, 0, 0, 56, 0, // 46, 48, 50, 52, 54, 56, 58,
0, 0, 64, 0, 0, 0, // 60, 62, 64, 68,N/A, 96,
100, 0, 0, 0, 108, 0, 0, //100,102,104,106,108,110,112,
0, 116, 0, 0, 0, 124, 0, //114,116,118,120,122,124,126,
0, 0, 132, 0, 0, 0, 140, //128,N/A,132,134,136,138,140,
0, 0, 0, 149, 0, 0, 0, //142,144,N/A,149,151,153,155,
157, 0, 0, 0, 165, 0, 0, //157,159,161,163,165,167,169,
0, 173}; //171,173
// Channel color mapping
uint16_t channel_color[] = {
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, WHITE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE};
uint16_t channelIdx(int channel)
{
if (channel <= 14) // 2.4 GHz, channel 1-14
{
return channel - 1;
}
if (channel <= 64) // 5 GHz, channel 32 - 64
{
return 14 + ((channel - 32) / 2);
}
if (channel == 68)
{
return 31;
}
if (channel == 96)
{
return 33;
}
if (channel <= 144) // channel 98 - 144
{
return 34 + ((channel - 100) / 2);
}
// channel 149 - 177
return 58 + ((channel - 149) / 2);
}
uint8_t _networkCount;
char _networkSsid[WL_NETWORKS_LIST_MAXNUM][WL_SSID_MAX_LENGTH];
int32_t _networkRssi[WL_NETWORKS_LIST_MAXNUM];
uint32_t _networkEncr[WL_NETWORKS_LIST_MAXNUM];
uint8_t _networkChannel[WL_NETWORKS_LIST_MAXNUM];
char _networkMac[WL_NETWORKS_LIST_MAXNUM][18];
rtw_result_t wifidrv_scan_result_handler(rtw_scan_handler_result_t *malloced_scan_result)
{
rtw_scan_result_t *record;
if (malloced_scan_result->scan_complete != RTW_TRUE)
{
record = &malloced_scan_result->ap_details;
record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */
if (_networkCount < WL_NETWORKS_LIST_MAXNUM)
{
strcpy(_networkSsid[_networkCount], (char *)record->SSID.val);
_networkRssi[_networkCount] = record->signal_strength;
_networkEncr[_networkCount] = record->security;
_networkChannel[_networkCount] = record->channel;
sprintf(_networkMac[_networkCount], "%02X:%02X:%02X:%02X:%02X:%02X",
record->BSSID.octet[0], record->BSSID.octet[1], record->BSSID.octet[2],
record->BSSID.octet[3], record->BSSID.octet[4], record->BSSID.octet[5]);
_networkCount++;
}
}
return RTW_SUCCESS;
}
int8_t scanNetworks()
{
uint8_t attempts = 10;
_networkCount = 0;
if (wifi_scan_networks(wifidrv_scan_result_handler, NULL) != RTW_SUCCESS)
{
return WL_FAILURE;
}
do
{
delay(SCAN_INTERVAL);
} while ((_networkCount == 0) && (--attempts > 0));
return _networkCount;
}
void setup()
{
LwIP_Init();
wifi_on(RTW_MODE_STA);
#if defined(LCD_PWR_PIN)
pinMode(LCD_PWR_PIN, OUTPUT); // sets the pin as output
digitalWrite(LCD_PWR_PIN, HIGH); // power on
#endif
#ifdef GFX_BL
pinMode(GFX_BL, OUTPUT);
digitalWrite(GFX_BL, HIGH);
#endif
// init LCD
gfx->begin();
gfx->setUTF8Print(true); // enable UTF8 support for the Arduino print() function
gfx->setFont(u8g2_font_unifont_t_chinese);
w = gfx->width();
h = gfx->height();
banner_height = 16;
graph_height = ((gfx->height() - banner_height) / 2) - (3 * 16);
graph24_baseline = banner_height + graph_height + 16;
graph50_baseline = graph24_baseline + graph_height + (3 * 16);
channel24_width = w / 17;
channel50_width = w / 62;
// direct draw banner to output display
gfx->fillScreen(BLACK);
gfx->setTextColor(GREEN);
gfx->setCursor(0, 14);
gfx->print("RTL");
gfx->setTextColor(WHITE);
gfx->print(" WiFi分析儀");
}
void loop()
{
uint8_t ap_count_list[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
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, 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, 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, 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, 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, RSSI_FLOOR};
int16_t peak_id_list[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
int32_t channel;
int16_t idx;
int32_t rssi;
String ssid;
uint16_t color;
int16_t height, offset, text_width;
int n = scanNetworks();
// clear old graph
gfx->fillRect(0, banner_height, w, h - banner_height, BLACK);
if (n == 0)
{
gfx->setTextColor(WHITE);
gfx->setCursor(0, banner_height + 14);
gfx->println("找不到WiFi");
}
else
{
for (int i = 0; i < n; i++)
{
channel = _networkChannel[i];
idx = channelIdx(channel);
rssi = _networkRssi[i];
// channel peak stat
if (peak_list[idx] < rssi)
{
peak_list[idx] = rssi;
peak_id_list[idx] = i;
}
ap_count_list[idx]++;
}
// plot found WiFi info
for (int i = 0; i < n; i++)
{
channel = _networkChannel[i];
idx = channelIdx(channel);
rssi = _networkRssi[i];
color = channel_color[idx];
height = constrain(map(rssi, RSSI_FLOOR, RSSI_CEILING, 1, graph_height), 1, graph_height);
if (idx < 14)
{
graph_baseline = graph24_baseline;
channel_width = channel24_width;
signal_width = channel24_width * 2;
offset = (idx + 2) * channel24_width;
}
else
{
graph_baseline = graph50_baseline;
channel_width = channel50_width;
signal_width = channel50_width * 2;
offset = (idx - 14 + 2) * channel50_width;
}
// trim rssi with RSSI_FLOOR
if (rssi < RSSI_FLOOR)
{
rssi = RSSI_FLOOR;
}
// plot chart
gfx->startWrite();
gfx->drawEllipseHelper(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 = _networkSsid[i];
if (ssid.length() == 0)
{
ssid = _networkMac[i];
}
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 (_networkEncr[i] == RTW_SECURITY_OPEN)
{
gfx->print('*');
}
}
}
}
// draw 2.4 GHz graph base axle
gfx->drawFastHLine(0, graph24_baseline, 320, WHITE);
for (idx = 0; idx < 14; idx++)
{
channel = channel_legend[idx];
offset = (idx + 2) * channel24_width;
if (channel > 0)
{
gfx->setTextColor(channel_color[idx]);
gfx->setCursor(offset - ((channel < 10) ? 4 : 8), graph24_baseline + 14);
gfx->print(channel);
}
if (ap_count_list[idx] > 0)
{
gfx->setTextColor(LIGHTGREY);
gfx->setCursor(offset - ((ap_count_list[idx] < 10) ? 4 : 8), graph24_baseline + 16 + 14);
gfx->print(ap_count_list[idx]);
}
}
// draw 5 GHz graph base axle
gfx->drawFastHLine(0, graph50_baseline, 320, WHITE);
for (idx = 14; idx < 71; idx++)
{
channel = channel_legend[idx];
offset = (idx - 14 + 2) * channel50_width;
if (channel > 0)
{
gfx->setTextColor(channel_color[idx]);
gfx->setCursor(offset - ((channel < 100) ? 8 : 12), graph50_baseline + 14);
gfx->print(channel);
}
if (ap_count_list[idx] > 0)
{
gfx->setTextColor(DARKGREY);
gfx->setCursor(offset - ((ap_count_list[idx] < 10) ? 4 : 8), graph50_baseline + 16 + 14);
gfx->print(ap_count_list[idx]);
}
}
// Wait a bit before scanning again
delay(SCAN_INTERVAL);
}

View File

@@ -0,0 +1,300 @@
/*
* Wio WiFi Analyzer
* Require Wio Terminal.
*
* Libraries:
* https://github.com/Seeed-Studio/Seeed_Arduino_FS/releases/tag/v2.0.2
* https://github.com/Seeed-Studio/Seeed_Arduino_SFUD/releases/tag/v2.0.1
* https://github.com/Seeed-Studio/Seeed_Arduino_mbedtls/archive/d1ca0175e24768120781bf4a43a1fb2c39fce85f.zip
* https://github.com/Seeed-Studio/Seeed_Arduino_rpcUnified/releases/tag/v2.1.1
* https://github.com/Seeed-Studio/Seeed_Arduino_rpcWiFi/releases/tag/v1.0.2
*
* Firmware:
* https://github.com/Seeed-Studio/seeed-ambd-firmware/releases/tag/v2.1.1
*/
#define SCAN_INTERVAL 1000
#include <Arduino_GFX_Library.h>
#define GFX_BL DF_GFX_BL // default backlight pin, you may replace DF_GFX_BL to actual backlight pin
Arduino_GFX *gfx = create_default_Arduino_GFX();
#include "rpcWiFi.h"
int16_t w, h, text_size, banner_height, graph24_baseline, graph50_baseline, graph_baseline, graph_height, channel24_width, channel50_width, channel_width, signal_width;
// RSSI RANGE
#define RSSI_CEILING -40
#define RSSI_FLOOR -100
// Channel legend mapping
uint16_t channel_legend[] = {
1, 2, 3, 4, 5, 6, 7, // 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, // 8, 9, 10, 11, 12, 13, 14,
32, 0, 0, 0, 40, 0, 0, // 32, 34, 36, 38, 40, 42, 44,
0, 48, 0, 0, 0, 56, 0, // 46, 48, 50, 52, 54, 56, 58,
0, 0, 64, 0, 0, 0, // 60, 62, 64, 68,N/A, 96,
100, 0, 0, 0, 108, 0, 0, //100,102,104,106,108,110,112,
0, 116, 0, 0, 0, 124, 0, //114,116,118,120,122,124,126,
0, 0, 132, 0, 0, 0, 140, //128,N/A,132,134,136,138,140,
0, 0, 0, 149, 0, 0, 0, //142,144,N/A,149,151,153,155,
157, 0, 0, 0, 165, 0, 0, //157,159,161,163,165,167,169,
0, 173}; //171,173
// Channel color mapping
uint16_t channel_color[] = {
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, WHITE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, MAGENTA,
RED, ORANGE};
uint8_t scan_count = 0;
uint16_t channelIdx(int channel)
{
if (channel <= 14) // 2.4 GHz, channel 1-14
{
return channel - 1;
}
if (channel <= 64) // 5 GHz, channel 32 - 64
{
return 14 + ((channel - 32) / 2);
}
if (channel == 68)
{
return 31;
}
if (channel == 96)
{
return 33;
}
if (channel <= 144)
{
return 34 + ((channel - 100) / 2); // channe;
}
return 58 + ((channel - 149) / 2);
}
void setup()
{
// Set WiFi to station mode and disconnect from an AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
#if defined(LCD_PWR_PIN)
pinMode(LCD_PWR_PIN, OUTPUT); // sets the pin as output
digitalWrite(LCD_PWR_PIN, HIGH); // power on
#endif
#ifdef GFX_BL
pinMode(GFX_BL, OUTPUT);
digitalWrite(GFX_BL, HIGH);
#endif
// init LCD
gfx->begin();
w = gfx->width();
h = gfx->height();
text_size = (h < 200) ? 1 : 2;
banner_height = (text_size * 8) + 4;
graph_height = ((gfx->height() - banner_height) / 2) - 30;
graph24_baseline = banner_height + graph_height + 10;
graph50_baseline = graph24_baseline + graph_height + 30;
channel24_width = w / 17;
channel50_width = w / 62;
// init banner
gfx->setTextSize(text_size);
gfx->fillScreen(BLACK);
gfx->setTextColor(BLUE);
gfx->setCursor(2, 2);
gfx->print("Wio");
gfx->setTextColor(WHITE);
gfx->print(" WiFi Analyzer");
}
void loop()
{
uint8_t ap_count_list[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
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, 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, 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, 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, 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, RSSI_FLOOR};
int16_t peak_id_list[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
int32_t channel;
uint16_t idx;
int32_t rssi;
String ssid;
uint16_t color;
int16_t height, offset, text_width;
// WiFi.scanNetworks will return the number of networks found
int n = WiFi.scanNetworks(false /* async */, true /* show_hidden */, true /* passive */, 500 /* max_ms_per_chan */);
// 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);
gfx->println("No networks found");
}
else
{
for (int i = 0; i < n; i++)
{
channel = WiFi.channel(i);
idx = channelIdx(channel);
rssi = WiFi.RSSI(i);
// channel peak stat
if (peak_list[idx] < rssi)
{
peak_list[idx] = rssi;
peak_id_list[idx] = i;
}
ap_count_list[idx]++;
}
// plot found WiFi info
for (int i = 0; i < n; i++)
{
channel = WiFi.channel(i);
idx = channelIdx(channel);
rssi = WiFi.RSSI(i);
color = channel_color[idx];
height = constrain(map(rssi, RSSI_FLOOR, RSSI_CEILING, 1, graph_height), 1, graph_height);
if (idx < 14)
{
graph_baseline = graph24_baseline;
channel_width = channel24_width;
signal_width = channel24_width * 2;
offset = (idx + 2) * channel24_width;
}
else
{
graph_baseline = graph50_baseline;
channel_width = channel50_width;
signal_width = channel50_width * 2;
offset = (idx - 14 + 2) * channel50_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->drawEllipseHelper(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)
{
ssid = WiFi.BSSIDstr(i);
}
text_width = (ssid.length() + 6) * 6;
if (text_width > w)
{
offset = 0;
}
else
{
if ((offset + text_width) > w)
{
offset = w - text_width;
}
}
gfx->setTextColor(color);
gfx->setCursor(offset, graph_baseline - 10 - height);
gfx->print(ssid);
gfx->print('(');
gfx->print(rssi);
gfx->print(')');
if (WiFi.encryptionType(i) == WIFI_AUTH_OPEN)
{
gfx->print('*');
}
}
}
}
// print WiFi found
gfx->setTextColor(WHITE);
gfx->setCursor(2, banner_height);
gfx->print(n);
gfx->print(" networks");
// draw 2.4 GHz graph base axle
gfx->drawFastHLine(0, graph24_baseline, 320, WHITE);
for (idx = 0; idx < 14; idx++)
{
channel = channel_legend[idx];
offset = (idx + 2) * channel24_width;
if (channel > 0)
{
gfx->setTextColor(channel_color[idx]);
gfx->setCursor(offset - ((channel < 10) ? 3 : 6), graph24_baseline + 2);
gfx->print(channel);
}
if (ap_count_list[idx] > 0)
{
gfx->setTextColor(DARKGREY);
gfx->setCursor(offset - ((ap_count_list[idx] < 10) ? 3 : 6), graph24_baseline + 8 + 2);
gfx->print(ap_count_list[idx]);
}
}
// draw 5 GHz graph base axle
gfx->drawFastHLine(0, graph50_baseline, 320, WHITE);
for (idx = 14; idx < 71; idx++)
{
channel = channel_legend[idx];
offset = (idx - 14 + 2) * channel50_width;
if (channel > 0)
{
gfx->setTextColor(channel_color[idx]);
gfx->setCursor(offset - ((channel < 100) ? 6 : 9), graph50_baseline + 2);
gfx->print(channel);
}
if (ap_count_list[idx] > 0)
{
gfx->setTextColor(DARKGREY);
gfx->setCursor(offset - ((ap_count_list[idx] < 10) ? 3 : 6), graph50_baseline + 8 + 2);
gfx->print(ap_count_list[idx]);
}
}
// Wait a bit before scanning again
delay(SCAN_INTERVAL);
#if defined(SCAN_COUNT_SLEEP)
//POWER SAVING
if (++scan_count >= SCAN_COUNT_SLEEP)
{
#if defined(LCD_PWR_PIN)
pinMode(LCD_PWR_PIN, INPUT); // disable pin
#endif
#if defined(GFX_BL)
pinMode(GFX_BL, INPUT); // disable pin
#endif
}
#endif // defined(SCAN_COUNT_SLEEP)
}