A Docker Compose based simulated cGMP manufacturing site for testing industrial protocol ingestion into the Factory Intelligence Platform.
This is a non-GxP simulation environment only. It is not intended for production use, and no generated data should be used as a regulated record.
flowchart LR
UI[Web UI\nReact + Vite] --> API[REST API\nFastAPI]
UI <-->|ws://localhost:8000/ws/live| API
API --> CORE[Authoritative\nSimulation Engine]
OPC[OPC-UA Server] -->|polls internal REST| API
SP[Sparkplug Edge Node] -->|polls internal REST| API
BAC[BACnet Demo Server] -->|polls internal REST| API
SP --> MQTT[Eclipse Mosquitto]
| Protocol | Endpoint |
|---|---|
| REST | http://localhost:8000 |
| OpenAPI | http://localhost:8000/docs |
| Web UI | http://localhost:3000 |
| OPC-UA | opc.tcp://localhost:4840/freeopcua/server/ |
| MQTT | localhost:1883, topic root spBv1.0/OpenFactory/# |
| MQTT WebSocket | localhost:9001 |
| BACnet/IP demo service | UDP 47808, device OFI-DEMO-BMS-001 |
docker compose up --buildOpen the Web UI:
http://localhost:3000
make smoke-test
make drift-test
make rest-test
make mqtt-test
make opcua-test
make bacnet-test
make ui-testcurl http://localhost:8000/health
curl http://localhost:8000/api/v1/assets
curl http://localhost:8000/api/v1/simulation/drifts
curl -X POST http://localhost:8000/api/v1/simulation/drifts/BR101_TEMPERATURE_DRIFT/enable
curl -X POST http://localhost:8000/api/v1/simulation/drifts/BR101_TEMPERATURE_DRIFT/disable
curl -X POST http://localhost:8000/api/v1/simulation/drifts/disable-all
curl -X POST http://localhost:8000/api/v1/simulation/drifts/reset-all
curl -X POST http://localhost:8000/api/v1/simulation/excursion/environmental
curl -X POST http://localhost:8000/api/v1/simulation/alarm/bioreactordocker compose exec mqtt-broker mosquitto_sub -h localhost -t 'spBv1.0/OpenFactory/#' -vThe publisher uses Sparkplug B topic conventions with JSON demo payloads. This is useful for local ingestion and demos, but it is not a complete certified Sparkplug B implementation.
Use UaExpert with:
opc.tcp://localhost:4840/freeopcua/server/
Browse the OpenFactoryDemoSite namespace for Areas, Batches, Alarms, QualityEvents, and Simulation/DriftScenarios.
Script test:
make opcua-testThe BACnet service exposes HVAC and utility objects on UDP 47808 using a demo-grade UDP responder so it runs reliably in Docker Desktop. Docker Desktop on macOS and Windows may not support BACnet broadcast discovery the same way as native Linux networking. For full BACnet/IP interoperability testing, run on Linux with host networking or replace this service with a BACpypes3/BAC0 device profile.
make bacnet-testOpen http://localhost:3000.
Use Dashboard for a scannable operations overview, Assets for the factory hierarchy and asset details, Tags for searchable live tag values and protocol exposure, Trends for rolling telemetry, Alarms for acknowledgement workflow, Events for recent simulation history, Protocols for endpoint health and troubleshooting commands, and Simulation for drift and excursion controls.
The header shows REST API status, WebSocket status, active alarm count, active drift count, and the last live update age. If WebSocket updates become stale or disconnected, the UI falls back to REST polling and shows a non-blocking warning.
To run a drift demo, open Simulation, select an individual drift card's Enable Drift button, or use Enable Demo Drifts for the standard multi-area scenario. Disable All Drifts starts recovery, Reset All Drifts restores affected values to normal, and Reset Simulation clears alarms/deviations and returns the local demo state to baseline.
Protocol Diagnostics includes one health card each for REST API, WebSocket, OPC-UA, MQTT Broker, Sparkplug Edge Node, and BACnet Server. It also shows a searchable protocol mapping table and local test commands. BACnet broadcast discovery can be limited on Docker Desktop; use make bacnet-test for the supported demo check.
Known UI limitation: the demo keeps live trend history in browser memory for the current page session only. Reloading the page clears chart history while leaving the authoritative simulation state in the REST API container.
Available scenarios:
BR101_TEMPERATURE_DRIFTBR101_PH_DRIFTBR101_DO_DRIFTWFI201_CONDUCTIVITY_DRIFTWFI201_TOC_DRIFTCR01_DIFFERENTIAL_PRESSURE_DRIFTCR01_HUMIDITY_DRIFTFL401_REJECT_RATE_DRIFT
Enable starts gradual movement toward warning or alarm limits. Disable starts gradual recovery toward normal. Reset disables every drift, clears drift-created alarms where reasonable, and immediately restores affected values to normal.
This demo is for integration testing, education, and demonstrations. Production use would require approved intended use, validation, access control, audit trails, backup and restore, cybersecurity review, change control, network segmentation, disaster recovery, vendor assessment, and test evidence. Factory Intelligence Platform outputs should be treated as advisory unless validated and approved for a specific intended use.
- Port already in use: stop the process using ports 3000, 8000, 1883, 9001, 4840, or UDP 47808.
- BACnet broadcast not visible on Docker Desktop: use
make bacnet-testfor the demo path, or test full BACnet discovery on native Linux. - MQTT connection failure: check
docker compose logs mqtt-broker sparkplug-edge-node. - OPC-UA bind issue: check port 4840 and
docker compose logs opcua-server. - WebSocket failure: the UI falls back to REST polling and shows a warning.
- Web UI cannot reach REST API: verify
curl http://localhost:8000/health. - Python dependency issue: run tests inside the service containers or install the requirements from each service.
- Node dependency issue: run
docker compose build web-uiorcd services/web_ui && npm install.