Skip to content

Repository files navigation

RunPilot — Edge-compute SCADA for smart factories

Made with ❤️ by Lumi

License: MIT Python 3.11+ Status: beta Runs on edge hardware

Edge-compute SCADA platform for smart factories — 8 PLC protocols out of the box, a visual workflow builder, and an AI assistant with tool calling, all running on the edge device itself.

Quick start

# install (requires Python 3.11+)
uv sync --all-extras

# build the web UI (Node 20+, build-time only)
cd frontend && npm install && npm run build && cd ..

# run — serves API + UI on :8080 (needs NATS: docker compose up nats)
runpilot start -c config/runpilot.yaml

Open http://localhost:8080, log in (admin / $RUNPILOT_ADMIN_PASSWORD; auto-generated and logged on first boot if unset), and build workflows visually: drag device tags → transforms → connectors, deploy, watch live counters.

Demo without hardware — a simulated high-speed plant

A full bottling-plant digital twin (5 devices, 38 tags: servo x/y axes, motor parameters, utilities/electrical segment, compressor, production counters) with 24 h of history, an ISA-95 asset tree, and 8 seeded raw→derived workflows:

docker run -d --name nats -p 4222:4222 nats:2-alpine
uv run python scripts/seed_demo.py            # one-shot: history + assets
RUNPILOT_ADMIN_PASSWORD=runpilot-local-admin \
  runpilot start -c config/runpilot.local.yaml &
uv run python scripts/sim_feed.py demo        # live feed (or a scenario)

Live scenarios (--list): overheating (filler crosses 85 °C → alarm), bearing-wear (capper vibration → anomaly), downtime (line stops → OEE hit), energy-spike (power-factor dip), quality-drift (fill volume out of 500±3 spec), capper-jam (line backs up → stall alarm), servo-degradation (x/y axis jitter → derived-KPI anomaly), and demo (a 14-min cycling tour). --duration N time-boxes a run for scripted demos; --counts G R continues production counters from the backfill.

The seeded workflows showcase raw→derived transforms: three-phase power from V·I·pf, stateful kWh accumulation, axis-speed magnitude from servo velocities, an expression where-filter, and a stall detector — all built from the same nodes available in the visual builder.

Tests

uv run pytest                     # backend
cd frontend && npx vitest run     # graph serialization

Architecture

RunPilot runs on edge hardware (RPi 4/5, Jetson, industrial PCs). Data flows through a validate → enrich → aggregate pipeline over NATS, stores locally in SQLite + DuckDB, and syncs to cloud when connected. The API + web UI are served from the same process (DuckDB is single-process).

PLC ──► Drivers ──► NATS Pipeline ──► Connectors ──► Cloud
                    (validate/enrich/agg)  (MQTT/HTTP)
                       │            │
                       │            ├──► Workflow engine (visual builder)
                       │            ├──► AI agent (chat, tools, advisories)
                       │            └──► SSE live feed (web UI)
                    DuckDB (time-series)
                    SQLite (assets/alarms/workflows/auth/audit)

PLC protocols (beta: simulator/mock-verified, not yet field-tested)

Protocol driver Library Address examples Notes
OPC-UA opcua asyncua ns=2;s=Motor.Speed subscriptions + cert auth
Modbus TCP modbus_tcp pymodbus 40001, 30001, 10001, 1 register batching
Modbus RTU modbus_rtu pymodbus[serial] same host: /dev/ttyUSB0; baud/parity in extra
Siemens S7 s7 pys7 (pure Python) DB1,R40, M54.4, IW22 S7-300/400/1200/1500; multi-var reads
EtherNet/IP ethernet_ip pycomm3 Program:Main.Counter, MyTag ControlLogix/CompactLogix
MELSEC MC melsec pymcprotocol D100, M100, X10 Q/L/iQ-R; port from GX Works required
Omron FINS fins stdlib UDP codec DM100, CIO50, W10 word areas; node = last IP octet
MQTT ingest mqtt aiomqtt topic or topic:$.json.path push/cache; numeric/bool payloads

Connection parameters go in each device's extra: dict — see the commented examples in config/runpilot.yaml.

Visual workflow builder

The web UI edits WorkflowConfig graphs on a React Flow canvas: sources are device tags, transforms come from TRANSFORM_REGISTRY, destinations are connectors or PLC write-back nodes. Deploy validates (unknown transforms, cycles, unknown destinations, write permissions) and hot-reloads the runner; threshold breaches create deduplicated alarms. Workflows persist in SQLite; the YAML workflows: section seeds first boot.

  • AI nodes: anomaly_detect (statistical z-score/IQR per tag) and ai_analyze (cooldown-gated LLM analysis of batch stats, optionally raised as an info alarm).
  • Code nodes: expression — safe one-line Python (simpleeval) to rewrite/filter, e.g. value * 1.8 + 32; python_code — full custom transform(readings, state) logic in a RestrictedPython sandbox (import whitelist, wall-clock timeout, security.custom_code_enabled kill-switch). Both offer ✨ Write with AI: describe the logic, get compile-checked code.
  • PLC write-back: plc:{device}.{tag} destinations, off by default — require security.plc_write_enabled + plc_write_from_workflows, a writable tag, deployer with the plc_write permission, and every write runs through WriteGuard's rate limit + audit.
  • Generate with AI: describe the workflow in a sentence; the copilot drafts a validated graph onto the canvas for review before deploy.

Self-service platform (no YAML editing needed)

Everything is manageable from the browser; the YAML seeds first boot, then SQLite is the source of truth (hot-applied, no restart):

  • Devices: add/edit/delete PLCs with per-driver connection forms, a tag table editor, Test connection, tag browse (OPC-UA / EtherNet-IP), CSV bulk import, and an AI tag mapper that cleans cryptic addresses (N7:0, DB100.DBW4) into readable names + units (POST /api/ai/suggest-tags).
  • Connectors: add/edit sinks from schema-driven forms; stop-and-recreate on save.
  • Users: admin CRUD + role changes; self-service password change; last-admin guards; everything audited.
  • System: live health (drivers, connectors, workflows, disk), Prometheus GET /metrics, LLM provider list + one-click test, DB backup, config export/import.

Generic LLM providers

Any vendor, any API style, configured as an ordered fallback chain — keys are always env-var names, never literals:

api_style Covers
anthropic Anthropic, MiniMax (api.minimax.io/anthropic)
openai OpenAI, Azure AI Foundry serverless, Groq, DeepSeek, vLLM, LM Studio
azure Azure OpenAI / Foundry deployments (api_version)
ollama local models

The legacy single-provider fields still work (auto-synthesized). See the llm.providers / llm.chain example in config/runpilot.yaml.

Add providers from the UI: System → "+ Add LLM provider" — base URL, type (anthropic/openai/azure/ollama), API key — then pick the default model from the vendor's own model list ("Models…" button). UI-added providers persist in the local store (0600 perms); keys are never echoed by any API and are masked in config exports. Ollama installs get a live model selector automatically.

Demo knowledge base

knowledge/plant/ ships six manuals matching the simulated line (filler servo specs, capper torque/vibration zones, compressor envelope, electrical tariffs, OEE targets, alarm playbook) — RAG-ingested at boot so the AI assistant answers "what's the capper vibration limit?" from the plant's own documentation.

Dashboards, digital twin & insight apps

  • Dashboards — built-in tile grid (live value, gauge, sparkline, alarm list, KPI card); browser-editable, YAML-seeded, no Grafana required.
  • Assets (digital twin) — ISA-95 tree with per-equipment live mirror: bound values, KPIs, health badge, alarms, sparklines. ✨ AI contextualize proposes the hierarchy + tag-class bindings from your raw tag list; one click applies it.
  • KPI framework — bind tags to semantic classes (run_state, counters, power/energy, quality, vibration…) and the edge computes OEE (availability × performance × quality, rolled up equipment→line), energy baselines with overspend alarms, predictive-maintenance health scores (IsolationForest when sklearn is present, statistical fallback always), SPC (X-bar/R, EWMA, Cp/Cpk transforms), and an anomaly feed (/api/alarms?category=anomaly) — each with optional LLM "why" narration. GET /api/kpi/latest, get_kpis agent tool.
  • Alarm suite — auto-clear on return-to-normal (hysteresis), shelving, escalation policies (severity bump + connector notification), per-tag flood caps; Alarms view with filters and one-click AI shift-handover report (also GET /api/reports/daily).
  • Operator kiosk — fullscreen line view (?kiosk=1 or the Kiosk button): big live tiles, one-tap andon downtime reasons, and the AI copilot grounded in live plant data.

Output streams

MQTT and HTTP webhooks in core; pip install 'runpilot[streams]' adds Kafka (also covers Azure Event Hubs' Kafka endpoint, Confluent, MSK, Redpanda), Azure Event Hubs (native), and AWS Kinesis — all behind the same store-and-forward buffering. See commented examples in config/runpilot.yaml.

AI agent (edge runtime)

POST /api/ai/chat streams a tool-calling agent over SSE. Cloud-first chain: Claude (via litellm, ANTHROPIC_API_KEY env) → local Ollama → rule-based advisories when fully offline. Tools: timeseries queries, asset tree, alarms, production/OEE summary, anomaly stats, knowledge search (RAG), workflow status — plus confirm-gated mutations (acknowledge alarm, PLC write through WriteGuard). Skills are markdown playbooks in knowledge/skills/; four ship by default (vibration triage, OEE analysis, Modbus commissioning, alarm-flood triage). An optional background advisor (ai.agent.proactive_advisories) turns statistical anomalies into info-level alarms.

Modules

Module Path Purpose
Runtime src/runpilot/runtime.py Composition root — wires drivers→bus→pipeline→API
Config src/runpilot/config/ YAML schema, validation, device config
Drivers src/runpilot/drivers/ 8 protocols, registry, connection manager with backoff
Models src/runpilot/models/ ISA-95 assets, alarm state machine, OEE
Pipeline src/runpilot/pipeline/ Validator, enricher, aggregator, recorder, protobuf bus
Security src/runpilot/security/ bcrypt auth, RBAC, audit log, PLC write guard
Workflow src/runpilot/workflow/ DAG engine, transforms + schemas, bus-fed runner
AI src/runpilot/ai/ Agent loop + tools + skills, anomaly detection, LLM chain, RAG
API src/runpilot/api/ FastAPI + SSE, auth middleware, workflow/AI routes, static UI
Frontend frontend/ React Flow workflow builder (Vite → static bundle)
Edge src/runpilot/edge/ Bandwidth governor, retention, watchdog, HW profiles
Sync src/runpilot/sync/ Store-and-forward queue, delta sync, backup/restore
Connectors src/runpilot/connectors/ MQTT, HTTP, Kafka, Event Hubs, Kinesis; ring buffer + WAL

See docs/ROADMAP.md for the Industry 5.0 accelerator positioning and the phased roadmap.

Docker

docker compose -f docker-compose.edge.yml up

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages