Core Concepts

Core Concepts

This page covers the fundamental building blocks you'll work with across every Plexus SDK.

Sources

A source represents a single device or data origin. Each source has a unique source_id — a URL-safe string like esp32-001, test-rig-A, or drone.alpha.

px = Plexus(source_id="test-rig-01")
plexus_client_t* px = plexus_init("plx_key", "esp32-001");

Rules for source IDs:

  • Only a-z A-Z 0-9 . _ - characters allowed (no spaces)
  • Use the slug shown in the Plexus dashboard, not the display name
  • Keep them consistent — the same physical device should always use the same ID

Metrics

A metric is a named value sent from a source. Metric names use dot notation for hierarchy:

px.send("engine.rpm", 3450)
px.send("coolant.temperature", 82.3)
px.send("position.x", 1.5)

Supported Value Types

TypeExampleUse Case
number72.5, -40, 3.14159Sensor readings (most common)
string"running", "error"Status, state labels
booleantrue, falseOn/off, enabled/disabled
object{"x": 1.2, "y": 3.4}Vectors, structured data
array[1.0, 2.0, 3.0]Waveforms, joint angles

Tags

Tags are key-value labels attached to data points for filtering and grouping:

px.send("temperature", 72.5, tags={"location": "lab", "unit": "A"})

Tags are indexed and searchable in the dashboard. Use them for:

  • Location: building, room, rack
  • Device metadata: firmware_version, hardware_rev
  • Experiment labels: trial, batch, operator

Sessions

A session groups related data points for analysis and playback. Use sessions for test runs, experiments, or any bounded recording:

with px.session("thermal-cycle-001"):
    while running:
        px.send("temperature", read_temp())
plexus_session_start(px, "motor-test-001");
// ... send data ...
plexus_session_end(px);

Sessions enable:

  • Playback — Replay sensor data at original speed or faster
  • Comparison — Overlay multiple sessions on the same chart
  • Export — Download session data as CSV or Parquet

Commands

Commands let you send typed instructions from the dashboard to a device. The dashboard auto-generates UI controls (sliders, dropdowns, toggles) from the command schema.

@px.command("set_speed", description="Set motor speed")
@param("rpm", type="float", min=0, max=10000, unit="rpm")
async def set_speed(rpm):
    motor.set_rpm(rpm)
    return {"actual_rpm": motor.read_rpm()}

Commands are sent over WebSocket and executed in real time on the device.

Authentication

Plexus uses API keys (prefixed plx_) for all authentication. Get a key from API Keys (opens in a new tab)

export PLEXUS_API_KEY=plx_xxxxx

Or pass it directly:

px = Plexus(api_key="plx_xxxxx")

Data Flow

┌─────────────┐     HTTP POST      ┌──────────────────┐     Store     ┌────────────┐
│   Device    │ ──────────────────→ │  /api/ingest     │ ───────────→ │ ClickHouse │
│ (Python/C)  │                     │  (Next.js API)   │              │ (timeseries)│
└─────────────┘                     └──────────────────┘              └────────────┘

      │ WebSocket

┌──────────────────┐     Broadcast    ┌────────────┐
│  PartyKit Server │ ───────────────→ │  Dashboard │
│  (real-time)     │                  │  (browser) │
└──────────────────┘                  └────────────┘
  • HTTP path: Used by the Plexus() client and C SDK for data ingestion. Data is stored in ClickHouse.
  • WebSocket path: Used by plexus run for real-time streaming. Data flows through PartyKit to connected browsers.
  • Both paths: When recording a session, both are used — WebSocket for live view, HTTP for persistence.

Next Steps