Remove WiFi station (client) support

- Drop station connect/status/credentials from wifi util and settings API
- Remove station activation from main
- Remove station UI and JS from index, settings template, and help.js
- Device settings now only configure WiFi Access Point

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-02-20 11:49:04 +13:00
parent 0e96223bf6
commit 2be0640622
6 changed files with 4 additions and 362 deletions

View File

@@ -13,51 +13,6 @@ async def get_settings(request):
# trigger MicroPython's "dict update sequence has wrong length" quirk. # trigger MicroPython's "dict update sequence has wrong length" quirk.
return json.dumps(settings), 200, {'Content-Type': 'application/json'} return json.dumps(settings), 200, {'Content-Type': 'application/json'}
@controller.get('/wifi/station')
async def get_station_status(request):
"""Get WiFi station connection status."""
status = wifi.get_sta_status()
if status:
return json.dumps(status), 200, {'Content-Type': 'application/json'}
return json.dumps({"error": "Failed to get station status"}), 500
@controller.post('/wifi/station')
async def connect_station(request):
"""Connect to WiFi station with credentials."""
try:
data = request.json
ssid = data.get('ssid')
password = data.get('password', '')
ip = data.get('ip')
gateway = data.get('gateway')
if not ssid:
return json.dumps({"error": "SSID is required"}), 400
# Save credentials to settings
settings['wifi_station_ssid'] = ssid
settings['wifi_station_password'] = password
if ip:
settings['wifi_station_ip'] = ip
if gateway:
settings['wifi_station_gateway'] = gateway
settings.save()
# Attempt connection
result = wifi.connect(ssid, password, ip, gateway)
if result:
return json.dumps({
"message": "Connected successfully",
"ip": result[0],
"netmask": result[1],
"gateway": result[2],
"dns": result[3] if len(result) > 3 else None
}), 200, {'Content-Type': 'application/json'}
else:
return json.dumps({"error": "Failed to connect"}), 400
except Exception as e:
return json.dumps({"error": str(e)}), 500
@controller.get('/wifi/ap') @controller.get('/wifi/ap')
async def get_ap_config(request): async def get_ap_config(request):
"""Get Access Point configuration.""" """Get Access Point configuration."""
@@ -106,15 +61,6 @@ async def configure_ap(request):
except Exception as e: except Exception as e:
return json.dumps({"error": str(e)}), 500 return json.dumps({"error": str(e)}), 500
@controller.get('/wifi/station/credentials')
async def get_station_credentials(request):
"""Get saved WiFi station credentials (without password)."""
return json.dumps({
"ssid": settings.get('wifi_station_ssid', ''),
"ip": settings.get('wifi_station_ip', ''),
"gateway": settings.get('wifi_station_gateway', '')
}), 200, {'Content-Type': 'application/json'}
@controller.put('/settings') @controller.put('/settings')
async def update_settings(request): async def update_settings(request):
"""Update general settings.""" """Update general settings."""

View File

@@ -9,7 +9,6 @@ from microdot.session import Session
from settings import Settings from settings import Settings
import aioespnow import aioespnow
import network
import controllers.preset as preset import controllers.preset as preset
import controllers.profile as profile import controllers.profile as profile
import controllers.group as group import controllers.group as group
@@ -27,9 +26,6 @@ async def main(port=80):
print(settings) print(settings)
print("Starting") print("Starting")
sta = network.WLAN(network.STA_IF)
sta.active(True)
# Initialize ESPNow singleton (config + peers) # Initialize ESPNow singleton (config + peers)
esp = ESPNow() esp = ESPNow()

View File

@@ -80,44 +80,6 @@ document.addEventListener('DOMContentLoaded', () => {
} }
} }
async function loadStationStatus() {
try {
const response = await fetch('/settings/wifi/station');
const status = await response.json();
const statusEl = document.getElementById('station-status');
if (!statusEl) return;
if (status.connected) {
statusEl.innerHTML = `
<h4>Connection Status: <span class="status-connected">Connected</span></h4>
<p><strong>SSID:</strong> ${status.ssid || 'N/A'}</p>
<p><strong>IP Address:</strong> ${status.ip || 'N/A'}</p>
<p><strong>Gateway:</strong> ${status.gateway || 'N/A'}</p>
<p><strong>Netmask:</strong> ${status.netmask || 'N/A'}</p>
<p><strong>DNS:</strong> ${status.dns || 'N/A'}</p>
`;
} else {
statusEl.innerHTML = `
<h4>Connection Status: <span class="status-disconnected">Disconnected</span></h4>
<p>Not connected to any WiFi network</p>
`;
}
} catch (error) {
console.error('Error loading station status:', error);
}
}
async function loadStationCredentials() {
try {
const response = await fetch('/settings/wifi/station/credentials');
const creds = await response.json();
if (creds.ssid) document.getElementById('station-ssid').value = creds.ssid;
if (creds.ip) document.getElementById('station-ip').value = creds.ip;
if (creds.gateway) document.getElementById('station-gateway').value = creds.gateway;
} catch (error) {
console.error('Error loading station credentials:', error);
}
}
async function loadAPStatus() { async function loadAPStatus() {
try { try {
const response = await fetch('/settings/wifi/ap'); const response = await fetch('/settings/wifi/ap');
@@ -149,8 +111,6 @@ document.addEventListener('DOMContentLoaded', () => {
settingsModal.classList.add('active'); settingsModal.classList.add('active');
// Load current WiFi status/config when opening // Load current WiFi status/config when opening
loadDeviceSettings(); loadDeviceSettings();
loadStationStatus();
loadStationCredentials();
loadAPStatus(); loadAPStatus();
}); });
} }
@@ -169,45 +129,6 @@ document.addEventListener('DOMContentLoaded', () => {
}); });
} }
const stationForm = document.getElementById('station-form');
if (stationForm) {
stationForm.addEventListener('submit', async (e) => {
e.preventDefault();
const ssid = (document.getElementById('station-ssid').value || '').trim();
if (!ssid) {
showSettingsMessage('SSID is required', 'error');
return;
}
const formData = {
ssid,
password: document.getElementById('station-password').value || '',
ip: (document.getElementById('station-ip').value || '').trim() || null,
gateway: (document.getElementById('station-gateway').value || '').trim() || null,
};
try {
const response = await fetch('/settings/wifi/station', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData),
});
let result = {};
try {
result = await response.json();
} catch (_) {
result = { error: response.status === 400 ? 'Bad request (check SSID and connection)' : 'Request failed' };
}
if (response.ok) {
showSettingsMessage('WiFi station connected successfully!', 'success');
setTimeout(loadStationStatus, 1000);
} else {
showSettingsMessage(`Error: ${result.error || 'Failed to connect'}`, 'error');
}
} catch (error) {
showSettingsMessage(`Error: ${error.message}`, 'error');
}
});
}
const deviceForm = document.getElementById('device-form'); const deviceForm = document.getElementById('device-form');
if (deviceForm) { if (deviceForm) {
deviceForm.addEventListener('submit', async (e) => { deviceForm.addEventListener('submit', async (e) => {

View File

@@ -250,7 +250,7 @@
<div id="settings-modal" class="modal"> <div id="settings-modal" class="modal">
<div class="modal-content"> <div class="modal-content">
<h2>Device Settings</h2> <h2>Device Settings</h2>
<p class="muted-text">Configure WiFi and device settings.</p> <p class="muted-text">Configure WiFi Access Point and device settings.</p>
<div id="settings-message" class="message"></div> <div id="settings-message" class="message"></div>
@@ -269,48 +269,6 @@
</form> </form>
</div> </div>
<!-- WiFi Station Settings -->
<div class="settings-section">
<h3>WiFi Station (Client)</h3>
<div id="station-status" class="status-info">
<h4>Connection Status</h4>
<p>Loading...</p>
</div>
<form id="station-form">
<div class="form-group">
<label for="station-ssid">SSID (Network Name)</label>
<input type="text" id="station-ssid" name="ssid" placeholder="Enter WiFi network name" required>
<small>The name of the WiFi network to connect to</small>
</div>
<div class="form-group">
<label for="station-password">Password</label>
<input type="password" id="station-password" name="password" placeholder="Enter WiFi password">
<small>Leave empty for open networks</small>
</div>
<div class="form-row">
<div class="form-group">
<label for="station-ip">IP Address (Optional)</label>
<input type="text" id="station-ip" name="ip" placeholder="192.168.1.100">
<small>Static IP address (leave empty for DHCP)</small>
</div>
<div class="form-group">
<label for="station-gateway">Gateway (Optional)</label>
<input type="text" id="station-gateway" name="gateway" placeholder="192.168.1.1">
<small>Gateway/router IP address</small>
</div>
</div>
<div class="btn-group">
<button type="submit" class="btn btn-primary btn-full">Connect</button>
</div>
</form>
</div>
<!-- WiFi Access Point Settings --> <!-- WiFi Access Point Settings -->
<div class="settings-section ap-settings-section"> <div class="settings-section ap-settings-section">
<h3>WiFi Access Point</h3> <h3>WiFi Access Point</h3>

View File

@@ -170,53 +170,11 @@
<div class="settings-header"> <div class="settings-header">
<h1>Device Settings</h1> <h1>Device Settings</h1>
<p>Configure WiFi and device settings</p> <p>Configure WiFi Access Point settings</p>
</div> </div>
<div id="message" class="message"></div> <div id="message" class="message"></div>
<!-- WiFi Station Settings -->
<div class="settings-section">
<h2>WiFi Station (Client) Settings</h2>
<div id="station-status" class="status-info">
<h3>Connection Status</h3>
<p>Loading...</p>
</div>
<form id="station-form">
<div class="form-group">
<label for="station-ssid">SSID (Network Name)</label>
<input type="text" id="station-ssid" name="ssid" placeholder="Enter WiFi network name" required>
<small>The name of the WiFi network to connect to</small>
</div>
<div class="form-group">
<label for="station-password">Password</label>
<input type="password" id="station-password" name="password" placeholder="Enter WiFi password">
<small>Leave empty for open networks</small>
</div>
<div class="form-row">
<div class="form-group">
<label for="station-ip">IP Address (Optional)</label>
<input type="text" id="station-ip" name="ip" placeholder="192.168.1.100">
<small>Static IP address (leave empty for DHCP)</small>
</div>
<div class="form-group">
<label for="station-gateway">Gateway (Optional)</label>
<input type="text" id="station-gateway" name="gateway" placeholder="192.168.1.1">
<small>Gateway/router IP address</small>
</div>
</div>
<div class="btn-group">
<button type="submit" class="btn btn-primary btn-full">Connect</button>
</div>
</form>
</div>
<!-- WiFi Access Point Settings --> <!-- WiFi Access Point Settings -->
<div class="settings-section"> <div class="settings-section">
<h2>WiFi Access Point Settings</h2> <h2>WiFi Access Point Settings</h2>
@@ -264,47 +222,6 @@
}, 5000); }, 5000);
} }
// Load station status
async function loadStationStatus() {
try {
const response = await fetch('/settings/wifi/station');
const status = await response.json();
const statusEl = document.getElementById('station-status');
if (status.connected) {
statusEl.innerHTML = `
<h3>Connection Status: <span class="status-connected">Connected</span></h3>
<p><strong>SSID:</strong> ${status.ssid || 'N/A'}</p>
<p><strong>IP Address:</strong> ${status.ip || 'N/A'}</p>
<p><strong>Gateway:</strong> ${status.gateway || 'N/A'}</p>
<p><strong>Netmask:</strong> ${status.netmask || 'N/A'}</p>
<p><strong>DNS:</strong> ${status.dns || 'N/A'}</p>
`;
} else {
statusEl.innerHTML = `
<h3>Connection Status: <span class="status-disconnected">Disconnected</span></h3>
<p>Not connected to any WiFi network</p>
`;
}
} catch (error) {
console.error('Error loading station status:', error);
}
}
// Load saved station credentials
async function loadStationCredentials() {
try {
const response = await fetch('/settings/wifi/station/credentials');
const creds = await response.json();
if (creds.ssid) document.getElementById('station-ssid').value = creds.ssid;
if (creds.ip) document.getElementById('station-ip').value = creds.ip;
if (creds.gateway) document.getElementById('station-gateway').value = creds.gateway;
} catch (error) {
console.error('Error loading station credentials:', error);
}
}
// Load AP status and config // Load AP status and config
async function loadAPStatus() { async function loadAPStatus() {
try { try {
@@ -334,39 +251,6 @@
} }
} }
// Station form submission
document.getElementById('station-form').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = {
ssid: document.getElementById('station-ssid').value,
password: document.getElementById('station-password').value,
ip: document.getElementById('station-ip').value || null,
gateway: document.getElementById('station-gateway').value || null
};
try {
const response = await fetch('/settings/wifi/station', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
});
const result = await response.json();
if (response.ok) {
showMessage('WiFi station connected successfully!', 'success');
setTimeout(loadStationStatus, 1000);
} else {
showMessage(`Error: ${result.error || 'Failed to connect'}`, 'error');
}
} catch (error) {
showMessage(`Error: ${error.message}`, 'error');
}
});
// AP form submission // AP form submission
document.getElementById('ap-form').addEventListener('submit', async (e) => { document.getElementById('ap-form').addEventListener('submit', async (e) => {
e.preventDefault(); e.preventDefault();
@@ -415,15 +299,10 @@
}); });
// Load all data on page load // Load all data on page load
loadStationStatus();
loadStationCredentials();
loadAPStatus(); loadAPStatus();
// Refresh status every 10 seconds // Refresh status every 10 seconds
setInterval(() => { setInterval(loadAPStatus, 10000);
loadStationStatus();
loadAPStatus();
}, 10000);
</script> </script>
</body> </body>
</html> </html>

View File

@@ -1,28 +1,4 @@
import network import network
from time import sleep
def connect(ssid, password, ip, gateway):
if ssid is None:
print("Missing ssid")
return None
if password is None:
password = ''
try:
sta_if = network.WLAN(network.STA_IF)
if ip is not None and gateway is not None:
sta_if.ifconfig((ip, '255.255.255.0', gateway, '1.1.1.1'))
if not sta_if.isconnected():
print('connecting to network...')
sta_if.active(True)
sta_if.connect(ssid, password)
sleep(0.1)
if sta_if.isconnected():
return sta_if.ifconfig()
return None
return sta_if.ifconfig()
except Exception as e:
print(f"Failed to connect to wifi {e}")
return None
def ap(ssid, password, channel=None): def ap(ssid, password, channel=None):
@@ -42,6 +18,7 @@ def get_mac():
ap_if = network.WLAN(network.AP_IF) ap_if = network.WLAN(network.AP_IF)
return ap_if.config('mac') return ap_if.config('mac')
def get_ap_config(): def get_ap_config():
"""Get current AP configuration.""" """Get current AP configuration."""
try: try:
@@ -63,38 +40,3 @@ def get_ap_config():
except Exception as e: except Exception as e:
print(f"Error getting AP config: {e}") print(f"Error getting AP config: {e}")
return None return None
def get_sta_status():
"""Get current station connection status."""
try:
sta_if = network.WLAN(network.STA_IF)
if sta_if.active():
if sta_if.isconnected():
config = sta_if.ifconfig()
return {
'connected': True,
'ssid': sta_if.config('essid'),
'ip': config[0] if config else None,
'gateway': config[2] if len(config) > 2 else None,
'netmask': config[1] if len(config) > 1 else None,
'dns': config[3] if len(config) > 3 else None
}
return {
'connected': False,
'ssid': None,
'ip': None,
'gateway': None,
'netmask': None,
'dns': None
}
return {
'connected': False,
'ssid': None,
'ip': None,
'gateway': None,
'netmask': None,
'dns': None
}
except Exception as e:
print(f"Error getting STA status: {e}")
return None