# NexIoT-Simulator **Repository Path**: thingscan/NexIoT-Simulator ## Basic Information - **Project Name**: NexIoT-Simulator - **Description**: A single-process device simulator covering 4 industrial protocols, for integration development and testing against host systems such as ThingsBoard Gateway. - **Primary Language**: Python - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-08-28 - **Last Updated**: 2026-08-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # NexIoT Simulator > **English** | [中文](./README.zh-CN.md) **A single-process device simulator covering 4 industrial protocols, for integration development and testing against host systems such as ThingsBoard Gateway.** `python -m app` starts everything at once: four protocol servers (Modbus TCP, OPC UA, BACnet, Siemens S7) plus a FastAPI management interface, with a Vue 3 frontend point configuration UI. All point data can be configured and modified via the REST API and takes effect on the protocol wire side **within at most 1 second**.
[![Python](https://img.shields.io/badge/Python-3.11-blue.svg)](https://www.python.org/) [![FastAPI](https://img.shields.io/badge/FastAPI-0.104+-009688.svg)](https://fastapi.tiangolo.com/) [![Vue](https://img.shields.io/badge/Vue-3.4%2B-42b883.svg)](https://vuejs.org/) [![License](https://img.shields.io/badge/License-Apache%202.0-green.svg)](LICENSE)
> Want technical details and internals? Read the docs under [`doc/`](doc/en/README.md). --- ## Table of Contents - [Features](#features) - [UI Preview](#ui-preview) - [Supported Protocols & Ports](#supported-protocols--ports) - [Quick Start](#quick-start) - [Docker One-Click Install (Recommended)](#docker-one-click-install-recommended) - [Docker Compose (Development)](#docker-compose-development) - [Local Run (Python + Frontend)](#local-run-python--frontend) - [Usage](#usage) - [API Overview](#api-overview) - [Technical Documentation](#technical-documentation) - [Project Structure](#project-structure) - [Testing & Verification](#testing--verification) - [Environment Variable Overrides](#environment-variable-overrides) - [FAQ](#faq) - [Contributing](#contributing) - [License](#license) --- ## Features - **Four industrial protocols**: simultaneously simulates Modbus TCP (2 slaves), OPC UA (2 devices), BACnet (15 objects), and Siemens S7 (4 memory areas) devices. - **Config immediately effective**: after creating, modifying, or deleting a point via the REST API / frontend, the sync loop writes the value to the protocol wire side within **≤1 second** (see [`doc/03-data-flow.md`](doc/en/03-data-flow.md)). - **RPC writes**: all protocols support native writes (FC06/FC16, UA Write, BACnet WriteProperty, S7 write_area) plus a unified REST API write. - **Web management UI**: Vue 3 + Pinia frontend with point list (filter by protocol), detail, create/edit/delete, and JSON import/export. - **Full REST API**: point CRUD, value read/write, import/export, stats, plus interactive Swagger docs. - **Flexible configuration**: environment variables override each protocol's initial values without rebuilding the image. - **Configuration persistence**: point configs and current values are auto-saved to disk (default `./data/points.json`) and restored automatically after a container restart/recreate — no need to reconfigure. - **Out of the box**: 49 built-in seed points covering multiple protocols and data types (bit/uint16/int32/float32/double/string/boolean, etc.). ## UI Preview **Web management UI** — point list, filter by protocol, stats and actions: ![Web management UI](img/web-ui-en.png) **Modbus TCP client reads** (coils / discrete inputs / holding registers): ![Modbus client](img/modbus-en.png) **OPC UA client reads** (MyDevice / MyDevice1 nodes): ![OPC UA client](img/opcua-en.png) **S7 client reads** (I / Q / M areas) and **DB1 data block read**: ![S7 DB1 read](img/s7-db.png) ## Supported Protocols & Ports | Protocol | Port | Transport | Description | |----------|------|-----------|-------------| | Modbus TCP | `502` | TCP | 2 slave devices (unit 1 / 2), with coils, discrete inputs, input/holding registers | | OPC UA | `53530` | TCP | `opc.tcp://0.0.0.0:53530/OPCUA/SimulationServer`, 2 devices | | BACnet | `47808` | UDP | device instance 1234 (SimBACnetDevice), 15 objects | | S7 | `102` | TCP | Siemens S7 simulator, I / Q / M / DB1 memory areas | | HTTP | `8000` | TCP | FastAPI management API + frontend (override with the `API_PORT` environment variable) | > Most ports are privileged 0–1024 ports (502 / 102); running locally on Linux requires root. It is recommended to use the [Docker method](#docker-one-click-install-recommended). ## Quick Start ### Docker One-Click Install (Recommended) Run the prebuilt Docker Hub image directly — no local build required: ```bash docker run -d --name nexiot-simulator --restart unless-stopped \ -p 502:502 \ -p 53530:53530 \ -p 47808:47808/udp \ -p 102:102 \ -p 8000:8000 \ -v nexiot-data:/app/data \ jettzhan/nexiot-simulator ``` - `--restart unless-stopped`: the container is restarted automatically if it exits and starts on boot. - `-v nexiot-data:/app/data`: named-volume persistence. Point configs and current values are stored in `points.json` and restored automatically on container restart/recreate; on first boot with no file, 49 seed points are written. - To override initial values, append `-e VAR=value` (e.g. `-e "MB_FLOAT_0=42.5"`); see [Environment Variable Overrides](#environment-variable-overrides). After startup: | Service | Address | |---------|---------| | Web management UI | | | Swagger API docs | | | Modbus TCP | `localhost:502` | | OPC UA | `opc.tcp://localhost:53530/OPCUA/SimulationServer` | | BACnet | `localhost:47808` (UDP) | | S7 | `localhost:102` | ### Docker Compose (Development) For development/debugging: build the image locally and orchestrate with Compose. `docker-compose.yml` already configures the port mappings and the named volume `nexiot-data`. ```bash docker compose up -d --build ``` ### Local Run (Python + Frontend) Requires Python 3.11+ and Node.js 18+. ```bash # 1. Install backend dependencies pip install -r requirements.txt # 2. Start the simulator (default API port 8000) python -m app # or with a custom API port: API_PORT=8001 python -m app ``` The frontend build is optional (otherwise there is no web UI; the API is unaffected): ```bash cd frontend npm install npx vite build # build output goes to ../app/static, served by FastAPI after restart # dev mode (hot reload, proxies /api → localhost:8000): npm run dev ``` ## Usage 1. Open to view the point list and stats, and filter points by protocol. 2. Create / edit / delete points in the UI, or import/export JSON configuration (all changes are saved automatically). 3. After changing a point value, OPC UA / BACnet / S7 / Modbus sync to the protocol wire side within **≤1 second** and can be read directly by clients such as ThingsBoard Gateway. 4. On the next startup / container restart, previously configured points and current values are restored automatically. 5. The detailed point table (address and initial value of each register/node) is in [`doc/02-data-model.md`](doc/en/02-data-model.md). ## API Overview Base URL: `http://:8000`, interactive docs: `http://:8000/docs`. | Method | Path | Description | |--------|------|-------------| | `GET` | `/api/points` | point list + stats | | `POST` | `/api/points` | create a point | | `GET` | `/api/points/{id}` | point detail + current value | | `PUT` | `/api/points/{id}` | update a point | | `DELETE` | `/api/points/{id}` | delete a point | | `DELETE` | `/api/points` | clear all points | | `GET` | `/api/points/{id}/value` | read the current value | | `PUT` | `/api/points/{id}/value` | write the current value (RPC) | | `GET` | `/api/points/export` | export all point configs | | `POST` | `/api/points/import` | full import of point configs | | `GET` | `/api/stats` | point stats | **Quick start:** ```bash # List points curl http://localhost:8000/api/points # Write an OPC UA point value (syncs to the UA node within 1s) curl -X PUT http://localhost:8000/api/points/16/value \ -H "Content-Type: application/json" -d '{"value":200.5}' # Create a Modbus point curl -X POST http://localhost:8000/api/points \ -H "Content-Type: application/json" \ -d '{"name":"MB_Test","protocol":"modbus","modbus":{"unitId":1,"functionCode":"03","address":30,"dataType":"uint16","byteOrder":"AB"},"initialValue":777,"changeMode":"fixed"}' ``` For the full API reference with request/response examples, see [`doc/05-api.md`](doc/en/05-api.md). ## Technical Documentation System design, data model, effect mechanism, and protocol implementation details are documented in the [`doc/`](doc/en/README.md) directory: | Doc | Content | |-----|---------| | [doc/README.md](doc/en/README.md) | technical doc index & 30-second architecture overview | | [01-architecture.md](doc/en/01-architecture.md) | system architecture, tech stack, process/thread model, port allocation | | [02-data-model.md](doc/en/02-data-model.md) | point data model, Registry design, 49 seed points | | [03-data-flow.md](doc/en/03-data-flow.md) | **Core**: data flow & the "configuration takes effect" mechanism | | [04-protocol-implementation.md](doc/en/04-protocol-implementation.md) | implementation details of the 4 protocol servers | | [05-api.md](doc/en/05-api.md) | REST API reference (with request/response examples) | | [06-run-deploy.md](doc/en/06-run-deploy.md) | running, frontend build, Docker deployment, environment variable overrides | | [07-verification.md](doc/en/07-verification.md) | verification & testing methods (three-layer verification system) | Chinese versions of these documents are available under [`doc/`](doc/README.md). ## Project Structure ``` . ├── app/ # backend (single process) │ ├── __main__.py # entry point: load persisted config / seed + 4 server threads + uvicorn │ ├── main.py # FastAPI instance, mounts /api and static assets │ ├── api.py # REST routes (point CRUD / value read-write / import-export / stats) │ ├── registry.py # PointRegistry: in-memory point configs + value store (thread-safe) │ ├── persistence.py # JSON persistence of point configs + current values │ ├── seed.py # 49 seed points │ ├── static/ # frontend build output (served by FastAPI at /) │ └── servers/ # 4 protocol servers │ ├── modbus_server.py │ ├── opcua_server.py │ ├── bacnet_server.py │ └── s7_server.py ├── frontend/ # Vue 3 + Pinia + Vite + TypeScript frontend │ └── src/ │ ├── api/ # REST wrapper (fetch) │ ├── i18n.ts # Chinese/English translations & language switcher │ ├── stores/ # Pinia store (point list/filter/detail/actions) │ ├── types/ # TypeScript types (mirror backend point structure) │ └── components/ # StatsBar / PointList / PointDetail / PointModal ├── doc/ # technical documentation (Chinese + English under doc/en/) ├── img/ # README screenshots ├── tests/ # unit / integration tests (pytest) ├── verify_point_config.py # point-config effect verification script (run after starting the service) ├── Dockerfile └── docker-compose.yml ``` ## Testing & Verification The project uses a three-layer verification system (see [`doc/07-verification.md`](doc/en/07-verification.md)): ```bash # 1. Unit tests (37 checks, no service required) python -m pytest tests -v -p no:cacheprovider # 2. Wire-level integration tests (start the simulator first, 162 checks) python tests/test_all_protocols.py # 3. Point-config effect verification (start the simulator first, 10 checks) python verify_point_config.py ``` The four protocols have all been verified for "API config syncs to the wire within ≤1s" (creating points, changing values, RPC writes, etc.); see [`doc/07-verification.md`](doc/en/07-verification.md#6-known-conclusions-confirmed-during-verification). ## Environment Variable Overrides Override each protocol's initial values in `docker-compose.yml` or the shell without modifying code: | Prefix | Description | Example | |--------|-------------|---------| | `MB_*` | Modbus initial values | `MB_FLOAT_0=42.5`, `MB_COIL_BITS=1023` | | `UA_*` | OPC UA variable values | `UA_MyDevice_Temperature=30.0` | | `BAC_*` | BACnet object presentValue | `BAC_AV_2=70.0`, `BAC_BV_1=inactive` | | `S7_*` | S7 memory area bytes | `S7_DB1_DBD0=99999`, `S7_M_0=255` | | `API_PORT` | FastAPI port (default 8000) | `API_PORT=8001` | ```yaml # docker-compose.yml example environment: - MB_FLOAT_0=42.5 # Modbus 1st float → 42.5 - UA_MyDevice_Count=999 # OPC UA MyDevice.Count → 999 - BAC_AV_2=70.0 # BACnet HumiditySetpoint → 70% - S7_DB1_DBD0=88888 # S7 DB1.DBD0 → 88888 ``` The full variable list is in [`doc/en/06-run-deploy.md`](doc/en/06-run-deploy.md#5-environment-variable-overrides-for-initial-values). ## FAQ **Q: Modbus / S7 port startup fails (Permission denied)?** Ports 502 / 102 are privileged ports; on Linux use root or Docker (the container runs as root). **Q: Docker build fails to pull the base image?** If your network is restricted and `python:3.11-slim` is unreachable, replace the base image in the `Dockerfile` with an accessible registry and rebuild. **Q: The wire side didn't change after modifying a point value?** - OPC UA / BACnet / S7 / Modbus all pull values from the Registry via a per-second sync loop, so in theory they take effect within ≤1s. - Values written natively by external tools are overwritten by the sync loop with Registry values; to persist, update via the REST API accordingly (see [`doc/03-data-flow.md`](doc/en/03-data-flow.md)). **Q: The data read during verification/integration is stale?** A leftover old simulator process may still occupy the port; clean it up and restart. ## Contributing Issues and Pull Requests are welcome. - When reporting a bug, please attach the protocol, port, reproduction steps, and logs. - Follow PEP 8; run `python -m pytest tests` after changes to ensure tests pass. - When adding or changing protocol behavior, please update the corresponding English technical docs under [`doc/en/`](doc/en/README.md) (and the Chinese versions under [`doc/`](doc/README.md)). ## License This project is open-sourced under the [Apache License 2.0](LICENSE).