Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lab Cell — Industrial IoT Unified Namespace (UNS) Stack

A self-contained Industrial IoT (IIoT) lab-automation stack that demonstrates a full Unified Namespace data pipeline: equipment telemetry → MQTT broker → SCADA historian → cloud data lakehouse, with a semantic knowledge graph layer on top.

A simulated liquid-handling robot publishes Sparkplug B telemetry, which flows through every tier of a modern industrial data architecture — from the edge all the way to analytics.

Everything runs locally with a single docker-compose up -d. No physical hardware required.


Architecture — three-tier UNS pattern

┌──────────────────────────────────────────────────────────────────────┐
│  TIER 1 — Unified Namespace (MQTT)                                     │
│                                                                        │
│   FastAPI Simulator ──── Sparkplug B ────▶  EMQX Broker                │
│   (liquid-handler robot)                    spBv1.0/{group}/{type}/... │
└───────────────────────────────────────────────┬──────────────────────┘
                                                 │  MQTT subscribe
┌────────────────────────────────────────────────▼──────────────────────┐
│  TIER 2 — Orchestration & Historian                                    │
│                                                                        │
│   Ignition SCADA ──── tag history ────▶  PostgreSQL (ignition_history) │
│   Keycloak (auth)        PgAdmin (DB admin UI)                         │
└────────────────────────────────────────────────┬──────────────────────┘
                                                 │  poll every 60 s
┌────────────────────────────────────────────────▼──────────────────────┐
│  TIER 3 — Analytics & Knowledge                                        │
│                                                                        │
│   ETL Service ────▶  Databricks Delta Lake   Neo4j Knowledge Graph     │
│                      (lab_cell.liquid_handler) (auto-discovers tags)   │
└────────────────────────────────────────────────────────────────────────┘

Tier 1 — Unified Namespace (MQTT)

  • EMQX is the central message hub (MQTT 1883, dashboard 18083).
  • A FastAPI simulator models a liquid-handler robot and continuously publishes Sparkplug B messages to EMQX. Sparkplug payloads are built directly from a compiled protobuf schema (no tahu dependency in the simulator).

Tier 2 — Orchestration & Historian

  • Ignition SCADA subscribes to EMQX via its MQTT Engine module and writes tag history to PostgreSQL.
  • PostgreSQL stores time-series data in monthly partition tables (sqlt_data_1_YYYY_MM).
  • Keycloak provides authentication; PgAdmin is the database admin UI.

Tier 3 — Analytics & Knowledge

  • ETL service polls PostgreSQL every 60 s and pushes new rows to a Databricks Delta Lake table (lab_cell.liquid_handler.tag_history).
  • Neo4j holds a semantic knowledge graph. A seeder loads static infrastructure nodes, then listens for Sparkplug B DBIRTH messages and auto-discovers new tags as Metric nodes — adding a tag to the simulator is enough to make it appear in the graph. All writes use MERGE, so seeding and message replay are idempotent.

Sparkplug B data flow

Simulator → EMQX topic:  spBv1.0/{group_id}/[NBIRTH|DBIRTH|DDATA|NDEATH]/{node_id}/{device_id}
  • On startup: NBIRTH (seq 0) → DBIRTH (seq 1) → DDATA every 2 s
  • On shutdown: NDEATH (also registered as the MQTT Last Will)

Metrics published

Metric Sparkplug type
equipment_id String (12)
running Boolean (11)
temperature_c Double (10)
vacuum_pressure_psi Double (10)
pipette_volume_ul Double (10)
flow_rate_ml_min Double (10)

DBIRTH includes all six metrics; DDATA omits equipment_id.


Quick start

# 1. Configure environment
cp .env.example .env
#    then edit .env and set your own passwords + Databricks credentials

# 2. Launch the full stack
docker-compose up -d

# 3. Tail logs for a service
docker-compose logs -f fastapi-sim     # or: emqx, ignition, postgres, etl, neo4j, ...

# Full reset (wipe all volumes)
docker-compose down -v

All credentials are supplied via .env — see .env.example for the full list of variables. Databricks credentials must be filled in before the ETL service will function.


Service access

Service URL Credentials
EMQX Dashboard http://localhost:18083 EMQX_DASHBOARD_USERNAME / EMQX_DASHBOARD_PASSWORD
Ignition SCADA http://localhost:8088 IGNITION_ADMIN_USERNAME / IGNITION_ADMIN_PASSWORD
PgAdmin http://localhost:5050 PGADMIN_EMAIL / PGADMIN_PASSWORD
Keycloak http://localhost:8080 KEYCLOAK_ADMIN_USERNAME / KEYCLOAK_ADMIN_PASSWORD
Neo4j Browser http://localhost:7474 neo4j / NEO4J_PASSWORD
FastAPI Simulator http://localhost:8000

All values are set in your local .env (never committed). Inspect the full graph in Neo4j with: MATCH (n)-[r]->(m) RETURN n, r, m


REST API (simulator)

Method Path Description
GET /status Current equipment state
POST /start Set running=true; publishes an immediate DDATA
POST /stop Set running=false; metrics decay toward idle
POST /rebirth Force-republish NBIRTH + DBIRTH (re-triggers knowledge-graph discovery without a restart)

Project structure

.
├── docker-compose.yaml          # full stack definition
├── .env.example                 # configuration template (copy to .env)
├── services/
│   ├── simulator/               # FastAPI liquid-handler simulator (Sparkplug B)
│   ├── etl/                     # PostgreSQL → Databricks Delta Lake ETL
│   ├── knowledge-graph/         # Neo4j seeder + live tag auto-discovery
│   └── ignition/                # Ignition SCADA support files
└── plc/                         # CODESYS PLC project (reference; not part of the Docker stack)

Tech stack

MQTT EMQX · Edge/Sim Python, FastAPI, Sparkplug B (Protocol Buffers) · SCADA Ignition · Historian PostgreSQL · Auth Keycloak · Lakehouse Databricks Delta Lake · Knowledge Graph Neo4j · Orchestration Docker Compose


Notes

  • The ETL watermark is held in memory; on restart the service re-fetches the most recent rows from the current partition rather than resuming from the last timestamp.
  • The simulator builds Sparkplug B payloads directly from sparkplug_b_pb2.py, while the knowledge-graph service uses tahu for protobuf decoding.
  • plc/ contains CODESYS PLC project files and is unrelated to the Docker stack.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages