mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-05 06:45:09 +00:00
fix(wifi): make Connect work from the setup AP (#571)
* fix(wifi): make Connect work from the setup AP Joining a network from LEDMatrix-Setup has to take the AP down first, which drops the phone that sent the request. The connect endpoint answered only after the attempt finished, so the browser never got a reply and the WiFi tab's Connect button appeared to do nothing. - /wifi/connect answers 202 immediately while the AP is active and connects in a background thread; the result (never the password) is reported via /wifi/status as last_connect_attempt. A second connect while one is pending gets 409. - connect_to_network holds a /tmp flag for the attempt; the monitor daemon skips AP management while it is fresh. Previously the daemon's disconnected counter, accumulated over the whole AP session, re-enabled the AP on its next tick in the middle of the connect. - The WiFi tab and captive setup page explain the handoff up front, and on reopening show why the last attempt failed. The wrong-password message now works: the route sets the error_type the captive page checks. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(wifi): serialize connect attempts on both paths Addresses CodeRabbit review on #571: - Check for a pending attempt before branching on AP state. A background attempt takes the AP down long before it finishes, so a second click used to bypass the 409 and start a competing synchronous connect. - Record pending for the synchronous (non-AP) path too, so two requests can't overlap and have the first clear the daemon's in-progress flag while the second is still connecting. - Clear the pending state if the background thread fails to start, rather than refusing every later request until restart. - Say the setup network returns "within a few minutes": a stale flag plus the daemon's grace period can take longer than one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -99,6 +99,16 @@ select:focus-visible,input:focus-visible{outline:2px solid var(--accent);outline
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="handoff-view" class="card hidden" tabindex="-1" aria-labelledby="handoff-title">
|
||||
<div class="success-box">
|
||||
<svg class="icon" style="color:var(--accent)" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 12a9 9 0 1 1-2.64-6.36"/><path d="M21 3v6h-6"/></svg>
|
||||
<p class="title" id="handoff-title">Connecting to <span id="handoff-ssid"></span></p>
|
||||
<p class="hint">LEDMatrix-Setup has turned off, so this page can’t follow along any more.</p>
|
||||
<p class="hint"><strong>If it worked:</strong> the LED display shows the new address. Rejoin your home WiFi and open it.</p>
|
||||
<p class="hint"><strong>If it didn’t:</strong> LEDMatrix-Setup comes back within a few minutes. Rejoin it and reopen this page to see why.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<a href="/">Open Full Interface</a>
|
||||
</div>
|
||||
@@ -259,17 +269,16 @@ function doConnect() {
|
||||
}, 60000)
|
||||
.then(readJson)
|
||||
.then(function(data) {
|
||||
if (data.status === 'success') {
|
||||
if (data.status === 'pending') {
|
||||
// Connecting in the background; this network is about to go away.
|
||||
showMsg(handoffMessage(ssid), 'info');
|
||||
setTimeout(function() { checkNewIP(ssid); }, 3000);
|
||||
} else if (data.status === 'success') {
|
||||
clearMsg();
|
||||
// Poll for the new IP
|
||||
setTimeout(function() { checkNewIP(ssid); }, 3000);
|
||||
} else {
|
||||
var msg = data.error_type === 'wrong_password'
|
||||
? 'Incorrect password — please try again.'
|
||||
: (data.message || 'Couldn’t connect to ' + ssid + '. Check the network name and password, then try again.');
|
||||
showMsg(msg, 'err');
|
||||
resetConnect();
|
||||
if (data.error_type === 'wrong_password') $('password').focus();
|
||||
showConnectError(data, ssid);
|
||||
}
|
||||
})
|
||||
.catch(function(e) {
|
||||
@@ -279,12 +288,49 @@ function doConnect() {
|
||||
return;
|
||||
}
|
||||
// Connection may drop if AP mode was disabled — that's expected
|
||||
clearMsg();
|
||||
showMsg('Connection attempt sent. If the page stops responding, the device is connecting to ' + ssid + '.', 'info');
|
||||
setTimeout(function() { showSuccessFallback(ssid); }, 5000);
|
||||
showHandoff(ssid);
|
||||
});
|
||||
}
|
||||
|
||||
function handoffMessage(ssid) {
|
||||
return 'Connecting to ' + ssid + '. LEDMatrix-Setup will turn off and your phone will disconnect from it. ' +
|
||||
'If it works, the LED display shows its new address. If not, LEDMatrix-Setup comes back within a few minutes: ' +
|
||||
'rejoin it and reopen this page to see why.';
|
||||
}
|
||||
|
||||
function resetConnectBtn() {
|
||||
var btn = $('btn-connect');
|
||||
connecting = false;
|
||||
btn.removeAttribute('aria-busy');
|
||||
btn.textContent = 'Connect';
|
||||
updateConnectBtn();
|
||||
}
|
||||
|
||||
// `attempt` is a /wifi/connect error body or a failed last_connect_attempt.
|
||||
function showConnectError(attempt, ssid) {
|
||||
var name = attempt.ssid || ssid;
|
||||
var wrongPassword = attempt.error_type === 'wrong_password';
|
||||
var msg = wrongPassword
|
||||
? 'Incorrect password for ' + name + ' — please try again.'
|
||||
: (attempt.message || 'Couldn’t connect to ' + name + '. Check the network name and password, then try again.');
|
||||
// A background failure brings the AP back: put the form back too.
|
||||
$('handoff-view').classList.add('hidden');
|
||||
$('setup-form').classList.remove('hidden');
|
||||
showMsg(msg, 'err');
|
||||
resetConnectBtn();
|
||||
if (wrongPassword) $('password').focus();
|
||||
}
|
||||
|
||||
function showHandoff(ssid) {
|
||||
$('setup-form').classList.add('hidden');
|
||||
$('success-view').classList.add('hidden');
|
||||
var view = $('handoff-view');
|
||||
view.classList.remove('hidden');
|
||||
$('handoff-ssid').textContent = ssid;
|
||||
clearMsg();
|
||||
view.focus();
|
||||
}
|
||||
|
||||
var MAX_IP_RETRIES = 20;
|
||||
|
||||
function checkNewIP(ssid, retriesLeft) {
|
||||
@@ -296,18 +342,38 @@ function checkNewIP(ssid, retriesLeft) {
|
||||
fetchWithTimeout('/api/v3/wifi/status', {}, 8000)
|
||||
.then(readJson)
|
||||
.then(function(data) {
|
||||
if (data.status === 'success' && data.data && data.data.connected && data.data.ip_address) {
|
||||
showSuccess(data.data.ip_address);
|
||||
var d = (data.status === 'success' && data.data) || {};
|
||||
var attempt = d.last_connect_attempt;
|
||||
if (attempt && attempt.ssid === ssid && attempt.state === 'failed') {
|
||||
showConnectError(attempt);
|
||||
} else if (d.connected && d.ip_address && !d.ap_mode_active) {
|
||||
showSuccess(d.ip_address);
|
||||
} else {
|
||||
setTimeout(function() { checkNewIP(ssid, retriesLeft - 1); }, 3000);
|
||||
}
|
||||
})
|
||||
.catch(function() {
|
||||
// AP likely down — show fallback
|
||||
showSuccessFallback(ssid);
|
||||
// The setup network went down, which is what connecting does.
|
||||
showHandoff(ssid);
|
||||
});
|
||||
}
|
||||
|
||||
// A failed attempt brings LEDMatrix-Setup back; tell the user who rejoined why.
|
||||
function showPreviousFailure() {
|
||||
fetchWithTimeout('/api/v3/wifi/status', {}, 8000)
|
||||
.then(readJson)
|
||||
.then(function(data) {
|
||||
var attempt = data.data && data.data.last_connect_attempt;
|
||||
if (attempt && attempt.state === 'failed' && !data.data.connected) {
|
||||
var reason = attempt.error_type === 'wrong_password'
|
||||
? 'the password was incorrect'
|
||||
: (attempt.message || 'an unknown error');
|
||||
showMsg('Last attempt to connect to ' + attempt.ssid + ' failed: ' + reason + '.', 'err');
|
||||
}
|
||||
})
|
||||
.catch(function() {});
|
||||
}
|
||||
|
||||
function revealSuccess(text) {
|
||||
$('setup-form').classList.add('hidden');
|
||||
var view = $('success-view');
|
||||
@@ -326,6 +392,7 @@ function showSuccessFallback(ssid) {
|
||||
}
|
||||
|
||||
// Auto-scan on load
|
||||
showPreviousFailure();
|
||||
doScan();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user