Add WiFi network scanner with dropdown selection instead of manual SSID entry

This commit is contained in:
Chad 2026-03-31 14:14:40 -05:00
parent db8986c077
commit c78f07b4b5

View file

@ -179,6 +179,15 @@ int keyboardPos = 0;
int indexScrollOffset = 0;
bool needsRefresh = false;
#define MAX_SCAN_NETWORKS 15
String scannedSSIDs[MAX_SCAN_NETWORKS];
int scannedCount = 0;
int wifiScrollOffset = 0;
bool wifiScanDone = false;
String selectedSSID = "";
String wifiPassword = "";
bool enteringPassword = false;
String formatPriceUS(double price, int decimals = 2, bool includeDollar = true) {
if (price <= 0) return "...";
@ -590,6 +599,33 @@ void drawIndexCustomizeScreen() {
lcd.drawString("CANCEL", SCREEN_WIDTH - 95, SCREEN_HEIGHT - 30);
}
void scanWifiNetworks() {
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
int n = WiFi.scanNetworks();
scannedCount = 0;
if (n > 0) {
for (int i = 0; i < n && scannedCount < MAX_SCAN_NETWORKS; i++) {
String ssid = WiFi.SSID(i);
bool duplicate = false;
for (int j = 0; j < scannedCount; j++) {
if (scannedSSIDs[j] == ssid) {
duplicate = true;
break;
}
}
if (!duplicate && ssid.length() > 0) {
scannedSSIDs[scannedCount++] = ssid;
}
}
}
wifiScanDone = true;
wifiScrollOffset = 0;
}
void drawWifiConfigScreen() {
lcd.fillScreen(TFT_BLACK);
@ -599,37 +635,94 @@ void drawWifiConfigScreen() {
lcd.setTextDatum(textdatum_t::middle_center);
lcd.drawString("WIFI CONFIGURATION", SCREEN_WIDTH / 2, 25);
if (!wifiScanDone) {
lcd.setTextColor(TFT_WHITE, TFT_BLACK);
lcd.setFont(&fonts::DejaVu18);
lcd.setTextDatum(textdatum_t::middle_center);
lcd.drawString("Scanning for networks...", SCREEN_WIDTH / 2, 150);
return;
}
lcd.setTextColor(TFT_WHITE, TFT_BLACK);
lcd.setFont(&fonts::DejaVu18);
lcd.setTextDatum(textdatum_t::middle_left);
lcd.drawString("SSID:", 100, 70);
lcd.drawString("Select Network:", 50, 60);
lcd.fillSmoothRoundRect(100, 90, 600, 40, 6, TFT_ORANGE);
lcd.setTextColor(TFT_WHITE, TFT_ORANGE);
lcd.setTextDatum(textdatum_t::middle_left);
String ssidDisplay = String(keyboardBuffer);
if (ssidDisplay.length() == 0) ssidDisplay = "_";
lcd.drawString(ssidDisplay, 120, 110);
int listY = 85;
int itemHeight = 36;
int visibleItems = 5;
for (int i = 0; i < visibleItems; i++) {
int idx = wifiScrollOffset + i;
if (idx >= scannedCount) break;
int y = listY + i * (itemHeight + 4);
bool isSelected = (scannedSSIDs[idx] == selectedSSID);
uint16_t bgColor = isSelected ? TFT_ORANGE : TFT_DARKGRAY;
lcd.fillSmoothRoundRect(50, y, 700, itemHeight, 6, bgColor);
lcd.setTextColor(TFT_WHITE, bgColor);
lcd.setTextDatum(textdatum_t::middle_left);
String displaySSID = scannedSSIDs[idx];
if (displaySSID.length() > 25) {
displaySSID = displaySSID.substring(0, 23) + "...";
}
lcd.drawString(displaySSID, 70, y + itemHeight / 2);
}
if (wifiScrollOffset > 0) {
lcd.fillSmoothRoundRect(380, listY - 28, 40, 22, 4, TFT_GRAY);
lcd.setTextColor(TFT_WHITE, TFT_GRAY);
lcd.setFont(&fonts::DejaVu18);
lcd.setTextDatum(textdatum_t::middle_center);
lcd.drawString("^", 400, listY - 17);
}
if (wifiScrollOffset + visibleItems < scannedCount) {
lcd.fillSmoothRoundRect(380, listY + visibleItems * (itemHeight + 4) + 6, 40, 22, 4, TFT_GRAY);
lcd.setTextColor(TFT_WHITE, TFT_GRAY);
lcd.setFont(&fonts::DejaVu18);
lcd.setTextDatum(textdatum_t::middle_center);
lcd.drawString("v", 400, listY + visibleItems * (itemHeight + 4) + 17);
}
lcd.setTextColor(TFT_WHITE, TFT_BLACK);
lcd.drawString("Password:", 100, 150);
lcd.fillSmoothRoundRect(100, 170, 600, 40, 6, TFT_DARKGRAY);
lcd.setTextColor(TFT_GRAY, TFT_DARKGRAY);
lcd.setFont(&fonts::DejaVu18);
lcd.setTextDatum(textdatum_t::middle_left);
lcd.drawString("(use same keyboard)", 120, 190);
lcd.drawString("Password:", 50, 285);
drawKeyboard(230);
lcd.fillSmoothRoundRect(50, 305, 700, 40, 6, enteringPassword ? TFT_ORANGE : TFT_DARKGRAY);
lcd.setTextColor(enteringPassword ? TFT_WHITE : TFT_GRAY, enteringPassword ? TFT_ORANGE : TFT_DARKGRAY);
lcd.setTextDatum(textdatum_t::middle_left);
String pwdDisplay = wifiPassword;
if (enteringPassword && keyboardPos > 0) {
pwdDisplay = String(keyboardBuffer);
}
if (pwdDisplay.length() == 0) {
lcd.drawString("(tap to enter password)", 70, 325);
} else {
String masked = "";
for (int i = 0; i < pwdDisplay.length(); i++) masked += "*";
lcd.drawString(masked, 70, 325);
}
lcd.fillSmoothRoundRect(100, SCREEN_HEIGHT - 50, 150, 40, 8, TFT_GRAY);
if (enteringPassword) {
drawKeyboard(360);
}
lcd.fillSmoothRoundRect(50, SCREEN_HEIGHT - 50, 150, 40, 8, TFT_GRAY);
lcd.setTextColor(TFT_WHITE, TFT_GRAY);
lcd.setFont(&fonts::DejaVu18);
lcd.setTextDatum(textdatum_t::middle_center);
lcd.drawString("BACK", 175, SCREEN_HEIGHT - 30);
lcd.drawString("BACK", 125, SCREEN_HEIGHT - 30);
lcd.fillSmoothRoundRect(SCREEN_WIDTH - 250, SCREEN_HEIGHT - 50, 150, 40, 8, TFT_GREEN);
lcd.setTextColor(TFT_WHITE, TFT_GREEN);
lcd.drawString("SAVE", SCREEN_WIDTH - 175, SCREEN_HEIGHT - 30);
bool canSave = selectedSSID.length() > 0 && (wifiPassword.length() > 0 || (!enteringPassword && keyboardPos > 0));
uint16_t saveColor = canSave ? TFT_GREEN : TFT_GRAY;
lcd.fillSmoothRoundRect(SCREEN_WIDTH - 200, SCREEN_HEIGHT - 50, 150, 40, 8, saveColor);
lcd.setTextColor(TFT_WHITE, saveColor);
lcd.drawString("CONNECT", SCREEN_WIDTH - 125, SCREEN_HEIGHT - 30);
}
void drawDashboard() {
@ -810,16 +903,20 @@ bool handleStockCustomizeTouch(int32_t x, int32_t y) {
}
bool handleWifiConfigTouch(int32_t x, int32_t y) {
if (x >= 100 && x < 250 && y >= SCREEN_HEIGHT - 50 && y < SCREEN_HEIGHT - 10) {
if (!wifiScanDone) return true;
if (x >= 50 && x < 200 && y >= SCREEN_HEIGHT - 50 && y < SCREEN_HEIGHT - 10) {
currentScreen = SCREEN_DASHBOARD;
needsRefresh = true;
return true;
}
if (x >= SCREEN_WIDTH - 250 && x < SCREEN_WIDTH - 100 && y >= SCREEN_HEIGHT - 50 && y < SCREEN_HEIGHT - 10) {
if (keyboardPos > 0) {
if (x >= SCREEN_WIDTH - 200 && x < SCREEN_WIDTH - 50 && y >= SCREEN_HEIGHT - 50 && y < SCREEN_HEIGHT - 10) {
String pwdToSave = enteringPassword ? String(keyboardBuffer) : wifiPassword;
if (selectedSSID.length() > 0 && pwdToSave.length() > 0) {
preferences.begin("wifi", false);
preferences.putString("ssid", keyboardBuffer);
preferences.putString("ssid", selectedSSID);
preferences.putString("password", pwdToSave);
preferences.end();
currentScreen = SCREEN_DASHBOARD;
needsRefresh = true;
@ -827,11 +924,94 @@ bool handleWifiConfigTouch(int32_t x, int32_t y) {
return true;
}
int keyboardY = 230;
if (handleKeyboardTouch(x, y, keyboardY)) {
int listY = 85;
int itemHeight = 36;
int visibleItems = 5;
if (x >= 380 && x < 420 && y >= listY - 28 && y < listY - 6) {
if (wifiScrollOffset > 0) {
wifiScrollOffset--;
}
return true;
}
if (x >= 380 && x < 420 && y >= listY + visibleItems * (itemHeight + 4) + 6 && y < listY + visibleItems * (itemHeight + 4) + 28) {
if (wifiScrollOffset + visibleItems < scannedCount) {
wifiScrollOffset++;
}
return true;
}
for (int i = 0; i < visibleItems; i++) {
int idx = wifiScrollOffset + i;
if (idx >= scannedCount) break;
int iy = listY + i * (itemHeight + 4);
if (x >= 50 && x < 750 && y >= iy && y < iy + itemHeight) {
selectedSSID = scannedSSIDs[idx];
enteringPassword = false;
keyboardPos = 0;
keyboardBuffer[0] = '\0';
return true;
}
}
if (x >= 50 && x < 750 && y >= 305 && y < 345) {
enteringPassword = true;
keyboardPos = 0;
keyboardBuffer[0] = '\0';
return true;
}
if (enteringPassword) {
int keyboardY = 360;
const char* rows[] = {
"QWERTYUIOP",
"ASDFGHJKL",
"ZXCVBNM",
"1234567890"
};
const int numRows = 4;
const int keySize = 32;
const int keyGap = 2;
for (int r = 0; r < numRows; r++) {
int rowLen = strlen(rows[r]);
int rowWidth = rowLen * (keySize + keyGap) - keyGap;
int startX = (SCREEN_WIDTH - rowWidth) / 2;
int keyY = keyboardY + r * (keySize + keyGap);
for (int k = 0; k < rowLen; k++) {
int keyX = startX + k * (keySize + keyGap);
if (x >= keyX && x < keyX + keySize && y >= keyY && y < keyY + keySize) {
if (keyboardPos < 63) {
keyboardBuffer[keyboardPos++] = rows[r][k];
keyboardBuffer[keyboardPos] = '\0';
}
return true;
}
}
}
int btnY = keyboardY + numRows * (keySize + keyGap) + 4;
int delX = SCREEN_WIDTH / 2 - 125;
int enterX = SCREEN_WIDTH / 2 + 5;
if (x >= delX && x < delX + 120 && y >= btnY && y < btnY + 32) {
if (keyboardPos > 0) {
keyboardPos--;
keyboardBuffer[keyboardPos] = '\0';
}
return true;
}
if (x >= enterX && x < enterX + 120 && y >= btnY && y < btnY + 32) {
wifiPassword = String(keyboardBuffer);
enteringPassword = false;
return true;
}
}
return false;
}
@ -944,8 +1124,13 @@ bool handleDashboardTouch(int32_t x, int32_t y) {
if (x >= 20 && x < 200 && y >= SCREEN_HEIGHT - 40 && y < SCREEN_HEIGHT) {
currentScreen = SCREEN_WIFI_CONFIG;
wifiScanDone = false;
wifiPassword = "";
selectedSSID = "";
enteringPassword = false;
keyboardPos = 0;
keyboardBuffer[0] = '\0';
scanWifiNetworks();
return true;
}