A self-contained Unified Namespace simulator for industrial IoT demos, training, and development.
What is this? · Devcontainer · Quick start · Docker · Ports · Full docs
UNS Design Studio lets you model an industrial enterprise, generate realistic plant data, and publish it through common OT/IIoT protocols — without connecting to real machines. Use it to prototype Unified Namespace designs, teach ISA-95 concepts, test MQTT/NATS pipelines, validate OPC-UA clients, and demo industrial dashboards with configurable sites, assets, recipes, tags, payloads, and faults.
| UNS Designer | MQTT Dashboard | Payload Designer |
|---|---|---|
- Browser dashboard for virtual plant control, recipes, metrics, anomaly injection, and process supervision.
- Visual ISA-95 / UNS tree designer backed by
uns_config.json. - Dynamic OPC-UA server generated from the configured UNS.
- OPC-UA → MQTT/NATS bridge with configurable broker, topic prefix, interval, and payload schemas.
- Closed-loop setpoints & command tags for Industrial-AI optimization — an optimizer publishes a setpoint request, the bridge writes it back to OPC-UA (pub/sub or NATS request-reply), and per-equipment control loops ramp the committed setpoint while PVs (RPM, current, power, flow) track it. A realistic PLC-HMI handshake (operator mode + permissive, EU limits, optimizer heartbeat/watchdog, command-status writeback) keeps the operator in control and fails safe on comms loss. Includes optical sorters with a sensitivity↔reject-rate trade-off. See docs/SETPOINT_OPTIMIZATION.md and docs/REALISTIC_CONTROL_ARCHITECTURE.md.
- PLC Simulators — import a raw PLC tag catalog (UNS-Protocol-Converter browse export or a native Kepware JSON/CSV export) and run it as its own standalone OPC-UA server, next to the UNS server. Each instance reproduces the Kepware-shaped browse structure (channel → device → tag groups / UDT instances) with live simulated values, held writable setpoints, and auto-detected UDT instances — a realistic "raw" datasource for testing PLC → UNS → SCADA integration paths and AI-driven tag mapping. Manage instances (import / start / stop) from the PLC Simulators page, the
/api/plc/*API, ortools/import_plc_catalog.py+UDS_CONFIG/UDS_OPC_PORTenv vars (seedocker-compose.plc-lab.yml). - Modelling agent & MCP server — describe the plant you want and let a language model build it. Give the agent your organisation's topic policy and it reads the rulebook, generates the ISA-95 tree, instantiates real equipment from the asset library, grades its own work with
policy_check, and shows you the topics the bridge will publish. Attach the policy spreadsheet or a tag-list CSV to the chat and it reads the rows; it answers with tables, charts, Mermaid diagrams and downloadable files, and can trend a live tag from the running simulation. Every edit is snapshotted, so anything it does is undoable. The same tools are exposed over MCP at/mcp, so Claude Desktop, Claude Code, UNS-Industrial-AI or any other MCP client can drive this simulator from outside — in-process, over stdio, or as its own container. Works with any OpenAI-compatible endpoint (Azure AI Foundry, OpenAI, OpenRouter, Ollama); with no LLM configured the MCP side still works on its own. See docs/AGENT_AND_MCP.md. - Live UNS viewer for real-time topic inspection in the browser.
- Built-in Mosquitto MQTT broker and MQTT Explorer — no external broker needed.
- Asset library, importable enterprise templates, and configurable simulation profiles.
The easiest way to run UNS Design Studio is with the included devcontainer. It automatically provisions the full environment — including an MQTT broker and MQTT Explorer — with zero manual setup.
- VS Code with the Dev Containers extension, or
- GitHub Codespaces
- Open this repository in VS Code and click Reopen in Container when prompted, or open it directly as a Codespace.
- Wait for the container to build and the
postStartCommandto finish (~1 minute on first run). - Start the dashboard:
python app.py
- Open the forwarded port 5000 in your browser.
The devcontainer automatically starts two Docker containers alongside the dev environment:
| Container | Port | Description |
|---|---|---|
mosquitto |
1883 (TCP), 8083 (WebSocket) | Eclipse Mosquitto MQTT broker |
mqtt-explorer |
4000 | MQTT Explorer web UI |
Both containers are on the uns-net Docker network and can address each other by container name.
Once python app.py is running:
- Open port 5000 — the main dashboard.
- Click Start Server to start the OPC-UA simulation server.
- Click Start All Plants to begin the simulation.
- Click Start Bridge to start publishing OPC-UA data to MQTT.
The bridge builds a node cache on first start (~5 seconds), then begins publishing all UNS tags to Mosquitto at ~1 second intervals.
The UNS Live View (sidebar → Live View) shows the real-time topic tree from the MQTT broker directly in the browser.
- The connection settings auto-detect the correct WebSocket URL for your environment.
- If you previously used the live view with different settings, clear
uns-live-settingsfrom your browser's LocalStorage (DevTools → Application → Local Storage) and reload the page. - Click Connect — you should immediately see the topic tree populate with live values.
The live view connects through the dashboard's built-in /mqtt-ws proxy, so it uses the same host and port as the dashboard itself. No separate broker port needed.
MQTT Explorer is a full-featured MQTT client pre-configured to connect to the local Mosquitto broker.
- Open port 4000 in your browser.
- Select the UNS Design Studio connection (pre-configured).
- Click Connect.
You will see the full UNS topic tree with live values, charts, and message history.
The MQTT bridge (bridge.py) runs on the host, not inside Docker. It connects to the broker at localhost:1883.
Do not change the broker host to
mosquittoin the Settings page — that hostname only resolves inside Docker containers. The Python bridge useslocalhost.
MQTT Explorer and the UNS Live View connect through Docker, so they use mosquitto:1883 (Explorer) and the /mqtt-ws proxy (live view) respectively.
Requires Python 3.10+ and Docker (for the MQTT broker).
pip install -r requirements.txt
# Start Mosquitto broker
docker run -d --name mosquitto -p 1883:1883 -p 8083:8083 \
-v "$(pwd)/.devcontainer/mosquitto.conf:/mosquitto/config/mosquitto.conf:ro" \
eclipse-mosquitto:2
# Start the dashboard
python app.pyOpen http://localhost:5000. Use the UI to start the OPC-UA server, plants, and bridge.
Optional launch scripts:
start_dashboard.batbash start_dashboard.sh| Port | Service | Notes |
|---|---|---|
| 5000 | Dashboard | Main web UI |
| 4840 | OPC-UA | Started on demand from the dashboard |
| 9999 | Anomaly TCP | Inject anomalies via TCP |
| 1883 | MQTT (TCP) | Mosquitto broker |
| 8083 | MQTT (WebSocket) | Mosquitto broker WebSocket listener |
| 4000 | MQTT Explorer | Browser-based MQTT client |
docker compose up -d --build
docker compose logs -fThe local Compose build tags the image as uns-design-studio:2.0. Runtime state is stored in the uns-design-studio-data Docker volume.
The dashboard already serves /mcp. Build Dockerfile.mcp only when you want the agent-facing server behind a separate trust boundary — its own bearer token, no UI, nothing of app.py in the process:
docker build -f Dockerfile.mcp -t uds-mcp .
docker run -e UDS_MCP_TOKEN=... -e UDS_URL=http://uds:5000 -p 8060:8060 uds-mcpUse portainer-stack.yml to deploy the published image from GitHub Container Registry:
ghcr.io/ilja0101/uns-design-studio:2.0
In Portainer, paste the stack file and optionally set:
UNS_IMAGE=ghcr.io/ilja0101/uns-design-studio:2.0
Root JSON files are live mutable state, not fixtures:
uns_config.json, sim_state.json, bridge_config.json, server_config.json, payload_schemas.json, asset_library.json
Docker seeds these into /data on first boot and symlinks /app/*.json to /data/*.json.
The agent adds agent_config.json (LLM endpoint and MCP token), topic_policy.json, and an agent/ directory holding conversations, chat attachments and the model-snapshot undo history.
python -m py_compile app.py factory.py bridge.py
docker compose config
python -m pytestMIT — see LICENSE.
Built by Ilja Bartels, Alex Hodakovsky & Jorgen van D. for practical UNS and industrial IoT learning.