Add Wi-Fi scan details display and MQTT publish

- HTML: Add Wi-Fi scan results container to network.html
- Rust: Implement `wifi_scan_details()` with RSSI, channel, auth method
- API & UI: Fetch and display scan results in table format
- MQTT: Publish top 10 networks sorted by RSSI to `/wifi_scan`
This commit is contained in:
2026-05-28 00:46:14 +02:00
parent 3618b3329c
commit 6b419dba6c
10 changed files with 180 additions and 10 deletions

View File

@@ -225,6 +225,15 @@ export interface Detection {
plant: DetectionPlant[]
}
/// Wi-Fi scan result details for UI display
export interface WifiScanResult {
ssid: string,
bssid: string,
rssi: number, // signal strength in dBm
channel: number,
auth_method: string
}
export interface TankInfo {
/// there is enough water in the tank
enough_water: boolean,

View File

@@ -37,7 +37,7 @@
}
#logpanel {
display: none;
}
</style>

View File

@@ -26,7 +26,7 @@ import {
Moistures,
NightLampCommand,
PlantControllerConfig,
SetTime, SSIDList, TankInfo,
SetTime, SSIDList, TankInfo, WifiScanResult,
TestPump,
VersionInfo,
SaveInfo, SolarState, PumpTestResult, Detection, DetectionRequest, CanPower
@@ -172,6 +172,21 @@ export class Controller {
}
}
async scanWifiDetails(): Promise<void> {
try {
const response = await fetch(PUBLIC_URL + "/wifi_details");
if (response.ok) {
const wifiDetails = await response.json();
controller.networkView.displayWifiResults(wifiDetails as WifiScanResult[]);
} else {
toast.error(`Failed to fetch Wi-Fi details: ${response.status}`);
}
} catch (error) {
toast.error(`Wi-Fi details error: ${error}`);
console.log(error);
}
}
uploadNewFirmware(file: File) {
let current = 0;
let max = 100;
@@ -501,6 +516,8 @@ export class Controller {
if (ajax.status >= 200 && ajax.status < 300) {
this.networkView.setScanResult(ajax.response as SSIDList);
toast.success("WiFi scan completed");
// Also fetch detailed Wi-Fi information
this.scanWifiDetails();
} else {
toast.error(`WiFi scan failed: ${ajax.status}`);
}

View File

@@ -85,7 +85,15 @@
<input class="mqttvalue" type="text" id="mqtt_password" placeholder="">
</div>
</div>
<div class="subcontainer">
<div class="flexcontainer">
<div class="subtitle">Wi-Fi Scan Results</div>
</div>
<div id="wifi-results">
<p>Scan for available networks to see signal strength</p>
</div>
</div>
</div>
</div>

View File

@@ -1,7 +1,9 @@
import { Controller } from "./main";
import {NetworkConfig, SSIDList} from "./api";
import {NetworkConfig, SSIDList, WifiScanResult} from "./api";
export class NetworkConfigView {
private wifiResults: HTMLElement;
setScanResult(ssidList: SSIDList) {
this.ssidlist.innerHTML = ''
for (const ssid of ssidList.ssids) {
@@ -10,6 +12,47 @@ export class NetworkConfigView {
this.ssidlist.appendChild(wi);
}
}
async scanAndDisplayWifiDetails() {
try {
const response = await fetch('/wifi_details');
if (response.ok) {
const data: WifiScanResult[] = await response.json();
this.displayWifiResults(data);
}
} catch (error) {
console.error('Error fetching Wi-Fi details:', error);
this.displayWifiResults([]);
}
}
displayWifiResults(results: WifiScanResult[]) {
const wifiContainer = document.getElementById('wifi-results');
if (!wifiContainer) return;
if (results.length === 0) {
wifiContainer.innerHTML = '<p>No Wi-Fi networks found</p>';
return;
}
let html = '<table style="width:100%; border-collapse: collapse;">';
html += '<tr><th style="text-align:left; padding: 8px;">SSID</th>';
html += '<th style="text-align:left; padding: 8px;">Signal (RSSI)</th>';
html += '<th style="text-align:left; padding: 8px;">Channel</th>';
html += '<th style="text-align:left; padding: 8px;">Authentication</th></tr>';
results.forEach(result => {
html += '<tr style="border-bottom: 1px solid #ddd;">';
html += `<td style="padding: 8px;">${result.ssid}</td>`;
html += `<td style="padding: 8px;">${result.rssi} dBm</td>`;
html += `<td style="padding: 8px;">${result.channel}</td>`;
html += `<td style="padding: 8px;">${result.auth_method}</td>`;
html += '</tr>';
});
html += '</table>';
wifiContainer.innerHTML = html;
}
private readonly ap_ssid: HTMLInputElement;
private readonly ssid: HTMLInputElement;
private readonly password: HTMLInputElement;
@@ -47,9 +90,14 @@ export class NetworkConfigView {
this.ssidlist = document.getElementById("ssidlist") as HTMLElement
let scanWifiBtn = document.getElementById("scan") as HTMLButtonElement;
scanWifiBtn.onclick = function (){
scanWifiBtn.onclick = async () => {
controller.scanWifi();
}
// After Wi-Fi scan, fetch and display detailed results
await this.scanAndDisplayWifiDetails();
};
// Store wifiResults reference for later use
this.wifiResults = document.getElementById('wifi-results') as HTMLElement;
}
setConfig(network: NetworkConfig) {