Fix WiFi list duplicates and ignore cancelled operation errors

- Deduplicate WiFi networks by SSID, keeping strongest signal
- Skip empty SSIDs from BLE response
- Ignore "Operation was cancelled" (error code 2) which is normal
  during cleanup when subscription is removed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Sergei 2026-01-26 18:47:17 -08:00
parent 20911fe521
commit c17292ea48

View File

@ -260,12 +260,23 @@ export class RealBLEManager implements IBLEManager {
// Safe reject wrapper to handle null error messages (Android BLE crash fix) // Safe reject wrapper to handle null error messages (Android BLE crash fix)
const safeReject = (error: any) => { const safeReject = (error: any) => {
if (responseReceived) return; if (responseReceived) return;
// Extract error code (numeric or string)
const errorCode = error?.errorCode || error?.code || 'BLE_ERROR';
// Ignore "Operation was cancelled" (code 2) - this is expected when we cleanup
// This happens when subscription is removed but BLE still tries to send callback
if (errorCode === 2 || errorCode === 'OperationCancelled' ||
(error?.message && error.message.includes('cancelled'))) {
console.log('[BLE] Ignoring cancelled operation (normal cleanup)');
return;
}
responseReceived = true; responseReceived = true;
cleanup(); cleanup();
// Ensure error has a valid message (fixes Android NullPointerException) // Ensure error has a valid message (fixes Android NullPointerException)
const errorMessage = error?.message || error?.reason || 'BLE operation failed'; const errorMessage = error?.message || error?.reason || 'BLE operation failed';
const errorCode = error?.errorCode || error?.code || 'BLE_ERROR';
reject(new Error(`[${errorCode}] ${errorMessage}`)); reject(new Error(`[${errorCode}] ${errorMessage}`));
}; };
@ -366,19 +377,30 @@ export class RealBLEManager implements IBLEManager {
} }
} }
const networks: WiFiNetwork[] = []; // Use Map to deduplicate by SSID, keeping the strongest signal
const networksMap = new Map<string, WiFiNetwork>();
for (let i = 3; i < parts.length; i++) { for (let i = 3; i < parts.length; i++) {
const [ssid, rssiStr] = parts[i].split(','); const [ssid, rssiStr] = parts[i].split(',');
if (ssid && rssiStr) { if (ssid && rssiStr) {
networks.push({ const trimmedSsid = ssid.trim();
ssid: ssid.trim(), const rssi = parseInt(rssiStr, 10);
rssi: parseInt(rssiStr, 10),
}); // Skip empty SSIDs
if (!trimmedSsid) continue;
// Keep the one with strongest signal if duplicate
const existing = networksMap.get(trimmedSsid);
if (!existing || rssi > existing.rssi) {
networksMap.set(trimmedSsid, {
ssid: trimmedSsid,
rssi: rssi,
});
}
} }
} }
// Sort by signal strength (strongest first) // Convert to array and sort by signal strength (strongest first)
return networks.sort((a, b) => b.rssi - a.rssi); return Array.from(networksMap.values()).sort((a, b) => b.rssi - a.rssi);
} }
async setWiFi(deviceId: string, ssid: string, password: string): Promise<boolean> { async setWiFi(deviceId: string, ssid: string, password: string): Promise<boolean> {