A monorepo containing an Arduino WebSocket service and a web client for compiling and uploading Arduino projects.
- Clone the repo
- Open the repo in vscode
- Open the terminal
- Run
npm install - Copy
packages/service/.env.exampleinto a new file namedpackages/service/.env - Hit
Ctrl+Shift+Pand type "run task" then select "Tasks: Run Task" - Then select "Start Dev Environment"
- Open your browser to localhost:5173 to use the test bench
Node.js TypeScript WebSocket service for compiling and uploading Arduino projects using Arduino CLI.
Features:
- WebSocket Server for real-time communication
- Arduino CLI Integration
- Board Detection
- Real-time Output Streaming
- Multi-client Support
- Health Check endpoint
React + TypeScript web client built with Vite for interacting with the Arduino WebSocket service.
Features:
- Modern React UI
- WebSocket integration
- Real-time compilation feedback
- Board management interface
-
Download Arduino CLI:
- Visit Arduino CLI releases
- Download the appropriate version for your system
- Extract and place the binary in your PATH
-
Alternative Installation Methods:
Windows (using Chocolatey):
choco install arduino-climacOS (using Homebrew):
brew install arduino-cliLinux (using curl):
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh -
Initialize Arduino CLI:
arduino-cli core update-index arduino-cli core install arduino:avr # For Arduino Uno, Nano, etc.
- Node.js 16.x or higher
- npm 7.x or higher (for workspace support)
-
Clone the repository:
git clone <repository-url> cd tinyService
-
Install all dependencies:
npm install
This will install dependencies for all packages in the monorepo.
-
Configuration:
Create a
.envfile inpackages/servicedirectory (optional):
PORT=3000
ARDUINO_CLI_PATH=arduino-cli
NODE_ENV=developmentRun both server and client:
npm run devRun server only:
npm run dev:serverRun client only:
npm run dev:clientBuild all packages:
npm run buildBuild specific package:
npm run build:server
npm run build:clientStart production server:
npm run start:serverFrom the root directory:
npm run dev- Start both server and client in development modenpm run dev:server- Start server onlynpm run dev:client- Start client onlynpm run build- Build all packagesnpm run build:server- Build server packagenpm run build:client- Build client packagenpm run start:server- Start production servernpm run lint- Lint all packagesnpm run lint:fix- Fix linting issues in all packages
For detailed documentation on each package, see:
- Server Documentation
- Client Documentation (coming soon)
tinyService/
βββ packages/
β βββ service/ # Arduino WebSocket service
β β βββ src/
β β βββ docs/
β β βββ package.json
β β βββ tsconfig.json
β β βββ README.md
β βββ client/ # React + Vite Web Client
β β βββ src/
β β βββ package.json
β β βββ README.md
β βββ shared/ # Messaging npm package
β
βββ package.json # Root workspace configuration
βββ docker-compose.yml
βββ Dockerfile
βββ README.md
To add a new package to the monorepo:
- Create a new directory in
packages/ - Initialize with
npm initor copy an existingpackage.json - The workspace will automatically pick it up
Run commands in specific packages:
# Run a script in a specific package
npm run <script> --workspace=packages/service
# Install a dependency in a specific package
npm install <package> --workspace=packages/serviceFor detailed API documentation, see:
- GET / - Service information and available actions
- GET /health - Health check endpoint
- ws://localhost:3000 - WebSocket connection endpoint
All messages follow this structure:
{
"action": "compile" | "upload" | "list-boards" | "verify",
"payload": {
"sketchPath": "string",
"board": "string",
"port": "string (optional, required for upload)"
}
}Compile a sketch:
{
"action": "compile",
"payload": {
"sketchPath": "/path/to/sketch.ino",
"board": "arduino:avr:uno"
}
}Upload to board:
{
"action": "upload",
"payload": {
"sketchPath": "/path/to/sketch.ino",
"board": "arduino:avr:uno",
"port": "/dev/ttyUSB0"
}
}List connected boards:
{
"action": "list-boards",
"payload": {}
}Verify sketch (compile without upload):
{
"action": "verify",
"payload": {
"sketchPath": "/path/to/sketch.ino",
"board": "arduino:avr:uno"
}
}All messages follow this structure:
{
"type": "status" | "output" | "error" | "complete",
"action": "string",
"data": "any"
}- status: Operation status updates
- output: Real-time compilation/upload output
- error: Error messages
- complete: Operation completed successfully
Status update:
{
"type": "status",
"action": "compile",
"data": {
"message": "Starting compilation...",
"sketchPath": "/path/to/sketch.ino",
"board": "arduino:avr:uno"
}
}Real-time output:
{
"type": "output",
"action": "compile",
"data": {
"output": "Compiling sketch..."
}
}Completion:
{
"type": "complete",
"action": "compile",
"data": {
"message": "Compilation completed successfully",
"sketchPath": "/path/to/sketch.ino",
"board": "arduino:avr:uno",
"output": "Full compilation output..."
}
}Error:
{
"type": "error",
"action": "compile",
"data": {
"error": "Compilation failed: Missing library"
}
}See individual package documentation for testing instructions:
See CONTRIBUTING.md for contribution guidelines.
MIT - See LICENSE for details.
Install wscat for testing WebSocket connections:
npm install -g wscat-
Connect to the WebSocket server:
wscat -c ws://localhost:3000
-
List connected boards:
{ "action": "list-boards", "payload": {} } -
Compile a sketch:
{ "action": "compile", "payload": { "sketchPath": "C:\\path\\to\\sketch\\sketch.ino", "board": "arduino:avr:uno" } } -
Upload to a board:
{ "action": "upload", "payload": { "sketchPath": "C:\\path\\to\\sketch\\sketch.ino", "board": "arduino:avr:uno", "port": "COM3" } }
Common Arduino board FQBNs:
- Arduino Uno:
arduino:avr:uno - Arduino Nano:
arduino:avr:nano - Arduino Mega:
arduino:avr:mega - Arduino Leonardo:
arduino:avr:leonardo - ESP32:
esp32:esp32:esp32 - ESP8266:
esp8266:esp8266:nodemcuv2
To find the FQBN for your board:
arduino-cli board listsrc/
βββ handlers/
β βββ compile.handler.ts # Handle compile requests
β βββ upload.handler.ts # Handle upload requests
β βββ boards.handler.ts # Handle board detection
βββ services/
β βββ arduino-cli.service.ts # Arduino CLI wrapper
β βββ websocket.service.ts # WebSocket server logic
βββ types/
β βββ messages.types.ts # TypeScript interfaces
βββ config.ts # Configuration management
βββ server.ts # Main entry point
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
Server port |
TINYSERVICE_HOST |
127.0.0.1 |
Address to listen on |
TINYSERVICE_ALLOWED_ORIGINS |
tinyStudio web app and localhost pages | Comma-separated browser origins allowed in |
ARDUINO_CLI_PATH |
arduino-cli |
Path to Arduino CLI executable |
NODE_ENV |
development |
Environment mode |
See Security Considerations for what the host and origin settings allow.
The service includes comprehensive error handling:
- Invalid WebSocket messages: Returns error message to client
- Missing Arduino CLI: Logs warning but continues running
- Compilation failures: Streams error output to client
- Connection errors: Automatic cleanup and logging
The service uses structured logging with different levels:
- INFO: General information and successful operations
- ERROR: Error conditions and failures
- WARN: Warning conditions
- DEBUG: Detailed debugging information (development mode only)
- Create a new handler in
src/handlers/ - Add the action type to
IncomingMessageinterface - Register the handler in
WebSocketService - Update the Arduino CLI service if needed
The project uses ESLint with TypeScript rules. Run npm run lint to check code style.
-
"Arduino CLI not found":
- Ensure Arduino CLI is installed and in PATH
- Set
ARDUINO_CLI_PATHenvironment variable if installed in custom location
-
"Permission denied" on Linux/macOS:
- Add user to dialout group:
sudo usermod -a -G dialout $USER - Logout and login again
- Add user to dialout group:
-
WebSocket connection refused:
- Check if server is running on correct port
- Verify firewall settings
-
Compilation fails:
- Ensure correct board FQBN
- Install required board packages:
arduino-cli core install <package> - Check sketch syntax
- Check the health endpoint:
http://localhost:3000/health - Review server logs for detailed error information
- Ensure Arduino CLI works independently:
arduino-cli version