Skip to content

Keenan-M-Stone/StoneLab

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

StoneLab: Lab Monitoring & Control

For a quick start of the full application and simulator, refer to the scripts directory contents. Consult the scripts/README.md and consider using the scripts/setup_and_launch --dev convenience tool, or bash scripts/run_sim_stack --frontend-mode dev --frontend-port 5173 for a simulator build and browser app pair.

In general, you can shut down your simulator instances with bash ./scripts/stop_sim_stack.

Make sure you stop your running instances once you're done testing and playing, but if you're connected to an actual instrument be cautious with which tool you use and how.
A lot of this is still in "beta" afterall.

Highlights

StoneLab is built to be right-to-repair friendly control software: usable by students and programmers, but also practical for operators and owners who want control over their own machines (even when a vendor has stopped supporting them).

What sets StoneLab apart:

  • Local-first, offline-capable

    • Runs on a laptop, shop PC, or edge box; no cloud dependency.
    • Projects stay portable (you own your configs, schemas, and recordings).
  • Protocol-as-code, UI derived from schema

    • DeviceGraph.json + ComponentSchema.json + parts libraries are the canonical spec.
    • The UI (Set dialogs, plots, and tooling) derives from what devices advertise.
  • Built-in simulator / digital twin

    • Same device IDs, same controls, same UI — swap between real and simulated.
    • Deterministic, seeded-noise simulation for reproducible debugging and demos.
  • Macro Wizard that round-trips to code

    • Import/export scripts that stay readable, reviewable, and diff-able.
    • Designed for workflows beyond classic tag edits: methods, procedures, and experiments.
  • Automation without UI coupling (BE macro jobs + scheduler)

    • Run macros in backend orchestration mode so they continue through refresh/reconnect.
    • Schedule macros to run at a specific time or on a fixed interval (persistent across restarts).
    • Enables practical multi-instrument workflows: switching between instruments in the same browser doesn’t stop in-flight automation.
  • Diagnostics, events, and alarms with nested causes

    • Errors/alarms can carry caused_by chains for root-cause visibility.
    • Core catalogs + toolkit-scoped catalogs keep messages consistent and discoverable.
  • Recording + replay for debugging and validation

    • “Flight recorder” runs: actions + measurements + UI state can be replayed.
    • Overlay comparisons to spot drift and regressions between runs.
  • Network-aware visualization (flowlines and beyond)

    • Edges can carry semantics: fluid flow, electrical current, etc.
    • Server-side derived edge state keeps toolkits consistent and extensible.
  • Composite mode (multi-instrument “backend-as-device”)

    • A “middleman” backend can proxy multiple instrument backends into one schematic.
    • Optional signal routing rules can drive one instrument from another.
  • External drivers (process adapter)

    • Load devices from external driver processes (--drivers) without embedding large protocol stacks.
    • Example driver included; config supports namespacing via id_prefix.
  • Launch ergonomics (path robustness)

    • Backend normalizes config paths (--graph, --composite, --drivers) and STONELAB_PROTOCOL_CONFIG to absolute paths at startup.
    • Reduces “changed working directory” surprises in scripts and automation.
  • Safety and governance without lock-in

    • Units/ranges, safe-state defaults, and audit-friendly action logging.
    • Supports serious instrument-control use cases without forcing vendor ecosystems.

Current Status (January 2026)

  • Schema-driven control surfaces

    • The backend advertises writable controls per device (derived from the active protocol schema), so toolkit devices populate the UI Set dialog without hardcoded frontend mappings.
  • Network-aware visualization

    • Server-side flowline computation supports both fluid networks (flow rate) and circuits (current) so edges can animate consistently across domains.
  • StoneFluid toolkit primitives

    • Reservoir volume/capacity primitives with empty / overfilled flags and overflow_ml, plus Macro Wizard templates for fill/drain and loop demos.
    • See: toolkits/StoneFluid/tools/macro_wizard/
  • StoneCircuits toolkit primitives

    • A shared RC transient simulator (Vs/R/C/switch) plus Macro Wizard templates and notebooks that drive the sim via WebSocket RPC.
    • See: toolkits/StoneCircuits/tools/macro_wizard/ and toolkits/StoneCircuits/notebooks/
  • Shared simulator utilities

    • A reusable core NoiseModeler used by toolkit simulators for consistent, deterministic noise.
  • Composite mode (multi-backend)

    • Run a composite backend that proxies multiple StoneLab backends as namespaced devices (A::device_id).
    • Optional routing rules (“signal router”) can forward measurements → actions with rate limiting.
  • Toolkit modularity

    • Toolkits can provide protocol assets, macro templates, notebooks, and optional plugins.
    • Protocol selection is persisted via shared/config/protocol.json (restart required).
  • Release bundles and run wrappers

    • Installer bundles include a single entrypoint runner (./bin/stonelab-run) with --sim, --composite, and --drivers modes.
    • Dev scripts support launching composite backends (see scripts/run_sim_stack --help).
  • External drivers (process adapter)

    • Backend can spawn one or more external driver processes via --drivers <config.json> and register their devices.
    • Example driver config is provided in shared/config/drivers.example.json.
  • End-to-end diagnostics improvements

    • Nested error reporting (caused_by) is carried through backend → UI and rendered for operators.

Roadmap (Proposed)

  • Near-term (0–3 months)

    • “Bring-up mode” for unknown hardware: safe probing tools, signal labeling, and schema generation.
    • Composite mode usability: route-firing events, health/latency summaries, and safer policy tooling.
    • Multi-instrument schematics UX: clearer namespacing, grouping, and cross-backend navigation.
    • Project bundles: export/import a single artifact containing protocol/schema/overrides/macros/recordings.
    • Alarms/events polish: hysteresis, ack workflows, routing, and audit views.
  • Mid-term (3–6 months)

    • Driver adapters for common transports (serial, Modbus, CAN, MQTT, OPC-UA client) built on the external driver process framework.
    • Driver protocol evolution: streaming/subscribe, reconnect/backoff, and richer metadata (units/ranges) from drivers.
    • Protocol CI: headless macro runner + invariants in simulation.
    • Optional persistence/historian path (recording queries, retention, export).
  • Longer-term (6–12 months)

    • Method execution and reporting (instrument-control workflows with provenance and calibration records).
    • Richer edge semantics (thermal/material/signal flow) and derived network analytics.
    • Continuous/data-plane wiring between instruments (beyond discrete routing rules)

Goals

  • Provide a working, well-structured skeleton codebase that implements subsystems for monitoring and controlling lab instrumentation:

    • Backend [c++]: diagnostics, results, reception, demo/simulator, state cache;
    • Frontend [vite/React]: transmission and reception of instructions for backend determined from user interactions, diagnostics UI, display of apparatus components in an editable schematic.
  • Provide users with ability to customize as much as possible.

  • Provide sample toolkits and utilities for getting started with "Simulational Integrity" as a top priority.

  • Enable multi-instrument schematics by treating backends as devices (composite mode).

  • Provide explicit “signal router” rules between instruments (policy/audit UX still evolving).

Repository layout (top-level)

backend/      C++ backend (simulator, device registry, WebSocket server, composite mode)
docs/         Project documentation (source-of-truth; synced into frontend)
frontend/     React + Vite web UI
scripts/      Convenience scripts (build, run stacks, docs sync)
shared/       Protocol assets + configs (DeviceGraph.json, ComponentSchema.json, errors/alarms)
toolkits/     Optional toolkits (protocol assets, plugins, notebooks, utilities)
tools/        Dev tools (SDK generators, installer/bundler, toolbox clients)
sdk/          Generated SDK outputs (Python, TS, etc.)
release/      Bundle outputs

Terminology (important)

StoneLab is commonly deployed across two machines:

  • Instrument backend: the machine running the C++ server in backend/ (often the instrument host: embedded Linux / a nearby control PC).
  • Browser UI (frontend): the machine where you open the web app built from frontend/ (often an operator workstation).

These do not need to be the same machine. The UI connects to the instrument backend over WebSocket (default path /status).

Notes:

  • When this README says “backend”, it refers to the process running on the instrument backend host.
  • When it says “frontend/UI”, it refers to the web app running in the operator’s browser (or a static web server).

Roles (where things run)

When using the convenience scripts, think in terms of roles:

  • Role: backend (instrument backend host)

    • Runs the C++ server (often --sim for demos, or real drivers for hardware).
    • Owns runtime state/log files (events, alarms state, audit log, historian log).
  • Role: ui (operator workstation)

    • Runs the web UI dev server or preview server.
    • Connects to the backend over WebSocket (default path /status).
    • Stores lightweight operator identity locally in the browser (localStorage).
  • Role: all (single machine dev)

    • Runs both backend + UI on the same host.

Convenience script examples:

# Single machine (developer laptop): backend + UI
bash scripts/run_sim_stack --role all

# Two machines:
# 1) On the instrument backend host
bash scripts/run_sim_stack --role backend --port 8080

# 2) On the operator workstation (point UI at the instrument backend)
bash scripts/run_sim_stack --role ui --backend-ws ws://<instrument-host>:8080/status --frontend-mode dev --frontend-port 5173

Prerequisites

  • C++20 compiler (GCC 10+, Clang 11+, or MSVC 2019+)
  • CMake 3.16+
  • nlohmann json development package (optional):
    • nlohmann-json3-dev (lets CMake find nlohmann_json target)
    • nlohmann/json (header-only, included)
  • Node.js 20+ (for backend-sim and frontend)
  • pnpm (or npm/yarn) for frontend
  • Python 3.10+ (recommended)
    • Used by developer tools (SDK generation, notebooks) and the stonelab-toolbox CLI.
    • tools/toolbox_python depends on websockets>=12.0.

Backend (C++)

Build

cd backend
mkdir -p build && cd build
cmake ..
cmake --build . -- -j$(nproc)

Run backend with real devices (default)

./StoneLab
# or specify port: ./StoneLab 9001

Run backend in simulation mode (auto-loads devices from shared/protocol/DeviceGraph.json)

./StoneLab --sim

# or, run in background
nohup ./backend/build/StoneLab --sim > /tmp/StoneLab.log 2>&1 &

Notes:

  • Use ./StoneLab --help to see available options (--sim, --port, etc.).
  • The backend starts a small stdin-based control thread only when stdin is a TTY. When you run the server detached (e.g. nohup, systemd, or redirecting stdin), the stdin control thread is skipped automatically to avoid the process being stopped by the shell.

Active protocol selection (simulator)

Simulator mode can load its protocol assets (DeviceGraph + ComponentSchema) from either:

  • the core protocol under shared/protocol/, or
  • a toolkit-provided protocol under toolkits/<ToolkitName>/....

Selection is persisted in shared/config/protocol.json and is restart-required (no hot-apply yet).

Common workflows:

# Use core protocol (next startup)
python3 tools/toolbox_python/stonegate_toolbox_client.py --ws ws://localhost:8080/status protocol.set core

# Use StoneQC toolkit protocol (next startup)
python3 tools/toolbox_python/stonegate_toolbox_client.py --ws ws://localhost:8080/status protocol.set StoneQC

# Preferred (rebranded) entrypoint (wrapper around the same client):
# python3 tools/toolbox_python/stonelab_toolbox_client.py --ws ws://localhost:8080/status protocol.set core

Then restart the backend (./StoneLab --sim).

Note: this repo also ships bundled example toolkits (if built with STONELAB_BUILD_TOOLKITS=ON) including StoneCircuits and StoneFluid. See docs/Toolkits.md.

Debugging: flowlines + quick metric watch

For a compact terminal view of flowlines plus key device measurements:

python -m tools.visualization.monitor --ws ws://localhost:8080/status --auto-watch

See tools/visualization/README.md for details and manual --watch usage.

Test simulator (deterministic output)

./test_simulator --seed 42
# Optionally specify a custom device graph:
# ./test_simulator --graph ../../shared/protocol/DeviceGraph.json --seed 123

This prints the loaded device descriptors and a single measurement poll for all simulated devices. Use a fixed seed for predictable results.


Frontend

cd frontend
pnpm install   # or npm install
pnpm dev       # or npm run dev

UI notes:

  • The Tools menu includes Diagnostics, Events, Trends, and Help.
  • Help shows the frontend version, git commit, and build time (injected at build time).

Operator identity (local, lightweight):

  • The Tools menu includes an Operator field.
  • This value is attached to WebSocket RPC requests as user and is used by the backend to attribute acknowledgements and audit records.

Deployment note:

  • The browser UI can run on a different machine than the instrument backend. In that case, set the UI endpoint to the instrument backend host, e.g. ws://<instrument-host>:8080/status.

Note: StoneLab includes a separate bundle installer flow (CLI wizard + scripts) for distribution and deployment. See the "Distribution / Installer" section.


Convenience scripts

For common one-command workflows (generate docs/SDKs, build + launch sim backend + frontend), see scripts/README.md.

Toolkit docs:

  • docs/Toolkits.md (how to create/install toolkits; protocol selection; using toolkits outside StoneLab)

Distribution / Installer

If you want to send someone a self-installable build (without requiring them to compile), you can create a "bundle" that includes:

  • the backend executable (StoneLab)
  • the built frontend static assets (frontend/dist)
  • a small runner + installer with multiple install modes

Create a tarball on your dev machine:

./tools/installer/stonegate-bundle.sh

# Preferred (rebranded) entrypoint:
# ./tools/installer/stonelab-bundle.sh

Then on the target machine:

tar -xzf stonegate-<version>.tar.gz
cd stonegate
./bin/install.sh --help

Guided setup (recommended):

./bin/stonegate-wizard

The installer can set defaults for the built UI (backend host/port, build-mode defaults) via frontend/dist/stonegate-config.js.

Docker option (build+run inside containers) is available if you create the bundle with --include-source.


Directory Structure

  • backend/ — C++ backend server, simulation, and device registry
  • backend-sim/ — Node.js simulator (optional, for frontend demo)
  • frontend/ — React frontend
  • shared/protocol/ — Device graph and component schemas
  • shared/config/ — Runtime config (toolkit enablement, active protocol selection)
  • toolkits/ — Installable toolkits (manifests + optional backend plugins + protocol assets)

Toolkit deployment note:

  • Toolkits (and any backend plugins they ship) must be present on the instrument backend host (or otherwise accessible to the backend process). The browser UI does not load toolkit files directly.

Testing

  • Run ./test_simulator --seed 42 to verify that simulated devices are loaded and produce deterministic measurements.
  • Extend with more tests as needed for device logic and protocol.

Project layout

stonelab/
├── README.md
├── backend/
│   ├── CMakeLists.txt
│   ├── include/
│   │   ├── Device.hpp
│   │   ├── DeviceRegistry.hpp
│   │   └── WebSocketServer.hpp
│   ├── src/
│   │   ├── main.cpp
│   │   ├── Backend.cpp
│   │   ├── DeviceRegistry.cpp
│   │   ├── WebSocketServer.cpp
│   │   └── core/
│   │       ├── PhysicsEngine.cpp
│   │       └── simulator/
│   └── tests/
├── backend-sim/
├── docs/
├── frontend/
│   ├── package.json
│   └── src/
│       ├── main.tsx
│       └── components/
│           └── SchematicCanvas/
├── shared/
│   ├── protocol/
│   │   ├── DeviceGraph.json
│   │   └── ComponentSchema.json
│   └── config/
├── tools/
└── LICENSE

Developer's Note: Quick tree generator (bash alias)

Below is a small bash function you can add to your shell aliases (e.g., in ~/.bashrc) to print a compact project tree similar to the block above.

It uses Python's stdlib so it doesn't require tree to be installed:

treeproj() {
  python3 - <<'PY'
import os
def tree(path, prefix=''):
    try:
        entries = sorted([e for e in os.listdir(path) if not e.startswith('.')])
    except PermissionError:
        return
    for i, name in enumerate(entries):
        p = os.path.join(path, name)
        connector = '└── ' if i == len(entries)-1 else '├── '
        print(prefix + connector + name)
        if os.path.isdir(p):
            extension = '    ' if i == len(entries)-1 else '│   '
            tree(p, prefix + extension)

print('.')
tree('.')
PY
}

# Example usage:
# cd /path/to/project && treeproj

High-level design notes

  • Backend (C++): modular libraries separated into diagnostic, results, reception, demo.
    Each subsystem exposes abstract interfaces (IDevice, IMeasurementSource, IReceiver) so hardware-specific drivers can be plugged in.
  • State cache: thread-safe in-memory cache containing latest measurements, device metadata (tolerances, baseline), operation state, and logs.
  • Networking: lightweight WebSocket server to communicate with browser frontend.
    Protocol uses JSON messages (well-typed) and supports streaming telemetry and command/response semantics.
  • Frontend (React + TypeScript):
    UI components for:
    • Transmission (send actions/scripts),
    • Reception (receive backend state),
    • Diagnostics (show sensors, tolerances, logs).
  • Demo subsystem: software-only simulator to generate semi-realistic device telemetry and sensor noise to exercise the full pipeline.

Build & Run (summary)

Backend (Linux / WSL / macOS)

Requires: C++17/C++20 compiler (GCC 10+/Clang 11+/MSVC 2019+), CMake >= 3.16, and a websocket library (the codebase references WebSocket++ or Boost.Beast; the provided skeleton uses a lightweight ASIO-based placeholder).

Below are step-by-step instructions for common developer and operator flows.

  1. Start backend in Simulator Mode (recommended for frontend/dev)

    cd backend
    mkdir -p build && cd build
    cmake .. -DCMAKE_BUILD_TYPE=Debug
    cmake --build . -- -j$(nproc)
    # start in simulator mode (auto-loads shared/protocol/DeviceGraph.json)
    ./StoneLab --sim

    Notes:

    • By default, simulator mode loads shared/protocol/DeviceGraph.json and shared/protocol/ComponentSchema.json. You can switch to a toolkit-provided protocol by setting shared/config/protocol.json (restart required).
    • The PhysicsEngine computes derived properties (temperature, noise coeff) from controller states;
      SimulatedDevice consults the engine when producing measurements.
    • To produce deterministic outputs for debugging, use the test_simulator binary with a fixed seed (see "Unit tests" below).

    Switch protocol (next startup):

    # core protocol
    python3 ../tools/toolbox_python/stonegate_toolbox_client.py --ws ws://localhost:8080/status protocol.set core
    
    # StoneQC protocol
    python3 ../tools/toolbox_python/stonegate_toolbox_client.py --ws ws://localhost:8080/status protocol.set StoneQC
    
    # Preferred (rebranded) entrypoint (wrapper around the same client):
    # python3 ../tools/toolbox_python/stonelab_toolbox_client.py --ws ws://localhost:8080/status protocol.set core
  2. Start backend against real instruments (hardware mode).
    Prerequisites:

    • Install required device drivers / vendor SDKs and verify hardware visibility (lsusb, ip link, etc.).
    • Edit shared/protocol/DeviceGraph.json so nodes map to real device identifiers and parts in PartsLibrary.json or shared/protocol/user_parts.json.
    • Ensure backend process can read/write shared/protocol (for device overrides and user parts persistence). Start the backend in hardware mode:
    cd backend/build
    ./StoneLab
    # or with explicit port: ./StoneLab 9001

    Notes:

    • In hardware mode the backend will attempt to instantiate real device driver classes (registered in main.cpp).
      If a driver initialization fails, check system permissions, device paths, and driver logs.
    • Use the frontend Manual Control dialog (or the stdin control hook in main.cpp during development) to send control messages.
  3. Unit tests and CI-less tests

    Build and run the CI-less tests (recommended; no GoogleTest dependency required):

    cd backend && mkdir -p build && cd build
    cmake .. -DCMAKE_BUILD_TYPE=Debug
    cmake --build . -- -j$(nproc)
    ./phys_engine_citest
    ./devices_citest
    ./simulator_citest

    Notes on GoogleTest:

    • To enable GoogleTest-based tests, configure cmake with -DBUILD_TESTS=ON and ensure a compatible GTest build is available.
    • If you see undefined references to a prebuilt libgtest, prefer building GTest from source for ABI compatibility.

Frontend (Vite/React/NodeJS)

cd frontend
pnpm install   # or npm install
pnpm dev       # or npm run dev

Open the URL printed by Vite (typically http://localhost:5173). The frontend will connect to ws://localhost:8080/status by default.

Notes:

  • The frontend WebSocket default is ws://localhost:8080/status (matches backend --sim). If you run the backend in hardware/default mode (port 9001), set VITE_BACKEND_WS_URL='ws://localhost:9001/status' before starting the frontend. If you change the endpoint in the UI, it is persisted in localStorage under stonegate.ws_url; use the Connection Panel Reset/Default button to clear the override and return to the build default.

Adding New Devices

To add a new device (real or simulated):

  1. Backend:
    • Create a new class inheriting from Device (see PhotonicDetectorDevice for an example).
    • Implement all required methods: id(), type(), descriptor(), read_measurement(), perform_action().
    • Register your device in main.cpp or via the Simulator loader.
    • For simulation, add your type and properties to shared/protocol/ComponentSchema.json.
    • For hardware, implement a driver class and call it from your device.

Action shape (UI + scripts):

  • The UI and generated scripts use a generic action payload: { "set": { "metric": value, ... } }.
  • Backend-side, map those generic set keys to your device's perform_action() keys, or accept {set:{...}} directly.
  1. Simulator:

    • Add your device type and properties to ComponentSchema.json.
    • The simulator will auto-load and generate measurements for all properties.
    • For custom simulation logic, extend SimulatedDevice::read_measurement().
  2. Frontend:

    • Update UI components if you want custom display/controls for your device type.
    • The default schematic and device panels will show all properties and allow actions defined in the schema.

Exposing New Operations to Python / C++

StoneLab exposes control operations via JSON-RPC over WebSocket.

  1. Backend (add an RPC method)
  • Implement the RPC handler in the backend WebSocket RPC router (see backend/src/WebSocketServer.cpp).
  • Choose a stable method name (example: "devices.list", "record.start").
  • Return JSON results (and structured errors) consistently.
  1. Python (add a helper wrapper)
  • Prefer adding a small wrapper in tools/sdk_sources/stonegate_api.py, then regenerate the installable SDK via python3 tools/generate_stonegate_sdk.py:
    • Use await sg.rpc("your.method", params) for raw calls.
    • Add a typed helper like async def your_method(...): ... for ergonomics.
  1. C++ (add a helper wrapper)
  • Prefer adding a method on stonegate::Client in tools/sdk_sources/stonegate_api.hpp, or call client.rpc("your.method", params) directly. Then regenerate the SDK headers via python3 tools/generate_stonegate_sdk.py.
  1. Device actions (no new RPC needed)
  • If it is a per-device control, prefer using the existing device.action RPC and send { "set": {...} }.
  • Python: await sg.device_action("device_id", {"set": {...}})
  • C++: client.device_action("device_id", json{{"set", json{{...}}}})
  1. Testing:
    • Add a test in test_simulator.cpp to verify your device loads and produces expected output.

See Device.hpp and SimulatedDevice.cpp for more documentation and extension points.

Build Mode, Swappable Parts, and Physical Coupling

More precisely described in docs/Software_Specifications.md. This is just to serve as a quick reference.

We support a "build mode" concept and a parts-library driven simulation so users can swap parts and see realistic physical coupling (e.g., LN2 flow -> temperature -> noise).

How it works (high level):

  • shared/protocol/PartsLibrary.json contains parts and their specs (thermal conductance, noise coefficients, nominal values).
  • shared/protocol/DeviceGraph.json nodes may optionally include a part field which names an entry in the parts library; otherwise the simulator picks a default part matching the node type.
  • The Simulator now registers devices and a PhysicsEngine that computes derived values (temperature, noise coefficients) from controller states (e.g., flow_rate_Lmin).
  • SimulatedDevice::read_measurement() will be extended to consult the physics engine and apply controller-influenced properties when available.

Build mode UX suggestions (to implement in frontend):

  • Enter build mode from the schematic to add/remove parts, drag/drop part versions onto nodes, and wire connections.
  • When editing a default (built-in) part, the frontend should prompt to "Save as new part" to avoid overwriting stock parts.
  • Allow mapping of readings to controls and derived metrics (e.g., map thermocouple temperature -> LN2 setpoint control loop).
  • Allow specifying capture windows, tolerances, and sampling rates per device; store these as per-device overrides in the DeviceGraph or a separate UserOverrides.json.

Persistence & safety:

  • Default parts (in PartsLibrary.json) are read-only. User-created or modified parts get saved to a user library (e.g., parts/user_parts.json).
  • Device instances in the DeviceGraph may include overrides that are persisted separately so the canonical graph remains intact.

Next steps to complete this feature:

  1. Extend SimulatedDevice to accept a PhysicsEngine& and query per-node computed properties each measurement.
  2. Add a small IPC or shared-memory bridge if you want a separate physics worker process (later).
  3. Build frontend build-mode UI: part browser (from PartsLibrary + user parts), drag/drop, wiring to signals/controls.
  4. Add persistence endpoints or file-based saves for user parts and overrides.

Controller Support

Controllers (such as liquid nitrogen cooling) are supported just like devices. See LN2CoolingControllerDevice for a C++ example. Add your controller to ComponentSchema.json and register it in main.cpp or via the simulator loader. The simulator and frontend will auto-detect new controllers and expose their properties and actions.

Developer resources

There is a concise developer quickstart in docs/DEVELOPER.md that shows the expected WebSocket message shapes, how the frontend hooks (onSelectNode, onOpenDialog) connect to the SchematicCanvas, and quick steps to run the backend in simulator mode.

This is left as a decision-engine module (frontend/src/errordecision.ts) with pluggable rules — the codebase includes a small example function with a few heuristics.


Integration points and where to plug real code

  • IDiagnosticProvider::pollOnce() — implement drivers that read from hardware SDKs or DAQ libraries (NI-DAQmx, serial, Modbus, gRPC bridges, etc.).
  • WebsocketServer — replace minimal hook with a real server (Boost.Beast, WebSocket++, uWebSockets) that accepts clients and routes JSON messages.
  • IScriptRunner::runInstruction() — implement concrete runners that call hardware control code (moving probes, toggling relays, scheduling pulse sequences to an AWG or FPGA).
  • DemoSimulator — extend to simulate additional device behaviors and fault modes (e.g., integrate with Eigen for linear algebra). For larger workloads, consider integrating C++ libraries like qpp or linking to Python simulators via IPC.
  • Error correction logic — real ECC selection depends heavily on available codes (surface code, repetition code, Bacon-Shor). Plug in libraries or proprietary implementations behind an interface.

Licensing

N/A


About

Generic SCADA support for getting engineering projects started fast.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors