A free Modbus TCP / RTU Serial device simulator with a real-time web dashboard.
Vibe Coding — This project is built primarily through AI-assisted rapid development.
Modbus Device Simulator is a full-stack Modbus device simulator built with modern web technologies. It runs both a Modbus TCP server and an RTU serial server backed by a high-performance singleton state engine, and exposes a real-time web dashboard for monitoring and controlling registers, viewing communication logs, and configuring server settings.
Whether you are developing Modbus client applications, testing PLC integrations, or learning the Modbus protocol, this simulator provides a lightweight, zero-hardware solution.
- Dual Protocol Support
- Modbus TCP Server — Configurable port (default 502)
- Modbus RTU Serial Server — Real serial port integration with configurable baud rate, parity, data bits, and stop bits
- Full Register Coverage
- 1,000 Coils (read/write boolean)
- 1,000 Discrete Inputs (read-only boolean)
- 10,000 Holding Registers (read/write 16-bit)
- 10,000 Input Registers (read-only 16-bit)
- Real-Time Dashboard
- Live register tables with pagination
- Toggle coils and write holding register values directly from the UI
- Communication logs in reverse chronological order (newest first)
- Server status and configuration panel
- Communication Logging
- In-memory log buffer (up to 1,000 entries)
- Track requests, responses, and errors
- Internationalization
- English and Chinese (中文) language support
- Theme Support
- Light / Dark / System theme modes
- REST API
- Full HTTP API for external integration and automation
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router) |
| UI Library | React 19 |
| Components | HeroUI v3 |
| Styling | Tailwind CSS v4 |
| Language | TypeScript |
| Modbus TCP | modbus-serial |
| Modbus RTU | serialport + custom frame parser |
| Testing | Vitest + Playwright |
| Icons | Iconify (Lucide) |
| Animation | Framer Motion |
The fastest way to get started — no cloning or installation required:
npx @ruixe/modbus-simulator@latestWith options:
npx @ruixe/modbus-simulator@latest -p 8080 -t 5020 -oSee all available options:
npx @ruixe/modbus-simulator@latest --help# Clone the repository
git clone https://github.com/yourusername/modbus-simulator.git
cd modbus-simulator
# Install dependencies
npm install
# or
pnpm install# Start the development server (default port 3000)
npm run devOpen http://localhost:3000 in your browser.
The Modbus TCP server starts automatically on port 502 (or as configured). The RTU serial server starts only when a serial port path is configured.
# Build for production
npm run build
# Start production server
npm startCreate a .env.local file in the project root to customize settings:
# Next.js dev server port (default is 3000)
PORT=3000
# Modbus TCP port (used in production; dev server always starts TCP on 502)
MODBUS_TCP_PORT=502Server settings (TCP port, RTU serial path, baud rate, parity, etc.) can also be changed at runtime via the web dashboard or the /api/config endpoint.
- Open the dashboard at
http://localhost:3000 - Registers — View all coils, discrete inputs, holding registers, and input registers. Toggle coils or edit holding register values directly.
- Logs — Monitor all Modbus communication in real time.
- Settings — Configure the TCP port, RTU serial port path, and serial parameters. Changes take effect immediately after restarting the servers.
Modbus TCP (using modbus-serial):
const { ModbusTCP } = require('modbus-serial')
const client = new ModbusTCP()
await client.connectTCP('127.0.0.1', { port: 502 })
// Read holding registers
const data = await client.readHoldingRegisters(0, 10)
console.log(data.data)
// Write a coil
await client.writeCoil(0, true)
client.close()Modbus RTU (serial port):
Configure the RTU serial path (e.g., COM3 on Windows, /dev/ttyUSB0 on Linux) in the dashboard settings, then connect with any standard Modbus RTU client.
All API routes are prefixed with /api and require the dev server to be running.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/registers |
Dump full Modbus engine state |
| POST | /api/registers |
Write a coil or holding register. Body: { registerType, address, value } |
| GET | /api/logs |
Get all communication logs |
| GET | /api/status |
Server status: { tcp: boolean, rtu: boolean } |
| GET | /api/config |
Get current configuration |
| POST | /api/config |
Update configuration and restart servers. Body: partial config object |
| GET | /api/serial-ports |
List available serial ports |
modbus-simulator/
├── app/
│ ├── api/ # Next.js API routes
│ │ ├── config/route.ts
│ │ ├── logs/route.ts
│ │ ├── registers/route.ts
│ │ ├── serial-ports/route.ts
│ │ └── status/route.ts
│ ├── globals.css # Tailwind CSS v4 entry + theme variables
│ ├── layout.tsx # Root layout with i18n & theme
│ └── page.tsx # Dashboard page (client component)
├── src/
│ ├── hooks/
│ │ ├── useModbusData.ts # React hook for polling Modbus data
│ │ └── useTheme.ts # Theme (light/dark/system) management
│ ├── i18n/
│ │ └── index.ts # i18next initialization (EN / CN)
│ ├── lib/
│ │ └── modbus/
│ │ ├── engine.ts # Singleton ModbusEngine (state + events)
│ │ ├── engine.test.ts # Unit tests for engine
│ │ ├── index.ts # Server manager (start/stop/config)
│ │ ├── mock-client.ts # Mock client for E2E tests
│ │ ├── rtu-serial-server.ts # Modbus RTU serial server
│ │ └── tcp-server.ts # Modbus TCP server
│ └── types/
│ └── modbus-serial.d.ts # Custom type declarations
├── e2e/ # Playwright E2E tests
├── public/locales/ # Translation JSON files
├── next.config.ts
├── vitest.config.ts
├── playwright.config.ts
└── package.json
# Run unit tests (Vitest)
npm run test:unit
# Run E2E tests (Playwright)
npm run test:e2e
# Run all tests
npm run test
# Run a specific unit test file
npx vitest run src/lib/modbus/engine.test.ts
# Run a specific E2E test
npx playwright test e2e/modbus.spec.ts --grep "UI to Protocol"| Script | Description |
|---|---|
npm run dev |
Start development server with Turbopack (port 3000) |
npm run build |
Production build |
npm run start |
Start production server |
npm run lint |
Run ESLint |
npm run format |
Format all files with Prettier |
npm run type-check |
Run TypeScript compiler (no emit) |
npm run test:unit |
Run Vitest unit tests |
npm run test:e2e |
Run Playwright E2E tests |
npm run test |
Run unit tests then E2E tests |
