feat: STM32 (Blue Pill / Black Pill) QEMU emulation + Pro board gating
STM32 emulation (open-core, runs via libqemu-arm in the backend worker):
- backend: stm32_lib_manager + stm32_worker (GPIO, USART, I2C/SPI device models
reusing the ESP32 slaves, live sensor updates), arduino_cli STM32 branch,
start_stm32 simulation route.
- frontend: Stm32Bridge + Stm32BluePill(/BlackPill) web components (Wokwi SVGs),
board kinds, Interconnect/boardPinMapping/boardProtocols wiring, example
projects (blink, serial, I2C BMP280/MPU6050/DS1307/SSD1306/weather, 7-seg,
RGB, button, switch, stepper, cross-board interconnect).
- Raspberry Pi 4/5 board elements + thumbnails.
Pro board gating (generic OSS->Pro seam; entitlement logic lives in the overlay):
- lib/proBoardGate.ts: isProBoardKind (STM32 + every QEMU Raspberry Pi),
installBoardGateImpl/boardGateDecision, triggerProUpgradePrompt.
- PRO badge on those boards in the component picker; gate at the picker add +
the run backstop (startBoard).
- backend/app/services/board_access.py: server-side enforcement seam for the
simulation WebSocket; STM32/Pi unavailable -> Pro-framed message.
- desktop: generic QemuDownloadPrompt + Stm32QemuPrompt (download-behind-license,
mirrors the ESP32 prompt).
- .gitignore: never ship libqemu-* binaries in the public image.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 05:06:14 +07:00
|
|
|
"""
|
|
|
|
|
Pro board-access gate — server-side enforcement seam.
|
|
|
|
|
|
|
|
|
|
STM32 and the QEMU-backed Raspberry Pi boards are Pro-only on velxio.dev. The
|
|
|
|
|
frontend gate (picker add + run) is the UX layer; this is the server-side
|
|
|
|
|
enforcement for the WebSocket simulation start, because on velxio.dev the QEMU
|
|
|
|
|
binary is present for every session, so the frontend gate alone is bypassable.
|
|
|
|
|
|
|
|
|
|
OSS / self-hosted has no binary at all (the start fails with a Pro-framed
|
|
|
|
|
message regardless), so this gate is a no-op there.
|
|
|
|
|
|
|
|
|
|
The pro overlay calls ``register_board_access_gate()`` from ``register_pro()``
|
|
|
|
|
with an implementation that resolves the user from the WebSocket cookies and
|
|
|
|
|
returns False for a non-paid web user. The desktop sidecar (VELXIO_DESKTOP=1)
|
|
|
|
|
always allows — the Tauri license already gates the whole app. Default with no
|
|
|
|
|
overlay installed: allow.
|
|
|
|
|
|
|
|
|
|
This mirrors the existing ``try: from app.pro import register_pro`` extension
|
|
|
|
|
pattern — a generic seam any private extension could populate.
|
|
|
|
|
"""
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import logging
|
|
|
|
|
from typing import Awaitable, Callable, Optional
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
# gate(websocket, board_kind) -> True to allow, False to block (Pro-gated).
|
|
|
|
|
BoardAccessGate = Callable[[object, str], Awaitable[bool]]
|
|
|
|
|
|
|
|
|
|
_gate: Optional[BoardAccessGate] = None
|
|
|
|
|
|
2026-08-26 00:22:29 +07:00
|
|
|
# Deliberately names the families, not one board: the QEMU-Linux lane also
|
|
|
|
|
# carries boards that are not Raspberry Pis (the UNIHIKER M10 boots through
|
|
|
|
|
# the same bridge), and telling their user that "Raspberry Pi emulation" is
|
|
|
|
|
# gated is a message about a board they did not place.
|
feat: STM32 (Blue Pill / Black Pill) QEMU emulation + Pro board gating
STM32 emulation (open-core, runs via libqemu-arm in the backend worker):
- backend: stm32_lib_manager + stm32_worker (GPIO, USART, I2C/SPI device models
reusing the ESP32 slaves, live sensor updates), arduino_cli STM32 branch,
start_stm32 simulation route.
- frontend: Stm32Bridge + Stm32BluePill(/BlackPill) web components (Wokwi SVGs),
board kinds, Interconnect/boardPinMapping/boardProtocols wiring, example
projects (blink, serial, I2C BMP280/MPU6050/DS1307/SSD1306/weather, 7-seg,
RGB, button, switch, stepper, cross-board interconnect).
- Raspberry Pi 4/5 board elements + thumbnails.
Pro board gating (generic OSS->Pro seam; entitlement logic lives in the overlay):
- lib/proBoardGate.ts: isProBoardKind (STM32 + every QEMU Raspberry Pi),
installBoardGateImpl/boardGateDecision, triggerProUpgradePrompt.
- PRO badge on those boards in the component picker; gate at the picker add +
the run backstop (startBoard).
- backend/app/services/board_access.py: server-side enforcement seam for the
simulation WebSocket; STM32/Pi unavailable -> Pro-framed message.
- desktop: generic QemuDownloadPrompt + Stm32QemuPrompt (download-behind-license,
mirrors the ESP32 prompt).
- .gitignore: never ship libqemu-* binaries in the public image.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 05:06:14 +07:00
|
|
|
PRO_BOARD_MESSAGE = (
|
2026-08-26 00:22:29 +07:00
|
|
|
'STM32 and QEMU-emulated Linux boards (Raspberry Pi, UNIHIKER) are '
|
|
|
|
|
'Velxio Pro features. Use them on velxio.dev with a paid plan, or '
|
|
|
|
|
'install Velxio Desktop.'
|
feat: STM32 (Blue Pill / Black Pill) QEMU emulation + Pro board gating
STM32 emulation (open-core, runs via libqemu-arm in the backend worker):
- backend: stm32_lib_manager + stm32_worker (GPIO, USART, I2C/SPI device models
reusing the ESP32 slaves, live sensor updates), arduino_cli STM32 branch,
start_stm32 simulation route.
- frontend: Stm32Bridge + Stm32BluePill(/BlackPill) web components (Wokwi SVGs),
board kinds, Interconnect/boardPinMapping/boardProtocols wiring, example
projects (blink, serial, I2C BMP280/MPU6050/DS1307/SSD1306/weather, 7-seg,
RGB, button, switch, stepper, cross-board interconnect).
- Raspberry Pi 4/5 board elements + thumbnails.
Pro board gating (generic OSS->Pro seam; entitlement logic lives in the overlay):
- lib/proBoardGate.ts: isProBoardKind (STM32 + every QEMU Raspberry Pi),
installBoardGateImpl/boardGateDecision, triggerProUpgradePrompt.
- PRO badge on those boards in the component picker; gate at the picker add +
the run backstop (startBoard).
- backend/app/services/board_access.py: server-side enforcement seam for the
simulation WebSocket; STM32/Pi unavailable -> Pro-framed message.
- desktop: generic QemuDownloadPrompt + Stm32QemuPrompt (download-behind-license,
mirrors the ESP32 prompt).
- .gitignore: never ship libqemu-* binaries in the public image.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 05:06:14 +07:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def register_board_access_gate(fn: Optional[BoardAccessGate]) -> None:
|
|
|
|
|
"""Install the gate (pro overlay) or clear it (None)."""
|
|
|
|
|
global _gate
|
|
|
|
|
_gate = fn
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def board_allowed(websocket: object, board_kind: str) -> bool:
|
|
|
|
|
"""True if this session may start the given Pro board. No gate -> allow."""
|
|
|
|
|
if _gate is None:
|
|
|
|
|
return True
|
|
|
|
|
try:
|
|
|
|
|
return await _gate(websocket, board_kind)
|
|
|
|
|
except Exception as exc: # fail-open: a gate bug must never wedge the sim
|
|
|
|
|
logger.warning('board_access gate raised, allowing: %r', exc)
|
|
|
|
|
return True
|