fix: align ESP32 WiFi SSID/channel with QEMU access_points[] array
Two fixes for ESP32 WiFi not connecting in production: 1. espidf_compiler.py: Change WiFi normalization from 'Velxio-GUEST' on channel 6 to 'Espressif' on channel 5. The lcgamboa QEMU binary downloaded from GitHub Releases only contains the original three APs: PICSimLabWifi (ch1), Espressif (ch5), MasseyWifi (ch10). Channel 6 had no matching AP, so the beacon timer's channel-match condition never fired → firmware scanned forever and never connected. 2. esp32_worker.py: Redirect fd 1 to /dev/null before loading QEMU so raw UART bytes from QEMU's -nographic mux don't corrupt the JSON event pipe. The real pipe fd is saved and sys.stdout is rebound so _emit() continues to work. This also prevents stdout pipe back-pressure from stalling qemu_main_loop() (and thus REALTIME timers). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2a386f99b0
commit
ef299ba7fa
|
|
@ -611,6 +611,25 @@ def main() -> None: # noqa: C901 (complexity OK for inline worker)
|
|||
os.dup2(_nul, 0)
|
||||
os.close(_nul)
|
||||
|
||||
# Also redirect fd 1 (stdout) to /dev/null so QEMU's -nographic UART mux
|
||||
# doesn't write raw UART bytes onto our JSON event pipe. Without this:
|
||||
# 1. Raw UART bytes prefix each JSON line, corrupting the protocol.
|
||||
# 2. On a busy host the pipe fills up, causing _on_uart_tx (called
|
||||
# synchronously from qemu_main_loop) to block inside sys.stdout.flush(),
|
||||
# which stalls qemu_main_loop() and prevents QEMU_CLOCK_REALTIME timers
|
||||
# (including Esp32_WLAN_beacon_timer) from firing → WiFi never connects.
|
||||
# Save the real pipe fd and rebind sys.stdout so _emit() keeps working.
|
||||
import io as _io
|
||||
_orig_stdout_fd = os.dup(1)
|
||||
_nul_w = os.open(os.devnull, os.O_WRONLY)
|
||||
os.dup2(_nul_w, 1)
|
||||
os.close(_nul_w)
|
||||
sys.stdout = _io.TextIOWrapper(
|
||||
_io.FileIO(_orig_stdout_fd, mode='w', closefd=True),
|
||||
line_buffering=True,
|
||||
write_through=True,
|
||||
)
|
||||
|
||||
qemu_t = threading.Thread(target=_qemu_thread, daemon=True, name=f'qemu-{machine}')
|
||||
qemu_t.start()
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,11 @@ _STATIC_IP = '192.168.4.15'
|
|||
_GATEWAY_IP = '192.168.4.2'
|
||||
_NETMASK = '255.255.255.0'
|
||||
|
||||
# SSID the QEMU WiFi AP broadcasts
|
||||
_QEMU_WIFI_SSID = 'Velxio-GUEST'
|
||||
# SSID the QEMU WiFi AP broadcasts.
|
||||
# Must match one of the access_point_info entries in esp32_wifi_ap.c
|
||||
# (the lcgamboa QEMU fork). "Espressif" is on channel 5 in that array.
|
||||
_QEMU_WIFI_SSID = 'Espressif'
|
||||
_QEMU_WIFI_CHANNEL = 5
|
||||
|
||||
|
||||
class ESPIDFCompiler:
|
||||
|
|
@ -109,11 +112,11 @@ class ESPIDFCompiler:
|
|||
"""
|
||||
Normalize WiFi SSID/password/channel in Arduino sketches for QEMU.
|
||||
|
||||
QEMU's WiFi AP broadcasts "Velxio-GUEST" on channel 6 with open auth.
|
||||
QEMU's WiFi AP broadcasts _QEMU_WIFI_SSID on _QEMU_WIFI_CHANNEL with open auth.
|
||||
This method rewrites the user's sketch so that:
|
||||
- Any SSID string literal → "Velxio-GUEST"
|
||||
- Any SSID string literal → _QEMU_WIFI_SSID
|
||||
- Password → "" (open auth)
|
||||
- Channel → 6
|
||||
- Channel → _QEMU_WIFI_CHANNEL
|
||||
The user's editor still shows their original code; only the compiled
|
||||
binary is modified.
|
||||
"""
|
||||
|
|
@ -121,9 +124,9 @@ class ESPIDFCompiler:
|
|||
return code
|
||||
|
||||
# 1) Replace SSID variable definitions:
|
||||
# const char* ssid = "anything" → "Velxio-GUEST"
|
||||
# char ssid[] = "anything" → "Velxio-GUEST"
|
||||
# #define WIFI_SSID "anything" → "Velxio-GUEST"
|
||||
# const char* ssid = "anything" → _QEMU_WIFI_SSID
|
||||
# char ssid[] = "anything" → _QEMU_WIFI_SSID
|
||||
# #define WIFI_SSID "anything" → _QEMU_WIFI_SSID
|
||||
code = re.sub(
|
||||
r'((?:const\s+)?char\s*\*?\s*ssid\s*\[?\]?\s*=\s*)"[^"]*"',
|
||||
rf'\1"{_QEMU_WIFI_SSID}"',
|
||||
|
|
@ -138,19 +141,19 @@ class ESPIDFCompiler:
|
|||
)
|
||||
|
||||
# 2) Normalize WiFi.begin() calls:
|
||||
# WiFi.begin("X") → WiFi.begin("Velxio-GUEST", "", 6)
|
||||
# WiFi.begin("X", "pass") → WiFi.begin("Velxio-GUEST", "", 6)
|
||||
# WiFi.begin(ssid, pass, N) → WiFi.begin(ssid, "", 6)
|
||||
# WiFi.begin(ssid) → WiFi.begin(ssid, "", 6)
|
||||
# WiFi.begin("X") → WiFi.begin(_QEMU_WIFI_SSID, "", _QEMU_WIFI_CHANNEL)
|
||||
# WiFi.begin("X", "pass") → WiFi.begin(_QEMU_WIFI_SSID, "", _QEMU_WIFI_CHANNEL)
|
||||
# WiFi.begin(ssid, pass, N) → WiFi.begin(ssid, "", _QEMU_WIFI_CHANNEL)
|
||||
# WiFi.begin(ssid) → WiFi.begin(ssid, "", _QEMU_WIFI_CHANNEL)
|
||||
|
||||
def _rewrite_wifi_begin(m: re.Match) -> str:
|
||||
args = m.group(1)
|
||||
parts = [a.strip() for a in args.split(',')]
|
||||
ssid_arg = parts[0]
|
||||
# If SSID is a string literal, force to Velxio-GUEST
|
||||
# If SSID is a string literal, force to _QEMU_WIFI_SSID
|
||||
if ssid_arg.startswith('"'):
|
||||
ssid_arg = f'"{_QEMU_WIFI_SSID}"'
|
||||
return f'WiFi.begin({ssid_arg}, "", 6)'
|
||||
return f'WiFi.begin({ssid_arg}, "", {_QEMU_WIFI_CHANNEL})'
|
||||
|
||||
code = re.sub(
|
||||
r'WiFi\.begin\s*\(([^)]+)\)',
|
||||
|
|
@ -158,7 +161,7 @@ class ESPIDFCompiler:
|
|||
code
|
||||
)
|
||||
|
||||
logger.info('[espidf] WiFi normalized: SSID→%s, channel→6, open auth', _QEMU_WIFI_SSID)
|
||||
logger.info('[espidf] WiFi normalized: SSID→%s, channel→%d, open auth', _QEMU_WIFI_SSID, _QEMU_WIFI_CHANNEL)
|
||||
return code
|
||||
|
||||
def _translate_sketch_to_espidf(self, sketch_code: str) -> str:
|
||||
|
|
|
|||
Loading…
Reference in New Issue