Skip to content

Latest commit

 

History

1,120 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

UnoSim

Supported OS GitHub commit activity
Tests Test Coverage
Issues Pull Requests

A web-based Arduino simulator with a browser UI, server-side Arduino compilation and an interactive Arduino Preview for sketches.

Administration: For local development and Docker installation, see docs/INSTALL_LOCAL.md and docs/INSTALL_SERVER.md. Security requirements are in docs/SECURITY.md.

Preview

UnoSim Interface UnoSim with Example loaded

UnoSim Arduino Preview

Features

  • Code Editor: Monaco editor integration for writing Arduino sketches with syntax highlighting
  • Compilation: Compile Arduino code through the UnoSim backend
  • Serial Monitor: Real-time output display from simulated Arduino execution
  • Pause/Resume Simulation: Pause running sketches to inspect state, change pin values, and resume execution
  • Arduino Preview: A preview of analog/digital inputs and outputs directly in the Arduino SVG
  • Web-based UI: Use the simulator in a browser; local/server installation runs the backend
  • Modern UI: Built with React and TailwindCSS for a responsive, professional interface
  • I/O Registry: You can see what Pins are used in your Program!

Tech Stack

  • Frontend: React, TypeScript, Vite, TailwindCSS, Radix UI
  • Backend: Node.js (TypeScript), Express, WebSocket support
  • Editor: Monaco Editor
  • Testing: Vitest with React Testing Library
  • Build Tools: Vite, esbuild

Installation (only for Linux/MacOS)

Prerequisites

  • Node.js 24.20.0 LTS (see .nvmrc)
  • npm or yarn

Setup

  1. Clone the repository:
git clone https://github.com/MoDevIO/UnoSim.git
cd UnoSim
  1. Install dependencies:
    npm ci
  1. Start the dev-server:
npm run dev:full

This will start both the backend server and the frontend development server.

Usage

UnoSim supports two runtime profiles: local development and Docker deployment.

Development Mode

npm run dev:full

Starts the backend (Express + WebSocket) and the Vite dev server with hot-reload. The backend runs via tsx (TypeScript execution) and the client is served by Vite on a separate port with HMR. Compilation uses arduino-cli directly on the host — Docker is not required.

npm run dev starts only the backend on the local listener (127.0.0.1). The development profile is single-user and is not a deployment mode. Both commands use the configured external-example source, ref, and host allowlist from the development script.

The accepted target architecture keeps that server configuration as the default, while allowing each browser to select a validated public GitHub Examples repository and ref in Settings. The browser preference is request-scoped, never changes the server default, and never fetches GitHub directly. The default is ttbombadil/unosim-examples at main; the server resolves the ref to a full commit SHA before loading a complete snapshot. See ssot_function_definition_ExternalExamples.md.

Component Details
Backend tsx server/index.ts on configured PORT (default 3000)
Client Vite HMR dev server (proxied)
Compiler Direct arduino-cli calls on host
Worker Pool Disabled (CompilerWithFallback.usePool = false outside production)

Docker Mode

npm run build
npm run start

Builds the full stack (client + server + worker) into dist/. The supported production profile runs this server in Docker and executes every simulation in a Docker sandbox. The Vite-built client is served as static files from dist/public/.

Component Details
Backend node dist/index.js on configured PORT (default 3000)
Client Static files from dist/public/
Compiler Configured Worker Pool (Compose reference: 8 parallel workers)
Docker Required for the server container and all simulation sandboxes

Note: Local development compiles and executes directly on the host. The Docker profile requires a working Docker daemon and sandbox image and never falls back to host-native simulation.

docker build -t unosim-sandbox:latest -f Dockerfile.sandbox .
docker build -t unosim-server:latest .

For a manual production container, use the same gateway, sandbox and mount requirements as Compose. At minimum, production requires Gateway mode, UNOSIM_GATEWAY_SECRET (at least 32 characters), UNOSIM_TRUSTED_PROXY, and UNOSIM_ALLOWED_WS_ORIGINS; the backend also needs the Docker socket and the unosim-sandbox:latest image available to the configured Docker daemon:

docker run --rm -p 3000:3000 \
   -e NODE_ENV=production \
   -e UNOSIM_SERVER_MODE=docker \
   -e UNOSIM_GATEWAY_SECRET='<secret-from-secret-store>' \
   -e UNOSIM_TRUSTED_PROXY='<gateway-ip-or-cidr>' \
   -e UNOSIM_ALLOWED_WS_ORIGINS='https://classroom.example.edu' \
   -e DOCKER_HOST=unix:///var/run/docker.sock \
   -e DOCKER_SANDBOX_IMAGE=unosim-sandbox:latest \
   -e ARDUINO_CACHE_DIR=${PWD}/server/arduino-cache \
   -e UNOSIM_SHARED_TEMP_DIR=${PWD}/temp \
   -v /var/run/docker.sock:/var/run/docker.sock \
   -v ${PWD}/server/arduino-cache:${PWD}/server/arduino-cache \
   -v ${PWD}/temp:${PWD}/temp \
   -v ${PWD}/storage:/app/storage \
   unosim-server:latest

Or with Docker Compose (backend only):

export DOCKER_GID="$(stat -c '%g' /var/run/docker.sock)"
export UNOSIM_GATEWAY_SECRET="<at-least-32-random-characters>"
export UNOSIM_TRUSTED_PROXY="<gateway-ip-or-cidr>"
export UNOSIM_ALLOWED_WS_ORIGINS="https://classroom.example.edu"
docker compose up --build

Compose starts the UnoSim backend only. Docker mode always requires an authentication gateway; the four variables above are mandatory and must be supplied by the deployment's secret/environment management. A reverse proxy/auth gateway must forward authenticated HTTP and WebSocket requests. Sandbox execution remains dynamic and uses the Docker socket at runtime.

If you need SonarQube, run it separately in its own stack or service; the UnoSim compose file does not include SonarQube or MCP.

The application runs inside a container and is available at http://localhost:3000.

For sandboxed sketch execution, the server container must use a temp directory that is bind-mounted from the host at the same absolute path. The provided Compose file does this via UNOSIM_SHARED_TEMP_DIR=${PWD}/temp and ${PWD}/temp:${PWD}/temp.

On macOS, make sure your project directory is allowed under Docker Desktop file sharing, otherwise the inner sandbox container cannot see generated files such as sketch.cpp.

Available Scripts

Command Description
npm run dev:full Start backend + client in development mode
npm run dev Start backend only (no client)
npm run dev:client Start Vite client only
npm run build Build client, server, and worker for production
npm run start Run the production build
npm run check TypeScript type-check (tsc --noEmit)
npm run test:fast Run deterministic unit tests
npm run test:integration Run Arduino/toolchain integration tests
npm run test:docker Run Docker sandbox integration tests
npm run test:e2e Run Playwright browser tests
npm run test:all Run unit, integration and Docker gates
./run-tests.sh Full pipeline: lint, unit tests, Docker build, integration tests, E2E
RUN_HEAVY_TESTS=1 ./run-tests.sh Full pipeline inklusive langsamem Parallel-Instanz-Stresstest

Architecture Overview

  • Sandbox Runner Pool — Manages runner leases for sketch execution. In the documented production path, each simulation runs in a short-lived isolated Docker sandbox with stdout/stderr capture for serial output and pin state reporting.
  • Compilation Worker Pool — In production mode, the configured Node.js Worker Thread pool handles compilations in parallel via CompilerWithFallback. The Compose reference uses 8 workers; capacity limits are documented in docs/SCALABILITY.md.
  • WebSocket Layer — Real-time communication between client and server for serial output, pin state batches, and simulation control (start/stop/pause/resume).
  • SonarQube Integration — Optional SonarQube scans are wired into the pre-push hook and ./run-tests.sh when SONAR_TOKEN and a reachable SonarQube service are available. Release blocking is controlled by REQUIRE_RELEASE_GATE=1.

Notes for running tests (optional)

The repository contains a robust, fast test pipeline:

  1. Unit tests (Vitest + React Testing Library) cover business logic and UI components. npm run test:unit is the deterministic refactoring gate; toolchain, Docker, browser and load tests are separate gates.
  2. E2E smoke flow comprises three Playwright tests in e2e/smoke-and-flow.spec.ts for startup, compile/run with serial output, and dialogs. The repository also contains separate responsive, board, visual, and scalability E2E suites; run npm run test:e2e for the configured suite.
  3. Heavy stress tests are opt-in. Use RUN_HEAVY_TESTS=1 ./run-tests.sh when validating Docker sandbox isolation and cleanup. Load-test commands are listed in docs/RELEASE_RUNBOOK.md and capacity conclusions belong in docs/SCALABILITY.md.

Local quick‑check example:

npm run test:unit

For release gates, follow docs/RELEASE_RUNBOOK.md. Testing conventions and timing budgets are maintained in docs/TESTING_STANDARDS.md.

License

MIT License - See LICENSE for details

This project uses third-party open-source dependencies under their respective licenses.

Contact & Support

Getting Help

  • Issues & Bugs: Use the GitHub Issues tracker
  • Feature Requests: Create an Pull Request
  • Questions: Open a discussion or check existing issues

Project Maintainers

  • Mo Tiltmann (MoDevIO) - Couven-Gymnasium, Aachen
  • Tom Tiltmann (ttbombadil) - Technische Hochschule, Köln

Additional Resources

About

A browser-based simulator for Arduino Uno

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages