From c55e399055a03b4a9c92eec6bce4f13fb6af92ce Mon Sep 17 00:00:00 2001 From: David Montero Crespo Date: Wed, 29 Jul 2026 17:26:02 +0200 Subject: [PATCH] fix(uart): el hook de TX de la Pi se reinstala cuando nace el bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Las rutas serie se construyen al cargar la pagina, pero el bridge de una placa QEMU-Linux nace al pulsar Run: ensureSerialHook encontraba bridge nulo, hacia no-op y nadie volvia a intentarlo — los bytes que el guest transmitia por el header salian del backend (uart_tx) y morian en un onUartTx sin instalar. reensureSerialHooks(boardId) repite el enganche (idempotente por el flag) y el store lo llama al crear el bridge. --- frontend/src/simulation/Interconnect.ts | 12 ++++++++++++ frontend/src/store/useSimulatorStore.ts | 5 +++++ 2 files changed, 17 insertions(+) diff --git a/frontend/src/simulation/Interconnect.ts b/frontend/src/simulation/Interconnect.ts index 28ba9a5a..51709cd9 100644 --- a/frontend/src/simulation/Interconnect.ts +++ b/frontend/src/simulation/Interconnect.ts @@ -747,6 +747,18 @@ export function notifyBoardReady(_boardId: string, wires: readonly Wire[]): void updateI2CBridges(wires); } +/** + * Re-attempt the serial hook for a board whose sim/bridge did not exist + * when the routes were built. Routes are installed at page load; a Pi's + * bridge is created at Run — so the TX hook silently no-opped and the + * guest's UART bytes never reached the wire. The store calls this when + * the bridge connects; ensureSerialHook is idempotent via its flag. + */ +export function reensureSerialHooks(boardId: string): void { + const entry = boards.get(boardId); + if (entry && entry.serialFanout.size > 0) ensureSerialHook(entry); +} + /** For tests: reset all internal state. */ export function resetInterconnect(): void { for (const r of routes.values()) r.teardown(); diff --git a/frontend/src/store/useSimulatorStore.ts b/frontend/src/store/useSimulatorStore.ts index 1b080194..a2cab443 100644 --- a/frontend/src/store/useSimulatorStore.ts +++ b/frontend/src/store/useSimulatorStore.ts @@ -55,6 +55,7 @@ import { isBreadboard } from '../utils/breadboardNets'; import { computeSeating } from '../utils/breadboardSnap'; import { createSerialBatcher } from './serialBatcher'; import { + reensureSerialHooks as icReensureSerialHooks, bindBoard as icBindBoard, unbindBoard as icUnbindBoard, updateWires as icUpdateWires, @@ -1344,6 +1345,10 @@ export const useSimulatorStore = create((set, get) => { }); }; bridgeMap.set(id, bridge); + // The UART routes were built at page load, when this bridge did + // not exist — re-attempt the TX hook now that it does, or the + // guest's header-UART bytes never reach the canvas wire. + icReensureSerialHooks(id); } else if (isEsp32Kind(boardKind)) { wireEsp32Board(id, boardKind, pm); } else if (isStm32BoardKind(boardKind)) {