fix: propagate has_wifi from compiler to startBoard for reliable WiFi detection

Frontend WiFi detection via file-content scanning was unreliable because
fileGroups[board.activeFileGroupId] could be an empty array (not null),
bypassing the ?? fallback to editorState.files.

Fix: the ESP-IDF compiler now returns has_wifi:bool in its compile response.
The frontend stores this on the BoardInstance and uses it in startBoard()
instead of scanning file contents. The file-content scan is kept as a
fallback for boards that haven't been compiled in this session.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
master
David Montero 2026-04-05 22:14:40 +02:00
parent 7c755ca3d1
commit 32acf80e0d
6 changed files with 32 additions and 13 deletions

View File

@ -29,6 +29,7 @@ class CompileResponse(BaseModel):
hex_content: str | None = None hex_content: str | None = None
binary_content: str | None = None # base64-encoded .bin for RP2040 binary_content: str | None = None # base64-encoded .bin for RP2040
binary_type: str | None = None # 'bin' or 'uf2' binary_type: str | None = None # 'bin' or 'uf2'
has_wifi: bool = False # True when sketch uses WiFi (ESP32 only)
stdout: str stdout: str
stderr: str stderr: str
error: str | None = None error: str | None = None
@ -63,6 +64,7 @@ async def compile_sketch(request: CompileRequest):
hex_content=result.get("hex_content"), hex_content=result.get("hex_content"),
binary_content=result.get("binary_content"), binary_content=result.get("binary_content"),
binary_type=result.get("binary_type"), binary_type=result.get("binary_type"),
has_wifi=result.get("has_wifi", False),
stdout=result.get("stdout", ""), stdout=result.get("stdout", ""),
stderr=result.get("stderr", ""), stderr=result.get("stderr", ""),
error=result.get("error"), error=result.get("error"),

View File

@ -477,6 +477,8 @@ class ESPIDFCompiler:
# QEMU's WiFi AP broadcasts "Velxio-GUEST" on channel 6. # QEMU's WiFi AP broadcasts "Velxio-GUEST" on channel 6.
# We normalize ANY user SSID → "Velxio-GUEST", enforce channel 6, # We normalize ANY user SSID → "Velxio-GUEST", enforce channel 6,
# and use open auth (empty password) so the connection always works. # and use open auth (empty password) so the connection always works.
# Detect WiFi BEFORE normalization so the flag reflects the original sketch.
has_wifi = self._detect_wifi_usage(main_content)
main_content = self._normalize_wifi_for_qemu(main_content) main_content = self._normalize_wifi_for_qemu(main_content)
if self.has_arduino: if self.has_arduino:
@ -622,13 +624,14 @@ class ESPIDFCompiler:
} }
binary_b64 = base64.b64encode(merged_path.read_bytes()).decode('ascii') binary_b64 = base64.b64encode(merged_path.read_bytes()).decode('ascii')
logger.info(f'[espidf] Compilation successful — {len(binary_b64) // 1024} KB (base64)') logger.info(f'[espidf] Compilation successful — {len(binary_b64) // 1024} KB (base64), has_wifi={has_wifi}')
return { return {
'success': True, 'success': True,
'hex_content': None, 'hex_content': None,
'binary_content': binary_b64, 'binary_content': binary_b64,
'binary_type': 'bin', 'binary_type': 'bin',
'has_wifi': has_wifi,
'stdout': all_stdout, 'stdout': all_stdout,
'stderr': all_stderr, 'stderr': all_stderr,
} }

View File

@ -49,6 +49,7 @@ export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compi
boards, boards,
activeBoardId, activeBoardId,
compileBoardProgram, compileBoardProgram,
updateBoard,
startBoard, startBoard,
stopBoard, stopBoard,
resetBoard, resetBoard,
@ -135,6 +136,9 @@ export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compi
const program = result.hex_content ?? result.binary_content ?? null; const program = result.hex_content ?? result.binary_content ?? null;
if (program && activeBoardId) { if (program && activeBoardId) {
compileBoardProgram(activeBoardId, program); compileBoardProgram(activeBoardId, program);
if (result.has_wifi !== undefined) {
updateBoard(activeBoardId, { hasWifi: result.has_wifi });
}
} }
setMessage({ type: 'success', text: 'Compiled successfully' }); setMessage({ type: 'success', text: 'Compiled successfully' });
markCompiled(); markCompiled();
@ -279,7 +283,12 @@ export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compi
if (result.success) { if (result.success) {
const program = result.hex_content ?? result.binary_content ?? null; const program = result.hex_content ?? result.binary_content ?? null;
if (program) compileBoardProgram(board.id, program); if (program) {
compileBoardProgram(board.id, program);
if (result.has_wifi !== undefined) {
updateBoard(board.id, { hasWifi: result.has_wifi });
}
}
updateStatus({ state: 'success' }); updateStatus({ state: 'success' });
} else { } else {
updateStatus({ state: 'error', error: result.stderr || result.error || 'Compilation failed' }); updateStatus({ state: 'error', error: result.stderr || result.error || 'Compilation failed' });

View File

@ -12,6 +12,7 @@ export interface CompileResult {
hex_content?: string; hex_content?: string;
binary_content?: string; // base64-encoded .bin for RP2040 binary_content?: string; // base64-encoded .bin for RP2040
binary_type?: 'bin' | 'uf2'; binary_type?: 'bin' | 'uf2';
has_wifi?: boolean; // True when sketch uses WiFi (ESP32 only)
stdout: string; stdout: string;
stderr: string; stderr: string;
error?: string; error?: string;

View File

@ -659,17 +659,20 @@ export const useSimulatorStore = create<SimulatorState>((set, get) => {
} }
esp32Bridge.setSensors(sensors); esp32Bridge.setSensors(sensors);
// Auto-detect WiFi usage in this board's sketch files. // Use WiFi flag set by the compiler (most reliable — avoids stale file group issues).
// Use the board's file group (not the legacy global files array). // Fall back to scanning the active file group if the flag hasn't been set yet.
const editorState = useEditorStore.getState(); let hasWifi = board.hasWifi;
const boardFiles = editorState.fileGroups[board.activeFileGroupId] if (hasWifi === undefined) {
?? editorState.files; const editorState = useEditorStore.getState();
const hasWifi = boardFiles.some(f => const rawFiles = editorState.fileGroups[board.activeFileGroupId];
f.content.includes('#include <WiFi.h>') || const boardFiles = (rawFiles && rawFiles.length > 0) ? rawFiles : editorState.files;
f.content.includes('#include <esp_wifi.h>') || hasWifi = boardFiles.some(f =>
f.content.includes('#include "WiFi.h"') || f.content.includes('#include <WiFi.h>') ||
f.content.includes('WiFi.begin(') f.content.includes('#include <esp_wifi.h>') ||
); f.content.includes('#include "WiFi.h"') ||
f.content.includes('WiFi.begin(')
);
}
esp32Bridge.wifiEnabled = hasWifi; esp32Bridge.wifiEnabled = hasWifi;
// Ensure firmware is loaded into the bridge (handles page-refresh case // Ensure firmware is loaded into the bridge (handles page-refresh case

View File

@ -38,6 +38,7 @@ export interface BoardInstance {
serialBaudRate: number; serialBaudRate: number;
serialMonitorOpen: boolean; serialMonitorOpen: boolean;
activeFileGroupId: string; activeFileGroupId: string;
hasWifi?: boolean; // set by compiler — true when sketch uses WiFi
wifiStatus?: WifiStatus; wifiStatus?: WifiStatus;
bleStatus?: BleStatus; bleStatus?: BleStatus;
} }