diff --git a/frontend/src/data/examples.ts b/frontend/src/data/examples.ts index 2a9a7c73..8b0456ad 100644 --- a/frontend/src/data/examples.ts +++ b/frontend/src/data/examples.ts @@ -5026,7 +5026,7 @@ void loop() { { id: 'w-btn', start: { componentId: 'arduino-uno', pinName: '2' }, - end: { componentId: 'btn1', pinName: '1a' }, + end: { componentId: 'btn1', pinName: '1.l' }, color: '#00aaff', }, { @@ -5043,7 +5043,7 @@ void loop() { }, { id: 'w-btn-gnd', - start: { componentId: 'btn1', pinName: '1b' }, + start: { componentId: 'btn1', pinName: '2.l' }, end: { componentId: 'arduino-uno', pinName: 'GND' }, color: '#000000', }, diff --git a/frontend/src/simulation/Esp32Bridge.ts b/frontend/src/simulation/Esp32Bridge.ts index da9f34e1..944cb616 100644 --- a/frontend/src/simulation/Esp32Bridge.ts +++ b/frontend/src/simulation/Esp32Bridge.ts @@ -48,8 +48,20 @@ export function toQemuBoardType(kind: BoardKind): 'esp32' | 'esp32-s3' | 'esp32- return 'esp32'; // esp32, esp32-devkit-c-v4, esp32-cam, wemos-lolin32-lite } -const API_BASE = (): string => - (import.meta.env.VITE_API_BASE as string | undefined) ?? 'http://localhost:8001/api'; +const API_BASE = (): string => { + // The desktop shell injects the sidecar URL at runtime (random port) via + // window.__VELXIO_API_BASE__; honor it first so the QEMU-board WebSocket + // reaches the local Python sidecar instead of the build-time / dev + // default. Without this, ESP32 / Pi / STM32 simulations never start in + // the desktop app (the WS dialed localhost:8001, not the sidecar port). + if (typeof window !== 'undefined') { + const injected = (window as { __VELXIO_API_BASE__?: string }).__VELXIO_API_BASE__; + if (typeof injected === 'string' && injected) { + return injected.replace(/\/+$/, ''); + } + } + return (import.meta.env.VITE_API_BASE as string | undefined) ?? 'http://localhost:8001/api'; +}; /** Returns a stable UUID for this browser tab (persists across reloads, resets on new tab). */ export function getTabSessionId(): string { diff --git a/frontend/src/simulation/RaspberryPi3Bridge.ts b/frontend/src/simulation/RaspberryPi3Bridge.ts index eb66a2c0..352c8dd3 100644 --- a/frontend/src/simulation/RaspberryPi3Bridge.ts +++ b/frontend/src/simulation/RaspberryPi3Bridge.ts @@ -27,8 +27,20 @@ * { type: 'error', data: { message: string } } */ -const API_BASE = (): string => - (import.meta.env.VITE_API_BASE as string | undefined) ?? 'http://localhost:8001/api'; +const API_BASE = (): string => { + // The desktop shell injects the sidecar URL at runtime (random port) via + // window.__VELXIO_API_BASE__; honor it first so the QEMU-board WebSocket + // reaches the local Python sidecar instead of the build-time / dev + // default. Without this, ESP32 / Pi / STM32 simulations never start in + // the desktop app (the WS dialed localhost:8001, not the sidecar port). + if (typeof window !== 'undefined') { + const injected = (window as { __VELXIO_API_BASE__?: string }).__VELXIO_API_BASE__; + if (typeof injected === 'string' && injected) { + return injected.replace(/\/+$/, ''); + } + } + return (import.meta.env.VITE_API_BASE as string | undefined) ?? 'http://localhost:8001/api'; +}; export class RaspberryPi3Bridge { readonly boardId: string; diff --git a/frontend/src/simulation/Stm32Bridge.ts b/frontend/src/simulation/Stm32Bridge.ts index 517d1508..f9a5bb11 100644 --- a/frontend/src/simulation/Stm32Bridge.ts +++ b/frontend/src/simulation/Stm32Bridge.ts @@ -27,8 +27,20 @@ import type { BoardKind } from '../types/board'; import { generateUUID } from '../utils/uuid'; -const API_BASE = (): string => - (import.meta.env.VITE_API_BASE as string | undefined) ?? 'http://localhost:8001/api'; +const API_BASE = (): string => { + // The desktop shell injects the sidecar URL at runtime (random port) via + // window.__VELXIO_API_BASE__; honor it first so the QEMU-board WebSocket + // reaches the local Python sidecar instead of the build-time / dev + // default. Without this, ESP32 / Pi / STM32 simulations never start in + // the desktop app (the WS dialed localhost:8001, not the sidecar port). + if (typeof window !== 'undefined') { + const injected = (window as { __VELXIO_API_BASE__?: string }).__VELXIO_API_BASE__; + if (typeof injected === 'string' && injected) { + return injected.replace(/\/+$/, ''); + } + } + return (import.meta.env.VITE_API_BASE as string | undefined) ?? 'http://localhost:8001/api'; +}; export function getTabSessionId(): string { if (typeof sessionStorage === 'undefined') return generateUUID(); diff --git a/frontend/src/simulation/cyw43/Cyw43Bridge.ts b/frontend/src/simulation/cyw43/Cyw43Bridge.ts index b7781d73..d29ebdc0 100644 --- a/frontend/src/simulation/cyw43/Cyw43Bridge.ts +++ b/frontend/src/simulation/cyw43/Cyw43Bridge.ts @@ -35,8 +35,20 @@ export interface WifiStatus { export interface PacketOutFrame { ether: Uint8Array; } export interface PacketInFrame { ether: Uint8Array; } -const API_BASE = (): string => - (import.meta.env.VITE_API_BASE as string | undefined) ?? 'http://localhost:8001/api'; +const API_BASE = (): string => { + // The desktop shell injects the sidecar URL at runtime (random port) via + // window.__VELXIO_API_BASE__; honor it first so the QEMU-board WebSocket + // reaches the local Python sidecar instead of the build-time / dev + // default. Without this, ESP32 / Pi / STM32 simulations never start in + // the desktop app (the WS dialed localhost:8001, not the sidecar port). + if (typeof window !== 'undefined') { + const injected = (window as { __VELXIO_API_BASE__?: string }).__VELXIO_API_BASE__; + if (typeof injected === 'string' && injected) { + return injected.replace(/\/+$/, ''); + } + } + return (import.meta.env.VITE_API_BASE as string | undefined) ?? 'http://localhost:8001/api'; +}; export class Cyw43Bridge { readonly boardId: string;