tekhsi_rs

Crates.iotekhsi_rs
lib.rstekhsi_rs
version0.1.1
created_at2026-01-21 21:18:20.165762+00
updated_at2026-01-21 21:46:31.827775+00
descriptionHigh-performance client for Tektronix TekHSI enabled oscilloscopes
homepage
repositoryhttps://github.com/dnetguru/tekhsi_rs
max_upload_size
id2060149
size347,482
(dnetguru)

documentation

README

tekhsi_rs

High-performance client for Tektronix HSI enabled oscilloscopes, with native Rust, Python, and Node.js bindings.

License: GPL v3 Rust Python Node.js

Overview

tekhsi_rs connects to Tektronix HSI-compatible oscilloscopes, validates waveform headers, and decodes analog/digital/IQ data into typed waveforms with strict validation. It prioritizes correctness, performance, and reliability over the Python reference implementation.

Key Features

  • High-throughput — Parallel download and decode loops and minimal allocations
  • Strict validation — Rejects invalid/unsupported waveform data with explicit errors
  • Streaming — Async iterator-based acquisition with broadcast channels
  • Multi-language — Native Rust, Python, and Node.js bindings
  • FFT support — Calibrated FFT helpers for frequency analysis

Language Bindings

Language Package Status
Rust tekhsi_rs Core implementation
Python pytekhsi Async + sync APIs
Node.js tekhsi_js TypedArray + async iter

Quick Start

Rust

use tekhsi_rs::{SubscribeOptions, TekHsiClient};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = TekHsiClient::connect("scope:5000").await?;
    let symbols = client.list_available_symbols().await?;
    let mut rx = client.subscribe(symbols, SubscribeOptions::default())?;

    while let Ok(acquisition) = rx.recv().await {
        for channel in acquisition.data.iter() {
            println!("{:?}", channel);
        }
    }

    client.disconnect().await?;
    Ok(())
}

Python

import asyncio
import pytekhsi

async def main():
    client = await pytekhsi.TekHsiClient.connect("scope:5000")
    symbols = await client.list_available_symbols()
    receiver = client.subscribe(symbols)

    async for acquisition in receiver:
        for channel in acquisition:
            print(channel)

    await client.disconnect()

asyncio.run(main())

Node.js

import { TekHsiClient } from 'tekhsi_js'

const client = await TekHsiClient.connect('scope:5000')
const symbols = await client.listAvailableSymbols()
const receiver = await client.subscribe(symbols)

for await (const acquisition of receiver) {
    for (const channel of acquisition.iter()) {
        console.log(channel)
    }
}

await client.disconnect()

Installation

Rust

cargo add tekhsi_rs
# or for FFT support:
cargo add tekhsi_rs --features fft

Python

pip install tekhsi-rs
# or build from source:
cd bindings/python && pip install .

Node.js

npm install tekhsi-js
# or build from source:
cd bindings/node && npm install

Benchmark

# Rust benchmark
cargo run --release --example benchmark -- 127.0.0.1:5000

# Python benchmark
cd bindings/python/examples && python benchmark.py

# Node.js benchmark
cd bindings/node && npm run bench

Demo Applications

scopeapp (Rust) — egui/eframe-based oscilloscope viewer

cargo run -p scopeapp -- 127.0.0.1:5000

pyscopeapp (Python) — PyQt6/pyqtgraph-based viewer

cd bindings/python/examples/pyscopeapp && python main.py

Testing

Integration tests depend on the Python test server in tests/server/.

# Build and run test server
cd tests/server && ./run-server.sh

# Run tests (requires --features client-id-header for test server)
cargo test --features client-id-header

# Clean test server artifacts
cd tests/server && ./clean.sh

License

GPL-3.0 — See LICENSE for details.

Related

Commit count: 0

cargo fmt