Skip to content

Commit e8ec330

Browse files
committed
WiFi radio off button, prefer BLE
1 parent 1a09d08 commit e8ec330

4 files changed

Lines changed: 85 additions & 1 deletion

File tree

1.16 KB
Binary file not shown.

src/web/index.html

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,19 @@ <h3>ChessConnect</h3>
7373
</label>
7474
</div>
7575

76+
<div class="toggle-row toggle-row-divider">
77+
<div>
78+
<label class="toggle-label" for="disableWifiRadioBtn">WiFi Radio</label>
79+
<p class="toggle-description">
80+
Turn off until next boot to make Bluetooth more reliable
81+
</p>
82+
</div>
83+
<button type="button" id="disableWifiRadioBtn" class="button"
84+
style="background-color: #f44336; width: auto; min-width: 92px; padding: 7px 14px; font-size: 14px; border-radius: 14px; margin: 0; flex: 0 0 auto;">
85+
Disable
86+
</button>
87+
</div>
88+
7689
<div class="form-group">
7790
<label for="bleBoard">Board to Emulate</label>
7891
<select id="bleBoard"></select>
@@ -824,6 +837,28 @@ <h3>Update Available</h3>
824837
updateChessConnectInfo();
825838
});
826839

840+
document.getElementById('disableWifiRadioBtn').addEventListener('click', async function () {
841+
if (!await showConfirm("Disable the ESP32 WiFi radio? You won't be able to access the WebUI until next boot")) return;
842+
const btn = this;
843+
btn.disabled = true;
844+
btn.textContent = 'Disabling...';
845+
try {
846+
const r = await fetch('/disable-wifi-radio', { method: 'POST' });
847+
const msg = await r.text();
848+
if (r.ok) {
849+
btn.textContent = 'Disabled';
850+
showAlert(msg);
851+
} else {
852+
btn.disabled = false;
853+
btn.textContent = 'Disable';
854+
showAlert(msg || 'Error disabling WiFi radio');
855+
}
856+
} catch (e) {
857+
btn.textContent = 'Disabled';
858+
showAlert('WiFi radio disable request sent. Reboot the ESP32 to access the WebUI again.');
859+
}
860+
});
861+
827862
// Board settings functions
828863
function updateBoardSettings() {
829864
fetch('/board-settings')

src/wifi_manager_esp32.cpp

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ static const IPAddress AP_IP(200, 200, 200, 1);
1616
static const IPAddress AP_GATEWAY(200, 200, 200, 1);
1717
static const IPAddress AP_SUBNET(255, 255, 255, 0);
1818

19-
WiFiManagerESP32::WiFiManagerESP32(BoardDriver* bd, MoveHistory* mh) : boardDriver(bd), moveHistory(mh), server(HTTP_PORT), boardEvents(nullptr), gameMode("0"), lichessToken(""), botConfig(), scanAllChannels(false), profileCount(0), connectedProfileIndex(-1), scanResults(nullptr), scanResultCount(0), currentFen(INITIAL_FEN), hasPendingEdit(false), hasPendingResign(false), hasPendingDraw(false), hasPendingResume(false), pendingResignColor('?'), promotion{}, boardEvaluation(0.0f), otaUpdater(bd), autoOtaEnabled(false), otaChecked(false) {
19+
WiFiManagerESP32::WiFiManagerESP32(BoardDriver* bd, MoveHistory* mh) : boardDriver(bd), moveHistory(mh), server(HTTP_PORT), boardEvents(nullptr), gameMode("0"), lichessToken(""), botConfig(), scanAllChannels(false), profileCount(0), connectedProfileIndex(-1), wifiRadioDisabled(false), scanResults(nullptr), scanResultCount(0), currentFen(INITIAL_FEN), hasPendingEdit(false), hasPendingResign(false), hasPendingDraw(false), hasPendingResume(false), pendingResignColor('?'), promotion{}, boardEvaluation(0.0f), otaUpdater(bd), autoOtaEnabled(false), otaChecked(false) {
2020
promotion.reset();
2121
pendingWiFi.reset();
2222
}
@@ -92,6 +92,7 @@ void WiFiManagerESP32::begin() {
9292
server.on("/draw", HTTP_POST, [this](AsyncWebServerRequest* request) { this->handleDraw(request); });
9393
server.on("/wifi", HTTP_GET, [this](AsyncWebServerRequest* request) { request->send(200, "application/json", this->getWiFiInfoJSON()); });
9494
server.on("/wifi", HTTP_POST, [this](AsyncWebServerRequest* request) { this->handleConnectWiFi(request); });
95+
server.on("/disable-wifi-radio", HTTP_POST, [this](AsyncWebServerRequest* request) { this->handleDisableWiFiRadio(request); });
9596
server.on("/gameselect", HTTP_POST, [this](AsyncWebServerRequest* request) { this->handleGameSelection(request); });
9697
server.on("/lichess", HTTP_GET, [this](AsyncWebServerRequest* request) { request->send(200, "application/json", this->getLichessInfoJSON()); });
9798
server.on("/lichess", HTTP_POST, [this](AsyncWebServerRequest* request) { this->handleSaveLichessToken(request); });
@@ -246,6 +247,8 @@ void WiFiManagerESP32::handleDraw(AsyncWebServerRequest* request) {
246247
}
247248

248249
void WiFiManagerESP32::handleConnectWiFi(AsyncWebServerRequest* request) {
250+
if (wifiRadioDisabled) return;
251+
249252
// Handle scanAllChannels toggle
250253
if (request->hasArg("scanAllChannels")) {
251254
bool newScanAll = request->arg("scanAllChannels") == "1";
@@ -320,6 +323,35 @@ void WiFiManagerESP32::handleConnectWiFi(AsyncWebServerRequest* request) {
320323
request->send(400, "text/plain", "Missing or invalid parameters");
321324
}
322325

326+
void WiFiManagerESP32::handleDisableWiFiRadio(AsyncWebServerRequest* request) {
327+
request->send(200, "text/plain", "WiFi radio disabling now. The WebUI will be unavailable until the ESP32 boots again.");
328+
329+
xTaskCreate(
330+
[](void* param) {
331+
delay(500);
332+
static_cast<WiFiManagerESP32*>(param)->disableWiFiRadio();
333+
vTaskDelete(nullptr);
334+
},
335+
"disableWiFiRadioTask", 2048, this, 3, nullptr);
336+
}
337+
338+
void WiFiManagerESP32::disableWiFiRadio() {
339+
webLog.println("Disabling ESP32 WiFi radio until next boot...");
340+
wifiRadioDisabled = true;
341+
pendingWiFi.action = NONE;
342+
connectedProfileIndex = -1;
343+
344+
stopCaptivePortal();
345+
MDNS.end();
346+
WiFi.scanDelete();
347+
WiFi.setAutoReconnect(false);
348+
WiFi.disconnect(true, false);
349+
WiFi.softAPdisconnect(true);
350+
WiFi.mode(WIFI_OFF);
351+
352+
webLog.println("WiFi radio disabled. Reboot the ESP32 to restore WebUI access.");
353+
}
354+
323355
void WiFiManagerESP32::handleGameSelection(AsyncWebServerRequest* request) {
324356
int mode = 0;
325357
if (request->hasArg("gamemode"))
@@ -596,6 +628,8 @@ void WiFiManagerESP32::clearPromotion() {
596628
}
597629

598630
void WiFiManagerESP32::checkPendingWiFi() {
631+
if (wifiRadioDisabled) return;
632+
599633
// Auto-reconnect: if we were connected to a network and lost it, try to reconnect
600634
if (connectedProfileIndex >= 0 && WiFi.status() != WL_CONNECTED) {
601635
webLog.println("WiFi connection lost, attempting reconnect...");
@@ -704,6 +738,8 @@ void WiFiManagerESP32::checkPendingWiFi() {
704738
}
705739

706740
bool WiFiManagerESP32::ensureConnected() {
741+
if (wifiRadioDisabled) return false;
742+
707743
if (WiFi.status() == WL_CONNECTED) return true;
708744
webLog.println("WiFi not connected, attempting reconnect...");
709745
if (connectToSavedProfile()) return true;
@@ -1030,6 +1066,8 @@ void WiFiManagerESP32::promoteProfile(int index) {
10301066
}
10311067

10321068
bool WiFiManagerESP32::waitForConnection(int maxAttempts) {
1069+
if (wifiRadioDisabled) return false;
1070+
10331071
for (int i = 0; i < maxAttempts; i++) {
10341072
boardDriver->showConnectingAnimation();
10351073
wl_status_t st = WiFi.status();
@@ -1041,6 +1079,8 @@ bool WiFiManagerESP32::waitForConnection(int maxAttempts) {
10411079
}
10421080

10431081
bool WiFiManagerESP32::tryConnect(const String& ssid, const String& password, const uint8_t* bssid, uint8_t channel) {
1082+
if (wifiRadioDisabled) return false;
1083+
10441084
bool isFast = (bssid != nullptr && channel > 0);
10451085
if (isFast)
10461086
webLog.printf(" Fast connect: SSID=%s, Password=%s, Channel=%d, BSSID=%02X:%02X:%02X:%02X:%02X:%02X\n", ssid.c_str(), password.c_str(), channel, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
@@ -1113,6 +1153,8 @@ bool WiFiManagerESP32::tryConnectProfile(int index) {
11131153
}
11141154

11151155
bool WiFiManagerESP32::connectToSavedProfile() {
1156+
if (wifiRadioDisabled) return false;
1157+
11161158
for (int i = 0; i < profileCount; i++) {
11171159
if (tryConnectProfile(i)) {
11181160
promoteProfile(i);
@@ -1124,6 +1166,8 @@ bool WiFiManagerESP32::connectToSavedProfile() {
11241166
}
11251167

11261168
void WiFiManagerESP32::startAPFallback() {
1169+
if (wifiRadioDisabled) return;
1170+
11271171
webLog.println("Starting AP fallback...");
11281172
WiFi.mode(WIFI_AP);
11291173
if (!WiFi.softAPConfig(AP_IP, AP_GATEWAY, AP_SUBNET))
@@ -1172,6 +1216,8 @@ void WiFiManagerESP32::pendingWiFiBackgroundTask(void* param) {
11721216
}
11731217

11741218
void WiFiManagerESP32::performScan() {
1219+
if (wifiRadioDisabled) return;
1220+
11751221
static bool scanInProgress = false;
11761222
if (scanInProgress) return;
11771223
scanInProgress = true;

src/wifi_manager_esp32.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class WiFiManagerESP32 {
7676
int profileCount;
7777
bool scanAllChannels;
7878
int connectedProfileIndex; // Index of currently connected profile, or -1
79+
bool wifiRadioDisabled; // True after the user disables WiFi until the next boot
7980

8081
// Scan results (populated by deferred scan task)
8182
ScannedNetwork* scanResults;
@@ -149,6 +150,7 @@ class WiFiManagerESP32 {
149150
bool connectToSavedProfile(); // Try all saved profiles, promote winner; returns true if connected
150151
void startAPFallback();
151152
void performScan();
153+
void disableWiFiRadio();
152154

153155
// Web interface methods
154156
String getWiFiInfoJSON();
@@ -159,6 +161,7 @@ class WiFiManagerESP32 {
159161
void handleBoardEditSuccess(AsyncWebServerRequest* request);
160162
void handlePromotion(AsyncWebServerRequest* request);
161163
void handleConnectWiFi(AsyncWebServerRequest* request);
164+
void handleDisableWiFiRadio(AsyncWebServerRequest* request);
162165
void handleGameSelection(AsyncWebServerRequest* request);
163166
void handleSaveLichessToken(AsyncWebServerRequest* request);
164167
void handleBoardSettings(AsyncWebServerRequest* request);

0 commit comments

Comments
 (0)