optimize AP mode
Some checks failed
ESP-IDF Build / build (esp32c6, release-v5.4) (push) Failing after 6m44s
ESP-IDF Build / build (esp32c6, release-v5.5) (push) Failing after 3m59s
ESP-IDF Build / build (esp32s3, release-v5.4) (push) Failing after 3m51s
ESP-IDF Build / build (esp32s3, release-v5.5) (push) Failing after 3m52s

- save wifi data
- show status led

Signed-off-by: Peter Siegmund <developer@mars3142.org>
This commit is contained in:
2026-01-15 00:36:19 +01:00
parent bccfb80791
commit 1fbc28a628
14 changed files with 213 additions and 257 deletions

View File

@@ -27,25 +27,9 @@
</button>
</div>
<h1>🚂 System Control</h1>
<p data-i18n="captive.subtitle">WLAN-Einrichtung</p>
</div>
<div class="card">
<div id="scan-section">
<button class="btn btn-secondary" onclick="scanNetworks()" data-i18n="captive.scan">
📡 Netzwerke suchen
</button>
<div id="loading" class="loading">
<div class="spinner"></div>
<p data-i18n="captive.scanning">Suche nach Netzwerken...</p>
</div>
<div id="network-list" class="network-list" style="display: none;"></div>
</div>
<div class="divider"><span data-i18n="captive.or.manual">oder manuell eingeben</span></div>
<div class="form-group">
<label for="ssid" data-i18n="wifi.ssid">WLAN-Name (SSID)</label>
<input type="text" id="ssid" data-i18n-placeholder="wifi.ssid.placeholder"
@@ -62,7 +46,8 @@
</div>
<div class="btn-group">
<button class="btn btn-primary" onclick="saveWifi()" data-i18n="captive.connect">
<button class="btn btn-primary" id="connect-btn" onclick="saveWifi()" data-i18n="captive.connect"
disabled>
💾 Verbinden
</button>
</div>
@@ -112,12 +97,21 @@
setTheme(current === 'dark' ? 'light' : 'dark');
}
// Button aktivieren/deaktivieren
function updateConnectBtn() {
const ssid = document.getElementById('ssid').value;
const pw = document.getElementById('password').value;
const btn = document.getElementById('connect-btn');
btn.disabled = !(ssid.length > 0 && pw.length > 0);
}
// Initialize on load
document.addEventListener('DOMContentLoaded', () => {
initTheme();
initI18n();
// Auto-scan on load
setTimeout(scanNetworks, 500);
document.getElementById('ssid').addEventListener('input', updateConnectBtn);
document.getElementById('password').addEventListener('input', updateConnectBtn);
updateConnectBtn();
});
// Toggle password visibility

View File

@@ -39,6 +39,15 @@ body {
box-shadow: 0 4px 20px var(--shadow);
}
#connect-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
pointer-events: none;
box-shadow: none;
background-color: #888 !important;
}
}
/* Form Group - More spacing */
.form-group {
margin-bottom: 16px;

View File

@@ -16,7 +16,6 @@
<body>
<div class="container">
<div class="header">
<h1>🚂 System Control</h1>
<div class="header-controls">
<button class="lang-toggle" onclick="toggleLanguage()" aria-label="Sprache wechseln">
<span class="lang-flag" id="lang-flag">🇩🇪</span>
@@ -27,6 +26,7 @@
<span class="theme-toggle-label" id="theme-label">Dark</span>
</button>
</div>
<h1>🚂 System Control</h1>
</div>
<div class="tabs">

View File

@@ -43,6 +43,13 @@ async function scanNetworks() {
try {
const response = await fetch('/api/wifi/scan');
if (!response.ok) {
// Fehlerhafte API-Antwort, aber ESP32 ist erreichbar
const errorText = await response.text();
showStatus('wifi-status', t('wifi.error.scan') + ': ' + errorText, 'error');
if (loading) loading.classList.remove('active');
return;
}
const networks = await response.json();
if (loading) {
@@ -92,43 +99,43 @@ async function scanNetworks() {
if (loading) {
loading.classList.remove('active');
}
// Demo mode for local testing
const demoNetworks = [
{ ssid: 'Demo-Netzwerk', rssi: -45 },
{ ssid: 'Gast-WLAN', rssi: -67 },
{ ssid: 'Nachbar-WiFi', rssi: -82 }
];
if (networkList) {
demoNetworks.forEach(network => {
const signalIcon = getSignalIcon(network.rssi);
const item = document.createElement('div');
item.className = 'network-item';
item.onclick = () => selectNetwork(network.ssid, item);
item.innerHTML = `
<span class="network-name">
<span class="signal-icon">${signalIcon}</span>
${escapeHtml(network.ssid)}
</span>
<span class="network-signal">${network.rssi} dBm</span>
`;
networkList.appendChild(item);
});
networkList.style.display = 'block';
// Nur bei Netzwerkfehlern Demo-Daten anzeigen
if (error instanceof TypeError) {
const demoNetworks = [
{ ssid: 'Demo-Netzwerk', rssi: -45 },
{ ssid: 'Gast-WLAN', rssi: -67 },
{ ssid: 'Nachbar-WiFi', rssi: -82 }
];
if (networkList) {
demoNetworks.forEach(network => {
const signalIcon = getSignalIcon(network.rssi);
const item = document.createElement('div');
item.className = 'network-item';
item.onclick = () => selectNetwork(network.ssid, item);
item.innerHTML = `
<span class="network-name">
<span class="signal-icon">${signalIcon}</span>
${escapeHtml(network.ssid)}
</span>
<span class="network-signal">${network.rssi} dBm</span>
`;
networkList.appendChild(item);
});
networkList.style.display = 'block';
}
if (select) {
select.innerHTML = `<option value="">${t('wifi.scan.hint')}</option>`;
demoNetworks.forEach(network => {
const option = document.createElement('option');
option.value = network.ssid;
option.textContent = `${network.ssid} (${network.rssi} dBm)`;
select.appendChild(option);
});
}
showStatus('wifi-status', 'Demo: ' + t('wifi.networks.found', { count: demoNetworks.length }), 'info');
} else {
showStatus('wifi-status', t('wifi.error.scan') + ': ' + error.message, 'error');
}
if (select) {
select.innerHTML = `<option value="">${t('wifi.scan.hint')}</option>`;
demoNetworks.forEach(network => {
const option = document.createElement('option');
option.value = network.ssid;
option.textContent = `${network.ssid} (${network.rssi} dBm)`;
select.appendChild(option);
});
}
showStatus('wifi-status', 'Demo: ' + t('wifi.networks.found', { count: demoNetworks.length }), 'info');
}
}